@internetarchive/histogram-date-range 0.0.11-beta → 0.1.2-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.
@@ -1,8 +1,10 @@
1
1
  import { __decorate } from "tslib";
2
- import { css, html, LitElement, svg, } from 'lit';
2
+ import { css, html, nothing, LitElement, svg, } from 'lit';
3
3
  import { property, state, customElement } from 'lit/decorators.js';
4
4
  import { live } from 'lit/directives/live.js';
5
5
  import dayjs from 'dayjs/esm/index.js';
6
+ import customParseFormat from 'dayjs/esm/plugin/customParseFormat';
7
+ dayjs.extend(customParseFormat);
6
8
  import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
7
9
  // these values can be overridden via the component's HTML (camelCased) attributes
8
10
  const WIDTH = 180;
@@ -12,21 +14,23 @@ const TOOLTIP_WIDTH = 125;
12
14
  const TOOLTIP_HEIGHT = 30;
13
15
  const DATE_FORMAT = 'YYYY';
14
16
  const MISSING_DATA = 'no data';
15
- const UPDATE_DEBOUNCE_DELAY_MS = 1000;
17
+ const UPDATE_DEBOUNCE_DELAY_MS = 0;
16
18
  // this constant is not set up to be overridden
17
19
  const SLIDER_CORNER_SIZE = 4;
18
20
  // these CSS custom props can be overridden from the HTML that is invoking this component
