@protomaze/time 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,9 @@ export declare class TimeSliderBush<T extends TimeSliderElement = TimeSliderElem
7
7
  private insertSafely;
8
8
  add(element: T): void;
9
9
  insert(element: T): this;
10
+ /** Bulk load (RBush builds the tree directly, without insert): the ids are registered here, so get/has/update/remove work for elements given to a model's constructor too. */
11
+ load(elements: readonly T[]): this;
12
+ clear(): this;
10
13
  remove(element: T): this;
11
14
  has(id: string): boolean;
12
15
  get(id: string): T | undefined;
@@ -1 +1 @@
1
- import e from"rbush";import{getTimeArray as r,getValueArray as i}from"./TimeSliderElement.js";import{timeSliderRangeAsObject as t}from"./TimeSliderRange.js";export class TimeSliderBush extends e{constructor(){super(),this.idMap=new Map}insertSafely(e){return this.idMap.set(e.id,e),super.insert(e),this}add(e){this.insertSafely(e)}insert(e){return this.insertSafely(e),this}remove(e){return this.idMap.delete(e.id),super.remove(e,(e,r)=>e.id===r.id),this}has(e){return this.idMap.has(e)}get(e){return this.idMap.get(e)}searchTime(e){const r=t(e);return super.search({minX:r.startTime,maxX:r.endTime,minY:Number.MIN_VALUE,maxY:Number.MAX_VALUE})}searchRange(e){return super.search({minX:e.startTime,maxX:e.endTime,minY:e.minValue,maxY:e.maxValue})}toBBox(e){const[t,s]=r(e),[n,m]=i(e);return{minX:t,maxX:s,minY:n,maxY:m}}compareMinX(e,i){const[t]=r(e),[s]=r(i);return t-s}compareMinY(e,r){const[t]=i(e),[s]=i(r);return t-s}}
1
+ import e from"rbush";import{getTimeArray as r,getValueArray as i}from"./TimeSliderElement.js";import{timeSliderRangeAsObject as t}from"./TimeSliderRange.js";export class TimeSliderBush extends e{constructor(){super(),this.idMap=new Map}insertSafely(e){return this.idMap.set(e.id,e),super.insert(e),this}add(e){this.insertSafely(e)}insert(e){return this.insertSafely(e),this}load(e){return e.forEach(e=>this.idMap.set(e.id,e)),super.load(e),this}clear(){return this.idMap?.clear(),super.clear(),this}remove(e){return this.idMap.delete(e.id),super.remove(e,(e,r)=>e.id===r.id),this}has(e){return this.idMap.has(e)}get(e){return this.idMap.get(e)}searchTime(e){const r=t(e);return super.search({minX:r.startTime,maxX:r.endTime,minY:Number.MIN_VALUE,maxY:Number.MAX_VALUE})}searchRange(e){return super.search({minX:e.startTime,maxX:e.endTime,minY:e.minValue,maxY:e.maxValue})}toBBox(e){const[t,s]=r(e),[a,n]=i(e);return{minX:t,maxX:s,minY:a,maxY:n}}compareMinX(e,i){const[t]=r(e),[s]=r(i);return t-s}compareMinY(e,r){const[t]=i(e),[s]=i(r);return t-s}}
@@ -5,17 +5,36 @@ import { TimeSliderHistogram, TimeSliderHistogramOptions } from "./TimeSliderHis
5
5
  export declare class TimeSliderDynamicHistogram<M extends TimeSliderModel = TimeSliderModel> extends TimeSliderHistogram<M> {
6
6
  protected model: TimeSliderIntervalsModel;
7
7
  protected content: M;
8
- private prevUpdateLength;
8
+ private boxIds;
9
9
  private needsUpdate;
10
+ /** Only the stacking (from the cached bins) is out of date: after reclassify. */
11
+ private needsRestack;
12
+ private cache?;
10
13
  private animationFrameId?;
11
14
  private maxEncountered;
12
15
  constructor(model: TimeSliderIntervalsModel, content: M, options?: TimeSliderHistogramOptions<M>);
13
16
  protected startUpdating(timeSlider: TimeSlider): void;
14
17
  private invalidate;
18
+ private classify;
19
+ private getElementWeight;
20
+ /**
21
+ * Re-classifies only the given elements (e.g. those whose filter state changed), using the bins
22
+ * of the last full pass: each moves its weight from its old class to its new one. The bars are
23
+ * re-stacked once per frame. Elements the last pass didn't see, and anything when no pass is
24
+ * cached yet, fall back to a full pass.
25
+ */
26
+ reclassify(ids: Iterable<string>): void;
15
27
  protected stopUpdating(): void;
16
28
  protected onOptionsChanged(): void;
17
29
  private getAmountOfBoxes;
18
30
  private getSegments;
31
+ /** The full pass: classifies every element in view into the bins, caches that, and stacks the bars. */
19
32
  private calculate;
33
+ /** Stacks the bars from the cached per-bin, per-class sums (averages when average is set). */
34
+ private stack;
35
+ /**
36
+ * Writes the stacked boxes into the model. Box ids are stable (bin start + class), so a box is only
37
+ * updated when it changed and only removed when it's gone: after a reclassify most boxes stay as they are.
38
+ */
20
39
  private updateBoxes;
21
40
  }
