@internetarchive/histogram-date-range 0.1.3-alpha → 0.1.6-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/index.html +30 -8
- package/demo/js/app-root.ts +59 -0
- package/docs/_snowpack/pkg/@internetarchive/ia-activity-indicator/ia-activity-indicator.js +2 -2
- package/docs/_snowpack/pkg/common/{lit-element-3254fb50.js → lit-element-fd3f69c3.js} +3 -3
- package/docs/_snowpack/pkg/common/lit-html-64eba09b.js +8 -0
- package/docs/_snowpack/pkg/lit/directives/live.js +1 -1
- package/docs/_snowpack/pkg/lit.js +2 -2
- package/docs/demo/index.html +30 -8
- package/docs/dist/demo/js/app-root.js +79 -0
- package/docs/dist/src/histogram-date-range.js +11 -10
- package/package.json +2 -2
- package/snowpack.config.js +1 -1
- package/src/histogram-date-range.ts +16 -12
- package/test/histogram-date-range.test.ts +46 -8
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/src/HistogramDateRange.d.ts +0 -58
- package/dist/src/HistogramDateRange.js +0 -447
- package/dist/src/HistogramDateRange.js.map +0 -1
- package/dist/src/histogram-date-range.d.ts +0 -154
- package/dist/src/histogram-date-range.js +0 -807
- package/dist/src/histogram-date-range.js.map +0 -1
- package/dist/test/histogram-date-range.test.d.ts +0 -1
- package/dist/test/histogram-date-range.test.js +0 -404
- package/dist/test/histogram-date-range.test.js.map +0 -1
- package/docs/_snowpack/pkg/common/lit-html-1d707ff6.js +0 -8
|
@@ -45,9 +45,9 @@ async function createCustomElementInHTMLContainer(): Promise<HistogramDateRange>
|
|
|
45
45
|
describe('HistogramDateRange', () => {
|
|
46
46
|
it('shows scaled histogram bars when provided with data', async () => {
|
|
47
47
|
const el = await createCustomElementInHTMLContainer();
|
|
48
|
-
const bars = el.shadowRoot?.querySelectorAll(
|
|
48
|
+
const bars = (el.shadowRoot?.querySelectorAll(
|
|
49
49
|
'.bar'
|
|
50
|
-
) as unknown as SVGRectElement[];
|
|
50
|
+
) as unknown) as SVGRectElement[];
|
|
51
51
|
const heights = Array.from(bars).map(b => b.height.baseVal.value);
|
|
52
52
|
|
|
53
53
|
expect(heights).to.eql([38, 7, 50]);
|
|
@@ -276,9 +276,9 @@ describe('HistogramDateRange', () => {
|
|
|
276
276
|
// include a number which will require commas (1,000,000)
|
|
277
277
|
el.bins = [1000000, 1, 100];
|
|
278
278
|
await aTimeout(10);
|
|
279
|
-
const bars = el.shadowRoot?.querySelectorAll(
|
|
279
|
+
const bars = (el.shadowRoot?.querySelectorAll(
|
|
280
280
|
'.bar'
|
|
281
|
-
) as unknown as SVGRectElement[];
|
|
281
|
+
) as unknown) as SVGRectElement[];
|
|
282
282
|
const tooltip = el.shadowRoot?.querySelector('#tooltip') as HTMLDivElement;
|
|
283
283
|
expect(tooltip.innerText).to.eq('');
|
|
284
284
|
|
|
@@ -304,9 +304,9 @@ describe('HistogramDateRange', () => {
|
|
|
304
304
|
|
|
305
305
|
it('does not show tooltip while dragging', async () => {
|
|
306
306
|
const el = await createCustomElementInHTMLContainer();
|
|
307
|
-
const bars = el.shadowRoot?.querySelectorAll(
|
|
307
|
+
const bars = (el.shadowRoot?.querySelectorAll(
|
|
308
308
|
'.bar'
|
|
309
|
-
) as unknown as SVGRectElement[];
|
|
309
|
+
) as unknown) as SVGRectElement[];
|
|
310
310
|
const tooltip = el.shadowRoot?.querySelector('#tooltip') as HTMLDivElement;
|
|
311
311
|
expect(tooltip.innerText).to.eq('');
|
|
312
312
|
const minSlider = el.shadowRoot?.querySelector('#slider-min') as SVGElement;
|
|
@@ -492,13 +492,27 @@ describe('HistogramDateRange', () => {
|
|
|
492
492
|
</histogram-date-range>
|
|
493
493
|
`
|
|
494
494
|
);
|
|
495
|
-
const bars = el.shadowRoot?.querySelectorAll(
|
|
495
|
+
const bars = (el.shadowRoot?.querySelectorAll(
|
|
496
496
|
'.bar'
|
|
497
|
-
) as unknown as SVGRectElement[];
|
|
497
|
+
) as unknown) as SVGRectElement[];
|
|
498
498
|
const heights = Array.from(bars).map(b => b.height.baseVal.value);
|
|
499
499
|
expect(heights).to.eql([157]);
|
|
500
500
|
});
|
|
501
501
|
|
|
502
|
+
it('correctly displays small diff between max and min values', async () => {
|
|
503
|
+
const el = await fixture<HistogramDateRange>(
|
|
504
|
+
html`
|
|
505
|
+
<histogram-date-range bins="[1519,2643,1880,2041,1638,1441]">
|
|
506
|
+
</histogram-date-range>
|
|
507
|
+
`
|
|
508
|
+
);
|
|
509
|
+
const bars = (el.shadowRoot?.querySelectorAll(
|
|
510
|
+
'.bar'
|
|
511
|
+
) as unknown) as SVGRectElement[];
|
|
512
|
+
const heights = Array.from(bars).map(b => b.height.baseVal.value);
|
|
513
|
+
expect(heights).to.eql([37, 40, 38, 38, 37, 36]);
|
|
514
|
+
});
|
|
515
|
+
|
|
502
516
|
it('has a disabled state', async () => {
|
|
503
517
|
const el = await fixture<HistogramDateRange>(
|
|
504
518
|
html`
|
|
@@ -554,4 +568,28 @@ describe('HistogramDateRange', () => {
|
|
|
554
568
|
?.attributes?.getNamedItem('mode')?.value
|
|
555
569
|
).to.eq('processing');
|
|
556
570
|
});
|
|
571
|
+
|
|
572
|
+
it('can use LitElement bound properties', async () => {
|
|
573
|
+
const el = await fixture<HistogramDateRange>(
|
|
574
|
+
html`
|
|
575
|
+
<histogram-date-range
|
|
576
|
+
.minDate=${1900}
|
|
577
|
+
.maxDate=${'Dec 4, 2020'}
|
|
578
|
+
.minSelectedDate=${2012}
|
|
579
|
+
.maxSelectedDate=${2019}
|
|
580
|
+
.bins=${[33, 1, 100]}
|
|
581
|
+
>
|
|
582
|
+
</histogram-date-range>
|
|
583
|
+
`
|
|
584
|
+
);
|
|
585
|
+
const minDateInput = el.shadowRoot?.querySelector(
|
|
586
|
+
'#date-min'
|
|
587
|
+
) as HTMLInputElement;
|
|
588
|
+
expect(minDateInput.value).to.eq('2012');
|
|
589
|
+
|
|
590
|
+
const maxDateInput = el.shadowRoot?.querySelector(
|
|
591
|
+
'#date-max'
|
|
592
|
+
) as HTMLInputElement;
|
|
593
|
+
expect(maxDateInput.value).to.eq('2019');
|
|
594
|
+
});
|
|
557
595
|
});
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { HistogramDateRange } from './src/histogram-date-range';
|
package/dist/index.js
DELETED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { LitElement, TemplateResult, SVGTemplateResult } from 'lit-element';
|
|
2
|
-
interface HistogramInputData {
|
|
3
|
-
minDate: string;
|
|
4
|
-
maxDate: string;
|
|
5
|
-
bins: number[];
|
|
6
|
-
}
|
|
7
|
-
export declare class HistogramDateRange extends LitElement {
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
sliderWidth: number;
|
|
11
|
-
tooltipWidth: number;
|
|
12
|
-
tooltipHeight: number;
|
|
13
|
-
dateFormat: string;
|
|
14
|
-
data?: HistogramInputData;
|
|
15
|
-
minSliderX: number;
|
|
16
|
-
maxSliderX: number;
|
|
17
|
-
tooltipOffset: number;
|
|
18
|
-
tooltipContent: TemplateResult | '';
|
|
19
|
-
tooltipDisplay: 'block' | 'none';
|
|
20
|
-
tooltip: HTMLDivElement;
|
|
21
|
-
container: HTMLDivElement;
|
|
22
|
-
private _minDate;
|
|
23
|
-
private _maxDate;
|
|
24
|
-
private _dragOffset;
|
|
25
|
-
private _histWidth;
|
|
26
|
-
private _numBins;
|
|
27
|
-
private _binWidth;
|
|
28
|
-
private _currentSlider?;
|
|
29
|
-
private _histData;
|
|
30
|
-
firstUpdated(): void;
|
|
31
|
-
private generateHistData;
|
|
32
|
-
private get dateRange();
|
|
33
|
-
private showTooltip;
|
|
34
|
-
private hideTooltip;
|
|
35
|
-
private drag;
|
|
36
|
-
private drop;
|
|
37
|
-
private move;
|
|
38
|
-
private setDragOffset;
|
|
39
|
-
private setMinSlider;
|
|
40
|
-
private setMaxSlider;
|
|
41
|
-
private translatePositionToDate;
|
|
42
|
-
private translateDateToPosition;
|
|
43
|
-
private handleMinDateInput;
|
|
44
|
-
private handleMaxDateInput;
|
|
45
|
-
private get minInputValue();
|
|
46
|
-
private get maxInputValue();
|
|
47
|
-
private get minSliderTemplate();
|
|
48
|
-
private get maxSliderTemplate();
|
|
49
|
-
private generateSliderSVG;
|
|
50
|
-
get selectedRangeTemplate(): SVGTemplateResult;
|
|
51
|
-
get histogramTemplate(): SVGTemplateResult[];
|
|
52
|
-
get minInputTemplate(): TemplateResult;
|
|
53
|
-
get maxInputTemplate(): TemplateResult;
|
|
54
|
-
get tooltipTemplate(): TemplateResult;
|
|
55
|
-
static styles: import("lit-element").CSSResult;
|
|
56
|
-
render(): TemplateResult;
|
|
57
|
-
}
|
|
58
|
-
export {};
|
|
@@ -1,447 +0,0 @@
|
|
|
1
|
-
import { __decorate } from "tslib";
|
|
2
|
-
import { html, svg, css, internalProperty, LitElement, property, query, } from 'lit-element';
|
|
3
|
-
import dayjs from 'dayjs/esm/index.js';
|
|
4
|
-
// these values can be overridden via the component's HTML (camelCased) attributes
|
|
5
|
-
const WIDTH = 180;
|
|
6
|
-
const HEIGHT = 40;
|
|
7
|
-
const SLIDER_WIDTH = 10;
|
|
8
|
-
const TOOLTIP_WIDTH = 125;
|
|
9
|
-
const TOOLTIP_HEIGHT = 30;
|
|
10
|
-
const DATE_FORMAT = 'M/D/YYYY';
|
|
11
|
-
// this constant is not set up to be overridden
|
|
12
|
-
const SLIDER_CORNER_SIZE = 4;
|
|
13
|
-
// these CSS custom props can be overridden from the HTML that is invoking this component
|
|
14
|
-
const sliderFill = 'var(--histogramDateRangeSliderFill, #4B65FE)';
|
|
15
|
-
const selectedRangeFill = 'var(--histogramDateRangeSelectedRangeFill, #DBE0FF)';
|
|
16
|
-
const barIncludedFill = 'var(--histogramDateRangeBarIncludedFill, #2C2C2C)';
|
|
17
|
-
const barExcludedFill = 'var(--histogramDateRangeBarExcludedFill, #CCCCCC)';
|
|
18
|
-
const inputBorder = css `var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;
|
|
19
|
-
const inputWidth = css `var(--histogramDateRangeInputWidth, 70px)`;
|
|
20
|
-
const inputFontSize = css `var(--histogramDateRangeInputFontSize, 1.2rem)`;
|
|
21
|
-
const tooltipBackgroundColor = css `var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;
|
|
22
|
-
const tooltipTextColor = css `var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;
|
|
23
|
-
const tooltipFontSize = css `var(--histogramDateRangeTooltipFontSize, 1.1rem)`;
|
|
24
|
-
export class HistogramDateRange extends LitElement {
|
|
25
|
-
constructor() {
|
|
26
|
-
/* eslint-disable lines-between-class-members */
|
|
27
|
-
super(...arguments);
|
|
28
|
-
// these properties are intended to be passed in as attributes
|
|
29
|
-
this.width = WIDTH;
|
|
30
|
-
this.height = HEIGHT;
|
|
31
|
-
this.sliderWidth = SLIDER_WIDTH;
|
|
32
|
-
this.tooltipWidth = TOOLTIP_WIDTH;
|
|
33
|
-
this.tooltipHeight = TOOLTIP_HEIGHT;
|
|
34
|
-
this.dateFormat = DATE_FORMAT;
|
|
35
|
-
this.minSliderX = 0;
|
|
36
|
-
this.maxSliderX = 0;
|
|
37
|
-
this.tooltipOffset = 0;
|
|
38
|
-
this.tooltipContent = '';
|
|
39
|
-
this.tooltipDisplay = 'none';
|
|
40
|
-
// these properties don't need to be tracked for changes
|
|
41
|
-
this._minDate = 0;
|
|
42
|
-
this._maxDate = 0;
|
|
43
|
-
this._dragOffset = 0;
|
|
44
|
-
this._histWidth = 0;
|
|
45
|
-
this._numBins = 0;
|
|
46
|
-
this._binWidth = 0;
|
|
47
|
-
this._histData = [];
|
|
48
|
-
// use arrow functions (rather than standard JS class instance methods) so
|
|
49
|
-
// that `this` is bound to the histogramDateRange object and not the event
|
|
50
|
-
// target. for more info see
|
|
51
|
-
// https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners
|
|
52
|
-
this.drag = (e) => {
|
|
53
|
-
// prevent selecting text or other ranges while dragging, especially in Safari
|
|
54
|
-
e.preventDefault();
|
|
55
|
-
this.setDragOffset(e);
|
|
56
|
-
this.container.classList.add('dragging');
|
|
57
|
-
window.addEventListener('pointermove', this.move);
|
|
58
|
-
window.addEventListener('pointerup', this.drop);
|
|
59
|
-
window.addEventListener('pointercancel', this.drop);
|
|
60
|
-
};
|
|
61
|
-
this.drop = () => {
|
|
62
|
-
this.container.classList.remove('dragging');
|
|
63
|
-
window.removeEventListener('pointermove', this.move);
|
|
64
|
-
window.removeEventListener('pointerup', this.drop);
|
|
65
|
-
window.removeEventListener('pointercancel', this.drop);
|
|
66
|
-
};
|
|
67
|
-
this.move = (e) => {
|
|
68
|
-
const newX = e.offsetX - this._dragOffset;
|
|
69
|
-
const slider = this._currentSlider;
|
|
70
|
-
return slider.id === 'slider-min'
|
|
71
|
-
? this.setMinSlider(newX)
|
|
72
|
-
: this.setMaxSlider(newX);
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
/* eslint-enable lines-between-class-members */
|
|
76
|
-
firstUpdated() {
|
|
77
|
-
var _a, _b, _c, _d, _e;
|
|
78
|
-
this.minSliderX = this.sliderWidth;
|
|
79
|
-
this.maxSliderX = this.width - this.sliderWidth;
|
|
80
|
-
this._minDate = dayjs((_a = this.data) === null || _a === void 0 ? void 0 : _a.minDate).valueOf();
|
|
81
|
-
this._maxDate = dayjs((_b = this.data) === null || _b === void 0 ? void 0 : _b.maxDate).valueOf();
|
|
82
|
-
this._histWidth = this.width - this.sliderWidth * 2;
|
|
83
|
-
this._numBins = (_e = (_d = (_c = this.data) === null || _c === void 0 ? void 0 : _c.bins) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 1;
|
|
84
|
-
this._binWidth = this._histWidth / this._numBins;
|
|
85
|
-
this._histData = this.generateHistData();
|
|
86
|
-
}
|
|
87
|
-
generateHistData() {
|
|
88
|
-
if (!this.data) {
|
|
89
|
-
return [];
|
|
90
|
-
}
|
|
91
|
-
const minValue = Math.min(...this.data.bins);
|
|
92
|
-
const maxValue = Math.max(...this.data.bins);
|
|
93
|
-
const valueScale = this.height / Math.log1p(maxValue - minValue);
|
|
94
|
-
const dateScale = this.dateRange / this._numBins;
|
|
95
|
-
return this.data.bins.map((v, i) => {
|
|
96
|
-
return {
|
|
97
|
-
value: v,
|
|
98
|
-
height: Math.floor(Math.log1p(v) * valueScale),
|
|
99
|
-
binStart: `${dayjs(i * dateScale + this._minDate).format(this.dateFormat)}`,
|
|
100
|
-
binEnd: `${dayjs((i + 1) * dateScale + this._minDate).format(this.dateFormat)}`,
|
|
101
|
-
};
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
get dateRange() {
|
|
105
|
-
return this._maxDate - this._minDate;
|
|
106
|
-
}
|
|
107
|
-
showTooltip(e) {
|
|
108
|
-
if (Array.from(this.container.classList).includes('dragging')) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const target = e.currentTarget;
|
|
112
|
-
const x = target.x.baseVal.value + this.sliderWidth / 2;
|
|
113
|
-
const data = target.dataset;
|
|
114
|
-
const itemsText = `item${data.numItems !== '1' ? 's' : ''}`;
|
|
115
|
-
this.tooltipOffset =
|
|
116
|
-
x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;
|
|
117
|
-
this.tooltipContent = html `
|
|
118
|
-
${data.numItems} ${itemsText}<br />
|
|
119
|
-
${data.binStart} - ${data.binEnd}
|
|
120
|
-
`;
|
|
121
|
-
this.tooltipDisplay = 'block';
|
|
122
|
-
}
|
|
123
|
-
hideTooltip() {
|
|
124
|
-
this.tooltipContent = '';
|
|
125
|
-
this.tooltipDisplay = 'none';
|
|
126
|
-
}
|
|
127
|
-
// find position of pointer in relation to the current slider
|
|
128
|
-
setDragOffset(e) {
|
|
129
|
-
this._currentSlider = e.currentTarget;
|
|
130
|
-
const sliderX = this._currentSlider.id === 'slider-min'
|
|
131
|
-
? this.minSliderX
|
|
132
|
-
: this.maxSliderX;
|
|
133
|
-
this._dragOffset = e.offsetX - sliderX;
|
|
134
|
-
// work around Firefox issue where e.offsetX seems to be not based on current
|
|
135
|
-
// element but on background element
|
|
136
|
-
if (this._dragOffset > this.sliderWidth ||
|
|
137
|
-
this._dragOffset < -this.sliderWidth) {
|
|
138
|
-
this._dragOffset = 0;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
setMinSlider(newX) {
|
|
142
|
-
const toSet = Math.max(newX, this.sliderWidth);
|
|
143
|
-
this.minSliderX = Math.min(toSet, this.maxSliderX);
|
|
144
|
-
}
|
|
145
|
-
setMaxSlider(newX) {
|
|
146
|
-
const toSet = Math.max(newX, this.minSliderX);
|
|
147
|
-
this.maxSliderX = Math.min(toSet, this.width - this.sliderWidth);
|
|
148
|
-
}
|
|
149
|
-
translatePositionToDate(x) {
|
|
150
|
-
const milliseconds = ((x - this.sliderWidth) * this.dateRange) / this._histWidth;
|
|
151
|
-
const date = dayjs(this._minDate + milliseconds);
|
|
152
|
-
return date.format(this.dateFormat);
|
|
153
|
-
}
|
|
154
|
-
translateDateToPosition(date) {
|
|
155
|
-
const milliseconds = dayjs(date).valueOf();
|
|
156
|
-
if (!milliseconds) {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
// translate where we are within the date range into what the new x-position
|
|
160
|
-
// of the slider should be
|
|
161
|
-
return (this.sliderWidth +
|
|
162
|
-
((milliseconds - this._minDate) * this._histWidth) / this.dateRange);
|
|
163
|
-
}
|
|
164
|
-
handleMinDateInput(e) {
|
|
165
|
-
const target = e.currentTarget;
|
|
166
|
-
const newX = this.translateDateToPosition(target.value);
|
|
167
|
-
if (newX) {
|
|
168
|
-
this.setMinSlider(newX);
|
|
169
|
-
}
|
|
170
|
-
target.value = this.minInputValue;
|
|
171
|
-
}
|
|
172
|
-
handleMaxDateInput(e) {
|
|
173
|
-
const target = e.currentTarget;
|
|
174
|
-
const newX = this.translateDateToPosition(target.value);
|
|
175
|
-
if (newX) {
|
|
176
|
-
this.setMaxSlider(newX);
|
|
177
|
-
}
|
|
178
|
-
target.value = this.maxInputValue;
|
|
179
|
-
}
|
|
180
|
-
get minInputValue() {
|
|
181
|
-
return this.translatePositionToDate(this.minSliderX);
|
|
182
|
-
}
|
|
183
|
-
get maxInputValue() {
|
|
184
|
-
return this.translatePositionToDate(this.maxSliderX);
|
|
185
|
-
}
|
|
186
|
-
get minSliderTemplate() {
|
|
187
|
-
// width/height in pixels of curved part of the sliders (like
|
|
188
|
-
// border-radius); used as part of a SVG quadratic curve. see
|
|
189
|
-
// https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands
|
|
190
|
-
const c = SLIDER_CORNER_SIZE;
|
|
191
|
-
const sliderShape = `
|
|
192
|
-
M${this.minSliderX},0
|
|
193
|
-
h-${this.sliderWidth - c}
|
|
194
|
-
q-${c},0 -${c},${c}
|
|
195
|
-
v${this.height - c * 2}
|
|
196
|
-
q0,${c} ${c},${c}
|
|
197
|
-
h${this.sliderWidth - c}
|
|
198
|
-
`;
|
|
199
|
-
return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);
|
|
200
|
-
}
|
|
201
|
-
get maxSliderTemplate() {
|
|
202
|
-
const c = SLIDER_CORNER_SIZE;
|
|
203
|
-
const sliderShape = `
|
|
204
|
-
M${this.maxSliderX},0
|
|
205
|
-
h${this.sliderWidth - c}
|
|
206
|
-
q${c},0 ${c},${c}
|
|
207
|
-
v${this.height - c * 2}
|
|
208
|
-
q0,${c} -${c},${c}
|
|
209
|
-
h-${this.sliderWidth - c}
|
|
210
|
-
`;
|
|
211
|
-
return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);
|
|
212
|
-
}
|
|
213
|
-
generateSliderSVG(sliderPositionX, id, sliderShape) {
|
|
214
|
-
// whether the curved part of the slider is facing towards the left (1), ie
|
|
215
|
-
// minimum, or facing towards the right (-1), ie maximum
|
|
216
|
-
const k = id === 'slider-min' ? 1 : -1;
|
|
217
|
-
return svg `
|
|
218
|
-
<svg
|
|
219
|
-
id="${id}"
|
|
220
|
-
@pointerdown="${this.drag}"
|
|
221
|
-
>
|
|
222
|
-
<path d="${sliderShape} z" fill="${sliderFill}" />
|
|
223
|
-
<rect
|
|
224
|
-
x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k}"
|
|
225
|
-
y="${this.height / 3}"
|
|
226
|
-
width="1"
|
|
227
|
-
height="${this.height / 3}"
|
|
228
|
-
fill="white"
|
|
229
|
-
/>
|
|
230
|
-
<rect
|
|
231
|
-
x="${sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k}"
|
|
232
|
-
y="${this.height / 3}"
|
|
233
|
-
width="1"
|
|
234
|
-
height="${this.height / 3}"
|
|
235
|
-
fill="white"
|
|
236
|
-
/>
|
|
237
|
-
</svg>
|
|
238
|
-
`;
|
|
239
|
-
}
|
|
240
|
-
get selectedRangeTemplate() {
|
|
241
|
-
return svg `
|
|
242
|
-
<rect
|
|
243
|
-
x="${this.minSliderX}"
|
|
244
|
-
y="0"
|
|
245
|
-
width="${this.maxSliderX - this.minSliderX}"
|
|
246
|
-
height="${this.height}"
|
|
247
|
-
fill="${selectedRangeFill}"
|
|
248
|
-
/>`;
|
|
249
|
-
}
|
|
250
|
-
get histogramTemplate() {
|
|
251
|
-
const xScale = this._histWidth / this._numBins;
|
|
252
|
-
const barWidth = xScale - 1;
|
|
253
|
-
let x = this.sliderWidth; // start at the left edge of the histogram
|
|
254
|
-
return this._histData.map(data => {
|
|
255
|
-
const bar = svg `
|
|
256
|
-
<rect
|
|
257
|
-
class="bar"
|
|
258
|
-
x="${x}"
|
|
259
|
-
y="${this.height - data.height}"
|
|
260
|
-
width="${barWidth}"
|
|
261
|
-
height="${data.height}"
|
|
262
|
-
@pointerenter="${this.showTooltip}"
|
|
263
|
-
@pointerleave="${this.hideTooltip}"
|
|
264
|
-
fill="${x >= this.minSliderX && x <= this.maxSliderX
|
|
265
|
-
? barIncludedFill
|
|
266
|
-
: barExcludedFill}"
|
|
267
|
-
data-num-items="${data.value}"
|
|
268
|
-
data-bin-start="${data.binStart}"
|
|
269
|
-
data-bin-end="${data.binEnd}"
|
|
270
|
-
/>`;
|
|
271
|
-
x += xScale;
|
|
272
|
-
return bar;
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
get minInputTemplate() {
|
|
276
|
-
return html `
|
|
277
|
-
<input
|
|
278
|
-
id="date-min"
|
|
279
|
-
placeholder="${DATE_FORMAT}"
|
|
280
|
-
type="text"
|
|
281
|
-
@change="${this.handleMinDateInput}"
|
|
282
|
-
.value="${this.minInputValue}"
|
|
283
|
-
/>
|
|
284
|
-
`;
|
|
285
|
-
}
|
|
286
|
-
get maxInputTemplate() {
|
|
287
|
-
return html `
|
|
288
|
-
<input
|
|
289
|
-
id="date-max"
|
|
290
|
-
placeholder="${DATE_FORMAT}"
|
|
291
|
-
type="text"
|
|
292
|
-
@change="${this.handleMaxDateInput}"
|
|
293
|
-
.value="${this.maxInputValue}"
|
|
294
|
-
/>
|
|
295
|
-
`;
|
|
296
|
-
}
|
|
297
|
-
get tooltipTemplate() {
|
|
298
|
-
return html `
|
|
299
|
-
<style>
|
|
300
|
-
#tooltip {
|
|
301
|
-
width: ${this.tooltipWidth}px;
|
|
302
|
-
height: ${this.tooltipHeight}px;
|
|
303
|
-
top: ${-9 - this.tooltipHeight}px;
|
|
304
|
-
left: ${this.tooltipOffset}px;
|
|
305
|
-
display: ${this.tooltipDisplay};
|
|
306
|
-
}
|
|
307
|
-
#tooltip:after {
|
|
308
|
-
left: ${this.tooltipWidth / 2}px;
|
|
309
|
-
}
|
|
310
|
-
</style>
|
|
311
|
-
<div id="tooltip">${this.tooltipContent}</div>
|
|
312
|
-
`;
|
|
313
|
-
}
|
|
314
|
-
render() {
|
|
315
|
-
if (!this.data || !this._histData) {
|
|
316
|
-
return html `no data`;
|
|
317
|
-
}
|
|
318
|
-
return html `
|
|
319
|
-
<div id="container" class="noselect" style="width: ${this.width}px">
|
|
320
|
-
${this.tooltipTemplate}
|
|
321
|
-
<svg
|
|
322
|
-
width="${this.width}"
|
|
323
|
-
height="${this.height}"
|
|
324
|
-
@pointerleave="${this.drop}"
|
|
325
|
-
>
|
|
326
|
-
${this.selectedRangeTemplate}
|
|
327
|
-
<svg id="histogram">${this.histogramTemplate}</svg>
|
|
328
|
-
${this.minSliderTemplate} ${this.maxSliderTemplate}
|
|
329
|
-
</svg>
|
|
330
|
-
<div id="inputs">
|
|
331
|
-
${this.minInputTemplate}
|
|
332
|
-
<div class="dash">-</div>
|
|
333
|
-
${this.maxInputTemplate}
|
|
334
|
-
</div>
|
|
335
|
-
</div>
|
|
336
|
-
`;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
HistogramDateRange.styles = css `
|
|
340
|
-
#container {
|
|
341
|
-
margin: 0;
|
|
342
|
-
touch-action: none;
|
|
343
|
-
position: relative;
|
|
344
|
-
}
|
|
345
|
-
/* prevent selection from interfering with tooltip, especially on mobile */
|
|
346
|
-
/* https://stackoverflow.com/a/4407335/1163042 */
|
|
347
|
-
.noselect {
|
|
348
|
-
-webkit-touch-callout: none; /* iOS Safari */
|
|
349
|
-
-webkit-user-select: none; /* Safari */
|
|
350
|
-
-moz-user-select: none; /* Old versions of Firefox */
|
|
351
|
-
-ms-user-select: none; /* Internet Explorer/Edge */
|
|
352
|
-
user-select: none; /* current Chrome, Edge, Opera and Firefox */
|
|
353
|
-
}
|
|
354
|
-
.bar:hover {
|
|
355
|
-
fill-opacity: 0.7;
|
|
356
|
-
}
|
|
357
|
-
/****** histogram ********/
|
|
358
|
-
#tooltip {
|
|
359
|
-
position: absolute;
|
|
360
|
-
background: ${tooltipBackgroundColor};
|
|
361
|
-
color: ${tooltipTextColor};
|
|
362
|
-
text-align: center;
|
|
363
|
-
border-radius: 3px;
|
|
364
|
-
padding: 2px;
|
|
365
|
-
font-size: ${tooltipFontSize};
|
|
366
|
-
font-family: sans-serif;
|
|
367
|
-
touch-action: none;
|
|
368
|
-
pointer-events: none;
|
|
369
|
-
}
|
|
370
|
-
#tooltip:after {
|
|
371
|
-
content: '';
|
|
372
|
-
position: absolute;
|
|
373
|
-
margin-left: -5px;
|
|
374
|
-
top: 100%;
|
|
375
|
-
/* arrow */
|
|
376
|
-
border: 5px solid ${tooltipTextColor};
|
|
377
|
-
border-color: ${tooltipBackgroundColor} transparent transparent
|
|
378
|
-
transparent;
|
|
379
|
-
}
|
|
380
|
-
/****** slider ********/
|
|
381
|
-
.draggable:hover {
|
|
382
|
-
cursor: grab;
|
|
383
|
-
}
|
|
384
|
-
.dragging {
|
|
385
|
-
cursor: grabbing !important;
|
|
386
|
-
}
|
|
387
|
-
/****** inputs ********/
|
|
388
|
-
#inputs {
|
|
389
|
-
display: flex;
|
|
390
|
-
justify-content: center;
|
|
391
|
-
}
|
|
392
|
-
#inputs .dash {
|
|
393
|
-
position: relative;
|
|
394
|
-
bottom: -1px;
|
|
395
|
-
}
|
|
396
|
-
input {
|
|
397
|
-
width: ${inputWidth};
|
|
398
|
-
margin: 0 3px;
|
|
399
|
-
border: ${inputBorder};
|
|
400
|
-
border-radius: 2px !important;
|
|
401
|
-
text-align: center;
|
|
402
|
-
font-size: ${inputFontSize};
|
|
403
|
-
}
|
|
404
|
-
`;
|
|
405
|
-
__decorate([
|
|
406
|
-
property({ type: Number })
|
|
407
|
-
], HistogramDateRange.prototype, "width", void 0);
|
|
408
|
-
__decorate([
|
|
409
|
-
property({ type: Number })
|
|
410
|
-
], HistogramDateRange.prototype, "height", void 0);
|
|
411
|
-
__decorate([
|
|
412
|
-
property({ type: Number })
|
|
413
|
-
], HistogramDateRange.prototype, "sliderWidth", void 0);
|
|
414
|
-
__decorate([
|
|
415
|
-
property({ type: Number })
|
|
416
|
-
], HistogramDateRange.prototype, "tooltipWidth", void 0);
|
|
417
|
-
__decorate([
|
|
418
|
-
property({ type: Number })
|
|
419
|
-
], HistogramDateRange.prototype, "tooltipHeight", void 0);
|
|
420
|
-
__decorate([
|
|
421
|
-
property({ type: String })
|
|
422
|
-
], HistogramDateRange.prototype, "dateFormat", void 0);
|
|
423
|
-
__decorate([
|
|
424
|
-
property({ type: Object })
|
|
425
|
-
], HistogramDateRange.prototype, "data", void 0);
|
|
426
|
-
__decorate([
|
|
427
|
-
internalProperty()
|
|
428
|
-
], HistogramDateRange.prototype, "minSliderX", void 0);
|
|
429
|
-
__decorate([
|
|
430
|
-
internalProperty()
|
|
431
|
-
], HistogramDateRange.prototype, "maxSliderX", void 0);
|
|
432
|
-
__decorate([
|
|
433
|
-
internalProperty()
|
|
434
|
-
], HistogramDateRange.prototype, "tooltipOffset", void 0);
|
|
435
|
-
__decorate([
|
|
436
|
-
internalProperty()
|
|
437
|
-
], HistogramDateRange.prototype, "tooltipContent", void 0);
|
|
438
|
-
__decorate([
|
|
439
|
-
internalProperty()
|
|
440
|
-
], HistogramDateRange.prototype, "tooltipDisplay", void 0);
|
|
441
|
-
__decorate([
|
|
442
|
-
query('#tooltip')
|
|
443
|
-
], HistogramDateRange.prototype, "tooltip", void 0);
|
|
444
|
-
__decorate([
|
|
445
|
-
query('#container')
|
|
446
|
-
], HistogramDateRange.prototype, "container", void 0);
|
|
447
|
-
//# sourceMappingURL=HistogramDateRange.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"HistogramDateRange.js","sourceRoot":"","sources":["../../src/HistogramDateRange.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n html,\n svg,\n css,\n internalProperty,\n LitElement,\n TemplateResult,\n SVGTemplateResult,\n property,\n query,\n} from 'lit-element';\nimport dayjs from 'dayjs/esm/index.js';\n\n// these values can be overridden via the component's HTML (camelCased) attributes\nconst WIDTH = 180;\nconst HEIGHT = 40;\nconst SLIDER_WIDTH = 10;\nconst TOOLTIP_WIDTH = 125;\nconst TOOLTIP_HEIGHT = 30;\nconst DATE_FORMAT = 'M/D/YYYY';\n\n// this constant is not set up to be overridden\nconst SLIDER_CORNER_SIZE = 4;\n\n// these CSS custom props can be overridden from the HTML that is invoking this component\nconst sliderFill = 'var(--histogramDateRangeSliderFill, #4B65FE)';\nconst selectedRangeFill = 'var(--histogramDateRangeSelectedRangeFill, #DBE0FF)';\nconst barIncludedFill = 'var(--histogramDateRangeBarIncludedFill, #2C2C2C)';\nconst barExcludedFill = 'var(--histogramDateRangeBarExcludedFill, #CCCCCC)';\nconst inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;\nconst inputWidth = css`var(--histogramDateRangeInputWidth, 70px)`;\nconst inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;\nconst tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;\nconst tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;\nconst tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;\n\ntype SliderIds = 'slider-min' | 'slider-max';\n\ninterface HistogramInputData {\n minDate: string;\n maxDate: string;\n bins: number[];\n}\n\ninterface HistogramItem {\n value: number;\n height: number;\n binStart: string;\n binEnd: string;\n}\n\nexport class HistogramDateRange extends LitElement {\n /* eslint-disable lines-between-class-members */\n\n // these properties are intended to be passed in as attributes\n @property({ type: Number }) width = WIDTH;\n @property({ type: Number }) height = HEIGHT;\n @property({ type: Number }) sliderWidth = SLIDER_WIDTH;\n @property({ type: Number }) tooltipWidth = TOOLTIP_WIDTH;\n @property({ type: Number }) tooltipHeight = TOOLTIP_HEIGHT;\n @property({ type: String }) dateFormat = DATE_FORMAT;\n @property({ type: Object }) data?: HistogramInputData;\n\n @internalProperty() minSliderX: number = 0;\n @internalProperty() maxSliderX: number = 0;\n @internalProperty() tooltipOffset = 0;\n @internalProperty() tooltipContent: TemplateResult | '' = '';\n @internalProperty() tooltipDisplay: 'block' | 'none' = 'none';\n\n @query('#tooltip') tooltip!: HTMLDivElement;\n @query('#container') container!: HTMLDivElement;\n\n // these properties don't need to be tracked for changes\n private _minDate: number = 0;\n private _maxDate: number = 0;\n private _dragOffset: number = 0;\n private _histWidth: number = 0;\n private _numBins: number = 0;\n private _binWidth: number = 0;\n private _currentSlider?: SVGRectElement;\n private _histData: HistogramItem[] = [];\n\n /* eslint-enable lines-between-class-members */\n\n firstUpdated(): void {\n this.minSliderX = this.sliderWidth;\n this.maxSliderX = this.width - this.sliderWidth;\n this._minDate = dayjs(this.data?.minDate).valueOf();\n this._maxDate = dayjs(this.data?.maxDate).valueOf();\n this._histWidth = this.width - this.sliderWidth * 2;\n this._numBins = this.data?.bins?.length ?? 1;\n this._binWidth = this._histWidth / this._numBins;\n this._histData = this.generateHistData();\n }\n\n private generateHistData(): HistogramItem[] {\n if (!this.data) {\n return [];\n }\n const minValue = Math.min(...this.data.bins);\n const maxValue = Math.max(...this.data.bins);\n const valueScale = this.height / Math.log1p(maxValue - minValue);\n const dateScale = this.dateRange / this._numBins;\n return this.data.bins.map((v: number, i: number) => {\n return {\n value: v,\n height: Math.floor(Math.log1p(v) * valueScale),\n binStart: `${dayjs(i * dateScale + this._minDate).format(\n this.dateFormat\n )}`,\n binEnd: `${dayjs((i + 1) * dateScale + this._minDate).format(\n this.dateFormat\n )}`,\n };\n });\n }\n\n private get dateRange(): number {\n return this._maxDate - this._minDate;\n }\n\n private showTooltip(e: PointerEvent): void {\n if (Array.from(this.container.classList).includes('dragging')) {\n return;\n }\n const target = e.currentTarget as SVGRectElement;\n const x = target.x.baseVal.value + this.sliderWidth / 2;\n const data = target.dataset;\n const itemsText = `item${data.numItems !== '1' ? 's' : ''}`;\n\n this.tooltipOffset =\n x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;\n\n this.tooltipContent = html`\n ${data.numItems} ${itemsText}<br />\n ${data.binStart} - ${data.binEnd}\n `;\n this.tooltipDisplay = 'block';\n }\n\n private hideTooltip(): void {\n this.tooltipContent = '';\n this.tooltipDisplay = 'none';\n }\n\n // use arrow functions (rather than standard JS class instance methods) so\n // that `this` is bound to the histogramDateRange object and not the event\n // target. for more info see\n // https://lit-element.polymer-project.org/guide/events#using-this-in-event-listeners\n private drag = (e: PointerEvent): void => {\n // prevent selecting text or other ranges while dragging, especially in Safari\n e.preventDefault();\n\n this.setDragOffset(e);\n this.container.classList.add('dragging');\n\n window.addEventListener('pointermove', this.move);\n window.addEventListener('pointerup', this.drop);\n window.addEventListener('pointercancel', this.drop);\n };\n\n private drop = (): void => {\n this.container.classList.remove('dragging');\n\n window.removeEventListener('pointermove', this.move);\n window.removeEventListener('pointerup', this.drop);\n window.removeEventListener('pointercancel', this.drop);\n };\n\n private move = (e: PointerEvent): void => {\n const newX = e.offsetX - this._dragOffset;\n const slider = this._currentSlider as SVGRectElement;\n return (slider.id as SliderIds) === 'slider-min'\n ? this.setMinSlider(newX)\n : this.setMaxSlider(newX);\n };\n\n // find position of pointer in relation to the current slider\n private setDragOffset(e: PointerEvent): void {\n this._currentSlider = e.currentTarget as SVGRectElement;\n const sliderX =\n (this._currentSlider.id as SliderIds) === 'slider-min'\n ? this.minSliderX\n : this.maxSliderX;\n this._dragOffset = e.offsetX - sliderX;\n // work around Firefox issue where e.offsetX seems to be not based on current\n // element but on background element\n if (\n this._dragOffset > this.sliderWidth ||\n this._dragOffset < -this.sliderWidth\n ) {\n this._dragOffset = 0;\n }\n }\n\n private setMinSlider(newX: number): void {\n const toSet = Math.max(newX, this.sliderWidth);\n this.minSliderX = Math.min(toSet, this.maxSliderX);\n }\n\n private setMaxSlider(newX: number): void {\n const toSet = Math.max(newX, this.minSliderX);\n this.maxSliderX = Math.min(toSet, this.width - this.sliderWidth);\n }\n\n private translatePositionToDate(x: number): string {\n const milliseconds =\n ((x - this.sliderWidth) * this.dateRange) / this._histWidth;\n const date = dayjs(this._minDate + milliseconds);\n return date.format(this.dateFormat);\n }\n\n private translateDateToPosition(date: string): number | null {\n const milliseconds: number | undefined = dayjs(date).valueOf();\n if (!milliseconds) {\n return null;\n }\n // translate where we are within the date range into what the new x-position\n // of the slider should be\n return (\n this.sliderWidth +\n ((milliseconds - this._minDate) * this._histWidth) / this.dateRange\n );\n }\n\n private handleMinDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n const newX = this.translateDateToPosition(target.value);\n if (newX) {\n this.setMinSlider(newX);\n }\n target.value = this.minInputValue;\n }\n\n private handleMaxDateInput(e: InputEvent): void {\n const target = e.currentTarget as HTMLInputElement;\n const newX = this.translateDateToPosition(target.value);\n if (newX) {\n this.setMaxSlider(newX);\n }\n target.value = this.maxInputValue;\n }\n\n private get minInputValue() {\n return this.translatePositionToDate(this.minSliderX);\n }\n\n private get maxInputValue() {\n return this.translatePositionToDate(this.maxSliderX);\n }\n\n private get minSliderTemplate(): SVGTemplateResult {\n // width/height in pixels of curved part of the sliders (like\n // border-radius); used as part of a SVG quadratic curve. see\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#curve_commands\n const c = SLIDER_CORNER_SIZE;\n\n const sliderShape = `\n M${this.minSliderX},0\n h-${this.sliderWidth - c}\n q-${c},0 -${c},${c}\n v${this.height - c * 2}\n q0,${c} ${c},${c}\n h${this.sliderWidth - c}\n `;\n return this.generateSliderSVG(this.minSliderX, 'slider-min', sliderShape);\n }\n\n private get maxSliderTemplate(): SVGTemplateResult {\n const c = SLIDER_CORNER_SIZE;\n const sliderShape = `\n M${this.maxSliderX},0\n h${this.sliderWidth - c}\n q${c},0 ${c},${c}\n v${this.height - c * 2}\n q0,${c} -${c},${c}\n h-${this.sliderWidth - c}\n `;\n return this.generateSliderSVG(this.maxSliderX, 'slider-max', sliderShape);\n }\n\n private generateSliderSVG(\n sliderPositionX: number,\n id: SliderIds,\n sliderShape: string\n ): SVGTemplateResult {\n // whether the curved part of the slider is facing towards the left (1), ie\n // minimum, or facing towards the right (-1), ie maximum\n const k = id === 'slider-min' ? 1 : -1;\n\n return svg`\n <svg\n id=\"${id}\"\n @pointerdown=\"${this.drag}\"\n >\n <path d=\"${sliderShape} z\" fill=\"${sliderFill}\" />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n <rect\n x=\"${\n sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.6 * k\n }\"\n y=\"${this.height / 3}\"\n width=\"1\"\n height=\"${this.height / 3}\"\n fill=\"white\"\n />\n </svg>\n `;\n }\n\n get selectedRangeTemplate(): SVGTemplateResult {\n return svg`\n <rect\n x=\"${this.minSliderX}\"\n y=\"0\"\n width=\"${this.maxSliderX - this.minSliderX}\"\n height=\"${this.height}\"\n fill=\"${selectedRangeFill}\"\n />`;\n }\n\n get histogramTemplate(): SVGTemplateResult[] {\n const xScale = this._histWidth / this._numBins;\n const barWidth = xScale - 1;\n let x = this.sliderWidth; // start at the left edge of the histogram\n return this._histData.map(data => {\n const bar = svg`\n <rect\n class=\"bar\"\n x=\"${x}\"\n y=\"${this.height - data.height}\"\n width=\"${barWidth}\"\n height=\"${data.height}\"\n @pointerenter=\"${this.showTooltip}\"\n @pointerleave=\"${this.hideTooltip}\"\n fill=\"${\n x >= this.minSliderX && x <= this.maxSliderX\n ? barIncludedFill\n : barExcludedFill\n }\"\n data-num-items=\"${data.value}\"\n data-bin-start=\"${data.binStart}\"\n data-bin-end=\"${data.binEnd}\"\n />`;\n x += xScale;\n return bar;\n });\n }\n\n get minInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-min\"\n placeholder=\"${DATE_FORMAT}\"\n type=\"text\"\n @change=\"${this.handleMinDateInput}\"\n .value=\"${this.minInputValue}\"\n />\n `;\n }\n\n get maxInputTemplate(): TemplateResult {\n return html`\n <input\n id=\"date-max\"\n placeholder=\"${DATE_FORMAT}\"\n type=\"text\"\n @change=\"${this.handleMaxDateInput}\"\n .value=\"${this.maxInputValue}\"\n />\n `;\n }\n\n get tooltipTemplate(): TemplateResult {\n return html`\n <style>\n #tooltip {\n width: ${this.tooltipWidth}px;\n height: ${this.tooltipHeight}px;\n top: ${-9 - this.tooltipHeight}px;\n left: ${this.tooltipOffset}px;\n display: ${this.tooltipDisplay};\n }\n #tooltip:after {\n left: ${this.tooltipWidth / 2}px;\n }\n </style>\n <div id=\"tooltip\">${this.tooltipContent}</div>\n `;\n }\n\n static styles = css`\n #container {\n margin: 0;\n touch-action: none;\n position: relative;\n }\n /* prevent selection from interfering with tooltip, especially on mobile */\n /* https://stackoverflow.com/a/4407335/1163042 */\n .noselect {\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* current Chrome, Edge, Opera and Firefox */\n }\n .bar:hover {\n fill-opacity: 0.7;\n }\n /****** histogram ********/\n #tooltip {\n position: absolute;\n background: ${tooltipBackgroundColor};\n color: ${tooltipTextColor};\n text-align: center;\n border-radius: 3px;\n padding: 2px;\n font-size: ${tooltipFontSize};\n font-family: sans-serif;\n touch-action: none;\n pointer-events: none;\n }\n #tooltip:after {\n content: '';\n position: absolute;\n margin-left: -5px;\n top: 100%;\n /* arrow */\n border: 5px solid ${tooltipTextColor};\n border-color: ${tooltipBackgroundColor} transparent transparent\n transparent;\n }\n /****** slider ********/\n .draggable:hover {\n cursor: grab;\n }\n .dragging {\n cursor: grabbing !important;\n }\n /****** inputs ********/\n #inputs {\n display: flex;\n justify-content: center;\n }\n #inputs .dash {\n position: relative;\n bottom: -1px;\n }\n input {\n width: ${inputWidth};\n margin: 0 3px;\n border: ${inputBorder};\n border-radius: 2px !important;\n text-align: center;\n font-size: ${inputFontSize};\n }\n `;\n\n render(): TemplateResult {\n if (!this.data || !this._histData) {\n return html`no data`;\n }\n return html`\n <div id=\"container\" class=\"noselect\" style=\"width: ${this.width}px\">\n ${this.tooltipTemplate}\n <svg\n width=\"${this.width}\"\n height=\"${this.height}\"\n @pointerleave=\"${this.drop}\"\n >\n ${this.selectedRangeTemplate}\n <svg id=\"histogram\">${this.histogramTemplate}</svg>\n ${this.minSliderTemplate} ${this.maxSliderTemplate}\n </svg>\n <div id=\"inputs\">\n ${this.minInputTemplate}\n <div class=\"dash\">-</div>\n ${this.maxInputTemplate}\n </div>\n </div>\n `;\n }\n}\n"]}
|