@internetarchive/histogram-date-range 1.2.2-alpha-webdev7377.0 → 1.2.2-alpha-webdev7377.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC","sourcesContent":["export { HistogramDateRange } from './src/histogram-date-range';\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC","sourcesContent":["export { HistogramDateRange } from './src/histogram-date-range';\n"]}
@@ -43,6 +43,10 @@ export declare class HistogramDateRange extends LitElement {
43
43
  * creating a tooltip.
44
44
  */
45
45
  private handleDataUpdate;
46
+ /**
47
+ * Rounds the given timestamp to the nearest start of a new month
48
+ */
49
+ private roundToMonth;
46
50
  private calculateHistData;
47
51
  private get hasBinData();
48
52
  private get _numBins();
@@ -146,22 +146,35 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
146
146
  ? this.maxSelectedDate
147
147
  : this.maxDate;
148
148
  }
149
+ /**
150
+ * Rounds the given timestamp to the nearest start of a new month
151
+ */
152
+ roundToMonth(timestamp) {
153
+ const date = new Date(timestamp);
154
+ const [y, m, d] = [date.getFullYear(), date.getMonth(), date.getDate()];
155
+ return d < 15
156
+ ? new Date(y, m, 1).getTime()
157
+ : new Date(y, m + 1, 1).getTime();
158
+ }
149
159
  calculateHistData() {
160
+ const { bins, height, dateRangeMS, _numBins, _minDateMS } = this;
150
161
  const minValue = Math.min(...this.bins);
151
162
  const maxValue = Math.max(...this.bins);
152
163
  // if there is no difference between the min and max values, use a range of
153
164
  // 1 because log scaling will fail if the range is 0
154
165
  const valueRange = minValue === maxValue ? 1 : Math.log1p(maxValue);
155
- const valueScale = this.height / valueRange;
156
- const dateScale = this.dateRangeMS / this._numBins;
157
- return this.bins.map((v, i) => {
166
+ const valueScale = height / valueRange;
167
+ const dateScale = dateRangeMS / _numBins;
168
+ return bins.map((v, i) => {
169
+ const binStartMS = this.roundToMonth(i * dateScale + _minDateMS);
170
+ const binEndMS = this.roundToMonth((i + 1) * dateScale + _minDateMS) - 1;
158
171
  return {
159
172
  value: v,
160
173
  // use log scaling for the height of the bar to prevent tall bars from
161
174
  // making the smaller ones too small to see
162
175
  height: Math.floor(Math.log1p(v) * valueScale),
163
- binStart: `${this.formatDate(i * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
164
- binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
176
+ binStart: this.formatDate(binStartMS, this.resolvedTooltipDateFormat),
177
+ binEnd: this.formatDate(binEndMS, this.resolvedTooltipDateFormat),
165
178
  };
166
179
  });
167
180
  }
@@ -262,9 +275,9 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
262
275
  const formattedNumItems = Number(dataset.numItems).toLocaleString();
263
276
  this._tooltipOffset =
264
277
  x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;
265
- this._tooltipContent = html `
266
- ${formattedNumItems} ${itemsText}<br />
267
- ${dataset.binStart} - ${dataset.binEnd}
278
+ this._tooltipContent = html `
279
+ ${formattedNumItems} ${itemsText}<br />
280
+ ${dataset.binStart} - ${dataset.binEnd}
268
281
  `;
269
282
  this._tooltipVisible = true;
270
283
  }
@@ -459,25 +472,25 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
459
472
  // border-radius); used as part of a SVG quadratic curve. see
460
473
  // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands
461
474
  const cs = SLIDER_CORNER_SIZE;
462
- const sliderShape = `
463
- M${this.minSliderX},0
464
- h-${this.sliderWidth - cs}
465
- q-${cs},0 -${cs},${cs}
466
- v${this.height - cs * 2}
467
- q0,${cs} ${cs},${cs}
468
- h${this.sliderWidth - cs}
475
+ const sliderShape = `
476
+ M${this.minSliderX},0
477
+ h-${this.sliderWidth - cs}
478
+ q-${cs},0 -${cs},${cs}
479
+ v${this.height - cs * 2}
480
+ q0,${cs} ${cs},${cs}
481
+ h${this.sliderWidth - cs}
469
482
  `;
470
483
  return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);
471
484
  }
472
485
  get maxSliderTemplate() {
473
486
  const cs = SLIDER_CORNER_SIZE;
474
- const sliderShape = `
475
- M${this.maxSliderX},0
476
- h${this.sliderWidth - cs}
477
- q${cs},0 ${cs},${cs}
478
- v${this.height - cs * 2}
479
- q0,${cs} -${cs},${cs}
480
- h-${this.sliderWidth - cs}
487
+ const sliderShape = `
488
+ M${this.maxSliderX},0
489
+ h${this.sliderWidth - cs}
490
+ q${cs},0 ${cs},${cs}
491
+ v${this.height - cs * 2}
492
+ q0,${cs} -${cs},${cs}
493
+ h-${this.sliderWidth - cs}
481
494
  `;
482
495
  return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);
483
496
  }
@@ -485,40 +498,40 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
485
498
  // whether the curved part of the slider is facing towards the left (1), ie
486
499
  // minimum, or facing towards the right (-1), ie maximum
487
500
  const k = id === 'slider-min' ? 1 : -1;
488
- return svg `
489
- <svg
490
- id="${id}"
491
- class="
492
- ${this.disabled ? '' : 'draggable'}
493
- ${this._isDragging ? 'dragging' : ''}"
494
- @pointerdown="${this.drag}"
495
- >
496
- <path d="${sliderShape} z" fill="${sliderColor}" />
497
- <rect
498
- x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k}"
499
- y="${this.height / 3}"
500
- width="1"
501
- height="${this.height / 3}"
502
- fill="white"
503
- />
504
- <rect
505
- x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k}"
506
- y="${this.height / 3}"
507
- width="1"
508
- height="${this.height / 3}"
509
- fill="white"
510
- />
511
- </svg>
501
+ return svg `
502
+ <svg
503
+ id="${id}"
504
+ class="
505
+ ${this.disabled ? '' : 'draggable'}
506
+ ${this._isDragging ? 'dragging' : ''}"
507
+ @pointerdown="${this.drag}"
508
+ >
509
+ <path d="${sliderShape} z" fill="${sliderColor}" />
510
+ <rect
511
+ x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k}"
512
+ y="${this.height / 3}"
513
+ width="1"
514
+ height="${this.height / 3}"
515
+ fill="white"
516
+ />
517
+ <rect
518
+ x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k}"
519
+ y="${this.height / 3}"
520
+ width="1"
521
+ height="${this.height / 3}"
522
+ fill="white"
523
+ />
524
+ </svg>
512
525
  `;
513
526
  }
514
527
  get selectedRangeTemplate() {
515
- return svg `
516
- <rect
517
- x="${this.minSliderX}"
518
- y="0"
519
- width="${this.maxSliderX - this.minSliderX}"
520
- height="${this.height}"
521
- fill="${selectedRangeColor}"
528
+ return svg `
529
+ <rect
530
+ x="${this.minSliderX}"
531
+ y="0"
532
+ width="${this.maxSliderX - this.minSliderX}"
533
+ height="${this.height}"
534
+ fill="${selectedRangeColor}"
522
535
  />`;
523
536
  }