19
- const sliderFill = css `var(--histogramDateRangeSliderFill, #4B65FE)`;
20
- const selectedRangeFill = css `var(--histogramDateRangeSelectedRangeFill, #DBE0FF)`;
21
+ const sliderColor = css `var(--histogramDateRangeSliderColor, #4B65FE)`;
22
+ const selectedRangeColor = css `var(--histogramDateRangeSelectedRangeColor, #DBE0FF)`;
21
23
  const barIncludedFill = css `var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;
22
24
  const activityIndicatorColor = css `var(--histogramDateRangeActivityIndicator, #2C2C2C)`;
23
25
  const barExcludedFill = css `var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;
24
26
  const inputBorder = css `var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;
25
27
  const inputWidth = css `var(--histogramDateRangeInputWidth, 35px)`;
26
28
  const inputFontSize = css `var(--histogramDateRangeInputFontSize, 1.2rem)`;
29
+ const inputFontFamily = css `var(--histogramDateRangeInputFontFamily, sans-serif)`;
27
30
  const tooltipBackgroundColor = css `var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;
28
31
  const tooltipTextColor = css `var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;
29
32
  const tooltipFontSize = css `var(--histogramDateRangeTooltipFontSize, 1.1rem)`;
33
+ const tooltipFontFamily = css `var(--histogramDateRangeTooltipFontFamily, sans-serif)`;
30
34
  let HistogramDateRange = class HistogramDateRange extends LitElement {
31
35
  constructor() {
32
36
  /* eslint-disable lines-between-class-members */
@@ -89,12 +93,11 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
89
93
  this.move = (e) => {
90
94
  const newX = e.offsetX - this._dragOffset;
91
95
  const slider = this._currentSlider;
92
- const date = this.translatePositionToDate(newX);
93
96
  if (slider.id === 'slider-min') {
94
- this.minSelectedDate = date;
97
+ this.minSelectedDate = this.translatePositionToDate(this.validMinSliderX(newX));
95
98
  }
96
99
  else {
97
- this.maxSelectedDate = date;
100
+ this.maxSelectedDate = this.translatePositionToDate(this.validMaxSliderX(newX));
98
101
  }
99
102
  };
100
103
  }
@@ -104,7 +107,12 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
104
107
  super.disconnectedCallback();
105
108
  }
106
109
  updated(changedProps) {
107
- if (changedProps.has('bins') || changedProps.has('Date')) {
110
+ // check for changes that would affect bin data calculations
111
+ if (changedProps.has('bins') ||
112
+ changedProps.has('minDate') ||
113
+ changedProps.has('maxDate') ||
114
+ changedProps.has('minSelectedDate') ||
115
+ changedProps.has('maxSelectedDate')) {
108
116
  this.handleDataUpdate();
109
117
  }
110
118
  }
@@ -120,8 +128,8 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
120
128
  return;
121
129
  }
122
130
  this._histWidth = this.width - this.sliderWidth * 2;
123
- this._minDateMS = dayjs(this.minDate).valueOf();
124
- this._maxDateMS = dayjs(this.maxDate).valueOf();
131
+ this._minDateMS = this.getMSFromString(this.minDate);
132
+ this._maxDateMS = this.getMSFromString(this.maxDate);
125
133
  this._binWidth = this._histWidth / this._numBins;
126
134
  this._previousDateRange = this.currentDateRangeString;
127
135
  this._histData = this.calculateHistData();
@@ -136,11 +144,16 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
136
144
  calculateHistData() {
137
145
  const minValue = Math.min(...this.bins);
138
146
  const maxValue = Math.max(...this.bins);
139
- const valueScale = this.height / Math.log1p(maxValue - minValue);
147
+ // if there is no difference between the min and max values, use a range of
148
+ // 1 because log scaling will fail if the range is 0
149
+ const valueRange = minValue === maxValue ? 1 : Math.log1p(maxValue - minValue);
150
+ const valueScale = this.height / valueRange;
140
151
  const dateScale = this.dateRangeMS / this._numBins;
141
152
  return this.bins.map((v, i) => {
142
153
  return {
143
154
  value: v,
155
+ // use log scaling for the height of the bar to prevent tall bars from
156
+ // making the smaller ones too small to see
144
157
  height: Math.floor(Math.log1p(v) * valueScale),
145
158
  binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,
146
159
  binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,
@@ -156,6 +169,12 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
156
169
  }
157
170
  return this.bins.length;
158
171
  }
172
+ get histogramLeftEdgeX() {
173
+ return this.sliderWidth;
174
+ }
175
+ get histogramRightEdgeX() {
176
+ return this.width - this.sliderWidth;
177
+ }
159
178
  /** component's loading (and disabled) state */
160
179
  get loading() {
161
180
  return this._isLoading;
@@ -166,51 +185,55 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
166
185
  }
167
186
  /** formatted minimum date of selected date range */
168
187
  get minSelectedDate() {
169
- return this.formatDate(this._minSelectedDate);
188
+ return this.formatDate(this.getMSFromString(this._minSelectedDate));
170
189
  }
190
+ /** updates minSelectedDate if new date is valid */
171
191
  set minSelectedDate(rawDate) {
172
192
  if (!this._minSelectedDate) {
173
193
  // because the values needed to calculate valid max/min values are not
174
194
  // available during the lit init when it's populating properties from
175
195
  // attributes, fall back to just the raw date if nothing is already set
176
196
  this._minSelectedDate = rawDate;
197
+ return;
177
198
  }
178
- const x = this.translateDateToPosition(rawDate);
179
- if (x) {
180
- const validX = this.validMinSliderX(x);
181
- this._minSelectedDate = this.translatePositionToDate(validX);
199
+ const proposedDateMS = this.getMSFromString(rawDate);
200
+ const isValidDate = !Number.isNaN(proposedDateMS);
201
+ const isNotTooRecent = proposedDateMS <= this.getMSFromString(this.maxSelectedDate);
202
+ if (isValidDate && isNotTooRecent) {
203
+ this._minSelectedDate = this.formatDate(proposedDateMS);
182
204
  }
183
205
  this.requestUpdate();
184
206
  }
185
207
  /** formatted maximum date of selected date range */
186
208
  get maxSelectedDate() {
187
- return this.formatDate(this._maxSelectedDate);
209
+ return this.formatDate(this.getMSFromString(this._maxSelectedDate));
188
210
  }
211
+ /** updates maxSelectedDate if new date is valid */
189
212
  set maxSelectedDate(rawDate) {
190
213
  if (!this._maxSelectedDate) {
191
- // see comment above in the minSelectedDate setter
214
+ // because the values needed to calculate valid max/min values are not
215
+ // available during the lit init when it's populating properties from
216
+ // attributes, fall back to just the raw date if nothing is already set
192
217
  this._maxSelectedDate = rawDate;
218
+ return;
193
219
  }
194
- const x = this.translateDateToPosition(rawDate);
195
- if (x) {
196
- const validX = this.validMaxSliderX(x);
197
- this._maxSelectedDate = this.translatePositionToDate(validX);
220
+ const proposedDateMS = this.getMSFromString(rawDate);
221
+ const isValidDate = !Number.isNaN(proposedDateMS);
222
+ const isNotTooOld = proposedDateMS >= this.getMSFromString(this.minSelectedDate);
223
+ if (isValidDate && isNotTooOld) {
224
+ this._maxSelectedDate = this.formatDate(proposedDateMS);
198
225
  }
199
226
  this.requestUpdate();
200
227
  }
201
228
  /** horizontal position of min date slider */
202
229
  get minSliderX() {
203
- var _a;
204
- return (
205
- // default to leftmost position if missing or invalid min position
206
- (_a = this.translateDateToPosition(this.minSelectedDate)) !== null && _a !== void 0 ? _a : this.sliderWidth);
230
+ const x = this.translateDateToPosition(this.minSelectedDate);
231
+ return this.validMinSliderX(x);
207
232
  }
208
233
  /** horizontal position of max date slider */
209
234
  get maxSliderX() {
210
- var _a;
211
- return (
212
- // default to rightmost position if missing or invalid max position
213
- (_a = this.translateDateToPosition(this.maxSelectedDate)) !== null && _a !== void 0 ? _a : this.width - this.sliderWidth);
235
+ const x = this.translateDateToPosition(this.maxSelectedDate);
236
+ return this.validMaxSliderX(x);
214
237
  }
215
238
  get dateRangeMS() {
216
239
  return this._maxDateMS - this._minDateMS;
@@ -223,10 +246,11 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
223
246
  const x = target.x.baseVal.value + this.sliderWidth / 2;
224
247
  const dataset = target.dataset;
225
248
  const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;
249
+ const formattedNumItems = Number(dataset.numItems).toLocaleString();
226
250
  this._tooltipOffset =
227
251
  x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;
228
252
  this._tooltipContent = html `
229
- ${dataset.numItems} ${itemsText}<br />
253
+ ${formattedNumItems} ${itemsText}<br />
230
254
  ${dataset.binStart} - ${dataset.binEnd}
231
255
  `;
232
256
  this._tooltipVisible = true;
@@ -239,25 +263,33 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
239
263
  * Constrain a proposed value for the minimum (left) slider
240
264
  *
241
265
  * If the value is less than the leftmost valid position, then set it to the
242
- * left edge of the widget (ie the slider width). If the value is greater than
243
- * the rightmost valid position (the position of the max slider), then set it
244
- * to the position of the max slider
266
+ * left edge of the histogram (ie the slider width). If the value is greater
267
+ * than the rightmost valid position (the position of the max slider), then
268
+ * set it to the position of the max slider
245
269
  */
246
270
  validMinSliderX(newX) {
247
- const validX = Math.max(newX, this.sliderWidth);
248
- return Math.min(validX, this.maxSliderX);
271
+ // allow the left slider to go right only to the right slider, even if the
272
+ // max selected date is out of range
273
+ const rightLimit = Math.min(this.translateDateToPosition(this.maxSelectedDate), this.histogramRightEdgeX);
274
+ newX = this.clamp(newX, this.histogramLeftEdgeX, rightLimit);
275
+ const isInvalid = Number.isNaN(newX) || rightLimit < this.histogramLeftEdgeX;
276
+ return isInvalid ? this.histogramLeftEdgeX : newX;
249
277
  }
250
278
  /**
251
279
  * Constrain a proposed value for the maximum (right) slider
252
280
  *
253
281
  * If the value is greater than the rightmost valid position, then set it to
254
- * the right edge of the widget (ie widget width - slider width). If the value
255
- * is less than the leftmost valid position (the position of the min slider),
256
- * then set it to the position of the min slider
282
+ * the right edge of the histogram (ie histogram width - slider width). If the
283
+ * value is less than the leftmost valid position (the position of the min
284
+ * slider), then set it to the position of the min slider
257
285
  */
258
286
  validMaxSliderX(newX) {
259
- const validX = Math.max(newX, this.minSliderX);
260
- return Math.min(validX, this.width - this.sliderWidth);
287
+ // allow the right slider to go left only to the left slider, even if the
288
+ // min selected date is out of range
289
+ const leftLimit = Math.max(this.histogramLeftEdgeX, this.translateDateToPosition(this.minSelectedDate));
290
+ newX = this.clamp(newX, leftLimit, this.histogramRightEdgeX);
291
+ const isInvalid = Number.isNaN(newX) || leftLimit > this.histogramRightEdgeX;
292
+ return isInvalid ? this.histogramRightEdgeX : newX;
261
293
  }
262
294
  addListeners() {
263
295
  window.addEventListener('pointermove', this.move);
@@ -327,17 +359,19 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
327
359
  return this.formatDate(this._minDateMS + milliseconds);
328
360
  }
329
361
  /**
330
- * Returns slider x-position corresponding to given date (or null if invalid
331
- * date)
362
+ * Returns slider x-position corresponding to given date
332
363
  *
333
364
  * @param date
334
365
  * @returns x-position of slider
335
366
  */
336
367
  translateDateToPosition(date) {
337
- const milliseconds = dayjs(date).valueOf();
338
- const xPosition = this.sliderWidth +
339
- ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS;
340
- return isNaN(milliseconds) || isNaN(xPosition) ? null : xPosition;
368
+ const milliseconds = this.getMSFromString(date);
369
+ return (this.sliderWidth +
370
+ ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS);
371
+ }
372
+ /** ensure that the returned value is between minValue and maxValue */
373
+ clamp(x, minValue, maxValue) {
374
+ return Math.min(Math.max(x, minValue), maxValue);
341
375
  }
342
376
  handleMinDateInput(e) {
343
377
  const target = e.currentTarget;
@@ -349,27 +383,44 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
349
383
  this.maxSelectedDate = target.value;
350
384
  this.beginEmitUpdateProcess();
351
385
  }
386
+ handleKeyUp(e) {
387
+ if (e.key === 'Enter') {
388
+ const target = e.currentTarget;
389
+ target.blur();
390
+ }
391
+ }
352
392
  get currentDateRangeString() {
353
393
  return `${this.minSelectedDate}:${this.maxSelectedDate}`;
354
394
  }
355
- /** minimum selected date in milliseconds */
356
- get minSelectedDateMS() {
357
- return dayjs(this.minSelectedDate).valueOf();
358
- }
359
- /** maximum selected date in milliseconds */
360
- get maxSelectedDateMS() {
361
- return dayjs(this.maxSelectedDate).valueOf();
395
+ getMSFromString(date) {
396
+ const digitGroupCount = (date.split(/(\d+)/).length - 1) / 2;
397
+ if (digitGroupCount === 1) {
398
+ // if there's just a single set of digits, assume it's a year
399
+ const dateObj = new Date(0, 0); // start at January 1, 1900
400
+ dateObj.setFullYear(Number(date)); // override year (=> 0099-01-01) = 99 CE
401
+ return dateObj.getTime(); // get time in milliseconds
402
+ }
403
+ return dayjs(date, [this.dateFormat, DATE_FORMAT]).valueOf();
362
404
  }
405
+ /**
406
+ * expand or narrow the selected range by moving the slider nearest the
407
+ * clicked bar to the outer edge of the clicked bar
408
+ *
409
+ * @param e Event click event from a histogram bar
410
+ */
363
411
  handleBarClick(e) {
364
- var _a, _b;
365
412
  const dataset = e.currentTarget.dataset;
366
- const binStartDateMS = dayjs(dataset.binStart).valueOf();
367
- if (binStartDateMS < this.minSelectedDateMS) {
368
- this.minSelectedDate = (_a = dataset.binStart) !== null && _a !== void 0 ? _a : '';
413
+ const clickPosition = (this.getMSFromString(dataset.binStart) +
414
+ this.getMSFromString(dataset.binEnd)) /
415
+ 2;
416
+ const distanceFromMinSlider = Math.abs(clickPosition - this.getMSFromString(this.minSelectedDate));
417
+ const distanceFromMaxSlider = Math.abs(clickPosition - this.getMSFromString(this.maxSelectedDate));
418
+ // update the selected range by moving the nearer slider
419
+ if (distanceFromMinSlider < distanceFromMaxSlider) {
420
+ this.minSelectedDate = dataset.binStart;
369
421
  }
370
- const binEndDateMS = dayjs(dataset.binEnd).valueOf();
371
- if (binEndDateMS > this.maxSelectedDateMS) {
372
- this.maxSelectedDate = (_b = dataset.binEnd) !== null && _b !== void 0 ? _b : '';
422
+ else {
423
+ this.maxSelectedDate = dataset.binEnd;
373
424
  }
374
425
  this.beginEmitUpdateProcess();
375
426
  }
@@ -407,10 +458,12 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
407
458
  return svg `
408
459
  <svg
409
460
  id="${id}"
410
- class="draggable ${this._isDragging ? 'dragging' : ''}"
461
+ class="
462
+ ${this.disabled ? '' : 'draggable'}
463
+ ${this._isDragging ? 'dragging' : ''}"
411
464
  @pointerdown="${this.drag}"
412
465
  >
413
- <path d="${sliderShape} z" fill="${sliderFill}" />
466
+ <path d="${sliderShape} z" fill="${sliderColor}" />
414
467
  <rect
415
468
  x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k}"
416
469
  y="${this.height / 3}"
@@ -435,7 +488,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
435
488
  y="0"
436
489
  width="${this.maxSliderX - this.minSliderX}"
437
490
  height="${this.height}"
438
- fill="${selectedRangeFill}"
491
+ fill="${selectedRangeColor}"
439
492
  />`;
440
493
  }
441
494
  get histogramTemplate() {
@@ -458,7 +511,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
458
511
  @pointerenter="${this.showTooltip}"
459
512
  @pointerleave="${this.hideTooltip}"
460
513
  @click="${this.handleBarClick}"
461
- fill="${x >= this.minSliderX && x <= this.maxSliderX
514
+ fill="${x + barWidth >= this.minSliderX && x <= this.maxSliderX
462
515
  ? barIncludedFill
463
516
  : barExcludedFill}"
464
517
  data-num-items="${data.value}"
@@ -469,9 +522,17 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
469
522
  return bar;
470
523
  });
471
524
  }
472
- formatDate(rawDate) {
473
- const date = dayjs(rawDate);
474
- return date.isValid() ? date.format(this.dateFormat) : '';
525
+ formatDate(dateMS) {
526
+ if (Number.isNaN(dateMS)) {
527
+ return '';
528
+ }
529
+ const date = dayjs(dateMS);
530
+ if (date.year() < 1000) {
531
+ // years before 1000 don't play well with dayjs custom formatting, so fall
532
+ // back to displaying only the year
533
+ return String(date.year());
534
+ }
535
+ return date.format(this.dateFormat);
475
536
  }
476
537
  /**
477
538
  * NOTE: we are relying on the lit `live` directive in the template to
@@ -487,6 +548,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
487
548
  type="text"
488
549
  @focus="${this.cancelPendingUpdateEvent}"
489
550
  @blur="${this.handleMinDateInput}"
551
+ @keyup="${this.handleKeyUp}"
490
552
  .value="${live(this.minSelectedDate)}"
491
553
  ?disabled="${this.disabled}"
492
554
  />
@@ -500,6 +562,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
500
562
  type="text"
501
563
  @focus="${this.cancelPendingUpdateEvent}"
502
564
  @blur="${this.handleMaxDateInput}"
565
+ @keyup="${this.handleKeyUp}"
503
566
  .value="${live(this.maxSelectedDate)}"
504
567
  ?disabled="${this.disabled}"
505
568
  />
@@ -529,7 +592,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
529
592
  }
530
593
  get activityIndicatorTemplate() {
531
594
  if (!this.loading) {
532
- return html ``;
595
+ return nothing;
533
596
  }
534
597
  return html `
535
598
  <ia-activity-indicator mode="processing"> </ia-activity-indicator>
@@ -629,7 +692,7 @@ HistogramDateRange.styles = css `
629
692
  border-radius: 3px;
630
693
  padding: 2px;
631
694
  font-size: ${tooltipFontSize};
632
- font-family: sans-serif;
695
+ font-family: ${tooltipFontFamily};
633
696
  touch-action: none;
634
697
  pointer-events: none;
635
698
  }
@@ -666,6 +729,7 @@ HistogramDateRange.styles = css `
666
729
  border-radius: 2px !important;
667
730
  text-align: center;
668
731
  font-size: ${inputFontSize};
732
+ font-family: ${inputFontFamily};
669
733
  }
670
734
  `;
671
735
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"histogram-date-range.js","sourceRoot":"","sources":["../../src/histogram-date-range.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n css,\n html,\n LitElement,\n PropertyValues,\n svg,\n SVGTemplateResult,\n TemplateResult,\n} from 'lit';\nimport { property, state, customElement } from 'lit/decorators.js';\nimport { live } from 'lit/directives/live.js';\nimport dayjs from 'dayjs/esm/index.js';\nimport '@internetarchive/ia-activity-indicator/ia-activity-indicator';\n\n// these values can be overridden via the component's HTML (camelCased) attributes\nconst WIDTH = 180;\nconst HEIGHT = 40;\nconst SLIDER_WIDTH = 10;\nconst TOOLTIP_WIDTH = 125;\nconst TOOLTIP_HEIGHT = 30;\nconst DATE_FORMAT = 'YYYY';\nconst MISSING_DATA = 'no data';\nconst UPDATE_DEBOUNCE_DELAY_MS = 1000;\n\n// this constant is not set up to be overridden\nconst SLIDER_CORNER_SIZE = 4;\n\n// these CSS custom props can be overridden from the HTML that is invoking this component\nconst sliderFill = css`var(--histogramDateRangeSliderFill, #4B65FE)`;\nconst selectedRangeFill = css`var(--histogramDateRangeSelectedRangeFill, #DBE0FF)`;\nconst barIncludedFill = css`var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;\nconst activityIndicatorColor = css`var(--histogramDateRangeActivityIndicator, #2C2C2C)`;\nconst barExcludedFill = css`var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;\nconst inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;\nconst inputWidth = css`var(--histogramDateRangeInputWidth, 35px)`;\nconst inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;\nconst tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;\nconst tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;\nconst tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;\n\ntype SliderId = 'slider-min' | 'slider-max';\n\ninterface HistogramItem {\n value: number;\n height: number;\n binStart: string;\n binEnd: string;\n}\n\n@customElement('histogram-date-range')\nexport class HistogramDateRange extends LitElement {\n /* eslint-disable lines-between-class-members */\n\n // public reactive properties that can be set via HTML attributes\n @property({ type: Number }) width = WIDTH;\n @property({ type: Number }) height = HEIGHT;\n @property({ type: Number }) sliderWidth = SLIDER_WIDTH;\n @property({ type: Number }) tooltipWidth = TOOLTIP_WIDTH;\n @property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;\n @property({ type: Number }) updateDelay = UPDATE_DEBOUNCE_DELAY_MS;\n @property() dateFormat = DATE_FORMAT;\n @property() missingDataMessage = MISSING_DATA;\n @property() minDate = '';\n @property() maxDate = '';\n @property({ type: Boolean }) disabled = false;\n @property({ type: Object }) bins: number[] = [];\n\n // internal reactive properties not exposed as attributes\n @state() private _tooltipOffset = 0;\n @state() private _tooltipContent?: TemplateResult;\n @state() private _tooltipVisible = false;\n @state() private _isDragging = false;\n @state() private _isLoading = false;\n\n // non-reactive properties (changes don't auto-trigger re-rendering)\n private _minSelectedDate = '';\n private _maxSelectedDate = '';\n private _minDateMS = 0;\n private _maxDateMS = 0;\n private _dragOffset = 0;\n private _histWidth = 0;\n private _binWidth = 0;\n private _currentSlider?: SVGRectElement;\n private _histData: HistogramItem[] = [];\n private _emitUpdatedEventTimer?: ReturnType<typeof setTimeout>;\n private _previousDateRange = '';\n\n /* eslint-enable lines-between-class-members */\n\n disconnectedCallback(): void {\n this.removeListeners();\n super.disconnectedCallback();\n }\n\n updated(changedProps: PropertyValues): void {\n if (changedProps.has('bins') || changedProps.has('Date')) {\n this.handleDataUpdate();\n }\n }\n\n /**\n * Set private properties that depend on the attribute bin data\n *\n * We're caching these values and not using getters to avoid recalculating all\n * of the hist data every time the user drags a slider or hovers over a bar\n * creating a tooltip.\n */\n private handleDataUpdate(): void {\n if (!this.hasBinData) {\n return;\n }\n this._histWidth = this.width - this.sliderWidth * 2;\n this._minDateMS = dayjs(this.minDate).valueOf();\n this._maxDateMS = dayjs(this.maxDate).valueOf();\n this._binWidth = this._histWidth / this._numBins;\n this._previousDateRange = this.currentDateRangeString;\n this._histData = this.calculateHistData();\n this.minSelectedDate = this.minSelectedDate\n ? this.minSelectedDate\n : this.minDate;\n this.maxSelectedDate = this.maxSelectedDate\n ? this.maxSelectedDate\n : this.maxDate;\n this.requestUpdate();\n }\n\n private calculateHistData(): HistogramItem[] {\n const minValue = Math.min(...this.bins);\n const maxValue = Math.max(...this.bins);\n const valueScale = this.height / Math.log1p(maxValue - minValue);\n const dateScale = this.dateRangeMS / this._numBins;\n return this.bins.map((v: number, i: number) => {\n return {\n value: v,\n height: Math.floor(Math.log1p(v) * valueScale),\n binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,\n binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,\n };\n });\n }\n\n private get hasBinData(): boolean {\n return this._numBins > 0;\n }\n\n private get _numBins(): number {\n if (!this.bins || !this.bins.length) {\n return 0;\n }\n return this.bins.length;\n }\n\n /** component's loading (and disabled) state */\n @property({ type: Boolean }) get loading(): boolean {\n return this._isLoading;\n }\n\n set loading(value: boolean) {\n this.disabled = value;\n this._isLoading = value;\n }\n\n /** formatted minimum date of selected date range */\n @property() get minSelectedDate(): string {\n return this.formatDate(this._minSelectedDate);\n }\n\n set minSelectedDate(rawDate: string) {\n if (!this._minSelectedDate) {\n // because the values needed to calculate valid max/min values are not\n // available during the lit init when it's populating properties from\n // attributes, fall back to just the raw date if nothing is already set\n this._minSelectedDate = rawDate;\n }\n const x = this.translateDateToPosition(rawDate);\n if (x) {\n const validX = this.validMinSliderX(x);\n this._minSelectedDate = this.translatePositionToDate(validX);\n }\n this.requestUpdate();\n }\n\n /** formatted maximum date of selected date range */\n @property() get maxSelectedDate(): string {\n return this.formatDate(this._maxSelectedDate);\n }\n\n set maxSelectedDate(rawDate: string) {\n if (!this._maxSelectedDate) {\n // see comment above in the minSelectedDate setter\n this._maxSelectedDate = rawDate;\n }\n const x = this.translateDateToPosition(rawDate);\n if (x) {\n const validX = this.validMaxSliderX(x);\n this._maxSelectedDate = this.translatePositionToDate(validX);\n }\n this.requestUpdate();\n }\n /** horizontal position of min date slider */\n get minSliderX(): number {\n return (\n // default to leftmost position if missing or invalid min position\n this.translateDateToPosition(this.minSelectedDate) ?? this.sliderWidth\n );\n }\n\n /** horizontal position of max date slider */\n get maxSliderX(): number {\n return (\n // default to rightmost position if missing or invalid max position\n this.translateDateToPosition(this.maxSelectedDate) ??\n this.width - this.sliderWidth\n );\n }\n\n private get dateRangeMS(): number {\n return this._maxDateMS - this._minDateMS;\n }\n\n private showTooltip(e: PointerEvent): void {\n if (this._isDragging || this.disabled) {\n return;\n }\n const target = e.currentTarget as SVGRectElement;\n const x = target.x.baseVal.value + this.sliderWidth / 2;\n const dataset = target.dataset;\n const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;\n\n this._tooltipOffset =\n x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;\n\n this._tooltipContent = html`\n ${dataset.numItems} ${itemsText}<br />\n ${dataset.binStart} - ${dataset.binEnd}\n `;\n this._tooltipVisible = true;\n }\n\n private hideTooltip(): void {\n this._tooltipContent = undefined;\n this._tooltipVisible = false;\n }\n\n // use arrow functions (rather than standard JS class instance methods) so\n // that `this` is bound to the histogramDateRange object and not the event\n // target. for more info see\n // https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners\n private drag = (e: PointerEvent): void => {\n // prevent selecting text or other ranges while dragging, especially in Safari\n e.preventDefault();\n if (this.disabled) {\n return;\n }\n this.setDragOffset(e);\n this._isDragging = true;\n this.addListeners();\n this.cancelPendingUpdateEvent();\n };\n\n private drop = (): void => {\n if (this._isDragging) {\n this.removeListeners();\n this.beginEmitUpdateProcess();\n }\n this._isDragging = false;\n };\n\n /**\n * Adjust the date range based on slider movement\n *\n * @param e PointerEvent from the slider being moved\n */\n private move = (e: PointerEvent): void => {\n const newX = e.offsetX - this._dragOffset;\n const slider = this._currentSlider as SVGRectElement;\n const date = this.translatePositionToDate(newX);\n if ((slider.id as SliderId) === 'slider-min') {\n this.minSelectedDate = date;\n } else {\n this.maxSelectedDate = date;\n }\n };\n\n /**\n * Constrain a proposed value for the minimum (left) slider\n *\n * If the value is less than the leftmost valid position, then set it to the\n * left edge of the widget (ie the slider width). If the value is greater than\n * the rightmost valid position (the position of the max slider), then set it\n * to the position of the max slider\n */\n private validMinSliderX(newX: number): number {\n const validX = Math.max(newX, this.sliderWidth);\n return Math.min(validX, this.maxSliderX);\n }\n\n /**\n * Constrain a proposed value for the maximum (right) slider\n *\n * If the value is greater than the rightmost valid position, then set it to\n * the right edge of the widget (ie widget width - slider width). If the value\n * is less than the leftmost valid position (the position of the min slider),\n * then set it to the position of the min slider\n */\n private validMaxSliderX(newX: number): number {\n const validX = Math.max(newX, this.minSliderX);\n return Math.min(validX, this.width - this.sliderWidth);\n }\n\n private addListeners(): void {\n window.addEventListener('pointermove', this.move);\n window.addEventListener('pointerup', this.drop);\n window.addEventListener('pointercancel', this.drop);\n }\n\n private removeListeners(): void {\n window.removeEventListener('pointermove', this.move);\n window.removeEventListener('pointerup', this.drop);\n window.removeEventListener('pointercancel', this.drop);\n }\n\n /**\n * start a timer to emit an update event. this timer can be canceled (and the\n * event not emitted) if user drags a slider or focuses a date input within\n * the update delay\n */\n private beginEmitUpdateProcess(): void {\n this.cancelPendingUpdateEvent();\n this._emitUpdatedEventTimer = setTimeout(() => {\n if (this.currentDateRangeString === this._previousDateRange) {\n // don't emit duplicate event if no change since last emitted event\n return;\n }\n this._previousDateRange = this.currentDateRangeString;\n const options = {\n detail: {\n minDate: this.minSelectedDate,\n maxDate: this.maxSelectedDate,\n },\n bubbles: true,\n composed: true,\n };\n this.dispatchEvent(new CustomEvent('histogramDateRangeUpdated', options));\n }, this.updateDelay);\n }\n\n private cancelPendingUpdateEvent(): void {\n if (this._emitUpdatedEventTimer === undefined) {\n return;\n }\n clearTimeout(this._emitUpdatedEventTimer);\n this._emitUpdatedEventTimer = undefined;\n }\n\n /**\n * find position of pointer in relation to the current slider\n */\n private setDragOffset(e: PointerEvent): void {\n this._currentSlider = e.currentTarget as SVGRectElement;\n const sliderX =\n (this._currentSlider.id as SliderId) === 'slider-min'\n ? this.minSliderX\n : this.maxSliderX;\n this._dragOffset = e.offsetX - sliderX;\n // work around Firefox issue where e.offsetX seems to be not based on current\n // element but on background element\n if (\n this._dragOffset > this.sliderWidth ||\n this._dragOffset < -this.sliderWidth\n ) {\n this._dragOffset = 0;\n }\n }\n\n /**\n * @param x horizontal position of slider\n * @returns string representation of date\n */\n private translatePositionToDate(x: number): string {\n // use Math.ceil to round up to fix case where input like 1/1/2010 would get\n // translated to 12/31/2009\n const milliseconds = Math.ceil(\n ((x - this.sliderWidth) * this.dateRangeMS) / this._histWidth\n );\n return this.formatDate(this._minDateMS + milliseconds);\n }\n\n /**\n * Returns slider x-position corresponding to given date (or null if invalid\n * date)\n *\n * @param date\n * @returns x-position of slider\n */\n private translateDateToPosition(date: string): number | null {\n const milliseconds = dayjs(date).valueOf();\n const xPosition =\n this.sliderWidth +\n ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS;\n return isNaN(milliseconds) || isNaN(xPosition) ? null : xPosition;\n }\n\n private handleMinDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n this.minSelectedDate = target.value;\n this.beginEmitUpdateProcess();\n }\n\n private handleMaxDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n this.maxSelectedDate = target.value;\n this.beginEmitUpdateProcess();\n }\n\n private get currentDateRangeString(): string {\n return `${this.minSelectedDate}:${this.maxSelectedDate}`;\n }\n\n /** minimum selected date in milliseconds */\n private get minSelectedDateMS(): number {\n return dayjs(this.minSelectedDate).valueOf();\n }\n\n /** maximum selected date in milliseconds */\n private get maxSelectedDateMS(): number {\n return dayjs(this.maxSelectedDate).valueOf();\n }\n\n private handleBarClick(e: InputEvent): void {\n const dataset = (e.currentTarget as SVGRectElement).dataset as DOMStringMap;\n const binStartDateMS = dayjs(dataset.binStart).valueOf();\n if (binStartDateMS < this.minSelectedDateMS) {\n this.minSelectedDate = dataset.binStart ?? '';\n }\n const binEndDateMS = dayjs(dataset.binEnd).valueOf();\n if (binEndDateMS > this.maxSelectedDateMS) {\n this.maxSelectedDate = dataset.binEnd ?? '';\n }\n this.beginEmitUpdateProcess();\n }\n\n private get minSliderTemplate(): SVGTemplateResult {\n // width/height in pixels of curved part of the sliders (like\n // border-radius); used as part of a SVG quadratic curve. see\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands\n const cs = SLIDER_CORNER_SIZE;\n\n const sliderShape = `\n M${this.minSliderX},0\n h-${this.sliderWidth - cs}\n q-${cs},0 -${cs},${cs}\n v${this.height - cs * 2}\n q0,${cs} ${cs},${cs}\n h${this.sliderWidth - cs}\n `;\n return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);\n }\n\n private get maxSliderTemplate(): SVGTemplateResult {\n const cs = SLIDER_CORNER_SIZE;\n const sliderShape = `\n M${this.maxSliderX},0\n h${this.sliderWidth - cs}\n q${cs},0 ${cs},${cs}\n v${this.height - cs * 2}\n q0,${cs} -${cs},${cs}\n h-${this.sliderWidth - cs}\n `;\n return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);\n }\n\n private generateSliderSVG(\n sliderPositionX: number,\n id: SliderId,\n sliderShape: string\n ): SVGTemplateResult {\n // whether the curved part of the slider is facing towards the left (1), ie\n // minimum, or facing towards the right (-1), ie maximum\n const k = id === 'slider-min' ? 1 : -1;\n\n return svg`\n <svg\n id=\"${id}\"\n class=\"draggable ${this._isDragging ? 'dragging' : ''}\"\n @pointerdown=\"${this.drag}\"\n >\n <path d=\"${sliderShape} z\" fill=\"${sliderFill}\" />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n </svg>\n `;\n }\n\n get selectedRangeTemplate(): SVGTemplateResult {\n return svg`\n <rect\n x=\"${this.minSliderX}\"\n y=\"0\"\n width=\"${this.maxSliderX - this.minSliderX}\"\n height=\"${this.height}\"\n fill=\"${selectedRangeFill}\"\n />`;\n }\n\n get histogramTemplate(): SVGTemplateResult[] {\n const xScale = this._histWidth / this._numBins;\n const barWidth = xScale - 1;\n let x = this.sliderWidth; // start at the left edge of the histogram\n\n // the stroke-dasharray style below creates a transparent border around the\n // right edge of the bar, which prevents user from encountering a gap\n // between adjacent bars (eg when viewing the tooltips or when trying to\n // extend the range by clicking on a bar)\n return this._histData.map(data => {\n const bar = svg`\n <rect\n class=\"bar\"\n style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${\n data.height\n };'\n x=\"${x}\"\n y=\"${this.height - data.height}\"\n width=\"${barWidth}\"\n height=\"${data.height}\"\n @pointerenter=\"${this.showTooltip}\"\n @pointerleave=\"${this.hideTooltip}\"\n @click=\"${this.handleBarClick}\"\n fill=\"${\n x >= this.minSliderX && x <= this.maxSliderX\n ? barIncludedFill\n : barExcludedFill\n }\"\n data-num-items=\"${data.value}\"\n data-bin-start=\"${data.binStart}\"\n data-bin-end=\"${data.binEnd}\"\n />`;\n x += xScale;\n return bar;\n });\n }\n\n private formatDate(rawDate: string | number): string {\n const date = dayjs(rawDate);\n return date.isValid() ? date.format(this.dateFormat) : '';\n }\n\n /**\n * NOTE: we are relying on the lit `live` directive in the template to\n * ensure that the change to minSelectedDate is noticed and the input value\n * gets properly re-rendered. see\n * https://lit.dev/docs/templates/directives/#live\n */\n get minInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-min\"\n placeholder=\"${this.dateFormat}\"\n type=\"text\"\n @focus=\"${this.cancelPendingUpdateEvent}\"\n @blur=\"${this.handleMinDateInput}\"\n .value=\"${live(this.minSelectedDate)}\"\n ?disabled=\"${this.disabled}\"\n />\n `;\n }\n\n get maxInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-max\"\n placeholder=\"${this.dateFormat}\"\n type=\"text\"\n @focus=\"${this.cancelPendingUpdateEvent}\"\n @blur=\"${this.handleMaxDateInput}\"\n .value=\"${live(this.maxSelectedDate)}\"\n ?disabled=\"${this.disabled}\"\n />\n `;\n }\n\n get tooltipTemplate(): TemplateResult {\n return html`\n <style>\n #tooltip {\n width: ${this.tooltipWidth}px;\n height: ${this.tooltipHeight}px;\n top: ${-9 - this.tooltipHeight}px;\n left: ${this._tooltipOffset}px;\n display: ${this._tooltipVisible ? 'block' : 'none'};\n }\n #tooltip:after {\n left: ${this.tooltipWidth / 2}px;\n }\n </style>\n <div id=\"tooltip\">${this._tooltipContent}</div>\n `;\n }\n\n private get noDataTemplate(): TemplateResult {\n return html`\n <div class=\"missing-data-message\">${this.missingDataMessage}</div>\n `;\n }\n\n private get activityIndicatorTemplate(): TemplateResult {\n if (!this.loading) {\n return html``;\n }\n return html`\n <ia-activity-indicator mode=\"processing\"> </ia-activity-indicator>\n `;\n }\n\n static styles = css`\n .missing-data-message {\n text-align: center;\n }\n #container {\n margin: 0;\n touch-action: none;\n position: relative;\n }\n .disabled {\n opacity: 0.3;\n }\n ia-activity-indicator {\n position: absolute;\n left: calc(50% - 10px);\n top: 10px;\n width: 20px;\n height: 20px;\n --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);\n --activityIndicatorLoadingRingColor: ${activityIndicatorColor};\n }\n\n /* prevent selection from interfering with tooltip, especially on mobile */\n /* https://stackoverflow.com/a/4407335/1163042 */\n .noselect {\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* current Chrome, Edge, Opera and Firefox */\n }\n .bar {\n /* create a transparent border around the hist bars to prevent \"gaps\" and\n flickering when moving around between bars. this also helps with handling\n clicks on the bars, preventing users from being able to click in between\n bars */\n stroke: rgba(0, 0, 0, 0);\n /* ensure transparent stroke wide enough to cover gap between bars */\n stroke-width: 2px;\n }\n .bar:hover {\n /* highlight currently hovered bar */\n fill-opacity: 0.7;\n }\n .disabled .bar:hover {\n /* ensure no visual hover interaction when disabled */\n fill-opacity: 1;\n }\n /****** histogram ********/\n #tooltip {\n position: absolute;\n background: ${tooltipBackgroundColor};\n color: ${tooltipTextColor};\n text-align: center;\n border-radius: 3px;\n padding: 2px;\n font-size: ${tooltipFontSize};\n font-family: sans-serif;\n touch-action: none;\n pointer-events: none;\n }\n #tooltip:after {\n content: '';\n position: absolute;\n margin-left: -5px;\n top: 100%;\n /* arrow */\n border: 5px solid ${tooltipTextColor};\n border-color: ${tooltipBackgroundColor} transparent transparent\n transparent;\n }\n /****** slider ********/\n .draggable:hover {\n cursor: grab;\n }\n .dragging {\n cursor: grabbing !important;\n }\n /****** inputs ********/\n #inputs {\n display: flex;\n justify-content: center;\n }\n #inputs .dash {\n position: relative;\n bottom: -1px;\n }\n input {\n width: ${inputWidth};\n margin: 0 3px;\n border: ${inputBorder};\n border-radius: 2px !important;\n text-align: center;\n font-size: ${inputFontSize};\n }\n `;\n\n render(): TemplateResult {\n if (!this.hasBinData) {\n return this.noDataTemplate;\n }\n return html`\n <div\n id=\"container\"\n class=\"\n noselect \n ${this._isDragging ? 'dragging' : ''}\n \"\n style=\"width: ${this.width}px\"\n >\n ${this.activityIndicatorTemplate} ${this.tooltipTemplate}\n <div\n class=\"inner-container\n ${this.disabled ? 'disabled' : ''}\"\n >\n <svg\n width=\"${this.width}\"\n height=\"${this.height}\"\n @pointerleave=\"${this.drop}\"\n >\n ${this.selectedRangeTemplate}\n <svg id=\"histogram\">${this.histogramTemplate}</svg>\n ${this.minSliderTemplate} ${this.maxSliderTemplate}\n </svg>\n <div id=\"inputs\">\n ${this.minInputTemplate}\n <div class=\"dash\">-</div>\n ${this.maxInputTemplate}\n </div>\n </div>\n </div>\n `;\n }\n}\ndeclare global {\n interface HTMLElementTagNameMap {\n 'histogram-date-range': HistogramDateRange;\n }\n}\n"]}
1
+ {"version":3,"file":"histogram-date-range.js","sourceRoot":"","sources":["../../src/histogram-date-range.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n css,\n html,\n nothing,\n LitElement,\n PropertyValues,\n svg,\n SVGTemplateResult,\n TemplateResult,\n} from 'lit';\nimport { property, state, customElement } from 'lit/decorators.js';\nimport { live } from 'lit/directives/live.js';\nimport dayjs from 'dayjs/esm/index.js';\nimport customParseFormat from 'dayjs/esm/plugin/customParseFormat';\ndayjs.extend(customParseFormat);\nimport '@internetarchive/ia-activity-indicator/ia-activity-indicator';\n\n// these values can be overridden via the component's HTML (camelCased) attributes\nconst WIDTH = 180;\nconst HEIGHT = 40;\nconst SLIDER_WIDTH = 10;\nconst TOOLTIP_WIDTH = 125;\nconst TOOLTIP_HEIGHT = 30;\nconst DATE_FORMAT = 'YYYY';\nconst MISSING_DATA = 'no data';\nconst UPDATE_DEBOUNCE_DELAY_MS = 0;\n\n// this constant is not set up to be overridden\nconst SLIDER_CORNER_SIZE = 4;\n\n// these CSS custom props can be overridden from the HTML that is invoking this component\nconst sliderColor = css`var(--histogramDateRangeSliderColor, #4B65FE)`;\nconst selectedRangeColor = css`var(--histogramDateRangeSelectedRangeColor, #DBE0FF)`;\nconst barIncludedFill = css`var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;\nconst activityIndicatorColor = css`var(--histogramDateRangeActivityIndicator, #2C2C2C)`;\nconst barExcludedFill = css`var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;\nconst inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;\nconst inputWidth = css`var(--histogramDateRangeInputWidth, 35px)`;\nconst inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;\nconst inputFontFamily = css`var(--histogramDateRangeInputFontFamily, sans-serif)`;\nconst tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;\nconst tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;\nconst tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;\nconst tooltipFontFamily = css`var(--histogramDateRangeTooltipFontFamily, sans-serif)`;\n\ntype SliderId = 'slider-min' | 'slider-max';\n\ninterface HistogramItem {\n value: number;\n height: number;\n binStart: string;\n binEnd: string;\n}\n\ninterface BarDataset extends DOMStringMap {\n numItems: string;\n binStart: string;\n binEnd: string;\n}\n\n@customElement('histogram-date-range')\nexport class HistogramDateRange extends LitElement {\n /* eslint-disable lines-between-class-members */\n\n // public reactive properties that can be set via HTML attributes\n @property({ type: Number }) width = WIDTH;\n @property({ type: Number }) height = HEIGHT;\n @property({ type: Number }) sliderWidth = SLIDER_WIDTH;\n @property({ type: Number }) tooltipWidth = TOOLTIP_WIDTH;\n @property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;\n @property({ type: Number }) updateDelay = UPDATE_DEBOUNCE_DELAY_MS;\n @property() dateFormat = DATE_FORMAT;\n @property() missingDataMessage = MISSING_DATA;\n @property() minDate = '';\n @property() maxDate = '';\n @property({ type: Boolean }) disabled = false;\n @property({ type: Object }) bins: number[] = [];\n\n // internal reactive properties not exposed as attributes\n @state() private _tooltipOffset = 0;\n @state() private _tooltipContent?: TemplateResult;\n @state() private _tooltipVisible = false;\n @state() private _isDragging = false;\n @state() private _isLoading = false;\n\n // non-reactive properties (changes don't auto-trigger re-rendering)\n private _minSelectedDate = '';\n private _maxSelectedDate = '';\n private _minDateMS = 0;\n private _maxDateMS = 0;\n private _dragOffset = 0;\n private _histWidth = 0;\n private _binWidth = 0;\n private _currentSlider?: SVGRectElement;\n private _histData: HistogramItem[] = [];\n private _emitUpdatedEventTimer?: ReturnType<typeof setTimeout>;\n private _previousDateRange = '';\n\n /* eslint-enable lines-between-class-members */\n\n disconnectedCallback(): void {\n this.removeListeners();\n super.disconnectedCallback();\n }\n\n updated(changedProps: PropertyValues): void {\n // check for changes that would affect bin data calculations\n if (\n changedProps.has('bins') ||\n changedProps.has('minDate') ||\n changedProps.has('maxDate') ||\n changedProps.has('minSelectedDate') ||\n changedProps.has('maxSelectedDate')\n ) {\n this.handleDataUpdate();\n }\n }\n\n /**\n * Set private properties that depend on the attribute bin data\n *\n * We're caching these values and not using getters to avoid recalculating all\n * of the hist data every time the user drags a slider or hovers over a bar\n * creating a tooltip.\n */\n private handleDataUpdate(): void {\n if (!this.hasBinData) {\n return;\n }\n this._histWidth = this.width - this.sliderWidth * 2;\n this._minDateMS = this.getMSFromString(this.minDate);\n this._maxDateMS = this.getMSFromString(this.maxDate);\n this._binWidth = this._histWidth / this._numBins;\n this._previousDateRange = this.currentDateRangeString;\n this._histData = this.calculateHistData();\n this.minSelectedDate = this.minSelectedDate\n ? this.minSelectedDate\n : this.minDate;\n this.maxSelectedDate = this.maxSelectedDate\n ? this.maxSelectedDate\n : this.maxDate;\n this.requestUpdate();\n }\n\n private calculateHistData(): HistogramItem[] {\n const minValue = Math.min(...this.bins);\n const maxValue = Math.max(...this.bins);\n // if there is no difference between the min and max values, use a range of\n // 1 because log scaling will fail if the range is 0\n const valueRange =\n minValue === maxValue ? 1 : Math.log1p(maxValue - minValue);\n const valueScale = this.height / valueRange;\n const dateScale = this.dateRangeMS / this._numBins;\n return this.bins.map((v: number, i: number) => {\n return {\n value: v,\n // use log scaling for the height of the bar to prevent tall bars from\n // making the smaller ones too small to see\n height: Math.floor(Math.log1p(v) * valueScale),\n binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,\n binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,\n };\n });\n }\n\n private get hasBinData(): boolean {\n return this._numBins > 0;\n }\n\n private get _numBins(): number {\n if (!this.bins || !this.bins.length) {\n return 0;\n }\n return this.bins.length;\n }\n\n private get histogramLeftEdgeX(): number {\n return this.sliderWidth;\n }\n\n private get histogramRightEdgeX(): number {\n return this.width - this.sliderWidth;\n }\n\n /** component's loading (and disabled) state */\n @property({ type: Boolean }) get loading(): boolean {\n return this._isLoading;\n }\n\n set loading(value: boolean) {\n this.disabled = value;\n this._isLoading = value;\n }\n\n /** formatted minimum date of selected date range */\n @property() get minSelectedDate(): string {\n return this.formatDate(this.getMSFromString(this._minSelectedDate));\n }\n\n /** updates minSelectedDate if new date is valid */\n set minSelectedDate(rawDate: string) {\n if (!this._minSelectedDate) {\n // because the values needed to calculate valid max/min values are not\n // available during the lit init when it's populating properties from\n // attributes, fall back to just the raw date if nothing is already set\n this._minSelectedDate = rawDate;\n return;\n }\n const proposedDateMS = this.getMSFromString(rawDate);\n const isValidDate = !Number.isNaN(proposedDateMS);\n const isNotTooRecent =\n proposedDateMS <= this.getMSFromString(this.maxSelectedDate);\n if (isValidDate && isNotTooRecent) {\n this._minSelectedDate = this.formatDate(proposedDateMS);\n }\n this.requestUpdate();\n }\n\n /** formatted maximum date of selected date range */\n @property() get maxSelectedDate(): string {\n return this.formatDate(this.getMSFromString(this._maxSelectedDate));\n }\n\n /** updates maxSelectedDate if new date is valid */\n set maxSelectedDate(rawDate: string) {\n if (!this._maxSelectedDate) {\n // because the values needed to calculate valid max/min values are not\n // available during the lit init when it's populating properties from\n // attributes, fall back to just the raw date if nothing is already set\n this._maxSelectedDate = rawDate;\n return;\n }\n const proposedDateMS = this.getMSFromString(rawDate);\n const isValidDate = !Number.isNaN(proposedDateMS);\n const isNotTooOld =\n proposedDateMS >= this.getMSFromString(this.minSelectedDate);\n if (isValidDate && isNotTooOld) {\n this._maxSelectedDate = this.formatDate(proposedDateMS);\n }\n this.requestUpdate();\n }\n\n /** horizontal position of min date slider */\n get minSliderX(): number {\n const x = this.translateDateToPosition(this.minSelectedDate);\n return this.validMinSliderX(x);\n }\n\n /** horizontal position of max date slider */\n get maxSliderX(): number {\n const x = this.translateDateToPosition(this.maxSelectedDate);\n return this.validMaxSliderX(x);\n }\n\n private get dateRangeMS(): number {\n return this._maxDateMS - this._minDateMS;\n }\n\n private showTooltip(e: PointerEvent): void {\n if (this._isDragging || this.disabled) {\n return;\n }\n const target = e.currentTarget as SVGRectElement;\n const x = target.x.baseVal.value + this.sliderWidth / 2;\n const dataset = target.dataset as BarDataset;\n const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;\n const formattedNumItems = Number(dataset.numItems).toLocaleString();\n\n this._tooltipOffset =\n x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;\n\n this._tooltipContent = html`\n ${formattedNumItems} ${itemsText}<br />\n ${dataset.binStart} - ${dataset.binEnd}\n `;\n this._tooltipVisible = true;\n }\n\n private hideTooltip(): void {\n this._tooltipContent = undefined;\n this._tooltipVisible = false;\n }\n\n // use arrow functions (rather than standard JS class instance methods) so\n // that `this` is bound to the histogramDateRange object and not the event\n // target. for more info see\n // https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners\n private drag = (e: PointerEvent): void => {\n // prevent selecting text or other ranges while dragging, especially in Safari\n e.preventDefault();\n if (this.disabled) {\n return;\n }\n this.setDragOffset(e);\n this._isDragging = true;\n this.addListeners();\n this.cancelPendingUpdateEvent();\n };\n\n private drop = (): void => {\n if (this._isDragging) {\n this.removeListeners();\n this.beginEmitUpdateProcess();\n }\n this._isDragging = false;\n };\n\n /**\n * Adjust the date range based on slider movement\n *\n * @param e PointerEvent from the slider being moved\n */\n private move = (e: PointerEvent): void => {\n const newX = e.offsetX - this._dragOffset;\n const slider = this._currentSlider as SVGRectElement;\n if ((slider.id as SliderId) === 'slider-min') {\n this.minSelectedDate = this.translatePositionToDate(\n this.validMinSliderX(newX)\n );\n } else {\n this.maxSelectedDate = this.translatePositionToDate(\n this.validMaxSliderX(newX)\n );\n }\n };\n\n /**\n * Constrain a proposed value for the minimum (left) slider\n *\n * If the value is less than the leftmost valid position, then set it to the\n * left edge of the histogram (ie the slider width). If the value is greater\n * than the rightmost valid position (the position of the max slider), then\n * set it to the position of the max slider\n */\n private validMinSliderX(newX: number): number {\n // allow the left slider to go right only to the right slider, even if the\n // max selected date is out of range\n const rightLimit = Math.min(\n this.translateDateToPosition(this.maxSelectedDate),\n this.histogramRightEdgeX\n );\n newX = this.clamp(newX, this.histogramLeftEdgeX, rightLimit);\n const isInvalid =\n Number.isNaN(newX) || rightLimit < this.histogramLeftEdgeX;\n return isInvalid ? this.histogramLeftEdgeX : newX;\n }\n\n /**\n * Constrain a proposed value for the maximum (right) slider\n *\n * If the value is greater than the rightmost valid position, then set it to\n * the right edge of the histogram (ie histogram width - slider width). If the\n * value is less than the leftmost valid position (the position of the min\n * slider), then set it to the position of the min slider\n */\n private validMaxSliderX(newX: number): number {\n // allow the right slider to go left only to the left slider, even if the\n // min selected date is out of range\n const leftLimit = Math.max(\n this.histogramLeftEdgeX,\n this.translateDateToPosition(this.minSelectedDate)\n );\n newX = this.clamp(newX, leftLimit, this.histogramRightEdgeX);\n const isInvalid =\n Number.isNaN(newX) || leftLimit > this.histogramRightEdgeX;\n return isInvalid ? this.histogramRightEdgeX : newX;\n }\n\n private addListeners(): void {\n window.addEventListener('pointermove', this.move);\n window.addEventListener('pointerup', this.drop);\n window.addEventListener('pointercancel', this.drop);\n }\n\n private removeListeners(): void {\n window.removeEventListener('pointermove', this.move);\n window.removeEventListener('pointerup', this.drop);\n window.removeEventListener('pointercancel', this.drop);\n }\n\n /**\n * start a timer to emit an update event. this timer can be canceled (and the\n * event not emitted) if user drags a slider or focuses a date input within\n * the update delay\n */\n private beginEmitUpdateProcess(): void {\n this.cancelPendingUpdateEvent();\n this._emitUpdatedEventTimer = setTimeout(() => {\n if (this.currentDateRangeString === this._previousDateRange) {\n // don't emit duplicate event if no change since last emitted event\n return;\n }\n this._previousDateRange = this.currentDateRangeString;\n const options = {\n detail: {\n minDate: this.minSelectedDate,\n maxDate: this.maxSelectedDate,\n },\n bubbles: true,\n composed: true,\n };\n this.dispatchEvent(new CustomEvent('histogramDateRangeUpdated', options));\n }, this.updateDelay);\n }\n\n private cancelPendingUpdateEvent(): void {\n if (this._emitUpdatedEventTimer === undefined) {\n return;\n }\n clearTimeout(this._emitUpdatedEventTimer);\n this._emitUpdatedEventTimer = undefined;\n }\n\n /**\n * find position of pointer in relation to the current slider\n */\n private setDragOffset(e: PointerEvent): void {\n this._currentSlider = e.currentTarget as SVGRectElement;\n const sliderX =\n (this._currentSlider.id as SliderId) === 'slider-min'\n ? this.minSliderX\n : this.maxSliderX;\n this._dragOffset = e.offsetX - sliderX;\n // work around Firefox issue where e.offsetX seems to be not based on current\n // element but on background element\n if (\n this._dragOffset > this.sliderWidth ||\n this._dragOffset < -this.sliderWidth\n ) {\n this._dragOffset = 0;\n }\n }\n\n /**\n * @param x horizontal position of slider\n * @returns string representation of date\n */\n private translatePositionToDate(x: number): string {\n // use Math.ceil to round up to fix case where input like 1/1/2010 would get\n // translated to 12/31/2009\n const milliseconds = Math.ceil(\n ((x - this.sliderWidth) * this.dateRangeMS) / this._histWidth\n );\n return this.formatDate(this._minDateMS + milliseconds);\n }\n\n /**\n * Returns slider x-position corresponding to given date\n *\n * @param date\n * @returns x-position of slider\n */\n private translateDateToPosition(date: string): number {\n const milliseconds = this.getMSFromString(date);\n return (\n this.sliderWidth +\n ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS\n );\n }\n\n /** ensure that the returned value is between minValue and maxValue */\n private clamp(x: number, minValue: number, maxValue: number): number {\n return Math.min(Math.max(x, minValue), maxValue);\n }\n\n private handleMinDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n this.minSelectedDate = target.value;\n this.beginEmitUpdateProcess();\n }\n\n private handleMaxDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n this.maxSelectedDate = target.value;\n this.beginEmitUpdateProcess();\n }\n\n private handleKeyUp(e: KeyboardEvent): void {\n if (e.key === 'Enter') {\n const target = e.currentTarget as HTMLInputElement;\n target.blur();\n }\n }\n\n private get currentDateRangeString(): string {\n return `${this.minSelectedDate}:${this.maxSelectedDate}`;\n }\n\n private getMSFromString(date: string): number {\n const digitGroupCount = (date.split(/(\\d+)/).length - 1) / 2;\n if (digitGroupCount === 1) {\n // if there's just a single set of digits, assume it's a year\n const dateObj = new Date(0, 0); // start at January 1, 1900\n dateObj.setFullYear(Number(date)); // override year (=> 0099-01-01) = 99 CE\n return dateObj.getTime(); // get time in milliseconds\n }\n return dayjs(date, [this.dateFormat, DATE_FORMAT]).valueOf();\n }\n\n /**\n * expand or narrow the selected range by moving the slider nearest the\n * clicked bar to the outer edge of the clicked bar\n *\n * @param e Event click event from a histogram bar\n */\n private handleBarClick(e: Event): void {\n const dataset = (e.currentTarget as SVGRectElement).dataset as BarDataset;\n const clickPosition =\n (this.getMSFromString(dataset.binStart) +\n this.getMSFromString(dataset.binEnd)) /\n 2;\n const distanceFromMinSlider = Math.abs(\n clickPosition - this.getMSFromString(this.minSelectedDate)\n );\n const distanceFromMaxSlider = Math.abs(\n clickPosition - this.getMSFromString(this.maxSelectedDate)\n );\n // update the selected range by moving the nearer slider\n if (distanceFromMinSlider < distanceFromMaxSlider) {\n this.minSelectedDate = dataset.binStart;\n } else {\n this.maxSelectedDate = dataset.binEnd;\n }\n this.beginEmitUpdateProcess();\n }\n\n private get minSliderTemplate(): SVGTemplateResult {\n // width/height in pixels of curved part of the sliders (like\n // border-radius); used as part of a SVG quadratic curve. see\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands\n const cs = SLIDER_CORNER_SIZE;\n\n const sliderShape = `\n M${this.minSliderX},0\n h-${this.sliderWidth - cs}\n q-${cs},0 -${cs},${cs}\n v${this.height - cs * 2}\n q0,${cs} ${cs},${cs}\n h${this.sliderWidth - cs}\n `;\n return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);\n }\n\n private get maxSliderTemplate(): SVGTemplateResult {\n const cs = SLIDER_CORNER_SIZE;\n const sliderShape = `\n M${this.maxSliderX},0\n h${this.sliderWidth - cs}\n q${cs},0 ${cs},${cs}\n v${this.height - cs * 2}\n q0,${cs} -${cs},${cs}\n h-${this.sliderWidth - cs}\n `;\n return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);\n }\n\n private generateSliderSVG(\n sliderPositionX: number,\n id: SliderId,\n sliderShape: string\n ): SVGTemplateResult {\n // whether the curved part of the slider is facing towards the left (1), ie\n // minimum, or facing towards the right (-1), ie maximum\n const k = id === 'slider-min' ? 1 : -1;\n\n return svg`\n <svg\n id=\"${id}\"\n class=\"\n ${this.disabled ? '' : 'draggable'} \n ${this._isDragging ? 'dragging' : ''}\"\n @pointerdown=\"${this.drag}\"\n >\n <path d=\"${sliderShape} z\" fill=\"${sliderColor}\" />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n </svg>\n `;\n }\n\n get selectedRangeTemplate(): SVGTemplateResult {\n return svg`\n <rect\n x=\"${this.minSliderX}\"\n y=\"0\"\n width=\"${this.maxSliderX - this.minSliderX}\"\n height=\"${this.height}\"\n fill=\"${selectedRangeColor}\"\n />`;\n }\n\n get histogramTemplate(): SVGTemplateResult[] {\n const xScale = this._histWidth / this._numBins;\n const barWidth = xScale - 1;\n let x = this.sliderWidth; // start at the left edge of the histogram\n\n // the stroke-dasharray style below creates a transparent border around the\n // right edge of the bar, which prevents user from encountering a gap\n // between adjacent bars (eg when viewing the tooltips or when trying to\n // extend the range by clicking on a bar)\n return this._histData.map(data => {\n const bar = svg`\n <rect\n class=\"bar\"\n style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${\n data.height\n };'\n x=\"${x}\"\n y=\"${this.height - data.height}\"\n width=\"${barWidth}\"\n height=\"${data.height}\"\n @pointerenter=\"${this.showTooltip}\"\n @pointerleave=\"${this.hideTooltip}\"\n @click=\"${this.handleBarClick}\"\n fill=\"${\n x + barWidth >= this.minSliderX && x <= this.maxSliderX\n ? barIncludedFill\n : barExcludedFill\n }\"\n data-num-items=\"${data.value}\"\n data-bin-start=\"${data.binStart}\"\n data-bin-end=\"${data.binEnd}\"\n />`;\n x += xScale;\n return bar;\n });\n }\n\n private formatDate(dateMS: number): string {\n if (Number.isNaN(dateMS)) {\n return '';\n }\n const date = dayjs(dateMS);\n if (date.year() < 1000) {\n // years before 1000 don't play well with dayjs custom formatting, so fall\n // back to displaying only the year\n return String(date.year());\n }\n return date.format(this.dateFormat);\n }\n\n /**\n * NOTE: we are relying on the lit `live` directive in the template to\n * ensure that the change to minSelectedDate is noticed and the input value\n * gets properly re-rendered. see\n * https://lit.dev/docs/templates/directives/#live\n */\n get minInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-min\"\n placeholder=\"${this.dateFormat}\"\n type=\"text\"\n @focus=\"${this.cancelPendingUpdateEvent}\"\n @blur=\"${this.handleMinDateInput}\"\n @keyup=\"${this.handleKeyUp}\"\n .value=\"${live(this.minSelectedDate)}\"\n ?disabled=\"${this.disabled}\"\n />\n `;\n }\n\n get maxInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-max\"\n placeholder=\"${this.dateFormat}\"\n type=\"text\"\n @focus=\"${this.cancelPendingUpdateEvent}\"\n @blur=\"${this.handleMaxDateInput}\"\n @keyup=\"${this.handleKeyUp}\"\n .value=\"${live(this.maxSelectedDate)}\"\n ?disabled=\"${this.disabled}\"\n />\n `;\n }\n\n get tooltipTemplate(): TemplateResult {\n return html`\n <style>\n #tooltip {\n width: ${this.tooltipWidth}px;\n height: ${this.tooltipHeight}px;\n top: ${-9 - this.tooltipHeight}px;\n left: ${this._tooltipOffset}px;\n display: ${this._tooltipVisible ? 'block' : 'none'};\n }\n #tooltip:after {\n left: ${this.tooltipWidth / 2}px;\n }\n </style>\n <div id=\"tooltip\">${this._tooltipContent}</div>\n `;\n }\n\n private get noDataTemplate(): TemplateResult {\n return html`\n <div class=\"missing-data-message\">${this.missingDataMessage}</div>\n `;\n }\n\n private get activityIndicatorTemplate(): TemplateResult | typeof nothing {\n if (!this.loading) {\n return nothing;\n }\n return html`\n <ia-activity-indicator mode=\"processing\"> </ia-activity-indicator>\n `;\n }\n\n static styles = css`\n .missing-data-message {\n text-align: center;\n }\n #container {\n margin: 0;\n touch-action: none;\n position: relative;\n }\n .disabled {\n opacity: 0.3;\n }\n ia-activity-indicator {\n position: absolute;\n left: calc(50% - 10px);\n top: 10px;\n width: 20px;\n height: 20px;\n --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);\n --activityIndicatorLoadingRingColor: ${activityIndicatorColor};\n }\n\n /* prevent selection from interfering with tooltip, especially on mobile */\n /* https://stackoverflow.com/a/4407335/1163042 */\n .noselect {\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* current Chrome, Edge, Opera and Firefox */\n }\n .bar {\n /* create a transparent border around the hist bars to prevent \"gaps\" and\n flickering when moving around between bars. this also helps with handling\n clicks on the bars, preventing users from being able to click in between\n bars */\n stroke: rgba(0, 0, 0, 0);\n /* ensure transparent stroke wide enough to cover gap between bars */\n stroke-width: 2px;\n }\n .bar:hover {\n /* highlight currently hovered bar */\n fill-opacity: 0.7;\n }\n .disabled .bar:hover {\n /* ensure no visual hover interaction when disabled */\n fill-opacity: 1;\n }\n /****** histogram ********/\n #tooltip {\n position: absolute;\n background: ${tooltipBackgroundColor};\n color: ${tooltipTextColor};\n text-align: center;\n border-radius: 3px;\n padding: 2px;\n font-size: ${tooltipFontSize};\n font-family: ${tooltipFontFamily};\n touch-action: none;\n pointer-events: none;\n }\n #tooltip:after {\n content: '';\n position: absolute;\n margin-left: -5px;\n top: 100%;\n /* arrow */\n border: 5px solid ${tooltipTextColor};\n border-color: ${tooltipBackgroundColor} transparent transparent\n transparent;\n }\n /****** slider ********/\n .draggable:hover {\n cursor: grab;\n }\n .dragging {\n cursor: grabbing !important;\n }\n /****** inputs ********/\n #inputs {\n display: flex;\n justify-content: center;\n }\n #inputs .dash {\n position: relative;\n bottom: -1px;\n }\n input {\n width: ${inputWidth};\n margin: 0 3px;\n border: ${inputBorder};\n border-radius: 2px !important;\n text-align: center;\n font-size: ${inputFontSize};\n font-family: ${inputFontFamily};\n }\n `;\n\n render(): TemplateResult {\n if (!this.hasBinData) {\n return this.noDataTemplate;\n }\n return html`\n <div\n id=\"container\"\n class=\"\n noselect \n ${this._isDragging ? 'dragging' : ''}\n \"\n style=\"width: ${this.width}px\"\n >\n ${this.activityIndicatorTemplate} ${this.tooltipTemplate}\n <div\n class=\"inner-container\n ${this.disabled ? 'disabled' : ''}\"\n >\n <svg\n width=\"${this.width}\"\n height=\"${this.height}\"\n @pointerleave=\"${this.drop}\"\n >\n ${this.selectedRangeTemplate}\n <svg id=\"histogram\">${this.histogramTemplate}</svg>\n ${this.minSliderTemplate} ${this.maxSliderTemplate}\n </svg>\n <div id=\"inputs\">\n ${this.minInputTemplate}\n <div class=\"dash\">-</div>\n ${this.maxInputTemplate}\n </div>\n </div>\n </div>\n `;\n }\n}\n\n// help TypeScript provide strong typing when interacting with DOM APIs\n// https://stackoverflow.com/questions/65148695/lit-element-typescript-project-global-interface-declaration-necessary\ndeclare global {\n interface HTMLElementTagNameMap {\n 'histogram-date-range': HistogramDateRange;\n }\n}\n"]}