@@ -1 +1 @@
1
- import{getTimeUnitInMs as t}from"../../common/TimeTools.js";import{TimeTicksBar as e}from"../../ticks/TimeTicksBar.js";import{timeRangeOverlaps as i}from"../TimeSliderRange.js";import{TimeSliderHistogram as s}from"./TimeSliderHistogram.js";export class TimeSliderDynamicHistogram extends s{constructor(t,e,i){super(t,e,i),this.model=t,this.content=e,this.prevUpdateLength=0,this.needsUpdate=!1,this.maxEncountered=1e3}startUpdating(t){this.invalidate();const e=e=>{e&&i(t.getTimeRange(),e.t)&&this.invalidate()};this.d.add(this.content.on("added",t=>e(t))),this.d.add(this.content.on("updated",t=>e(t.updated))),this.d.add(this.content.on("removed",()=>this.invalidate())),this.d.add(t.on("time",()=>this.invalidate())),this.d.add(t.on("size",()=>this.invalidate()));const s=()=>{this.needsUpdate&&(this.calculate(),this.needsUpdate=!1),this.animationFrameId=requestAnimationFrame(s)};this.animationFrameId=requestAnimationFrame(s)}invalidate(){this.needsUpdate=!0}stopUpdating(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.model.clear()}onOptionsChanged(){this.invalidate()}getAmountOfBoxes(){return this.mode?.amount?this.mode?.amount:Math.round(this.timeSlider.size.width/(this.mode?.pixels||12))}getSegments(){const i=this.timeSlider.getTimeRange(),s=i.startTime,n=i.endTime;if(this.mode?.autoUnits){const i=this.timeSlider.ticksBar.cache.medium.spacing,s=this.timeSlider?.getTimeRange().duration/i,n=this.timeSlider?.size.width/s<(this.mode.autoUnitsMinPixels||8)?this.timeSlider.ticksBar.cache.high:this.timeSlider.ticksBar.cache.medium,a=this.mode.minUnit?t(this.mode.minUnit):0,o=this.mode.maxUnit?t(this.mode.maxUnit):Number.MAX_VALUE;return n.spacing>=a&&n.spacing<=o?n.segments:this.mode.minUnit&&n.spacing<a?e.splitInTimeUnits(this.timeSlider,this.mode.minUnit):this.mode.maxUnit&&n.spacing>o?e.splitInTimeUnits(this.timeSlider,this.mode.maxUnit):[]}{const t=i.duration/this.getAmountOfBoxes(),e=[];for(let i=s;i<n-.5*t;i+=t)e.push({start:i,end:i+t});return e}}calculate(){let t=0;const e=[],i=this.weighted?t=>"number"==typeof t.v?t.v:.5*(t.v[1]+t.v[0]):t=>1,s=new Map,n=this.getSegments();n.forEach((e,n)=>{const a=this.content.dataInTimeRange([e.start,e.end]);let o=0;const h=new Map,d=new Map;if(a.forEach(t=>{const e=this.classifier?this.classifier(t):void 0;if(null!==e){const s=e||"#888",n=i(t);o+=n,this.registerClassification(s),h.has(s)?(h.set(s,h.get(s)+n),d.set(s,d.get(s)+1)):(h.set(s,n),d.set(s,1))}}),this.average){o=0;for(const[t,e]of h){const i=e/d.get(t);o+=i,h.set(t,i)}}s.set(n,h),o>t&&(t=o)});const a=new Map,o=new Map,h=new Set,d=Array.from(this.classOrder);s.forEach((t,i)=>{const m=n[i];let r=0;const c=[];d.forEach(d=>{let l=t.get(d);if(l)a.set(d,{index:i,height:l});else if(this.average&&!h.has(d)&&a.has(d)){let t;if(o.has(d))t=o.get(d);else{for(let e=i;e<n.length;e++){const i=s.get(e);i&&i.has(d)&&(t={index:e,height:i.get(d)})}t&&o.set(d,t)}if(t){const e=a.get(d),i=n[e.index],s=n[t.index],o=(m.start-i.start)/(s.start-i.start);l=e.height+o*(t.height-e.height)}else h.add(d)}if(l){const t={height:l,...m,bottom:r,classification:d};e.push(t),c.push(t),r+=l}}),c.forEach(t=>t.percentage=t.height/r)}),this.updateBoxes(e,t)}updateBoxes(t,e){if(e>this.maxEncountered&&(this.maxEncountered=e+100),this.maxValue=e,t.forEach((t,e)=>{const i=e+"",s=this.model.has(i),n={attributes:{classification:t.classification,percentage:t.percentage},t:[t.start,t.end],v:this.inverted?[this.maxEncountered-t.bottom-t.height,this.maxEncountered-t.bottom]:[t.bottom,t.bottom+t.height]};n.v[0]===n.v[1]&&console.warn(n),s?this.model.update(i,n):this.model.add({id:i,...n})}),this.prevUpdateLength>t.length)for(let e=t.length;e<this.prevUpdateLength;e++){const t=e+"";this.model.update(t,{v:[0,0]})}this.prevUpdateLength=t.length}}
1
+ import{getTimeUnitInMs as t}from"../../common/TimeTools.js";import{TimeTicksBar as i}from"../../ticks/TimeTicksBar.js";import{timeRangeOverlaps as e}from"../TimeSliderRange.js";import{TimeSliderHistogram as s}from"./TimeSliderHistogram.js";export class TimeSliderDynamicHistogram extends s{constructor(t,i,e){super(t,i,e),this.model=t,this.content=i,this.boxIds=new Set,this.needsUpdate=!1,this.needsRestack=!1,this.maxEncountered=1e3}startUpdating(t){this.invalidate();const i=i=>{i&&e(t.getTimeRange(),i.t)&&this.invalidate()};this.d.add(this.content.on("added",t=>i(t))),this.d.add(this.content.on("updated",t=>i(t.updated))),this.d.add(this.content.on("removed",()=>this.invalidate())),this.d.add(t.on("time",()=>this.invalidate())),this.d.add(t.on("size",()=>this.invalidate()));const s=()=>{this.needsUpdate?(this.calculate(),this.needsUpdate=!1,this.needsRestack=!1):this.needsRestack&&this.cache&&(this.stack(this.cache),this.needsRestack=!1),this.animationFrameId=requestAnimationFrame(s)};this.animationFrameId=requestAnimationFrame(s)}invalidate(){this.needsUpdate=!0,this.cache=void 0}classify(t){const i=this.classifier?this.classifier(t):void 0;return null===i?null:i||"#888"}getElementWeight(t){return this.weighted?"number"==typeof t.v?t.v:.5*(t.v[1]+t.v[0]):1}reclassify(t){const i=this.cache;if(i&&!this.needsUpdate){for(const s of t){const t=i.elements.get(s),a=this.content.get(s);if(!t){if(a&&this.timeSlider&&e(this.timeSlider.getTimeRange(),a.t))return void this.invalidate();continue}const o=a?this.classify(a):null;o!==t.classification&&(t.bins.forEach(e=>{null!==t.classification&&(n(i.sums[e],t.classification,-t.weight),n(i.counts[e],t.classification,-1)),null!==o&&(this.registerClassification(o),n(i.sums[e],o,t.weight),n(i.counts[e],o,1))}),t.classification=o)}this.needsRestack=!0}else this.invalidate()}stopUpdating(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=void 0),this.model.clear(),this.boxIds=new Set}onOptionsChanged(){this.invalidate()}getAmountOfBoxes(){return this.mode?.amount?this.mode?.amount:Math.round(this.timeSlider.size.width/(this.mode?.pixels||12))}getSegments(){const e=this.timeSlider.getTimeRange(),s=e.startTime,n=e.endTime;if(this.mode?.autoUnits){const e=this.timeSlider.ticksBar.cache.medium.spacing,s=this.timeSlider?.getTimeRange().duration/e,n=this.timeSlider?.size.width/s<(this.mode.autoUnitsMinPixels||8)?this.timeSlider.ticksBar.cache.high:this.timeSlider.ticksBar.cache.medium,a=this.mode.minUnit?t(this.mode.minUnit):0,o=this.mode.maxUnit?t(this.mode.maxUnit):Number.MAX_VALUE;return n.spacing>=a&&n.spacing<=o?n.segments:this.mode.minUnit&&n.spacing<a?i.splitInTimeUnits(this.timeSlider,this.mode.minUnit):this.mode.maxUnit&&n.spacing>o?i.splitInTimeUnits(this.timeSlider,this.mode.maxUnit):[]}{const t=e.duration/this.getAmountOfBoxes(),i=[];for(let e=s;e<n-.5*t;e+=t)i.push({start:e,end:e+t});return i}}calculate(){const t=this.getSegments(),i={segments:t,sums:[],counts:[],elements:new Map};t.forEach((t,e)=>{const s=this.content.dataInTimeRange([t.start,t.end]),a=new Map,o=new Map;s.forEach(t=>{const s=i.elements.get(t.id);if(s)return s.bins.push(e),void(null!==s.classification&&(n(a,s.classification,s.weight),n(o,s.classification,1)));const h=this.classify(t),c=this.getElementWeight(t);i.elements.set(t.id,{bins:[e],classification:h,weight:c}),null!==h&&(this.registerClassification(h),n(a,h,c),n(o,h,1))}),i.sums.push(a),i.counts.push(o)}),this.cache=i,this.stack(i)}stack(t){const i=t.segments;let e=0;const s=[],n=new Map;i.forEach((i,s)=>{let a=0;const o=new Map;t.sums[s].forEach((i,e)=>{const n=t.counts[s].get(e)??0;if(n<=0)return;const h=this.average?i/n:i;o.set(e,h),a+=h}),n.set(s,o),a>e&&(e=a)});const a=new Map,o=new Map,h=new Set,c=Array.from(this.classOrder);n.forEach((t,e)=>{const d=i[e];let r=0;const m=[];c.forEach(c=>{let l=t.get(c);if(l)a.set(c,{index:e,height:l});else if(this.average&&!h.has(c)&&a.has(c)){let t;if(o.has(c))t=o.get(c);else{for(let s=e;s<i.length;s++){const i=n.get(s);i&&i.has(c)&&(t={index:s,height:i.get(c)})}t&&o.set(c,t)}if(t){const e=a.get(c),s=i[e.index],n=i[t.index],o=(d.start-s.start)/(n.start-s.start);l=e.height+o*(t.height-e.height)}else h.add(c)}if(l){const t={height:l,...d,bottom:r,classification:c};s.push(t),m.push(t),r+=l}}),m.forEach(t=>t.percentage=t.height/r)}),this.updateBoxes(s,e)}updateBoxes(t,i){i>this.maxEncountered&&(this.maxEncountered=i+100),this.maxValue=i;const e=new Set;t.forEach(t=>{const i=t.start+"|"+t.classification;e.add(i);const s=this.inverted?[this.maxEncountered-t.bottom-t.height,this.maxEncountered-t.bottom]:[t.bottom,t.bottom+t.height],n=this.model.get(i);if(n){if(n.t[0]===t.start&&n.t[1]===t.end&&n.v[0]===s[0]&&n.v[1]===s[1]&&n.attributes?.classification===t.classification&&n.attributes?.percentage===t.percentage)return;this.model.update(i,{t:[t.start,t.end],v:s,attributes:{classification:t.classification,percentage:t.percentage}})}else this.model.add({id:i,t:[t.start,t.end],v:s,attributes:{classification:t.classification,percentage:t.percentage}})}),this.boxIds.forEach(t=>{e.has(t)||this.model.remove(t)}),this.boxIds=e}}function n(t,i,e){t.set(i,(t.get(i)??0)+e)}
@@ -53,6 +53,8 @@ export declare abstract class TimeSliderHistogram<M extends TimeSliderModel = Ti
53
53
  stop(): void;
54
54
  get classOrder(): string[];
55
55
  set classOrder(newOrder: string[]);
56
+ /** Re-classifies the given elements (ids of the content model). This histogram does a full pass; TimeSliderDynamicHistogram re-bins only these. */
57
+ reclassify(ids: Iterable<string>): void;
56
58
  protected registerClassification(classification: string): void;
57
59
  get classifier(): TimeSliderHistogramClassifier<M> | undefined;
58
60
  set classifier(newClassifier: TimeSliderHistogramClassifier<M> | undefined);
@@ -1 +1 @@
1
- import{Disposables as e}from"../../common/Disposables.js";export class TimeSliderHistogram{constructor(t,s,i){this.model=t,this.content=s,this.d=new e,this.classOrderSet=new Set,this.started=!1,this.maxValue=1,this._classifier=i?.classifier,this.classOrderSet=new Set(i?.classOrder),this._average=!0===i?.average,this._weighted=!0===i?.weighted,this._inverted=!0===i?.inverted,this._mode=i?.mode||{pixels:12}}start(e){this.started||(this.started=!0,this.timeSlider=e,this.startUpdating(e))}stop(){this.started&&(this.started=!1,this.d.dispose(),this.d=new e,this.stopUpdating())}get classOrder(){return Array.from(this.classOrderSet)}set classOrder(e){this.classOrderSet=new Set(e),this.onOptionsChanged("classOrder")}registerClassification(e){this.classOrderSet.add(e)}get classifier(){return this._classifier}set classifier(e){this._classifier=e,this.onOptionsChanged("classifier")}get mode(){return this._mode}set mode(e){JSON.stringify(e)!==JSON.stringify(this._mode)&&(this._mode=e,this.onOptionsChanged("mode"))}get average(){return this._average}set average(e){e!==this._average&&(this._average=e,this.onOptionsChanged("average"))}get inverted(){return this._inverted}set inverted(e){e!==this._inverted&&(this._inverted=e,this.onOptionsChanged("inverted"))}get weighted(){return this._weighted}set weighted(e){e!==this._weighted&&(this._weighted=e,this.onOptionsChanged("weighted"))}checkMaxValue(){if(this.timeSlider){let e=0;this.model.dataInTimeRange(this.timeSlider.getTimeRange()).forEach(t=>{t.v[1]>e&&(e=t.v[1])}),this.maxValue=e}}}
1
+ import{Disposables as e}from"../../common/Disposables.js";export class TimeSliderHistogram{constructor(t,s,i){this.model=t,this.content=s,this.d=new e,this.classOrderSet=new Set,this.started=!1,this.maxValue=1,this._classifier=i?.classifier,this.classOrderSet=new Set(i?.classOrder),this._average=!0===i?.average,this._weighted=!0===i?.weighted,this._inverted=!0===i?.inverted,this._mode=i?.mode||{pixels:12}}start(e){this.started||(this.started=!0,this.timeSlider=e,this.startUpdating(e))}stop(){this.started&&(this.started=!1,this.d.dispose(),this.d=new e,this.stopUpdating())}get classOrder(){return Array.from(this.classOrderSet)}set classOrder(e){this.classOrderSet=new Set(e),this.onOptionsChanged("classOrder")}reclassify(e){this.onOptionsChanged("classifier")}registerClassification(e){this.classOrderSet.add(e)}get classifier(){return this._classifier}set classifier(e){this._classifier=e,this.onOptionsChanged("classifier")}get mode(){return this._mode}set mode(e){JSON.stringify(e)!==JSON.stringify(this._mode)&&(this._mode=e,this.onOptionsChanged("mode"))}get average(){return this._average}set average(e){e!==this._average&&(this._average=e,this.onOptionsChanged("average"))}get inverted(){return this._inverted}set inverted(e){e!==this._inverted&&(this._inverted=e,this.onOptionsChanged("inverted"))}get weighted(){return this._weighted}set weighted(e){e!==this._weighted&&(this._weighted=e,this.onOptionsChanged("weighted"))}checkMaxValue(){if(this.timeSlider){let e=0;this.model.dataInTimeRange(this.timeSlider.getTimeRange()).forEach(t=>{t.v[1]>e&&(e=t.v[1])}),this.maxValue=e}}}
@@ -463,6 +463,16 @@ export declare class TimeSlider extends TypedEventEmitter<{
463
463
  t: number;
464
464
  v: number;
465
465
  }[];