524
537
  get histogramTemplate() {
@@ -530,23 +543,23 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
530
543
  // between adjacent bars (eg when viewing the tooltips or when trying to
531
544
  // extend the range by clicking on a bar)
532
545
  return this._histData.map(data => {
533
- const bar = svg `
534
- <rect
535
- class="bar"
536
- style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${data.height};'
537
- x="${x}"
538
- y="${this.height - data.height}"
539
- width="${barWidth}"
540
- height="${data.height}"
541
- @pointerenter="${this.showTooltip}"
542
- @pointerleave="${this.hideTooltip}"
543
- @click="${this.handleBarClick}"
546
+ const bar = svg `
547
+ <rect
548
+ class="bar"
549
+ style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${data.height};'
550
+ x="${x}"
551
+ y="${this.height - data.height}"
552
+ width="${barWidth}"
553
+ height="${data.height}"
554
+ @pointerenter="${this.showTooltip}"
555
+ @pointerleave="${this.hideTooltip}"
556
+ @click="${this.handleBarClick}"
544
557
  fill="${x + barWidth >= this.minSliderX && x <= this.maxSliderX
545
558
  ? barIncludedFill
546
- : barExcludedFill}"
547
- data-num-items="${data.value}"
548
- data-bin-start="${data.binStart}"
549
- data-bin-end="${data.binEnd}"
559
+ : barExcludedFill}"
560
+ data-num-items="${data.value}"
561
+ data-bin-start="${data.binStart}"
562
+ data-bin-end="${data.binEnd}"
550
563
  />`;
551
564
  x += xScale;
552
565
  return bar;
@@ -571,31 +584,31 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
571
584
  * https://lit.dev/docs/templates/directives/#live
572
585
  */
573
586
  get minInputTemplate() {
574
- return html `
575
- <input
576
- id="date-min"
577
- placeholder="${this.dateFormat}"
578
- type="text"
579
- @focus="${this.handleInputFocus}"
580
- @blur="${this.handleMinDateInput}"
581
- @keyup="${this.handleKeyUp}"
582
- .value="${live(this.minSelectedDate)}"
583
- ?disabled="${this.disabled}"
584
- />
587
+ return html `
588
+ <input
589
+ id="date-min"
590
+ placeholder="${this.dateFormat}"
591
+ type="text"
592
+ @focus="${this.handleInputFocus}"
593
+ @blur="${this.handleMinDateInput}"
594
+ @keyup="${this.handleKeyUp}"
595
+ .value="${live(this.minSelectedDate)}"
596
+ ?disabled="${this.disabled}"
597
+ />
585
598
  `;
586
599
  }
