@internetarchive/histogram-date-range 1.2.0 → 1.2.1-alpha-webdev7377.0
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.
|
@@ -8,6 +8,8 @@ export declare class HistogramDateRange extends LitElement {
|
|
|
8
8
|
tooltipHeight: number;
|
|
9
9
|
updateDelay: number;
|
|
10
10
|
dateFormat: string;
|
|
11
|
+
/** Optional; falls back to `dateFormat` if not provided */
|
|
12
|
+
tooltipDateFormat?: string;
|
|
11
13
|
missingDataMessage: string;
|
|
12
14
|
minDate: string;
|
|
13
15
|
maxDate: string;
|
|
@@ -32,7 +34,7 @@ export declare class HistogramDateRange extends LitElement {
|
|
|
32
34
|
private _emitUpdatedEventTimer?;
|
|
33
35
|
private _previousDateRange;
|
|
34
36
|
disconnectedCallback(): void;
|
|
35
|
-
|
|
37
|
+
willUpdate(changedProps: PropertyValues): void;
|
|
36
38
|
/**
|
|
37
39
|
* Set private properties that depend on the attribute bin data
|
|
38
40
|
*
|
|
@@ -46,6 +48,7 @@ export declare class HistogramDateRange extends LitElement {
|
|
|
46
48
|
private get _numBins();
|
|
47
49
|
private get histogramLeftEdgeX();
|
|
48
50
|
private get histogramRightEdgeX();
|
|
51
|
+
private get resolvedTooltipDateFormat();
|
|
49
52
|
/** component's loading (and disabled) state */
|
|
50
53
|
get loading(): boolean;
|
|
51
54
|
set loading(value: boolean);
|
|
@@ -117,7 +117,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
117
117
|
this.removeListeners();
|
|
118
118
|
super.disconnectedCallback();
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
willUpdate(changedProps) {
|
|
121
121
|
// check for changes that would affect bin data calculations
|
|
122
122
|
if (changedProps.has('bins') ||
|
|
123
123
|
changedProps.has('minDate') ||
|
|
@@ -152,7 +152,6 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
152
152
|
this.maxSelectedDate = this.maxSelectedDate
|
|
153
153
|
? this.maxSelectedDate
|
|
154
154
|
: this.maxDate;
|
|
155
|
-
this.requestUpdate();
|
|
156
155
|
}
|
|
157
156
|
calculateHistData() {
|
|
158
157
|
const minValue = Math.min(...this.bins);
|
|
@@ -168,8 +167,8 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
168
167
|
// use log scaling for the height of the bar to prevent tall bars from
|
|
169
168
|
// making the smaller ones too small to see
|
|
170
169
|
height: Math.floor(Math.log1p(v) * valueScale),
|
|
171
|
-
binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,
|
|
172
|
-
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,
|
|
170
|
+
binStart: `${this.formatDate(i * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
|
|
171
|
+
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
|
|
173
172
|
};
|
|
174
173
|
});
|
|
175
174
|
}
|
|
@@ -188,6 +187,12 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
188
187
|
get histogramRightEdgeX() {
|
|
189
188
|
return this.width - this.sliderWidth;
|
|
190
189
|
}
|
|
190
|
+
get resolvedTooltipDateFormat() {
|
|
191
|
+
var _a;
|
|
192
|
+
if (this.tooltipDateFormat)
|
|
193
|
+
return this.tooltipDateFormat;
|
|
194
|
+
return (_a = this.dateFormat) !== null && _a !== void 0 ? _a : DATE_FORMAT;
|
|
195
|
+
}
|
|
191
196
|
/** component's loading (and disabled) state */
|
|
192
197
|
get loading() {
|
|
193
198
|
return this._isLoading;
|
|
@@ -552,7 +557,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
552
557
|
return bar;
|
|
553
558
|
});
|
|
554
559
|
}
|
|
555
|
-
formatDate(dateMS) {
|
|
560
|
+
formatDate(dateMS, format = this.dateFormat) {
|
|
556
561
|
if (Number.isNaN(dateMS)) {
|
|
557
562
|
return '';
|
|
558
563
|
}
|
|
@@ -562,7 +567,7 @@ let HistogramDateRange = class HistogramDateRange extends LitElement {
|
|
|
562
567
|
// back to displaying only the year
|
|
563
568
|
return String(date.year());
|
|
564
569
|
}
|
|
565
|
-
return date.format(
|
|
570
|
+
return date.format(format);
|
|
566
571
|
}
|
|
567
572
|
/**
|
|
568
573
|
* NOTE: we are relying on the lit `live` directive in the template to
|
|
@@ -805,6 +810,9 @@ __decorate([
|
|
|
805
810
|
__decorate([
|
|
806
811
|
property({ type: String })
|
|
807
812
|
], HistogramDateRange.prototype, "dateFormat", void 0);
|
|
813
|
+
__decorate([
|
|
814
|
+
property({ type: String })
|
|
815
|
+
], HistogramDateRange.prototype, "tooltipDateFormat", void 0);
|
|
808
816
|
__decorate([
|
|
809
817
|
property({ type: String })
|
|
810
818
|
], HistogramDateRange.prototype, "missingDataMessage", void 0);
|
|
@@ -818,7 +826,7 @@ __decorate([
|
|
|
818
826
|
property({ type: Boolean })
|
|
819
827
|
], HistogramDateRange.prototype, "disabled", void 0);
|
|
820
828
|
__decorate([
|
|
821
|
-
property({ type:
|
|
829
|
+
property({ type: Array })
|
|
822
830
|
], HistogramDateRange.prototype, "bins", void 0);
|
|
823
831
|
__decorate([
|
|
824
832
|
property({ type: Boolean })
|
|
@@ -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 {\r\n css,\r\n html,\r\n nothing,\r\n LitElement,\r\n PropertyValues,\r\n svg,\r\n SVGTemplateResult,\r\n TemplateResult,\r\n} from 'lit';\r\nimport { property, state, customElement } from 'lit/decorators.js';\r\nimport { live } from 'lit/directives/live.js';\r\nimport '@internetarchive/ia-activity-indicator/ia-activity-indicator';\r\n\r\n/* eslint-disable-next-line */\r\n/* @ts-ignore Import module -- JS, so no types */\r\nimport dayjs from 'https://esm.archive.org/dayjs@1.11.10';\r\n/* eslint-disable-next-line */\r\n/* @ts-ignore Import module -- JS, so no types */\r\nimport customParseFormat from 'https://esm.archive.org/dayjs@1.9.4/esm/plugin/customParseFormat';\r\n// NOTE: using a specific *earlier* pegged commit for the plugin ^, because esm.archive.org has a\r\n// problem creating later versions where the `export` of an included `utils.js` gets mangled. Eg:\r\n// https://github.com/internetarchive/esbuild_es5/commit/ce19e8b841282c0e94d2b8e6830fd7744b2216c2#diff-4b2ed47327851d566740a30ce5f60271c059ae67eff2006bc07bb7c4fcee8b50L296\r\n\r\ndayjs.extend(customParseFormat);\r\n\r\n// these values can be overridden via the component's HTML (camelCased) attributes\r\nconst WIDTH = 180;\r\nconst HEIGHT = 40;\r\nconst SLIDER_WIDTH = 10;\r\nconst TOOLTIP_WIDTH = 125;\r\nconst TOOLTIP_HEIGHT = 30;\r\nconst DATE_FORMAT = 'YYYY';\r\nconst MISSING_DATA = 'no data';\r\nconst UPDATE_DEBOUNCE_DELAY_MS = 0;\r\n\r\n// this constant is not set up to be overridden\r\nconst SLIDER_CORNER_SIZE = 4;\r\n\r\n// these CSS custom props can be overridden from the HTML that is invoking this component\r\nconst sliderColor = css`var(--histogramDateRangeSliderColor, #4B65FE)`;\r\nconst selectedRangeColor = css`var(--histogramDateRangeSelectedRangeColor, #DBE0FF)`;\r\nconst barIncludedFill = css`var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;\r\nconst activityIndicatorColor = css`var(--histogramDateRangeActivityIndicator, #2C2C2C)`;\r\nconst barExcludedFill = css`var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;\r\nconst inputRowMargin = css`var(--histogramDateRangeInputRowMargin, 0)`;\r\nconst inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;\r\nconst inputWidth = css`var(--histogramDateRangeInputWidth, 35px)`;\r\nconst inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;\r\nconst inputFontFamily = css`var(--histogramDateRangeInputFontFamily, sans-serif)`;\r\nconst tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;\r\nconst tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;\r\nconst tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;\r\nconst tooltipFontFamily = css`var(--histogramDateRangeTooltipFontFamily, sans-serif)`;\r\n\r\ntype SliderId = 'slider-min' | 'slider-max';\r\n\r\ninterface HistogramItem {\r\n value: number;\r\n height: number;\r\n binStart: string;\r\n binEnd: string;\r\n}\r\n\r\ninterface BarDataset extends DOMStringMap {\r\n numItems: string;\r\n binStart: string;\r\n binEnd: string;\r\n}\r\n\r\n@customElement('histogram-date-range')\r\nexport class HistogramDateRange extends LitElement {\r\n /* eslint-disable lines-between-class-members */\r\n\r\n // public reactive properties that can be set via HTML attributes\r\n @property({ type: Number }) width = WIDTH;\r\n @property({ type: Number }) height = HEIGHT;\r\n @property({ type: Number }) sliderWidth = SLIDER_WIDTH;\r\n @property({ type: Number }) tooltipWidth = TOOLTIP_WIDTH;\r\n @property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;\r\n @property({ type: Number }) updateDelay = UPDATE_DEBOUNCE_DELAY_MS;\r\n @property({ type: String }) dateFormat = DATE_FORMAT;\r\n @property({ type: String }) missingDataMessage = MISSING_DATA;\r\n @property({ type: String }) minDate = '';\r\n @property({ type: String }) maxDate = '';\r\n @property({ type: Boolean }) disabled = false;\r\n @property({ type: Object }) bins: number[] = [];\r\n /** If true, update events will not be canceled by the date inputs receiving focus */\r\n @property({ type: Boolean }) updateWhileFocused = false;\r\n\r\n // internal reactive properties not exposed as attributes\r\n @state() private _tooltipOffset = 0;\r\n @state() private _tooltipContent?: TemplateResult;\r\n @state() private _tooltipVisible = false;\r\n @state() private _isDragging = false;\r\n @state() private _isLoading = false;\r\n\r\n // non-reactive properties (changes don't auto-trigger re-rendering)\r\n private _minSelectedDate = '';\r\n private _maxSelectedDate = '';\r\n private _minDateMS = 0;\r\n private _maxDateMS = 0;\r\n private _dragOffset = 0;\r\n private _histWidth = 0;\r\n private _binWidth = 0;\r\n private _currentSlider?: SVGRectElement;\r\n private _histData: HistogramItem[] = [];\r\n private _emitUpdatedEventTimer?: ReturnType<typeof setTimeout>;\r\n private _previousDateRange = '';\r\n\r\n /* eslint-enable lines-between-class-members */\r\n\r\n disconnectedCallback(): void {\r\n this.removeListeners();\r\n super.disconnectedCallback();\r\n }\r\n\r\n updated(changedProps: PropertyValues): void {\r\n // check for changes that would affect bin data calculations\r\n if (\r\n changedProps.has('bins') ||\r\n changedProps.has('minDate') ||\r\n changedProps.has('maxDate') ||\r\n changedProps.has('minSelectedDate') ||\r\n changedProps.has('maxSelectedDate') ||\r\n changedProps.has('width') ||\r\n changedProps.has('height')\r\n ) {\r\n this.handleDataUpdate();\r\n }\r\n }\r\n\r\n /**\r\n * Set private properties that depend on the attribute bin data\r\n *\r\n * We're caching these values and not using getters to avoid recalculating all\r\n * of the hist data every time the user drags a slider or hovers over a bar\r\n * creating a tooltip.\r\n */\r\n private handleDataUpdate(): void {\r\n if (!this.hasBinData) {\r\n return;\r\n }\r\n this._histWidth = this.width - this.sliderWidth * 2;\r\n this._minDateMS = this.getMSFromString(this.minDate);\r\n this._maxDateMS = this.getMSFromString(this.maxDate);\r\n this._binWidth = this._histWidth / this._numBins;\r\n this._previousDateRange = this.currentDateRangeString;\r\n this._histData = this.calculateHistData();\r\n this.minSelectedDate = this.minSelectedDate\r\n ? this.minSelectedDate\r\n : this.minDate;\r\n this.maxSelectedDate = this.maxSelectedDate\r\n ? this.maxSelectedDate\r\n : this.maxDate;\r\n this.requestUpdate();\r\n }\r\n\r\n private calculateHistData(): HistogramItem[] {\r\n const minValue = Math.min(...this.bins);\r\n const maxValue = Math.max(...this.bins);\r\n // if there is no difference between the min and max values, use a range of\r\n // 1 because log scaling will fail if the range is 0\r\n const valueRange = minValue === maxValue ? 1 : Math.log1p(maxValue);\r\n const valueScale = this.height / valueRange;\r\n const dateScale = this.dateRangeMS / this._numBins;\r\n return this.bins.map((v: number, i: number) => {\r\n return {\r\n value: v,\r\n // use log scaling for the height of the bar to prevent tall bars from\r\n // making the smaller ones too small to see\r\n height: Math.floor(Math.log1p(v) * valueScale),\r\n binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,\r\n binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,\r\n };\r\n });\r\n }\r\n\r\n private get hasBinData(): boolean {\r\n return this._numBins > 0;\r\n }\r\n\r\n private get _numBins(): number {\r\n if (!this.bins || !this.bins.length) {\r\n return 0;\r\n }\r\n return this.bins.length;\r\n }\r\n\r\n private get histogramLeftEdgeX(): number {\r\n return this.sliderWidth;\r\n }\r\n\r\n private get histogramRightEdgeX(): number {\r\n return this.width - this.sliderWidth;\r\n }\r\n\r\n /** component's loading (and disabled) state */\r\n @property({ type: Boolean }) get loading(): boolean {\r\n return this._isLoading;\r\n }\r\n\r\n set loading(value: boolean) {\r\n this.disabled = value;\r\n this._isLoading = value;\r\n }\r\n\r\n /** formatted minimum date of selected date range */\r\n @property() get minSelectedDate(): string {\r\n return this.formatDate(this.getMSFromString(this._minSelectedDate));\r\n }\r\n\r\n /** updates minSelectedDate if new date is valid */\r\n set minSelectedDate(rawDate: string) {\r\n if (!this._minSelectedDate) {\r\n // because the values needed to calculate valid max/min values are not\r\n // available during the lit init when it's populating properties from\r\n // attributes, fall back to just the raw date if nothing is already set\r\n this._minSelectedDate = rawDate;\r\n return;\r\n }\r\n const proposedDateMS = this.getMSFromString(rawDate);\r\n const isValidDate = !Number.isNaN(proposedDateMS);\r\n const isNotTooRecent =\r\n proposedDateMS <= this.getMSFromString(this.maxSelectedDate);\r\n if (isValidDate && isNotTooRecent) {\r\n this._minSelectedDate = this.formatDate(proposedDateMS);\r\n }\r\n this.requestUpdate();\r\n }\r\n\r\n /** formatted maximum date of selected date range */\r\n @property() get maxSelectedDate(): string {\r\n return this.formatDate(this.getMSFromString(this._maxSelectedDate));\r\n }\r\n\r\n /** updates maxSelectedDate if new date is valid */\r\n set maxSelectedDate(rawDate: string) {\r\n if (!this._maxSelectedDate) {\r\n // because the values needed to calculate valid max/min values are not\r\n // available during the lit init when it's populating properties from\r\n // attributes, fall back to just the raw date if nothing is already set\r\n this._maxSelectedDate = rawDate;\r\n return;\r\n }\r\n const proposedDateMS = this.getMSFromString(rawDate);\r\n const isValidDate = !Number.isNaN(proposedDateMS);\r\n const isNotTooOld =\r\n proposedDateMS >= this.getMSFromString(this.minSelectedDate);\r\n if (isValidDate && isNotTooOld) {\r\n this._maxSelectedDate = this.formatDate(proposedDateMS);\r\n }\r\n this.requestUpdate();\r\n }\r\n\r\n /** horizontal position of min date slider */\r\n get minSliderX(): number {\r\n const x = this.translateDateToPosition(this.minSelectedDate);\r\n return this.validMinSliderX(x);\r\n }\r\n\r\n /** horizontal position of max date slider */\r\n get maxSliderX(): number {\r\n const x = this.translateDateToPosition(this.maxSelectedDate);\r\n return this.validMaxSliderX(x);\r\n }\r\n\r\n private get dateRangeMS(): number {\r\n return this._maxDateMS - this._minDateMS;\r\n }\r\n\r\n private showTooltip(e: PointerEvent): void {\r\n if (this._isDragging || this.disabled) {\r\n return;\r\n }\r\n const target = e.currentTarget as SVGRectElement;\r\n const x = target.x.baseVal.value + this.sliderWidth / 2;\r\n const dataset = target.dataset as BarDataset;\r\n const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;\r\n const formattedNumItems = Number(dataset.numItems).toLocaleString();\r\n\r\n this._tooltipOffset =\r\n x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;\r\n\r\n this._tooltipContent = html`\r\n ${formattedNumItems} ${itemsText}<br />\r\n ${dataset.binStart} - ${dataset.binEnd}\r\n `;\r\n this._tooltipVisible = true;\r\n }\r\n\r\n private hideTooltip(): void {\r\n this._tooltipContent = undefined;\r\n this._tooltipVisible = false;\r\n }\r\n\r\n // use arrow functions (rather than standard JS class instance methods) so\r\n // that `this` is bound to the histogramDateRange object and not the event\r\n // target. for more info see\r\n // https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners\r\n private drag = (e: PointerEvent): void => {\r\n // prevent selecting text or other ranges while dragging, especially in Safari\r\n e.preventDefault();\r\n if (this.disabled) {\r\n return;\r\n }\r\n this.setDragOffset(e);\r\n this._isDragging = true;\r\n this.addListeners();\r\n this.cancelPendingUpdateEvent();\r\n };\r\n\r\n private drop = (): void => {\r\n if (this._isDragging) {\r\n this.removeListeners();\r\n this.beginEmitUpdateProcess();\r\n }\r\n this._isDragging = false;\r\n };\r\n\r\n /**\r\n * Adjust the date range based on slider movement\r\n *\r\n * @param e PointerEvent from the slider being moved\r\n */\r\n private move = (e: PointerEvent): void => {\r\n const histogramClientX = this.getBoundingClientRect().x;\r\n const newX = e.clientX - histogramClientX - this._dragOffset;\r\n const slider = this._currentSlider as SVGRectElement;\r\n if ((slider.id as SliderId) === 'slider-min') {\r\n this.minSelectedDate = this.translatePositionToDate(\r\n this.validMinSliderX(newX)\r\n );\r\n } else {\r\n this.maxSelectedDate = this.translatePositionToDate(\r\n this.validMaxSliderX(newX)\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Constrain a proposed value for the minimum (left) slider\r\n *\r\n * If the value is less than the leftmost valid position, then set it to the\r\n * left edge of the histogram (ie the slider width). If the value is greater\r\n * than the rightmost valid position (the position of the max slider), then\r\n * set it to the position of the max slider\r\n */\r\n private validMinSliderX(newX: number): number {\r\n // allow the left slider to go right only to the right slider, even if the\r\n // max selected date is out of range\r\n const rightLimit = Math.min(\r\n this.translateDateToPosition(this.maxSelectedDate),\r\n this.histogramRightEdgeX\r\n );\r\n newX = this.clamp(newX, this.histogramLeftEdgeX, rightLimit);\r\n const isInvalid =\r\n Number.isNaN(newX) || rightLimit < this.histogramLeftEdgeX;\r\n return isInvalid ? this.histogramLeftEdgeX : newX;\r\n }\r\n\r\n /**\r\n * Constrain a proposed value for the maximum (right) slider\r\n *\r\n * If the value is greater than the rightmost valid position, then set it to\r\n * the right edge of the histogram (ie histogram width - slider width). If the\r\n * value is less than the leftmost valid position (the position of the min\r\n * slider), then set it to the position of the min slider\r\n */\r\n private validMaxSliderX(newX: number): number {\r\n // allow the right slider to go left only to the left slider, even if the\r\n // min selected date is out of range\r\n const leftLimit = Math.max(\r\n this.histogramLeftEdgeX,\r\n this.translateDateToPosition(this.minSelectedDate)\r\n );\r\n newX = this.clamp(newX, leftLimit, this.histogramRightEdgeX);\r\n const isInvalid =\r\n Number.isNaN(newX) || leftLimit > this.histogramRightEdgeX;\r\n return isInvalid ? this.histogramRightEdgeX : newX;\r\n }\r\n\r\n private addListeners(): void {\r\n window.addEventListener('pointermove', this.move);\r\n window.addEventListener('pointerup', this.drop);\r\n window.addEventListener('pointercancel', this.drop);\r\n }\r\n\r\n private removeListeners(): void {\r\n window.removeEventListener('pointermove', this.move);\r\n window.removeEventListener('pointerup', this.drop);\r\n window.removeEventListener('pointercancel', this.drop);\r\n }\r\n\r\n /**\r\n * start a timer to emit an update event. this timer can be canceled (and the\r\n * event not emitted) if user drags a slider or focuses a date input within\r\n * the update delay\r\n */\r\n private beginEmitUpdateProcess(): void {\r\n this.cancelPendingUpdateEvent();\r\n this._emitUpdatedEventTimer = setTimeout(() => {\r\n if (this.currentDateRangeString === this._previousDateRange) {\r\n // don't emit duplicate event if no change since last emitted event\r\n return;\r\n }\r\n this._previousDateRange = this.currentDateRangeString;\r\n const options = {\r\n detail: {\r\n minDate: this.minSelectedDate,\r\n maxDate: this.maxSelectedDate,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n };\r\n this.dispatchEvent(new CustomEvent('histogramDateRangeUpdated', options));\r\n }, this.updateDelay);\r\n }\r\n\r\n private cancelPendingUpdateEvent(): void {\r\n if (this._emitUpdatedEventTimer === undefined) {\r\n return;\r\n }\r\n clearTimeout(this._emitUpdatedEventTimer);\r\n this._emitUpdatedEventTimer = undefined;\r\n }\r\n\r\n /**\r\n * find position of pointer in relation to the current slider\r\n */\r\n private setDragOffset(e: PointerEvent): void {\r\n this._currentSlider = e.currentTarget as SVGRectElement;\r\n const sliderX =\r\n (this._currentSlider.id as SliderId) === 'slider-min'\r\n ? this.minSliderX\r\n : this.maxSliderX;\r\n const histogramClientX = this.getBoundingClientRect().x;\r\n this._dragOffset = e.clientX - histogramClientX - sliderX;\r\n }\r\n\r\n /**\r\n * @param x horizontal position of slider\r\n * @returns string representation of date\r\n */\r\n private translatePositionToDate(x: number): string {\r\n // use Math.ceil to round up to fix case where input like 1/1/2010 would get\r\n // translated to 12/31/2009\r\n const milliseconds = Math.ceil(\r\n ((x - this.sliderWidth) * this.dateRangeMS) / this._histWidth\r\n );\r\n return this.formatDate(this._minDateMS + milliseconds);\r\n }\r\n\r\n /**\r\n * Returns slider x-position corresponding to given date\r\n *\r\n * @param date\r\n * @returns x-position of slider\r\n */\r\n private translateDateToPosition(date: string): number {\r\n const milliseconds = this.getMSFromString(date);\r\n return (\r\n this.sliderWidth +\r\n ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS\r\n );\r\n }\r\n\r\n /** ensure that the returned value is between minValue and maxValue */\r\n private clamp(x: number, minValue: number, maxValue: number): number {\r\n return Math.min(Math.max(x, minValue), maxValue);\r\n }\r\n\r\n private handleInputFocus(): void {\r\n if (!this.updateWhileFocused) {\r\n this.cancelPendingUpdateEvent();\r\n }\r\n }\r\n\r\n private handleMinDateInput(e: Event): void {\r\n const target = e.currentTarget as HTMLInputElement;\r\n if (target.value !== this.minSelectedDate) {\r\n this.minSelectedDate = target.value;\r\n this.beginEmitUpdateProcess();\r\n }\r\n }\r\n\r\n private handleMaxDateInput(e: Event): void {\r\n const target = e.currentTarget as HTMLInputElement;\r\n if (target.value !== this.maxSelectedDate) {\r\n this.maxSelectedDate = target.value;\r\n this.beginEmitUpdateProcess();\r\n }\r\n }\r\n\r\n private handleKeyUp(e: KeyboardEvent): void {\r\n if (e.key === 'Enter') {\r\n const target = e.currentTarget as HTMLInputElement;\r\n target.blur();\r\n if (target.id === 'date-min') {\r\n this.handleMinDateInput(e);\r\n } else if (target.id === 'date-max') {\r\n this.handleMaxDateInput(e);\r\n }\r\n }\r\n }\r\n\r\n private get currentDateRangeString(): string {\r\n return `${this.minSelectedDate}:${this.maxSelectedDate}`;\r\n }\r\n\r\n private getMSFromString(date: unknown): number {\r\n // It's possible that `date` is not a string in certain situations.\r\n // For instance if you use LitElement bindings and the date is `2000`,\r\n // it will be treated as a number instead of a string. This just makes sure\r\n // we're dealing with a string.\r\n const stringified = typeof date === 'string' ? date : String(date);\r\n const digitGroupCount = (stringified.split(/(\\d+)/).length - 1) / 2;\r\n if (digitGroupCount === 1) {\r\n // if there's just a single set of digits, assume it's a year\r\n const dateObj = new Date(0, 0); // start at January 1, 1900\r\n dateObj.setFullYear(Number(stringified)); // override year\r\n return dateObj.getTime(); // get time in milliseconds\r\n }\r\n return dayjs(stringified, [this.dateFormat, DATE_FORMAT]).valueOf();\r\n }\r\n\r\n /**\r\n * expand or narrow the selected range by moving the slider nearest the\r\n * clicked bar to the outer edge of the clicked bar\r\n *\r\n * @param e Event click event from a histogram bar\r\n */\r\n private handleBarClick(e: Event): void {\r\n const dataset = (e.currentTarget as SVGRectElement).dataset as BarDataset;\r\n // use the midpoint of the width of the clicked bar to determine which is\r\n // the nearest slider\r\n const clickPosition =\r\n (this.getMSFromString(dataset.binStart) +\r\n this.getMSFromString(dataset.binEnd)) /\r\n 2;\r\n const distanceFromMinSlider = Math.abs(\r\n clickPosition - this.getMSFromString(this.minSelectedDate)\r\n );\r\n const distanceFromMaxSlider = Math.abs(\r\n clickPosition - this.getMSFromString(this.maxSelectedDate)\r\n );\r\n // update the selected range by moving the nearer slider\r\n if (distanceFromMinSlider < distanceFromMaxSlider) {\r\n this.minSelectedDate = dataset.binStart;\r\n } else {\r\n this.maxSelectedDate = dataset.binEnd;\r\n }\r\n this.beginEmitUpdateProcess();\r\n }\r\n\r\n private get minSliderTemplate(): SVGTemplateResult {\r\n // width/height in pixels of curved part of the sliders (like\r\n // border-radius); used as part of a SVG quadratic curve. see\r\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands\r\n const cs = SLIDER_CORNER_SIZE;\r\n\r\n const sliderShape = `\r\n M${this.minSliderX},0\r\n h-${this.sliderWidth - cs}\r\n q-${cs},0 -${cs},${cs}\r\n v${this.height - cs * 2}\r\n q0,${cs} ${cs},${cs}\r\n h${this.sliderWidth - cs}\r\n `;\r\n return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);\r\n }\r\n\r\n private get maxSliderTemplate(): SVGTemplateResult {\r\n const cs = SLIDER_CORNER_SIZE;\r\n const sliderShape = `\r\n M${this.maxSliderX},0\r\n h${this.sliderWidth - cs}\r\n q${cs},0 ${cs},${cs}\r\n v${this.height - cs * 2}\r\n q0,${cs} -${cs},${cs}\r\n h-${this.sliderWidth - cs}\r\n `;\r\n return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);\r\n }\r\n\r\n private generateSliderSVG(\r\n sliderPositionX: number,\r\n id: SliderId,\r\n sliderShape: string\r\n ): SVGTemplateResult {\r\n // whether the curved part of the slider is facing towards the left (1), ie\r\n // minimum, or facing towards the right (-1), ie maximum\r\n const k = id === 'slider-min' ? 1 : -1;\r\n\r\n return svg`\r\n <svg\r\n id=\"${id}\"\r\n class=\"\r\n ${this.disabled ? '' : 'draggable'}\r\n ${this._isDragging ? 'dragging' : ''}\"\r\n @pointerdown=\"${this.drag}\"\r\n >\r\n <path d=\"${sliderShape} z\" fill=\"${sliderColor}\" />\r\n <rect\r\n x=\"${\r\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k\r\n }\"\r\n y=\"${this.height / 3}\"\r\n width=\"1\"\r\n height=\"${this.height / 3}\"\r\n fill=\"white\"\r\n />\r\n <rect\r\n x=\"${\r\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k\r\n }\"\r\n y=\"${this.height / 3}\"\r\n width=\"1\"\r\n height=\"${this.height / 3}\"\r\n fill=\"white\"\r\n />\r\n </svg>\r\n `;\r\n }\r\n\r\n get selectedRangeTemplate(): SVGTemplateResult {\r\n return svg`\r\n <rect\r\n x=\"${this.minSliderX}\"\r\n y=\"0\"\r\n width=\"${this.maxSliderX - this.minSliderX}\"\r\n height=\"${this.height}\"\r\n fill=\"${selectedRangeColor}\"\r\n />`;\r\n }\r\n\r\n get histogramTemplate(): SVGTemplateResult[] {\r\n const xScale = this._histWidth / this._numBins;\r\n const barWidth = xScale - 1;\r\n let x = this.sliderWidth; // start at the left edge of the histogram\r\n\r\n // the stroke-dasharray style below creates a transparent border around the\r\n // right edge of the bar, which prevents user from encountering a gap\r\n // between adjacent bars (eg when viewing the tooltips or when trying to\r\n // extend the range by clicking on a bar)\r\n return this._histData.map(data => {\r\n const bar = svg`\r\n <rect\r\n class=\"bar\"\r\n style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${\r\n data.height\r\n };'\r\n x=\"${x}\"\r\n y=\"${this.height - data.height}\"\r\n width=\"${barWidth}\"\r\n height=\"${data.height}\"\r\n @pointerenter=\"${this.showTooltip}\"\r\n @pointerleave=\"${this.hideTooltip}\"\r\n @click=\"${this.handleBarClick}\"\r\n fill=\"${\r\n x + barWidth >= this.minSliderX && x <= this.maxSliderX\r\n ? barIncludedFill\r\n : barExcludedFill\r\n }\"\r\n data-num-items=\"${data.value}\"\r\n data-bin-start=\"${data.binStart}\"\r\n data-bin-end=\"${data.binEnd}\"\r\n />`;\r\n x += xScale;\r\n return bar;\r\n });\r\n }\r\n\r\n private formatDate(dateMS: number): string {\r\n if (Number.isNaN(dateMS)) {\r\n return '';\r\n }\r\n const date = dayjs(dateMS);\r\n if (date.year() < 1000) {\r\n // years before 1000 don't play well with dayjs custom formatting, so fall\r\n // back to displaying only the year\r\n return String(date.year());\r\n }\r\n return date.format(this.dateFormat);\r\n }\r\n\r\n /**\r\n * NOTE: we are relying on the lit `live` directive in the template to\r\n * ensure that the change to minSelectedDate is noticed and the input value\r\n * gets properly re-rendered. see\r\n * https://lit.dev/docs/templates/directives/#live\r\n */\r\n get minInputTemplate(): TemplateResult {\r\n return html`\r\n <input\r\n id=\"date-min\"\r\n placeholder=\"${this.dateFormat}\"\r\n type=\"text\"\r\n @focus=\"${this.handleInputFocus}\"\r\n @blur=\"${this.handleMinDateInput}\"\r\n @keyup=\"${this.handleKeyUp}\"\r\n .value=\"${live(this.minSelectedDate)}\"\r\n ?disabled=\"${this.disabled}\"\r\n />\r\n `;\r\n }\r\n\r\n get maxInputTemplate(): TemplateResult {\r\n return html`\r\n <input\r\n id=\"date-max\"\r\n placeholder=\"${this.dateFormat}\"\r\n type=\"text\"\r\n @focus=\"${this.handleInputFocus}\"\r\n @blur=\"${this.handleMaxDateInput}\"\r\n @keyup=\"${this.handleKeyUp}\"\r\n .value=\"${live(this.maxSelectedDate)}\"\r\n ?disabled=\"${this.disabled}\"\r\n />\r\n `;\r\n }\r\n\r\n get minLabelTemplate(): TemplateResult {\r\n return html`<label for=\"date-min\" class=\"sr-only\">Minimum date:</label>`;\r\n }\r\n\r\n get maxLabelTemplate(): TemplateResult {\r\n return html`<label for=\"date-max\" class=\"sr-only\">Maximum date:</label>`;\r\n }\r\n\r\n get tooltipTemplate(): TemplateResult {\r\n return html`\r\n <style>\r\n #tooltip {\r\n width: ${this.tooltipWidth}px;\r\n height: ${this.tooltipHeight}px;\r\n top: ${-9 - this.tooltipHeight}px;\r\n left: ${this._tooltipOffset}px;\r\n display: ${this._tooltipVisible ? 'block' : 'none'};\r\n }\r\n #tooltip:after {\r\n left: ${this.tooltipWidth / 2}px;\r\n }\r\n </style>\r\n <div id=\"tooltip\">${this._tooltipContent}</div>\r\n `;\r\n }\r\n\r\n private get noDataTemplate(): TemplateResult {\r\n return html`\r\n <div class=\"missing-data-message\">${this.missingDataMessage}</div>\r\n `;\r\n }\r\n\r\n private get activityIndicatorTemplate(): TemplateResult | typeof nothing {\r\n if (!this.loading) {\r\n return nothing;\r\n }\r\n return html`\r\n <ia-activity-indicator mode=\"processing\"> </ia-activity-indicator>\r\n `;\r\n }\r\n\r\n static styles = css`\r\n .missing-data-message {\r\n text-align: center;\r\n }\r\n #container {\r\n margin: 0;\r\n touch-action: none;\r\n position: relative;\r\n }\r\n .disabled {\r\n opacity: 0.3;\r\n }\r\n ia-activity-indicator {\r\n position: absolute;\r\n left: calc(50% - 10px);\r\n top: 10px;\r\n width: 20px;\r\n height: 20px;\r\n --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);\r\n --activityIndicatorLoadingRingColor: ${activityIndicatorColor};\r\n }\r\n\r\n /* prevent selection from interfering with tooltip, especially on mobile */\r\n /* https://stackoverflow.com/a/4407335/1163042 */\r\n .noselect {\r\n -webkit-touch-callout: none; /* iOS Safari */\r\n -webkit-user-select: none; /* Safari */\r\n -moz-user-select: none; /* Old versions of Firefox */\r\n -ms-user-select: none; /* Internet Explorer/Edge */\r\n user-select: none; /* current Chrome, Edge, Opera and Firefox */\r\n }\r\n .bar {\r\n /* create a transparent border around the hist bars to prevent \"gaps\" and\r\n flickering when moving around between bars. this also helps with handling\r\n clicks on the bars, preventing users from being able to click in between\r\n bars */\r\n stroke: rgba(0, 0, 0, 0);\r\n /* ensure transparent stroke wide enough to cover gap between bars */\r\n stroke-width: 2px;\r\n }\r\n .bar:hover {\r\n /* highlight currently hovered bar */\r\n fill-opacity: 0.7;\r\n }\r\n .disabled .bar:hover {\r\n /* ensure no visual hover interaction when disabled */\r\n fill-opacity: 1;\r\n }\r\n /****** histogram ********/\r\n #tooltip {\r\n position: absolute;\r\n background: ${tooltipBackgroundColor};\r\n color: ${tooltipTextColor};\r\n text-align: center;\r\n border-radius: 3px;\r\n padding: 2px;\r\n font-size: ${tooltipFontSize};\r\n font-family: ${tooltipFontFamily};\r\n touch-action: none;\r\n pointer-events: none;\r\n }\r\n #tooltip:after {\r\n content: '';\r\n position: absolute;\r\n margin-left: -5px;\r\n top: 100%;\r\n /* arrow */\r\n border: 5px solid ${tooltipTextColor};\r\n border-color: ${tooltipBackgroundColor} transparent transparent\r\n transparent;\r\n }\r\n /****** slider ********/\r\n .draggable:hover {\r\n cursor: grab;\r\n }\r\n .dragging {\r\n cursor: grabbing !important;\r\n }\r\n /****** inputs ********/\r\n #inputs {\r\n display: flex;\r\n justify-content: center;\r\n margin: ${inputRowMargin};\r\n }\r\n #inputs .dash {\r\n position: relative;\r\n bottom: -1px;\r\n align-self: center; /* Otherwise the dash sticks to the top while the inputs grow */\r\n }\r\n input {\r\n width: ${inputWidth};\r\n margin: 0 3px;\r\n border: ${inputBorder};\r\n border-radius: 2px !important;\r\n text-align: center;\r\n font-size: ${inputFontSize};\r\n font-family: ${inputFontFamily};\r\n }\r\n .sr-only {\r\n position: absolute !important;\r\n width: 1px !important;\r\n height: 1px !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n overflow: hidden !important;\r\n white-space: nowrap !important;\r\n clip: rect(1px, 1px, 1px, 1px) !important;\r\n -webkit-clip-path: inset(50%) !important;\r\n clip-path: inset(50%) !important;\r\n }\r\n `;\r\n\r\n render(): TemplateResult {\r\n if (!this.hasBinData) {\r\n return this.noDataTemplate;\r\n }\r\n return html`\r\n <div\r\n id=\"container\"\r\n class=\"\r\n noselect\r\n ${this._isDragging ? 'dragging' : ''}\r\n \"\r\n style=\"width: ${this.width}px\"\r\n >\r\n ${this.activityIndicatorTemplate} ${this.tooltipTemplate}\r\n <div\r\n class=\"inner-container\r\n ${this.disabled ? 'disabled' : ''}\"\r\n >\r\n <svg\r\n width=\"${this.width}\"\r\n height=\"${this.height}\"\r\n @pointerleave=\"${this.drop}\"\r\n >\r\n ${this.selectedRangeTemplate}\r\n <svg id=\"histogram\">${this.histogramTemplate}</svg>\r\n ${this.minSliderTemplate} ${this.maxSliderTemplate}\r\n </svg>\r\n <div id=\"inputs\">\r\n ${this.minLabelTemplate} ${this.minInputTemplate}\r\n <div class=\"dash\">-</div>\r\n ${this.maxLabelTemplate} ${this.maxInputTemplate}\r\n <slot name=\"inputs-right-side\"></slot>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\n// help TypeScript provide strong typing when interacting with DOM APIs\r\n// https://stackoverflow.com/questions/65148695/lit-element-typescript-project-global-interface-declaration-necessary\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'histogram-date-range': HistogramDateRange;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"histogram-date-range.js","sourceRoot":"","sources":["../../src/histogram-date-range.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n css,\r\n html,\r\n nothing,\r\n LitElement,\r\n PropertyValues,\r\n svg,\r\n SVGTemplateResult,\r\n TemplateResult,\r\n} from 'lit';\r\nimport { property, state, customElement } from 'lit/decorators.js';\r\nimport { live } from 'lit/directives/live.js';\r\nimport '@internetarchive/ia-activity-indicator/ia-activity-indicator';\r\n\r\n/* eslint-disable-next-line */\r\n/* @ts-ignore Import module -- JS, so no types */\r\nimport dayjs from 'https://esm.archive.org/dayjs@1.11.10';\r\n/* eslint-disable-next-line */\r\n/* @ts-ignore Import module -- JS, so no types */\r\nimport customParseFormat from 'https://esm.archive.org/dayjs@1.9.4/esm/plugin/customParseFormat';\r\n// NOTE: using a specific *earlier* pegged commit for the plugin ^, because esm.archive.org has a\r\n// problem creating later versions where the `export` of an included `utils.js` gets mangled. Eg:\r\n// https://github.com/internetarchive/esbuild_es5/commit/ce19e8b841282c0e94d2b8e6830fd7744b2216c2#diff-4b2ed47327851d566740a30ce5f60271c059ae67eff2006bc07bb7c4fcee8b50L296\r\n\r\ndayjs.extend(customParseFormat);\r\n\r\n// these values can be overridden via the component's HTML (camelCased) attributes\r\nconst WIDTH = 180;\r\nconst HEIGHT = 40;\r\nconst SLIDER_WIDTH = 10;\r\nconst TOOLTIP_WIDTH = 125;\r\nconst TOOLTIP_HEIGHT = 30;\r\nconst DATE_FORMAT = 'YYYY';\r\nconst MISSING_DATA = 'no data';\r\nconst UPDATE_DEBOUNCE_DELAY_MS = 0;\r\n\r\n// this constant is not set up to be overridden\r\nconst SLIDER_CORNER_SIZE = 4;\r\n\r\n// these CSS custom props can be overridden from the HTML that is invoking this component\r\nconst sliderColor = css`var(--histogramDateRangeSliderColor, #4B65FE)`;\r\nconst selectedRangeColor = css`var(--histogramDateRangeSelectedRangeColor, #DBE0FF)`;\r\nconst barIncludedFill = css`var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;\r\nconst activityIndicatorColor = css`var(--histogramDateRangeActivityIndicator, #2C2C2C)`;\r\nconst barExcludedFill = css`var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;\r\nconst inputRowMargin = css`var(--histogramDateRangeInputRowMargin, 0)`;\r\nconst inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;\r\nconst inputWidth = css`var(--histogramDateRangeInputWidth, 35px)`;\r\nconst inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;\r\nconst inputFontFamily = css`var(--histogramDateRangeInputFontFamily, sans-serif)`;\r\nconst tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;\r\nconst tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;\r\nconst tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;\r\nconst tooltipFontFamily = css`var(--histogramDateRangeTooltipFontFamily, sans-serif)`;\r\n\r\ntype SliderId = 'slider-min' | 'slider-max';\r\n\r\ninterface HistogramItem {\r\n value: number;\r\n height: number;\r\n binStart: string;\r\n binEnd: string;\r\n}\r\n\r\ninterface BarDataset extends DOMStringMap {\r\n numItems: string;\r\n binStart: string;\r\n binEnd: string;\r\n}\r\n\r\n@customElement('histogram-date-range')\r\nexport class HistogramDateRange extends LitElement {\r\n /* eslint-disable lines-between-class-members */\r\n\r\n // public reactive properties that can be set via HTML attributes\r\n @property({ type: Number }) width = WIDTH;\r\n @property({ type: Number }) height = HEIGHT;\r\n @property({ type: Number }) sliderWidth = SLIDER_WIDTH;\r\n @property({ type: Number }) tooltipWidth = TOOLTIP_WIDTH;\r\n @property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;\r\n @property({ type: Number }) updateDelay = UPDATE_DEBOUNCE_DELAY_MS;\r\n @property({ type: String }) dateFormat = DATE_FORMAT;\r\n /** Optional; falls back to `dateFormat` if not provided */\r\n @property({ type: String }) tooltipDateFormat?: string;\r\n @property({ type: String }) missingDataMessage = MISSING_DATA;\r\n @property({ type: String }) minDate = '';\r\n @property({ type: String }) maxDate = '';\r\n @property({ type: Boolean }) disabled = false;\r\n @property({ type: Array }) bins: number[] = [];\r\n /** If true, update events will not be canceled by the date inputs receiving focus */\r\n @property({ type: Boolean }) updateWhileFocused = false;\r\n\r\n // internal reactive properties not exposed as attributes\r\n @state() private _tooltipOffset = 0;\r\n @state() private _tooltipContent?: TemplateResult;\r\n @state() private _tooltipVisible = false;\r\n @state() private _isDragging = false;\r\n @state() private _isLoading = false;\r\n\r\n // non-reactive properties (changes don't auto-trigger re-rendering)\r\n private _minSelectedDate = '';\r\n private _maxSelectedDate = '';\r\n private _minDateMS = 0;\r\n private _maxDateMS = 0;\r\n private _dragOffset = 0;\r\n private _histWidth = 0;\r\n private _binWidth = 0;\r\n private _currentSlider?: SVGRectElement;\r\n private _histData: HistogramItem[] = [];\r\n private _emitUpdatedEventTimer?: ReturnType<typeof setTimeout>;\r\n private _previousDateRange = '';\r\n\r\n /* eslint-enable lines-between-class-members */\r\n\r\n disconnectedCallback(): void {\r\n this.removeListeners();\r\n super.disconnectedCallback();\r\n }\r\n\r\n willUpdate(changedProps: PropertyValues): void {\r\n // check for changes that would affect bin data calculations\r\n if (\r\n changedProps.has('bins') ||\r\n changedProps.has('minDate') ||\r\n changedProps.has('maxDate') ||\r\n changedProps.has('minSelectedDate') ||\r\n changedProps.has('maxSelectedDate') ||\r\n changedProps.has('width') ||\r\n changedProps.has('height')\r\n ) {\r\n this.handleDataUpdate();\r\n }\r\n }\r\n\r\n /**\r\n * Set private properties that depend on the attribute bin data\r\n *\r\n * We're caching these values and not using getters to avoid recalculating all\r\n * of the hist data every time the user drags a slider or hovers over a bar\r\n * creating a tooltip.\r\n */\r\n private handleDataUpdate(): void {\r\n if (!this.hasBinData) {\r\n return;\r\n }\r\n this._histWidth = this.width - this.sliderWidth * 2;\r\n this._minDateMS = this.getMSFromString(this.minDate);\r\n this._maxDateMS = this.getMSFromString(this.maxDate);\r\n this._binWidth = this._histWidth / this._numBins;\r\n this._previousDateRange = this.currentDateRangeString;\r\n this._histData = this.calculateHistData();\r\n this.minSelectedDate = this.minSelectedDate\r\n ? this.minSelectedDate\r\n : this.minDate;\r\n this.maxSelectedDate = this.maxSelectedDate\r\n ? this.maxSelectedDate\r\n : this.maxDate;\r\n }\r\n\r\n private calculateHistData(): HistogramItem[] {\r\n const minValue = Math.min(...this.bins);\r\n const maxValue = Math.max(...this.bins);\r\n // if there is no difference between the min and max values, use a range of\r\n // 1 because log scaling will fail if the range is 0\r\n const valueRange = minValue === maxValue ? 1 : Math.log1p(maxValue);\r\n const valueScale = this.height / valueRange;\r\n const dateScale = this.dateRangeMS / this._numBins;\r\n return this.bins.map((v: number, i: number) => {\r\n return {\r\n value: v,\r\n // use log scaling for the height of the bar to prevent tall bars from\r\n // making the smaller ones too small to see\r\n height: Math.floor(Math.log1p(v) * valueScale),\r\n binStart: `${this.formatDate(i * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,\r\n binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,\r\n };\r\n });\r\n }\r\n\r\n private get hasBinData(): boolean {\r\n return this._numBins > 0;\r\n }\r\n\r\n private get _numBins(): number {\r\n if (!this.bins || !this.bins.length) {\r\n return 0;\r\n }\r\n return this.bins.length;\r\n }\r\n\r\n private get histogramLeftEdgeX(): number {\r\n return this.sliderWidth;\r\n }\r\n\r\n private get histogramRightEdgeX(): number {\r\n return this.width - this.sliderWidth;\r\n }\r\n\r\n private get resolvedTooltipDateFormat(): string {\r\n if (this.tooltipDateFormat) return this.tooltipDateFormat;\r\n return this.dateFormat ?? DATE_FORMAT;\r\n }\r\n\r\n /** component's loading (and disabled) state */\r\n @property({ type: Boolean }) get loading(): boolean {\r\n return this._isLoading;\r\n }\r\n\r\n set loading(value: boolean) {\r\n this.disabled = value;\r\n this._isLoading = value;\r\n }\r\n\r\n /** formatted minimum date of selected date range */\r\n @property() get minSelectedDate(): string {\r\n return this.formatDate(this.getMSFromString(this._minSelectedDate));\r\n }\r\n\r\n /** updates minSelectedDate if new date is valid */\r\n set minSelectedDate(rawDate: string) {\r\n if (!this._minSelectedDate) {\r\n // because the values needed to calculate valid max/min values are not\r\n // available during the lit init when it's populating properties from\r\n // attributes, fall back to just the raw date if nothing is already set\r\n this._minSelectedDate = rawDate;\r\n return;\r\n }\r\n const proposedDateMS = this.getMSFromString(rawDate);\r\n const isValidDate = !Number.isNaN(proposedDateMS);\r\n const isNotTooRecent =\r\n proposedDateMS <= this.getMSFromString(this.maxSelectedDate);\r\n if (isValidDate && isNotTooRecent) {\r\n this._minSelectedDate = this.formatDate(proposedDateMS);\r\n }\r\n this.requestUpdate();\r\n }\r\n\r\n /** formatted maximum date of selected date range */\r\n @property() get maxSelectedDate(): string {\r\n return this.formatDate(this.getMSFromString(this._maxSelectedDate));\r\n }\r\n\r\n /** updates maxSelectedDate if new date is valid */\r\n set maxSelectedDate(rawDate: string) {\r\n if (!this._maxSelectedDate) {\r\n // because the values needed to calculate valid max/min values are not\r\n // available during the lit init when it's populating properties from\r\n // attributes, fall back to just the raw date if nothing is already set\r\n this._maxSelectedDate = rawDate;\r\n return;\r\n }\r\n const proposedDateMS = this.getMSFromString(rawDate);\r\n const isValidDate = !Number.isNaN(proposedDateMS);\r\n const isNotTooOld =\r\n proposedDateMS >= this.getMSFromString(this.minSelectedDate);\r\n if (isValidDate && isNotTooOld) {\r\n this._maxSelectedDate = this.formatDate(proposedDateMS);\r\n }\r\n this.requestUpdate();\r\n }\r\n\r\n /** horizontal position of min date slider */\r\n get minSliderX(): number {\r\n const x = this.translateDateToPosition(this.minSelectedDate);\r\n return this.validMinSliderX(x);\r\n }\r\n\r\n /** horizontal position of max date slider */\r\n get maxSliderX(): number {\r\n const x = this.translateDateToPosition(this.maxSelectedDate);\r\n return this.validMaxSliderX(x);\r\n }\r\n\r\n private get dateRangeMS(): number {\r\n return this._maxDateMS - this._minDateMS;\r\n }\r\n\r\n private showTooltip(e: PointerEvent): void {\r\n if (this._isDragging || this.disabled) {\r\n return;\r\n }\r\n const target = e.currentTarget as SVGRectElement;\r\n const x = target.x.baseVal.value + this.sliderWidth / 2;\r\n const dataset = target.dataset as BarDataset;\r\n const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;\r\n const formattedNumItems = Number(dataset.numItems).toLocaleString();\r\n\r\n this._tooltipOffset =\r\n x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;\r\n\r\n this._tooltipContent = html`\r\n ${formattedNumItems} ${itemsText}<br />\r\n ${dataset.binStart} - ${dataset.binEnd}\r\n `;\r\n this._tooltipVisible = true;\r\n }\r\n\r\n private hideTooltip(): void {\r\n this._tooltipContent = undefined;\r\n this._tooltipVisible = false;\r\n }\r\n\r\n // use arrow functions (rather than standard JS class instance methods) so\r\n // that `this` is bound to the histogramDateRange object and not the event\r\n // target. for more info see\r\n // https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners\r\n private drag = (e: PointerEvent): void => {\r\n // prevent selecting text or other ranges while dragging, especially in Safari\r\n e.preventDefault();\r\n if (this.disabled) {\r\n return;\r\n }\r\n this.setDragOffset(e);\r\n this._isDragging = true;\r\n this.addListeners();\r\n this.cancelPendingUpdateEvent();\r\n };\r\n\r\n private drop = (): void => {\r\n if (this._isDragging) {\r\n this.removeListeners();\r\n this.beginEmitUpdateProcess();\r\n }\r\n this._isDragging = false;\r\n };\r\n\r\n /**\r\n * Adjust the date range based on slider movement\r\n *\r\n * @param e PointerEvent from the slider being moved\r\n */\r\n private move = (e: PointerEvent): void => {\r\n const histogramClientX = this.getBoundingClientRect().x;\r\n const newX = e.clientX - histogramClientX - this._dragOffset;\r\n const slider = this._currentSlider as SVGRectElement;\r\n if ((slider.id as SliderId) === 'slider-min') {\r\n this.minSelectedDate = this.translatePositionToDate(\r\n this.validMinSliderX(newX)\r\n );\r\n } else {\r\n this.maxSelectedDate = this.translatePositionToDate(\r\n this.validMaxSliderX(newX)\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Constrain a proposed value for the minimum (left) slider\r\n *\r\n * If the value is less than the leftmost valid position, then set it to the\r\n * left edge of the histogram (ie the slider width). If the value is greater\r\n * than the rightmost valid position (the position of the max slider), then\r\n * set it to the position of the max slider\r\n */\r\n private validMinSliderX(newX: number): number {\r\n // allow the left slider to go right only to the right slider, even if the\r\n // max selected date is out of range\r\n const rightLimit = Math.min(\r\n this.translateDateToPosition(this.maxSelectedDate),\r\n this.histogramRightEdgeX\r\n );\r\n newX = this.clamp(newX, this.histogramLeftEdgeX, rightLimit);\r\n const isInvalid =\r\n Number.isNaN(newX) || rightLimit < this.histogramLeftEdgeX;\r\n return isInvalid ? this.histogramLeftEdgeX : newX;\r\n }\r\n\r\n /**\r\n * Constrain a proposed value for the maximum (right) slider\r\n *\r\n * If the value is greater than the rightmost valid position, then set it to\r\n * the right edge of the histogram (ie histogram width - slider width). If the\r\n * value is less than the leftmost valid position (the position of the min\r\n * slider), then set it to the position of the min slider\r\n */\r\n private validMaxSliderX(newX: number): number {\r\n // allow the right slider to go left only to the left slider, even if the\r\n // min selected date is out of range\r\n const leftLimit = Math.max(\r\n this.histogramLeftEdgeX,\r\n this.translateDateToPosition(this.minSelectedDate)\r\n );\r\n newX = this.clamp(newX, leftLimit, this.histogramRightEdgeX);\r\n const isInvalid =\r\n Number.isNaN(newX) || leftLimit > this.histogramRightEdgeX;\r\n return isInvalid ? this.histogramRightEdgeX : newX;\r\n }\r\n\r\n private addListeners(): void {\r\n window.addEventListener('pointermove', this.move);\r\n window.addEventListener('pointerup', this.drop);\r\n window.addEventListener('pointercancel', this.drop);\r\n }\r\n\r\n private removeListeners(): void {\r\n window.removeEventListener('pointermove', this.move);\r\n window.removeEventListener('pointerup', this.drop);\r\n window.removeEventListener('pointercancel', this.drop);\r\n }\r\n\r\n /**\r\n * start a timer to emit an update event. this timer can be canceled (and the\r\n * event not emitted) if user drags a slider or focuses a date input within\r\n * the update delay\r\n */\r\n private beginEmitUpdateProcess(): void {\r\n this.cancelPendingUpdateEvent();\r\n this._emitUpdatedEventTimer = setTimeout(() => {\r\n if (this.currentDateRangeString === this._previousDateRange) {\r\n // don't emit duplicate event if no change since last emitted event\r\n return;\r\n }\r\n this._previousDateRange = this.currentDateRangeString;\r\n const options = {\r\n detail: {\r\n minDate: this.minSelectedDate,\r\n maxDate: this.maxSelectedDate,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n };\r\n this.dispatchEvent(new CustomEvent('histogramDateRangeUpdated', options));\r\n }, this.updateDelay);\r\n }\r\n\r\n private cancelPendingUpdateEvent(): void {\r\n if (this._emitUpdatedEventTimer === undefined) {\r\n return;\r\n }\r\n clearTimeout(this._emitUpdatedEventTimer);\r\n this._emitUpdatedEventTimer = undefined;\r\n }\r\n\r\n /**\r\n * find position of pointer in relation to the current slider\r\n */\r\n private setDragOffset(e: PointerEvent): void {\r\n this._currentSlider = e.currentTarget as SVGRectElement;\r\n const sliderX =\r\n (this._currentSlider.id as SliderId) === 'slider-min'\r\n ? this.minSliderX\r\n : this.maxSliderX;\r\n const histogramClientX = this.getBoundingClientRect().x;\r\n this._dragOffset = e.clientX - histogramClientX - sliderX;\r\n }\r\n\r\n /**\r\n * @param x horizontal position of slider\r\n * @returns string representation of date\r\n */\r\n private translatePositionToDate(x: number): string {\r\n // use Math.ceil to round up to fix case where input like 1/1/2010 would get\r\n // translated to 12/31/2009\r\n const milliseconds = Math.ceil(\r\n ((x - this.sliderWidth) * this.dateRangeMS) / this._histWidth\r\n );\r\n return this.formatDate(this._minDateMS + milliseconds);\r\n }\r\n\r\n /**\r\n * Returns slider x-position corresponding to given date\r\n *\r\n * @param date\r\n * @returns x-position of slider\r\n */\r\n private translateDateToPosition(date: string): number {\r\n const milliseconds = this.getMSFromString(date);\r\n return (\r\n this.sliderWidth +\r\n ((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS\r\n );\r\n }\r\n\r\n /** ensure that the returned value is between minValue and maxValue */\r\n private clamp(x: number, minValue: number, maxValue: number): number {\r\n return Math.min(Math.max(x, minValue), maxValue);\r\n }\r\n\r\n private handleInputFocus(): void {\r\n if (!this.updateWhileFocused) {\r\n this.cancelPendingUpdateEvent();\r\n }\r\n }\r\n\r\n private handleMinDateInput(e: Event): void {\r\n const target = e.currentTarget as HTMLInputElement;\r\n if (target.value !== this.minSelectedDate) {\r\n this.minSelectedDate = target.value;\r\n this.beginEmitUpdateProcess();\r\n }\r\n }\r\n\r\n private handleMaxDateInput(e: Event): void {\r\n const target = e.currentTarget as HTMLInputElement;\r\n if (target.value !== this.maxSelectedDate) {\r\n this.maxSelectedDate = target.value;\r\n this.beginEmitUpdateProcess();\r\n }\r\n }\r\n\r\n private handleKeyUp(e: KeyboardEvent): void {\r\n if (e.key === 'Enter') {\r\n const target = e.currentTarget as HTMLInputElement;\r\n target.blur();\r\n if (target.id === 'date-min') {\r\n this.handleMinDateInput(e);\r\n } else if (target.id === 'date-max') {\r\n this.handleMaxDateInput(e);\r\n }\r\n }\r\n }\r\n\r\n private get currentDateRangeString(): string {\r\n return `${this.minSelectedDate}:${this.maxSelectedDate}`;\r\n }\r\n\r\n private getMSFromString(date: unknown): number {\r\n // It's possible that `date` is not a string in certain situations.\r\n // For instance if you use LitElement bindings and the date is `2000`,\r\n // it will be treated as a number instead of a string. This just makes sure\r\n // we're dealing with a string.\r\n const stringified = typeof date === 'string' ? date : String(date);\r\n const digitGroupCount = (stringified.split(/(\\d+)/).length - 1) / 2;\r\n if (digitGroupCount === 1) {\r\n // if there's just a single set of digits, assume it's a year\r\n const dateObj = new Date(0, 0); // start at January 1, 1900\r\n dateObj.setFullYear(Number(stringified)); // override year\r\n return dateObj.getTime(); // get time in milliseconds\r\n }\r\n return dayjs(stringified, [this.dateFormat, DATE_FORMAT]).valueOf();\r\n }\r\n\r\n /**\r\n * expand or narrow the selected range by moving the slider nearest the\r\n * clicked bar to the outer edge of the clicked bar\r\n *\r\n * @param e Event click event from a histogram bar\r\n */\r\n private handleBarClick(e: Event): void {\r\n const dataset = (e.currentTarget as SVGRectElement).dataset as BarDataset;\r\n // use the midpoint of the width of the clicked bar to determine which is\r\n // the nearest slider\r\n const clickPosition =\r\n (this.getMSFromString(dataset.binStart) +\r\n this.getMSFromString(dataset.binEnd)) /\r\n 2;\r\n const distanceFromMinSlider = Math.abs(\r\n clickPosition - this.getMSFromString(this.minSelectedDate)\r\n );\r\n const distanceFromMaxSlider = Math.abs(\r\n clickPosition - this.getMSFromString(this.maxSelectedDate)\r\n );\r\n // update the selected range by moving the nearer slider\r\n if (distanceFromMinSlider < distanceFromMaxSlider) {\r\n this.minSelectedDate = dataset.binStart;\r\n } else {\r\n this.maxSelectedDate = dataset.binEnd;\r\n }\r\n this.beginEmitUpdateProcess();\r\n }\r\n\r\n private get minSliderTemplate(): SVGTemplateResult {\r\n // width/height in pixels of curved part of the sliders (like\r\n // border-radius); used as part of a SVG quadratic curve. see\r\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands\r\n const cs = SLIDER_CORNER_SIZE;\r\n\r\n const sliderShape = `\r\n M${this.minSliderX},0\r\n h-${this.sliderWidth - cs}\r\n q-${cs},0 -${cs},${cs}\r\n v${this.height - cs * 2}\r\n q0,${cs} ${cs},${cs}\r\n h${this.sliderWidth - cs}\r\n `;\r\n return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);\r\n }\r\n\r\n private get maxSliderTemplate(): SVGTemplateResult {\r\n const cs = SLIDER_CORNER_SIZE;\r\n const sliderShape = `\r\n M${this.maxSliderX},0\r\n h${this.sliderWidth - cs}\r\n q${cs},0 ${cs},${cs}\r\n v${this.height - cs * 2}\r\n q0,${cs} -${cs},${cs}\r\n h-${this.sliderWidth - cs}\r\n `;\r\n return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);\r\n }\r\n\r\n private generateSliderSVG(\r\n sliderPositionX: number,\r\n id: SliderId,\r\n sliderShape: string\r\n ): SVGTemplateResult {\r\n // whether the curved part of the slider is facing towards the left (1), ie\r\n // minimum, or facing towards the right (-1), ie maximum\r\n const k = id === 'slider-min' ? 1 : -1;\r\n\r\n return svg`\r\n <svg\r\n id=\"${id}\"\r\n class=\"\r\n ${this.disabled ? '' : 'draggable'}\r\n ${this._isDragging ? 'dragging' : ''}\"\r\n @pointerdown=\"${this.drag}\"\r\n >\r\n <path d=\"${sliderShape} z\" fill=\"${sliderColor}\" />\r\n <rect\r\n x=\"${\r\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k\r\n }\"\r\n y=\"${this.height / 3}\"\r\n width=\"1\"\r\n height=\"${this.height / 3}\"\r\n fill=\"white\"\r\n />\r\n <rect\r\n x=\"${\r\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k\r\n }\"\r\n y=\"${this.height / 3}\"\r\n width=\"1\"\r\n height=\"${this.height / 3}\"\r\n fill=\"white\"\r\n />\r\n </svg>\r\n `;\r\n }\r\n\r\n get selectedRangeTemplate(): SVGTemplateResult {\r\n return svg`\r\n <rect\r\n x=\"${this.minSliderX}\"\r\n y=\"0\"\r\n width=\"${this.maxSliderX - this.minSliderX}\"\r\n height=\"${this.height}\"\r\n fill=\"${selectedRangeColor}\"\r\n />`;\r\n }\r\n\r\n get histogramTemplate(): SVGTemplateResult[] {\r\n const xScale = this._histWidth / this._numBins;\r\n const barWidth = xScale - 1;\r\n let x = this.sliderWidth; // start at the left edge of the histogram\r\n\r\n // the stroke-dasharray style below creates a transparent border around the\r\n // right edge of the bar, which prevents user from encountering a gap\r\n // between adjacent bars (eg when viewing the tooltips or when trying to\r\n // extend the range by clicking on a bar)\r\n return this._histData.map(data => {\r\n const bar = svg`\r\n <rect\r\n class=\"bar\"\r\n style='stroke-dasharray: 0 ${barWidth} ${data.height} ${barWidth} 0 ${\r\n data.height\r\n };'\r\n x=\"${x}\"\r\n y=\"${this.height - data.height}\"\r\n width=\"${barWidth}\"\r\n height=\"${data.height}\"\r\n @pointerenter=\"${this.showTooltip}\"\r\n @pointerleave=\"${this.hideTooltip}\"\r\n @click=\"${this.handleBarClick}\"\r\n fill=\"${\r\n x + barWidth >= this.minSliderX && x <= this.maxSliderX\r\n ? barIncludedFill\r\n : barExcludedFill\r\n }\"\r\n data-num-items=\"${data.value}\"\r\n data-bin-start=\"${data.binStart}\"\r\n data-bin-end=\"${data.binEnd}\"\r\n />`;\r\n x += xScale;\r\n return bar;\r\n });\r\n }\r\n\r\n private formatDate(dateMS: number, format: string = this.dateFormat): string {\r\n if (Number.isNaN(dateMS)) {\r\n return '';\r\n }\r\n const date = dayjs(dateMS);\r\n if (date.year() < 1000) {\r\n // years before 1000 don't play well with dayjs custom formatting, so fall\r\n // back to displaying only the year\r\n return String(date.year());\r\n }\r\n return date.format(format);\r\n }\r\n\r\n /**\r\n * NOTE: we are relying on the lit `live` directive in the template to\r\n * ensure that the change to minSelectedDate is noticed and the input value\r\n * gets properly re-rendered. see\r\n * https://lit.dev/docs/templates/directives/#live\r\n */\r\n get minInputTemplate(): TemplateResult {\r\n return html`\r\n <input\r\n id=\"date-min\"\r\n placeholder=\"${this.dateFormat}\"\r\n type=\"text\"\r\n @focus=\"${this.handleInputFocus}\"\r\n @blur=\"${this.handleMinDateInput}\"\r\n @keyup=\"${this.handleKeyUp}\"\r\n .value=\"${live(this.minSelectedDate)}\"\r\n ?disabled=\"${this.disabled}\"\r\n />\r\n `;\r\n }\r\n\r\n get maxInputTemplate(): TemplateResult {\r\n return html`\r\n <input\r\n id=\"date-max\"\r\n placeholder=\"${this.dateFormat}\"\r\n type=\"text\"\r\n @focus=\"${this.handleInputFocus}\"\r\n @blur=\"${this.handleMaxDateInput}\"\r\n @keyup=\"${this.handleKeyUp}\"\r\n .value=\"${live(this.maxSelectedDate)}\"\r\n ?disabled=\"${this.disabled}\"\r\n />\r\n `;\r\n }\r\n\r\n get minLabelTemplate(): TemplateResult {\r\n return html`<label for=\"date-min\" class=\"sr-only\">Minimum date:</label>`;\r\n }\r\n\r\n get maxLabelTemplate(): TemplateResult {\r\n return html`<label for=\"date-max\" class=\"sr-only\">Maximum date:</label>`;\r\n }\r\n\r\n get tooltipTemplate(): TemplateResult {\r\n return html`\r\n <style>\r\n #tooltip {\r\n width: ${this.tooltipWidth}px;\r\n height: ${this.tooltipHeight}px;\r\n top: ${-9 - this.tooltipHeight}px;\r\n left: ${this._tooltipOffset}px;\r\n display: ${this._tooltipVisible ? 'block' : 'none'};\r\n }\r\n #tooltip:after {\r\n left: ${this.tooltipWidth / 2}px;\r\n }\r\n </style>\r\n <div id=\"tooltip\">${this._tooltipContent}</div>\r\n `;\r\n }\r\n\r\n private get noDataTemplate(): TemplateResult {\r\n return html`\r\n <div class=\"missing-data-message\">${this.missingDataMessage}</div>\r\n `;\r\n }\r\n\r\n private get activityIndicatorTemplate(): TemplateResult | typeof nothing {\r\n if (!this.loading) {\r\n return nothing;\r\n }\r\n return html`\r\n <ia-activity-indicator mode=\"processing\"> </ia-activity-indicator>\r\n `;\r\n }\r\n\r\n static styles = css`\r\n .missing-data-message {\r\n text-align: center;\r\n }\r\n #container {\r\n margin: 0;\r\n touch-action: none;\r\n position: relative;\r\n }\r\n .disabled {\r\n opacity: 0.3;\r\n }\r\n ia-activity-indicator {\r\n position: absolute;\r\n left: calc(50% - 10px);\r\n top: 10px;\r\n width: 20px;\r\n height: 20px;\r\n --activityIndicatorLoadingDotColor: rgba(0, 0, 0, 0);\r\n --activityIndicatorLoadingRingColor: ${activityIndicatorColor};\r\n }\r\n\r\n /* prevent selection from interfering with tooltip, especially on mobile */\r\n /* https://stackoverflow.com/a/4407335/1163042 */\r\n .noselect {\r\n -webkit-touch-callout: none; /* iOS Safari */\r\n -webkit-user-select: none; /* Safari */\r\n -moz-user-select: none; /* Old versions of Firefox */\r\n -ms-user-select: none; /* Internet Explorer/Edge */\r\n user-select: none; /* current Chrome, Edge, Opera and Firefox */\r\n }\r\n .bar {\r\n /* create a transparent border around the hist bars to prevent \"gaps\" and\r\n flickering when moving around between bars. this also helps with handling\r\n clicks on the bars, preventing users from being able to click in between\r\n bars */\r\n stroke: rgba(0, 0, 0, 0);\r\n /* ensure transparent stroke wide enough to cover gap between bars */\r\n stroke-width: 2px;\r\n }\r\n .bar:hover {\r\n /* highlight currently hovered bar */\r\n fill-opacity: 0.7;\r\n }\r\n .disabled .bar:hover {\r\n /* ensure no visual hover interaction when disabled */\r\n fill-opacity: 1;\r\n }\r\n /****** histogram ********/\r\n #tooltip {\r\n position: absolute;\r\n background: ${tooltipBackgroundColor};\r\n color: ${tooltipTextColor};\r\n text-align: center;\r\n border-radius: 3px;\r\n padding: 2px;\r\n font-size: ${tooltipFontSize};\r\n font-family: ${tooltipFontFamily};\r\n touch-action: none;\r\n pointer-events: none;\r\n }\r\n #tooltip:after {\r\n content: '';\r\n position: absolute;\r\n margin-left: -5px;\r\n top: 100%;\r\n /* arrow */\r\n border: 5px solid ${tooltipTextColor};\r\n border-color: ${tooltipBackgroundColor} transparent transparent\r\n transparent;\r\n }\r\n /****** slider ********/\r\n .draggable:hover {\r\n cursor: grab;\r\n }\r\n .dragging {\r\n cursor: grabbing !important;\r\n }\r\n /****** inputs ********/\r\n #inputs {\r\n display: flex;\r\n justify-content: center;\r\n margin: ${inputRowMargin};\r\n }\r\n #inputs .dash {\r\n position: relative;\r\n bottom: -1px;\r\n align-self: center; /* Otherwise the dash sticks to the top while the inputs grow */\r\n }\r\n input {\r\n width: ${inputWidth};\r\n margin: 0 3px;\r\n border: ${inputBorder};\r\n border-radius: 2px !important;\r\n text-align: center;\r\n font-size: ${inputFontSize};\r\n font-family: ${inputFontFamily};\r\n }\r\n .sr-only {\r\n position: absolute !important;\r\n width: 1px !important;\r\n height: 1px !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n overflow: hidden !important;\r\n white-space: nowrap !important;\r\n clip: rect(1px, 1px, 1px, 1px) !important;\r\n -webkit-clip-path: inset(50%) !important;\r\n clip-path: inset(50%) !important;\r\n }\r\n `;\r\n\r\n render(): TemplateResult {\r\n if (!this.hasBinData) {\r\n return this.noDataTemplate;\r\n }\r\n return html`\r\n <div\r\n id=\"container\"\r\n class=\"\r\n noselect\r\n ${this._isDragging ? 'dragging' : ''}\r\n \"\r\n style=\"width: ${this.width}px\"\r\n >\r\n ${this.activityIndicatorTemplate} ${this.tooltipTemplate}\r\n <div\r\n class=\"inner-container\r\n ${this.disabled ? 'disabled' : ''}\"\r\n >\r\n <svg\r\n width=\"${this.width}\"\r\n height=\"${this.height}\"\r\n @pointerleave=\"${this.drop}\"\r\n >\r\n ${this.selectedRangeTemplate}\r\n <svg id=\"histogram\">${this.histogramTemplate}</svg>\r\n ${this.minSliderTemplate} ${this.maxSliderTemplate}\r\n </svg>\r\n <div id=\"inputs\">\r\n ${this.minLabelTemplate} ${this.minInputTemplate}\r\n <div class=\"dash\">-</div>\r\n ${this.maxLabelTemplate} ${this.maxInputTemplate}\r\n <slot name=\"inputs-right-side\"></slot>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\n// help TypeScript provide strong typing when interacting with DOM APIs\r\n// https://stackoverflow.com/questions/65148695/lit-element-typescript-project-global-interface-declaration-necessary\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'histogram-date-range': HistogramDateRange;\r\n }\r\n}\r\n"]}
|
|
@@ -106,7 +106,7 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
106
106
|
this.removeListeners();
|
|
107
107
|
super.disconnectedCallback();
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
willUpdate(changedProps) {
|
|
110
110
|
if (changedProps.has("bins") || changedProps.has("minDate") || changedProps.has("maxDate") || changedProps.has("minSelectedDate") || changedProps.has("maxSelectedDate") || changedProps.has("width") || changedProps.has("height")) {
|
|
111
111
|
this.handleDataUpdate();
|
|
112
112
|
}
|
|
@@ -123,7 +123,6 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
123
123
|
this._histData = this.calculateHistData();
|
|
124
124
|
this.minSelectedDate = this.minSelectedDate ? this.minSelectedDate : this.minDate;
|
|
125
125
|
this.maxSelectedDate = this.maxSelectedDate ? this.maxSelectedDate : this.maxDate;
|
|
126
|
-
this.requestUpdate();
|
|
127
126
|
}
|
|
128
127
|
calculateHistData() {
|
|
129
128
|
const minValue = Math.min(...this.bins);
|
|
@@ -135,8 +134,8 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
135
134
|
return {
|
|
136
135
|
value: v,
|
|
137
136
|
height: Math.floor(Math.log1p(v) * valueScale),
|
|
138
|
-
binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,
|
|
139
|
-
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`
|
|
137
|
+
binStart: `${this.formatDate(i * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
|
|
138
|
+
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`
|
|
140
139
|
};
|
|
141
140
|
});
|
|
142
141
|
}
|
|
@@ -155,6 +154,11 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
155
154
|
get histogramRightEdgeX() {
|
|
156
155
|
return this.width - this.sliderWidth;
|
|
157
156
|
}
|
|
157
|
+
get resolvedTooltipDateFormat() {
|
|
158
|
+
if (this.tooltipDateFormat)
|
|
159
|
+
return this.tooltipDateFormat;
|
|
160
|
+
return this.dateFormat ?? DATE_FORMAT;
|
|
161
|
+
}
|
|
158
162
|
get loading() {
|
|
159
163
|
return this._isLoading;
|
|
160
164
|
}
|
|
@@ -431,7 +435,7 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
431
435
|
return bar;
|
|
432
436
|
});
|
|
433
437
|
}
|
|
434
|
-
formatDate(dateMS) {
|
|
438
|
+
formatDate(dateMS, format = this.dateFormat) {
|
|
435
439
|
if (Number.isNaN(dateMS)) {
|
|
436
440
|
return "";
|
|
437
441
|
}
|
|
@@ -439,7 +443,7 @@ export let HistogramDateRange = class extends LitElement {
|
|
|
439
443
|
if (date.year() < 1e3) {
|
|
440
444
|
return String(date.year());
|
|
441
445
|
}
|
|
442
|
-
return date.format(
|
|
446
|
+
return date.format(format);
|
|
443
447
|
}
|
|
444
448
|
get minInputTemplate() {
|
|
445
449
|
return html`
|
|
@@ -676,6 +680,9 @@ __decorate([
|
|
|
676
680
|
__decorate([
|
|
677
681
|
property({type: String})
|
|
678
682
|
], HistogramDateRange.prototype, "dateFormat", 2);
|
|
683
|
+
__decorate([
|
|
684
|
+
property({type: String})
|
|
685
|
+
], HistogramDateRange.prototype, "tooltipDateFormat", 2);
|
|
679
686
|
__decorate([
|
|
680
687
|
property({type: String})
|
|
681
688
|
], HistogramDateRange.prototype, "missingDataMessage", 2);
|
|
@@ -689,7 +696,7 @@ __decorate([
|
|
|
689
696
|
property({type: Boolean})
|
|
690
697
|
], HistogramDateRange.prototype, "disabled", 2);
|
|
691
698
|
__decorate([
|
|
692
|
-
property({type:
|
|
699
|
+
property({type: Array})
|
|
693
700
|
], HistogramDateRange.prototype, "bins", 2);
|
|
694
701
|
__decorate([
|
|
695
702
|
property({type: Boolean})
|
package/package.json
CHANGED
|
@@ -80,11 +80,13 @@ export class HistogramDateRange extends LitElement {
|
|
|
80
80
|
@property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;
|
|
81
81
|
@property({ type: Number }) updateDelay = UPDATE_DEBOUNCE_DELAY_MS;
|
|
82
82
|
@property({ type: String }) dateFormat = DATE_FORMAT;
|
|
83
|
+
/** Optional; falls back to `dateFormat` if not provided */
|
|
84
|
+
@property({ type: String }) tooltipDateFormat?: string;
|
|
83
85
|
@property({ type: String }) missingDataMessage = MISSING_DATA;
|
|
84
86
|
@property({ type: String }) minDate = '';
|
|
85
87
|
@property({ type: String }) maxDate = '';
|
|
86
88
|
@property({ type: Boolean }) disabled = false;
|
|
87
|
-
@property({ type:
|
|
89
|
+
@property({ type: Array }) bins: number[] = [];
|
|
88
90
|
/** If true, update events will not be canceled by the date inputs receiving focus */
|
|
89
91
|
@property({ type: Boolean }) updateWhileFocused = false;
|
|
90
92
|
|
|
@@ -115,7 +117,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
115
117
|
super.disconnectedCallback();
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
willUpdate(changedProps: PropertyValues): void {
|
|
119
121
|
// check for changes that would affect bin data calculations
|
|
120
122
|
if (
|
|
121
123
|
changedProps.has('bins') ||
|
|
@@ -153,7 +155,6 @@ export class HistogramDateRange extends LitElement {
|
|
|
153
155
|
this.maxSelectedDate = this.maxSelectedDate
|
|
154
156
|
? this.maxSelectedDate
|
|
155
157
|
: this.maxDate;
|
|
156
|
-
this.requestUpdate();
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
private calculateHistData(): HistogramItem[] {
|
|
@@ -170,8 +171,8 @@ export class HistogramDateRange extends LitElement {
|
|
|
170
171
|
// use log scaling for the height of the bar to prevent tall bars from
|
|
171
172
|
// making the smaller ones too small to see
|
|
172
173
|
height: Math.floor(Math.log1p(v) * valueScale),
|
|
173
|
-
binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,
|
|
174
|
-
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,
|
|
174
|
+
binStart: `${this.formatDate(i * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
|
|
175
|
+
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS, this.resolvedTooltipDateFormat)}`,
|
|
175
176
|
};
|
|
176
177
|
});
|
|
177
178
|
}
|
|
@@ -195,6 +196,11 @@ export class HistogramDateRange extends LitElement {
|
|
|
195
196
|
return this.width - this.sliderWidth;
|
|
196
197
|
}
|
|
197
198
|
|
|
199
|
+
private get resolvedTooltipDateFormat(): string {
|
|
200
|
+
if (this.tooltipDateFormat) return this.tooltipDateFormat;
|
|
201
|
+
return this.dateFormat ?? DATE_FORMAT;
|
|
202
|
+
}
|
|
203
|
+
|
|
198
204
|
/** component's loading (and disabled) state */
|
|
199
205
|
@property({ type: Boolean }) get loading(): boolean {
|
|
200
206
|
return this._isLoading;
|
|
@@ -671,7 +677,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
671
677
|
});
|
|
672
678
|
}
|
|
673
679
|
|
|
674
|
-
private formatDate(dateMS: number): string {
|
|
680
|
+
private formatDate(dateMS: number, format: string = this.dateFormat): string {
|
|
675
681
|
if (Number.isNaN(dateMS)) {
|
|
676
682
|
return '';
|
|
677
683
|
}
|
|
@@ -681,7 +687,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
681
687
|
// back to displaying only the year
|
|
682
688
|
return String(date.year());
|
|
683
689
|
}
|
|
684
|
-
return date.format(
|
|
690
|
+
return date.format(format);
|
|
685
691
|
}
|
|
686
692
|
|
|
687
693
|
/**
|