466
+ /** The elements under the pointer at its height, whatever the pick mode: bars where they are drawn (time and value), points within pickSize px (default 12). */
467
+ findElementsAtPoint(mouse: {
468
+ x: number;
469
+ y: number;
470
+ }, pickSize?: number): {
471
+ layer: TimeSliderLayer<TimeSliderElement, import("..").TimeSliderStyle>;
472
+ elements: TimeSliderElement[];
473
+ t: number;
474
+ v: number;
475
+ }[];
466
476
  /** Pick mode 'column': ignores cursor height entirely — every visible layer's element(s) whose time interval contains the cursor time. */
467
477
  private findColumnElements;
468
478
  private hoverCleared;
@@ -1 +1 @@
1
- import{v4 as e}from"uuid";import{Disposables as t}from"../common/Disposables.js";import{animateRangeTransition as i}from"../common/Easing.js";import{describeTimeSpan as s,formatDate as n,formatDateRange as l,formatDuration as o,formatTimeSpanDates as a,getDefaultLocale as r,getLargeTimeUnitRange as h,getMatchingTimeUnit as d,getTimeUnitRange as c,setDefaultLocale as m}from"../common/TimeTools.js";import{TimeSliderDynamicHistogram as g}from"../data/histogram/TimeSliderDynamicHistogram.js";import{getTimeArray as u}from"../data/TimeSliderElement.js";import{TimeSliderIntervalsModel as p}from"../data/TimeSliderIntervalsModel.js";import{addDuration as y,addPadding as T,applyTimeRangeUpdate as v,clampTimeRange as f,mergeTimeRanges as x,timeRangesOverlap as E,timeRangesUnion as b}from"../data/TimeSliderRange.js";import{TypedEventEmitter as w}from"../event/TypedEventEmitter.js";import{TimeSliderHistogramLayer as L}from"../layer/TimeSliderHistogramLayer.js";import{TimeSliderIntervalsLayer as R}from"../layer/TimeSliderIntervalsLayer.js";import{CENTURY as S,DECADE as k,MILLENIUM as C,ONE_DAY as M,ONE_HOUR as B,ONE_MINUTE as V,ONE_MONTH as O,ONE_SECOND as _,ONE_WEEK as D,ONE_YEAR as I,TODAY as z}from"../ticks/TimeSliderConstants.js";import{TimeTicksBar as A}from"../ticks/TimeTicksBar.js";import{YAxisTicks as H}from"../ticks/YAxisTicks.js";import{resolveFont as $,toCssFont as F}from"../common/Font.js";import{getDevicePixelRatio as U}from"../common/Pixels.js";const P={idle:{fill:"rgba(100, 180, 255, 0.15)",border:{color:"rgba(100, 180, 255, 0.8)",width:1,style:"solid"},handle:{color:"rgba(100, 180, 255, 0.9)",width:0,look:"bar"}},editing:{fill:"rgba(100, 180, 255, 0.15)",border:{color:"rgba(100, 180, 255, 0.8)",width:2,style:"solid"},handle:{color:"rgba(100, 180, 255, 0.9)",width:4,look:"bar"}},drawing:{fill:"#df04",border:{color:"#df0",width:3,style:"solid"},handle:{color:"#df0",width:0,look:"bar"}}};function Y(e){if(!e||e.size<=0||e.intensity<=0)return"";const t=Math.round(100*Math.min(1,e.intensity)),i=`color-mix(in srgb, ${e.color} ${t}%, transparent)`;return`drop-shadow(0 0 ${.4*e.size}px ${i}) drop-shadow(0 0 ${e.size}px ${i})`}const j=_,W=10*C;export class TimeSlider extends w{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 A,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:z,value:{minValue:0,maxValue:100}},this.size={width:100,height:100},this.sliderElement=document.createElement("div"),this.yAxisTicks=new H,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.selectionBehindContainer=document.createElement("div"),this._selectionEditMode="always",this.editingIndex=null,this.selectionStyle={},this._selectionOrder="front",this.shadingElements=[],this.columnBandOverlayContainer=document.createElement("div"),this.columnBandElements=[],this.selectingRange=!1,this.selectingRangeVisible=!1,this.tickTooltip=!0,this.tooltipStyle={},this.tickToolTip=document.createElement("div"),this._gridOrder="front",this.selectingRangeStyle={},this.updateValueRangesQueue=new Map,this.showingStats=!1,this._engineReady=!1,this.mouse=null,this.updatingLabel=!1,this.warnedDirection=new Set,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*_,this.theme=i?.theme||"dark",this._locale=i?.locale||r(),m(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.tickTooltip=i?.tickTooltip??!0,this.tooltipStyle=i?.tooltipStyle??{},this.ticksBar.onHoverTick=e=>this.onTickHover(e),this._gridOrder=i?.gridOrder??"front",this.setSelectingRangeStyle(i?.selectingRangeStyle??{}),this._selectionEditMode=i?.selectionEditMode??"always",this.selectionStyle=i?.selectionStyle??{},this.applyDrawingStyle(),this._selectionOrder=i?.selectionOrder??"front",this.selectionBehindContainer.style.position="absolute",this.selectionBehindContainer.style.width="100%",this.selectionBehindContainer.style.overflow="hidden",this.selectionBehindContainer.style.pointerEvents="none",this.selectionBehindContainer.style.zIndex="0",this.setBackground(i?.background),this.setFont(i?.font),this.syncMaxValues(),this.on("time",()=>this.renderSelectionOverlay()),this.on("size",()=>this.renderSelectionOverlay())}get locale(){return this._locale}setLocale(e){this._locale=e,m(e),this.ticksBar.setLocale(e),this.emit("locale",e)}setWeekLabel(e,t){this.ticksBar.setWeekLabel(e,t)}setTickLabelStyler(e){this.ticksBar.setTickLabelStyler(e)}get font(){return this._font?{...this._font}:void 0}setFont(e){this._font=e?{...e}:void 0;const t=$(e);this.ticksBar.setFont(F(t),t.size),this.yAxisTicks.setFont(e),this.applyTooltipStyles(),this.renderYAxis(),e&&"undefined"!=typeof document&&document.fonts&&document.fonts.load(F(t)).then(()=>this.refreshFonts(),()=>{})}refreshFonts(){this.ticksBar.refreshFont(),this.renderYAxis()}watchFontLoading(){if(this.stopWatchingFonts||"undefined"==typeof document||!document.fonts)return;const e=document.fonts,t=()=>this.refreshFonts();e.addEventListener("loadingdone",t),e.ready.then(t,()=>{}),this.stopWatchingFonts=()=>e.removeEventListener("loadingdone",t),this.onDestroy.push(()=>this.stopWatchingFonts?.())}watchPixelRatio(){if("undefined"==typeof window||!window.matchMedia)return;let e=()=>{};const t=()=>{const i=window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),s=()=>{e(),this.ticksBar.draw(),this.renderYAxis(),t()};i.addEventListener("change",s),e=()=>i.removeEventListener("change",s)};t(),this.onDestroy.push(()=>e())}get background(){return this._background}setBackground(e){this._background=e,this.engine?.setBackground(e),this.ticksBar.setBackground(e),this.updateBehindLayers()}setSelectingRangeStyle(e){this.selectingRangeStyle={...e},this.applyDrawingStyle()}applyDrawingStyle(){const e=this.selectingRangeElement,t=this.selectionStyle.drawing??{},i=this.resolveSelectionStyle("drawing");e.style.boxSizing="border-box",e.style.zIndex="3",e.style.background=t.fill??this.selectingRangeStyle.background??i.fill,e.style.border=t.border||!this.selectingRangeStyle.border?`${function(e){if(e<=0)return 0;const t=U();return Math.max(1,Math.round(e*t))/t}(i.border.width)}px ${i.border.style} ${i.border.color}`:this.selectingRangeStyle.border,e.style.filter=Y(i.glow)}get selectionEditMode(){return this._selectionEditMode}setSelectionEditMode(e){this._selectionEditMode=e,this.editingIndex=null,this.renderSelectionOverlay(!0)}get editingSelection(){return this.editingIndex}editSelection(e){const t=null!==e&&e>=0&&e<this._selectionRanges.length?e:null;t!==this.editingIndex&&(this.editingIndex=t,this.renderSelectionOverlay(!0),this.emit("selectionedit",null===t?null:{index:t,range:{...this._selectionRanges[t]}}))}setSelectionStyle(e){this.selectionStyle={idle:e.idle&&{...e.idle},editing:e.editing&&{...e.editing},drawing:e.drawing&&{...e.drawing}},this.applyDrawingStyle(),this.selectionRangeElements.forEach((e,t)=>this.styleSelectionRange(e,this.isRangeEditable(t))),this.renderSelectionOverlay()}get selectionOrder(){return this._selectionOrder}setSelectionOrder(e){this._selectionOrder=e,this.updateBehindLayers(),this.renderSelectionOverlay(!0)}isRangeEditable(e){return"always"===this._selectionEditMode||this.editingIndex===e}resolveSelectionStyle(e){const t=P[e],i=this.selectionStyle[e]??{},s=i.border?.color??t.border.color;return{fill:i.fill??t.fill,border:{color:s,width:i.border?.width??t.border.width,style:i.border?.style??t.border.style},handle:{color:i.handle?.color??t.handle.color,width:i.handle?.width??t.handle.width,look:i.handle?.look??t.handle.look},glow:i.glow?{color:i.glow.color??s,size:i.glow.size??8,intensity:i.glow.intensity??1}:void 0}}styleSelectionRange(e,t){const i=this.resolveSelectionStyle(t?"editing":"idle");e.fill.style.background=i.fill,e.frame.style.borderStyle=i.border.style,e.frame.style.borderColor=i.border.color,e.frame.style.filter=Y(i.glow),[e.startHandle,e.endHandle].forEach(e=>{const t=e?.firstElementChild;if(!t)return;t.style.background=i.handle.color;const s="grip"===i.handle.look;t.style.top=s?"50%":"0px",t.style.height=s?"min(32px, 40%)":"100%",t.style.transform=s?"translateY(-50%)":"",t.style.borderRadius=s?"999px":""})}layoutOverlays(){const e=this.sliderElement.style.top||"0px",t=this.sliderElement.style.height||"100%";[this.selectionOverlayContainer,this.columnBandOverlayContainer].forEach(i=>{i.style.top=e,i.style.height=t}),this.selectionBehindContainer.style.height=t,this.yAxisTicks.behindCanvas.style.height=t}get gridOrder(){return this._gridOrder}setGridOrder(e){this._gridOrder=e,this.updateBehindLayers(),this.renderYAxis()}updateBehindLayers(){const e="behind"===this._gridOrder||this.getVisibleLayers().some(e=>e.baseline)||"behind"===this._selectionOrder&&this._selectionRanges.length>0;this.engine?.setTransparent(e),this.sliderElement.style.background=e?this._background??("dark"===this.theme?"#111":"#eee"):""}attachBehindCanvas(){const e=this.yAxisTicks.behindCanvas;e.style.height=this.sliderElement.style.height,e.style.zIndex="0",[...this.sliderElement.children].forEach(t=>{t!==e&&t!==this.selectedLabel&&t!==this.selectionBehindContainer&&t instanceof HTMLCanvasElement&&(t.style.zIndex="1")}),e.parentElement!==this.sliderElement&&this.sliderElement.insertBefore(e,this.sliderElement.firstChild),this.selectionBehindContainer.parentElement!==this.sliderElement&&this.sliderElement.insertBefore(this.selectionBehindContainer,e.nextSibling),this.layoutOverlays()}setTickTooltip(e){this.tickTooltip=e,!1===e&&(this.tickToolTip.style.display="none")}setTooltipStyle(e){this.tooltipStyle={...e},this.applyTooltipStyles()}applyTooltipStyles(){this.applyTooltipStyle(this.toolTip),this.applyTooltipStyle(this.tickToolTip),this.applyTooltipStyle(this.selectedLabel,"200px")}applyTooltipStyle(e,t=""){const i=this.tooltipStyle;e.style.background=i.background??"rgba(0, 0, 0, 0.75)",e.style.color=i.color??"white",e.style.border=i.border??"none",e.style.borderRadius=i.borderRadius??"4px",e.style.padding=i.padding??"4px 8px",e.style.maxWidth=i.maxWidth??t,e.style.font=F($(i.font??this._font))}onTickHover(e){if(!e)return this.tickToolTip.style.display="none",void this.emit("tickhover",null);const t=this.ticksBar.getCanvasRect(),i=new DOMRect(t.left+e.x,t.top,e.width,t.height),s={startTime:e.startTime,endTime:e.endTime,unit:d(e.startTime,e.endTime),label:e.label,fullLabel:this.ticksBar.getFullLabel(e)};this.emit("tickhover",{...s,rect:i});const n=!1===this.tickTooltip?void 0:"function"==typeof this.tickTooltip?this.tickTooltip(s):s.fullLabel;if(!n)return void(this.tickToolTip.style.display="none");this.tickToolTip.textContent=n,this.tickToolTip.style.display="block";const l=this.tickToolTip.offsetWidth,o=this.tickToolTip.offsetHeight,a=Math.min(Math.max(4,i.left+.5*i.width-.5*l),window.innerWidth-l-4),r=i.top-o-6;this.tickToolTip.style.left=`${a}px`,this.tickToolTip.style.top=`${r>=4?r:i.bottom+6}px`}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})),null!==this.editingIndex&&this.editingIndex>=this._selectionRanges.length&&(this.editingIndex=null,this.emit("selectionedit",null)),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),l=U(),o=e=>Math.round(e*l),a=e=>e>0?Math.max(1,Math.round(e*l)):0;if((e||this.selectionRangeElements.length!==this._selectionRanges.length||this.selectionRangeElements.some((e,t)=>e.range!==this._selectionRanges[t]))&&(this.selectionRangeElements.forEach(({fill:e,frame:t,startHandle:i,endHandle:s})=>{e.remove(),t.remove(),i?.remove(),s?.remove()}),this.selectionRangeElements=this._selectionRanges.map((e,t)=>this.createSelectionRangeElements(e,t)),this.updateBehindLayers()),this.selectionRangeElements.forEach(({range:e,fill:t,frame:i,startHandle:s,endHandle:r},h)=>{const d=this.resolveSelectionStyle(this.isRangeEditable(h)?"editing":"idle"),c=e.startTime===-1/0,m=e.endTime===1/0,g=o(n(e.startTime)),u=o(n(e.endTime));t.style.left=g/l+"px",t.style.width=Math.max(0,u-g)/l+"px";const p=a(d.border.width),y=Math.floor(p/2),T=c?g:g-y,v=m?u:u-y+p,f=p/l;i.style.left=T/l+"px",i.style.width=Math.max(0,v-T)/l+"px",i.style.borderWidth=`${f}px ${m?0:f}px ${f}px ${c?0:f}px`;const x=(e,t)=>{const i=e?.firstElementChild;if(!e||!i)return;const s=a(d.handle.width),n=(t-Math.floor(s/2))/l,o=s/l,r=Math.max(8,o),h=n+.5*o-.5*r;e.style.left=h+"px",e.style.width=r+"px",i.style.left=n-h+"px",i.style.width=o+"px"};x(s,g),x(r,u)}),this.shadingElements.forEach(e=>e.remove()),this.shadingElements=[],this.selectionOptions.shading&&this._selectionRanges.length>0){const e=x(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",o=this.selectionOptions.columnBand?.opacity??.15;e.forEach(({layer:e,elements:t})=>{const i=t.map(u),s=Math.min(...i.map(e=>e[0])),a=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(a)-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(o),r.style.pointerEvents="none",this.columnBandOverlayContainer.appendChild(r),this.columnBandElements.push(r)})}createSelectionRangeElements(e,t){const i=this.isRangeEditable(t),s=document.createElement("div");s.style.position="absolute",s.style.top="0px",s.style.height="100%",s.style.pointerEvents="none",("behind"===this._selectionOrder?this.selectionBehindContainer:this.selectionOverlayContainer).appendChild(s);const n=document.createElement("div");n.style.position="absolute",n.style.top="0px",n.style.height="100%",n.style.boxSizing="border-box",n.style.background="transparent",n.style.pointerEvents=i?"auto":"none",n.style.cursor=i?"grab":"",n.style.touchAction=i?"none":"",this.selectionOverlayContainer.appendChild(n);const l=()=>{const e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.height="100%",e.style.cursor="ew-resize",e.style.pointerEvents="auto",e.style.touchAction="none";const t=document.createElement("div");return t.style.position="absolute",t.style.pointerEvents="none",e.appendChild(t),this.selectionOverlayContainer.appendChild(e),e},o=i&&e.startTime!==-1/0?l():null,a=i&&e.endTime!==1/0?l():null,r={range:e,fill:s,frame:n,startHandle:o,endHandle:a};return this.styleSelectionRange(r,i),i&&this.wireSelectionDrag(e,n,o,a),r}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 o=t=>{l||(l=!0,e.hasPointerCapture(t.pointerId)&&e.releasePointerCapture(t.pointerId),e.removeEventListener("pointermove",n),e.removeEventListener("pointerup",o),e.removeEventListener("pointercancel",o),e.removeEventListener("lostpointercapture",o),this.emit("selectionchange",{ranges:this.getSelection(),phase:"end"}))};this.emit("selectionchange",{ranges:this.getSelection(),phase:"start"}),e.addEventListener("pointermove",n),e.addEventListener("pointerup",o),e.addEventListener("pointercancel",o),e.addEventListener("lostpointercapture",o)})};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.editSelection(null),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,direction:this.isHangingDown(t)?"down":"up"})});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})}});const i=this.getVisibleLayers().filter(e=>e.baseline).map(e=>({y:this.isHangingDown(e)?e.max:e.min,color:e.baseline.color,width:e.baseline.width??1}));this.yAxisTicks.render(t,{gridBehind:"behind"===this._gridOrder,baselines:i})}setTheme(e){this.theme=e,this.updateBehindLayers(),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),this.engine.setBackground(this._background),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),this.attachBehindCanvas(),this.updateBehindLayers(),this.renderYAxis()}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)`,this.yAxisTicks.behindCanvas.style.height=this.sliderElement.style.height,this.layoutOverlays()}}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=d(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),i.style.isolation="isolate",this.yAxisTicks.canvas.style.zIndex="2",this.selectionOverlayContainer.style.zIndex="3",this.columnBandOverlayContainer.style.zIndex="3",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)`,this.selectionBehindContainer.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.initTickTooltip(),this.watchFontLoading();const n=e=>{"Escape"===e.key&&null!==this.editingIndex&&this.editSelection(null)};document.addEventListener("keydown",n),this.onDestroy.push(()=>document.removeEventListener("keydown",n)),this.watchPixelRatio(),this.initSelectLabel(),this.setSize(this.sliderElement.clientWidth,this.sliderElement.clientHeight),this.syncSize(),this.setTimeRange(K(t)),this.setValueRange(K(t))}else console.warn(`Element ${e} not found`)}initSelectLabel(){this.selectedLabel.style.position="absolute",this.applyTooltipStyle(this.selectedLabel,"200px"),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 o=Array.isArray(e.t);this.updatingLabel=!0;const a=()=>{if(!this.updatingLabel)return;const{startTime:i,duration:s,endTime:a}=this.getTimeRange(),r=t[0].layer.model.get(e.id);if(r){const e=E(this.getTimeRange(),r.t);if(e){const a=this.getSliderBounds();let h=(.5*(e.startTime+e.endTime)-i)/s*a.width;const d="number"==typeof r.v?r.v:.5*(r.v[1]+r.v[0]);let c=this.modelValueToPixels(d,t[0].layer);o?c-=.5*l:c+=8;const m=.5*n,g=.5*l,u=a.width-.5*n,p=a.height-.5*l,y=Math.min(u,Math.max(m,h)),T=Math.min(p,Math.max(g,c));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"};a();const r=s instanceof L&&s.histogram instanceof g;this.stopUpdatingLabel=this.on("time",r?i:a)}}else i()}onSelectionRangeClick(e){if("always"===this._selectionEditMode||0===this._selectionRanges.length)return;if("never"===this._selectionEditMode)return void this.editSelection(null);const{t:t}=this.mouseInSlider(e),i=this.findElements(e,24).some(e=>e.elements.length>0),s=this._selectionRanges.findIndex(e=>e.startTime<=t&&t<=e.endTime);this.editSelection(!i&&s>=0?s:null)}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.onSelectionRangeClick(e),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:o}=this.getTimeRange(),a=l+n.x*o,{minValue:r,maxValue:h}=this.getValueRange();return{absolute:s,normalized:n,t:a,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,n=t.max;const l=n-s;return{yInLayer:this.isHangingDown(t)?(n-i.y)/l:(i.y-s)/l,toLayerHeight:l/this.getSliderBounds().height}}isHangingDown(e){return"down"===e.direction&&(e instanceof R||(this.warnedDirection.has(e.id)||(this.warnedDirection.add(e.id),console.warn("Layer direction 'down' is only supported for bar (intervals / histogram) layers, ignoring it for",e.name)),!1))}pixelsToModelValue(e,t){const{yInLayer:i,toLayerHeight:s}=this.pixelsToLayerValue(e,t);let n=0,l=100;if(t.model instanceof p){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,s=t.max;const n=s-i,l=this.getSliderBounds().height;return(1-(this.isHangingDown(t)?s-n*e:i+n*e))*l}modelValueToPixels(e,t){let i=0,s=100;if(t.model instanceof p){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:o,duration:a}=this.getTimeRange(),r=l+n.x*a,h=t||12,d=h/i*a,c={startTime:r-1,endTime:r+1},m={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?c:m,o={minValue:t-.5*s,maxValue:t+.5*s},a=e.model.dataInRange({...l,...o});return{layer:e,elements:a,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(),o=n+s.x*l,a=(t||12)/i*l,r={startTime:o-1,endTime:o+1},h={startTime:o-.5*a,endTime:o+.5*a};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:o,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:s,duration:l}=this.getTimeRange(),o=i+t.x*l,a=this.findElements(this.mouse);this.renderColumnHoverBand(a),this.hoverCleared=!1,this.emit("hover",{elements:a.map(e=>({layer:e.layer,elements:e.elements})),t:o,clientX:this.mouse.x,clientY:this.mouse.y});const r=a.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=a.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(o),i=t.getHours(),s=t.getMinutes(),l=t.getSeconds(),a=n(o,!0,this._locale),r=`${(i<10?"0":"")+i}:${(s<10?"0":"")+s}:${(l<10?"0":"")+l}`;let d="";const c=this.ticksBar.cache.high.spacing;(void 0===this.hoverOptions.date?c>=B:this.hoverOptions.date)&&(d+=`<div>${a}</div>`),(void 0===this.hoverOptions.time?c<=M:this.hoverOptions.time)&&(d+=`<div>${r}</div>`),h&&(d+=h),this.toolTip.innerHTML=d,this.toolTip.style.display=d.length>0?"block":"none";const m=88,g=36;let u=this.mouse.x+10,p=this.mouse.y+10;const y=e.left+e.width-m-5,T=e.top+e.height-g-5;u>y&&(u=y),p>T&&(p=T),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="fixed",this.applyTooltipStyle(this.toolTip),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),this.onDestroy.push(()=>this.toolTip.remove())}initTickTooltip(){this.tickToolTip.style.position="fixed",this.applyTooltipStyle(this.tickToolTip),this.tickToolTip.style.pointerEvents="none",this.tickToolTip.style.display="none",this.tickToolTip.style.zIndex="10",this.tickToolTip.style.whiteSpace="pre-line",document.body.appendChild(this.tickToolTip),this.onDestroy.push(()=>this.tickToolTip.remove())}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 y(this.range.time)}getValueRange(){return this.range.value}setTimeRange(e,t){const i=this.getTimeRange(),s=v(i,e),n=this._limits?f(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.renderYAxis(),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*C){const e=Q(10*s);n=h(l,e)}else{const e=[{threshold:S,unit:"millennium"},{threshold:k,unit:"century"},{threshold:I,unit:"decade"},{threshold:.9*O,unit:"year"},{threshold:D,unit:"month"},{threshold:M,unit:"week"},{threshold:B,unit:"day"},{threshold:V,unit:"hour"},{threshold:_,unit:"minute"},{threshold:-1,unit:"second"}];let t=0;for(;s<.9*e[t].threshold;)t++;const i=e[t].unit;n=c(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*C){const e=Q(s/10);n=h(l,e)}else{let e=0;const t=[{threshold:C,unit:"century"},{threshold:S,unit:"decade"},{threshold:k,unit:"year"},{threshold:I,unit:"month"},{threshold:1.1*O,unit:"week"},{threshold:D,unit:"day"},{threshold:M,unit:"hour"},{threshold:B,unit:"minute"},{threshold:V,unit:"second"}].reverse();for(;s>1.1*t[e].threshold;)e++;const i=t[e].unit;n=c(l,i)}this.fit({...e,range:n})}next(e){this.skip(1,e)}previous(e){this.skip(-1,e)}skip(e,t){this.fit({...t,range:this.getSkipRange(e)})}getSkipRange(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange(),n=.5*(t+i);if(s>=9*C){const e=Q(s);return h(n,e)}const l=d(t,i);return l?c(n,l,Math.round(e)):{startTime:t+e*s,endTime:i+e*s}}clampToLimits(e){return this._limits?f(e,this._limits):e}describeStep(e){const t=this.getTimeRange(),i=this.getSkipRange(e),n=this.clampToLimits(i),l=Math.abs(n.startTime-t.startTime)>X||Math.abs(n.endTime-t.endTime)>X,o=l?n:i,a=e>0?s(t.startTime,o.startTime,this._locale):s(o.startTime,t.startTime,this._locale);return{range:n,canStep:l,span:a,label:G(e,a,this._locale)}}canStep(e){return this.describeStep(e).canStep}describeSpan(e){const{startTime:t,endTime:i}=e??this.getTimeRange(),n=s(t,i,this._locale);return{text:n.text,exact:n.exact,dates:a(t,i,this._locale)}}isFitted(e){const t=this.clampToLimits(e??this.getLayersTimeRange()),i=this.getTimeRange(),s=Math.max(X,.001*(t.endTime-t.startTime));return Math.abs(i.startTime-t.startTime)<=s&&Math.abs(i.endTime-t.endTime)<=s}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()?l([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?T(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 z;{let e=this.getVisibleLayers()[0].model.getTimeRange();return this.getVisibleLayers().slice(1).forEach(t=>e=b(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 ${o(Date.now()-i)}`);const l=this.syncMaxValuesForLayer(e);this.layerLoaders.set(e.id,t),this.layerUnloaders.set(e.id,()=>{l(),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=b(this.getTimeRange(),t);this.setTimeRange(e)}}const t=[e.on("visible",()=>{e.visible?this.loadLayer(e):this.unloadLayer(e),this.updateAllValueRanges(),this.updateBehindLayers()}),e.on("min",()=>this.onLayerBandChange(e)),e.on("max",()=>this.onLayerBandChange(e)),e.on("direction",()=>this.onLayerBandChange(e)),e.on("baseline",()=>{this.updateBehindLayers(),this.renderYAxis()})];this.layerListenerStoppers.set(e.id,()=>t.forEach(e=>e())),this.updateBehindLayers(),this.renderYAxis()}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),this.updateBehindLayers(),this.renderYAxis())}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),o=Math.max(i,n),a=(t-e)/(o-l);let r=e-l*a,h=t+(1-o)*a;if(a>W){const e=.5*(r+h);r=e-.5*W,h=e+.5*W}if(a<j){const e=.5*(r+h);r=e-.5*j,h=e+.5*j}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 o=e=>{this.sliderElement.focus(),e.preventDefault();const t=this.mouseInSlider(e);this.zoom(.001*e.deltaY,{x:t.normalized.x})};let a=0,r=-1;const h=e=>{const t=Date.now(),i=t-a;r>=0&&i<300&&i>0&&(this.select(null),e.preventDefault(),this.zoom(-.75,{animate:1e3,x:r})),a=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.pointerEvents="none",this.selectingRangeElement.style.position="absolute",this.selectingRangeElement.style.top="0px";const c=e=>{if(this.sliderElement.focus(),2===e.button||0===e.button){e.preventDefault();const t=this.mouseInSlider(e),i=t.normalized.x,{startTime:o,duration:a}=this.getTimeRange();s=o+i*a,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.selectingRangeElement.style.top=this.sliderElement.style.top||"0px",this.selectingRangeElement.style.height=this.sliderElement.style.height||"100%",this.container.appendChild(this.selectingRangeElement),this.selectingRangeVisible=!0):this.dragging=!0}},m=e=>{const t=this.mouseInSlider(e);return i=t.normalized.x,t},g=e=>{const t=m(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+"px"}if(!this.dragging||Date.now()-n<100&&Math.abs(l-t.absolute.x)<10)return;e.preventDefault();const i=t.normalized.x,{startTime:o,endTime:a}=this.getTimeRange(),r=o+i*(a-o)-s;this.setTimeRange({startTime:o-r,endTime:a-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 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",o),this.sliderElement.addEventListener("pointerdown",c),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 x=()=>{this.sliderElement.removeEventListener("contextmenu",f),this.sliderElement.removeEventListener("wheel",o),this.sliderElement.removeEventListener("pointerdown",c),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(x),e.add(x),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(),o={startTime:s-e*l*i,endTime:n+e*l*(1-i)},a=o.endTime-o.startTime,r=o.startTime+.5*a;a>W&&(o.startTime=r-.5*W,o.endTime=r+.5*W),a<j&&(o.startTime=r-.5*j,o.endTime=r+.5*j),this.fit({range:o,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:_}),this.play()}this.emit("live",e)}}}function K(e){return{startTime:"number"==typeof e?.startTime?e.startTime:"number"==typeof e?.endTime?e.duration?e.endTime-e.duration:e.endTime-M:e?.duration?Date.now()-.5*e.duration:Date.now()-.5*M,endTime:"number"==typeof e?.endTime?e.endTime:"number"==typeof e?.startTime?e.duration?e.startTime+e.duration:e.startTime+M:e?.duration?Date.now()+.5*e.duration:Date.now()+.5*M,duration:e?.duration?e.duration:"number"==typeof e?.startTime&&"number"==typeof e?.endTime?e.endTime+e.startTime:M,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}}const X=_,N={en:{next:"Next {span}",previous:"Previous {span}",nextUnit:"Next {unit}",previousUnit:"Previous {unit}"},de:{next:"Weiter: {span}",previous:"Zurück: {span}"},fr:{next:"Suivant : {span}",previous:"Précédent : {span}"},nl:{next:"Volgende: {span}",previous:"Vorige: {span}"}};function G(e,t,i){const s=N[i.split("-")[0].toLowerCase()];if(!s)return(e>0?"→ ":"← ")+t.text;const n=e>0?s.nextUnit:s.previousUnit;return n&&t.unitName?n.replace("{unit}",t.unitName):(e>0?s.next:s.previous).replace("{span}",t.text)}function Q(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{describeTimeSpan as s,formatDate as n,formatDateRange as l,formatDuration as o,formatTimeSpanDates as a,getDefaultLocale as r,getLargeTimeUnitRange as h,getMatchingTimeUnit as d,getTimeUnitRange as c,setDefaultLocale as m}from"../common/TimeTools.js";import{TimeSliderDynamicHistogram as g}from"../data/histogram/TimeSliderDynamicHistogram.js";import{getTimeArray as u}from"../data/TimeSliderElement.js";import{TimeSliderIntervalsModel as p}from"../data/TimeSliderIntervalsModel.js";import{addDuration as y,addPadding as T,applyTimeRangeUpdate as v,clampTimeRange as f,mergeTimeRanges as E,timeRangesOverlap as x,timeRangesUnion as b}from"../data/TimeSliderRange.js";import{TypedEventEmitter as w}from"../event/TypedEventEmitter.js";import{TimeSliderHistogramLayer as L}from"../layer/TimeSliderHistogramLayer.js";import{TimeSliderIntervalsLayer as R}from"../layer/TimeSliderIntervalsLayer.js";import{CENTURY as S,DECADE as k,MILLENIUM as C,ONE_DAY as M,ONE_HOUR as B,ONE_MINUTE as V,ONE_MONTH as O,ONE_SECOND as _,ONE_WEEK as D,ONE_YEAR as I,TODAY as z}from"../ticks/TimeSliderConstants.js";import{TimeTicksBar as A}from"../ticks/TimeTicksBar.js";import{YAxisTicks as H}from"../ticks/YAxisTicks.js";import{resolveFont as $,toCssFont as P}from"../common/Font.js";import{getDevicePixelRatio as F}from"../common/Pixels.js";const U={idle:{fill:"rgba(100, 180, 255, 0.15)",border:{color:"rgba(100, 180, 255, 0.8)",width:1,style:"solid"},handle:{color:"rgba(100, 180, 255, 0.9)",width:0,look:"bar"}},editing:{fill:"rgba(100, 180, 255, 0.15)",border:{color:"rgba(100, 180, 255, 0.8)",width:2,style:"solid"},handle:{color:"rgba(100, 180, 255, 0.9)",width:4,look:"bar"}},drawing:{fill:"#df04",border:{color:"#df0",width:3,style:"solid"},handle:{color:"#df0",width:0,look:"bar"}}};function Y(e){if(!e||e.size<=0||e.intensity<=0)return"";const t=Math.round(100*Math.min(1,e.intensity)),i=`color-mix(in srgb, ${e.color} ${t}%, transparent)`;return`drop-shadow(0 0 ${.4*e.size}px ${i}) drop-shadow(0 0 ${e.size}px ${i})`}const j=_,W=10*C;export class TimeSlider extends w{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 A,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:z,value:{minValue:0,maxValue:100}},this.size={width:100,height:100},this.sliderElement=document.createElement("div"),this.yAxisTicks=new H,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.selectionBehindContainer=document.createElement("div"),this._selectionEditMode="always",this.editingIndex=null,this.selectionStyle={},this._selectionOrder="front",this.shadingElements=[],this.columnBandOverlayContainer=document.createElement("div"),this.columnBandElements=[],this.selectingRange=!1,this.selectingRangeVisible=!1,this.tickTooltip=!0,this.tooltipStyle={},this.tickToolTip=document.createElement("div"),this._gridOrder="front",this.selectingRangeStyle={},this.updateValueRangesQueue=new Map,this.showingStats=!1,this._engineReady=!1,this.mouse=null,this.updatingLabel=!1,this.warnedDirection=new Set,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*_,this.theme=i?.theme||"dark",this._locale=i?.locale||r(),m(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.tickTooltip=i?.tickTooltip??!0,this.tooltipStyle=i?.tooltipStyle??{},this.ticksBar.onHoverTick=e=>this.onTickHover(e),this._gridOrder=i?.gridOrder??"front",this.setSelectingRangeStyle(i?.selectingRangeStyle??{}),this._selectionEditMode=i?.selectionEditMode??"always",this.selectionStyle=i?.selectionStyle??{},this.applyDrawingStyle(),this._selectionOrder=i?.selectionOrder??"front",this.selectionBehindContainer.style.position="absolute",this.selectionBehindContainer.style.width="100%",this.selectionBehindContainer.style.overflow="hidden",this.selectionBehindContainer.style.pointerEvents="none",this.selectionBehindContainer.style.zIndex="0",this.setBackground(i?.background),this.setFont(i?.font),this.syncMaxValues(),this.on("time",()=>this.renderSelectionOverlay()),this.on("size",()=>this.renderSelectionOverlay())}get locale(){return this._locale}setLocale(e){this._locale=e,m(e),this.ticksBar.setLocale(e),this.emit("locale",e)}setWeekLabel(e,t){this.ticksBar.setWeekLabel(e,t)}setTickLabelStyler(e){this.ticksBar.setTickLabelStyler(e)}get font(){return this._font?{...this._font}:void 0}setFont(e){this._font=e?{...e}:void 0;const t=$(e);this.ticksBar.setFont(P(t),t.size),this.yAxisTicks.setFont(e),this.applyTooltipStyles(),this.renderYAxis(),e&&"undefined"!=typeof document&&document.fonts&&document.fonts.load(P(t)).then(()=>this.refreshFonts(),()=>{})}refreshFonts(){this.ticksBar.refreshFont(),this.renderYAxis()}watchFontLoading(){if(this.stopWatchingFonts||"undefined"==typeof document||!document.fonts)return;const e=document.fonts,t=()=>this.refreshFonts();e.addEventListener("loadingdone",t),e.ready.then(t,()=>{}),this.stopWatchingFonts=()=>e.removeEventListener("loadingdone",t),this.onDestroy.push(()=>this.stopWatchingFonts?.())}watchPixelRatio(){if("undefined"==typeof window||!window.matchMedia)return;let e=()=>{};const t=()=>{const i=window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),s=()=>{e(),this.ticksBar.draw(),this.renderYAxis(),t()};i.addEventListener("change",s),e=()=>i.removeEventListener("change",s)};t(),this.onDestroy.push(()=>e())}get background(){return this._background}setBackground(e){this._background=e,this.engine?.setBackground(e),this.ticksBar.setBackground(e),this.updateBehindLayers()}setSelectingRangeStyle(e){this.selectingRangeStyle={...e},this.applyDrawingStyle()}applyDrawingStyle(){const e=this.selectingRangeElement,t=this.selectionStyle.drawing??{},i=this.resolveSelectionStyle("drawing");e.style.boxSizing="border-box",e.style.zIndex="3",e.style.background=t.fill??this.selectingRangeStyle.background??i.fill,e.style.border=t.border||!this.selectingRangeStyle.border?`${function(e){if(e<=0)return 0;const t=F();return Math.max(1,Math.round(e*t))/t}(i.border.width)}px ${i.border.style} ${i.border.color}`:this.selectingRangeStyle.border,e.style.filter=Y(i.glow)}get selectionEditMode(){return this._selectionEditMode}setSelectionEditMode(e){this._selectionEditMode=e,this.editingIndex=null,this.renderSelectionOverlay(!0)}get editingSelection(){return this.editingIndex}editSelection(e){const t=null!==e&&e>=0&&e<this._selectionRanges.length?e:null;t!==this.editingIndex&&(this.editingIndex=t,this.renderSelectionOverlay(!0),this.emit("selectionedit",null===t?null:{index:t,range:{...this._selectionRanges[t]}}))}setSelectionStyle(e){this.selectionStyle={idle:e.idle&&{...e.idle},editing:e.editing&&{...e.editing},drawing:e.drawing&&{...e.drawing}},this.applyDrawingStyle(),this.selectionRangeElements.forEach((e,t)=>this.styleSelectionRange(e,this.isRangeEditable(t))),this.renderSelectionOverlay()}get selectionOrder(){return this._selectionOrder}setSelectionOrder(e){this._selectionOrder=e,this.updateBehindLayers(),this.renderSelectionOverlay(!0)}isRangeEditable(e){return"always"===this._selectionEditMode||this.editingIndex===e}resolveSelectionStyle(e){const t=U[e],i=this.selectionStyle[e]??{},s=i.border?.color??t.border.color;return{fill:i.fill??t.fill,border:{color:s,width:i.border?.width??t.border.width,style:i.border?.style??t.border.style},handle:{color:i.handle?.color??t.handle.color,width:i.handle?.width??t.handle.width,look:i.handle?.look??t.handle.look},glow:i.glow?{color:i.glow.color??s,size:i.glow.size??8,intensity:i.glow.intensity??1}:void 0}}styleSelectionRange(e,t){const i=this.resolveSelectionStyle(t?"editing":"idle");e.fill.style.background=i.fill,e.frame.style.borderStyle=i.border.style,e.frame.style.borderColor=i.border.color,e.frame.style.filter=Y(i.glow),[e.startHandle,e.endHandle].forEach(e=>{const t=e?.firstElementChild;if(!t)return;t.style.background=i.handle.color;const s="grip"===i.handle.look;t.style.top=s?"50%":"0px",t.style.height=s?"min(32px, 40%)":"100%",t.style.transform=s?"translateY(-50%)":"",t.style.borderRadius=s?"999px":""})}layoutOverlays(){const e=this.sliderElement.style.top||"0px",t=this.sliderElement.style.height||"100%";[this.selectionOverlayContainer,this.columnBandOverlayContainer].forEach(i=>{i.style.top=e,i.style.height=t}),this.selectionBehindContainer.style.height=t,this.yAxisTicks.behindCanvas.style.height=t}get gridOrder(){return this._gridOrder}setGridOrder(e){this._gridOrder=e,this.updateBehindLayers(),this.renderYAxis()}updateBehindLayers(){const e="behind"===this._gridOrder||this.getVisibleLayers().some(e=>e.baseline)||"behind"===this._selectionOrder&&this._selectionRanges.length>0;this.engine?.setTransparent(e),this.sliderElement.style.background=e?this._background??("dark"===this.theme?"#111":"#eee"):""}attachBehindCanvas(){const e=this.yAxisTicks.behindCanvas;e.style.height=this.sliderElement.style.height,e.style.zIndex="0",[...this.sliderElement.children].forEach(t=>{t!==e&&t!==this.selectedLabel&&t!==this.selectionBehindContainer&&t instanceof HTMLCanvasElement&&(t.style.zIndex="1")}),e.parentElement!==this.sliderElement&&this.sliderElement.insertBefore(e,this.sliderElement.firstChild),this.selectionBehindContainer.parentElement!==this.sliderElement&&this.sliderElement.insertBefore(this.selectionBehindContainer,e.nextSibling),this.layoutOverlays()}setTickTooltip(e){this.tickTooltip=e,!1===e&&(this.tickToolTip.style.display="none")}setTooltipStyle(e){this.tooltipStyle={...e},this.applyTooltipStyles()}applyTooltipStyles(){this.applyTooltipStyle(this.toolTip),this.applyTooltipStyle(this.tickToolTip),this.applyTooltipStyle(this.selectedLabel,"200px")}applyTooltipStyle(e,t=""){const i=this.tooltipStyle;e.style.background=i.background??"rgba(0, 0, 0, 0.75)",e.style.color=i.color??"white",e.style.border=i.border??"none",e.style.borderRadius=i.borderRadius??"4px",e.style.padding=i.padding??"4px 8px",e.style.maxWidth=i.maxWidth??t,e.style.font=P($(i.font??this._font))}onTickHover(e){if(!e)return this.tickToolTip.style.display="none",void this.emit("tickhover",null);const t=this.ticksBar.getCanvasRect(),i=new DOMRect(t.left+e.x,t.top,e.width,t.height),s={startTime:e.startTime,endTime:e.endTime,unit:d(e.startTime,e.endTime),label:e.label,fullLabel:this.ticksBar.getFullLabel(e)};this.emit("tickhover",{...s,rect:i});const n=!1===this.tickTooltip?void 0:"function"==typeof this.tickTooltip?this.tickTooltip(s):s.fullLabel;if(!n)return void(this.tickToolTip.style.display="none");this.tickToolTip.textContent=n,this.tickToolTip.style.display="block";const l=this.tickToolTip.offsetWidth,o=this.tickToolTip.offsetHeight,a=Math.min(Math.max(4,i.left+.5*i.width-.5*l),window.innerWidth-l-4),r=i.top-o-6;this.tickToolTip.style.left=`${a}px`,this.tickToolTip.style.top=`${r>=4?r:i.bottom+6}px`}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})),null!==this.editingIndex&&this.editingIndex>=this._selectionRanges.length&&(this.editingIndex=null,this.emit("selectionedit",null)),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),l=F(),o=e=>Math.round(e*l),a=e=>e>0?Math.max(1,Math.round(e*l)):0;if((e||this.selectionRangeElements.length!==this._selectionRanges.length||this.selectionRangeElements.some((e,t)=>e.range!==this._selectionRanges[t]))&&(this.selectionRangeElements.forEach(({fill:e,frame:t,startHandle:i,endHandle:s})=>{e.remove(),t.remove(),i?.remove(),s?.remove()}),this.selectionRangeElements=this._selectionRanges.map((e,t)=>this.createSelectionRangeElements(e,t)),this.updateBehindLayers()),this.selectionRangeElements.forEach(({range:e,fill:t,frame:i,startHandle:s,endHandle:r},h)=>{const d=this.resolveSelectionStyle(this.isRangeEditable(h)?"editing":"idle"),c=e.startTime===-1/0,m=e.endTime===1/0,g=o(n(e.startTime)),u=o(n(e.endTime));t.style.left=g/l+"px",t.style.width=Math.max(0,u-g)/l+"px";const p=a(d.border.width),y=Math.floor(p/2),T=c?g:g-y,v=m?u:u-y+p,f=p/l;i.style.left=T/l+"px",i.style.width=Math.max(0,v-T)/l+"px",i.style.borderWidth=`${f}px ${m?0:f}px ${f}px ${c?0:f}px`;const E=(e,t)=>{const i=e?.firstElementChild;if(!e||!i)return;const s=a(d.handle.width),n=(t-Math.floor(s/2))/l,o=s/l,r=Math.max(8,o),h=n+.5*o-.5*r;e.style.left=h+"px",e.style.width=r+"px",i.style.left=n-h+"px",i.style.width=o+"px"};E(s,g),E(r,u)}),this.shadingElements.forEach(e=>e.remove()),this.shadingElements=[],this.selectionOptions.shading&&this._selectionRanges.length>0){const e=E(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",o=this.selectionOptions.columnBand?.opacity??.15;e.forEach(({layer:e,elements:t})=>{const i=t.map(u),s=Math.min(...i.map(e=>e[0])),a=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(a)-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(o),r.style.pointerEvents="none",this.columnBandOverlayContainer.appendChild(r),this.columnBandElements.push(r)})}createSelectionRangeElements(e,t){const i=this.isRangeEditable(t),s=document.createElement("div");s.style.position="absolute",s.style.top="0px",s.style.height="100%",s.style.pointerEvents="none",("behind"===this._selectionOrder?this.selectionBehindContainer:this.selectionOverlayContainer).appendChild(s);const n=document.createElement("div");n.style.position="absolute",n.style.top="0px",n.style.height="100%",n.style.boxSizing="border-box",n.style.background="transparent",n.style.pointerEvents=i?"auto":"none",n.style.cursor=i?"grab":"",n.style.touchAction=i?"none":"",this.selectionOverlayContainer.appendChild(n);const l=()=>{const e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.height="100%",e.style.cursor="ew-resize",e.style.pointerEvents="auto",e.style.touchAction="none";const t=document.createElement("div");return t.style.position="absolute",t.style.pointerEvents="none",e.appendChild(t),this.selectionOverlayContainer.appendChild(e),e},o=i&&e.startTime!==-1/0?l():null,a=i&&e.endTime!==1/0?l():null,r={range:e,fill:s,frame:n,startHandle:o,endHandle:a};return this.styleSelectionRange(r,i),i&&this.wireSelectionDrag(e,n,o,a),r}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 o=t=>{l||(l=!0,e.hasPointerCapture(t.pointerId)&&e.releasePointerCapture(t.pointerId),e.removeEventListener("pointermove",n),e.removeEventListener("pointerup",o),e.removeEventListener("pointercancel",o),e.removeEventListener("lostpointercapture",o),this.emit("selectionchange",{ranges:this.getSelection(),phase:"end"}))};this.emit("selectionchange",{ranges:this.getSelection(),phase:"start"}),e.addEventListener("pointermove",n),e.addEventListener("pointerup",o),e.addEventListener("pointercancel",o),e.addEventListener("lostpointercapture",o)})};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.editSelection(null),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,direction:this.isHangingDown(t)?"down":"up"})});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})}});const i=this.getVisibleLayers().filter(e=>e.baseline).map(e=>({y:this.isHangingDown(e)?e.max:e.min,color:e.baseline.color,width:e.baseline.width??1}));this.yAxisTicks.render(t,{gridBehind:"behind"===this._gridOrder,baselines:i})}setTheme(e){this.theme=e,this.updateBehindLayers(),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),this.engine.setBackground(this._background),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),this.attachBehindCanvas(),this.updateBehindLayers(),this.renderYAxis()}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)`,this.yAxisTicks.behindCanvas.style.height=this.sliderElement.style.height,this.layoutOverlays()}}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=d(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),i.style.isolation="isolate",this.yAxisTicks.canvas.style.zIndex="2",this.selectionOverlayContainer.style.zIndex="3",this.columnBandOverlayContainer.style.zIndex="3",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)`,this.selectionBehindContainer.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.initTickTooltip(),this.watchFontLoading();const n=e=>{"Escape"===e.key&&null!==this.editingIndex&&this.editSelection(null)};document.addEventListener("keydown",n),this.onDestroy.push(()=>document.removeEventListener("keydown",n)),this.watchPixelRatio(),this.initSelectLabel(),this.setSize(this.sliderElement.clientWidth,this.sliderElement.clientHeight),this.syncSize(),this.setTimeRange(K(t)),this.setValueRange(K(t))}else console.warn(`Element ${e} not found`)}initSelectLabel(){this.selectedLabel.style.position="absolute",this.applyTooltipStyle(this.selectedLabel,"200px"),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 o=Array.isArray(e.t);this.updatingLabel=!0;const a=()=>{if(!this.updatingLabel)return;const{startTime:i,duration:s,endTime:a}=this.getTimeRange(),r=t[0].layer.model.get(e.id);if(r){const e=x(this.getTimeRange(),r.t);if(e){const a=this.getSliderBounds();let h=(.5*(e.startTime+e.endTime)-i)/s*a.width;const d="number"==typeof r.v?r.v:.5*(r.v[1]+r.v[0]);let c=this.modelValueToPixels(d,t[0].layer);o?c-=.5*l:c+=8;const m=.5*n,g=.5*l,u=a.width-.5*n,p=a.height-.5*l,y=Math.min(u,Math.max(m,h)),T=Math.min(p,Math.max(g,c));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"};a();const r=s instanceof L&&s.histogram instanceof g;this.stopUpdatingLabel=this.on("time",r?i:a)}}else i()}onSelectionRangeClick(e){if("always"===this._selectionEditMode||0===this._selectionRanges.length)return;if("never"===this._selectionEditMode)return void this.editSelection(null);const{t:t}=this.mouseInSlider(e),i=this.findElementsAtPoint(e).some(e=>e.elements.length>0),s=this._selectionRanges.findIndex(e=>e.startTime<=t&&t<=e.endTime);this.editSelection(!i&&s>=0?s:null)}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.onSelectionRangeClick(e),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:o}=this.getTimeRange(),a=l+n.x*o,{minValue:r,maxValue:h}=this.getValueRange();return{absolute:s,normalized:n,t:a,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,n=t.max;const l=n-s;return{yInLayer:this.isHangingDown(t)?(n-i.y)/l:(i.y-s)/l,toLayerHeight:l/this.getSliderBounds().height}}isHangingDown(e){return"down"===e.direction&&(e instanceof R||(this.warnedDirection.has(e.id)||(this.warnedDirection.add(e.id),console.warn("Layer direction 'down' is only supported for bar (intervals / histogram) layers, ignoring it for",e.name)),!1))}pixelsToModelValue(e,t){const{yInLayer:i,toLayerHeight:s}=this.pixelsToLayerValue(e,t);let n=0,l=100;if(t.model instanceof p){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,s=t.max;const n=s-i,l=this.getSliderBounds().height;return(1-(this.isHangingDown(t)?s-n*e:i+n*e))*l}modelValueToPixels(e,t){let i=0,s=100;if(t.model instanceof p){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){return"column"===this.selectionOptions.pick?this.findColumnElements(e):this.findElementsAtPoint(e,t)}findElementsAtPoint(e,t){const{width:i,height:s}=this.getSliderBounds(),{normalized:n}=this.mouseInSlider(e),{startTime:l,endTime:o,duration:a}=this.getTimeRange(),r=l+n.x*a,h=t||12,d=h/i*a,c={startTime:r-1,endTime:r+1},m={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?c:m,o={minValue:t-.5*s,maxValue:t+.5*s},a=e.model.dataInRange({...l,...o});return{layer:e,elements:a,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(),o=n+s.x*l,a=(t||12)/i*l,r={startTime:o-1,endTime:o+1},h={startTime:o-.5*a,endTime:o+.5*a};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:o,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:s,duration:l}=this.getTimeRange(),o=i+t.x*l,a=this.findElements(this.mouse);this.renderColumnHoverBand(a),this.hoverCleared=!1,this.emit("hover",{elements:a.map(e=>({layer:e.layer,elements:e.elements})),t:o,clientX:this.mouse.x,clientY:this.mouse.y});const r=a.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=a.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(o),i=t.getHours(),s=t.getMinutes(),l=t.getSeconds(),a=n(o,!0,this._locale),r=`${(i<10?"0":"")+i}:${(s<10?"0":"")+s}:${(l<10?"0":"")+l}`;let d="";const c=this.ticksBar.cache.high.spacing;(void 0===this.hoverOptions.date?c>=B:this.hoverOptions.date)&&(d+=`<div>${a}</div>`),(void 0===this.hoverOptions.time?c<=M:this.hoverOptions.time)&&(d+=`<div>${r}</div>`),h&&(d+=h),this.toolTip.innerHTML=d,this.toolTip.style.display=d.length>0?"block":"none";const m=88,g=36;let u=this.mouse.x+10,p=this.mouse.y+10;const y=e.left+e.width-m-5,T=e.top+e.height-g-5;u>y&&(u=y),p>T&&(p=T),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="fixed",this.applyTooltipStyle(this.toolTip),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),this.onDestroy.push(()=>this.toolTip.remove())}initTickTooltip(){this.tickToolTip.style.position="fixed",this.applyTooltipStyle(this.tickToolTip),this.tickToolTip.style.pointerEvents="none",this.tickToolTip.style.display="none",this.tickToolTip.style.zIndex="10",this.tickToolTip.style.whiteSpace="pre-line",document.body.appendChild(this.tickToolTip),this.onDestroy.push(()=>this.tickToolTip.remove())}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 y(this.range.time)}getValueRange(){return this.range.value}setTimeRange(e,t){const i=this.getTimeRange(),s=v(i,e),n=this._limits?f(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.renderYAxis(),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*C){const e=Q(10*s);n=h(l,e)}else{const e=[{threshold:S,unit:"millennium"},{threshold:k,unit:"century"},{threshold:I,unit:"decade"},{threshold:.9*O,unit:"year"},{threshold:D,unit:"month"},{threshold:M,unit:"week"},{threshold:B,unit:"day"},{threshold:V,unit:"hour"},{threshold:_,unit:"minute"},{threshold:-1,unit:"second"}];let t=0;for(;s<.9*e[t].threshold;)t++;const i=e[t].unit;n=c(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*C){const e=Q(s/10);n=h(l,e)}else{let e=0;const t=[{threshold:C,unit:"century"},{threshold:S,unit:"decade"},{threshold:k,unit:"year"},{threshold:I,unit:"month"},{threshold:1.1*O,unit:"week"},{threshold:D,unit:"day"},{threshold:M,unit:"hour"},{threshold:B,unit:"minute"},{threshold:V,unit:"second"}].reverse();for(;s>1.1*t[e].threshold;)e++;const i=t[e].unit;n=c(l,i)}this.fit({...e,range:n})}next(e){this.skip(1,e)}previous(e){this.skip(-1,e)}skip(e,t){this.fit({...t,range:this.getSkipRange(e)})}getSkipRange(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange(),n=.5*(t+i);if(s>=9*C){const e=Q(s);return h(n,e)}const l=d(t,i);return l?c(n,l,Math.round(e)):{startTime:t+e*s,endTime:i+e*s}}clampToLimits(e){return this._limits?f(e,this._limits):e}describeStep(e){const t=this.getTimeRange(),i=this.getSkipRange(e),n=this.clampToLimits(i),l=Math.abs(n.startTime-t.startTime)>X||Math.abs(n.endTime-t.endTime)>X,o=l?n:i,a=e>0?s(t.startTime,o.startTime,this._locale):s(o.startTime,t.startTime,this._locale);return{range:n,canStep:l,span:a,label:G(e,a,this._locale)}}canStep(e){return this.describeStep(e).canStep}describeSpan(e){const{startTime:t,endTime:i}=e??this.getTimeRange(),n=s(t,i,this._locale);return{text:n.text,exact:n.exact,dates:a(t,i,this._locale)}}isFitted(e){const t=this.clampToLimits(e??this.getLayersTimeRange()),i=this.getTimeRange(),s=Math.max(X,.001*(t.endTime-t.startTime));return Math.abs(i.startTime-t.startTime)<=s&&Math.abs(i.endTime-t.endTime)<=s}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()?l([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?T(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 z;{let e=this.getVisibleLayers()[0].model.getTimeRange();return this.getVisibleLayers().slice(1).forEach(t=>e=b(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 ${o(Date.now()-i)}`);const l=this.syncMaxValuesForLayer(e);this.layerLoaders.set(e.id,t),this.layerUnloaders.set(e.id,()=>{l(),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=b(this.getTimeRange(),t);this.setTimeRange(e)}}const t=[e.on("visible",()=>{e.visible?this.loadLayer(e):this.unloadLayer(e),this.updateAllValueRanges(),this.updateBehindLayers()}),e.on("min",()=>this.onLayerBandChange(e)),e.on("max",()=>this.onLayerBandChange(e)),e.on("direction",()=>this.onLayerBandChange(e)),e.on("baseline",()=>{this.updateBehindLayers(),this.renderYAxis()})];this.layerListenerStoppers.set(e.id,()=>t.forEach(e=>e())),this.updateBehindLayers(),this.renderYAxis()}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),this.updateBehindLayers(),this.renderYAxis())}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),o=Math.max(i,n),a=(t-e)/(o-l);let r=e-l*a,h=t+(1-o)*a;if(a>W){const e=.5*(r+h);r=e-.5*W,h=e+.5*W}if(a<j){const e=.5*(r+h);r=e-.5*j,h=e+.5*j}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 o=e=>{this.sliderElement.focus(),e.preventDefault();const t=this.mouseInSlider(e);this.zoom(.001*e.deltaY,{x:t.normalized.x})};let a=0,r=-1;const h=e=>{const t=Date.now(),i=t-a;r>=0&&i<300&&i>0&&(this.select(null),e.preventDefault(),this.zoom(-.75,{animate:1e3,x:r})),a=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.pointerEvents="none",this.selectingRangeElement.style.position="absolute",this.selectingRangeElement.style.top="0px";const c=e=>{if(this.sliderElement.focus(),2===e.button||0===e.button){e.preventDefault();const t=this.mouseInSlider(e),i=t.normalized.x,{startTime:o,duration:a}=this.getTimeRange();s=o+i*a,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.selectingRangeElement.style.top=this.sliderElement.style.top||"0px",this.selectingRangeElement.style.height=this.sliderElement.style.height||"100%",this.container.appendChild(this.selectingRangeElement),this.selectingRangeVisible=!0):this.dragging=!0}},m=e=>{const t=this.mouseInSlider(e);return i=t.normalized.x,t},g=e=>{const t=m(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+"px"}if(!this.dragging||Date.now()-n<100&&Math.abs(l-t.absolute.x)<10)return;e.preventDefault();const i=t.normalized.x,{startTime:o,endTime:a}=this.getTimeRange(),r=o+i*(a-o)-s;this.setTimeRange({startTime:o-r,endTime:a-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 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",o),this.sliderElement.addEventListener("pointerdown",c),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",o),this.sliderElement.removeEventListener("pointerdown",c),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(),o={startTime:s-e*l*i,endTime:n+e*l*(1-i)},a=o.endTime-o.startTime,r=o.startTime+.5*a;a>W&&(o.startTime=r-.5*W,o.endTime=r+.5*W),a<j&&(o.startTime=r-.5*j,o.endTime=r+.5*j),this.fit({range:o,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:_}),this.play()}this.emit("live",e)}}}function K(e){return{startTime:"number"==typeof e?.startTime?e.startTime:"number"==typeof e?.endTime?e.duration?e.endTime-e.duration:e.endTime-M:e?.duration?Date.now()-.5*e.duration:Date.now()-.5*M,endTime:"number"==typeof e?.endTime?e.endTime:"number"==typeof e?.startTime?e.duration?e.startTime+e.duration:e.startTime+M:e?.duration?Date.now()+.5*e.duration:Date.now()+.5*M,duration:e?.duration?e.duration:"number"==typeof e?.startTime&&"number"==typeof e?.endTime?e.endTime+e.startTime:M,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}}const X=_,N={en:{next:"Next {span}",previous:"Previous {span}",nextUnit:"Next {unit}",previousUnit:"Previous {unit}"},de:{next:"Weiter: {span}",previous:"Zurück: {span}"},fr:{next:"Suivant : {span}",previous:"Précédent : {span}"},nl:{next:"Volgende: {span}",previous:"Vorige: {span}"}};function G(e,t,i){const s=N[i.split("-")[0].toLowerCase()];if(!s)return(e>0?"→ ":"← ")+t.text;const n=e>0?s.nextUnit:s.previousUnit;return n&&t.unitName?n.replace("{unit}",t.unitName):(e>0?s.next:s.previous).replace("{span}",t.text)}function Q(e){const t=e/315576e5,i=Math.log10(t),s=Math.ceil(i);return Math.pow(10,s)}
@@ -17,6 +17,15 @@ export declare class TimeSliderHistogramLayer<M extends TimeSliderModel = TimeSl
17
17
  maxClassifications?: number;