587
600
  get maxInputTemplate() {
588
- return html `
589
- <input
590
- id="date-max"
591
- placeholder="${this.dateFormat}"
592
- type="text"
593
- @focus="${this.handleInputFocus}"
594
- @blur="${this.handleMaxDateInput}"
595
- @keyup="${this.handleKeyUp}"
596
- .value="${live(this.maxSelectedDate)}"
597
- ?disabled="${this.disabled}"
598
- />
601
+ return html `
602
+ <input
603
+ id="date-max"
604
+ placeholder="${this.dateFormat}"
605
+ type="text"
606
+ @focus="${this.handleInputFocus}"
607
+ @blur="${this.handleMaxDateInput}"
608
+ @keyup="${this.handleKeyUp}"
609
+ .value="${live(this.maxSelectedDate)}"
610
+ ?disabled="${this.disabled}"
611
+ />
599
612
  `;
600
613
  }
601
614
  get minLabelTemplate() {
@@ -605,184 +618,184 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
605
618
  return html `<label for="date-max" class="sr-only">Maximum date:</label>`;
606
619
  }
607
620
  get tooltipTemplate() {
608
- return html `
609
- <style>
610
- #tooltip {
611
- width: ${this.tooltipWidth}px;
612
- height: ${this.tooltipHeight}px;
613
- top: ${-9 - this.tooltipHeight}px;
614
- left: ${this._tooltipOffset}px;
615
- display: ${this._tooltipVisible ? 'block' : 'none'};
616
- }
617
- #tooltip:after {
618
- left: ${this.tooltipWidth / 2}px;
619
- }
620
- </style>
621
- <div id="tooltip">${this._tooltipContent}</div>
621
+ return html `
622
+ <style>
623
+ #tooltip {
624
+ width: ${this.tooltipWidth}px;
625
+ height: ${this.tooltipHeight}px;
626
+ top: ${-9 - this.tooltipHeight}px;
627
+ left: ${this._tooltipOffset}px;
628
+ display: ${this._tooltipVisible ? 'block' : 'none'};
629
+ }
630
+ #tooltip:after {
631
+ left: ${this.tooltipWidth / 2}px;
632
+ }
633
+ </style>
634
+ <div id="tooltip">${this._tooltipContent}</div>
622
635
  `;
