@protomaze/time 1.4.3

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.
Files changed (152) hide show
  1. package/README.md +1 -0
  2. package/TimeSliderDemo.d.ts +1 -0
  3. package/TimeSliderDemo.js +1 -0
  4. package/common/CaptureConsole.d.ts +5 -0
  5. package/common/CaptureConsole.js +1 -0
  6. package/common/Clamper.d.ts +6 -0
  7. package/common/Clamper.js +1 -0
  8. package/common/Disposables.d.ts +7 -0
  9. package/common/Disposables.js +1 -0
  10. package/common/Easing.d.ts +1 -0
  11. package/common/Easing.js +1 -0
  12. package/common/Expand.d.ts +3 -0
  13. package/common/Expand.js +1 -0
  14. package/common/GlslTools.d.ts +4 -0
  15. package/common/GlslTools.js +1 -0
  16. package/common/TimeTools.d.ts +42 -0
  17. package/common/TimeTools.js +1 -0
  18. package/data/CompositeTimeSliderModel.d.ts +13 -0
  19. package/data/CompositeTimeSliderModel.js +1 -0
  20. package/data/IntervalLaneManager.d.ts +24 -0
  21. package/data/IntervalLaneManager.js +1 -0
  22. package/data/TimeSliderBush.d.ts +23 -0
  23. package/data/TimeSliderBush.js +1 -0
  24. package/data/TimeSliderElement.d.ts +21 -0
  25. package/data/TimeSliderElement.js +1 -0
  26. package/data/TimeSliderIntervalsModel.d.ts +6 -0
  27. package/data/TimeSliderIntervalsModel.js +1 -0
  28. package/data/TimeSliderLanesModel.d.ts +11 -0
  29. package/data/TimeSliderLanesModel.js +1 -0
  30. package/data/TimeSliderModel.d.ts +45 -0
  31. package/data/TimeSliderModel.js +1 -0
  32. package/data/TimeSliderPointsModel.d.ts +6 -0
  33. package/data/TimeSliderPointsModel.js +1 -0
  34. package/data/TimeSliderRange.d.ts +30 -0
  35. package/data/TimeSliderRange.js +1 -0
  36. package/data/histogram/TimeSliderDynamicHistogram.d.ts +21 -0
  37. package/data/histogram/TimeSliderDynamicHistogram.js +1 -0
  38. package/data/histogram/TimeSliderFixedHistogram.d.ts +52 -0
  39. package/data/histogram/TimeSliderFixedHistogram.js +1 -0
  40. package/data/histogram/TimeSliderHistogram.d.ts +68 -0
  41. package/data/histogram/TimeSliderHistogram.js +1 -0
  42. package/data/histogram/TimeSliderSplittingFixedHistogram.d.ts +45 -0
  43. package/data/histogram/TimeSliderSplittingFixedHistogram.js +1 -0
  44. package/demo/Common.d.ts +21 -0
  45. package/demo/Common.js +1 -0
  46. package/demo/Metrics.d.ts +2 -0
  47. package/demo/Metrics.js +1 -0
  48. package/demo/Nasdaq.d.ts +3 -0
  49. package/demo/Nasdaq.js +1 -0
  50. package/demo/Quakes.d.ts +3 -0
  51. package/demo/Quakes.js +1 -0
  52. package/demo/QuakesFilters.d.ts +3 -0
  53. package/demo/QuakesFilters.js +1 -0
  54. package/demo/Random.d.ts +49 -0
  55. package/demo/Random.js +1 -0
  56. package/demo/Test.d.ts +5 -0
  57. package/demo/Test.js +1 -0
  58. package/demo/Wars.d.ts +2 -0
  59. package/demo/Wars.js +1 -0
  60. package/engine/HorizontalPinchZoom.d.ts +3 -0
  61. package/engine/HorizontalPinchZoom.js +1 -0
  62. package/engine/PinchZoom.d.ts +17 -0
  63. package/engine/PinchZoom.js +1 -0
  64. package/engine/TimeSlider.d.ts +225 -0
  65. package/engine/TimeSlider.js +1 -0
  66. package/engine/TimeSliderEngine.d.ts +42 -0
  67. package/engine/TimeSliderEngine.js +1 -0
  68. package/event/TypedEventEmitter.d.ts +13 -0
  69. package/event/TypedEventEmitter.js +1 -0
  70. package/index.d.ts +1 -0
  71. package/index.js +1 -0
  72. package/layer/TimeSliderHistogramLayer.d.ts +27 -0
  73. package/layer/TimeSliderHistogramLayer.js +1 -0
  74. package/layer/TimeSliderHistogramLayerOld.d.ts +20 -0
  75. package/layer/TimeSliderHistogramLayerOld.js +1 -0
  76. package/layer/TimeSliderIntervalsLayer.d.ts +7 -0
  77. package/layer/TimeSliderIntervalsLayer.js +1 -0
  78. package/layer/TimeSliderLayer.d.ts +66 -0
  79. package/layer/TimeSliderLayer.js +1 -0
  80. package/layer/TimeSliderLayerLoader.d.ts +8 -0
  81. package/layer/TimeSliderLayerLoader.js +1 -0
  82. package/layer/TimeSliderPointsLayer.d.ts +7 -0
  83. package/layer/TimeSliderPointsLayer.js +1 -0
  84. package/package.json +58 -0
  85. package/react/ColoredSlider.d.ts +58 -0
  86. package/react/ColoredSlider.js +1 -0
  87. package/react/ColoredSliderExtendsInput.d.ts +31 -0
  88. package/react/ColoredSliderExtendsInput.js +1 -0
  89. package/react/DateLabelWithPicker.d.ts +6 -0
  90. package/react/DateLabelWithPicker.js +1 -0
  91. package/react/DateRangeLabelWithPicker.d.ts +7 -0
  92. package/react/DateRangeLabelWithPicker.js +1 -0
  93. package/react/DeepMemoHook.d.ts +1 -0
  94. package/react/DeepMemoHook.js +1 -0
  95. package/react/FullscreenButton.d.ts +1 -0
  96. package/react/FullscreenButton.js +1 -0
  97. package/react/MaterialIconButton.d.ts +7 -0
  98. package/react/MaterialIconButton.js +1 -0
  99. package/react/MaterialTextButton.d.ts +8 -0
  100. package/react/MaterialTextButton.js +1 -0
  101. package/react/PinchZoomHook.d.ts +10 -0
  102. package/react/PinchZoomHook.js +1 -0
  103. package/react/PointerClick.d.ts +1 -0
  104. package/react/PointerClick.js +1 -0
  105. package/react/ReactTimeSlider.d.ts +52 -0
  106. package/react/ReactTimeSlider.js +1 -0
  107. package/react/TimeLabelWithPicker.d.ts +8 -0
  108. package/react/TimeLabelWithPicker.js +1 -0
  109. package/react/YearScroller.d.ts +13 -0
  110. package/react/YearScroller.js +1 -0
  111. package/style/TimeSliderColors.d.ts +6 -0
  112. package/style/TimeSliderColors.js +1 -0
  113. package/style/TimeSliderHistogramStyle.d.ts +3 -0
  114. package/style/TimeSliderHistogramStyle.js +1 -0
  115. package/style/TimeSliderIntervalsStyle.d.ts +13 -0
  116. package/style/TimeSliderIntervalsStyle.js +1 -0
  117. package/style/TimeSliderLabeler.d.ts +2 -0
  118. package/style/TimeSliderLabeler.js +1 -0
  119. package/style/TimeSliderPointsStyle.d.ts +38 -0
  120. package/style/TimeSliderPointsStyle.js +1 -0
  121. package/style/TimeSliderStyle.d.ts +1 -0
  122. package/style/TimeSliderStyle.js +1 -0
  123. package/style/TimeSliderStyler.d.ts +3 -0
  124. package/style/TimeSliderStyler.js +1 -0
  125. package/three/Three3DTimeSliderEngine.d.ts +27 -0
  126. package/three/Three3DTimeSliderEngine.js +1 -0
  127. package/three/ThreeTimeSlider.d.ts +4 -0
  128. package/three/ThreeTimeSlider.js +1 -0
  129. package/three/ThreeTimeSliderEngine.d.ts +20 -0
  130. package/three/ThreeTimeSliderEngine.js +1 -0
  131. package/three/layer/GrowingBufferGeometry.d.ts +26 -0
  132. package/three/layer/GrowingBufferGeometry.js +1 -0
  133. package/three/layer/GrowingInstanceMatrix.d.ts +43 -0
  134. package/three/layer/GrowingInstanceMatrix.js +1 -0
  135. package/three/layer/Three3DIntervalsTimeLayerLoader.d.ts +11 -0
  136. package/three/layer/Three3DIntervalsTimeLayerLoader.js +1 -0
  137. package/three/layer/Three3DPointsTimeLayerLoader.d.ts +10 -0
  138. package/three/layer/Three3DPointsTimeLayerLoader.js +1 -0
  139. package/three/layer/ThreeIntervalsTimeLayerLoader.d.ts +10 -0
  140. package/three/layer/ThreeIntervalsTimeLayerLoader.js +1 -0
  141. package/three/layer/ThreePointsTimeLayerLoader.d.ts +9 -0
  142. package/three/layer/ThreePointsTimeLayerLoader.js +1 -0
  143. package/three/layer/ThreeTimeLayerLoader.d.ts +10 -0
  144. package/three/layer/ThreeTimeLayerLoader.js +1 -0
  145. package/three/react/ReactThreeTimeSlider.d.ts +2 -0
  146. package/three/react/ReactThreeTimeSlider.js +1 -0
  147. package/ticks/TimeSliderConstants.d.ts +15 -0
  148. package/ticks/TimeSliderConstants.js +1 -0
  149. package/ticks/TimeTicksBar.d.ts +46 -0
  150. package/ticks/TimeTicksBar.js +1 -0
  151. package/ticks/YAxisTicks.d.ts +31 -0
  152. package/ticks/YAxisTicks.js +1 -0