18
18
  _classificationColors: string[];
19
19
  constructor(content: M, options?: TimeSliderHistogramLayerOptions<M>);
20
+ /**
21
+ * Re-classifies only these elements of the content model (ids, or elements with an id), e.g. those whose
22
+ * filter state changed, instead of every element: each moves from its old class to the one the classifier
23
+ * now gives it, and the bars are re-stacked once per frame. A new classifier (or style change) still does a
24
+ * full pass. Dynamic (non-fixed) histograms only re-bin these; fixed ones do a full pass.
25
+ */
26
+ reclassify(elementsOrIds: Iterable<string | {
27
+ id: string;
28
+ }>): void;
20
29
  getClassification(element: TimeSliderInterval<TimeSliderHistogramAttributes>, v: number): string | undefined;
21
30
  set classificationColors(ccs: string[]);
22
31
  get classificationColors(): string[];
@@ -1 +1 @@
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
+ 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 o}from"./TimeSliderIntervalsLayer.js";export class TimeSliderHistogramLayer extends o{constructor(i,t){super(new e,t),this.content=i,this.d=new s;const o=this.createHistogram({classifier:t?.classifier,...t?.style});this.histogram=o,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?o.start(this.timeSlider):o.stop()})),this.d.add(this.on("invalidateAll",()=>{o.average=!0===this.style.average,o.weighted=!0===this.style.weighted,o.inverted=!0===this.style.inverted,this.style.mode&&(o.mode=this.style.mode),o.classifier=this.style.classifier,this.style.classOrder&&(o.classOrder=this.style.classOrder)}))}reclassify(s){const i=[];for(const t of s)i.push("string"==typeof t?t:t.id);this.histogram.reclassify(i)}getClassification(s,i){const t=s.v[1]-s.v[0],e=s.attributes?.splits||[1],o=i/t;let a=0;for(let s=0;s<e.length;s++)if(a+=e[s],o<a)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{}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protomaze/time",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Protomaze Time sliders",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",