@protomaze/time 1.4.3 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/TimeSliderDemo.d.ts +12 -1
- package/TimeSliderDemo.js +1 -1
- package/common/TimeTools.d.ts +17 -5
- package/common/TimeTools.js +1 -1
- package/data/CompositeTimeSliderModel.js +1 -1
- package/data/TimeSliderBush.js +1 -1
- package/data/TimeSliderIntervalsModel.js +1 -1
- package/data/TimeSliderLanesModel.js +1 -1
- package/data/TimeSliderModel.js +1 -1
- package/data/TimeSliderPointsModel.js +1 -1
- package/data/TimeSliderRange.d.ts +8 -0
- package/data/TimeSliderRange.js +1 -1
- package/data/histogram/TimeSliderDynamicHistogram.js +1 -1
- package/data/histogram/TimeSliderFixedHistogram.js +1 -1
- package/data/histogram/TimeSliderHistogram.js +1 -1
- package/data/histogram/TimeSliderSplittingFixedHistogram.js +1 -1
- package/demo/Common.d.ts +5 -1
- package/demo/Common.js +1 -1
- package/demo/Metrics.d.ts +2 -2
- package/demo/Metrics.js +1 -1
- package/demo/Nasdaq.d.ts +5 -2
- package/demo/Nasdaq.js +1 -1
- package/demo/Quakes.d.ts +6 -3
- package/demo/Quakes.js +1 -1
- package/demo/QuakesFilters.d.ts +3 -1
- package/demo/QuakesFilters.js +1 -1
- package/demo/Random.d.ts +45 -35
- package/demo/Random.js +1 -1
- package/demo/Test.d.ts +5 -2
- package/demo/Test.js +1 -1
- package/demo/Wars.js +1 -1
- package/engine/TimeSlider.d.ts +131 -5
- package/engine/TimeSlider.js +1 -1
- package/engine/TimeSliderEngine.js +1 -1
- package/index.d.ts +62 -1
- package/index.js +1 -1
- package/layer/TimeSliderHistogramLayer.js +1 -1
- package/layer/TimeSliderHistogramLayerOld.js +1 -1
- package/layer/TimeSliderIntervalsLayer.js +1 -1
- package/layer/TimeSliderLayer.js +1 -1
- package/layer/TimeSliderLayerLoader.d.ts +2 -0
- package/layer/TimeSliderPointsLayer.js +1 -1
- package/package.json +60 -58
- package/react/DateLabelWithPicker.js +1 -1
- package/react/DateRangeLabelWithPicker.js +1 -1
- package/react/FullscreenButton.js +1 -1
- package/react/ReactTimeSlider.js +1 -1
- package/react/TimeLabelWithPicker.js +1 -1
- package/style/TimeSliderIntervalsStyle.d.ts +4 -0
- package/three/Three3DTimeSliderEngine.js +1 -1
- package/three/ThreeTimeSlider.js +1 -1
- package/three/ThreeTimeSliderEngine.js +1 -1
- package/three/layer/GrowingBufferGeometry.js +1 -1
- package/three/layer/GrowingInstanceMatrix.js +1 -1
- package/three/layer/Three3DIntervalsTimeLayerLoader.d.ts +2 -2
- package/three/layer/Three3DIntervalsTimeLayerLoader.js +1 -1
- package/three/layer/Three3DPointsTimeLayerLoader.d.ts +1 -2
- package/three/layer/Three3DPointsTimeLayerLoader.js +1 -1
- package/three/layer/ThreeIntervalsTimeLayerLoader.d.ts +2 -2
- package/three/layer/ThreeIntervalsTimeLayerLoader.js +1 -1
- package/three/layer/ThreePointsTimeLayerLoader.d.ts +1 -2
- package/three/layer/ThreePointsTimeLayerLoader.js +1 -1
- package/three/layer/ThreeTimeLayerLoader.js +1 -1
- package/three/react/ReactThreeTimeSlider.js +1 -1
- package/ticks/TimeTicksBar.d.ts +14 -1
- package/ticks/TimeTicksBar.js +1 -1
package/demo/Random.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as t}from"uuid";import{TimeSliderLanesModel as e}from"../data/TimeSliderLanesModel";import{TimeSliderPointsModel as o}from"../data/TimeSliderPointsModel";import{ONE_SECOND as n}from"../ticks/TimeSliderConstants";import{createDemoHistogramLayer as a,createDemoIntervalsLayer as r,createDemoPointsLayer as i}from"./Common";const
|
|
1
|
+
import{v4 as t}from"uuid";import{TimeSliderLanesModel as e}from"../data/TimeSliderLanesModel.js";import{TimeSliderPointsModel as o}from"../data/TimeSliderPointsModel.js";import{ONE_SECOND as n}from"../ticks/TimeSliderConstants.js";import{createDemoHistogramLayer as a,createDemoIntervalsLayer as r,createDemoPointsLayer as i}from"./Common.js";export function createRandomDemo(){const s=[],c=function(e){const n=new o;return n.name="Measurements",e.push(function(e){const o=setInterval(()=>{const o=Date.now()+10*Math.random(),n=5+90*generateRealisticY(.02*o,.1,.8);e.add({id:t(),t:o,v:n,name:"M#"+e.data.length+" ("+Math.round(n)+"%)"})},10);return()=>clearInterval(o)}(n)),n}(s),{model:l,styleMap:d}=function(o){const a=new e;a.name="Tracks";const{styleMap:r,stop:i}=function(e){const o=e,a=new Set,r=new Map,i=()=>{const e=getDistinctColors()[Math.floor(20*Math.random())],i=getDistinctColors()[Math.floor(20*Math.random())],s=t(),c={id:s,name:getRandomFunkyName(),t:[Date.now(),Date.now()]};return r.set(s,{fill:{color:e},border:{color:i}}),a.add(c),o.add(c),setTimeout(()=>{o.update(c,{t:[c.t[0],Date.now()]}),a.delete(c)},n+7*Math.random()*n),c};i();const s=7;let c=!0;const l=()=>{c&&(a.size<s&&Math.random()<1*Math.random()*(1-a.size/s)&&i(),a.forEach(t=>{o.update(t,{t:[t.t[0],Date.now()]})}),requestAnimationFrame(l))};return l(),{styleMap:r,stop:()=>c=!1}}(a);return o.push(i),{model:a,styleMap:r}}(s);return{single:[a([c,l],{min:.9,style:{weighted:!0}}),i(c,{min:.5,max:.9,style:{area:{color:"#df0",height:.2,opacity:1}}}),r(l,{max:.5})],multiple:[[i(c,{min:.25,max:1,style:{line:void 0,area:void 0}}),a([c],{min:0,max:.25,style:{weighted:!0,mode:{fixed:{duration:100}},inverted:!1}})],[i(c,{min:.5,max:1,style:{point:void 0,area:{color:"#df0",height:.2,opacity:1}}}),r(l,{min:0,max:.5,style:{border:{width:2,color:"#df0"}}})],[r(l,{max:.8,style:{border:{centered:!1,width:4}},styler:t=>d.get(t.id)}),a([l],{min:.9})]],stop:()=>s.forEach(t=>t())}}export function getDistinctColors(){return["#e6194B","#3cb44b","#ffe119","#4363d8","#f58231","#911eb4","#42d4f4","#bfef45","#f032e6","#808000","#fabed4","#469990","#dcbeff","#9A6324","#fffac8","#800000","#aaffc3","#ffd8b1","#000075","#a9a9a9"]}export function invertColor(t,e){const[o,n,a]=parseColor(t),r=void 0!==e?Math.max(0,Math.min(1,e)):1,i=t=>255*t;return`rgb(${i(1-o)}, ${i(1-n)}, ${i(1-a)}, ${r})`}export function parseColor(t){const e=document.createElement("canvas").getContext("2d");e.fillStyle=t,e.fillRect(0,0,1,1);const[o,n,a]=e.getImageData(0,0,1,1).data;return[o/255,n/255,a/255]}export function getRandomFunkyName(){const t=t=>t[Math.floor(Math.random()*t.length)];return`${t(["Funky","Groovy","Zany","Wacky","Spicy","Nifty","Bouncy","Chill","Snazzy","Sassy","Loopy","Trippy","Nerdy","Cranky","Fluffy","Quirky"])}${t(["Banana","Tofu","Octopus","Falcon","Pineapple","Robot","Llama","Pizza","Koala","Unicorn","Muffin","Cactus","Taco","Yeti","Squirrel","Donut"])}`}const s=256,c=new Array(2*s);export function generateRealisticY(t,e=.1,o=1){const n=function(t){const e=Math.floor(t),o=t-e,n=c[e&s-1],a=c[e+1&s-1],r=.5*(1-Math.cos(o*Math.PI));return n*(1-r)+a*r}(t*e),a=.5+(n-.5)*o;return Math.max(0,Math.min(1,a))}(()=>{for(let t=0;t<s;t++)c[t]=c[t+s]=Math.random()})();
|
package/demo/Test.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { TimeSliderElement } from "../data/TimeSliderElement";
|
|
2
2
|
import { TimeSliderModel } from "../data/TimeSliderModel";
|
|
3
3
|
import { TimeSliderHistogramLayerOld } from "../layer/TimeSliderHistogramLayerOld";
|
|
4
|
-
|
|
5
|
-
export declare
|
|
4
|
+
/** 10 000 seeded points in a histogram, for testing the histogram */
|
|
5
|
+
export declare function createTestDemo(): {
|
|
6
|
+
single: TimeSliderHistogramLayerOld<TimeSliderModel<TimeSliderElement>>[];
|
|
7
|
+
multiple: TimeSliderHistogramLayerOld<TimeSliderModel<TimeSliderElement>>[][];
|
|
8
|
+
};
|
package/demo/Test.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as t}from"uuid";import{TimeSliderPointsModel as e}from"../data/TimeSliderPointsModel";import{MAGNITUDE_COLORS as r}from"../style/TimeSliderColors";import{ONE_YEAR as i}from"../ticks/TimeSliderConstants";import{TimeSliderHistogramLayerOld as o}from"../layer/TimeSliderHistogramLayerOld";const s=
|
|
1
|
+
import{v4 as t}from"uuid";import{TimeSliderPointsModel as e}from"../data/TimeSliderPointsModel.js";import{MAGNITUDE_COLORS as r}from"../style/TimeSliderColors.js";import{ONE_YEAR as i}from"../ticks/TimeSliderConstants.js";import{TimeSliderHistogramLayerOld as o}from"../layer/TimeSliderHistogramLayerOld.js";const s=Array.from({length:10},(t,e)=>e.toString()),n=Array.from({length:20},(t,e)=>e.toString());export function createTestDemo(){const l=[function(t){const e=t=>a(10*t.attributes.test,s)+"",i=t=>a(t.v/10,s)+"",l=new o(t,{name:"Histogram",min:0,max:1,style:{loggin:!0,fill:{color:"#fff",opacity:.3},border:{color:"#fff",width:4,centered:!1},inverted:!1,mode:{fixedUnit:"month"},classOrder:n},classifier:e,styler:t=>{const e=r[parseInt(t.attributes?.classification||"0")];return{fill:{color:e},border:{color:e}}},labeler:t=>`Test #${parseInt(t.attributes?.classification||"0")}`,yAxis:{visible:!0,style:{labels:{position:"left"}}}});let m=!0,c=!1,d=!1;document.addEventListener("keypress",t=>{"t"===t.key&&(m=!1,l.histogram.classifier=i),"g"===t.key&&(m=!0,l.histogram.classifier=e)}),document.addEventListener("keydown",t=>{"y"===t.key&&(d=!0),"h"===t.key&&(c=!0)}),document.addEventListener("keyup",t=>{"y"===t.key&&(d=!1),"h"===t.key&&(c=!1)});let f=0;return setInterval(()=>{(d||c)&&(l.histogram.classifier=m?t=>a(10*t.attributes.test,s)+(t.attributes.ok<f?10:0)+"":t=>a(t.v/10,s)+(t.attributes.ok<f?10:0)+"");let t=0;d&&(t+=.05),c&&(t-=.05),f=Math.max(0,Math.min(1,f+t))},50),l}(function(){const r=(s=42,()=>{let t=s+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}),o=new e;var s;o.name="Test";for(let e=0;e<1e4;e++){const e={id:t(),t:Date.now()-r()*i,v:100*r(),attributes:{test:r(),ok:r()}};o.add(e)}return o}())];return{single:l,multiple:[l]}}function a(t,e){return Math.min(e.length-1,Math.max(0,Math.round(t)))}
|
package/demo/Wars.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as o}from"uuid";import{getTimeUnitRange as m}from"../common/TimeTools";import{TimeSliderLanesModel as r}from"../data/TimeSliderLanesModel";export const WARS_SINGLE_LAYERS=[];export const WARS_MULTI_LAYERS=[[],[]];
|
|
1
|
+
import{v4 as o}from"uuid";import{getTimeUnitRange as m}from"../common/TimeTools.js";import{TimeSliderLanesModel as r}from"../data/TimeSliderLanesModel.js";export const WARS_SINGLE_LAYERS=[];export const WARS_MULTI_LAYERS=[[],[]];
|
package/engine/TimeSlider.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TimeUnit } from '../common/TimeTools';
|
|
1
2
|
import { TimeSliderElement } from "../data/TimeSliderElement";
|
|
2
3
|
import { TimeSliderRange, TimeSliderTimeRange, TimeSliderTimeRangeWithDuration, TimeSliderValueRange } from "../data/TimeSliderRange";
|
|
3
4
|
import { TypedEventEmitter } from "../event/TypedEventEmitter";
|
|
@@ -8,16 +9,65 @@ import { TimeSliderEngine } from "./TimeSliderEngine";
|
|
|
8
9
|
export type TimeSliderHoverOptions = {
|
|
9
10
|
time?: boolean;
|
|
10
11
|
date?: boolean;
|
|
12
|
+
/** Set false to disable the built-in tooltip and render your own from the 'hover' event instead. Default true. */
|
|
13
|
+
tooltip?: boolean;
|
|
11
14
|
};
|
|
15
|
+
export type TimeSliderPickMode = 'element' | 'column';
|
|
12
16
|
export type TimeSliderSelectionOptions = {
|
|
13
17
|
highlight?: boolean;
|
|
14
18
|
label?: boolean;
|
|
19
|
+
/** Dims the time outside the range(s) set via setSelection(). Default true. */
|
|
20
|
+
shading?: boolean;
|
|
21
|
+
/** Dims inside the selected range(s) instead of outside. Default false. */
|
|
22
|
+
invertShading?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 'element' (default) picks elements near the cursor's time AND height, the
|
|
25
|
+
* existing behavior. 'column' picks every visible layer's element(s) whose
|
|
26
|
+
* time interval contains the cursor time, regardless of cursor height —
|
|
27
|
+
* for picking thin bars/bins by clicking anywhere in their column. Applies
|
|
28
|
+
* to both hover and click. See also setPickMode().
|
|
29
|
+
*/
|
|
30
|
+
pick?: TimeSliderPickMode;
|
|
31
|
+
/** Style of the column highlight band drawn on hover when pick is 'column'. */
|
|
32
|
+
columnBand?: {
|
|
33
|
+
color?: string;
|
|
34
|
+
opacity?: number;
|
|
35
|
+
};
|
|
15
36
|
};
|
|
16
37
|
export type TimeSliderSelection = {
|
|
17
38
|
layer: TimeSliderLayer;
|
|
18
39
|
elements: TimeSliderElement[];
|
|
19
40
|
};
|
|
20
|
-
export type
|
|
41
|
+
export type TimeSliderHoverInfo = {
|
|
42
|
+
elements: {
|
|
43
|
+
layer: TimeSliderLayer;
|
|
44
|
+
elements: TimeSliderElement[];
|
|
45
|
+
}[];
|
|
46
|
+
t: number;
|
|
47
|
+
clientX: number;
|
|
48
|
+
clientY: number;
|
|
49
|
+
};
|
|
50
|
+
/** Fired by clicking a tick label on the ticks bar (e.g. clicking "2023" while bins are months). unit is this library's best guess at the tick's granularity, via getMatchingTimeUnit — undefined if the range doesn't cleanly match one. */
|
|
51
|
+
export type TimeSliderTickClickInfo = {
|
|
52
|
+
startTime: number;
|
|
53
|
+
endTime: number;
|
|
54
|
+
unit?: TimeUnit;
|
|
55
|
+
};
|
|
56
|
+
/** Returns per-tick label overrides, e.g. to fade ticks outside a selection like a chart legend. */
|
|
57
|
+
export type TimeSliderTickLabelStyler = (range: {
|
|
58
|
+
startTime: number;
|
|
59
|
+
endTime: number;
|
|
60
|
+
}) => {
|
|
61
|
+
color?: string;
|
|
62
|
+
opacity?: number;
|
|
63
|
+
} | undefined;
|
|
64
|
+
/** A programmatic, draggable time-range selection (distinct from the click-driven element `select`/`'select'` event). startTime/endTime may be -Infinity/Infinity for an open-ended "before X" / "after X" range. */
|
|
65
|
+
export type TimeSliderSelectionRange = {
|
|
66
|
+
startTime: number;
|
|
67
|
+
endTime: number;
|
|
68
|
+
};
|
|
69
|
+
export type TimeSliderSelectionChangePhase = 'start' | 'drag' | 'end';
|
|
70
|
+
export type TimeSliderSelectRangeMode = 'zoom' | 'select' | 'createSelection';
|
|
21
71
|
export interface TimeSliderOptions {
|
|
22
72
|
showCurrent?: boolean;
|
|
23
73
|
showTicks?: boolean;
|
|
@@ -27,6 +77,16 @@ export interface TimeSliderOptions {
|
|
|
27
77
|
playSpeed?: number | 'auto';
|
|
28
78
|
hover?: TimeSliderHoverOptions;
|
|
29
79
|
selection?: TimeSliderSelectionOptions;
|
|
80
|
+
/** BCP-47 tag (e.g. 'de', 'en-GB'). Defaults to navigator.language. See also setLocale(). */
|
|
81
|
+
locale?: string;
|
|
82
|
+
/** 'calendarWeek' labels week ticks as ISO 8601 calendar weeks (e.g. "KW12") instead of a date range. Defaults to 'default' (unchanged behavior). */
|
|
83
|
+
weekLabel?: 'default' | 'calendarWeek';
|
|
84
|
+
/** Overrides the localized calendar-week prefix (e.g. "KW" for German). Only used when weekLabel is 'calendarWeek'. */
|
|
85
|
+
weekLabelPrefix?: string;
|
|
86
|
+
/** Per-tick label color/opacity override, e.g. to fade ticks outside a selection. */
|
|
87
|
+
tickLabelStyler?: TimeSliderTickLabelStyler;
|
|
88
|
+
/** Outer bounds of the visible time range: zooming out never shows more than this and panning stops at its edges. Applied in setTimeRange(), so wheel, pinch, up(), fit() and animations all respect it. Either side may be -Infinity/Infinity. See also setLimits(). */
|
|
89
|
+
limits?: TimeSliderTimeRange;
|
|
30
90
|
}
|
|
31
91
|
export declare class TimeSlider extends TypedEventEmitter<{
|
|
32
92
|
live: boolean;
|
|
@@ -40,6 +100,17 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
40
100
|
value: TimeSliderValueRange;
|
|
41
101
|
select: TimeSliderSelection[];
|
|
42
102
|
valueRanges: string;
|
|
103
|
+
locale: string;
|
|
104
|
+
selectionchange: {
|
|
105
|
+
ranges: TimeSliderSelectionRange[];
|
|
106
|
+
phase: TimeSliderSelectionChangePhase;
|
|
107
|
+
};
|
|
108
|
+
/** Fires once the engine passed to setEngine() has finished its async init() and layers can actually render. See also engineReady / whenReady(). */
|
|
109
|
+
ready: void;
|
|
110
|
+
/** Fires on every hover position update (and on leave/drag, with null), regardless of whether the built-in tooltip is shown. */
|
|
111
|
+
hover: TimeSliderHoverInfo | null;
|
|
112
|
+
/** Fires when a tick label on the ticks bar is clicked. Also still zooms/fits to that tick's range, same as before this event existed. */
|
|
113
|
+
tickclick: TimeSliderTickClickInfo;
|
|
43
114
|
}> {
|
|
44
115
|
valueRanges: Map<string, {
|
|
45
116
|
min: number;
|
|
@@ -50,6 +121,8 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
50
121
|
ticksBar: TimeTicksBar;
|
|
51
122
|
private loaders;
|
|
52
123
|
private layerUnloaders;
|
|
124
|
+
private layerListenerStoppers;
|
|
125
|
+
private layerLoaders;
|
|
53
126
|
pressedKeys: Set<string>;
|
|
54
127
|
protected container: HTMLElement | null;
|
|
55
128
|
theme: 'dark' | 'light';
|
|
@@ -61,6 +134,7 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
61
134
|
private _showCurrent;
|
|
62
135
|
showTicks: boolean;
|
|
63
136
|
playSpeed: number | 'auto';
|
|
137
|
+
private _locale;
|
|
64
138
|
current: number;
|
|
65
139
|
range: {
|
|
66
140
|
time: TimeSliderTimeRange;
|
|
@@ -76,6 +150,12 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
76
150
|
private toolTip;
|
|
77
151
|
private selectedLabel;
|
|
78
152
|
private selectingRangeElement;
|
|
153
|
+
private selectionOverlayContainer;
|
|
154
|
+
private _selectionRanges;
|
|
155
|
+
private selectionRangeElements;
|
|
156
|
+
private shadingElements;
|
|
157
|
+
private columnBandOverlayContainer;
|
|
158
|
+
private columnBandElements;
|
|
79
159
|
private stopUpdatingLabel?;
|
|
80
160
|
hoverOptions: TimeSliderHoverOptions;
|
|
81
161
|
selectionOptions: TimeSliderSelectionOptions;
|
|
@@ -84,9 +164,43 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
84
164
|
selectingRange: boolean;
|
|
85
165
|
selectingRangeVisible: boolean;
|
|
86
166
|
whenDoneSelectingRange?: () => void;
|
|
87
|
-
|
|
88
|
-
|
|
167
|
+
private _limits?;
|
|
168
|
+
getLayers(): TimeSliderLayer<TimeSliderElement, import("..").TimeSliderStyle>[];
|
|
169
|
+
getVisibleLayers(): TimeSliderLayer<TimeSliderElement, import("..").TimeSliderStyle>[];
|
|
89
170
|
constructor(options?: TimeSliderOptions);
|
|
171
|
+
get locale(): string;
|
|
172
|
+
/** Sets the locale for this slider's own rendering (ticks, hover tooltip) and for the TimeTools formatters' module-wide default, so code calling them directly (e.g. a custom labeler) stays in sync too. */
|
|
173
|
+
setLocale(locale: string): void;
|
|
174
|
+
/** Switches week ticks between the default date-range label and ISO calendar-week labels (e.g. "KW12"). */
|
|
175
|
+
setWeekLabel(weekLabel: 'default' | 'calendarWeek', weekLabelPrefix?: string): void;
|
|
176
|
+
/** Overrides per-tick label color/opacity, e.g. to fade ticks outside a selection. Pass undefined to clear. */
|
|
177
|
+
setTickLabelStyler(styler: TimeSliderTickLabelStyler | undefined): void;
|
|
178
|
+
get limits(): TimeSliderTimeRange | undefined;
|
|
179
|
+
/** Sets (or with undefined clears) the outer bounds of the visible time range, see TimeSliderOptions.limits. The current range is clamped right away. */
|
|
180
|
+
setLimits(limits: TimeSliderTimeRange | undefined): void;
|
|
181
|
+
/**
|
|
182
|
+
* Sets the draggable, programmatic selection range(s) — distinct from the
|
|
183
|
+
* click-driven element `select()` / `'select'` event, which keeps working
|
|
184
|
+
* independently. A range's startTime/endTime may be -Infinity/Infinity for
|
|
185
|
+
* an open-ended "before X" / "after X" selection, drawn to the slider edge.
|
|
186
|
+
* Fires 'selectionchange' with phase 'end'.
|
|
187
|
+
*/
|
|
188
|
+
setSelection(ranges: TimeSliderSelectionRange[]): void;
|
|
189
|
+
getSelection(): TimeSliderSelectionRange[];
|
|
190
|
+
clearSelection(): void;
|
|
191
|
+
/**
|
|
192
|
+
* Switches how hover/click pick elements: 'element' (default) uses cursor
|
|
193
|
+
* time AND height, 'column' uses cursor time only — every visible layer's
|
|
194
|
+
* element(s) at that time, regardless of height. Also updates the hover
|
|
195
|
+
* column-highlight band immediately.
|
|
196
|
+
*/
|
|
197
|
+
setPickMode(pick: TimeSliderPickMode): void;
|
|
198
|
+
private selectionTimeToX;
|
|
199
|
+
private renderSelectionOverlay;
|
|
200
|
+
/** Draws the pick-mode 'column' hover highlight: one band per layer with a hovered element, spanning that layer's own y-range and the hovered element(s)' time extent. No-op unless pick is 'column'. */
|
|
201
|
+
private renderColumnHoverBand;
|
|
202
|
+
private createSelectionRangeElements;
|
|
203
|
+
private wireSelectionDrag;
|
|
90
204
|
startSelectingRange(whenDone: () => void): void;
|
|
91
205
|
stopSelectingRange(): void;
|
|
92
206
|
updateValueRangesQueue: Map<string, {
|
|
@@ -103,6 +217,11 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
103
217
|
showingStats: boolean;
|
|
104
218
|
showStats(showingStats: boolean): void;
|
|
105
219
|
protected engine?: TimeSliderEngine<any>;
|
|
220
|
+
private _engineReady;
|
|
221
|
+
/** True once the current engine's async init() has resolved and layers can actually render — see also the 'ready' event and whenReady(). */
|
|
222
|
+
get engineReady(): boolean;
|
|
223
|
+
/** Resolves once the engine is ready (immediately, if it already is). Layers added before this point are queued and loaded automatically — see loadLayer(). */
|
|
224
|
+
whenReady(): Promise<void>;
|
|
106
225
|
setEngine(engine: TimeSliderEngine<any>): Promise<void>;
|
|
107
226
|
initSliderContainer(): void;
|
|
108
227
|
get showCurrent(): boolean;
|
|
@@ -113,7 +232,7 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
113
232
|
private updatingLabel;
|
|
114
233
|
private selectedLayerId?;
|
|
115
234
|
getLabel(element: TimeSliderElement, layer: TimeSliderLayer, t: number, v: number): string | null;
|
|
116
|
-
getLayerById(id: string): TimeSliderLayer<TimeSliderElement, import("
|
|
235
|
+
getLayerById(id: string): TimeSliderLayer<TimeSliderElement, import("..").TimeSliderStyle> | undefined;
|
|
117
236
|
select(mouse: {
|
|
118
237
|
x: number;
|
|
119
238
|
y: number;
|
|
@@ -151,11 +270,16 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
151
270
|
x: number;
|
|
152
271
|
y: number;
|
|
153
272
|
}, pickSize?: number): {
|
|
154
|
-
layer: TimeSliderLayer<TimeSliderElement, import("
|
|
273
|
+
layer: TimeSliderLayer<TimeSliderElement, import("..").TimeSliderStyle>;
|
|
155
274
|
elements: TimeSliderElement[];
|
|
156
275
|
t: number;
|
|
157
276
|
v: number;
|
|
158
277
|
}[];
|
|
278
|
+
/** Pick mode 'column': ignores cursor height entirely — every visible layer's element(s) whose time interval contains the cursor time. */
|
|
279
|
+
private findColumnElements;
|
|
280
|
+
private hoverCleared;
|
|
281
|
+
/** Clears the column band and emits 'hover' null once per hover-to-no-hover change, not on every time-range update while the mouse is away. */
|
|
282
|
+
private clearHoverEvent;
|
|
159
283
|
updateHover(mouse?: {
|
|
160
284
|
x: number;
|
|
161
285
|
y: number;
|
|
@@ -200,6 +324,8 @@ export declare class TimeSlider extends TypedEventEmitter<{
|
|
|
200
324
|
private loadLayer;
|
|
201
325
|
private unloadLayer;
|
|
202
326
|
addLayer(layer: TimeSliderLayer): void;
|
|
327
|
+
/** layer.min / layer.max changed: reload the layer unless its loader follows the band by itself. Unlike toggling visible, this keeps the element selection. */
|
|
328
|
+
private onLayerBandChange;
|
|
203
329
|
removeLayer(layer: string | {
|
|
204
330
|
id: string;
|
|
205
331
|
}): void;
|
package/engine/TimeSlider.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as e}from"uuid";import{Disposables as t}from"../common/Disposables";import{animateRangeTransition as i}from"../common/Easing";import{formatDuration as s,getLargeTimeUnitRange as n,getMatchingTimeUnit as l,getTimeUnitRange as a,MONTH_NAMES as o}from"../common/TimeTools";import{TimeSliderDynamicHistogram as h}from"../data/histogram/TimeSliderDynamicHistogram";import{TimeSliderIntervalsModel as r}from"../data/TimeSliderIntervalsModel";import{addDuration as d,addPadding as m,applyTimeRangeUpdate as g,timeRangesOverlap as u,timeRangesUnion as c}from"../data/TimeSliderRange";import{TypedEventEmitter as p}from"../event/TypedEventEmitter";import{TimeSliderHistogramLayer as y}from"../layer/TimeSliderHistogramLayer";import{TimeSliderIntervalsLayer as T}from"../layer/TimeSliderIntervalsLayer";import{CENTURY as v,DECADE as f,MILLENIUM as E,ONE_DAY as L,ONE_HOUR as x,ONE_MINUTE as R,ONE_MONTH as b,ONE_SECOND as w,ONE_WEEK as V,ONE_YEAR as S,TODAY as D}from"../ticks/TimeSliderConstants";import{TimeTicksBar as M}from"../ticks/TimeTicksBar";import{YAxisTicks as k}from"../ticks/YAxisTicks";const $=w,z=10*E;export class TimeSlider extends p{getLayers(){return[...this.layers]}getVisibleLayers(){return this.getLayers().filter(e=>e.visible)}constructor(i){super(),this.valueRanges=new Map,this.layers=[],this.onDestroy=[],this.ticksBar=new M,this.loaders=new Set,this.layerUnloaders=new Map,this.pressedKeys=new Set,this.container=null,this.d=new t,this.id=e(),this.playing=!1,this.live=!1,this._showCurrent=!1,this.current=Date.now(),this.range={time:D,value:{minValue:0,maxValue:100}},this.size={width:100,height:100},this.sliderElement=document.createElement("div"),this.yAxisTicks=new k,this.hoverLine=document.createElement("div"),this.toolTip=document.createElement("div"),this.selectedLabel=document.createElement("div"),this.selectingRangeElement=document.createElement("div"),this.selectingRange=!1,this.selectingRangeVisible=!1,this.updateValueRangesQueue=new Map,this.showingStats=!1,this.mouse=null,this.updatingLabel=!1,this.dragging=!1,this.pinching=!1,this.hoverOptions=i?.hover||{},this.selectionOptions={highlight:"boolean"!=typeof i?.selection?.highlight||i.selection.highlight,label:"boolean"!=typeof i?.selection?.label||i.selection.label},this.showCurrent=i?.showCurrent||!1,this.showTicks=i?.showTicks||!1,this.selectRangeMode=i?.selectRangeMode||"select",this.playSpeed=i?.playSpeed||"auto",this.liveRange=i?.liveRange||10*w,this.theme=i?.theme||"dark",this.syncMaxValues()}startSelectingRange(e){this.selectingRange=!0,this.whenDoneSelectingRange=e}stopSelectingRange(){this.selectingRange=!1,this.whenDoneSelectingRange?.(),this.whenDoneSelectingRange=void 0,this.selectingRangeVisible&&(this.container.removeChild(this.selectingRangeElement),this.selectingRangeVisible=!1)}syncMaxValues(){return this.updateAllValueRanges(),this.on("time",()=>this.updateAllValueRanges())}syncMaxValuesForLayer(e){return this.updateValueRanges(e.yAxisGroup),e.model.on(()=>this.updateValueRanges(e.yAxisGroup))}updateAllValueRanges(){this.layers.filter(e=>e.visible).forEach(e=>{this.updateValueRanges(e.yAxisGroup,!0)}),this.renderYAxis()}updateValueRanges(e,t){this.updateValueRangesQueue.has(e)||this.updateValueRangesQueue.set(e,{lastUpdate:0,pending:void 0});const i=this.updateValueRangesQueue.get(e);if(Date.now()-i.lastUpdate<100)return i.pending&&clearTimeout(i.pending),void(i.pending=setTimeout(()=>{i.pending=void 0,this.updateValueRanges(e)},200));i.lastUpdate=Date.now();const s=new Map,n=new Map;this.layers.filter(e=>e.visible).forEach(e=>{const t=e.yAxis.group||e.id;s.has(t)||(s.set(t,-Number.MAX_VALUE),n.set(t,Number.MAX_VALUE));const i=e.model.getValueRange(this.getTimeRange());i.minValue<n.get(t)&&n.set(t,i.minValue),i.maxValue>s.get(t)&&s.set(t,i.maxValue)}),this.valueRanges.clear(),s.forEach((e,t)=>{this.valueRanges.set(t,{max:e,min:n.get(t)})}),t||this.renderYAxis(),this.emit("valueRanges",e)}renderYAxis(){const e=new Map;this.layers.filter(e=>e.visible).forEach(t=>{const i=t.yAxis.group||t.id;e.has(i)||e.set(i,{min:t.min,max:t.max,group:i}),e.set(i,{...e.get(i),...t.yAxis,min:t.min,max:t.max})});const t=[];e.forEach(e=>{if(e.visible){const i=this.valueRanges.get(e.group);i&&t.push({...e,minValue:i.min,maxValue:i.max})}}),this.yAxisTicks.render(t)}setTheme(e){this.theme=e,this.ticksBar.setDarkMode("dark"===e),this.engine?.setTheme(e)}addLayerLoader(e){this.loaders.add(e)}showStats(e){this.showingStats=e,this.engine?.showStats(e)}async setEngine(e){this.engine&&(this.layerUnloaders.forEach(e=>e()),this.layerUnloaders.clear(),this.engine.dispose()),this.initSliderContainer(),this.engine=e,this.engine.setTheme(this.theme),await this.engine.init(this.sliderElement),this.engine.setTheme(this.theme),this.getVisibleLayers().forEach(e=>this.loadLayer(e)),this.engine.showStats(this.showingStats),this.engine.setTimeRange(this.getTimeRange()),this.engine.setValueRange(this.getValueRange()),this.engine.setSize(this.size.width,this.size.height)}initSliderContainer(){this.stopControls&&this.stopControls(),this.container?.removeChild(this.sliderElement);let e=0;this.showTicks&&(e+=24),this.showCurrent&&(e+=4),this.sliderElement=document.createElement("div"),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top="0px",this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${0+e}px)`,this.container?.appendChild(this.sliderElement),this.initSelectLabel(),this.stopControls=this.initControls(),this.onDestroy.push(()=>{this.container?.removeChild(this.sliderElement)})}get showCurrent(){return this._showCurrent}set showCurrent(e){if(e!==this._showCurrent){this._showCurrent=e,this.ticksBar.showLine=!this.showCurrent;let t=0,i=0;this.showTicks&&(i+=24),this.showCurrent&&(i+=4),this.sliderElement.style.height=`calc(100% - ${t+i}px)`}}async init(e,t){const i="string"==typeof e?document.getElementById(e):e;if(this.container=i,i){i.oncontextmenu=()=>!1;let e=0,s=0;if(this.showTicks){s+=24;const e=document.createElement("div");e.style.width="100%",e.style.height="24px",e.style.position="absolute",e.style.bottom="0px",e.style.touchAction="none",i.appendChild(e),this.ticksBar.init(e,e=>this.fit({range:e,animate:1e3})),this.ticksBar.showLine=!this.showCurrent}this.showCurrent&&(s+=4),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top=`${e}px`,this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.sliderElement),this.yAxisTicks.canvas.style.top=`${e}px`,this.yAxisTicks.canvas.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.yAxisTicks.canvas),this.initHoverTooltip(),this.initSelectLabel(),this.setSize(this.sliderElement.clientWidth,this.sliderElement.clientHeight),this.syncSize(),this.setTimeRange(C(t)),this.setValueRange(C(t))}else console.warn(`Element ${e} not found`)}initSelectLabel(){this.selectedLabel.style.position="absolute",this.selectedLabel.style.padding="4px 8px",this.selectedLabel.style.background="rgba(0, 0, 0, 0.75)",this.selectedLabel.style.color="white",this.selectedLabel.style.fontSize="12px",this.selectedLabel.style.maxWidth="200px",this.selectedLabel.style.fontFamily="monospace",this.selectedLabel.style.borderRadius="4px",this.selectedLabel.style.pointerEvents="none",this.selectedLabel.style.display="none",this.selectedLabel.style.zIndex="10",this.sliderElement.appendChild(this.selectedLabel)}getLabel(e,t,i,s){if(t.labeler){const n=t.labeler(e,i,s);return null===n?null:"string"==typeof n?`<div>${n}</div>`:n?n.outerHTML:`<div>${e.name||e.id}</div>`}return`<div>${e.name||e.id}</div>`}getLayerById(e){return this.layers.find(t=>t.id===e)}select(e,t){this.stopSelectingRange(),this.stopUpdatingLabel?.();const i=()=>{this.updatingLabel=!1,this.stopUpdatingLabel?.(),this.stopUpdatingLabel=void 0,this.selectedLabel.style.display="none",this.layers.forEach(e=>e.select([])),this.selectedLayerId=void 0,this.emit("select",[])},s=e=>{this.layers.filter(t=>!e.some(e=>t.id===e.layer.id)).forEach(e=>e.select([])),e.forEach(e=>{e.layer.select(e.elements)}),this.emit("select",e)};if(t){s(this.getVisibleLayers().map(e=>{const i=e.model.dataInTimeRange(t);return{layer:e,elements:i}}).filter(e=>e.elements.length>0))}else if(e){const t=this.findElements(e,24);if(s(t.map(e=>({layer:e.layer,elements:e.elements})).flat()),1===t.length&&t[0].elements.length>0&&this.selectionOptions.label){const e=t[0].elements[0],s=t[0].layer;this.selectedLabel.innerHTML=this.getLabel(e,s,t[0].t,t[0].v)||"",this.selectedLabel.style.display="block";const n=this.selectedLabel.offsetWidth,l=this.selectedLabel.offsetHeight;this.selectedLayerId=s.id;const a=Array.isArray(e.t);this.updatingLabel=!0;const o=()=>{if(!this.updatingLabel)return;const{startTime:i,duration:s,endTime:o}=this.getTimeRange(),h=t[0].layer.model.get(e.id);if(h){const e=u(this.getTimeRange(),h.t);if(e){const o=this.getSliderBounds();let r=(.5*(e.startTime+e.endTime)-i)/s*o.width;const d="number"==typeof h.v?h.v:.5*(h.v[1]+h.v[0]);let m=this.modelValueToPixels(d,t[0].layer);a?m-=.5*l:m+=8;const g=.5*n,u=.5*l,c=o.width-.5*n,p=o.height-.5*l,y=Math.min(c,Math.max(g,r)),T=Math.min(p,Math.max(u,m));this.selectedLabel.style.display="block",this.selectedLabel.style.left=y-.5*n+"px",this.selectedLabel.style.top=`${T}px`}else this.selectedLabel.style.display="none"}else this.selectedLabel.style.display="none"};o();const r=s instanceof y&&s.histogram instanceof h;this.stopUpdatingLabel=this.on("time",r?i:o)}}else i()}listenToClicks(){let e=null;const t=t=>{e={x:t.clientX,y:t.clientY}},i=t=>{if(!e)return;const i=t.clientX-e.x,s=t.clientY-e.y;i*i+s*s<=25&&(this.stopSelectingRange(),this.select(e)),e=null},s=()=>{e=null};return this.sliderElement.addEventListener("pointerdown",t),this.sliderElement.addEventListener("pointerup",i),this.sliderElement.addEventListener("pointercancel",s),()=>{this.sliderElement.removeEventListener("pointerdown",t),this.sliderElement.removeEventListener("pointerup",i),this.sliderElement.removeEventListener("pointercancel",s)}}getSliderBounds(){return this.sliderElement.getBoundingClientRect()}mouseInSlider(e){const t=this.getSliderBounds(),i="x"in e?e:{x:e.clientX,y:e.clientY},s={x:i.x-t.left,y:i.y-t.top},n={x:s.x/t.width,y:-s.y/t.height+1},{startTime:l,duration:a}=this.getTimeRange(),o=l+n.x*a,{minValue:h,maxValue:r}=this.getValueRange();return{absolute:s,normalized:n,t:o,v:h+n.x*(r-h)}}pixelsToLayerValue(e,t){if(!e)return{yInLayer:0,toLayerHeight:1};const i="normalized"in e?e.normalized:this.mouseInSlider(e).normalized;let s=t.min;const n=t.max-s;return{yInLayer:(i.y-s)/n,toLayerHeight:n/this.getSliderBounds().height}}pixelsToModelValue(e,t){const{yInLayer:i,toLayerHeight:s}=this.pixelsToLayerValue(e,t);let n=0,l=100;if(t.model instanceof r){const e=this.valueRanges.get(t.yAxisGroup)||{min:0,max:1e3};n=e.min,l=e.max-n}return{yInModel:n+i*l,toModelHeight:s*l}}layerValueToPixels(e,t){let i=t.min;return(1-(i+(t.max-i)*e))*this.getSliderBounds().height}modelValueToPixels(e,t){let i=0,s=100;if(t.model instanceof r){const e=t.model.getValueRange(this.getTimeRange());i=e.minValue,s=e.maxValue-i}const n=(e-i)/s;return this.layerValueToPixels(n,t)}findElements(e,t){const{width:i,height:s}=this.getSliderBounds(),{normalized:n}=this.mouseInSlider(e),{startTime:l,endTime:a,duration:o}=this.getTimeRange(),h=l+n.x*o,r=t||12,d=r/i*o,m={startTime:h-1,endTime:h+1},g={startTime:h-.5*d,endTime:h+.5*d};return this.getVisibleLayers().map(e=>{const{yInModel:t,toModelHeight:i}=this.pixelsToModelValue({normalized:n},e),s=e instanceof T?0:r*i,l=e instanceof T?m:g,a={minValue:t-.5*s,maxValue:t+.5*s},o=e.model.dataInRange({...l,...a});return{layer:e,elements:o,t:h,v:t}}).filter(e=>e.elements.length>0)}updateHover(e){if(this.dragging)return this.hoverLine.style.display="none",void(this.toolTip.style.display="none");if(void 0!==e&&(this.mouse=e),this.mouse){const e=this.getSliderBounds(),{normalized:t}=this.mouseInSlider(this.mouse),{startTime:i,endTime:s,duration:n}=this.getTimeRange(),l=i+t.x*n,a=this.findElements(this.mouse),h=a.map(e=>e.elements.map(t=>({e:t,l:e.layer,t:e.t,v:e.v}))).flat();let r;if(h.length>0)if(h.length>3){const e=h.slice(0,2).map(e=>this.getLabel(e.e,e.l,e.t,e.v));r=e.flat().filter(e=>null!==e).join(""),r+=`<div>And ${h.length-2} more...</div>`}else{const e=a.map(e=>e.elements.map(t=>this.getLabel(t,e.layer,e.t,e.v)));r=e.flat().filter(e=>null!==e).join("")}const d=new Date(l),m=d.getDate(),g=d.getMonth(),u=d.getFullYear(),c=d.getHours(),p=d.getMinutes(),y=d.getSeconds(),T=`${(m<10?"0":"")+m} ${o[g]} ${u}`,v=`${(c<10?"0":"")+c}:${(p<10?"0":"")+p}:${(y<10?"0":"")+y}`;let f="";const E=this.ticksBar.cache.high.spacing;(void 0===this.hoverOptions.date?E>=x:this.hoverOptions.date)&&(f+=`<div>${T}</div>`),(void 0===this.hoverOptions.time?E<=L:this.hoverOptions.time)&&(f+=`<div>${v}</div>`),r&&(f+=r),this.toolTip.innerHTML=f,this.toolTip.style.display=f.length>0?"block":"none";const R=88,b=36;let w=this.mouse.x+10,V=this.mouse.y+10;const S=e.left+e.width-R-5,D=e.top+e.height-b-5;w>S&&(w=S),V>D&&(V=D),this.toolTip.style.left=`${w}px`,this.toolTip.style.top=`${V}px`}else this.hoverLine.style.display="none",this.toolTip.style.display="none"}initHoverTooltip(){this.toolTip.style.position="absolute",this.toolTip.style.padding="4px 8px",this.toolTip.style.background="rgba(0, 0, 0, 0.75)",this.toolTip.style.color="white",this.toolTip.style.fontSize="12px",this.toolTip.style.fontFamily="monospace",this.toolTip.style.borderRadius="4px",this.toolTip.style.pointerEvents="none",this.toolTip.style.display="none",this.toolTip.style.zIndex="10",this.toolTip.style.overflow="hidden",document.body.appendChild(this.toolTip)}initHoverListener(){const e=()=>{this.updateHover(null)},t=e=>{this.updateHover({x:e.clientX,y:e.clientY})};this.sliderElement.addEventListener("mouseleave",e),this.sliderElement.addEventListener("mousemove",t);const i=this.listenToClicks();return()=>{this.sliderElement.removeEventListener("mouseleave",e),this.sliderElement.removeEventListener("mousemove",t),i()}}syncSize(){const e=()=>{const{offsetWidth:e,offsetHeight:t}=this.sliderElement;this.setSize(e,t)},t=new ResizeObserver(()=>{e()});this.container&&(t.observe(this.container),e()),this.onDestroy.push(()=>{t.disconnect()})}getTimeRange(){return d(this.range.time)}getValueRange(){return this.range.value}setTimeRange(e,t){const i=this.getTimeRange(),s=g(i,e);s.startTime===i.startTime&&s.endTime===i.endTime||(this.range.time=s,this.engine?.setTimeRange(s),this.showTicks&&this.ticksBar.setTimeRange(s),this.emit("time",s),this.updateHover())}setValueRange(e){const t={...this.getValueRange(),...e};this.range.value=t,this.engine?.setValueRange(t),this.emit("value",this.getValueRange()),this.updateHover()}setSize(e,t){this.size={width:e,height:t},this.showTicks&&this.ticksBar.setWidth(e);const i=this.getTimeRange(),s=this.getValueRange();this.engine?.setSize(e,t),this.setTimeRange(i),this.setValueRange(s),this.updateHover(),this.emit("size",{width:e,height:t})}up(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let l={startTime:0,endTime:Date.now()};const o=.5*(t+i);if(s>=.9*E){const e=A(10*s);l=n(o,e)}else{const e=[{threshold:v,unit:"millennium"},{threshold:f,unit:"century"},{threshold:S,unit:"decade"},{threshold:.9*b,unit:"year"},{threshold:V,unit:"month"},{threshold:L,unit:"week"},{threshold:x,unit:"day"},{threshold:R,unit:"hour"},{threshold:w,unit:"minute"},{threshold:-1,unit:"second"}];let t=0;for(;s<.9*e[t].threshold;)t++;const i=e[t].unit;l=a(o,i)}this.fit({...e,range:l})}down(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let l={startTime:0,endTime:Date.now()};const o=t+("number"==typeof e?.xRatio?e.xRatio:.5)*s;if(s>=.9*E){const e=A(s/10);l=n(o,e)}else{let e=0;const t=[{threshold:E,unit:"century"},{threshold:v,unit:"decade"},{threshold:f,unit:"year"},{threshold:S,unit:"month"},{threshold:1.1*b,unit:"week"},{threshold:V,unit:"day"},{threshold:L,unit:"hour"},{threshold:x,unit:"minute"},{threshold:R,unit:"second"}].reverse();for(;s>1.1*t[e].threshold;)e++;const i=t[e].unit;l=a(o,i)}this.fit({...e,range:l})}next(e){this.skip(1,e)}previous(e){this.skip(-1,e)}skip(e,t){let i={startTime:0,endTime:Date.now()};const{startTime:s,endTime:o,duration:h}=this.getTimeRange(),r=.5*(s+o);if(h>=9*E){const e=A(h);i=n(r,e)}else{const t=l(s,o);i=t?a(r,t,Math.round(e)):{startTime:s+e*h,endTime:o+e*h}}this.fit({...t,range:i})}getTimeRangeLabel(){const{startTime:e,endTime:t}=this.getTimeRange(),i=new Date(e),s=new Date(t);if(0===i.getHours()&&0===i.getHours()&&0===i.getMinutes()&&0===i.getMinutes()&&0===i.getSeconds()&&0===i.getSeconds()&&0===i.getMilliseconds()&&0===i.getMilliseconds()){const e=new Date(t-1),n=i.toLocaleString("default",{month:"short"}),l=e.toLocaleString("default",{month:"short"});return i.getFullYear()===e.getFullYear()?i.getMonth()===e.getMonth()?i.getDate()===e.getDate()?`${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()?`${l} ${e.getFullYear()}`:`${i.getDate()} - ${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()&&0===i.getMonth()&&0===s.getMonth()?`${e.getFullYear()}`:`${i.getDate()} ${n} - ${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()&&0===i.getMonth()&&0===s.getMonth()?` ${i.getFullYear()} - ${e.getFullYear()}`:`${i.getDate()} ${n} ${i.getFullYear()} - ${e.getDate()} ${l} ${e.getFullYear()}`}}cancelFit(){this.stopFit?.(),this.stopFit=void 0}fit(e){this.cancelFit();const t=e?.range||this.getLayersTimeRange(),s=e?.padding?m(t,e.padding):t;if(e?.animate){const t=this.getTimeRange();this.stopFit=i(t.startTime,t.endTime,s.startTime,s.endTime,e.animate,(e,t)=>this.setTimeRange({startTime:e,endTime:t}))}else this.setTimeRange(s)}getLayersTimeRange(){if(0===this.getVisibleLayers().length)return D;{let e=this.getVisibleLayers()[0].model.getTimeRange();return this.getVisibleLayers().slice(1).forEach(t=>e=c(e,t.model.getTimeRange())),e}}loadLayer(e){if(e.timeSlider&&e.timeSlider.id!==this.id)console.warn("Layer already has been loaded by another time slider, create a new layer with the same model and style if you want to add it to another time slider");else if(this.engine&&!this.layerUnloaders.has(e.id)){const t=[...this.loaders].filter(e=>this.engine instanceof e.engineClass).find(t=>t.canLoad(e));if(t){const i=Date.now(),n=t.load(e,this.engine.scene,this.engine,this);e.timeSlider=this,e.loaded=!0;const l=e.name||e.constructor.name+"#"+e.id.slice(e.id.length-4).toUpperCase();console.log(`Loaded ${l} in ${s(Date.now()-i)}`);const a=this.syncMaxValuesForLayer(e);this.layerUnloaders.set(e.id,()=>{a(),n(),e.loaded=!1})}else console.warn("No loader found for",{layer:e})}}unloadLayer(e){this.selectedLayerId===e.id&&this.select(null),this.layerUnloaders.has(e.id)&&(this.layerUnloaders.get(e.id)(),this.layerUnloaders.delete(e.id))}addLayer(e){if(this.layers.push(e),e.visible){this.loadLayer(e);const t=e.model.getTimeRange();if(1===this.getVisibleLayers().length)this.setTimeRange(t);else{const e=c(this.getTimeRange(),t);this.setTimeRange(e)}}e.on("visible",t=>{e.visible?this.loadLayer(e):this.unloadLayer(e)})}removeLayer(e){const t="string"==typeof e?e:e.id,i=this.layers.find(e=>e.id===t);i&&(this.unloadLayer(i),this.layerUnloaders.delete(t),this.layers=this.layers.filter(e=>e.id!==t))}destroy(){this.layers.map(e=>e.id).forEach(e=>this.removeLayer(e)),this.onDestroy.forEach(e=>e())}addHorizontalPinchZoom(){let e=null,t=null;const i=()=>{this.pinching=!1,e=null,t=null},s=i=>{if(2===i.touches.length){i.preventDefault(),this.dragging=!1,this.pinching=!0;const s=this.mouseInSlider(i.touches[0]).t,n=this.mouseInSlider(i.touches[1]).t;e=Math.min(s,n),t=Math.max(s,n)}},n=s=>{if(2===s.touches.length){if(null===e||null===t)return;s.preventDefault(),this.dragging=!1;const i=this.mouseInSlider(s.touches[0]).normalized.x,n=this.mouseInSlider(s.touches[1]).normalized.x,l=Math.min(i,n),a=Math.max(i,n),o=(t-e)/(a-l);let h=e-l*o,r=t+(1-a)*o;if(o>z){const e=.5*(h+r);h=e-.5*z,r=e+.5*z}if(o<$){const e=.5*(h+r);h=e-.5*$,r=e+.5*$}this.setTimeRange({startTime:h,endTime:r})}else i()},l=()=>{i()};this.sliderElement.addEventListener("touchstart",s,{passive:!1}),this.sliderElement.addEventListener("touchmove",n,{passive:!1}),this.sliderElement.addEventListener("touchend",l),this.sliderElement.addEventListener("touchcancel",l),this.onDestroy.push(()=>{this.sliderElement.removeEventListener("touchstart",s),this.sliderElement.removeEventListener("touchmove",n),this.sliderElement.removeEventListener("touchend",l),this.sliderElement.removeEventListener("touchcancel",l)})}initControls(){const e=new t;this.dragging=!1;let i,s=0,n=0,l=0;e.add(this.initHoverListener());const a=e=>{this.sliderElement.focus(),e.preventDefault();const t=this.mouseInSlider(e);this.zoom(.001*e.deltaY,{x:t.normalized.x})};let o=0,h=-1;const r=e=>{const t=Date.now(),i=t-o;h>=0&&i<300&&i>0&&(this.select(null),e.preventDefault(),this.zoom(-.75,{animate:1e3,x:h})),o=t},d=e=>{e.preventDefault(),this.select(null);const t=this.mouseInSlider(e);this.zoom(-.75,{animate:1e3,x:t.normalized.x})};this.selectingRangeElement.style.height="calc(100% - 6px)",this.selectingRangeElement.style.pointerEvents="none",this.selectingRangeElement.style.position="absolute",this.selectingRangeElement.style.border="3px solid #df0",this.selectingRangeElement.style.background="#df04",this.selectingRangeElement.style.top="0px";const m=e=>{if(this.sliderElement.focus(),2===e.button||0===e.button){e.preventDefault();const t=this.mouseInSlider(e),i=t.normalized.x,{startTime:a,duration:o}=this.getTimeRange();s=a+i*o,n=Date.now(),l=t.absolute.x,(e.ctrlKey||2===e.button)&&(this.selectingRange=!0),this.selectingRange?(this.selectingRangeElement.style.left=t.absolute.x+"px",this.selectingRangeElement.style.width="0px",this.container.appendChild(this.selectingRangeElement),this.selectingRangeVisible=!0):this.dragging=!0}},g=e=>{const t=this.mouseInSlider(e);return i=t.normalized.x,t},u=e=>{const t=g(e);if(this.selectingRange){const e=Math.abs(l-t.absolute.x),i=Math.min(l,t.absolute.x);this.selectingRangeElement.style.left=i+"px",this.selectingRangeElement.style.width=e-6+"px"}if(!this.dragging||Date.now()-n<100&&Math.abs(l-t.absolute.x)<10)return;e.preventDefault();const i=t.normalized.x,{startTime:a,endTime:o}=this.getTimeRange(),h=a+i*(o-a)-s;this.setTimeRange({startTime:a-h,endTime:o-h})},c=e=>{const t=this.getSliderBounds(),n=t.height-(e.clientY-t.top);if(!this.dragging&&!this.pinching&&n<8)this.ticksBar.click(e);else if(i=void 0,this.dragging=!1,this.selectingRange){const t=this.mouseInSlider(e).normalized.x,{startTime:i,endTime:n}=this.getTimeRange(),l=i+t*(n-i);"zoom"===this.selectRangeMode&&this.fit({range:{startTime:Math.min(s,l),endTime:Math.max(s,l)},animate:1e3}),"select"===this.selectRangeMode&&this.select(null,{startTime:Math.min(s,l),endTime:Math.max(s,l)})}this.stopSelectingRange()},p=e=>{this.pressedKeys.add(e.code)},y=e=>{this.pressedKeys.delete(e.code),"Space"===e.code&&(e.preventDefault(),this.togglePlaying()),"KeyF"===e.code&&(e.preventDefault(),this.fit({animate:3e3}));const t=void 0;"ArrowRight"===e.code&&(e.preventDefault(),this.skip(1,{animate:t})),"ArrowLeft"===e.code&&(e.preventDefault(),this.skip(-1,{animate:t})),"ArrowUp"===e.code&&(e.preventDefault(),this.up({animate:t})),"ArrowDown"===e.code&&(e.preventDefault(),this.down({xRatio:i,animate:t}))};let T=!0;const v=()=>{if(T){const e=this.pressedKeys.has("ShiftLeft")?.05:.01,t=2*e,s=this.pressedKeys.has("KeyD"),n=this.pressedKeys.has("KeyA");s&&this.shift(-e),n&&this.shift(e),this.pressedKeys.has("KeyW")&&this.zoom(-t,{x:s||n?void 0:i}),this.pressedKeys.has("KeyS")&&this.zoom(t,{x:s||n?void 0:i}),requestAnimationFrame(v)}};v(),e.add(()=>T=!1);const f=e=>e.preventDefault();this.sliderElement.addEventListener("contextmenu",f),this.sliderElement.addEventListener("wheel",a),this.sliderElement.addEventListener("pointerdown",m),this.sliderElement.addEventListener("pointermove",u),this.sliderElement.addEventListener("pointerup",c),this.sliderElement.addEventListener("dblclick",d),this.sliderElement.addEventListener("touchend",r),this.sliderElement.addEventListener("touchstart",e=>{if(1===e.touches.length){const t=this.mouseInSlider(e.touches[0]);h=t.normalized.x}else h=-1}),this.sliderElement.addEventListener("keydown",p),this.sliderElement.addEventListener("keyup",y),this.addHorizontalPinchZoom();const E=()=>{this.sliderElement.removeEventListener("contextmenu",f),this.sliderElement.removeEventListener("wheel",a),this.sliderElement.removeEventListener("pointerdown",m),this.sliderElement.removeEventListener("pointermove",u),this.sliderElement.removeEventListener("pointerup",c),this.sliderElement.removeEventListener("dblclick",d),this.sliderElement.removeEventListener("touchend",r),this.sliderElement.removeEventListener("keydown",p),this.sliderElement.removeEventListener("keyup",y)};return this.onDestroy.push(E),e.add(E),e.disposeLater()}shift(e,t){const{startTime:i,endTime:s,duration:n}=this.getTimeRange(),l=t?.absolute?e:e*n;this.fit({...t,range:{startTime:i-l,endTime:s-l}})}zoom(e,t){const i="number"==typeof t?.x?t.x:.5,{startTime:s,endTime:n,duration:l}=this.getTimeRange(),a={startTime:s-e*l*i,endTime:n+e*l*(1-i)},o=a.endTime-a.startTime,h=a.startTime+.5*o;o>z&&(a.startTime=h-.5*z,a.endTime=h+.5*z),o<$&&(a.startTime=h-.5*$,a.endTime=h+.5*$),this.fit({range:a,animate:t?.animate})}togglePlaying(){this.playing?this.pause():this.play()}isPlaying(){return this.playing}play(){if(this.playing)return;this.playing=!0,this.emit("playing",!0);let e=Date.now();const t=()=>{if(this.playing){if(this.live){const{duration:e}=this.getTimeRange(),t=Date.now(),i=10/this.size.width;this.setTimeRange({startTime:t-(1-i)*e,endTime:t+i*e}),this.setCurrent(t)}else if("auto"!==this.playSpeed||this.showCurrent){const t=Date.now(),i=t-e,s=this.current-this.getTimeRange().startTime,n="auto"===this.playSpeed?1:this.playSpeed;this.shift(-n*i,{absolute:!0}),this.setCurrent(this.getTimeRange().startTime+s),e=t}else{const t=Date.now();let i=5e-5*(t-e);this.pressedKeys.has("ShiftLeft")&&(i*=5);const s=this.current-this.getTimeRange().startTime;this.shift(-i),this.setCurrent(this.getTimeRange().startTime+s),e=t}requestAnimationFrame(t)}};t()}setCurrent(e){this.current!==e&&(Math.abs(e-Date.now())>100&&this.live&&(this.pause(),this.setLive(!1)),this.current=e,this.emit("current",e))}pause(){this.playing&&(this.playing=!1,this.emit("playing",!1),this.setLive(!1))}setLive(e){if(this.live!==e){if(this.live=e,e){const e=this.getTimeRange();this.fit({range:{startTime:e.endTime-this.liveRange,endTime:e.endTime},animate:w}),this.play()}this.emit("live",e)}}}function C(e){return{startTime:"number"==typeof e?.startTime?e.startTime:"number"==typeof e?.endTime?e.duration?e.endTime-e.duration:e.endTime-L:e?.duration?Date.now()-.5*e.duration:Date.now()-.5*L,endTime:"number"==typeof e?.endTime?e.endTime:"number"==typeof e?.startTime?e.duration?e.startTime+e.duration:e.startTime+L:e?.duration?Date.now()+.5*e.duration:Date.now()+.5*L,duration:e?.duration?e.duration:"number"==typeof e?.startTime&&"number"==typeof e?.endTime?e.endTime+e.startTime:L,minValue:"number"==typeof e?.minValue?e.minValue:"number"==typeof e?.maxValue?e.maxValue>0?0:e.maxValue-100:0,maxValue:"number"==typeof e?.maxValue?e.maxValue:"number"==typeof e?.minValue?e.minValue<0?0:e.minValue+100:100}}function A(e){const t=e/315576e5,i=Math.log10(t),s=Math.ceil(i);return Math.pow(10,s)}
|
|
1
|
+
import{v4 as e}from"uuid";import{Disposables as t}from"../common/Disposables.js";import{animateRangeTransition as i}from"../common/Easing.js";import{formatDate as s,formatDateRange as n,formatDuration as l,getDefaultLocale as a,getLargeTimeUnitRange as o,getMatchingTimeUnit as r,getTimeUnitRange as h,setDefaultLocale as d}from"../common/TimeTools.js";import{TimeSliderDynamicHistogram as m}from"../data/histogram/TimeSliderDynamicHistogram.js";import{getTimeArray as c}from"../data/TimeSliderElement.js";import{TimeSliderIntervalsModel as g}from"../data/TimeSliderIntervalsModel.js";import{addDuration as u,addPadding as p,applyTimeRangeUpdate as y,clampTimeRange as v,mergeTimeRanges as T,timeRangesOverlap as f,timeRangesUnion as E}from"../data/TimeSliderRange.js";import{TypedEventEmitter as L}from"../event/TypedEventEmitter.js";import{TimeSliderHistogramLayer as x}from"../layer/TimeSliderHistogramLayer.js";import{TimeSliderIntervalsLayer as R}from"../layer/TimeSliderIntervalsLayer.js";import{CENTURY as b,DECADE as w,MILLENIUM as S,ONE_DAY as C,ONE_HOUR as V,ONE_MINUTE as k,ONE_MONTH as M,ONE_SECOND as B,ONE_WEEK as D,ONE_YEAR as z,TODAY as I}from"../ticks/TimeSliderConstants.js";import{TimeTicksBar as O}from"../ticks/TimeTicksBar.js";import{YAxisTicks as A}from"../ticks/YAxisTicks.js";const H=B,_=10*S;export class TimeSlider extends L{getLayers(){return[...this.layers]}getVisibleLayers(){return this.getLayers().filter(e=>e.visible)}constructor(i){super(),this.valueRanges=new Map,this.layers=[],this.onDestroy=[],this.ticksBar=new O,this.loaders=new Set,this.layerUnloaders=new Map,this.layerListenerStoppers=new Map,this.layerLoaders=new Map,this.pressedKeys=new Set,this.container=null,this.d=new t,this.id=e(),this.playing=!1,this.live=!1,this._showCurrent=!1,this.current=Date.now(),this.range={time:I,value:{minValue:0,maxValue:100}},this.size={width:100,height:100},this.sliderElement=document.createElement("div"),this.yAxisTicks=new A,this.hoverLine=document.createElement("div"),this.toolTip=document.createElement("div"),this.selectedLabel=document.createElement("div"),this.selectingRangeElement=document.createElement("div"),this.selectionOverlayContainer=document.createElement("div"),this._selectionRanges=[],this.selectionRangeElements=[],this.shadingElements=[],this.columnBandOverlayContainer=document.createElement("div"),this.columnBandElements=[],this.selectingRange=!1,this.selectingRangeVisible=!1,this.updateValueRangesQueue=new Map,this.showingStats=!1,this._engineReady=!1,this.mouse=null,this.updatingLabel=!1,this.hoverCleared=!0,this.dragging=!1,this.pinching=!1,this.hoverOptions=i?.hover||{},this.selectionOptions={highlight:"boolean"!=typeof i?.selection?.highlight||i.selection.highlight,label:"boolean"!=typeof i?.selection?.label||i.selection.label,shading:"boolean"!=typeof i?.selection?.shading||i.selection.shading,invertShading:"boolean"==typeof i?.selection?.invertShading&&i.selection.invertShading,pick:i?.selection?.pick||"element",columnBand:i?.selection?.columnBand},this.showCurrent=i?.showCurrent||!1,this.showTicks=i?.showTicks||!1,this.selectRangeMode=i?.selectRangeMode||"select",this.playSpeed=i?.playSpeed||"auto",this.liveRange=i?.liveRange||10*B,this.theme=i?.theme||"dark",this._locale=i?.locale||a(),d(this._locale),this.ticksBar.setLocale(this._locale),this.ticksBar.setWeekLabel(i?.weekLabel||"default",i?.weekLabelPrefix),this.ticksBar.setTickLabelStyler(i?.tickLabelStyler),this.setLimits(i?.limits),this.syncMaxValues(),this.on("time",()=>this.renderSelectionOverlay()),this.on("size",()=>this.renderSelectionOverlay())}get locale(){return this._locale}setLocale(e){this._locale=e,d(e),this.ticksBar.setLocale(e),this.emit("locale",e)}setWeekLabel(e,t){this.ticksBar.setWeekLabel(e,t)}setTickLabelStyler(e){this.ticksBar.setTickLabelStyler(e)}get limits(){return this._limits?{...this._limits}:void 0}setLimits(e){!e||e.endTime>e.startTime||(console.warn("Ignoring time slider limits whose endTime is not after startTime",e),e=void 0),this._limits=e?{startTime:e.startTime,endTime:e.endTime}:void 0,this._limits&&this.setTimeRange(this.getTimeRange())}setSelection(e){this._selectionRanges=e.map(e=>({...e})),this.renderSelectionOverlay(!0),this.emit("selectionchange",{ranges:this.getSelection(),phase:"end"})}getSelection(){return this._selectionRanges.map(e=>({...e}))}clearSelection(){this.setSelection([])}setPickMode(e){this.selectionOptions.pick=e,this.updateHover()}selectionTimeToX(e,t,i,s){return e===-1/0?0:e===1/0?s:Math.min(s,Math.max(0,(e-t)/(i-t)*s))}renderSelectionOverlay(e=!1){if(!this.container)return;const t=this.getSliderBounds();if(t.width<=0)return;const{startTime:i,endTime:s}=this.getTimeRange(),n=e=>this.selectionTimeToX(e,i,s,t.width);if((e||this.selectionRangeElements.length!==this._selectionRanges.length||this.selectionRangeElements.some((e,t)=>e.range!==this._selectionRanges[t]))&&(this.selectionRangeElements.forEach(({body:e,startHandle:t,endHandle:i})=>{e.remove(),t?.remove(),i?.remove()}),this.selectionRangeElements=this._selectionRanges.map(e=>this.createSelectionRangeElements(e))),this.selectionRangeElements.forEach(({range:e,body:t,startHandle:i,endHandle:s})=>{const l=n(e.startTime),a=n(e.endTime);t.style.left=l+"px",t.style.width=Math.max(0,a-l)+"px",i&&(i.style.left=l-4+"px"),s&&(s.style.left=a-4+"px")}),this.shadingElements.forEach(e=>e.remove()),this.shadingElements=[],this.selectionOptions.shading&&this._selectionRanges.length>0){const e=T(this._selectionRanges).map(e=>[n(e.startTime),n(e.endTime)]);(this.selectionOptions.invertShading?e:function(e,t){const i=[];let s=0;for(const[t,n]of e)t>s&&i.push([s,t]),s=Math.max(s,n);s<t&&i.push([s,t]);return i}(e,t.width)).forEach(([e,t])=>{if(t<=e)return;const i=document.createElement("div");i.style.position="absolute",i.style.top="0px",i.style.height="100%",i.style.left=e+"px",i.style.width=t-e+"px",i.style.background="rgba(0, 0, 0, 0.5)",i.style.pointerEvents="none",this.selectionOverlayContainer.appendChild(i),this.shadingElements.push(i)})}}renderColumnHoverBand(e){if(this.columnBandElements.forEach(e=>e.remove()),this.columnBandElements=[],"column"!==this.selectionOptions.pick||0===e.length||!this.container)return;const t=this.getSliderBounds();if(t.width<=0)return;const{startTime:i,endTime:s}=this.getTimeRange(),n=e=>Math.min(t.width,Math.max(0,(e-i)/(s-i)*t.width)),l=this.selectionOptions.columnBand?.color??"#fff",a=this.selectionOptions.columnBand?.opacity??.15;e.forEach(({layer:e,elements:t})=>{const i=t.map(c),s=Math.min(...i.map(e=>e[0])),o=Math.max(...i.map(e=>e[1])),r=document.createElement("div");r.style.position="absolute",r.style.left=n(s)+"px",r.style.width=Math.max(1,n(o)-n(s))+"px",r.style.top=100*(1-e.max)+"%",r.style.height=100*(e.max-e.min)+"%",r.style.background=l,r.style.opacity=String(a),r.style.pointerEvents="none",this.columnBandOverlayContainer.appendChild(r),this.columnBandElements.push(r)})}createSelectionRangeElements(e){const t=document.createElement("div");t.style.position="absolute",t.style.top="0px",t.style.height="100%",t.style.background="rgba(100, 180, 255, 0.15)",t.style.borderTop="2px solid rgba(100, 180, 255, 0.8)",t.style.borderBottom="2px solid rgba(100, 180, 255, 0.8)",t.style.boxSizing="border-box",t.style.cursor="grab",t.style.pointerEvents="auto",t.style.touchAction="none",this.selectionOverlayContainer.appendChild(t);const i=()=>{const e=document.createElement("div");return e.style.position="absolute",e.style.top="0px",e.style.height="100%",e.style.width="8px",e.style.cursor="ew-resize",e.style.pointerEvents="auto",e.style.touchAction="none",e.style.background="rgba(100, 180, 255, 0.9)",this.selectionOverlayContainer.appendChild(e),e},s=e.startTime===-1/0?null:i(),n=e.endTime===1/0?null:i();return this.wireSelectionDrag(e,t,s,n),{range:e,body:t,startHandle:s,endHandle:n}}wireSelectionDrag(e,t,i,s){const n=(e,t)=>{e.addEventListener("pointerdown",i=>{i.stopPropagation(),i.preventDefault(),e.setPointerCapture(i.pointerId);const s=t(i),n=e=>{s(e),this.renderSelectionOverlay(),this.emit("selectionchange",{ranges:this.getSelection(),phase:"drag"})};let l=!1;const a=t=>{l||(l=!0,e.hasPointerCapture(t.pointerId)&&e.releasePointerCapture(t.pointerId),e.removeEventListener("pointermove",n),e.removeEventListener("pointerup",a),e.removeEventListener("pointercancel",a),e.removeEventListener("lostpointercapture",a),this.emit("selectionchange",{ranges:this.getSelection(),phase:"end"}))};this.emit("selectionchange",{ranges:this.getSelection(),phase:"start"}),e.addEventListener("pointermove",n),e.addEventListener("pointerup",a),e.addEventListener("pointercancel",a),e.addEventListener("lostpointercapture",a)})};i&&n(i,()=>t=>{const{t:i}=this.mouseInSlider(t);e.startTime=e.endTime===1/0?i:Math.min(i,e.endTime)}),s&&n(s,()=>t=>{const{t:i}=this.mouseInSlider(t);e.endTime=e.startTime===-1/0?i:Math.max(i,e.startTime)}),n(t,t=>{const i=this.mouseInSlider(t).t,s=e.startTime,n=e.endTime;return t=>{const l=this.mouseInSlider(t).t-i;s===-1/0&&n!==1/0?e.endTime=n+l:n===1/0&&s!==-1/0?e.startTime=s+l:s!==-1/0&&n!==1/0&&(e.startTime=s+l,e.endTime=n+l)}})}startSelectingRange(e){this.selectingRange=!0,this.whenDoneSelectingRange=e}stopSelectingRange(){this.selectingRange=!1,this.whenDoneSelectingRange?.(),this.whenDoneSelectingRange=void 0,this.selectingRangeVisible&&(this.container.removeChild(this.selectingRangeElement),this.selectingRangeVisible=!1)}syncMaxValues(){return this.updateAllValueRanges(),this.on("time",()=>this.updateAllValueRanges())}syncMaxValuesForLayer(e){return this.updateValueRanges(e.yAxisGroup),e.model.on(()=>this.updateValueRanges(e.yAxisGroup))}updateAllValueRanges(){this.layers.filter(e=>e.visible).forEach(e=>{this.updateValueRanges(e.yAxisGroup,!0)}),this.renderYAxis()}updateValueRanges(e,t){this.updateValueRangesQueue.has(e)||this.updateValueRangesQueue.set(e,{lastUpdate:0,pending:void 0});const i=this.updateValueRangesQueue.get(e);if(Date.now()-i.lastUpdate<100)return i.pending&&clearTimeout(i.pending),void(i.pending=setTimeout(()=>{i.pending=void 0,this.updateValueRanges(e)},200));i.lastUpdate=Date.now();const s=new Map,n=new Map;this.layers.filter(e=>e.visible).forEach(e=>{const t=e.yAxis.group||e.id;s.has(t)||(s.set(t,-Number.MAX_VALUE),n.set(t,Number.MAX_VALUE));const i=e.model.getValueRange(this.getTimeRange());i.minValue<n.get(t)&&n.set(t,i.minValue),i.maxValue>s.get(t)&&s.set(t,i.maxValue)}),this.valueRanges.clear(),s.forEach((e,t)=>{this.valueRanges.set(t,{max:e,min:n.get(t)})}),t||this.renderYAxis(),this.emit("valueRanges",e)}renderYAxis(){const e=new Map;this.layers.filter(e=>e.visible).forEach(t=>{const i=t.yAxis.group||t.id;e.has(i)||e.set(i,{min:t.min,max:t.max,group:i}),e.set(i,{...e.get(i),...t.yAxis,min:t.min,max:t.max})});const t=[];e.forEach(e=>{if(e.visible){const i=this.valueRanges.get(e.group);i&&t.push({...e,minValue:i.min,maxValue:i.max})}}),this.yAxisTicks.render(t)}setTheme(e){this.theme=e,this.ticksBar.setDarkMode("dark"===e),this.engine?.setTheme(e)}addLayerLoader(e){this.loaders.add(e)}showStats(e){this.showingStats=e,this.engine?.showStats(e)}get engineReady(){return this._engineReady}whenReady(){return this._engineReady?Promise.resolve():new Promise(e=>{const t=this.on("ready",()=>{t(),e()})})}async setEngine(e){this._engineReady=!1,this.engine&&(this.layerUnloaders.forEach(e=>e()),this.layerUnloaders.clear(),this.engine.dispose()),this.initSliderContainer(),this.engine=e,this.engine.setTheme(this.theme),await this.engine.init(this.sliderElement),this.engine.setTheme(this.theme),this._engineReady=!0,this.emit("ready"),this.getVisibleLayers().forEach(e=>this.loadLayer(e)),this.engine.showStats(this.showingStats),this.engine.setTimeRange(this.getTimeRange()),this.engine.setValueRange(this.getValueRange()),this.engine.setSize(this.size.width,this.size.height)}initSliderContainer(){this.stopControls&&this.stopControls(),this.container?.removeChild(this.sliderElement);let e=0;this.showTicks&&(e+=24),this.showCurrent&&(e+=4),this.sliderElement=document.createElement("div"),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top="0px",this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${0+e}px)`,this.container?.appendChild(this.sliderElement),this.initSelectLabel(),this.stopControls=this.initControls(),this.onDestroy.push(()=>{this.container?.removeChild(this.sliderElement)})}get showCurrent(){return this._showCurrent}set showCurrent(e){if(e!==this._showCurrent){this._showCurrent=e,this.ticksBar.showLine=!this.showCurrent;let t=0,i=0;this.showTicks&&(i+=24),this.showCurrent&&(i+=4),this.sliderElement.style.height=`calc(100% - ${t+i}px)`}}async init(e,t){const i="string"==typeof e?document.getElementById(e):e;if(this.container=i,i){i.oncontextmenu=()=>!1;let e=0,s=0;if(this.showTicks){s+=24;const e=document.createElement("div");e.style.width="100%",e.style.height="24px",e.style.position="absolute",e.style.bottom="0px",e.style.touchAction="none",i.appendChild(e),this.ticksBar.init(e,e=>{const t=r(e.startTime,e.endTime);this.emit("tickclick",{startTime:e.startTime,endTime:e.endTime,unit:t}),this.fit({range:e,animate:1e3})}),this.ticksBar.showLine=!this.showCurrent}this.showCurrent&&(s+=4),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top=`${e}px`,this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.sliderElement),this.yAxisTicks.canvas.style.top=`${e}px`,this.yAxisTicks.canvas.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.yAxisTicks.canvas),this.selectionOverlayContainer.style.position="absolute",this.selectionOverlayContainer.style.width="100%",this.selectionOverlayContainer.style.overflow="hidden",this.selectionOverlayContainer.style.pointerEvents="none",this.selectionOverlayContainer.style.top=`${e}px`,this.selectionOverlayContainer.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.selectionOverlayContainer),this.onDestroy.push(()=>i.removeChild(this.selectionOverlayContainer)),this.columnBandOverlayContainer.style.position="absolute",this.columnBandOverlayContainer.style.width="100%",this.columnBandOverlayContainer.style.overflow="hidden",this.columnBandOverlayContainer.style.pointerEvents="none",this.columnBandOverlayContainer.style.top=`${e}px`,this.columnBandOverlayContainer.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.columnBandOverlayContainer),this.onDestroy.push(()=>i.removeChild(this.columnBandOverlayContainer)),this.initHoverTooltip(),this.initSelectLabel(),this.setSize(this.sliderElement.clientWidth,this.sliderElement.clientHeight),this.syncSize(),this.setTimeRange($(t)),this.setValueRange($(t))}else console.warn(`Element ${e} not found`)}initSelectLabel(){this.selectedLabel.style.position="absolute",this.selectedLabel.style.padding="4px 8px",this.selectedLabel.style.background="rgba(0, 0, 0, 0.75)",this.selectedLabel.style.color="white",this.selectedLabel.style.fontSize="12px",this.selectedLabel.style.maxWidth="200px",this.selectedLabel.style.fontFamily="monospace",this.selectedLabel.style.borderRadius="4px",this.selectedLabel.style.pointerEvents="none",this.selectedLabel.style.display="none",this.selectedLabel.style.zIndex="10",this.sliderElement.appendChild(this.selectedLabel)}getLabel(e,t,i,s){if(t.labeler){const n=t.labeler(e,i,s);return null===n?null:"string"==typeof n?`<div>${n}</div>`:n?n.outerHTML:`<div>${e.name||e.id}</div>`}return`<div>${e.name||e.id}</div>`}getLayerById(e){return this.layers.find(t=>t.id===e)}select(e,t){this.stopSelectingRange(),this.stopUpdatingLabel?.();const i=()=>{this.updatingLabel=!1,this.stopUpdatingLabel?.(),this.stopUpdatingLabel=void 0,this.selectedLabel.style.display="none",this.layers.forEach(e=>e.select([])),this.selectedLayerId=void 0,this.emit("select",[])},s=e=>{this.layers.filter(t=>!e.some(e=>t.id===e.layer.id)).forEach(e=>e.select([])),e.forEach(e=>{e.layer.select(e.elements)}),this.emit("select",e)};if(t){s(this.getVisibleLayers().map(e=>{const i=e.model.dataInTimeRange(t);return{layer:e,elements:i}}).filter(e=>e.elements.length>0))}else if(e){const t=this.findElements(e,24);if(s(t.map(e=>({layer:e.layer,elements:e.elements})).flat()),1===t.length&&t[0].elements.length>0&&this.selectionOptions.label){const e=t[0].elements[0],s=t[0].layer;this.selectedLabel.innerHTML=this.getLabel(e,s,t[0].t,t[0].v)||"",this.selectedLabel.style.display="block";const n=this.selectedLabel.offsetWidth,l=this.selectedLabel.offsetHeight;this.selectedLayerId=s.id;const a=Array.isArray(e.t);this.updatingLabel=!0;const o=()=>{if(!this.updatingLabel)return;const{startTime:i,duration:s,endTime:o}=this.getTimeRange(),r=t[0].layer.model.get(e.id);if(r){const e=f(this.getTimeRange(),r.t);if(e){const o=this.getSliderBounds();let h=(.5*(e.startTime+e.endTime)-i)/s*o.width;const d="number"==typeof r.v?r.v:.5*(r.v[1]+r.v[0]);let m=this.modelValueToPixels(d,t[0].layer);a?m-=.5*l:m+=8;const c=.5*n,g=.5*l,u=o.width-.5*n,p=o.height-.5*l,y=Math.min(u,Math.max(c,h)),v=Math.min(p,Math.max(g,m));this.selectedLabel.style.display="block",this.selectedLabel.style.left=y-.5*n+"px",this.selectedLabel.style.top=`${v}px`}else this.selectedLabel.style.display="none"}else this.selectedLabel.style.display="none"};o();const r=s instanceof x&&s.histogram instanceof m;this.stopUpdatingLabel=this.on("time",r?i:o)}}else i()}listenToClicks(){let e=null;const t=t=>{e={x:t.clientX,y:t.clientY}},i=t=>{if(!e)return;const i=t.clientX-e.x,s=t.clientY-e.y;i*i+s*s<=25&&(this.stopSelectingRange(),this.select(e)),e=null},s=()=>{e=null};return this.sliderElement.addEventListener("pointerdown",t),this.sliderElement.addEventListener("pointerup",i),this.sliderElement.addEventListener("pointercancel",s),()=>{this.sliderElement.removeEventListener("pointerdown",t),this.sliderElement.removeEventListener("pointerup",i),this.sliderElement.removeEventListener("pointercancel",s)}}getSliderBounds(){return this.sliderElement.getBoundingClientRect()}mouseInSlider(e){const t=this.getSliderBounds(),i="x"in e?e:{x:e.clientX,y:e.clientY},s={x:i.x-t.left,y:i.y-t.top},n={x:s.x/t.width,y:-s.y/t.height+1},{startTime:l,duration:a}=this.getTimeRange(),o=l+n.x*a,{minValue:r,maxValue:h}=this.getValueRange();return{absolute:s,normalized:n,t:o,v:r+n.x*(h-r)}}pixelsToLayerValue(e,t){if(!e)return{yInLayer:0,toLayerHeight:1};const i="normalized"in e?e.normalized:this.mouseInSlider(e).normalized;let s=t.min;const n=t.max-s;return{yInLayer:(i.y-s)/n,toLayerHeight:n/this.getSliderBounds().height}}pixelsToModelValue(e,t){const{yInLayer:i,toLayerHeight:s}=this.pixelsToLayerValue(e,t);let n=0,l=100;if(t.model instanceof g){const e=this.valueRanges.get(t.yAxisGroup)||{min:0,max:1e3};n=e.min,l=e.max-n}return{yInModel:n+i*l,toModelHeight:s*l}}layerValueToPixels(e,t){let i=t.min;return(1-(i+(t.max-i)*e))*this.getSliderBounds().height}modelValueToPixels(e,t){let i=0,s=100;if(t.model instanceof g){const e=t.model.getValueRange(this.getTimeRange());i=e.minValue,s=e.maxValue-i}const n=(e-i)/s;return this.layerValueToPixels(n,t)}findElements(e,t){if("column"===this.selectionOptions.pick)return this.findColumnElements(e);const{width:i,height:s}=this.getSliderBounds(),{normalized:n}=this.mouseInSlider(e),{startTime:l,endTime:a,duration:o}=this.getTimeRange(),r=l+n.x*o,h=t||12,d=h/i*o,m={startTime:r-1,endTime:r+1},c={startTime:r-.5*d,endTime:r+.5*d};return this.getVisibleLayers().map(e=>{const{yInModel:t,toModelHeight:i}=this.pixelsToModelValue({normalized:n},e),s=e instanceof R?0:h*i,l=e instanceof R?m:c,a={minValue:t-.5*s,maxValue:t+.5*s},o=e.model.dataInRange({...l,...a});return{layer:e,elements:o,t:r,v:t}}).filter(e=>e.elements.length>0)}findColumnElements(e,t){const{width:i}=this.getSliderBounds(),{normalized:s}=this.mouseInSlider(e),{startTime:n,duration:l}=this.getTimeRange(),a=n+s.x*l,o=(t||12)/i*l,r={startTime:a-1,endTime:a+1},h={startTime:a-.5*o,endTime:a+.5*o};return this.getVisibleLayers().map(e=>{const{yInModel:t}=this.pixelsToModelValue({normalized:s},e),i=e instanceof R?r:h,n=e.model.dataInTimeRange(i);return{layer:e,elements:n,t:a,v:t}}).filter(e=>e.elements.length>0)}clearHoverEvent(){this.hoverCleared||(this.hoverCleared=!0,this.renderColumnHoverBand([]),this.emit("hover",null))}updateHover(e){if(this.dragging)return this.hoverLine.style.display="none",this.toolTip.style.display="none",void this.clearHoverEvent();if(void 0!==e&&(this.mouse=e),this.mouse){const e=this.getSliderBounds(),{normalized:t}=this.mouseInSlider(this.mouse),{startTime:i,endTime:n,duration:l}=this.getTimeRange(),a=i+t.x*l,o=this.findElements(this.mouse);this.renderColumnHoverBand(o),this.hoverCleared=!1,this.emit("hover",{elements:o.map(e=>({layer:e.layer,elements:e.elements})),t:a,clientX:this.mouse.x,clientY:this.mouse.y});const r=o.map(e=>e.elements.map(t=>({e:t,l:e.layer,t:e.t,v:e.v}))).flat();let h;if(r.length>0)if(r.length>3){h=r.slice(0,2).map(e=>this.getLabel(e.e,e.l,e.t,e.v)).flat().filter(e=>null!==e).join(""),h+=`<div>And ${r.length-2} more...</div>`}else{h=o.map(e=>e.elements.map(t=>this.getLabel(t,e.layer,e.t,e.v))).flat().filter(e=>null!==e).join("")}if(!1===this.hoverOptions.tooltip)this.toolTip.style.display="none";else{const t=new Date(a),i=t.getHours(),n=t.getMinutes(),l=t.getSeconds(),o=s(a,!0,this._locale),r=`${(i<10?"0":"")+i}:${(n<10?"0":"")+n}:${(l<10?"0":"")+l}`;let d="";const m=this.ticksBar.cache.high.spacing;(void 0===this.hoverOptions.date?m>=V:this.hoverOptions.date)&&(d+=`<div>${o}</div>`),(void 0===this.hoverOptions.time?m<=C:this.hoverOptions.time)&&(d+=`<div>${r}</div>`),h&&(d+=h),this.toolTip.innerHTML=d,this.toolTip.style.display=d.length>0?"block":"none";const c=88,g=36;let u=this.mouse.x+10,p=this.mouse.y+10;const y=e.left+e.width-c-5,v=e.top+e.height-g-5;u>y&&(u=y),p>v&&(p=v),this.toolTip.style.left=`${u}px`,this.toolTip.style.top=`${p}px`}}else this.hoverLine.style.display="none",this.toolTip.style.display="none",this.clearHoverEvent()}initHoverTooltip(){this.toolTip.style.position="absolute",this.toolTip.style.padding="4px 8px",this.toolTip.style.background="rgba(0, 0, 0, 0.75)",this.toolTip.style.color="white",this.toolTip.style.fontSize="12px",this.toolTip.style.fontFamily="monospace",this.toolTip.style.borderRadius="4px",this.toolTip.style.pointerEvents="none",this.toolTip.style.display="none",this.toolTip.style.zIndex="10",this.toolTip.style.overflow="hidden",document.body.appendChild(this.toolTip)}initHoverListener(){const e=()=>{this.updateHover(null)},t=e=>{this.updateHover({x:e.clientX,y:e.clientY})};this.sliderElement.addEventListener("mouseleave",e),this.sliderElement.addEventListener("mousemove",t);const i=this.listenToClicks();return()=>{this.sliderElement.removeEventListener("mouseleave",e),this.sliderElement.removeEventListener("mousemove",t),i()}}syncSize(){const e=()=>{const{offsetWidth:e,offsetHeight:t}=this.sliderElement;this.setSize(e,t)},t=new ResizeObserver(()=>{e()});this.container&&(t.observe(this.container),e()),this.onDestroy.push(()=>{t.disconnect()})}getTimeRange(){return u(this.range.time)}getValueRange(){return this.range.value}setTimeRange(e,t){const i=this.getTimeRange(),s=y(i,e),n=this._limits?v(s,this._limits):s;n.startTime===i.startTime&&n.endTime===i.endTime||(this.range.time=n,this.engine?.setTimeRange(n),this.showTicks&&this.ticksBar.setTimeRange(n),this.emit("time",n),this.updateHover())}setValueRange(e){const t={...this.getValueRange(),...e};this.range.value=t,this.engine?.setValueRange(t),this.emit("value",this.getValueRange()),this.updateHover()}setSize(e,t){this.size={width:e,height:t},this.showTicks&&this.ticksBar.setWidth(e);const i=this.getTimeRange(),s=this.getValueRange();this.engine?.setSize(e,t),this.setTimeRange(i),this.setValueRange(s),this.updateHover(),this.emit("size",{width:e,height:t})}up(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let n={startTime:0,endTime:Date.now()};const l=.5*(t+i);if(s>=.9*S){const e=U(10*s);n=o(l,e)}else{const e=[{threshold:b,unit:"millennium"},{threshold:w,unit:"century"},{threshold:z,unit:"decade"},{threshold:.9*M,unit:"year"},{threshold:D,unit:"month"},{threshold:C,unit:"week"},{threshold:V,unit:"day"},{threshold:k,unit:"hour"},{threshold:B,unit:"minute"},{threshold:-1,unit:"second"}];let t=0;for(;s<.9*e[t].threshold;)t++;const i=e[t].unit;n=h(l,i)}this.fit({...e,range:n})}down(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let n={startTime:0,endTime:Date.now()};const l=t+("number"==typeof e?.xRatio?e.xRatio:.5)*s;if(s>=.9*S){const e=U(s/10);n=o(l,e)}else{let e=0;const t=[{threshold:S,unit:"century"},{threshold:b,unit:"decade"},{threshold:w,unit:"year"},{threshold:z,unit:"month"},{threshold:1.1*M,unit:"week"},{threshold:D,unit:"day"},{threshold:C,unit:"hour"},{threshold:V,unit:"minute"},{threshold:k,unit:"second"}].reverse();for(;s>1.1*t[e].threshold;)e++;const i=t[e].unit;n=h(l,i)}this.fit({...e,range:n})}next(e){this.skip(1,e)}previous(e){this.skip(-1,e)}skip(e,t){let i={startTime:0,endTime:Date.now()};const{startTime:s,endTime:n,duration:l}=this.getTimeRange(),a=.5*(s+n);if(l>=9*S){const e=U(l);i=o(a,e)}else{const t=r(s,n);i=t?h(a,t,Math.round(e)):{startTime:s+e*l,endTime:n+e*l}}this.fit({...t,range:i})}getTimeRangeLabel(){const{startTime:e,endTime:t}=this.getTimeRange(),i=new Date(e);return 0===i.getHours()&&0===i.getMinutes()&&0===i.getSeconds()&&0===i.getMilliseconds()?n([e,t],this._locale):void 0}cancelFit(){this.stopFit?.(),this.stopFit=void 0}fit(e){this.cancelFit();const t=e?.range||this.getLayersTimeRange(),s=e?.padding?p(t,e.padding):t;if(e?.animate){const t=this.getTimeRange();this.stopFit=i(t.startTime,t.endTime,s.startTime,s.endTime,e.animate,(e,t)=>this.setTimeRange({startTime:e,endTime:t}))}else this.setTimeRange(s)}getLayersTimeRange(){if(0===this.getVisibleLayers().length)return I;{let e=this.getVisibleLayers()[0].model.getTimeRange();return this.getVisibleLayers().slice(1).forEach(t=>e=E(e,t.model.getTimeRange())),e}}loadLayer(e){if(e.timeSlider&&e.timeSlider.id!==this.id)console.warn("Layer already has been loaded by another time slider, create a new layer with the same model and style if you want to add it to another time slider");else if(this.engine&&this._engineReady&&!this.layerUnloaders.has(e.id)){const t=[...this.loaders].filter(e=>this.engine instanceof e.engineClass).find(t=>t.canLoad(e));if(t){const i=Date.now(),s=t.load(e,this.engine.scene,this.engine,this);e.timeSlider=this,e.loaded=!0;const n=e.name||e.constructor.name+"#"+e.id.slice(e.id.length-4).toUpperCase();console.log(`Loaded ${n} in ${l(Date.now()-i)}`);const a=this.syncMaxValuesForLayer(e);this.layerLoaders.set(e.id,t),this.layerUnloaders.set(e.id,()=>{a(),s(),this.layerLoaders.delete(e.id),e.loaded=!1})}else console.warn("No loader found for",{layer:e})}}unloadLayer(e){this.selectedLayerId===e.id&&this.select(null),this.layerUnloaders.has(e.id)&&(this.layerUnloaders.get(e.id)(),this.layerUnloaders.delete(e.id))}addLayer(e){if(this.layers.push(e),e.visible){this.loadLayer(e);const t=e.model.getTimeRange();if(1===this.getVisibleLayers().length)this.setTimeRange(t);else{const e=E(this.getTimeRange(),t);this.setTimeRange(e)}}const t=[e.on("visible",()=>{e.visible?this.loadLayer(e):this.unloadLayer(e),this.updateAllValueRanges()}),e.on("min",()=>this.onLayerBandChange(e)),e.on("max",()=>this.onLayerBandChange(e))];this.layerListenerStoppers.set(e.id,()=>t.forEach(e=>e()))}onLayerBandChange(e){const t=this.layerLoaders.get(e.id);t&&!t.followsLayerBand&&(this.layerUnloaders.get(e.id)?.(),this.layerUnloaders.delete(e.id),this.loadLayer(e)),this.updateAllValueRanges()}removeLayer(e){const t="string"==typeof e?e:e.id,i=this.layers.find(e=>e.id===t);i&&(this.unloadLayer(i),this.layerUnloaders.delete(t),this.layerListenerStoppers.get(t)?.(),this.layerListenerStoppers.delete(t),this.layers=this.layers.filter(e=>e.id!==t))}destroy(){this.layers.map(e=>e.id).forEach(e=>this.removeLayer(e)),this.onDestroy.forEach(e=>e())}addHorizontalPinchZoom(){let e=null,t=null;const i=()=>{this.pinching=!1,e=null,t=null},s=i=>{if(2===i.touches.length){i.preventDefault(),this.dragging=!1,this.pinching=!0;const s=this.mouseInSlider(i.touches[0]).t,n=this.mouseInSlider(i.touches[1]).t;e=Math.min(s,n),t=Math.max(s,n)}},n=s=>{if(2===s.touches.length){if(null===e||null===t)return;s.preventDefault(),this.dragging=!1;const i=this.mouseInSlider(s.touches[0]).normalized.x,n=this.mouseInSlider(s.touches[1]).normalized.x,l=Math.min(i,n),a=Math.max(i,n),o=(t-e)/(a-l);let r=e-l*o,h=t+(1-a)*o;if(o>_){const e=.5*(r+h);r=e-.5*_,h=e+.5*_}if(o<H){const e=.5*(r+h);r=e-.5*H,h=e+.5*H}this.setTimeRange({startTime:r,endTime:h})}else i()},l=()=>{i()};this.sliderElement.addEventListener("touchstart",s,{passive:!1}),this.sliderElement.addEventListener("touchmove",n,{passive:!1}),this.sliderElement.addEventListener("touchend",l),this.sliderElement.addEventListener("touchcancel",l),this.onDestroy.push(()=>{this.sliderElement.removeEventListener("touchstart",s),this.sliderElement.removeEventListener("touchmove",n),this.sliderElement.removeEventListener("touchend",l),this.sliderElement.removeEventListener("touchcancel",l)})}initControls(){const e=new t;this.dragging=!1;let i,s=0,n=0,l=0;e.add(this.initHoverListener());const a=e=>{this.sliderElement.focus(),e.preventDefault();const t=this.mouseInSlider(e);this.zoom(.001*e.deltaY,{x:t.normalized.x})};let o=0,r=-1;const h=e=>{const t=Date.now(),i=t-o;r>=0&&i<300&&i>0&&(this.select(null),e.preventDefault(),this.zoom(-.75,{animate:1e3,x:r})),o=t},d=e=>{e.preventDefault(),this.select(null);const t=this.mouseInSlider(e);this.zoom(-.75,{animate:1e3,x:t.normalized.x})};this.selectingRangeElement.style.height="calc(100% - 6px)",this.selectingRangeElement.style.pointerEvents="none",this.selectingRangeElement.style.position="absolute",this.selectingRangeElement.style.border="3px solid #df0",this.selectingRangeElement.style.background="#df04",this.selectingRangeElement.style.top="0px";const m=e=>{if(this.sliderElement.focus(),2===e.button||0===e.button){e.preventDefault();const t=this.mouseInSlider(e),i=t.normalized.x,{startTime:a,duration:o}=this.getTimeRange();s=a+i*o,n=Date.now(),l=t.absolute.x,(e.ctrlKey||2===e.button)&&(this.selectingRange=!0),this.selectingRange?(this.selectingRangeElement.style.left=t.absolute.x+"px",this.selectingRangeElement.style.width="0px",this.container.appendChild(this.selectingRangeElement),this.selectingRangeVisible=!0):this.dragging=!0}},c=e=>{const t=this.mouseInSlider(e);return i=t.normalized.x,t},g=e=>{const t=c(e);if(this.selectingRange){const e=Math.abs(l-t.absolute.x),i=Math.min(l,t.absolute.x);this.selectingRangeElement.style.left=i+"px",this.selectingRangeElement.style.width=e-6+"px"}if(!this.dragging||Date.now()-n<100&&Math.abs(l-t.absolute.x)<10)return;e.preventDefault();const i=t.normalized.x,{startTime:a,endTime:o}=this.getTimeRange(),r=a+i*(o-a)-s;this.setTimeRange({startTime:a-r,endTime:o-r})},u=e=>{const t=this.getSliderBounds(),n=t.height-(e.clientY-t.top);if(!this.dragging&&!this.pinching&&n<8)this.ticksBar.click(e);else if(i=void 0,this.dragging=!1,this.selectingRange){const t=this.mouseInSlider(e).normalized.x,{startTime:i,endTime:n}=this.getTimeRange(),l=i+t*(n-i);"zoom"===this.selectRangeMode&&this.fit({range:{startTime:Math.min(s,l),endTime:Math.max(s,l)},animate:1e3}),"select"===this.selectRangeMode&&this.select(null,{startTime:Math.min(s,l),endTime:Math.max(s,l)}),"createSelection"===this.selectRangeMode&&this.setSelection([...this.getSelection(),{startTime:Math.min(s,l),endTime:Math.max(s,l)}])}this.stopSelectingRange()},p=e=>{this.pressedKeys.add(e.code)},y=e=>{this.pressedKeys.delete(e.code),"Space"===e.code&&(e.preventDefault(),this.togglePlaying()),"KeyF"===e.code&&(e.preventDefault(),this.fit({animate:3e3}));const t=void 0;"ArrowRight"===e.code&&(e.preventDefault(),this.skip(1,{animate:t})),"ArrowLeft"===e.code&&(e.preventDefault(),this.skip(-1,{animate:t})),"ArrowUp"===e.code&&(e.preventDefault(),this.up({animate:t})),"ArrowDown"===e.code&&(e.preventDefault(),this.down({xRatio:i,animate:t}))};let v=!0;const T=()=>{if(v){const e=this.pressedKeys.has("ShiftLeft")?.05:.01,t=2*e,s=this.pressedKeys.has("KeyD"),n=this.pressedKeys.has("KeyA");s&&this.shift(-e),n&&this.shift(e),this.pressedKeys.has("KeyW")&&this.zoom(-t,{x:s||n?void 0:i}),this.pressedKeys.has("KeyS")&&this.zoom(t,{x:s||n?void 0:i}),requestAnimationFrame(T)}};T(),e.add(()=>v=!1);const f=e=>e.preventDefault();this.sliderElement.addEventListener("contextmenu",f),this.sliderElement.addEventListener("wheel",a),this.sliderElement.addEventListener("pointerdown",m),this.sliderElement.addEventListener("pointermove",g),this.sliderElement.addEventListener("pointerup",u),this.sliderElement.addEventListener("dblclick",d),this.sliderElement.addEventListener("touchend",h),this.sliderElement.addEventListener("touchstart",e=>{if(1===e.touches.length){const t=this.mouseInSlider(e.touches[0]);r=t.normalized.x}else r=-1}),this.sliderElement.addEventListener("keydown",p),this.sliderElement.addEventListener("keyup",y),this.addHorizontalPinchZoom();const E=()=>{this.sliderElement.removeEventListener("contextmenu",f),this.sliderElement.removeEventListener("wheel",a),this.sliderElement.removeEventListener("pointerdown",m),this.sliderElement.removeEventListener("pointermove",g),this.sliderElement.removeEventListener("pointerup",u),this.sliderElement.removeEventListener("dblclick",d),this.sliderElement.removeEventListener("touchend",h),this.sliderElement.removeEventListener("keydown",p),this.sliderElement.removeEventListener("keyup",y)};return this.onDestroy.push(E),e.add(E),e.disposeLater()}shift(e,t){const{startTime:i,endTime:s,duration:n}=this.getTimeRange(),l=t?.absolute?e:e*n;this.fit({...t,range:{startTime:i-l,endTime:s-l}})}zoom(e,t){const i="number"==typeof t?.x?t.x:.5,{startTime:s,endTime:n,duration:l}=this.getTimeRange(),a={startTime:s-e*l*i,endTime:n+e*l*(1-i)},o=a.endTime-a.startTime,r=a.startTime+.5*o;o>_&&(a.startTime=r-.5*_,a.endTime=r+.5*_),o<H&&(a.startTime=r-.5*H,a.endTime=r+.5*H),this.fit({range:a,animate:t?.animate})}togglePlaying(){this.playing?this.pause():this.play()}isPlaying(){return this.playing}play(){if(this.playing)return;this.playing=!0,this.emit("playing",!0);let e=Date.now();const t=()=>{if(this.playing){if(this.live){const{duration:e}=this.getTimeRange(),t=Date.now(),i=10/this.size.width;this.setTimeRange({startTime:t-(1-i)*e,endTime:t+i*e}),this.setCurrent(t)}else if("auto"!==this.playSpeed||this.showCurrent){const t=Date.now(),i=t-e,s=this.current-this.getTimeRange().startTime,n="auto"===this.playSpeed?1:this.playSpeed;this.shift(-n*i,{absolute:!0}),this.setCurrent(this.getTimeRange().startTime+s),e=t}else{const t=Date.now();let i=5e-5*(t-e);this.pressedKeys.has("ShiftLeft")&&(i*=5);const s=this.current-this.getTimeRange().startTime;this.shift(-i),this.setCurrent(this.getTimeRange().startTime+s),e=t}requestAnimationFrame(t)}};t()}setCurrent(e){this.current!==e&&(Math.abs(e-Date.now())>100&&this.live&&(this.pause(),this.setLive(!1)),this.current=e,this.emit("current",e))}pause(){this.playing&&(this.playing=!1,this.emit("playing",!1),this.setLive(!1))}setLive(e){if(this.live!==e){if(this.live=e,e){const e=this.getTimeRange();this.fit({range:{startTime:e.endTime-this.liveRange,endTime:e.endTime},animate:B}),this.play()}this.emit("live",e)}}}function $(e){return{startTime:"number"==typeof e?.startTime?e.startTime:"number"==typeof e?.endTime?e.duration?e.endTime-e.duration:e.endTime-C:e?.duration?Date.now()-.5*e.duration:Date.now()-.5*C,endTime:"number"==typeof e?.endTime?e.endTime:"number"==typeof e?.startTime?e.duration?e.startTime+e.duration:e.startTime+C:e?.duration?Date.now()+.5*e.duration:Date.now()+.5*C,duration:e?.duration?e.duration:"number"==typeof e?.startTime&&"number"==typeof e?.endTime?e.endTime+e.startTime:C,minValue:"number"==typeof e?.minValue?e.minValue:"number"==typeof e?.maxValue?e.maxValue>0?0:e.maxValue-100:0,maxValue:"number"==typeof e?.maxValue?e.maxValue:"number"==typeof e?.minValue?e.minValue<0?0:e.minValue+100:100}}function U(e){const t=e/315576e5,i=Math.log10(t),s=Math.ceil(i);return Math.pow(10,s)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TypedEventEmitter as e}from"../event/TypedEventEmitter";import{TODAY as t}from"../ticks/TimeSliderConstants";import{addDuration as i}from"../data/TimeSliderRange";export class TimeSliderEngine extends e{constructor(e){super(),this.scene=e,this.timeRange=t,this.valueRange={minValue:0,maxValue:100},this.size={width:1e3,height:100},this.theme="dark"}setTheme(e){this.theme=e,this.setTimeRange(this.timeRange)}getTimeRange(){return{...this.timeRange,duration:this.timeRange.endTime-this.timeRange.startTime}}getValueRange(){return this.valueRange}getSize(){return this.size}showStats(e){}dispose(){this.destroy(),this.size={width:1e3,height:100}}setTimeRange(e){if(e.startTime!==this.timeRange.startTime||e.endTime!==this.timeRange.endTime){this.timeRange=e;const t=i(e);this.updateTimeRange(t),this.emit("time",t)}}setValueRange(e){e.minValue===this.valueRange.minValue&&e.maxValue===this.valueRange.maxValue||(this.valueRange=e,this.updateValueRange(e),this.emit("value",e))}setSize(e,t){this.size.width===e&&this.size.height===t||(this.size={width:e,height:t},this.updateSize(e,t),this.emit("size",this.size))}}
|
|
1
|
+
import{TypedEventEmitter as e}from"../event/TypedEventEmitter.js";import{TODAY as t}from"../ticks/TimeSliderConstants.js";import{addDuration as i}from"../data/TimeSliderRange.js";export class TimeSliderEngine extends e{constructor(e){super(),this.scene=e,this.timeRange=t,this.valueRange={minValue:0,maxValue:100},this.size={width:1e3,height:100},this.theme="dark"}setTheme(e){this.theme=e,this.setTimeRange(this.timeRange)}getTimeRange(){return{...this.timeRange,duration:this.timeRange.endTime-this.timeRange.startTime}}getValueRange(){return this.valueRange}getSize(){return this.size}showStats(e){}dispose(){this.destroy(),this.size={width:1e3,height:100}}setTimeRange(e){if(e.startTime!==this.timeRange.startTime||e.endTime!==this.timeRange.endTime){this.timeRange=e;const t=i(e);this.updateTimeRange(t),this.emit("time",t)}}setValueRange(e){e.minValue===this.valueRange.minValue&&e.maxValue===this.valueRange.maxValue||(this.valueRange=e,this.updateValueRange(e),this.emit("value",e))}setSize(e,t){this.size.width===e&&this.size.height===t||(this.size={width:e,height:t},this.updateSize(e,t),this.emit("size",this.size))}}
|
package/index.d.ts
CHANGED
|
@@ -1 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
export * from './engine/TimeSlider';
|
|
2
|
+
export * from './engine/TimeSliderEngine';
|
|
3
|
+
export * from './engine/PinchZoom';
|
|
4
|
+
export * from './engine/HorizontalPinchZoom';
|
|
5
|
+
export * from './three/ThreeTimeSlider';
|
|
6
|
+
export * from './three/ThreeTimeSliderEngine';
|
|
7
|
+
export * from './three/Three3DTimeSliderEngine';
|
|
8
|
+
export * from './three/react/ReactThreeTimeSlider';
|
|
9
|
+
export * from './three/layer/ThreeTimeLayerLoader';
|
|
10
|
+
export * from './three/layer/ThreePointsTimeLayerLoader';
|
|
11
|
+
export * from './three/layer/ThreeIntervalsTimeLayerLoader';
|
|
12
|
+
export * from './three/layer/Three3DPointsTimeLayerLoader';
|
|
13
|
+
export * from './three/layer/Three3DIntervalsTimeLayerLoader';
|
|
14
|
+
export * from './react/ReactTimeSlider';
|
|
15
|
+
export * from './react/ColoredSlider';
|
|
16
|
+
export { ColoredSliderExtendsInput } from './react/ColoredSliderExtendsInput';
|
|
17
|
+
export type { ColoredSliderInputElement } from './react/ColoredSliderExtendsInput';
|
|
18
|
+
export * from './react/FullscreenButton';
|
|
19
|
+
export * from './react/MaterialIconButton';
|
|
20
|
+
export * from './react/MaterialTextButton';
|
|
21
|
+
export * from './react/DateLabelWithPicker';
|
|
22
|
+
export * from './react/TimeLabelWithPicker';
|
|
23
|
+
export * from './react/DateRangeLabelWithPicker';
|
|
24
|
+
export * from './react/YearScroller';
|
|
25
|
+
export * from './react/PointerClick';
|
|
26
|
+
export * from './react/PinchZoomHook';
|
|
27
|
+
export * from './react/DeepMemoHook';
|
|
28
|
+
export * from './data/TimeSliderElement';
|
|
29
|
+
export * from './data/TimeSliderModel';
|
|
30
|
+
export * from './data/TimeSliderPointsModel';
|
|
31
|
+
export * from './data/TimeSliderIntervalsModel';
|
|
32
|
+
export * from './data/CompositeTimeSliderModel';
|
|
33
|
+
export * from './data/TimeSliderRange';
|
|
34
|
+
export * from './data/TimeSliderBush';
|
|
35
|
+
export * from './data/IntervalLaneManager';
|
|
36
|
+
export * from './data/TimeSliderLanesModel';
|
|
37
|
+
export * from './data/histogram/TimeSliderHistogram';
|
|
38
|
+
export * from './data/histogram/TimeSliderFixedHistogram';
|
|
39
|
+
export * from './data/histogram/TimeSliderDynamicHistogram';
|
|
40
|
+
export * from './data/histogram/TimeSliderSplittingFixedHistogram';
|
|
41
|
+
export * from './layer/TimeSliderLayer';
|
|
42
|
+
export * from './layer/TimeSliderLayerLoader';
|
|
43
|
+
export * from './layer/TimeSliderPointsLayer';
|
|
44
|
+
export * from './layer/TimeSliderIntervalsLayer';
|
|
45
|
+
export * from './layer/TimeSliderHistogramLayer';
|
|
46
|
+
export * from './style/TimeSliderStyle';
|
|
47
|
+
export * from './style/TimeSliderStyler';
|
|
48
|
+
export * from './style/TimeSliderColors';
|
|
49
|
+
export * from './style/TimeSliderLabeler';
|
|
50
|
+
export * from './style/TimeSliderPointsStyle';
|
|
51
|
+
export * from './style/TimeSliderIntervalsStyle';
|
|
52
|
+
export * from './style/TimeSliderHistogramStyle';
|
|
53
|
+
export * from './ticks/TimeSliderConstants';
|
|
54
|
+
export * from './ticks/TimeTicksBar';
|
|
55
|
+
export * from './ticks/YAxisTicks';
|
|
56
|
+
export * from './common/TimeTools';
|
|
57
|
+
export * from './common/Easing';
|
|
58
|
+
export * from './common/Clamper';
|
|
59
|
+
export * from './common/Disposables';
|
|
60
|
+
export * from './common/Expand';
|
|
61
|
+
export * from './common/GlslTools';
|
|
62
|
+
export * from './event/TypedEventEmitter';
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export*from"./engine/TimeSlider.js";export*from"./engine/TimeSliderEngine.js";export*from"./engine/PinchZoom.js";export*from"./engine/HorizontalPinchZoom.js";export*from"./three/ThreeTimeSlider.js";export*from"./three/ThreeTimeSliderEngine.js";export*from"./three/Three3DTimeSliderEngine.js";export*from"./three/react/ReactThreeTimeSlider.js";export*from"./three/layer/ThreeTimeLayerLoader.js";export*from"./three/layer/ThreePointsTimeLayerLoader.js";export*from"./three/layer/ThreeIntervalsTimeLayerLoader.js";export*from"./three/layer/Three3DPointsTimeLayerLoader.js";export*from"./three/layer/Three3DIntervalsTimeLayerLoader.js";export*from"./react/ReactTimeSlider.js";export*from"./react/ColoredSlider.js";export{ColoredSliderExtendsInput}from"./react/ColoredSliderExtendsInput.js";export*from"./react/FullscreenButton.js";export*from"./react/MaterialIconButton.js";export*from"./react/MaterialTextButton.js";export*from"./react/DateLabelWithPicker.js";export*from"./react/TimeLabelWithPicker.js";export*from"./react/DateRangeLabelWithPicker.js";export*from"./react/YearScroller.js";export*from"./react/PointerClick.js";export*from"./react/PinchZoomHook.js";export*from"./react/DeepMemoHook.js";export*from"./data/TimeSliderElement.js";export*from"./data/TimeSliderModel.js";export*from"./data/TimeSliderPointsModel.js";export*from"./data/TimeSliderIntervalsModel.js";export*from"./data/CompositeTimeSliderModel.js";export*from"./data/TimeSliderRange.js";export*from"./data/TimeSliderBush.js";export*from"./data/IntervalLaneManager.js";export*from"./data/TimeSliderLanesModel.js";export*from"./data/histogram/TimeSliderHistogram.js";export*from"./data/histogram/TimeSliderFixedHistogram.js";export*from"./data/histogram/TimeSliderDynamicHistogram.js";export*from"./data/histogram/TimeSliderSplittingFixedHistogram.js";export*from"./layer/TimeSliderLayer.js";export*from"./layer/TimeSliderLayerLoader.js";export*from"./layer/TimeSliderPointsLayer.js";export*from"./layer/TimeSliderIntervalsLayer.js";export*from"./layer/TimeSliderHistogramLayer.js";export*from"./style/TimeSliderStyle.js";export*from"./style/TimeSliderStyler.js";export*from"./style/TimeSliderColors.js";export*from"./style/TimeSliderLabeler.js";export*from"./style/TimeSliderPointsStyle.js";export*from"./style/TimeSliderIntervalsStyle.js";export*from"./style/TimeSliderHistogramStyle.js";export*from"./ticks/TimeSliderConstants.js";export*from"./ticks/TimeTicksBar.js";export*from"./ticks/YAxisTicks.js";export*from"./common/TimeTools.js";export*from"./common/Easing.js";export*from"./common/Clamper.js";export*from"./common/Disposables.js";export*from"./common/Expand.js";export*from"./common/GlslTools.js";export*from"./event/TypedEventEmitter.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Disposables as s}from"../common/Disposables";import{TimeSliderDynamicHistogram as i}from"../data/histogram/TimeSliderDynamicHistogram";import{TimeSliderSplittingFixedHistogram as t}from"../data/histogram/TimeSliderSplittingFixedHistogram";import{TimeSliderIntervalsModel as e}from"../data/TimeSliderIntervalsModel";import{TimeSliderIntervalsLayer as a}from"./TimeSliderIntervalsLayer";export class TimeSliderHistogramLayer extends a{constructor(i,t){super(new e,t),this.content=i,this.d=new s;const a=this.createHistogram({classifier:t?.classifier,...t?.style});this.histogram=a,this.maxClassifications=t?.maxClassifications,this._classificationColors=t?.classificationColors||[],t?.classificationIsColor&&!this.fixedBoxes&&(this.styler=s=>{const i=s.attributes?.classification;return i?{fill:{color:i},border:{color:i}}:void 0}),t?.classifier&&!t.labeler&&(this.fixedBoxes?t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+" TODO use split":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i+" TODO use split"}:t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+"":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i}),this.d.add(this.on("loaded",s=>{s?a.start(this.timeSlider):a.stop()})),this.d.add(this.on("invalidateAll",()=>{a.average=!0===this.style.average,a.weighted=!0===this.style.weighted,a.inverted=!0===this.style.inverted,this.style.mode&&(a.mode=this.style.mode),a.classifier=this.style.classifier,this.style.classOrder&&(a.classOrder=this.style.classOrder)}))}getClassification(s,i){const t=s.v[1]-s.v[0],e=s.attributes?.splits||[1],a=i/t;let o=0;for(let s=0;s<e.length;s++)if(o+=e[s],a<o)return this.histogram.classOrder[s]}set classificationColors(s){this._classificationColors=s,this.invalidateAll()}get classificationColors(){return this._classificationColors}createHistogram(s){return this.fixedBoxes?new t(this.model,this.content,s):new i(this.model,this.content,s)}get fixedBoxes(){return void 0!==this.style.mode?.fixed||void 0!==this.style.mode?.fixedUnit}dispose(){this.model.clear(),this.d.dispose()}getDefaultStyle(){return{}}}
|
|
1
|
+
import{Disposables as s}from"../common/Disposables.js";import{TimeSliderDynamicHistogram as i}from"../data/histogram/TimeSliderDynamicHistogram.js";import{TimeSliderSplittingFixedHistogram as t}from"../data/histogram/TimeSliderSplittingFixedHistogram.js";import{TimeSliderIntervalsModel as e}from"../data/TimeSliderIntervalsModel.js";import{TimeSliderIntervalsLayer as a}from"./TimeSliderIntervalsLayer.js";export class TimeSliderHistogramLayer extends a{constructor(i,t){super(new e,t),this.content=i,this.d=new s;const a=this.createHistogram({classifier:t?.classifier,...t?.style});this.histogram=a,this.maxClassifications=t?.maxClassifications,this._classificationColors=t?.classificationColors||[],t?.classificationIsColor&&!this.fixedBoxes&&(this.styler=s=>{const i=s.attributes?.classification;return i?{fill:{color:i},border:{color:i}}:void 0}),t?.classifier&&!t.labeler&&(this.fixedBoxes?t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+" TODO use split":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i+" TODO use split"}:t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+"":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i}),this.d.add(this.on("loaded",s=>{s?a.start(this.timeSlider):a.stop()})),this.d.add(this.on("invalidateAll",()=>{a.average=!0===this.style.average,a.weighted=!0===this.style.weighted,a.inverted=!0===this.style.inverted,this.style.mode&&(a.mode=this.style.mode),a.classifier=this.style.classifier,this.style.classOrder&&(a.classOrder=this.style.classOrder)}))}getClassification(s,i){const t=s.v[1]-s.v[0],e=s.attributes?.splits||[1],a=i/t;let o=0;for(let s=0;s<e.length;s++)if(o+=e[s],a<o)return this.histogram.classOrder[s]}set classificationColors(s){this._classificationColors=s,this.invalidateAll()}get classificationColors(){return this._classificationColors}createHistogram(s){return this.fixedBoxes?new t(this.model,this.content,s):new i(this.model,this.content,s)}get fixedBoxes(){return void 0!==this.style.mode?.fixed||void 0!==this.style.mode?.fixedUnit}dispose(){this.model.clear(),this.d.dispose()}getDefaultStyle(){return{}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Disposables as
|
|
1
|
+
import{Disposables as s}from"../common/Disposables.js";import{TimeSliderDynamicHistogram as t}from"../data/histogram/TimeSliderDynamicHistogram.js";import{TimeSliderFixedHistogram as e}from"../data/histogram/TimeSliderFixedHistogram.js";import{TimeSliderIntervalsModel as i}from"../data/TimeSliderIntervalsModel.js";import{TimeSliderIntervalsLayer as r}from"./TimeSliderIntervalsLayer.js";export class TimeSliderHistogramLayerOld extends r{constructor(t,e){super(new i,e),this.content=t,this.d=new s;const r=this.createHistogram({classifier:e?.classifier,...e?.style});this.histogram=r,e?.classifier&&!e.labeler&&(e.classificationIsColor?this.labeler=s=>Math.abs(s.v[0]-s.v[1])+"":this.labeler=s=>{const t=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+t}),e?.classificationIsColor&&(this.styler=s=>{const t=s.attributes?.classification;return t?{fill:{color:t},border:{color:t}}:void 0}),this.d.add(this.on("loaded",s=>{s?r.start(this.timeSlider):r.stop()})),this.d.add(this.on("invalidateAll",()=>{r.average=!0===this.style.average,r.weighted=!0===this.style.weighted,r.inverted=!0===this.style.inverted,this.style.mode&&(r.mode=this.style.mode),r.classifier=this.style.classifier,this.style.classOrder&&(r.classOrder=this.style.classOrder)}))}createHistogram(s){return this.fixedBoxes?new e(this.model,this.content,s):new t(this.model,this.content,s)}get fixedBoxes(){return void 0!==this.style.mode?.fixed||void 0!==this.style.mode?.fixedUnit}dispose(){this.model.clear(),this.d.dispose()}getDefaultStyle(){return{}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TimeSliderLayer as e}from"./TimeSliderLayer";export class TimeSliderIntervalsLayer extends e{getDefaultStyle(){return{}}}
|
|
1
|
+
import{TimeSliderLayer as e}from"./TimeSliderLayer.js";export class TimeSliderIntervalsLayer extends e{getDefaultStyle(){return{}}}
|
package/layer/TimeSliderLayer.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as i}from"uuid";import{TypedEventEmitter as t}from"../event/TypedEventEmitter";export class TimeSliderLayer extends t{constructor(t,e){super(),this.model=t,this._visible=!0,this._loaded=!1,this.id=e?.id||i(),this.style=e?.style||this.getDefaultStyle(),this._styler=e?.styler,this.labeler=e?.labeler,this.yAxis=e?.yAxis||{},this._name=e?.name||t.name||"Unknown",this._min=e?.min||0,this._max=e?.max||1,this._visible="boolean"!=typeof e?.visible||e.visible}get yAxisGroup(){return this.yAxis.group||this.id}get styler(){return this._styler}set styler(i){this._styler=i,this.invalidateAll()}invalidate(i){const t="string"==typeof i?i:i.id;this.emit("invalidate",t)}invalidateAll(){this.emit("invalidateAll")}select(i){this.emit("selection",i)}get min(){return this._min}set min(i){i!==this._min&&(this._min=i,this.emit("min",i))}get max(){return this._max}set max(i){i!==this._max&&(this._max=i,this.emit("max",i))}get timeSlider(){return this._timeSlider}set timeSlider(i){this._timeSlider=i}get name(){return this._name}set name(i){i!==this._name&&(this._name=i,this.emit("name",i))}get visible(){return this._visible}set visible(i){i!==this._visible&&(this._visible=i,this.emit("visible",i),this.shouldModelLoad())}get loaded(){return this._loaded}set loaded(i){i!==this._loaded&&(this._loaded=i,this.shouldModelLoad(),this.emit("loaded",i))}shouldModelLoad(){const i=this.loaded&&this.visible;this.model.loaded(this.id,i)}}
|
|
1
|
+
import{v4 as i}from"uuid";import{TypedEventEmitter as t}from"../event/TypedEventEmitter.js";export class TimeSliderLayer extends t{constructor(t,e){super(),this.model=t,this._visible=!0,this._loaded=!1,this.id=e?.id||i(),this.style=e?.style||this.getDefaultStyle(),this._styler=e?.styler,this.labeler=e?.labeler,this.yAxis=e?.yAxis||{},this._name=e?.name||t.name||"Unknown",this._min=e?.min||0,this._max=e?.max||1,this._visible="boolean"!=typeof e?.visible||e.visible}get yAxisGroup(){return this.yAxis.group||this.id}get styler(){return this._styler}set styler(i){this._styler=i,this.invalidateAll()}invalidate(i){const t="string"==typeof i?i:i.id;this.emit("invalidate",t)}invalidateAll(){this.emit("invalidateAll")}select(i){this.emit("selection",i)}get min(){return this._min}set min(i){i!==this._min&&(this._min=i,this.emit("min",i))}get max(){return this._max}set max(i){i!==this._max&&(this._max=i,this.emit("max",i))}get timeSlider(){return this._timeSlider}set timeSlider(i){this._timeSlider=i}get name(){return this._name}set name(i){i!==this._name&&(this._name=i,this.emit("name",i))}get visible(){return this._visible}set visible(i){i!==this._visible&&(this._visible=i,this.emit("visible",i),this.shouldModelLoad())}get loaded(){return this._loaded}set loaded(i){i!==this._loaded&&(this._loaded=i,this.shouldModelLoad(),this.emit("loaded",i))}shouldModelLoad(){const i=this.loaded&&this.visible;this.model.loaded(this.id,i)}}
|
|
@@ -4,5 +4,7 @@ import { TimeSliderLayer } from "./TimeSliderLayer";
|
|
|
4
4
|
export interface TimeSliderLayerLoader<T extends TimeSliderEngine<any>> {
|
|
5
5
|
engineClass: TimeSliderEngineClass<T>;
|
|
6
6
|
canLoad(layer: TimeSliderLayer): boolean;
|
|
7
|
+
/** True when a loaded layer follows changes to its band (layer.min / layer.max) by itself. Otherwise the slider reloads the layer on such a change. */
|
|
8
|
+
followsLayerBand?: boolean;
|
|
7
9
|
load(layer: TimeSliderLayer, scene: TimeSliderEngineScene<T>, engine: T, timeSlider: TimeSlider): () => void;
|
|
8
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TimeSliderLayer as e}from"./TimeSliderLayer";export class TimeSliderPointsLayer extends e{getDefaultStyle(){return{}}}
|
|
1
|
+
import{TimeSliderLayer as e}from"./TimeSliderLayer.js";export class TimeSliderPointsLayer extends e{getDefaultStyle(){return{}}}
|