@@ -0,0 +1 @@
1
+ import{getTimeOffset as t,getTimeUnitRange as e}from"../../common/TimeTools";import{ONE_HOUR as s}from"../../ticks/TimeSliderConstants";import{TimeSliderHistogram as i}from"./TimeSliderHistogram";const o="default";export class TimeSliderSplittingFixedHistogram extends i{constructor(t,e,i){super(t,e,i),this.model=t,this.content=e,this.elementClasifications=new Map,this.elementBoxRanges=new Map,this.classificationIndices=new Map,this.boxes=new Map,this.maxEncountered=1e3,this.loggin=!1,this.loggin=i?.loggin||!1,this.time0=this.mode?.fixed?.start||Date.UTC(0,0,1,0,0,0,0),this.duration=this.mode?.fixed?.duration||s,this.populate(),this.content.on("added",t=>{t&&this.addElement(t)}),this.content.on("updated",t=>{const e=t.updated;e&&this.updateElement(e)}),this.content.on("removed",t=>{this.elementBoxRanges.get(t)&&this.removeElement(t)})}startUpdating(t){}stopUpdating(){}onOptionsChanged(t){"classifier"===t&&(this.elementClasifications.clear(),this.classificationIndices.clear(),this.boxes.forEach(t=>t.values={}),this.populate())}populate(){this.classOrder.forEach((t,e)=>this.classificationIndices.set(t,e)),this.time0=this.mode?.fixed?.start||Date.UTC(0,0,1,0,0,0,0),this.duration=this.mode?.fixed?.duration||s;this.content.data.forEach(t=>this.addElement(t,!0)),this.boxes.forEach(t=>this.updateBoxInterval(t))}addElement(t,e){const s=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,s);const i=this.weighted?this.toSingleValue(t.v):1,n=this.classifier?this.classifier(t):void 0;if(null!==n){const a=n||o;this.registerClassification(a),this.elementClasifications.set(t.id,a),this.forBoxRange(s,s=>{s.values[a]||(s.values[a]=new Map),s.values[a].set(t.id,i),e||this.updateBoxInterval(s)},{create:!0})}}updateElement(t){const e=this.classifier?this.classifier(t):void 0;if(null===e)this.removeElement(t.id);else{const s=e||o;this.elementClasifications.set(t.id,s);const i=this.elementBoxRanges.get(t.id);if(i){const e=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,e);const o=[];for(let e=i[0];e<=i[1];e++){const i=this.getBox(e);i&&(i.values[s].delete(t.id),o.push(e))}const n=this.weighted?this.toSingleValue(t.v):1;for(let i=e[0];i<=e[1];i++){const e=this.requireBox(i);e.values[s]||(e.values[s]=new Map),e.values[s].set(t.id,n),o.push(i)}o.forEach(t=>{const e=this.getBox(t);e&&this.updateBoxInterval(e)})}else this.addElement(t)}}removeElement(t){const e=this.elementBoxRanges.get(t),s=this.elementClasifications.get(t)||o;if(this.elementBoxRanges.delete(t),e)for(let i=e[0];i<=e[1];i++){const e=this.getBox(i);e&&(e.values[s].delete(t),this.updateBoxInterval(e))}}getBox(t){return this.boxes.get(t)}getBoxIndex(e){return this.mode?.fixedUnit?t(this.time0,e,this.mode?.fixedUnit):Math.floor((e-this.time0)/this.duration)}getBoxRange(t){if("number"==typeof t){const e=this.getBoxIndex(t);return[e,e]}return t.map(this.getBoxIndex)}createBox(t){let s,i;if(this.mode?.fixedUnit){const{startTime:o,endTime:n}=e(this.time0,this.mode?.fixedUnit,t);s=o,i=n}else s=this.time0+t*this.duration,i=this.time0+t*this.duration+this.duration;const o={index:t,start:s,end:i,values:{}};return this.boxes.set(t,o),o}requireBox(t){const e=this.getBox(t);return e||this.createBox(t)}forBoxRange(t,e,s){for(let i=t[0];i<=t[1];i++){const t=s?.create?this.requireBox(i):this.getBox(i);t&&e(t)}}getBoxValue(t){return this.weighted?Object.values(t.values).map(t=>Array.from(t.values())).flat().reduce((t,e)=>t+e,0):Object.values(t.values).map(t=>t.size).reduce((t,e)=>t+e,0)}updateBoxInterval(t){const e=t.index+"",s=this.model.get(e),i=this.getBoxValue(t),o=s?s.v[1]-s.v[0]:0,n={attributes:{splits:[1]}};if(this.classifier){const s=1499===t.index;Math.abs(o-i)>1e-5&&(this.loggin&&s&&console.log("- Setting value",e),n.v=this.inverted?[this.maxEncountered-i,this.maxEncountered]:[0,i]);let a=0;n.attributes={splits:this.classOrder.map(e=>{const s=t.values[e];if(s){const t=this.weighted?Array.from(s.values()).reduce((t,e)=>t+e):s.size;a+=t;return a/i}return a/i})},this.loggin&&s&&console.log("- Setting splits",e),this.loggin&&a<.999&&console.log({accumulated:a,classOrder:this.classOrder,splits:n.attributes.splits,box:t}),this.loggin&&s&&console.log(n.attributes.splits)}else o!==i&&(this.loggin&&console.log("- Setting value (no classification)",e),n.v=this.inverted?[this.maxEncountered-i,this.maxEncountered]:[0,i]);s?this.model.update(e,n):i>0&&this.model.add({id:e,t:[t.start,t.end],...n})}toSingleValue(t){return Array.isArray(t)?.5*(t[0]+t[1]):t}}
@@ -0,0 +1,21 @@
1
+ import { CompositeTimeSliderModel } from "../data/CompositeTimeSliderModel";
2
+ import { TimeSliderIntervalsModel } from "../data/TimeSliderIntervalsModel";
3
+ import { TimeSliderModel } from "../data/TimeSliderModel";
4
+ import { TimeSliderPointsModel } from "../data/TimeSliderPointsModel";
5
+ import { TimeSliderHistogramLayer, TimeSliderHistogramLayerOptions } from "../layer/TimeSliderHistogramLayer";
6
+ import { TimeSliderIntervalsLayer, TimeSliderIntervalsLayerOptions } from "../layer/TimeSliderIntervalsLayer";
7
+ import { TimeSliderPointsLayer, TimeSliderPointsLayerOptions } from "../layer/TimeSliderPointsLayer";
8
+ export declare function createDemoPointsLayer(model: TimeSliderPointsModel, options?: TimeSliderPointsLayerOptions): TimeSliderPointsLayer;
9
+ export declare function createDemoIntervalsLayer(model: TimeSliderIntervalsModel, options?: TimeSliderIntervalsLayerOptions): TimeSliderIntervalsLayer<import("../data/TimeSliderElement").TimeSliderInterval<any>, {
10
+ fill?: {
11
+ color?: string;
12
+ opacity?: number;
13
+ };
14
+ border?: {
15
+ centered?: boolean;
16
+ color?: string;
17
+ opacity?: number;
18
+ width?: number;
19
+ };
20
+ }>;
21
+ export declare function createDemoHistogramLayer(models: TimeSliderModel<any>[], options?: TimeSliderHistogramLayerOptions): TimeSliderHistogramLayer<CompositeTimeSliderModel | TimeSliderModel<any>>;
package/demo/Common.js ADDED
@@ -0,0 +1 @@
1
+ import{CompositeTimeSliderModel as e}from"../data/CompositeTimeSliderModel";import{TimeSliderHistogramLayer as r}from"../layer/TimeSliderHistogramLayer";import{TimeSliderIntervalsLayer as o}from"../layer/TimeSliderIntervalsLayer";import{TimeSliderPointsLayer as t}from"../layer/TimeSliderPointsLayer";export function createDemoPointsLayer(e,r){return new t(e,{name:e.name||"Points",...r,style:{point:{size:12,color:"#000",border:{color:"#f00",width:2},core:{color:"#df0",size:4},multipass:!0},line:{color:"#000",border:{color:"#f00",width:2},width:8},area:{color:"#df0",opacity:1},...r?.style}})}export function createDemoIntervalsLayer(e,r){return new o(e,{name:e.name||"Intervals",...r,style:{fill:{color:"#f00",opacity:.3},border:{color:"#df0",width:4},...r?.style}})}export function createDemoHistogramLayer(o,t){return new r(1===o.length?o[0]:new e(...o),{name:1===o.length&&o[0].name?o[0].name+" Histogram":"Histogram",...t,style:{fill:{color:"#0df",opacity:.3},border:{color:"#0df",width:1},inverted:!0,...t?.style}})}
@@ -0,0 +1,2 @@
1
+ export declare const METRICS_SINGLE_LAYERS: (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[];
2
+ export declare const METRICS_MULTI_LAYERS: (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[][];
@@ -0,0 +1 @@
1
+ import{v4 as o}from"uuid";import{TimeSliderPointsModel as e}from"../data/TimeSliderPointsModel";import{createDemoHistogramLayer as n,createDemoPointsLayer as t}from"./Common";const i=function(){const n=new e;n.name="FPS";let t=!1,i=0,a=performance.now(),m=60;function r(e){if(t&&e===i){const t=performance.now(),i=t-a;a=t;let d=1e3/i;const l=10;d-m>l&&(d=m+l),m=d,d<=100&&n.add({id:o(),t:Date.now(),v:d,name:Math.round(d)+" FPS"}),requestAnimationFrame(()=>r(e))}}return n.on("loaded",o=>{console.log({loaded:o}),o!==t&&(t=o,t?(console.log("LETSGO"),i++,r(i)):console.log("STOPPING"))}),n}();export const METRICS_SINGLE_LAYERS=[n([i],{min:.9,style:{weighted:!0}}),t(i,{min:.5,max:.9,style:{area:{color:"#df0",height:.2,opacity:1}}})];export const METRICS_MULTI_LAYERS=[[t(i,{min:.25,max:1,style:{line:void 0,area:void 0}}),n([i],{min:0,max:.25,style:{weighted:!0,mode:{fixed:{duration:100}},inverted:!1}})],[t(i,{min:.5,max:1,style:{point:void 0,area:{color:"#df0",height:.2,opacity:1}}})],[n([i],{min:.9})]];
@@ -0,0 +1,3 @@
1
+ import { TimeSliderPointsLayer } from "../layer/TimeSliderPointsLayer";
2
+ export declare const NASDAQ_SINGLE_LAYERS: (TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[];
3
+ export declare const NASDAQ_MULTI_LAYERS: TimeSliderPointsLayer[][];
package/demo/Nasdaq.js ADDED
@@ -0,0 +1 @@
1
+ import{v4 as e}from"uuid";import{TimeSliderPointsModel as t}from"../data/TimeSliderPointsModel";import{TimeSliderPointsLayer as a}from"../layer/TimeSliderPointsLayer";import{createDemoHistogramLayer as r}from"./Common";const o=[{name:"Apple",color:"#FFFFFF",darker:"#888888"},{name:"Amazon",color:"#ED6C2D",darker:"#823e1c"},{name:"Microsoft",color:"#00A4EF",darker:"#02557b"},{name:"Netflix",color:"#C7322D",darker:"#6e1916"},{name:"McDonalds",color:"#F7CF46",darker:"#715e1f"},{name:"Spotify",color:"#65D56E",darker:"#35733a"}],n=o.map(r=>{const o=function(a){const r=new t;return r.name=a,fetch("./resources/data/"+a.toLowerCase()+".csv").then(e=>e.text()).then(t=>{const o=t.split("\n");let n=1/0,i=-1/0;const l=[];for(let t=1;t<o.length;t++){const r=o[t];if(r.length>20){const[t,o]=r.split(","),c=parseFloat(o.slice(1)),s=new Date(t).getTime();n=Math.min(n,c),i=Math.max(i,c),l.push({t:s,v:c,name:a+" "+o,id:e()})}}l.forEach(e=>{e.v=100*(e.v-n)/(i-n),r.add(e)})}),r}(r.name),n=r.color,i={area:{color:"Apple"===r.name?"#ccc":l(n,.5)},line:{width:7,color:n,border:{width:2,color:"#000"}},point:void 0};return{layer:new a(o,{min:.5,max:.95,style:{...i,area:{...i.area,height:.05,opacity:.5}}}),multiLayer:new a(o,{style:{...i,area:{...i.area,base:!0,opacity:1}}})}}),i=r(n.map(e=>e.layer.model),{max:.5,style:{weighted:!0,inverted:!1,average:!0,mode:{autoUnits:!0,minUnit:"week",maxUnit:"year"},fill:{opacity:.5},border:{centered:!0,width:1}},classifier:e=>o.find(t=>t.name===e.name?.split(" ")[0])?.name,styler:e=>{const t=o.find(t=>t.name===e.attributes?.classification),a=t?.color;return{fill:{color:a},border:{color:"#000"}}},labeler:e=>e.attributes?.classification+" "+Math.round(100*(e.attributes?.percentage||0))+"%"});export const NASDAQ_SINGLE_LAYERS=[...n.map(e=>e.layer),i];export const NASDAQ_MULTI_LAYERS=n.map(e=>[e.multiLayer]);function l(e,t){const a=Math.min(Math.max(t,0),1),r=parseInt(e.slice(1,3),16),o=parseInt(e.slice(3,5),16),n=parseInt(e.slice(5,7),16),i=Math.round(r+(255-r)*a),l=Math.round(o+(255-o)*a),c=Math.round(n+(255-n)*a);return`#${i.toString(16).padStart(2,"0")}${l.toString(16).padStart(2,"0")}${c.toString(16).padStart(2,"0")}`}
@@ -0,0 +1,3 @@
1
+ export declare const quakesHistogramLayer: import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>;
2
+ export declare const QUAKES_SINGLE_LAYERS: (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[];
3
+ export declare const QUAKES_MULTI_LAYERS: (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[][];
package/demo/Quakes.js ADDED
@@ -0,0 +1 @@
1
+ import{v4 as e}from"uuid";import{getTimeUnitRange as t}from"../common/TimeTools";import{TimeSliderPointsModel as a}from"../data/TimeSliderPointsModel";import{getMagnitudeColors as o,getMagnitudeColors2 as r,getUltraFadedMagnitudeColors as s}from"../style/TimeSliderColors";import{createDemoHistogramLayer as n,createDemoPointsLayer as i}from"./Common";const l=function(){const t=new a;t.name="Quakes";let o=9999;return fetch("./resources/data/quakes.json").then(e=>e.json()).then(a=>{a.features.forEach(a=>{const r=a.properties.mag,s=4+24*(r-6),n=a.geometry?.coordinates[2]||0;o=Math.min(o,n);const i={id:e(),t:a.properties.time,v:s,attributes:{depth:n,mag:r},name:a.properties.title};t.add(i)}),console.log({min:o})}),t}(),m=u("global_anomaly"),c=u("ocean_anomaly"),d={area:{color:"#0fd",height:.2,opacity:1},line:{color:"#000",border:{color:"#0df"}},point:void 0},p=Array.from({length:10},(e,t)=>t.toString());export const quakesHistogramLayer=n([l],{min:0,max:.3,style:{inverted:!1,mode:{fixedUnit:"month"},classOrder:p},classifier:e=>Math.round(e.attributes.depth/68.8)+"",styler:e=>{const t=o()[parseInt(e.attributes?.classification||"0")];return{fill:{color:t},border:{color:t}}},maxClassifications:20,classificationColors:[...o(),...s()],labeler:e=>`Depth -${68.8*parseInt(e.attributes?.classification||"0")}m`});export const QUAKES_SINGLE_LAYERS=[i(c,{min:.8,max:1,style:d}),i(l,{min:.3,max:.8,style:{line:void 0,area:void 0}}),quakesHistogramLayer];export const QUAKES_MULTI_LAYERS=[[n([l],{min:.8,style:{mode:{autoUnits:!0},classOrder:p},classifier:e=>Math.round(e.v/10)+"",styler:e=>{const t=r()[parseInt(e.attributes?.classification||"0")];return{fill:{color:t},border:{color:t}}},labeler:e=>{const t=6+.4*parseInt(e.attributes?.classification||"0"),a=t+.4;return`Mag ${t.toFixed(1)}-${a.toFixed(1)}`}}),i(l,{max:.8,style:{line:void 0,area:void 0}})],[i(c,{style:d}),i(m,{style:{point:void 0,area:{color:"#df0",height:.2,opacity:1}}})]];function u(o){const r=new a;switch(o){case"global_temp_abs":r.name="Global Temperature";break;case"global_anomaly":r.name="Global Temperature Anomaly";break;case"ocean_temp_abs":r.name="Ocean Temperature";break;case"ocean_anomaly":r.name="Ocean Temperature Anomaly"}return fetch("./resources/data/temperature.json").then(e=>e.json()).then(a=>{a.forEach(a=>{const s=a[o];if(null!==s){const n=new Date,[i,l]=a.date.split("-").map(e=>parseInt(e));n.setFullYear(i),n.setMonth(l-1),n.setDate(10);const m=t(n.getTime(),"month"),c=o.includes("abs")?10*(s-10):40*s+50,d={id:e(),t:.5*(m.startTime+m.endTime),v:c,name:a.date};r.add(d)}})}),r}
@@ -0,0 +1,3 @@
1
+ export declare function QuakesFilters({ darkMode }: {
2
+ darkMode: boolean;
3
+ }): JSX.Element;
@@ -0,0 +1 @@
1
+ import t,{useEffect as e,useState as a}from"react";import{MaterialTextButton as n}from"../react/MaterialTextButton";import{quakesHistogramLayer as r}from"./Quakes";const i=Array.from({length:10},(t,e)=>e.toString());function o(t,e){return Math.min(e.length-1,Math.max(0,Math.round(t)))}export function QuakesFilters({darkMode:s}){const[m,l]=a(0),[p,u]=a(6),[c,g]=a("mag");return e(()=>{const t=t=>t.attributes.mag>p&&t.attributes.depth>m?0:10;r.histogram.classifier="mag"===c?e=>o(2.5*(e.attributes.mag-6),i)+t(e)+"":e=>o(e.attributes.depth/68.8,i)+t(e)+"",r.labeler="mag"===c?(t,e,a)=>{const n=r.getClassification(t,a),i=6+.4*parseInt(n||"0"),o=i+.4;return`Mag ${i.toFixed(1)}-${o.toFixed(1)}`}:(t,e,a)=>{const n=r.getClassification(t,a);return`Depth -${68.8*parseInt(n||"0")}m`}},[m,p,c]),t.createElement("div",{style:{zIndex:999,position:"absolute",inset:"88px 16px 16px",pointerEvents:"none"}},t.createElement("div",{className:"select-container",style:{backgroundColor:s?"#222":"#ddd",padding:"4px",borderRadius:"4px",pointerEvents:"initial",position:"absolute",justifySelf:"center",top:"20%"}},t.createElement("input",{type:"range",min:0,step:1,max:688,value:m,onChange:t=>l(Number(t.target.value))}),t.createElement("input",{type:"range",min:6,step:.1,max:10,value:p,onChange:t=>u(Number(t.target.value))}),t.createElement(n,{text:"Random",onClick:()=>g("mag"),active:"mag"===c}),t.createElement(n,{text:"Magnitude",onClick:()=>g("depth"),active:"depth"===c})))}
@@ -0,0 +1,49 @@
1
+ export declare const RANDOM_SINGLE_LAYERS: (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderIntervalsLayer").TimeSliderIntervalsLayer<import("../data/TimeSliderElement").TimeSliderInterval<any>, {
2
+ fill?: {
3
+ color?: string;
4
+ opacity?: number;
5
+ };
6
+ border?: {
7
+ centered?: boolean;
8
+ color?: string;
9
+ opacity?: number;
10
+ width?: number;
11
+ };
12
+ }> | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[];
13
+ export declare const RANDOM_MULTI_LAYERS: ((import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[] | (import("../layer/TimeSliderPointsLayer").TimeSliderPointsLayer | import("../layer/TimeSliderIntervalsLayer").TimeSliderIntervalsLayer<import("../data/TimeSliderElement").TimeSliderInterval<any>, {
14
+ fill?: {
15
+ color?: string;
16
+ opacity?: number;
17
+ };
18
+ border?: {
19
+ centered?: boolean;
20
+ color?: string;
21
+ opacity?: number;
22
+ width?: number;
23
+ };
24
+ }>)[] | (import("../layer/TimeSliderIntervalsLayer").TimeSliderIntervalsLayer<import("../data/TimeSliderElement").TimeSliderInterval<any>, {
25
+ fill?: {
26
+ color?: string;
27
+ opacity?: number;
28
+ };
29
+ border?: {
30
+ centered?: boolean;
31
+ color?: string;
32
+ opacity?: number;
33
+ width?: number;
34
+ };
35
+ }> | import("../layer/TimeSliderHistogramLayer").TimeSliderHistogramLayer<import("../data/CompositeTimeSliderModel").CompositeTimeSliderModel | import("../data/TimeSliderModel").TimeSliderModel<any>>)[])[];
36
+ export declare function getDistinctColors(): string[];
37
+ export declare function invertColor(color: string, opacity?: number): string;
38
+ export declare function parseColor(color: string): [number, number, number];
39
+ export declare function getRandomFunkyName(): string;
40
+ /**
41
+ * Generates a realistic sample point (y) between 0 and 1 for a given x.
42
+ * This version uses a self-contained value noise algorithm.
43
+ *
44
+ * @param x The input coordinate (e.g., an index, time, or position).
45
+ * @param frequency Controls how quickly the y-value changes. Higher values lead to more rapid fluctuations.
46
+ * @param amplitude Controls the magnitude of the fluctuations. A value of 1 means the full range of noise is used.
47
+ * @returns A number between 0 and 1.
48
+ */
49
+ export declare function generateRealisticY(x: number, frequency?: number, amplitude?: number): number;
package/demo/Random.js ADDED
@@ -0,0 +1 @@
1
+ import{v4 as t}from"uuid";import{TimeSliderLanesModel as e}from"../data/TimeSliderLanesModel";import{TimeSliderPointsModel as o}from"../data/TimeSliderPointsModel";import{ONE_SECOND as n}from"../ticks/TimeSliderConstants";import{createDemoHistogramLayer as a,createDemoIntervalsLayer as r,createDemoPointsLayer as i}from"./Common";const d=function(){const e=new o;return e.name="Measurements",function(e){const n=e||new o;setInterval(()=>{const e=Date.now()+10*Math.random(),o=5+90*generateRealisticY(.02*e,.1,.8);n.add({id:t(),t:e,v:o,name:"M#"+n.data.length+" ("+Math.round(o)+"%)"})},10)}(e),e}(),{model:c,styleMap:m}=function(){const o=new e;o.name="Tracks";const a=function(e){const o=e,a=new Set,r=new Map,i=()=>{const e=getDistinctColors()[Math.floor(20*Math.random())],i=getDistinctColors()[Math.floor(20*Math.random())],d=t(),c={id:d,name:getRandomFunkyName(),t:[Date.now(),Date.now()]};return r.set(d,{fill:{color:e},border:{color:i}}),a.add(c),o.add(c),setTimeout(()=>{o.update(c,{t:[c.t[0],Date.now()]}),a.delete(c)},n+7*Math.random()*n),c};i();const d=7,c=()=>{a.size<d&&Math.random()<1*Math.random()*(1-a.size/d)&&i(),a.forEach(t=>{o.update(t,{t:[t.t[0],Date.now()]})}),requestAnimationFrame(c)};return c(),r}(o);return{model:o,styleMap:a}}();export const RANDOM_SINGLE_LAYERS=[a([d,c],{min:.9,style:{weighted:!0}}),i(d,{min:.5,max:.9,style:{area:{color:"#df0",height:.2,opacity:1}}}),r(c,{max:.5})];export const RANDOM_MULTI_LAYERS=[[i(d,{min:.25,max:1,style:{line:void 0,area:void 0}}),a([d],{min:0,max:.25,style:{weighted:!0,mode:{fixed:{duration:100}},inverted:!1}})],[i(d,{min:.5,max:1,style:{point:void 0,area:{color:"#df0",height:.2,opacity:1}}}),r(c,{min:0,max:.5,style:{border:{width:2,color:"#df0"}}})],[r(c,{max:.8,style:{border:{centered:!1,width:4}},styler:t=>m.get(t.id)}),a([c],{min:.9})]];export function getDistinctColors(){return["#e6194B","#3cb44b","#ffe119","#4363d8","#f58231","#911eb4","#42d4f4","#bfef45","#f032e6","#808000","#fabed4","#469990","#dcbeff","#9A6324","#fffac8","#800000","#aaffc3","#ffd8b1","#000075","#a9a9a9"]}export function invertColor(t,e){const[o,n,a]=parseColor(t),r=void 0!==e?Math.max(0,Math.min(1,e)):1,i=t=>255*t;return`rgb(${i(1-o)}, ${i(1-n)}, ${i(1-a)}, ${r})`}export function parseColor(t){const e=document.createElement("canvas").getContext("2d");e.fillStyle=t,e.fillRect(0,0,1,1);const[o,n,a]=e.getImageData(0,0,1,1).data;return[o/255,n/255,a/255]}export function getRandomFunkyName(){const t=t=>t[Math.floor(Math.random()*t.length)];return`${t(["Funky","Groovy","Zany","Wacky","Spicy","Nifty","Bouncy","Chill","Snazzy","Sassy","Loopy","Trippy","Nerdy","Cranky","Fluffy","Quirky"])}${t(["Banana","Tofu","Octopus","Falcon","Pineapple","Robot","Llama","Pizza","Koala","Unicorn","Muffin","Cactus","Taco","Yeti","Squirrel","Donut"])}`}const s=256,l=new Array(2*s);export function generateRealisticY(t,e=.1,o=1){const n=function(t){const e=Math.floor(t),o=t-e,n=l[e&s-1],a=l[e+1&s-1],r=.5*(1-Math.cos(o*Math.PI));return n*(1-r)+a*r}(t*e),a=.5+(n-.5)*o;return Math.max(0,Math.min(1,a))}(()=>{for(let t=0;t<s;t++)l[t]=l[t+s]=Math.random()})();
package/demo/Test.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { TimeSliderElement } from "../data/TimeSliderElement";
2
+ import { TimeSliderModel } from "../data/TimeSliderModel";
3
+ import { TimeSliderHistogramLayerOld } from "../layer/TimeSliderHistogramLayerOld";
4
+ export declare const testHistogramLayer: TimeSliderHistogramLayerOld<TimeSliderModel<TimeSliderElement>>;
5
+ export declare const TEST_LAYERS: TimeSliderHistogramLayerOld<TimeSliderModel<TimeSliderElement>>[];
package/demo/Test.js ADDED
@@ -0,0 +1 @@
1
+ import{v4 as t}from"uuid";import{TimeSliderPointsModel as e}from"../data/TimeSliderPointsModel";import{MAGNITUDE_COLORS as r}from"../style/TimeSliderColors";import{ONE_YEAR as i}from"../ticks/TimeSliderConstants";import{TimeSliderHistogramLayerOld as o}from"../layer/TimeSliderHistogramLayerOld";const s=function(){const r=(s=42,()=>{let t=s+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}),o=new e;var s;o.name="Test";for(let e=0;e<1e4;e++){const e={id:t(),t:Date.now()-r()*i,v:100*r(),attributes:{test:r(),ok:r()}};o.add(e)}return o}(),a=Array.from({length:10},(t,e)=>e.toString()),n=Array.from({length:20},(t,e)=>e.toString());export const testHistogramLayer=function(t){const e=t=>l(10*t.attributes.test,a)+"",i=t=>l(t.v/10,a)+"",s=new o(t,{name:"Histogram",min:0,max:1,style:{loggin:!0,fill:{color:"#fff",opacity:.3},border:{color:"#fff",width:4,centered:!1},inverted:!1,mode:{fixedUnit:"month"},classOrder:n},classifier:e,styler:t=>{const e=r[parseInt(t.attributes?.classification||"0")];return{fill:{color:e},border:{color:e}}},labeler:t=>`Test #${parseInt(t.attributes?.classification||"0")}`,yAxis:{visible:!0,style:{labels:{position:"left"}}}});let m=!0,d=!1,c=!1;document.addEventListener("keypress",t=>{"t"===t.key&&(m=!1,s.histogram.classifier=i),"g"===t.key&&(m=!0,s.histogram.classifier=e)}),document.addEventListener("keydown",t=>{"y"===t.key&&(c=!0),"h"===t.key&&(d=!0)}),document.addEventListener("keyup",t=>{"y"===t.key&&(c=!1),"h"===t.key&&(d=!1)});let f=0;return setInterval(()=>{(c||d)&&(s.histogram.classifier=m?t=>l(10*t.attributes.test,a)+(t.attributes.ok<f?10:0)+"":t=>l(t.v/10,a)+(t.attributes.ok<f?10:0)+"");let t=0;c&&(t+=.05),d&&(t-=.05),f=Math.max(0,Math.min(1,f+t))},50),s}(s);export const TEST_LAYERS=[testHistogramLayer];function l(t,e){return Math.min(e.length-1,Math.max(0,Math.round(t)))}
package/demo/Wars.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const WARS_SINGLE_LAYERS: never[];
2
+ export declare const WARS_MULTI_LAYERS: never[][];
package/demo/Wars.js ADDED
@@ -0,0 +1 @@
1
+ import{v4 as o}from"uuid";import{getTimeUnitRange as m}from"../common/TimeTools";import{TimeSliderLanesModel as r}from"../data/TimeSliderLanesModel";export const WARS_SINGLE_LAYERS=[];export const WARS_MULTI_LAYERS=[[],[]];
@@ -0,0 +1,3 @@
1
+ export declare function addHorizontalPinchZoom(element: HTMLElement, callback: (scaleFactor: number, xRatio: number) => void): {
2
+ destroy: () => void;
3
+ };
@@ -0,0 +1 @@
1
+ export function addHorizontalPinchZoom(e,t){let n=0;const o=t=>{2===t.touches.length&&(t=>{t.preventDefault();const o=t.touches[0].clientX,c=t.touches[1].clientX,s=e.getBoundingClientRect();s.left,s.width,n=Math.abs(o-c)})(t)},c=o=>{if(2===o.touches.length&&n>0){o.preventDefault();const c=o.touches[0].clientX,s=o.touches[1].clientX,i=Math.abs(c-s),h=i/n-1,r=.5*(c+s),u=e.getBoundingClientRect(),a=(r-u.left)/u.width;t(-h,a),n=i}},s=()=>{n=0};return e.addEventListener("touchstart",o,{passive:!1}),e.addEventListener("touchmove",c,{passive:!1}),e.addEventListener("touchend",s),e.addEventListener("touchcancel",s),{destroy:()=>{e.removeEventListener("touchstart",o),e.removeEventListener("touchmove",c),e.removeEventListener("touchend",s),e.removeEventListener("touchcancel",s)}}}
@@ -0,0 +1,17 @@
1
+ export interface Transform {
2
+ scale: number;
3
+ x: number;
4
+ y: number;
5
+ }
6
+ type ZoomCallback = (transform: Transform) => void;
7
+ /**
8
+ * Attaches pinch-to-zoom and pan listeners to an HTML element.
9
+ *
10
+ * @param element The HTML element to attach the listeners to.
11
+ * @param callback The function to call with updated transform data during a gesture.
12
+ * @returns An object with a `destroy` method to remove the event listeners.
13
+ */
14
+ export declare function addPinchZoom(element: HTMLElement, callback: ZoomCallback): {
15
+ destroy: () => void;
16
+ };
17
+ export {};
@@ -0,0 +1 @@
1
+ const e=(e,t)=>Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)),t=(e,t)=>({x:(e.x+t.x)/2,y:(e.y+t.y)/2});export function addPinchZoom(c,n){let o=0,s={x:0,y:0},h={scale:1,x:0,y:0},i={scale:1,x:0,y:0};const u=c=>{if(2===c.touches.length){c.preventDefault();const n={x:c.touches[0].clientX,y:c.touches[0].clientY},u={x:c.touches[1].clientX,y:c.touches[1].clientY};o=e(n,u),s=t(n,u),h={...i}}},r=c=>{if(2===c.touches.length&&o>0){c.preventDefault();const u={x:c.touches[0].clientX,y:c.touches[0].clientY},r={x:c.touches[1].clientX,y:c.touches[1].clientY},a=e(u,r)/o,l=h.scale*a,v=t(u,r),x=h.x+(v.x-s.x),y=h.y+(v.y-s.y);i={scale:l,x:x,y:y},n(i)}},a=()=>{o=0};return c.addEventListener("touchstart",u,{passive:!1}),c.addEventListener("touchmove",r,{passive:!1}),c.addEventListener("touchend",a),c.addEventListener("touchcancel",a),{destroy:()=>{c.removeEventListener("touchstart",u),c.removeEventListener("touchmove",r),c.removeEventListener("touchend",a),c.removeEventListener("touchcancel",a)}}}
@@ -0,0 +1,225 @@
1
+ import { TimeSliderElement } from "../data/TimeSliderElement";
2
+ import { TimeSliderRange, TimeSliderTimeRange, TimeSliderTimeRangeWithDuration, TimeSliderValueRange } from "../data/TimeSliderRange";
3
+ import { TypedEventEmitter } from "../event/TypedEventEmitter";
4
+ import { TimeSliderLayer } from "../layer/TimeSliderLayer";
5
+ import { TimeSliderLayerLoader } from "../layer/TimeSliderLayerLoader";
6
+ import { TimeTicksBar } from "../ticks/TimeTicksBar";
7
+ import { TimeSliderEngine } from "./TimeSliderEngine";
8
+ export type TimeSliderHoverOptions = {
9
+ time?: boolean;
10
+ date?: boolean;
11
+ };
12
+ export type TimeSliderSelectionOptions = {
13
+ highlight?: boolean;
14
+ label?: boolean;
15
+ };
16
+ export type TimeSliderSelection = {
17
+ layer: TimeSliderLayer;
18
+ elements: TimeSliderElement[];
19
+ };
20
+ export type TimeSliderSelectRangeMode = 'zoom' | 'select';
21
+ export interface TimeSliderOptions {
22
+ showCurrent?: boolean;
23
+ showTicks?: boolean;
24
+ theme?: 'dark' | 'light';
25
+ selectRangeMode?: TimeSliderSelectRangeMode;
26
+ liveRange?: number;
27
+ playSpeed?: number | 'auto';
28
+ hover?: TimeSliderHoverOptions;
29
+ selection?: TimeSliderSelectionOptions;
30
+ }
31
+ export declare class TimeSlider extends TypedEventEmitter<{
32
+ live: boolean;
33
+ playing: boolean;
34
+ current: number;
35
+ size: {
36
+ width: number;
37
+ height: number;
38
+ };
39
+ time: TimeSliderTimeRangeWithDuration;
40
+ value: TimeSliderValueRange;
41
+ select: TimeSliderSelection[];
42
+ valueRanges: string;
43
+ }> {
44
+ valueRanges: Map<string, {
45
+ min: number;
46
+ max: number;
47
+ }>;
48
+ private layers;
49
+ private onDestroy;
50
+ ticksBar: TimeTicksBar;
51
+ private loaders;
52
+ private layerUnloaders;
53
+ pressedKeys: Set<string>;
54
+ protected container: HTMLElement | null;
55
+ theme: 'dark' | 'light';
56
+ private d;
57
+ id: string;
58
+ private playing;
59
+ live: boolean;
60
+ liveRange: number;
61
+ private _showCurrent;
62
+ showTicks: boolean;
63
+ playSpeed: number | 'auto';
64
+ current: number;
65
+ range: {
66
+ time: TimeSliderTimeRange;
67
+ value: TimeSliderValueRange;
68
+ };
69
+ size: {
70
+ width: number;
71
+ height: number;
72
+ };
73
+ private sliderElement;
74
+ private yAxisTicks;
75
+ private hoverLine;
76
+ private toolTip;
77
+ private selectedLabel;
78
+ private selectingRangeElement;
79
+ private stopUpdatingLabel?;
80
+ hoverOptions: TimeSliderHoverOptions;
81
+ selectionOptions: TimeSliderSelectionOptions;
82
+ private stopControls?;
83
+ selectRangeMode: TimeSliderSelectRangeMode;
84
+ selectingRange: boolean;
85
+ selectingRangeVisible: boolean;
86
+ whenDoneSelectingRange?: () => void;
87
+ getLayers(): TimeSliderLayer<TimeSliderElement, import("../style/TimeSliderStyle").TimeSliderStyle>[];
88
+ getVisibleLayers(): TimeSliderLayer<TimeSliderElement, import("../style/TimeSliderStyle").TimeSliderStyle>[];
89
+ constructor(options?: TimeSliderOptions);
90
+ startSelectingRange(whenDone: () => void): void;
91
+ stopSelectingRange(): void;
92
+ updateValueRangesQueue: Map<string, {
93
+ lastUpdate: number;
94
+ pending: NodeJS.Timeout | undefined;
95
+ }>;
96
+ syncMaxValues(): () => void;
97
+ syncMaxValuesForLayer(layer: TimeSliderLayer): () => void;
98
+ updateAllValueRanges(): void;
99
+ updateValueRanges(group: string, willRender?: boolean): void;
100
+ renderYAxis(): void;
101
+ setTheme(theme: 'dark' | 'light'): void;
102
+ addLayerLoader(loader: TimeSliderLayerLoader<any>): void;
103
+ showingStats: boolean;
104
+ showStats(showingStats: boolean): void;
105
+ protected engine?: TimeSliderEngine<any>;
106
+ setEngine(engine: TimeSliderEngine<any>): Promise<void>;
107
+ initSliderContainer(): void;
108
+ get showCurrent(): boolean;
109
+ set showCurrent(newShowCurrent: boolean);
110
+ init(container: string | HTMLElement, initial?: Partial<TimeSliderRange>): Promise<void>;
111
+ initSelectLabel(): void;
112
+ private mouse;
113
+ private updatingLabel;
114
+ private selectedLayerId?;
115
+ getLabel(element: TimeSliderElement, layer: TimeSliderLayer, t: number, v: number): string | null;
116
+ getLayerById(id: string): TimeSliderLayer<TimeSliderElement, import("../style/TimeSliderStyle").TimeSliderStyle> | undefined;
117
+ select(mouse: {
118
+ x: number;
119
+ y: number;
120
+ } | null, range?: TimeSliderTimeRange): void;
121
+ listenToClicks(): () => void;
122
+ getSliderBounds(): {
123
+ top: number;
124
+ left: number;
125
+ width: number;
126
+ height: number;
127
+ };
128
+ mouseInSlider(mouse: {
129
+ x: number;
130
+ y: number;
131
+ } | {
132
+ clientX: number;
133
+ clientY: number;
134
+ }): {
135
+ absolute: {
136
+ x: number;
137
+ y: number;
138
+ };
139
+ normalized: {
140
+ x: number;
141
+ y: number;
142
+ };
143
+ t: number;
144
+ v: number;
145
+ };
146
+ private pixelsToLayerValue;
147
+ private pixelsToModelValue;
148
+ private layerValueToPixels;
149
+ private modelValueToPixels;
150
+ findElements(mouse: {
151
+ x: number;
152
+ y: number;
153
+ }, pickSize?: number): {
154
+ layer: TimeSliderLayer<TimeSliderElement, import("../style/TimeSliderStyle").TimeSliderStyle>;
155
+ elements: TimeSliderElement[];
156
+ t: number;
157
+ v: number;
158
+ }[];
159
+ updateHover(mouse?: {
160
+ x: number;
161
+ y: number;
162
+ } | null): void;
163
+ initHoverTooltip(): void;
164
+ initHoverListener(): () => void;
165
+ private syncSize;
166
+ getTimeRange(): TimeSliderTimeRangeWithDuration;
167
+ getValueRange(): TimeSliderValueRange;
168
+ setTimeRange(newRange: Partial<TimeSliderTimeRange>, label?: string): void;
169
+ setValueRange(newRange: Partial<TimeSliderValueRange>): void;
170
+ setSize(width: number, height: number): void;
171
+ up(options?: {
172
+ animate?: number;
173
+ }): void;
174
+ down(options?: {
175
+ xRatio?: number;
176
+ animate?: number;
177
+ }): void;
178
+ next(options?: {
179
+ animate?: number;
180
+ }): void;
181
+ previous(options?: {
182
+ animate?: number;
183
+ }): void;
184
+ skip(amount: number, options?: {
185
+ animate?: number;
186
+ }): void;
187
+ getTimeRangeLabel(): string | undefined;
188
+ private stopFit?;
189
+ private cancelFit;
190
+ fit(options?: {
191
+ animate?: number;
192
+ range?: Omit<TimeSliderTimeRange, 'duration'>;
193
+ padding?: number;
194
+ }): void;
195
+ getLayersTimeRange(): {
196
+ startTime: number;
197
+ endTime: number;
198
+ duration: number;
199
+ };
200
+ private loadLayer;
201
+ private unloadLayer;
202
+ addLayer(layer: TimeSliderLayer): void;
203
+ removeLayer(layer: string | {
204
+ id: string;
205
+ }): void;
206
+ destroy(): void;
207
+ dragging: boolean;
208
+ pinching: boolean;
209
+ addHorizontalPinchZoom(): void;
210
+ private initControls;
211
+ shift(offsetRatio: number, options?: {
212
+ animate?: number;
213
+ absolute?: boolean;
214
+ }): void;
215
+ zoom(scaleFactor: number, options?: {
216
+ x?: number;
217
+ animate?: number;
218
+ }): void;
219
+ togglePlaying(): void;
220
+ isPlaying(): boolean;
221
+ play(): void;
222
+ setCurrent(newCurrent: number): void;
223
+ pause(): void;
224
+ setLive(live: boolean): void;
225
+ }
@@ -0,0 +1 @@
1
+ import{v4 as e}from"uuid";import{Disposables as t}from"../common/Disposables";import{animateRangeTransition as i}from"../common/Easing";import{formatDuration as s,getLargeTimeUnitRange as n,getMatchingTimeUnit as l,getTimeUnitRange as a,MONTH_NAMES as o}from"../common/TimeTools";import{TimeSliderDynamicHistogram as h}from"../data/histogram/TimeSliderDynamicHistogram";import{TimeSliderIntervalsModel as r}from"../data/TimeSliderIntervalsModel";import{addDuration as d,addPadding as m,applyTimeRangeUpdate as g,timeRangesOverlap as u,timeRangesUnion as c}from"../data/TimeSliderRange";import{TypedEventEmitter as p}from"../event/TypedEventEmitter";import{TimeSliderHistogramLayer as y}from"../layer/TimeSliderHistogramLayer";import{TimeSliderIntervalsLayer as T}from"../layer/TimeSliderIntervalsLayer";import{CENTURY as v,DECADE as f,MILLENIUM as E,ONE_DAY as L,ONE_HOUR as x,ONE_MINUTE as R,ONE_MONTH as b,ONE_SECOND as w,ONE_WEEK as V,ONE_YEAR as S,TODAY as D}from"../ticks/TimeSliderConstants";import{TimeTicksBar as M}from"../ticks/TimeTicksBar";import{YAxisTicks as k}from"../ticks/YAxisTicks";const $=w,z=10*E;export class TimeSlider extends p{getLayers(){return[...this.layers]}getVisibleLayers(){return this.getLayers().filter(e=>e.visible)}constructor(i){super(),this.valueRanges=new Map,this.layers=[],this.onDestroy=[],this.ticksBar=new M,this.loaders=new Set,this.layerUnloaders=new Map,this.pressedKeys=new Set,this.container=null,this.d=new t,this.id=e(),this.playing=!1,this.live=!1,this._showCurrent=!1,this.current=Date.now(),this.range={time:D,value:{minValue:0,maxValue:100}},this.size={width:100,height:100},this.sliderElement=document.createElement("div"),this.yAxisTicks=new k,this.hoverLine=document.createElement("div"),this.toolTip=document.createElement("div"),this.selectedLabel=document.createElement("div"),this.selectingRangeElement=document.createElement("div"),this.selectingRange=!1,this.selectingRangeVisible=!1,this.updateValueRangesQueue=new Map,this.showingStats=!1,this.mouse=null,this.updatingLabel=!1,this.dragging=!1,this.pinching=!1,this.hoverOptions=i?.hover||{},this.selectionOptions={highlight:"boolean"!=typeof i?.selection?.highlight||i.selection.highlight,label:"boolean"!=typeof i?.selection?.label||i.selection.label},this.showCurrent=i?.showCurrent||!1,this.showTicks=i?.showTicks||!1,this.selectRangeMode=i?.selectRangeMode||"select",this.playSpeed=i?.playSpeed||"auto",this.liveRange=i?.liveRange||10*w,this.theme=i?.theme||"dark",this.syncMaxValues()}startSelectingRange(e){this.selectingRange=!0,this.whenDoneSelectingRange=e}stopSelectingRange(){this.selectingRange=!1,this.whenDoneSelectingRange?.(),this.whenDoneSelectingRange=void 0,this.selectingRangeVisible&&(this.container.removeChild(this.selectingRangeElement),this.selectingRangeVisible=!1)}syncMaxValues(){return this.updateAllValueRanges(),this.on("time",()=>this.updateAllValueRanges())}syncMaxValuesForLayer(e){return this.updateValueRanges(e.yAxisGroup),e.model.on(()=>this.updateValueRanges(e.yAxisGroup))}updateAllValueRanges(){this.layers.filter(e=>e.visible).forEach(e=>{this.updateValueRanges(e.yAxisGroup,!0)}),this.renderYAxis()}updateValueRanges(e,t){this.updateValueRangesQueue.has(e)||this.updateValueRangesQueue.set(e,{lastUpdate:0,pending:void 0});const i=this.updateValueRangesQueue.get(e);if(Date.now()-i.lastUpdate<100)return i.pending&&clearTimeout(i.pending),void(i.pending=setTimeout(()=>{i.pending=void 0,this.updateValueRanges(e)},200));i.lastUpdate=Date.now();const s=new Map,n=new Map;this.layers.filter(e=>e.visible).forEach(e=>{const t=e.yAxis.group||e.id;s.has(t)||(s.set(t,-Number.MAX_VALUE),n.set(t,Number.MAX_VALUE));const i=e.model.getValueRange(this.getTimeRange());i.minValue<n.get(t)&&n.set(t,i.minValue),i.maxValue>s.get(t)&&s.set(t,i.maxValue)}),this.valueRanges.clear(),s.forEach((e,t)=>{this.valueRanges.set(t,{max:e,min:n.get(t)})}),t||this.renderYAxis(),this.emit("valueRanges",e)}renderYAxis(){const e=new Map;this.layers.filter(e=>e.visible).forEach(t=>{const i=t.yAxis.group||t.id;e.has(i)||e.set(i,{min:t.min,max:t.max,group:i}),e.set(i,{...e.get(i),...t.yAxis,min:t.min,max:t.max})});const t=[];e.forEach(e=>{if(e.visible){const i=this.valueRanges.get(e.group);i&&t.push({...e,minValue:i.min,maxValue:i.max})}}),this.yAxisTicks.render(t)}setTheme(e){this.theme=e,this.ticksBar.setDarkMode("dark"===e),this.engine?.setTheme(e)}addLayerLoader(e){this.loaders.add(e)}showStats(e){this.showingStats=e,this.engine?.showStats(e)}async setEngine(e){this.engine&&(this.layerUnloaders.forEach(e=>e()),this.layerUnloaders.clear(),this.engine.dispose()),this.initSliderContainer(),this.engine=e,this.engine.setTheme(this.theme),await this.engine.init(this.sliderElement),this.engine.setTheme(this.theme),this.getVisibleLayers().forEach(e=>this.loadLayer(e)),this.engine.showStats(this.showingStats),this.engine.setTimeRange(this.getTimeRange()),this.engine.setValueRange(this.getValueRange()),this.engine.setSize(this.size.width,this.size.height)}initSliderContainer(){this.stopControls&&this.stopControls(),this.container?.removeChild(this.sliderElement);let e=0;this.showTicks&&(e+=24),this.showCurrent&&(e+=4),this.sliderElement=document.createElement("div"),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top="0px",this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${0+e}px)`,this.container?.appendChild(this.sliderElement),this.initSelectLabel(),this.stopControls=this.initControls(),this.onDestroy.push(()=>{this.container?.removeChild(this.sliderElement)})}get showCurrent(){return this._showCurrent}set showCurrent(e){if(e!==this._showCurrent){this._showCurrent=e,this.ticksBar.showLine=!this.showCurrent;let t=0,i=0;this.showTicks&&(i+=24),this.showCurrent&&(i+=4),this.sliderElement.style.height=`calc(100% - ${t+i}px)`}}async init(e,t){const i="string"==typeof e?document.getElementById(e):e;if(this.container=i,i){i.oncontextmenu=()=>!1;let e=0,s=0;if(this.showTicks){s+=24;const e=document.createElement("div");e.style.width="100%",e.style.height="24px",e.style.position="absolute",e.style.bottom="0px",e.style.touchAction="none",i.appendChild(e),this.ticksBar.init(e,e=>this.fit({range:e,animate:1e3})),this.ticksBar.showLine=!this.showCurrent}this.showCurrent&&(s+=4),this.sliderElement.oncontextmenu=()=>!1,this.sliderElement.tabIndex=0,this.sliderElement.style.top=`${e}px`,this.sliderElement.style.width="100%",this.sliderElement.style.outline="none",this.sliderElement.style.touchAction="none",this.sliderElement.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.sliderElement),this.yAxisTicks.canvas.style.top=`${e}px`,this.yAxisTicks.canvas.style.height=`calc(100% - ${e+s}px)`,i.appendChild(this.yAxisTicks.canvas),this.initHoverTooltip(),this.initSelectLabel(),this.setSize(this.sliderElement.clientWidth,this.sliderElement.clientHeight),this.syncSize(),this.setTimeRange(C(t)),this.setValueRange(C(t))}else console.warn(`Element ${e} not found`)}initSelectLabel(){this.selectedLabel.style.position="absolute",this.selectedLabel.style.padding="4px 8px",this.selectedLabel.style.background="rgba(0, 0, 0, 0.75)",this.selectedLabel.style.color="white",this.selectedLabel.style.fontSize="12px",this.selectedLabel.style.maxWidth="200px",this.selectedLabel.style.fontFamily="monospace",this.selectedLabel.style.borderRadius="4px",this.selectedLabel.style.pointerEvents="none",this.selectedLabel.style.display="none",this.selectedLabel.style.zIndex="10",this.sliderElement.appendChild(this.selectedLabel)}getLabel(e,t,i,s){if(t.labeler){const n=t.labeler(e,i,s);return null===n?null:"string"==typeof n?`<div>${n}</div>`:n?n.outerHTML:`<div>${e.name||e.id}</div>`}return`<div>${e.name||e.id}</div>`}getLayerById(e){return this.layers.find(t=>t.id===e)}select(e,t){this.stopSelectingRange(),this.stopUpdatingLabel?.();const i=()=>{this.updatingLabel=!1,this.stopUpdatingLabel?.(),this.stopUpdatingLabel=void 0,this.selectedLabel.style.display="none",this.layers.forEach(e=>e.select([])),this.selectedLayerId=void 0,this.emit("select",[])},s=e=>{this.layers.filter(t=>!e.some(e=>t.id===e.layer.id)).forEach(e=>e.select([])),e.forEach(e=>{e.layer.select(e.elements)}),this.emit("select",e)};if(t){s(this.getVisibleLayers().map(e=>{const i=e.model.dataInTimeRange(t);return{layer:e,elements:i}}).filter(e=>e.elements.length>0))}else if(e){const t=this.findElements(e,24);if(s(t.map(e=>({layer:e.layer,elements:e.elements})).flat()),1===t.length&&t[0].elements.length>0&&this.selectionOptions.label){const e=t[0].elements[0],s=t[0].layer;this.selectedLabel.innerHTML=this.getLabel(e,s,t[0].t,t[0].v)||"",this.selectedLabel.style.display="block";const n=this.selectedLabel.offsetWidth,l=this.selectedLabel.offsetHeight;this.selectedLayerId=s.id;const a=Array.isArray(e.t);this.updatingLabel=!0;const o=()=>{if(!this.updatingLabel)return;const{startTime:i,duration:s,endTime:o}=this.getTimeRange(),h=t[0].layer.model.get(e.id);if(h){const e=u(this.getTimeRange(),h.t);if(e){const o=this.getSliderBounds();let r=(.5*(e.startTime+e.endTime)-i)/s*o.width;const d="number"==typeof h.v?h.v:.5*(h.v[1]+h.v[0]);let m=this.modelValueToPixels(d,t[0].layer);a?m-=.5*l:m+=8;const g=.5*n,u=.5*l,c=o.width-.5*n,p=o.height-.5*l,y=Math.min(c,Math.max(g,r)),T=Math.min(p,Math.max(u,m));this.selectedLabel.style.display="block",this.selectedLabel.style.left=y-.5*n+"px",this.selectedLabel.style.top=`${T}px`}else this.selectedLabel.style.display="none"}else this.selectedLabel.style.display="none"};o();const r=s instanceof y&&s.histogram instanceof h;this.stopUpdatingLabel=this.on("time",r?i:o)}}else i()}listenToClicks(){let e=null;const t=t=>{e={x:t.clientX,y:t.clientY}},i=t=>{if(!e)return;const i=t.clientX-e.x,s=t.clientY-e.y;i*i+s*s<=25&&(this.stopSelectingRange(),this.select(e)),e=null},s=()=>{e=null};return this.sliderElement.addEventListener("pointerdown",t),this.sliderElement.addEventListener("pointerup",i),this.sliderElement.addEventListener("pointercancel",s),()=>{this.sliderElement.removeEventListener("pointerdown",t),this.sliderElement.removeEventListener("pointerup",i),this.sliderElement.removeEventListener("pointercancel",s)}}getSliderBounds(){return this.sliderElement.getBoundingClientRect()}mouseInSlider(e){const t=this.getSliderBounds(),i="x"in e?e:{x:e.clientX,y:e.clientY},s={x:i.x-t.left,y:i.y-t.top},n={x:s.x/t.width,y:-s.y/t.height+1},{startTime:l,duration:a}=this.getTimeRange(),o=l+n.x*a,{minValue:h,maxValue:r}=this.getValueRange();return{absolute:s,normalized:n,t:o,v:h+n.x*(r-h)}}pixelsToLayerValue(e,t){if(!e)return{yInLayer:0,toLayerHeight:1};const i="normalized"in e?e.normalized:this.mouseInSlider(e).normalized;let s=t.min;const n=t.max-s;return{yInLayer:(i.y-s)/n,toLayerHeight:n/this.getSliderBounds().height}}pixelsToModelValue(e,t){const{yInLayer:i,toLayerHeight:s}=this.pixelsToLayerValue(e,t);let n=0,l=100;if(t.model instanceof r){const e=this.valueRanges.get(t.yAxisGroup)||{min:0,max:1e3};n=e.min,l=e.max-n}return{yInModel:n+i*l,toModelHeight:s*l}}layerValueToPixels(e,t){let i=t.min;return(1-(i+(t.max-i)*e))*this.getSliderBounds().height}modelValueToPixels(e,t){let i=0,s=100;if(t.model instanceof r){const e=t.model.getValueRange(this.getTimeRange());i=e.minValue,s=e.maxValue-i}const n=(e-i)/s;return this.layerValueToPixels(n,t)}findElements(e,t){const{width:i,height:s}=this.getSliderBounds(),{normalized:n}=this.mouseInSlider(e),{startTime:l,endTime:a,duration:o}=this.getTimeRange(),h=l+n.x*o,r=t||12,d=r/i*o,m={startTime:h-1,endTime:h+1},g={startTime:h-.5*d,endTime:h+.5*d};return this.getVisibleLayers().map(e=>{const{yInModel:t,toModelHeight:i}=this.pixelsToModelValue({normalized:n},e),s=e instanceof T?0:r*i,l=e instanceof T?m:g,a={minValue:t-.5*s,maxValue:t+.5*s},o=e.model.dataInRange({...l,...a});return{layer:e,elements:o,t:h,v:t}}).filter(e=>e.elements.length>0)}updateHover(e){if(this.dragging)return this.hoverLine.style.display="none",void(this.toolTip.style.display="none");if(void 0!==e&&(this.mouse=e),this.mouse){const e=this.getSliderBounds(),{normalized:t}=this.mouseInSlider(this.mouse),{startTime:i,endTime:s,duration:n}=this.getTimeRange(),l=i+t.x*n,a=this.findElements(this.mouse),h=a.map(e=>e.elements.map(t=>({e:t,l:e.layer,t:e.t,v:e.v}))).flat();let r;if(h.length>0)if(h.length>3){const e=h.slice(0,2).map(e=>this.getLabel(e.e,e.l,e.t,e.v));r=e.flat().filter(e=>null!==e).join(""),r+=`<div>And ${h.length-2} more...</div>`}else{const e=a.map(e=>e.elements.map(t=>this.getLabel(t,e.layer,e.t,e.v)));r=e.flat().filter(e=>null!==e).join("")}const d=new Date(l),m=d.getDate(),g=d.getMonth(),u=d.getFullYear(),c=d.getHours(),p=d.getMinutes(),y=d.getSeconds(),T=`${(m<10?"0":"")+m} ${o[g]} ${u}`,v=`${(c<10?"0":"")+c}:${(p<10?"0":"")+p}:${(y<10?"0":"")+y}`;let f="";const E=this.ticksBar.cache.high.spacing;(void 0===this.hoverOptions.date?E>=x:this.hoverOptions.date)&&(f+=`<div>${T}</div>`),(void 0===this.hoverOptions.time?E<=L:this.hoverOptions.time)&&(f+=`<div>${v}</div>`),r&&(f+=r),this.toolTip.innerHTML=f,this.toolTip.style.display=f.length>0?"block":"none";const R=88,b=36;let w=this.mouse.x+10,V=this.mouse.y+10;const S=e.left+e.width-R-5,D=e.top+e.height-b-5;w>S&&(w=S),V>D&&(V=D),this.toolTip.style.left=`${w}px`,this.toolTip.style.top=`${V}px`}else this.hoverLine.style.display="none",this.toolTip.style.display="none"}initHoverTooltip(){this.toolTip.style.position="absolute",this.toolTip.style.padding="4px 8px",this.toolTip.style.background="rgba(0, 0, 0, 0.75)",this.toolTip.style.color="white",this.toolTip.style.fontSize="12px",this.toolTip.style.fontFamily="monospace",this.toolTip.style.borderRadius="4px",this.toolTip.style.pointerEvents="none",this.toolTip.style.display="none",this.toolTip.style.zIndex="10",this.toolTip.style.overflow="hidden",document.body.appendChild(this.toolTip)}initHoverListener(){const e=()=>{this.updateHover(null)},t=e=>{this.updateHover({x:e.clientX,y:e.clientY})};this.sliderElement.addEventListener("mouseleave",e),this.sliderElement.addEventListener("mousemove",t);const i=this.listenToClicks();return()=>{this.sliderElement.removeEventListener("mouseleave",e),this.sliderElement.removeEventListener("mousemove",t),i()}}syncSize(){const e=()=>{const{offsetWidth:e,offsetHeight:t}=this.sliderElement;this.setSize(e,t)},t=new ResizeObserver(()=>{e()});this.container&&(t.observe(this.container),e()),this.onDestroy.push(()=>{t.disconnect()})}getTimeRange(){return d(this.range.time)}getValueRange(){return this.range.value}setTimeRange(e,t){const i=this.getTimeRange(),s=g(i,e);s.startTime===i.startTime&&s.endTime===i.endTime||(this.range.time=s,this.engine?.setTimeRange(s),this.showTicks&&this.ticksBar.setTimeRange(s),this.emit("time",s),this.updateHover())}setValueRange(e){const t={...this.getValueRange(),...e};this.range.value=t,this.engine?.setValueRange(t),this.emit("value",this.getValueRange()),this.updateHover()}setSize(e,t){this.size={width:e,height:t},this.showTicks&&this.ticksBar.setWidth(e);const i=this.getTimeRange(),s=this.getValueRange();this.engine?.setSize(e,t),this.setTimeRange(i),this.setValueRange(s),this.updateHover(),this.emit("size",{width:e,height:t})}up(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let l={startTime:0,endTime:Date.now()};const o=.5*(t+i);if(s>=.9*E){const e=A(10*s);l=n(o,e)}else{const e=[{threshold:v,unit:"millennium"},{threshold:f,unit:"century"},{threshold:S,unit:"decade"},{threshold:.9*b,unit:"year"},{threshold:V,unit:"month"},{threshold:L,unit:"week"},{threshold:x,unit:"day"},{threshold:R,unit:"hour"},{threshold:w,unit:"minute"},{threshold:-1,unit:"second"}];let t=0;for(;s<.9*e[t].threshold;)t++;const i=e[t].unit;l=a(o,i)}this.fit({...e,range:l})}down(e){const{startTime:t,endTime:i,duration:s}=this.getTimeRange();let l={startTime:0,endTime:Date.now()};const o=t+("number"==typeof e?.xRatio?e.xRatio:.5)*s;if(s>=.9*E){const e=A(s/10);l=n(o,e)}else{let e=0;const t=[{threshold:E,unit:"century"},{threshold:v,unit:"decade"},{threshold:f,unit:"year"},{threshold:S,unit:"month"},{threshold:1.1*b,unit:"week"},{threshold:V,unit:"day"},{threshold:L,unit:"hour"},{threshold:x,unit:"minute"},{threshold:R,unit:"second"}].reverse();for(;s>1.1*t[e].threshold;)e++;const i=t[e].unit;l=a(o,i)}this.fit({...e,range:l})}next(e){this.skip(1,e)}previous(e){this.skip(-1,e)}skip(e,t){let i={startTime:0,endTime:Date.now()};const{startTime:s,endTime:o,duration:h}=this.getTimeRange(),r=.5*(s+o);if(h>=9*E){const e=A(h);i=n(r,e)}else{const t=l(s,o);i=t?a(r,t,Math.round(e)):{startTime:s+e*h,endTime:o+e*h}}this.fit({...t,range:i})}getTimeRangeLabel(){const{startTime:e,endTime:t}=this.getTimeRange(),i=new Date(e),s=new Date(t);if(0===i.getHours()&&0===i.getHours()&&0===i.getMinutes()&&0===i.getMinutes()&&0===i.getSeconds()&&0===i.getSeconds()&&0===i.getMilliseconds()&&0===i.getMilliseconds()){const e=new Date(t-1),n=i.toLocaleString("default",{month:"short"}),l=e.toLocaleString("default",{month:"short"});return i.getFullYear()===e.getFullYear()?i.getMonth()===e.getMonth()?i.getDate()===e.getDate()?`${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()?`${l} ${e.getFullYear()}`:`${i.getDate()} - ${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()&&0===i.getMonth()&&0===s.getMonth()?`${e.getFullYear()}`:`${i.getDate()} ${n} - ${e.getDate()} ${l} ${e.getFullYear()}`:1===i.getDate()&&1===s.getDate()&&0===i.getMonth()&&0===s.getMonth()?` ${i.getFullYear()} - ${e.getFullYear()}`:`${i.getDate()} ${n} ${i.getFullYear()} - ${e.getDate()} ${l} ${e.getFullYear()}`}}cancelFit(){this.stopFit?.(),this.stopFit=void 0}fit(e){this.cancelFit();const t=e?.range||this.getLayersTimeRange(),s=e?.padding?m(t,e.padding):t;if(e?.animate){const t=this.getTimeRange();this.stopFit=i(t.startTime,t.endTime,s.startTime,s.endTime,e.animate,(e,t)=>this.setTimeRange({startTime:e,endTime:t}))}else this.setTimeRange(s)}getLayersTimeRange(){if(0===this.getVisibleLayers().length)return D;{let e=this.getVisibleLayers()[0].model.getTimeRange();return this.getVisibleLayers().slice(1).forEach(t=>e=c(e,t.model.getTimeRange())),e}}loadLayer(e){if(e.timeSlider&&e.timeSlider.id!==this.id)console.warn("Layer already has been loaded by another time slider, create a new layer with the same model and style if you want to add it to another time slider");else if(this.engine&&!this.layerUnloaders.has(e.id)){const t=[...this.loaders].filter(e=>this.engine instanceof e.engineClass).find(t=>t.canLoad(e));if(t){const i=Date.now(),n=t.load(e,this.engine.scene,this.engine,this);e.timeSlider=this,e.loaded=!0;const l=e.name||e.constructor.name+"#"+e.id.slice(e.id.length-4).toUpperCase();console.log(`Loaded ${l} in ${s(Date.now()-i)}`);const a=this.syncMaxValuesForLayer(e);this.layerUnloaders.set(e.id,()=>{a(),n(),e.loaded=!1})}else console.warn("No loader found for",{layer:e})}}unloadLayer(e){this.selectedLayerId===e.id&&this.select(null),this.layerUnloaders.has(e.id)&&(this.layerUnloaders.get(e.id)(),this.layerUnloaders.delete(e.id))}addLayer(e){if(this.layers.push(e),e.visible){this.loadLayer(e);const t=e.model.getTimeRange();if(1===this.getVisibleLayers().length)this.setTimeRange(t);else{const e=c(this.getTimeRange(),t);this.setTimeRange(e)}}e.on("visible",t=>{e.visible?this.loadLayer(e):this.unloadLayer(e)})}removeLayer(e){const t="string"==typeof e?e:e.id,i=this.layers.find(e=>e.id===t);i&&(this.unloadLayer(i),this.layerUnloaders.delete(t),this.layers=this.layers.filter(e=>e.id!==t))}destroy(){this.layers.map(e=>e.id).forEach(e=>this.removeLayer(e)),this.onDestroy.forEach(e=>e())}addHorizontalPinchZoom(){let e=null,t=null;const i=()=>{this.pinching=!1,e=null,t=null},s=i=>{if(2===i.touches.length){i.preventDefault(),this.dragging=!1,this.pinching=!0;const s=this.mouseInSlider(i.touches[0]).t,n=this.mouseInSlider(i.touches[1]).t;e=Math.min(s,n),t=Math.max(s,n)}},n=s=>{if(2===s.touches.length){if(null===e||null===t)return;s.preventDefault(),this.dragging=!1;const i=this.mouseInSlider(s.touches[0]).normalized.x,n=this.mouseInSlider(s.touches[1]).normalized.x,l=Math.min(i,n),a=Math.max(i,n),o=(t-e)/(a-l);let h=e-l*o,r=t+(1-a)*o;if(o>z){const e=.5*(h+r);h=e-.5*z,r=e+.5*z}if(o<$){const e=.5*(h+r);h=e-.5*$,r=e+.5*$}this.setTimeRange({startTime:h,endTime:r})}else i()},l=()=>{i()};this.sliderElement.addEventListener("touchstart",s,{passive:!1}),this.sliderElement.addEventListener("touchmove",n,{passive:!1}),this.sliderElement.addEventListener("touchend",l),this.sliderElement.addEventListener("touchcancel",l),this.onDestroy.push(()=>{this.sliderElement.removeEventListener("touchstart",s),this.sliderElement.removeEventListener("touchmove",n),this.sliderElement.removeEventListener("touchend",l),this.sliderElement.removeEventListener("touchcancel",l)})}initControls(){const e=new t;this.dragging=!1;let i,s=0,n=0,l=0;e.add(this.initHoverListener());const a=e=>{this.sliderElement.focus(),e.preventDefault();const t=this.mouseInSlider(e);this.zoom(.001*e.deltaY,{x:t.normalized.x})};let o=0,h=-1;const r=e=>{const t=Date.now(),i=t-o;h>=0&&i<300&&i>0&&(this.select(null),e.preventDefault(),this.zoom(-.75,{animate:1e3,x:h})),o=t},d=e=>{e.preventDefault(),this.select(null);const t=this.mouseInSlider(e);this.zoom(-.75,{animate:1e3,x:t.normalized.x})};this.selectingRangeElement.style.height="calc(100% - 6px)",this.selectingRangeElement.style.pointerEvents="none",this.selectingRangeElement.style.position="absolute",this.selectingRangeElement.style.border="3px solid #df0",this.selectingRangeElement.style.background="#df04",this.selectingRangeElement.style.top="0px";const m=e=>{if(this.sliderElement.focus(),2===e.button||0===e.button){e.preventDefault();const t=this.mouseInSlider(e),i=t.normalized.x,{startTime:a,duration:o}=this.getTimeRange();s=a+i*o,n=Date.now(),l=t.absolute.x,(e.ctrlKey||2===e.button)&&(this.selectingRange=!0),this.selectingRange?(this.selectingRangeElement.style.left=t.absolute.x+"px",this.selectingRangeElement.style.width="0px",this.container.appendChild(this.selectingRangeElement),this.selectingRangeVisible=!0):this.dragging=!0}},g=e=>{const t=this.mouseInSlider(e);return i=t.normalized.x,t},u=e=>{const t=g(e);if(this.selectingRange){const e=Math.abs(l-t.absolute.x),i=Math.min(l,t.absolute.x);this.selectingRangeElement.style.left=i+"px",this.selectingRangeElement.style.width=e-6+"px"}if(!this.dragging||Date.now()-n<100&&Math.abs(l-t.absolute.x)<10)return;e.preventDefault();const i=t.normalized.x,{startTime:a,endTime:o}=this.getTimeRange(),h=a+i*(o-a)-s;this.setTimeRange({startTime:a-h,endTime:o-h})},c=e=>{const t=this.getSliderBounds(),n=t.height-(e.clientY-t.top);if(!this.dragging&&!this.pinching&&n<8)this.ticksBar.click(e);else if(i=void 0,this.dragging=!1,this.selectingRange){const t=this.mouseInSlider(e).normalized.x,{startTime:i,endTime:n}=this.getTimeRange(),l=i+t*(n-i);"zoom"===this.selectRangeMode&&this.fit({range:{startTime:Math.min(s,l),endTime:Math.max(s,l)},animate:1e3}),"select"===this.selectRangeMode&&this.select(null,{startTime:Math.min(s,l),endTime:Math.max(s,l)})}this.stopSelectingRange()},p=e=>{this.pressedKeys.add(e.code)},y=e=>{this.pressedKeys.delete(e.code),"Space"===e.code&&(e.preventDefault(),this.togglePlaying()),"KeyF"===e.code&&(e.preventDefault(),this.fit({animate:3e3}));const t=void 0;"ArrowRight"===e.code&&(e.preventDefault(),this.skip(1,{animate:t})),"ArrowLeft"===e.code&&(e.preventDefault(),this.skip(-1,{animate:t})),"ArrowUp"===e.code&&(e.preventDefault(),this.up({animate:t})),"ArrowDown"===e.code&&(e.preventDefault(),this.down({xRatio:i,animate:t}))};let T=!0;const v=()=>{if(T){const e=this.pressedKeys.has("ShiftLeft")?.05:.01,t=2*e,s=this.pressedKeys.has("KeyD"),n=this.pressedKeys.has("KeyA");s&&this.shift(-e),n&&this.shift(e),this.pressedKeys.has("KeyW")&&this.zoom(-t,{x:s||n?void 0:i}),this.pressedKeys.has("KeyS")&&this.zoom(t,{x:s||n?void 0:i}),requestAnimationFrame(v)}};v(),e.add(()=>T=!1);const f=e=>e.preventDefault();this.sliderElement.addEventListener("contextmenu",f),this.sliderElement.addEventListener("wheel",a),this.sliderElement.addEventListener("pointerdown",m),this.sliderElement.addEventListener("pointermove",u),this.sliderElement.addEventListener("pointerup",c),this.sliderElement.addEventListener("dblclick",d),this.sliderElement.addEventListener("touchend",r),this.sliderElement.addEventListener("touchstart",e=>{if(1===e.touches.length){const t=this.mouseInSlider(e.touches[0]);h=t.normalized.x}else h=-1}),this.sliderElement.addEventListener("keydown",p),this.sliderElement.addEventListener("keyup",y),this.addHorizontalPinchZoom();const E=()=>{this.sliderElement.removeEventListener("contextmenu",f),this.sliderElement.removeEventListener("wheel",a),this.sliderElement.removeEventListener("pointerdown",m),this.sliderElement.removeEventListener("pointermove",u),this.sliderElement.removeEventListener("pointerup",c),this.sliderElement.removeEventListener("dblclick",d),this.sliderElement.removeEventListener("touchend",r),this.sliderElement.removeEventListener("keydown",p),this.sliderElement.removeEventListener("keyup",y)};return this.onDestroy.push(E),e.add(E),e.disposeLater()}shift(e,t){const{startTime:i,endTime:s,duration:n}=this.getTimeRange(),l=t?.absolute?e:e*n;this.fit({...t,range:{startTime:i-l,endTime:s-l}})}zoom(e,t){const i="number"==typeof t?.x?t.x:.5,{startTime:s,endTime:n,duration:l}=this.getTimeRange(),a={startTime:s-e*l*i,endTime:n+e*l*(1-i)},o=a.endTime-a.startTime,h=a.startTime+.5*o;o>z&&(a.startTime=h-.5*z,a.endTime=h+.5*z),o<$&&(a.startTime=h-.5*$,a.endTime=h+.5*$),this.fit({range:a,animate:t?.animate})}togglePlaying(){this.playing?this.pause():this.play()}isPlaying(){return this.playing}play(){if(this.playing)return;this.playing=!0,this.emit("playing",!0);let e=Date.now();const t=()=>{if(this.playing){if(this.live){const{duration:e}=this.getTimeRange(),t=Date.now(),i=10/this.size.width;this.setTimeRange({startTime:t-(1-i)*e,endTime:t+i*e}),this.setCurrent(t)}else if("auto"!==this.playSpeed||this.showCurrent){const t=Date.now(),i=t-e,s=this.current-this.getTimeRange().startTime,n="auto"===this.playSpeed?1:this.playSpeed;this.shift(-n*i,{absolute:!0}),this.setCurrent(this.getTimeRange().startTime+s),e=t}else{const t=Date.now();let i=5e-5*(t-e);this.pressedKeys.has("ShiftLeft")&&(i*=5);const s=this.current-this.getTimeRange().startTime;this.shift(-i),this.setCurrent(this.getTimeRange().startTime+s),e=t}requestAnimationFrame(t)}};t()}setCurrent(e){this.current!==e&&(Math.abs(e-Date.now())>100&&this.live&&(this.pause(),this.setLive(!1)),this.current=e,this.emit("current",e))}pause(){this.playing&&(this.playing=!1,this.emit("playing",!1),this.setLive(!1))}setLive(e){if(this.live!==e){if(this.live=e,e){const e=this.getTimeRange();this.fit({range:{startTime:e.endTime-this.liveRange,endTime:e.endTime},animate:w}),this.play()}this.emit("live",e)}}}function C(e){return{startTime:"number"==typeof e?.startTime?e.startTime:"number"==typeof e?.endTime?e.duration?e.endTime-e.duration:e.endTime-L:e?.duration?Date.now()-.5*e.duration:Date.now()-.5*L,endTime:"number"==typeof e?.endTime?e.endTime:"number"==typeof e?.startTime?e.duration?e.startTime+e.duration:e.startTime+L:e?.duration?Date.now()+.5*e.duration:Date.now()+.5*L,duration:e?.duration?e.duration:"number"==typeof e?.startTime&&"number"==typeof e?.endTime?e.endTime+e.startTime:L,minValue:"number"==typeof e?.minValue?e.minValue:"number"==typeof e?.maxValue?e.maxValue>0?0:e.maxValue-100:0,maxValue:"number"==typeof e?.maxValue?e.maxValue:"number"==typeof e?.minValue?e.minValue<0?0:e.minValue+100:100}}function A(e){const t=e/315576e5,i=Math.log10(t),s=Math.ceil(i);return Math.pow(10,s)}
@@ -0,0 +1,42 @@
1
+ import { TypedEventEmitter } from "../event/TypedEventEmitter";
2
+ import { TimeSliderTimeRangeWithDuration, TimeSliderValueRange, TimeSliderTimeRange } from "../data/TimeSliderRange";
3
+ export type TimeSliderEngineScene<T extends TimeSliderEngine<any>> = T['scene'];
4
+ export declare abstract class TimeSliderEngine<T> extends TypedEventEmitter<{
5
+ time: TimeSliderTimeRangeWithDuration;
6
+ value: TimeSliderValueRange;
7
+ size: {
8
+ width: number;
9
+ height: number;
10
+ };
11
+ }> {
12
+ scene: T;
13
+ private timeRange;
14
+ private valueRange;
15
+ private size;
16
+ theme: 'dark' | 'light';
17
+ constructor(scene: T);
18
+ setTheme(theme: 'dark' | 'light'): void;
19
+ getTimeRange(): {
20
+ duration: number;
21
+ startTime: number;
22
+ endTime: number;
23
+ };
24
+ getValueRange(): TimeSliderValueRange;
25
+ getSize(): {
26
+ width: number;
27
+ height: number;
28
+ };
29
+ showStats(showingStats: boolean): void;
30
+ abstract init(container: HTMLElement): Promise<void>;
31
+ protected abstract destroy(): void;
32
+ dispose(): void;
33
+ protected abstract updateTimeRange(newRange: TimeSliderTimeRangeWithDuration): void;
34
+ setTimeRange(newRange: TimeSliderTimeRange): void;
35
+ protected abstract updateValueRange(newRange: TimeSliderValueRange): void;
36
+ setValueRange(newRange: TimeSliderValueRange): void;
37
+ protected abstract updateSize(width: number, height: number): void;
38
+ setSize(width: number, height: number): void;
39
+ }
40
+ export type TimeSliderEngineClass<T extends TimeSliderEngine<any>> = Function & {
41
+ prototype: T;
42
+ };
@@ -0,0 +1 @@
1
+ import{TypedEventEmitter as e}from"../event/TypedEventEmitter";import{TODAY as t}from"../ticks/TimeSliderConstants";import{addDuration as i}from"../data/TimeSliderRange";export class TimeSliderEngine extends e{constructor(e){super(),this.scene=e,this.timeRange=t,this.valueRange={minValue:0,maxValue:100},this.size={width:1e3,height:100},this.theme="dark"}setTheme(e){this.theme=e,this.setTimeRange(this.timeRange)}getTimeRange(){return{...this.timeRange,duration:this.timeRange.endTime-this.timeRange.startTime}}getValueRange(){return this.valueRange}getSize(){return this.size}showStats(e){}dispose(){this.destroy(),this.size={width:1e3,height:100}}setTimeRange(e){if(e.startTime!==this.timeRange.startTime||e.endTime!==this.timeRange.endTime){this.timeRange=e;const t=i(e);this.updateTimeRange(t),this.emit("time",t)}}setValueRange(e){e.minValue===this.valueRange.minValue&&e.maxValue===this.valueRange.maxValue||(this.valueRange=e,this.updateValueRange(e),this.emit("value",e))}setSize(e,t){this.size.width===e&&this.size.height===t||(this.size={width:e,height:t},this.updateSize(e,t),this.emit("size",this.size))}}
@@ -0,0 +1,13 @@
1
+ type EventHandler<T> = (data: T) => void;
2
+ type AnyEventHandler<Events> = <K extends keyof Events>(event: K, data: Events[K]) => void;
3
+ export declare class TypedEventEmitter<Events extends Record<string, any>> {
4
+ private listeners;
5
+ private anyListeners;
6
+ on(handler: AnyEventHandler<Events>): () => void;
7
+ on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): () => void;
8
+ off<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): void;
9
+ off(handler: AnyEventHandler<Events>): void;
10
+ protected emit<K extends keyof Events>(event: K, data: Events[K]): void;
11
+ protected emit<K extends keyof Events>(event: K): void;
12
+ }
13
+ export {};
@@ -0,0 +1 @@
1
+ export class TypedEventEmitter{constructor(){this.listeners={},this.anyListeners=new Set}on(e,t){if("function"==typeof e){const t=e;return this.anyListeners.add(t),()=>this.anyListeners.delete(t)}if("function"==typeof t){const s=e;return this.listeners[s]||(this.listeners[s]=new Set),this.listeners[s].add(t),()=>this.listeners[s].delete(t)}return()=>{}}off(e,t){if("function"==typeof e){const t=e;this.anyListeners.delete(t)}else"function"==typeof t&&this.listeners[e]?.delete(t)}emit(e,t){this.listeners[e]?.forEach(e=>{e(t)}),this.anyListeners.forEach(s=>{s(e,t)})}}
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ import './index.css';
package/index.js ADDED
@@ -0,0 +1 @@
1
+ import e from"react";import*as t from"react-dom/client";import{TimeSliderDemo as r}from"./TimeSliderDemo";import"./index.css";t.createRoot(function(){const e=document.createElement("protovice");return document.body.appendChild(e),e}()).render(e.createElement(function(){return e.createElement("div",{id:"app"},e.createElement(r,null))},null));
@@ -0,0 +1,27 @@
1
+ import { TimeSliderHistogram, TimeSliderHistogramAttributes, TimeSliderHistogramClassifier, TimeSliderHistogramOptions } from "../data/histogram/TimeSliderHistogram";
2
+ import { TimeSliderInterval } from "../data/TimeSliderElement";
3
+ import { TimeSliderModel } from "../data/TimeSliderModel";
4
+ import { TimeSliderHistogramStyle } from "../style/TimeSliderHistogramStyle";
5
+ import { TimeSliderIntervalsLayer } from "./TimeSliderIntervalsLayer";
6
+ import { TimeSliderLayerOptions } from "./TimeSliderLayer";
7
+ export type TimeSliderHistogramLayerOptions<M extends TimeSliderModel = TimeSliderModel> = TimeSliderLayerOptions<TimeSliderInterval<TimeSliderHistogramAttributes>, TimeSliderHistogramStyle> & {
8
+ classifier?: TimeSliderHistogramClassifier<M>;
9
+ classificationIsColor?: boolean;
10
+ maxClassifications?: number;
11
+ classificationColors?: string[];
12
+ };
13
+ export declare class TimeSliderHistogramLayer<M extends TimeSliderModel = TimeSliderModel> extends TimeSliderIntervalsLayer<TimeSliderInterval<TimeSliderHistogramAttributes>, TimeSliderHistogramStyle> {
14
+ private content;
15
+ private d;
16
+ histogram: TimeSliderHistogram;
17
+ maxClassifications?: number;
18
+ _classificationColors: string[];
19
+ constructor(content: M, options?: TimeSliderHistogramLayerOptions<M>);
20
+ getClassification(element: TimeSliderInterval<TimeSliderHistogramAttributes>, v: number): string | undefined;
21
+ set classificationColors(ccs: string[]);
22
+ get classificationColors(): string[];
23
+ createHistogram(options?: TimeSliderHistogramOptions<M>): TimeSliderHistogram;
24
+ get fixedBoxes(): boolean;
25
+ dispose(): void;
26
+ getDefaultStyle(): TimeSliderHistogramStyle;
27
+ }
@@ -0,0 +1 @@
1
+ import{Disposables as s}from"../common/Disposables";import{TimeSliderDynamicHistogram as i}from"../data/histogram/TimeSliderDynamicHistogram";import{TimeSliderSplittingFixedHistogram as t}from"../data/histogram/TimeSliderSplittingFixedHistogram";import{TimeSliderIntervalsModel as e}from"../data/TimeSliderIntervalsModel";import{TimeSliderIntervalsLayer as a}from"./TimeSliderIntervalsLayer";export class TimeSliderHistogramLayer extends a{constructor(i,t){super(new e,t),this.content=i,this.d=new s;const a=this.createHistogram({classifier:t?.classifier,...t?.style});this.histogram=a,this.maxClassifications=t?.maxClassifications,this._classificationColors=t?.classificationColors||[],t?.classificationIsColor&&!this.fixedBoxes&&(this.styler=s=>{const i=s.attributes?.classification;return i?{fill:{color:i},border:{color:i}}:void 0}),t?.classifier&&!t.labeler&&(this.fixedBoxes?t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+" TODO use split":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i+" TODO use split"}:t.classificationIsColor?this.labeler=(s,i,t)=>Math.abs(s.v[0]-s.v[1])+"":this.labeler=s=>{const i=Math.abs(s.v[0]-s.v[1]);return s.attributes?.classification+": "+i}),this.d.add(this.on("loaded",s=>{s?a.start(this.timeSlider):a.stop()})),this.d.add(this.on("invalidateAll",()=>{a.average=!0===this.style.average,a.weighted=!0===this.style.weighted,a.inverted=!0===this.style.inverted,this.style.mode&&(a.mode=this.style.mode),a.classifier=this.style.classifier,this.style.classOrder&&(a.classOrder=this.style.classOrder)}))}getClassification(s,i){const t=s.v[1]-s.v[0],e=s.attributes?.splits||[1],a=i/t;let o=0;for(let s=0;s<e.length;s++)if(o+=e[s],a<o)return this.histogram.classOrder[s]}set classificationColors(s){this._classificationColors=s,this.invalidateAll()}get classificationColors(){return this._classificationColors}createHistogram(s){return this.fixedBoxes?new t(this.model,this.content,s):new i(this.model,this.content,s)}get fixedBoxes(){return void 0!==this.style.mode?.fixed||void 0!==this.style.mode?.fixedUnit}dispose(){this.model.clear(),this.d.dispose()}getDefaultStyle(){return{}}}