623
636
  }
624
637
  get noDataTemplate() {
625
- return html `
626
- <div class="missing-data-message">${this.missingDataMessage}</div>
638
+ return html `
639
+ <div class="missing-data-message">${this.missingDataMessage}</div>
627
640
  `;
628
641
  }
629
642
  get activityIndicatorTemplate() {
630
643
  if (!this.loading) {
631
644
  return nothing;
632
645
  }
633
- return html `
634
- <ia-activity-indicator mode="processing"> </ia-activity-indicator>
646
+ return html `
647
+ <ia-activity-indicator mode="processing"> </ia-activity-indicator>
635
648
  `;
636
649
  }
637
650
  render() {
638
651
  if (!this.hasBinData) {
639
652
  return this.noDataTemplate;
640
653
  }
641
- return html `
642
- <div
643
- id="container"
644
- class="
645
- noselect
646
- ${this._isDragging ? 'dragging' : ''}
647
- "
648
- style="width: ${this.width}px"
649
- >
650
- ${this.activityIndicatorTemplate} ${this.tooltipTemplate}
651
- <div
652
- class="inner-container
653
- ${this.disabled ? 'disabled' : ''}"
654
- >
655
- <svg
656
- width="${this.width}"
657
- height="${this.height}"
658
- @pointerleave="${this.drop}"
659
- >
660
- ${this.selectedRangeTemplate}
661
- <svg id="histogram">${this.histogramTemplate}</svg>
662
- ${this.minSliderTemplate} ${this.maxSliderTemplate}
663
- </svg>
664
- <div id="inputs">
665
- ${this.minLabelTemplate} ${this.minInputTemplate}
666
- <div class="dash">-</div>
667
- ${this.maxLabelTemplate} ${this.maxInputTemplate}
668
- <slot name="inputs-right-side"></slot>
669
- </div>
670
- </div>
671
- </div>
654
+ return html `
655
+ <div
656
+ id="container"
657
+ class="
658
+ noselect
659
+ ${this._isDragging ? 'dragging' : ''}
660
+ "
661
+ style="width: ${this.width}px"
662
+ >
663
+ ${this.activityIndicatorTemplate} ${this.tooltipTemplate}
664
+ <div
665
+ class="inner-container
666
+ ${this.disabled ? 'disabled' : ''}"
667
+ >
668
+ <svg
669
+ width="${this.width}"
670
+ height="${this.height}"
671
+ @pointerleave="${this.drop}"
672
+ >
673
+ ${this.selectedRangeTemplate}
674
+ <svg id="histogram">${this.histogramTemplate}</svg>
675
+ ${this.minSliderTemplate} ${this.maxSliderTemplate}
676
+ </svg>
677
+ <div id="inputs">
678
+ ${this.minLabelTemplate} ${this.minInputTemplate}
679
+ <div class="dash">-</div>
680
+ ${this.maxLabelTemplate} ${this.maxInputTemplate}
681
+ <slot name="inputs-right-side"></slot>
682
+ </div>
683
+ </div>
684
+ </div>
672
685
  `;
673
686
  }
674
687
  };
675
- HistogramDateRange.styles = css `
676
- .missing-data-message {
677
- text-align: center;
678
- }
679
- #container {
680
- margin: 0;
681
- touch-action: none;
682
- position: relative;
683
- }
684
- .disabled {
685
- opacity: 0.3;
686
- }
687
- ia-activity-indicator {
688
- position: absolute;
689
- left: calc(50% - 10px);
690
- top: 10px;
691
- width: 20px;
692
- height: 20px;
693
- --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);
694
- --activityIndicatorLoadingRingColor: ${activityIndicatorColor};
695
- }
696
-
697
- /* prevent selection from interfering with tooltip, especially on mobile */
698
- /* https://stackoverflow.com/a/4407335/1163042 */
699
- .noselect {
700
- -webkit-touch-callout: none; /* iOS Safari */
701
- -webkit-user-select: none; /* Safari */
702
- -moz-user-select: none; /* Old versions of Firefox */
703
- -ms-user-select: none; /* Internet Explorer/Edge */
704
- user-select: none; /* current Chrome, Edge, Opera and Firefox */
705
- }
706
- .bar {
707
- /* create a transparent border around the hist bars to prevent "gaps" and
708
- flickering when moving around between bars. this also helps with handling
709
- clicks on the bars, preventing users from being able to click in between
710
- bars */
711
- stroke: rgba(0, 0, 0, 0);
712
- /* ensure transparent stroke wide enough to cover gap between bars */
713
- stroke-width: 2px;
714
- }
715
- .bar:hover {
716
- /* highlight currently hovered bar */
717
- fill-opacity: 0.7;
718
- }
719
- .disabled .bar:hover {
720
- /* ensure no visual hover interaction when disabled */
721
- fill-opacity: 1;
722
- }
723
- /****** histogram ********/
724
- #tooltip {
725
- position: absolute;
726
- background: ${tooltipBackgroundColor};
727
- color: ${tooltipTextColor};
728
- text-align: center;
729
- border-radius: 3px;
730
- padding: 2px;
731
- font-size: ${tooltipFontSize};
732
- font-family: ${tooltipFontFamily};
733
- touch-action: none;
734
- pointer-events: none;
735
- }
736
- #tooltip:after {
737
- content: '';
738
- position: absolute;
739
- margin-left: -5px;
740
- top: 100%;
741
- /* arrow */
742
- border: 5px solid ${tooltipTextColor};
743
- border-color: ${tooltipBackgroundColor} transparent transparent
744
- transparent;
745
- }
746
- /****** slider ********/
747
- .draggable:hover {
748
- cursor: grab;
749
- }
750
- .dragging {
751
- cursor: grabbing !important;
752
- }
753
- /****** inputs ********/
754
- #inputs {
755
- display: flex;
756
- justify-content: center;
757
- margin: ${inputRowMargin};
758
- }
759
- #inputs .dash {
760
- position: relative;
761
- bottom: -1px;
762
- align-self: center; /* Otherwise the dash sticks to the top while the inputs grow */
763
- }
764
- input {
765
- width: ${inputWidth};
766
- margin: 0 3px;
767
- border: ${inputBorder};
768
- border-radius: 2px !important;
769
- text-align: center;
770
- font-size: ${inputFontSize};
771
- font-family: ${inputFontFamily};
772
- }
773
- .sr-only {
774
- position: absolute !important;
775
- width: 1px !important;
776
- height: 1px !important;
777
- margin: 0 !important;
778
- padding: 0 !important;
779
- border: 0 !important;
780
- overflow: hidden !important;
781
- white-space: nowrap !important;
782
- clip: rect(1px, 1px, 1px, 1px) !important;
783
- -webkit-clip-path: inset(50%) !important;
784
- clip-path: inset(50%) !important;
785
- }
688
+ HistogramDateRange.styles = css `
689
+ .missing-data-message {
690
+ text-align: center;
691
+ }
692
+ #container {
693
+ margin: 0;
694
+ touch-action: none;
695
+ position: relative;
696
+ }
697
+ .disabled {
698
+ opacity: 0.3;
699
+ }
700
+ ia-activity-indicator {
701
+ position: absolute;
702
+ left: calc(50% - 10px);
703
+ top: 10px;
704
+ width: 20px;
705
+ height: 20px;
706
+ --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);
707
+ --activityIndicatorLoadingRingColor: ${activityIndicatorColor};
708
+ }
709
+
710
+ /* prevent selection from interfering with tooltip, especially on mobile */
711
+ /* https://stackoverflow.com/a/4407335/1163042 */
712
+ .noselect {
713
+ -webkit-touch-callout: none; /* iOS Safari */
714
+ -webkit-user-select: none; /* Safari */
715
+ -moz-user-select: none; /* Old versions of Firefox */
716
+ -ms-user-select: none; /* Internet Explorer/Edge */
717
+ user-select: none; /* current Chrome, Edge, Opera and Firefox */
718
+ }
719
+ .bar {
720
+ /* create a transparent border around the hist bars to prevent "gaps" and
721
+ flickering when moving around between bars. this also helps with handling
722
+ clicks on the bars, preventing users from being able to click in between
723
+ bars */
724
+ stroke: rgba(0, 0, 0, 0);
725
+ /* ensure transparent stroke wide enough to cover gap between bars */
726
+ stroke-width: 2px;
727
+ }
728
+ .bar:hover {
729
+ /* highlight currently hovered bar */
730
+ fill-opacity: 0.7;
731
+ }
732
+ .disabled .bar:hover {
733
+ /* ensure no visual hover interaction when disabled */
734
+ fill-opacity: 1;
735
+ }
736
+ /****** histogram ********/
737
+ #tooltip {
738
+ position: absolute;
739
+ background: ${tooltipBackgroundColor};
740
+ color: ${tooltipTextColor};
741
+ text-align: center;
742
+ border-radius: 3px;
743
+ padding: 2px;
744
+ font-size: ${tooltipFontSize};
745
+ font-family: ${tooltipFontFamily};
746
+ touch-action: none;
747
+ pointer-events: none;
748
+ }
749
+ #tooltip:after {
750
+ content: '';
751
+ position: absolute;
752
+ margin-left: -5px;
753
+ top: 100%;
754
+ /* arrow */
755
+ border: 5px solid ${tooltipTextColor};
756
+ border-color: ${tooltipBackgroundColor} transparent transparent
757
+ transparent;
758
+ }
759
+ /****** slider ********/
760
+ .draggable:hover {
761
+ cursor: grab;
762
+ }
763
+ .dragging {
764
+ cursor: grabbing !important;
765
+ }
766
+ /****** inputs ********/
767
+ #inputs {
768
+ display: flex;
769
+ justify-content: center;
770
+ margin: ${inputRowMargin};
771
+ }
772
+ #inputs .dash {
773
+ position: relative;
774
+ bottom: -1px;
775
+ align-self: center; /* Otherwise the dash sticks to the top while the inputs grow */
776
+ }
777
+ input {
778
+ width: ${inputWidth};
779
+ margin: 0 3px;
780
+ border: ${inputBorder};
781
+ border-radius: 2px !important;
782
+ text-align: center;
783
+ font-size: ${inputFontSize};
784
+ font-family: ${inputFontFamily};
785
+ }
786
+ .sr-only {
787
+ position: absolute !important;
788
+ width: 1px !important;
789
+ height: 1px !important;
790
+ margin: 0 !important;
791
+ padding: 0 !important;
792
+ border: 0 !important;
793
+ overflow: hidden !important;
794
+ white-space: nowrap !important;
795
+ clip: rect(1px, 1px, 1px, 1px) !important;
796
+ -webkit-clip-path: inset(50%) !important;
797
+ clip-path: inset(50%) !important;
798
+ }
786
799
  `;
787
800
  __decorate([
788
801
  property({ type: Number })