@protomaze/time 1.4.3 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +29 -1
  2. package/TimeSliderDemo.d.ts +12 -1
  3. package/TimeSliderDemo.js +1 -1
  4. package/common/TimeTools.d.ts +17 -5
  5. package/common/TimeTools.js +1 -1
  6. package/data/CompositeTimeSliderModel.js +1 -1
  7. package/data/TimeSliderBush.js +1 -1
  8. package/data/TimeSliderIntervalsModel.js +1 -1
  9. package/data/TimeSliderLanesModel.js +1 -1
  10. package/data/TimeSliderModel.js +1 -1
  11. package/data/TimeSliderPointsModel.js +1 -1
  12. package/data/TimeSliderRange.d.ts +8 -0
  13. package/data/TimeSliderRange.js +1 -1
  14. package/data/histogram/TimeSliderDynamicHistogram.js +1 -1
  15. package/data/histogram/TimeSliderFixedHistogram.js +1 -1
  16. package/data/histogram/TimeSliderHistogram.js +1 -1
  17. package/data/histogram/TimeSliderSplittingFixedHistogram.js +1 -1
  18. package/demo/Common.d.ts +5 -1
  19. package/demo/Common.js +1 -1
  20. package/demo/Metrics.d.ts +2 -2
  21. package/demo/Metrics.js +1 -1
  22. package/demo/Nasdaq.d.ts +5 -2
  23. package/demo/Nasdaq.js +1 -1
  24. package/demo/Quakes.d.ts +6 -3
  25. package/demo/Quakes.js +1 -1
  26. package/demo/QuakesFilters.d.ts +3 -1
  27. package/demo/QuakesFilters.js +1 -1
  28. package/demo/Random.d.ts +45 -35
  29. package/demo/Random.js +1 -1
  30. package/demo/Test.d.ts +5 -2
  31. package/demo/Test.js +1 -1
  32. package/demo/Wars.js +1 -1
  33. package/engine/TimeSlider.d.ts +131 -5
  34. package/engine/TimeSlider.js +1 -1
  35. package/engine/TimeSliderEngine.js +1 -1
  36. package/index.d.ts +62 -1
  37. package/index.js +1 -1
  38. package/layer/TimeSliderHistogramLayer.js +1 -1
  39. package/layer/TimeSliderHistogramLayerOld.js +1 -1
  40. package/layer/TimeSliderIntervalsLayer.js +1 -1
  41. package/layer/TimeSliderLayer.js +1 -1
  42. package/layer/TimeSliderLayerLoader.d.ts +2 -0
  43. package/layer/TimeSliderPointsLayer.js +1 -1
  44. package/package.json +60 -58
  45. package/react/DateLabelWithPicker.js +1 -1
  46. package/react/DateRangeLabelWithPicker.js +1 -1
  47. package/react/FullscreenButton.js +1 -1
  48. package/react/ReactTimeSlider.js +1 -1
  49. package/react/TimeLabelWithPicker.js +1 -1
  50. package/style/TimeSliderIntervalsStyle.d.ts +4 -0
  51. package/three/Three3DTimeSliderEngine.js +1 -1
  52. package/three/ThreeTimeSlider.js +1 -1
  53. package/three/ThreeTimeSliderEngine.js +1 -1
  54. package/three/layer/GrowingBufferGeometry.js +1 -1
  55. package/three/layer/GrowingInstanceMatrix.js +1 -1
  56. package/three/layer/Three3DIntervalsTimeLayerLoader.d.ts +2 -2
  57. package/three/layer/Three3DIntervalsTimeLayerLoader.js +1 -1
  58. package/three/layer/Three3DPointsTimeLayerLoader.d.ts +1 -2
  59. package/three/layer/Three3DPointsTimeLayerLoader.js +1 -1
  60. package/three/layer/ThreeIntervalsTimeLayerLoader.d.ts +2 -2
  61. package/three/layer/ThreeIntervalsTimeLayerLoader.js +1 -1
  62. package/three/layer/ThreePointsTimeLayerLoader.d.ts +1 -2
  63. package/three/layer/ThreePointsTimeLayerLoader.js +1 -1
  64. package/three/layer/ThreeTimeLayerLoader.js +1 -1
  65. package/three/react/ReactThreeTimeSlider.js +1 -1
  66. package/ticks/TimeTicksBar.d.ts +14 -1
  67. package/ticks/TimeTicksBar.js +1 -1
package/README.md CHANGED
@@ -1 +1,29 @@
1
- # Protomaze Timesliders
1
+ # Protomaze Timesliders
2
+
3
+ ## Publishing
4
+
5
+ Releases go out via [`.github/workflows/publish.yml`](.github/workflows/publish.yml) using npm's
6
+ **Trusted Publishing**: no npm token lives anywhere, in CI or on any laptop. GitHub Actions proves
7
+ its identity to npm with a short-lived OIDC credential scoped to this exact repo and workflow file.
8
+ The workflow type-checks and compiles the sources and publishes `build/`, which is the package.
9
+
10
+ One-time setup (needs the npm account owner, see [Trusted
11
+ Publishers](https://docs.npmjs.com/trusted-publishers)):
12
+
13
+ 1. On npmjs.com, under the package's settings, add a Trusted Publisher: GitHub Actions, repository
14
+ `protomaze/time`, workflow file `.github/workflows/publish.yml`.
15
+
16
+ After that, a release is:
17
+
18
+ ```bash
19
+ npm version patch # or minor / major - bumps package.json and tags it
20
+ git push --follow-tags
21
+ ```
22
+
23
+ The tag push triggers the workflow. `workflow_dispatch` is also enabled, so a release can be re-run
24
+ by hand from the Actions tab.
25
+
26
+ Publishing from a laptop is not the path: the npm account has two-factor authentication, so a local
27
+ `npm publish` asks for a one-time code that a security key cannot produce, and the access tokens
28
+ that used to bypass this are being restricted by npm. `npm run deploy` and `npm run pub` remain for
29
+ emergencies and for a local [Verdaccio](https://verdaccio.org) on port 4873 respectively.
@@ -1 +1,12 @@
1
- export declare function TimeSliderDemo(): JSX.Element;
1
+ export type TimeSliderDemoDataSet = 'random' | 'quakes' | 'nasdaq' | 'wars' | 'test';
2
+ export type TimeSliderDemoProps = {
3
+ /** Where the data sets load their files from (quakes.json, apple.csv, ...), './resources/data/' by default */
4
+ dataUrl?: string;
5
+ /** The data set shown first, 'test' by default */
6
+ initialDataSet?: TimeSliderDemoDataSet;
7
+ };
8
+ /**
9
+ * Every kind of time slider layer on a few data sets: random live data, earthquakes and temperatures, stock prices.
10
+ * Fills its positioned parent. The data sets are only created (and their files loaded) once they are shown.
11
+ */
12
+ export declare function TimeSliderDemo({ dataUrl, initialDataSet }: TimeSliderDemoProps): JSX.Element;
package/TimeSliderDemo.js CHANGED
@@ -1 +1 @@
1
- import e,{useEffect as t,useMemo as r,useRef as a,useState as n}from"react";import{setupInPageConsole as o}from"./common/CaptureConsole";import{NASDAQ_MULTI_LAYERS as i,NASDAQ_SINGLE_LAYERS as m}from"./demo/Nasdaq";import{QUAKES_MULTI_LAYERS as l,QUAKES_SINGLE_LAYERS as s}from"./demo/Quakes";import{RANDOM_MULTI_LAYERS as c,RANDOM_SINGLE_LAYERS as d}from"./demo/Random";import{WARS_MULTI_LAYERS as p,WARS_SINGLE_LAYERS as u}from"./demo/Wars";import{FullscreenButton as f}from"./react/FullscreenButton";import{MaterialIconButton as w}from"./react/MaterialIconButton";import{MaterialTextButton as h}from"./react/MaterialTextButton";import{ReactTimeSlider as k}from"./react/ReactTimeSlider";import{Three3DTimeSliderEngine as x}from"./three/Three3DTimeSliderEngine";import{ThreeTimeSliderEngine as E}from"./three/ThreeTimeSliderEngine";import{Three3DIntervalsTimeLayerLoader as g}from"./three/layer/Three3DIntervalsTimeLayerLoader";import{Three3DPointsTimeLayerLoader as y}from"./three/layer/Three3DPointsTimeLayerLoader";import{ThreeIntervalsTimeLayerLoader as T}from"./three/layer/ThreeIntervalsTimeLayerLoader";import{ThreePointsTimeLayerLoader as v}from"./three/layer/ThreePointsTimeLayerLoader";import{ONE_MINUTE as q}from"./ticks/TimeSliderConstants";import{QuakesFilters as C}from"./demo/QuakesFilters";import{TEST_LAYERS as D}from"./demo/Test";const L="development"===process.env.NODE_ENV,S=L;L&&!1&&o();const N=Date.now(),R=N-37*q,b={single:{test:[!1],random:[!0],quakes:[!1],nasdaq:[!1],wars:[!1]},multiple:{test:[!1],random:[!1,!0,!1],quakes:[!1,!1,!1],nasdaq:[!1,!1,!1,!1,!1],wars:[!1,!1]}},I={single:{test:[D],random:[d],quakes:[s],nasdaq:[m],wars:[u]},multiple:{test:[D],random:c,quakes:l,nasdaq:i,wars:p}},_=[new v,new T,new y,new g],B=[new E,new E,new E,new E,new E,new E],F=[new x,new x,new x,new x,new x,new x],M={display:"flex",justifyContent:"center",alignItems:"center",borderRadius:"4px",backgroundColor:"#222"},Q={...M,flexShrink:0},G={...M,flexGrow:1};export function TimeSliderDemo(){const[o,i]=n([R,N]),[m,l]=n(!0),[s,c]=n(!1),[d,p]=n("test"),[u,x]=n(!0),E=a([]),g=r(()=>I[s?"multiple":"single"][d],[d,s]);return t(()=>{E.current.forEach((e,t)=>{e?.timeSlider.pause();const r=b[s?"multiple":"single"][d][t];"random"===d&&r&&setTimeout(()=>{e?.timeSlider.setLive(!0)},200)})},[d,s]),e.createElement(e.Fragment,null,e.createElement("div",{style:{position:"absolute",display:"flex",flexDirection:"column",inset:"0",gap:"8px",padding:"8px",height:"calc(100% - 16px)"}},e.createElement("div",{style:{...Q,height:"22px",gap:"8px",padding:"8px",backgroundColor:u?"#222":"#ddd",display:"flex"}},e.createElement(h,{text:"Random",onClick:()=>p("random"),active:"random"===d}),e.createElement(h,{text:"Quakes",onClick:()=>p("quakes"),active:"quakes"===d}),e.createElement(h,{text:"Nasdaq",onClick:()=>p("nasdaq"),active:"nasdaq"===d}),e.createElement("div",{style:{flexGrow:1}}),e.createElement(w,{iconName:u?"dark_mode":"light_mode",onClick:()=>x(e=>!e)}),e.createElement("div",{style:{width:"0px"}}),e.createElement(w,{iconName:"crop_square",onClick:()=>c(!1),active:!s}),e.createElement(w,{iconName:"splitscreen",onClick:()=>c(!0),active:s}),e.createElement("div",{style:{width:"0px"}}),e.createElement(h,{text:"2D",onClick:()=>l(!1),active:!m}),e.createElement(h,{text:"3D",onClick:()=>l(!0),active:m}),e.createElement("div",{style:{width:"0px"}}),e.createElement(f,null)),"quakes"===d&&e.createElement(C,{darkMode:u}),g.map((t,r)=>e.createElement("div",{key:r,style:G},e.createElement(k,{engine:(m?F:B)[r],theme:u?"dark":"light",ref:e=>{E.current[r]=e},timeRange:o,onTimeRange:i,layers:t,loaders:_,showTicks:!0,showCurrent:b[s?"multiple":"single"][d][r],showStats:S})))))}
1
+ import e,{useEffect as t,useMemo as r,useRef as a,useState as n}from"react";import{setupInPageConsole as o}from"./common/CaptureConsole.js";import{DEMO_DATA_URL as i}from"./demo/Common.js";import{createNasdaqDemo as s}from"./demo/Nasdaq.js";import{createQuakesDemo as m}from"./demo/Quakes.js";import{createRandomDemo as l}from"./demo/Random.js";import{WARS_MULTI_LAYERS as c,WARS_SINGLE_LAYERS as d}from"./demo/Wars.js";import{FullscreenButton as p}from"./react/FullscreenButton.js";import{MaterialIconButton as u}from"./react/MaterialIconButton.js";import{MaterialTextButton as f}from"./react/MaterialTextButton.js";import{ReactTimeSlider as h}from"./react/ReactTimeSlider.js";import{Three3DTimeSliderEngine as g}from"./three/Three3DTimeSliderEngine.js";import{ThreeTimeSliderEngine as y}from"./three/ThreeTimeSliderEngine.js";import{Three3DIntervalsTimeLayerLoader as k}from"./three/layer/Three3DIntervalsTimeLayerLoader.js";import{Three3DPointsTimeLayerLoader as E}from"./three/layer/Three3DPointsTimeLayerLoader.js";import{ThreeIntervalsTimeLayerLoader as x}from"./three/layer/ThreeIntervalsTimeLayerLoader.js";import{ThreePointsTimeLayerLoader as j}from"./three/layer/ThreePointsTimeLayerLoader.js";import{ONE_MINUTE as w}from"./ticks/TimeSliderConstants.js";import{QuakesFilters as T}from"./demo/QuakesFilters.js";import{createTestDemo as v}from"./demo/Test.js";const C="undefined"!=typeof process&&"development"===process.env?.NODE_ENV,q=C,D=C&&!1;const L={single:{test:[!1],random:[!0],quakes:[!1],nasdaq:[!1],wars:[!1]},multiple:{test:[!1],random:[!1,!0,!1],quakes:[!1,!1,!1],nasdaq:[!1,!1,!1,!1,!1],wars:[!1,!1]}};const S={display:"flex",justifyContent:"center",alignItems:"center",borderRadius:"4px",backgroundColor:"#222"},N={...S,flexShrink:0},R={...S,flexGrow:1};export function TimeSliderDemo({dataUrl:C=i,initialDataSet:S="test"}){const[b,I]=n(()=>{const e=Date.now();return[e-37*w,e]}),[M,_]=n(!0),[B,F]=n(!1),[Q,A]=n(S),[G,P]=n(!0),O=a([]),[{loaders:U,engines2D:V,engines3D:W}]=n(()=>(D&&o(),{loaders:[new j,new x,new E,new k],engines2D:Array.from({length:6},()=>new y),engines3D:Array.from({length:6},()=>new g)})),z=a(new Map),H=r(()=>(z.current.has(Q)||z.current.set(Q,function(e,t){switch(e){case"random":return l();case"quakes":return m(t);case"nasdaq":return s(t);case"wars":return{single:d,multiple:c};case"test":return v()}}(Q,C)),z.current.get(Q)),[Q]);t(()=>()=>z.current.forEach(e=>e.stop?.()),[]);const J=r(()=>B?H.multiple:[H.single],[H,B]);return t(()=>{O.current.forEach((e,t)=>{e?.timeSlider.pause();const r=L[B?"multiple":"single"][Q][t];"random"===Q&&r&&setTimeout(()=>{e?.timeSlider.setLive(!0)},200)})},[Q,B]),e.createElement(e.Fragment,null,e.createElement("div",{style:{position:"absolute",display:"flex",flexDirection:"column",inset:"0",gap:"8px",padding:"8px",height:"calc(100% - 16px)"}},e.createElement("div",{style:{...N,height:"22px",gap:"8px",padding:"8px",backgroundColor:G?"#222":"#ddd",display:"flex"}},e.createElement(f,{text:"Random",onClick:()=>A("random"),active:"random"===Q}),e.createElement(f,{text:"Quakes",onClick:()=>A("quakes"),active:"quakes"===Q}),e.createElement(f,{text:"Nasdaq",onClick:()=>A("nasdaq"),active:"nasdaq"===Q}),e.createElement("div",{style:{flexGrow:1}}),e.createElement(u,{iconName:G?"dark_mode":"light_mode",onClick:()=>P(e=>!e)}),e.createElement("div",{style:{width:"0px"}}),e.createElement(u,{iconName:"crop_square",onClick:()=>F(!1),active:!B}),e.createElement(u,{iconName:"splitscreen",onClick:()=>F(!0),active:B}),e.createElement("div",{style:{width:"0px"}}),e.createElement(f,{text:"2D",onClick:()=>_(!1),active:!M}),e.createElement(f,{text:"3D",onClick:()=>_(!0),active:M}),e.createElement("div",{style:{width:"0px"}}),e.createElement(p,null)),"quakes"===Q&&H.histogramLayer&&e.createElement(T,{darkMode:G,histogramLayer:H.histogramLayer}),J.map((t,r)=>e.createElement("div",{key:r,style:R},e.createElement(h,{engine:(M?W:V)[r],theme:G?"dark":"light",ref:e=>{O.current[r]=e},timeRange:b,onTimeRange:I,layers:t,loaders:U,showTicks:!0,showCurrent:L[B?"multiple":"single"][Q][r],showStats:q})))))}
@@ -5,11 +5,23 @@ export declare const SPLIT_PART_2: number;
5
5
  export declare const SPLIT_TIME_3: number;
6
6
  export declare const SPLIT_TIME_3_POW2: number;
7
7
  export declare const MONTH_NAMES: string[];
8
+ export declare function setDefaultLocale(locale: string | undefined): void;
9
+ export declare function getDefaultLocale(): string;
8
10
  export declare function getStartOfSecond(timestamp: number): number;
9
11
  export declare function getStartOfMinute(timestamp: number): number;
10
12
  export declare function getStartOfHour(timestamp: number): number;
11
13
  export declare function getStartOfDay(timestamp: number): number;
12
14
  export declare function getStartOfWeek(timestamp: number): number;
15
+ /** The ISO week number (1-53) for a given date. */
16
+ export declare function getISOWeekNumber(date: Date): number;
17
+ /**
18
+ * The ISO week-year for a given date — not always the same as getFullYear():
19
+ * e.g. 31 Dec 2024 is ISO week 1 of 2025, and 1 Jan 2024 is ISO week 1 of 2024
20
+ * but 1 Jan 2023 was ISO week 52 of 2022.
21
+ */
22
+ export declare function getISOWeekYear(date: Date): number;
23
+ /** Localized short prefix for a calendar-week label (e.g. "KW" for German "KW12"). Falls back to English's "W" for locales without an entry. */
24
+ export declare function getWeekLabelPrefix(locale: string): string;
13
25
  export declare function getStartOfMonth(timestamp: number): number;
14
26
  export declare function getStartOfXYears(timestamp: number, interval: number): number;
15
27
  export type TimeUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'decade' | 'century' | 'millennium';
@@ -30,11 +42,11 @@ export declare function getTimeOffset(startTime: number, endTime: number, catego
30
42
  */
31
43
  export declare function getMatchingTimeUnit(startTime: number, endTime: number): TimeUnit | undefined;
32
44
  export declare function getLargeTimeUnitRange(time: number, years: number, shift?: number): TimeSliderTimeRange;
33
- export declare function formatDuration(durationOrRange: number | TimeSliderTimeRange | [start: number, end: number]): string;
34
- export declare function formatDate(time: number, padding?: boolean): string;
35
- export declare function formatDateTime(time: number): string;
36
- export declare function formatDateWithWeekDay(time: number): string;
37
- export declare function formatDateRange(range: TimeSliderTimeRangeArray): string;
45
+ export declare function formatDuration(durationOrRange: number | TimeSliderTimeRange | [start: number, end: number], locale?: string): string;
46
+ export declare function formatDate(time: number, padding?: boolean, locale?: string): string;
47
+ export declare function formatDateTime(time: number, locale?: string): string;
48
+ export declare function formatDateWithWeekDay(time: number, locale?: string): string;
49
+ export declare function formatDateRange(range: TimeSliderTimeRangeArray, locale?: string): string;
38
50
  export declare function formatTime(time: number): string;
39
51
  export declare function getTimePartsInHours(time: number): [hoursSinceYear0: number, msSinceHourStart: number];
40
52
  export declare function splitTime3(time: number): [t1: number, t2: number, t3: number];
@@ -1 +1 @@
1
- import{CENTURY as e,DECADE as t,MILLENIUM as r,ONE_DAY as a,ONE_HOUR as o,ONE_MINUTE as n,ONE_MONTH as s,ONE_SECOND as u,ONE_WEEK as l,ONE_YEAR as i}from"../ticks/TimeSliderConstants";const g=new Date;g.setFullYear(0,0,1),g.setHours(0,0,0,0);export const year0Ms=g.getTime();const c=new Date;c.setFullYear(1e3,0,1),c.setHours(0,0,0,0);export const year1000Ms=c.getTime();export const SPLIT_PART_2=Math.pow(2,22);export const SPLIT_TIME_3=Math.pow(2,14);export const SPLIT_TIME_3_POW2=SPLIT_TIME_3*SPLIT_TIME_3;export const MONTH_NAMES=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];export function getStartOfSecond(e){return new Date(e).setMilliseconds(0)}export function getStartOfMinute(e){return new Date(e).setSeconds(0,0)}export function getStartOfHour(e){return new Date(e).setMinutes(0,0,0)}export function getStartOfDay(e){return new Date(e).setHours(0,0,0,0)}export function getStartOfWeek(e){const t=new Date(e),r=t.getDay(),a=t.getDate()-r+(0===r?-6:1);return new Date(t.setDate(a)).setHours(0,0,0,0)}export function getStartOfMonth(e){const t=new Date(e);return t.setDate(1),t.setHours(0,0,0,0)}export function getStartOfXYears(e,t){const r=new Date(e),a=t*Math.floor(r.getFullYear()/t),o=new Date(a,0,1);o.setFullYear(a);return o.setHours(0,0,0,0)}export function getTimeUnitInMs(g){switch(g){case"year":return i;case"month":return s;case"week":return l;case"day":return a;case"hour":return o;case"minute":return n;case"second":return u;case"decade":return t;case"century":return e;case"millennium":return r}}export function getTimeUnitRange(e,t,r=0){const a=new Date(e),o=new Date(a),n=new Date(a);switch(t){case"year":{const e=a.getFullYear()+r;o.setFullYear(e,0,1),o.setHours(0,0,0,0),n.setFullYear(e+1,0,1),n.setHours(0,0,0,0);break}case"month":{const e=a.getFullYear(),t=a.getMonth()+r;o.setFullYear(e,t,1),o.setHours(0,0,0,0),n.setFullYear(e,t+1,1),n.setHours(0,0,0,0);break}case"week":{const e=(a.getDay()+6)%7;o.setDate(a.getDate()-e+7*r),o.setHours(0,0,0,0),n.setTime(o.getTime()),n.setDate(o.getDate()+7);break}case"day":o.setDate(a.getDate()+r),o.setHours(0,0,0,0),n.setTime(o.getTime()),n.setDate(o.getDate()+1);break;case"hour":o.setTime(a.getTime()),o.setHours(a.getHours()+r,0,0,0),n.setTime(o.getTime()),n.setHours(o.getHours()+1);break;case"minute":o.setTime(a.getTime()),o.setMinutes(a.getMinutes()+r,0,0),n.setTime(o.getTime()),n.setMinutes(o.getMinutes()+1);break;case"second":o.setTime(a.getTime()),o.setSeconds(a.getSeconds()+r,0),n.setTime(o.getTime()),n.setSeconds(o.getSeconds()+1);break;case"decade":{const e=10*Math.floor(a.getFullYear()/10)+10*r;o.setFullYear(e,0,1),o.setHours(0,0,0,0),n.setFullYear(e+10,0,1),n.setHours(0,0,0,0);break}case"century":{const e=100*Math.floor(a.getFullYear()/100)+100*r;o.setFullYear(e,0,1),o.setHours(0,0,0,0),n.setFullYear(e+100,0,1),n.setHours(0,0,0,0);break}case"millennium":{const e=1e3*Math.floor(a.getFullYear()/1e3)+1e3*r;o.setFullYear(e,0,1),o.setHours(0,0,0,0),n.setFullYear(e+1e3,0,1),n.setHours(0,0,0,0);break}default:throw new Error("Invalid category")}return{startTime:o.getTime(),endTime:n.getTime()}}export function getTimeOffset(e,t,r){const a=new Date(e),o=new Date(t);switch(r){case"year":return o.getFullYear()-a.getFullYear();case"month":return 12*(o.getFullYear()-a.getFullYear())+(o.getMonth()-a.getMonth());case"week":const e=6048e5;return Math.floor((o.getTime()-a.getTime())/e);case"day":const t=864e5;return Math.floor((o.getTime()-a.getTime())/t);case"hour":const r=36e5;return Math.floor((o.getTime()-a.getTime())/r);case"minute":const n=6e4;return Math.floor((o.getTime()-a.getTime())/n);case"second":const s=1e3;return Math.floor((o.getTime()-a.getTime())/s);case"decade":return Math.floor(o.getFullYear()/10)-Math.floor(a.getFullYear()/10);case"century":return Math.floor(o.getFullYear()/100)-Math.floor(a.getFullYear()/100);case"millennium":return Math.floor(o.getFullYear()/1e3)-Math.floor(a.getFullYear()/1e3);default:throw new Error("Invalid category")}}export function getMatchingTimeUnit(e,t){const r=["millennium","century","decade","year","month","week","day","hour","minute","second"];for(const a of r){const r=getTimeUnitRange(e,a),o=r.endTime-r.startTime;if(0===o)continue;const n=.1*o,s=Math.abs(e-r.startTime)<=n,u=Math.abs(t-r.endTime)<=n;if(s&&u)return a}}export function getLargeTimeUnitRange(e,t,r=0){const a=new Date(e),o=new Date(a),n=new Date(a),s=Math.floor(o.getFullYear()/t)*t+r*t;return o.setFullYear(s,0,1),o.setHours(0,0,0,0),n.setFullYear(s+t-1,11,31),n.setHours(23,59,59,999),{startTime:o.getTime(),endTime:n.getTime()}}export function formatDuration(t){const r="number"==typeof t?t:Array.isArray(t)?t[1]-t[0]:t.endTime-t.startTime,a=Math.floor(r/1e3),n=Math.floor(a/60),s=Math.floor(n/60),g=Math.floor(s/24),c=Math.floor(g/365),m=Math.floor(r%1e3),f=a%60,h=n%60,T=s%24,M=g%365,D=[];if(c>0&&D.push(`${c} year${c>1?"s":""}`),c<1||M>Math.ceil(c/4))if(M%7==0&&0===T&&0===h&&0===f&&M>0&&r<e){const e=Math.floor(M/7);D.push(`${e} week${e>1?"s":""}`)}else M>0&&r<e&&D.push(`${M} day${M>1?"s":""}`),T>0&&r<i&&D.push(`${T}h`),h>0&&r<l&&D.push(`${h}m`),f>0&&r<o&&D.push(`${f}s`),r<5*u&&r>=1&&D.push(`${m}ms`),r<1&&D.push("<1ms");return D.join(" ")}export function formatDate(e,t){const r=new Date(e),a=t?String(r.getFullYear()).padStart(4,"0"):String(r.getFullYear());return`${t?String(r.getDate()).padStart(2,"0"):String(r.getDate())} ${MONTH_NAMES[r.getMonth()]} ${a}`}export function formatDateTime(e){const t="number"==typeof e?new Date(e):e,r=t.getFullYear().toString().padStart(4,"0"),a=t.getDate().toString().padStart(2,"0"),o=t.toLocaleString("default",{month:"short"});return`${t.toLocaleString("default",{weekday:"short"})} ${a} ${o} ${r} ${t.getHours().toString().padStart(2,"0")}:${t.getMinutes().toString().padStart(2,"0")}:${t.getSeconds().toString().padStart(2,"0")}`}export function formatDateWithWeekDay(e){const t="number"==typeof e?new Date(e):e,r=t.getFullYear().toString().padStart(4,"0"),a=t.getDate().toString().padStart(2,"0"),o=t.toLocaleString("default",{month:"short"});return`${t.toLocaleString("default",{weekday:"short"})} ${a} ${o} ${r}`}export function formatDateRange(e){const[t,r]=e,a=new Date(t),o=new Date(r),n=new Date(r-1),s=a.toLocaleString("default",{month:"short"}),u=n.toLocaleString("default",{month:"short"}),l=a.getDate().toString().padStart(2,"0"),i=n.getDate().toString().padStart(2,"0");return a.getFullYear()===n.getFullYear()?a.getMonth()===n.getMonth()?a.getDate()===n.getDate()?`${i} ${u} ${n.getFullYear()}`:1===a.getDate()&&1===o.getDate()?`${u} ${n.getFullYear()}`:`${l} - ${i} ${u} ${n.getFullYear()}`:1===a.getDate()&&1===o.getDate()&&0===a.getMonth()&&0===o.getMonth()?`${n.getFullYear()}`:`${l} ${s} - ${i} ${u} ${n.getFullYear()}`:1===a.getDate()&&1===o.getDate()&&0===a.getMonth()&&0===o.getMonth()?` ${a.getFullYear()} - ${n.getFullYear()}`:`${l} ${s} ${a.getFullYear()} - ${i} ${u} ${n.getFullYear()}`}export function formatTime(e){const t=new Date(e),r=t.getHours(),a=t.getMinutes(),o=t.getSeconds();return(r<10?"0":"")+r+":"+(a<10?"0":"")+a+":"+(o<10?"0":"")+o}export function getTimePartsInHours(e){return[Math.floor(e/o),e%o]}export function splitTime3(e){const t=Math.floor(e/SPLIT_TIME_3_POW2),r=e%SPLIT_TIME_3_POW2;return[t,Math.floor(r/SPLIT_TIME_3),r%SPLIT_TIME_3]}export function splitTime2(e){return[Math.floor(e/SPLIT_PART_2),e%SPLIT_PART_2]}export function getDurationParts(e){return[Math.floor(e/a),e%a]}
1
+ import{CENTURY as e,DECADE as t,MILLENIUM as r,ONE_DAY as a,ONE_HOUR as n,ONE_MINUTE as o,ONE_MONTH as s,ONE_SECOND as u,ONE_WEEK as i,ONE_YEAR as c}from"../ticks/TimeSliderConstants.js";const l=new Date;l.setFullYear(0,0,1),l.setHours(0,0,0,0);export const year0Ms=l.getTime();const g=new Date;g.setFullYear(1e3,0,1),g.setHours(0,0,0,0);export const year1000Ms=g.getTime();export const SPLIT_PART_2=Math.pow(2,22);export const SPLIT_TIME_3=Math.pow(2,14);export const SPLIT_TIME_3_POW2=SPLIT_TIME_3*SPLIT_TIME_3;export const MONTH_NAMES=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];let m;export function setDefaultLocale(e){m=e}export function getDefaultLocale(){return m??("undefined"!=typeof navigator?navigator.language:"en")}const f=new Map;function h(e,t){const r=e??getDefaultLocale(),a=r+JSON.stringify(t);let n=f.get(a);return n||(n=new Intl.DateTimeFormat(r,t),f.set(a,n)),n}const T={en:{year:["year","years"],week:["week","weeks"],day:["day","days"]},de:{year:["Jahr","Jahre"],week:["Woche","Wochen"],day:["Tag","Tage"]},fr:{year:["an","ans"],week:["semaine","semaines"],day:["jour","jours"]},nl:{year:["jaar","jaar"],week:["week","weken"],day:["dag","dagen"]}};export function getStartOfSecond(e){return new Date(e).setMilliseconds(0)}export function getStartOfMinute(e){return new Date(e).setSeconds(0,0)}export function getStartOfHour(e){return new Date(e).setMinutes(0,0,0)}export function getStartOfDay(e){return new Date(e).setHours(0,0,0,0)}export function getStartOfWeek(e){const t=new Date(e),r=t.getDay(),a=t.getDate()-r+(0===r?-6:1);return new Date(t.setDate(a)).setHours(0,0,0,0)}function M(e){const t=new Date(e.valueOf()),r=(e.getDay()+6)%7+1;return t.setDate(t.getDate()-r+4),t}export function getISOWeekNumber(e){const t=M(e),r=new Date(t.getFullYear(),0,1),n=new Date(t.getFullYear(),t.getMonth(),t.getDate()),o=Math.round((n.getTime()-r.getTime())/a);return Math.floor(o/7)+1}export function getISOWeekYear(e){return M(e).getFullYear()}const D={en:"W",de:"KW",fr:"S",nl:"Wk"};export function getWeekLabelPrefix(e){const t=e.split("-")[0].toLowerCase();return D[t]??D.en}export function getStartOfMonth(e){const t=new Date(e);return t.setDate(1),t.setHours(0,0,0,0)}export function getStartOfXYears(e,t){const r=new Date(e),a=t*Math.floor(r.getFullYear()/t),n=new Date(a,0,1);n.setFullYear(a);return n.setHours(0,0,0,0)}export function getTimeUnitInMs(l){switch(l){case"year":return c;case"month":return s;case"week":return i;case"day":return a;case"hour":return n;case"minute":return o;case"second":return u;case"decade":return t;case"century":return e;case"millennium":return r}}export function getTimeUnitRange(e,t,r=0){const a=new Date(e),n=new Date(a),o=new Date(a);switch(t){case"year":{const e=a.getFullYear()+r;n.setFullYear(e,0,1),n.setHours(0,0,0,0),o.setFullYear(e+1,0,1),o.setHours(0,0,0,0);break}case"month":{const e=a.getFullYear(),t=a.getMonth()+r;n.setFullYear(e,t,1),n.setHours(0,0,0,0),o.setFullYear(e,t+1,1),o.setHours(0,0,0,0);break}case"week":{const e=(a.getDay()+6)%7;n.setDate(a.getDate()-e+7*r),n.setHours(0,0,0,0),o.setTime(n.getTime()),o.setDate(n.getDate()+7);break}case"day":n.setDate(a.getDate()+r),n.setHours(0,0,0,0),o.setTime(n.getTime()),o.setDate(n.getDate()+1);break;case"hour":n.setTime(a.getTime()),n.setHours(a.getHours()+r,0,0,0),o.setTime(n.getTime()),o.setHours(n.getHours()+1);break;case"minute":n.setTime(a.getTime()),n.setMinutes(a.getMinutes()+r,0,0),o.setTime(n.getTime()),o.setMinutes(n.getMinutes()+1);break;case"second":n.setTime(a.getTime()),n.setSeconds(a.getSeconds()+r,0),o.setTime(n.getTime()),o.setSeconds(n.getSeconds()+1);break;case"decade":{const e=10*Math.floor(a.getFullYear()/10)+10*r;n.setFullYear(e,0,1),n.setHours(0,0,0,0),o.setFullYear(e+10,0,1),o.setHours(0,0,0,0);break}case"century":{const e=100*Math.floor(a.getFullYear()/100)+100*r;n.setFullYear(e,0,1),n.setHours(0,0,0,0),o.setFullYear(e+100,0,1),o.setHours(0,0,0,0);break}case"millennium":{const e=1e3*Math.floor(a.getFullYear()/1e3)+1e3*r;n.setFullYear(e,0,1),n.setHours(0,0,0,0),o.setFullYear(e+1e3,0,1),o.setHours(0,0,0,0);break}default:throw new Error("Invalid category")}return{startTime:n.getTime(),endTime:o.getTime()}}export function getTimeOffset(e,t,r){const a=new Date(e),n=new Date(t);switch(r){case"year":return n.getFullYear()-a.getFullYear();case"month":return 12*(n.getFullYear()-a.getFullYear())+(n.getMonth()-a.getMonth());case"week":const e=6048e5;return Math.floor((n.getTime()-a.getTime())/e);case"day":const t=864e5;return Math.floor((n.getTime()-a.getTime())/t);case"hour":const r=36e5;return Math.floor((n.getTime()-a.getTime())/r);case"minute":const o=6e4;return Math.floor((n.getTime()-a.getTime())/o);case"second":const s=1e3;return Math.floor((n.getTime()-a.getTime())/s);case"decade":return Math.floor(n.getFullYear()/10)-Math.floor(a.getFullYear()/10);case"century":return Math.floor(n.getFullYear()/100)-Math.floor(a.getFullYear()/100);case"millennium":return Math.floor(n.getFullYear()/1e3)-Math.floor(a.getFullYear()/1e3);default:throw new Error("Invalid category")}}export function getMatchingTimeUnit(e,t){const r=["millennium","century","decade","year","month","week","day","hour","minute","second"];for(const a of r){const r=getTimeUnitRange(e,a),n=r.endTime-r.startTime;if(0===n)continue;const o=.1*n,s=Math.abs(e-r.startTime)<=o,u=Math.abs(t-r.endTime)<=o;if(s&&u)return a}}export function getLargeTimeUnitRange(e,t,r=0){const a=new Date(e),n=new Date(a),o=new Date(a),s=Math.floor(n.getFullYear()/t)*t+r*t;return n.setFullYear(s,0,1),n.setHours(0,0,0,0),o.setFullYear(s+t-1,11,31),o.setHours(23,59,59,999),{startTime:n.getTime(),endTime:o.getTime()}}export function formatDuration(t,r){const a=function(e){const t=e.split("-")[0].toLowerCase();return T[t]??T.en}(r??getDefaultLocale()),o="number"==typeof t?t:Array.isArray(t)?t[1]-t[0]:t.endTime-t.startTime,s=Math.floor(o/1e3),l=Math.floor(s/60),g=Math.floor(l/60),m=Math.floor(g/24),f=Math.floor(m/365),h=Math.floor(o%1e3),M=s%60,D=l%60,d=g%24,w=m%365,y=[];if(f>0&&y.push(`${f} ${f>1?a.year[1]:a.year[0]}`),f<1||w>Math.ceil(f/4))if(w%7==0&&0===d&&0===D&&0===M&&w>0&&o<e){const e=Math.floor(w/7);y.push(`${e} ${e>1?a.week[1]:a.week[0]}`)}else w>0&&o<e&&y.push(`${w} ${w>1?a.day[1]:a.day[0]}`),d>0&&o<c&&y.push(`${d}h`),D>0&&o<i&&y.push(`${D}m`),M>0&&o<n&&y.push(`${M}s`),o<5*u&&o>=1&&y.push(`${h}ms`),o<1&&y.push("<1ms");return y.join(" ")}export function formatDate(e,t,r){const a=new Date(e);return h(r,{day:t?"2-digit":"numeric",month:"short",year:"numeric"}).format(a)}export function formatDateTime(e,t){const r="number"==typeof e?new Date(e):e;return`${h(t,{weekday:"short",day:"2-digit",month:"short",year:"numeric"}).format(r)} ${formatTime(r.getTime())}`}export function formatDateWithWeekDay(e,t){const r="number"==typeof e?new Date(e):e;return h(t,{weekday:"short",day:"2-digit",month:"short",year:"numeric"}).format(r)}export function formatDateRange(e,t){const[r,a]=e,n=new Date(r),o=new Date(a),s=new Date(a-1),u=1===n.getDate()&&1===o.getDate(),i=u&&0===n.getMonth()&&0===o.getMonth(),c=h(t,{day:"2-digit",month:"short",year:"numeric"}),l=h(t,{month:"short",year:"numeric"}),g=h(t,{year:"numeric"});return n.getFullYear()===s.getFullYear()?n.getMonth()===s.getMonth()?n.getDate()===s.getDate()?c.format(s):u?l.format(s):c.formatRange(n,s):i?g.format(s):c.formatRange(n,s):i?g.formatRange(n,s):c.formatRange(n,s)}export function formatTime(e){const t=new Date(e),r=t.getHours(),a=t.getMinutes(),n=t.getSeconds();return(r<10?"0":"")+r+":"+(a<10?"0":"")+a+":"+(n<10?"0":"")+n}export function getTimePartsInHours(e){return[Math.floor(e/n),e%n]}export function splitTime3(e){const t=Math.floor(e/SPLIT_TIME_3_POW2),r=e%SPLIT_TIME_3_POW2;return[t,Math.floor(r/SPLIT_TIME_3),r%SPLIT_TIME_3]}export function splitTime2(e){return[Math.floor(e/SPLIT_PART_2),e%SPLIT_PART_2]}export function getDurationParts(e){return[Math.floor(e/a),e%a]}
@@ -1 +1 @@
1
- import{TimeSliderModel as e}from"./TimeSliderModel";import{timeRangesUnion as t}from"./TimeSliderRange";export class CompositeTimeSliderModel extends e{constructor(...e){super(),this.models=e,this.models.forEach(e=>e.on((e,t)=>{"added"===e&&this.emit("added",t),"updated"===e&&this.emit("updated",t),"removed"===e&&this.emit("removed",t)}))}get data(){return this.models.map(e=>e.data).flat()}get(e){return this.models.find(t=>t.get(e))?.get(e)}dataInTimeRange(e){return this.models.map(t=>t.dataInTimeRange(e)).flat()}dataInRange(e){return this.models.map(t=>t.dataInRange(e)).flat()}clear(){return this.models.forEach(e=>e.clear())}getTimeRange(){return this.models.map(e=>e.getTimeRange()).reduce((e,a)=>t(e,a))}}
1
+ import{TimeSliderModel as e}from"./TimeSliderModel.js";import{timeRangesUnion as t}from"./TimeSliderRange.js";export class CompositeTimeSliderModel extends e{constructor(...e){super(),this.models=e,this.models.forEach(e=>e.on((e,t)=>{"added"===e&&this.emit("added",t),"updated"===e&&this.emit("updated",t),"removed"===e&&this.emit("removed",t)}))}get data(){return this.models.map(e=>e.data).flat()}get(e){return this.models.find(t=>t.get(e))?.get(e)}dataInTimeRange(e){return this.models.map(t=>t.dataInTimeRange(e)).flat()}dataInRange(e){return this.models.map(t=>t.dataInRange(e)).flat()}clear(){return this.models.forEach(e=>e.clear())}getTimeRange(){return this.models.map(e=>e.getTimeRange()).reduce((e,a)=>t(e,a))}}
@@ -1 +1 @@
1
- import e from"rbush";import{getTimeArray as r,getValueArray as i}from"./TimeSliderElement";import{timeSliderRangeAsObject as t}from"./TimeSliderRange";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}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 +1 @@
1
- import{TimeSliderModel as r}from"./TimeSliderModel";export class TimeSliderIntervalsModel extends r{constructor(r){super(r)}}export function isTimeInterval(r){return Array.isArray(r.t)&&Array.isArray(r.v)}
1
+ import{TimeSliderModel as r}from"./TimeSliderModel.js";export class TimeSliderIntervalsModel extends r{constructor(r){super(r)}}export function isTimeInterval(r){return Array.isArray(r.t)&&Array.isArray(r.v)}
@@ -1 +1 @@
1
- import{IntervalLaneManager as e}from"./IntervalLaneManager";import{TimeSliderIntervalsModel as a}from"./TimeSliderIntervalsModel";export class TimeSliderLanesModel extends a{constructor(a){const n=new e;super(a?.map(e=>{n.add(e);const a=n.getLane(e.id)||0;return{...e,v:[a,a+1]}})),this.minMax=4,this.laneManager=n,this.on("removed",e=>this.laneManager.remove(e))}add(e){this.laneManager.add(e);const a=this.laneManager.getLane(e.id)||0,n={...e,v:[a,a+1]};super.add(n)}update(e,a){const n="string"==typeof e?e:e.id,t=this.get(n);if(t){this.laneManager.update({...t,...a});const e=this.laneManager.getLane(t.id)||0,r={...a};Array.isArray(t.v)&&e===t.v[0]||(r.v=[e,e+1]),super.update(n,r)}}}
1
+ import{IntervalLaneManager as e}from"./IntervalLaneManager.js";import{TimeSliderIntervalsModel as a}from"./TimeSliderIntervalsModel.js";export class TimeSliderLanesModel extends a{constructor(a){const n=new e;super(a?.map(e=>{n.add(e);const a=n.getLane(e.id)||0;return{...e,v:[a,a+1]}})),this.minMax=4,this.laneManager=n,this.on("removed",e=>this.laneManager.remove(e))}add(e){this.laneManager.add(e);const a=this.laneManager.getLane(e.id)||0,n={...e,v:[a,a+1]};super.add(n)}update(e,a){const n="string"==typeof e?e:e.id,t=this.get(n);if(t){this.laneManager.update({...t,...a});const e=this.laneManager.getLane(t.id)||0,r={...a};Array.isArray(t.v)&&e===t.v[0]||(r.v=[e,e+1]),super.update(n,r)}}}
@@ -1 +1 @@
1
- import{v4 as e}from"uuid";import{TypedEventEmitter as t}from"../event/TypedEventEmitter";import{TODAY as s}from"../ticks/TimeSliderConstants";import{TimeSliderBush as i}from"./TimeSliderBush";import{getTimeArray as h}from"./TimeSliderElement";import{timeSliderRangeAsObject as a}from"./TimeSliderRange";export class TimeSliderModel extends t{constructor(t){super(),this.id=e(),this.bush=new i,this.sortedCache=null,this.idToIndex=new Map,this.searchCacheRange=null,this.searchCache=null,this.visibleLayers=new Set,this.bush.load(t||[])}get data(){if(this.sortedCache)return this.sortedCache;{const e=this.bush.all().sort((e,t)=>{const[s]=h(e),[i]=h(t);return s-i});return this.sortedCache=e,this.idToIndex.clear(),e.forEach((e,t)=>this.idToIndex.set(e.id,t)),e}}clear(){this.bush.clear(),this.idToIndex.clear(),this.sortedCache=null,this.searchCache=null,this.emit("cleared")}getNeightbor(e,t){const s=this.data,i="string"==typeof e?e:e.id;if(s&&this.idToIndex.has(i)){const e=this.idToIndex.get(i)+Math.round(t);if(e>0&&e<s.length)return s[e]}}dataInTimeRange(e){const t="number"==typeof e?[e,e]:e,{startTime:s,endTime:i}=a(t);return this.searchCache&&this.searchCacheRange&&this.searchCacheRange.startTime==s&&this.searchCacheRange.endTime==i||(this.searchCache=this.bush.searchTime(t)),this.searchCache}dataInRange(e){return this.bush.searchRange(e)}toJSON(){return this.bush.toJSON()}add(e){Array.isArray(e.v)&&e.v[0]===e.v[1]&&e.v[0]>0&&console.warn(e),this.bush.add(e),this.sortedCache=null,this.searchCache=null,this.emit("added",e);const t=this.bush.get(e.id);Array.isArray(t.v)&&t.v[0]===t.v[1]&&t.v[0]>0&&console.warn({element:e,added:t})}remove(e){const t="string"==typeof e?e:e.id,s=this.bush.get(t);s&&(this.bush.remove(s),this.sortedCache=null,this.searchCache=null,this.emit("removed",s.id))}has(e){return this.bush.has(e)}get(e){return this.bush.get(e)}update(e,t){const s="string"==typeof e?e:e.id,i=this.bush.get(s);if(i){const e={...i};if("t"in t||"v"in t){this.bush.remove(i);const s={...i,...t};this.bush.add(s),this.sortedCache=null,this.searchCache=null,this.emit("updated",{id:i.id,update:t,previous:e,updated:s})}else{for(const e in t)i[e]=t[e];this.emit("updated",{id:i.id,update:t,previous:e,updated:i})}}}getTimeRange(){const e=this.data;if(0===e.length)return s;const t=h(e[0])[0],i=e[e.length-1],a=h(i)[1];return{startTime:t,endTime:a,duration:a-t}}getValueRange(e){if(e){let t=1/0,s=-1/0;const i=this.dataInTimeRange(e);for(const e of i)t=Math.min(t,"number"==typeof e.v?e.v:e.v[0]),s=Math.max(s,"number"==typeof e.v?e.v:e.v[1]);return"number"==typeof this.minMax&&s<this.minMax&&(s=this.minMax),"number"==typeof this.maxMin&&t>this.maxMin&&(t=this.maxMin),{minValue:t,maxValue:s}}{const e=this.bush.toJSON();return{minValue:e.minY,maxValue:e.maxY}}}get shouldLoad(){return this.visibleLayers.size>0}loaded(e,t){t&&!this.visibleLayers.has(e)?(this.visibleLayers.add(e),1===this.visibleLayers.size&&this.emit("loaded",!0)):this.visibleLayers.has(e)&&(this.visibleLayers.delete(e),0===this.visibleLayers.size&&this.emit("loaded",!1))}}
1
+ import{v4 as e}from"uuid";import{TypedEventEmitter as t}from"../event/TypedEventEmitter.js";import{TODAY as s}from"../ticks/TimeSliderConstants.js";import{TimeSliderBush as i}from"./TimeSliderBush.js";import{getTimeArray as h}from"./TimeSliderElement.js";import{timeSliderRangeAsObject as a}from"./TimeSliderRange.js";export class TimeSliderModel extends t{constructor(t){super(),this.id=e(),this.bush=new i,this.sortedCache=null,this.idToIndex=new Map,this.searchCacheRange=null,this.searchCache=null,this.visibleLayers=new Set,this.bush.load(t||[])}get data(){if(this.sortedCache)return this.sortedCache;{const e=this.bush.all().sort((e,t)=>{const[s]=h(e),[i]=h(t);return s-i});return this.sortedCache=e,this.idToIndex.clear(),e.forEach((e,t)=>this.idToIndex.set(e.id,t)),e}}clear(){this.bush.clear(),this.idToIndex.clear(),this.sortedCache=null,this.searchCache=null,this.emit("cleared")}getNeightbor(e,t){const s=this.data,i="string"==typeof e?e:e.id;if(s&&this.idToIndex.has(i)){const e=this.idToIndex.get(i)+Math.round(t);if(e>0&&e<s.length)return s[e]}}dataInTimeRange(e){const t="number"==typeof e?[e,e]:e,{startTime:s,endTime:i}=a(t);return this.searchCache&&this.searchCacheRange&&this.searchCacheRange.startTime==s&&this.searchCacheRange.endTime==i||(this.searchCache=this.bush.searchTime(t)),this.searchCache}dataInRange(e){return this.bush.searchRange(e)}toJSON(){return this.bush.toJSON()}add(e){Array.isArray(e.v)&&e.v[0]===e.v[1]&&e.v[0]>0&&console.warn(e),this.bush.add(e),this.sortedCache=null,this.searchCache=null,this.emit("added",e);const t=this.bush.get(e.id);Array.isArray(t.v)&&t.v[0]===t.v[1]&&t.v[0]>0&&console.warn({element:e,added:t})}remove(e){const t="string"==typeof e?e:e.id,s=this.bush.get(t);s&&(this.bush.remove(s),this.sortedCache=null,this.searchCache=null,this.emit("removed",s.id))}has(e){return this.bush.has(e)}get(e){return this.bush.get(e)}update(e,t){const s="string"==typeof e?e:e.id,i=this.bush.get(s);if(i){const e={...i};if("t"in t||"v"in t){this.bush.remove(i);const s={...i,...t};this.bush.add(s),this.sortedCache=null,this.searchCache=null,this.emit("updated",{id:i.id,update:t,previous:e,updated:s})}else{for(const e in t)i[e]=t[e];this.emit("updated",{id:i.id,update:t,previous:e,updated:i})}}}getTimeRange(){const e=this.data;if(0===e.length)return s;const t=h(e[0])[0],i=e[e.length-1],a=h(i)[1];return{startTime:t,endTime:a,duration:a-t}}getValueRange(e){if(e){let t=1/0,s=-1/0;const i=this.dataInTimeRange(e);for(const e of i)t=Math.min(t,"number"==typeof e.v?e.v:e.v[0]),s=Math.max(s,"number"==typeof e.v?e.v:e.v[1]);return"number"==typeof this.minMax&&s<this.minMax&&(s=this.minMax),"number"==typeof this.maxMin&&t>this.maxMin&&(t=this.maxMin),{minValue:t,maxValue:s}}{const e=this.bush.toJSON();return{minValue:e.minY,maxValue:e.maxY}}}get shouldLoad(){return this.visibleLayers.size>0}loaded(e,t){t&&!this.visibleLayers.has(e)?(this.visibleLayers.add(e),1===this.visibleLayers.size&&this.emit("loaded",!0)):this.visibleLayers.has(e)&&(this.visibleLayers.delete(e),0===this.visibleLayers.size&&this.emit("loaded",!1))}}
@@ -1 +1 @@
1
- import{TimeSliderModel as e}from"./TimeSliderModel";export class TimeSliderPointsModel extends e{constructor(e){super(e)}}export function isTimePoint(e){return"number"==typeof e.t&&"number"==typeof e.v}
1
+ import{TimeSliderModel as e}from"./TimeSliderModel.js";export class TimeSliderPointsModel extends e{constructor(e){super(e)}}export function isTimePoint(e){return"number"==typeof e.t&&"number"==typeof e.v}
@@ -18,6 +18,8 @@ export type TimeSliderValueRange = {
18
18
  export type TimeSliderRange = Expand<TimeSliderTimeRange & TimeSliderValueRange>;
19
19
  export type TimeSliderRangeWithDuration = Expand<TimeSliderTimeRangeWithDuration & TimeSliderValueRange>;
20
20
  export declare function timeRangesUnion(range1: TimeSliderTimeRange, range2: TimeSliderTimeRange): TimeSliderTimeRangeWithDuration;
21
+ /** Merges overlapping/touching ranges into a sorted, non-overlapping list. startTime/endTime may be -Infinity/Infinity for open-ended ranges. */
22
+ export declare function mergeTimeRanges(ranges: TimeSliderTimeRange[]): TimeSliderTimeRange[];
21
23
  export declare function timeRangesOverlap(range1: TimeSliderTimeRange, target: TimeSliderTimeRange | TimeSliderTimeRangeArray | number): TimeSliderTimeRangeWithDuration | undefined;
22
24
  export declare function timeRangeOverlaps(range: TimeSliderTimeRange, target: TimeSliderTimeRange | TimeSliderTimeRangeArray | number): boolean;
23
25
  export declare function addPadding(range: TimeSliderTimeRange, padding: number): TimeSliderTimeRangeWithDuration;
@@ -28,3 +30,9 @@ export declare function addDuration(range: TimeSliderTimeRange): {
28
30
  endTime: number;
29
31
  };
30
32
  export declare function applyTimeRangeUpdate(current: TimeSliderTimeRange, update: Partial<TimeSliderTimeRangeWithDuration>): TimeSliderTimeRangeWithDuration;
33
+ /**
34
+ * Keeps a range inside limits: a range wider than the limits becomes the
35
+ * limits, otherwise it is shifted (duration kept) so it no longer crosses an
36
+ * edge. Either limit may be -Infinity/Infinity for a one-sided limit.
37
+ */
38
+ export declare function clampTimeRange(range: TimeSliderTimeRange, limits: TimeSliderTimeRange): TimeSliderTimeRangeWithDuration;
@@ -1 +1 @@
1
- import{formatDuration as e}from"../common/TimeTools";export function timeSliderRangeAsObject(e){return Array.isArray(e)?{startTime:e[0],endTime:e[1]}:e}export function timeRangesUnion(e,t){const n=Math.min(e.startTime,t.startTime),r=Math.max(e.endTime,t.endTime);return{startTime:n,endTime:r,duration:r-n}}export function timeRangesOverlap(e,t){if("number"==typeof t)return timeRangeOverlaps(e,t)?{startTime:t,endTime:t,duration:0}:void 0;{const n=timeSliderRangeAsObject(t);if(timeRangeOverlaps(e,n)){const t=Math.max(e.startTime,n.startTime),r=Math.min(e.endTime,n.endTime);return{startTime:t,endTime:r,duration:r-t}}return}}export function timeRangeOverlaps(e,t){if("number"==typeof t)return e.startTime<=t&&t<=e.endTime;{const n=timeSliderRangeAsObject(t);return e.startTime<n.endTime&&n.startTime<e.endTime}}export function addPadding(e,t){const n=Math.min(1,Math.max(t,0)),r=e.endTime-e.startTime;return{startTime:e.startTime-n*r,endTime:e.endTime+n*r,duration:(1+2*n)*r}}export function formatRange(t){const n=Array.isArray(t)?t[0]:t.startTime,r=Array.isArray(t)?t[1]:t.endTime,i=r-n;return[new Date(n).toISOString(),e(i),new Date(r).toISOString()]}export function addDuration(e){const t=e.endTime-e.startTime;return{...e,duration:t}}export function applyTimeRangeUpdate(e,t){let n,r;const i=e.endTime-e.startTime;return"number"!=typeof t.duration||"number"==typeof t.startTime&&"number"==typeof t.endTime?(n="number"==typeof t.startTime?t.startTime:e.startTime,r="number"==typeof t.endTime?t.endTime:e.endTime):"number"==typeof t.startTime?(n=t.startTime,r=t.startTime+t.duration):"number"==typeof t.endTime?(n=t.endTime-t.duration,r=t.endTime):(n=e.startTime-.5*(t.duration-i),r=e.endTime+.5*(t.duration-i)),{startTime:n,endTime:r,duration:r-n}}
1
+ import{formatDuration as e}from"../common/TimeTools.js";export function timeSliderRangeAsObject(e){return Array.isArray(e)?{startTime:e[0],endTime:e[1]}:e}export function timeRangesUnion(e,t){const n=Math.min(e.startTime,t.startTime),i=Math.max(e.endTime,t.endTime);return{startTime:n,endTime:i,duration:i-n}}export function mergeTimeRanges(e){if(0===e.length)return[];const t=[...e].sort((e,t)=>e.startTime-t.startTime),n=[{...t[0]}];for(let e=1;e<t.length;e++){const i=n[n.length-1],r=t[e];r.startTime<=i.endTime?i.endTime=Math.max(i.endTime,r.endTime):n.push({...r})}return n}export function timeRangesOverlap(e,t){if("number"==typeof t)return timeRangeOverlaps(e,t)?{startTime:t,endTime:t,duration:0}:void 0;{const n=timeSliderRangeAsObject(t);if(timeRangeOverlaps(e,n)){const t=Math.max(e.startTime,n.startTime),i=Math.min(e.endTime,n.endTime);return{startTime:t,endTime:i,duration:i-t}}return}}export function timeRangeOverlaps(e,t){if("number"==typeof t)return e.startTime<=t&&t<=e.endTime;{const n=timeSliderRangeAsObject(t);return e.startTime<n.endTime&&n.startTime<e.endTime}}export function addPadding(e,t){const n=Math.min(1,Math.max(t,0)),i=e.endTime-e.startTime;return{startTime:e.startTime-n*i,endTime:e.endTime+n*i,duration:(1+2*n)*i}}export function formatRange(t){const n=Array.isArray(t)?t[0]:t.startTime,i=Array.isArray(t)?t[1]:t.endTime,r=i-n;return[new Date(n).toISOString(),e(r),new Date(i).toISOString()]}export function addDuration(e){const t=e.endTime-e.startTime;return{...e,duration:t}}export function applyTimeRangeUpdate(e,t){let n,i;const r=e.endTime-e.startTime;return"number"!=typeof t.duration||"number"==typeof t.startTime&&"number"==typeof t.endTime?(n="number"==typeof t.startTime?t.startTime:e.startTime,i="number"==typeof t.endTime?t.endTime:e.endTime):"number"==typeof t.startTime?(n=t.startTime,i=t.startTime+t.duration):"number"==typeof t.endTime?(n=t.endTime-t.duration,i=t.endTime):(n=e.startTime-.5*(t.duration-r),i=e.endTime+.5*(t.duration-r)),{startTime:n,endTime:i,duration:i-n}}export function clampTimeRange(e,t){const n=e.endTime-e.startTime;let i=e.startTime,r=e.endTime;return n>=t.endTime-t.startTime?(i=t.startTime,r=t.endTime):i<t.startTime?(i=t.startTime,r=t.startTime+n):r>t.endTime&&(i=t.endTime-n,r=t.endTime),{startTime:i,endTime:r,duration:r-i}}
@@ -1 +1 @@
1
- import{getTimeUnitInMs as t}from"../../common/TimeTools";import{TimeTicksBar as e}from"../../ticks/TimeTicksBar";import{timeRangeOverlaps as i}from"../TimeSliderRange";import{TimeSliderHistogram as s}from"./TimeSliderHistogram";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 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 +1 @@
1
- import{getTimeOffset as t,getTimeUnitRange as e}from"../../common/TimeTools";import{ONE_HOUR as i}from"../../ticks/TimeSliderConstants";import{TimeSliderHistogram as s}from"./TimeSliderHistogram";export class TimeSliderFixedHistogram extends s{constructor(t,e,s){super(t,e,s),this.model=t,this.content=e,this.elementClasifications=new Map,this.elementBoxRanges=new Map,this.classificationIndices=new Map,this.boxes=new Map,this.currentIntervals=new Set,this.maxEncountered=1e3,this.loggin=!1,this.loggin=s?.loggin||!1,this.time0=this.mode?.fixed?.start||Date.UTC(0,0,1,0,0,0,0),this.duration=this.mode?.fixed?.duration||i,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){this.maxValueCheckingInterval=setInterval(()=>{this.checkMaxValue()},1e3)}stopUpdating(){clearInterval(this.maxValueCheckingInterval),this.maxValueCheckingInterval=void 0}onOptionsChanged(t){if("classifier"===t){this.elementClasifications.clear(),this.classificationIndices.clear(),this.boxes.clear();const t=new Set(this.currentIntervals);this.currentIntervals.clear(),this.populate(),t.forEach(t=>{this.currentIntervals.has(t)||(this.loggin&&console.log("Turning invisible",t),this.model.update(t,{v:[0,0]}))})}}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||i;this.content.data.forEach(t=>this.addElement(t))}addElement(t){const e=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,e);const i=this.weighted?this.toSingleValue(t.v):1,s=this.classifier?this.classifier(t):void 0;null!==s&&(this.elementClasifications.set(t.id,s),this.forBoxRange(e,e=>{e.values.set(t.id,i),this.updateBoxInterval(e)},{create:!0,classification:s}))}updateElement(t){const e=this.classifier?this.classifier(t):void 0;if(null===e)this.removeElement(t.id);else{this.elementClasifications.set(t.id,e);const i=this.elementBoxRanges.get(t.id);if(i){const s=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,s);const n=[];for(let s=i[0];s<=i[1];s++){const i=this.getBox(s,e);i&&(i.values.delete(t.id),n.push(s))}const a=this.weighted?this.toSingleValue(t.v):1;for(let i=s[0];i<=s[1];i++){this.requireBox(i,e).values.set(t.id,a),n.push(i)}n.forEach(t=>{const i=this.getBox(t,e);i&&this.updateBoxInterval(i)})}else this.addElement(t)}}removeElement(t){const e=this.elementBoxRanges.get(t),i=this.elementClasifications.get(t);if(this.elementBoxRanges.delete(t),e)for(let s=e[0];s<=e[1];s++){const e=this.getBox(s,i);e&&(e.values.delete(t),this.updateBoxInterval(e))}}requireClassificationIndex(t){return this.classificationIndices.has(t||null)||this.classificationIndices.set(t||null,this.classificationIndices.size),this.classificationIndices.get(t||null)}getBox(t,e){if(this.boxes.has(t)){return this.boxes.get(t).get(this.requireClassificationIndex(e))}}getBoxIndex(e){return this.mode?.fixedUnit?t(this.time0,e,this.mode?.fixedUnit):Math.floor((e-this.time0)/this.duration)}getIntervalId(t){const e=this.requireClassificationIndex(t.classification);return t.index+"#"+e}getBoxRange(t){if("number"==typeof t){const e=this.getBoxIndex(t);return[e,e]}return t.map(this.getBoxIndex)}createBox(t,i){let s,n;if(this.mode?.fixedUnit){const{startTime:i,endTime:a}=e(this.time0,this.mode?.fixedUnit,t);s=i,n=a}else s=this.time0+t*this.duration,n=this.time0+t*this.duration+this.duration;const a=this.requireClassificationIndex(i),o=this.getIntervalId({index:t,classification:i});this.boxes.has(t)||this.boxes.set(t,new Map);const l=this.boxes.get(t);l.has(a)&&console.warn("Box already exists..");const r={index:t,classification:i,start:s,end:n,values:new Map};return l.set(a,r),i&&this.registerClassification(i),this.currentIntervals.add(o),this.model.has(o)?(this.loggin&&console.log("Reusing",o),this.model.update(o,{attributes:{classification:i}})):(this.loggin&&console.log("Creating",o),this.model.add({id:o,attributes:{classification:i},t:[s,n],v:[0,0]})),r}requireBox(t,e){const i=this.getBox(t,e);return i||this.createBox(t,e)}forBoxRange(t,e,i){const s=i?.classification;for(let n=t[0];n<=t[1];n++){const t=i?.create?this.requireBox(n,s):this.getBox(n,s);t&&e(t)}}getBoxValue(t){return this.weighted?Array.from(t.values.values()).reduce((t,e)=>t+e):t.values.size}updateBoxInterval(t){const e=this.getIntervalId(t),i=this.model.get(e),s=this.getBoxValue(t);if(i)if(this.classifier){let i=0;const n=this.classOrder.map(e=>{const i=this.getIntervalId({index:t.index,classification:e});if(this.currentIntervals.has(i)){const t=this.model.get(i);return{classification:e,value:t?t.v[1]-t.v[0]:void 0,id:i}}return null}).filter(t=>null!==t);n.forEach(e=>{e.classification===t.classification?i+=s:i+=e.value||0}),i>this.maxEncountered&&(this.maxEncountered=i+100);let a=0,o=!1;n.forEach(n=>{o?n.value&&(this.loggin&&console.log("- Shifting",n.id),this.model.update(n.id,{v:this.inverted?[this.maxEncountered-a-n.value,this.maxEncountered-a]:[a,a+n.value],attributes:{classification:n.classification,percentage:n.value/i}}),a+=n.value):n.classification===t.classification?(this.loggin&&console.log("- Setting value",e),this.model.update(e,{v:this.inverted?[this.maxEncountered-a-s,this.maxEncountered-a]:[a,a+s],attributes:{classification:n.classification,percentage:s/i}}),o=!0,a+=s):n.value&&(this.loggin&&console.log("- Percentage",n.id),this.model.update(n.id,{attributes:{classification:n.classification,percentage:n.value/i}}),a+=n.value)})}else this.loggin&&console.log("- Setting value (no classification)",e),this.model.update(e,{v:this.inverted?[this.maxEncountered-s,0]:[0,s]})}toSingleValue(t){return"number"==typeof t?t:.5*(t[0]+t[1])}}
1
+ import{getTimeOffset as t,getTimeUnitRange as e}from"../../common/TimeTools.js";import{ONE_HOUR as i}from"../../ticks/TimeSliderConstants.js";import{TimeSliderHistogram as s}from"./TimeSliderHistogram.js";export class TimeSliderFixedHistogram extends s{constructor(t,e,s){super(t,e,s),this.model=t,this.content=e,this.elementClasifications=new Map,this.elementBoxRanges=new Map,this.classificationIndices=new Map,this.boxes=new Map,this.currentIntervals=new Set,this.maxEncountered=1e3,this.loggin=!1,this.loggin=s?.loggin||!1,this.time0=this.mode?.fixed?.start||Date.UTC(0,0,1,0,0,0,0),this.duration=this.mode?.fixed?.duration||i,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){this.maxValueCheckingInterval=setInterval(()=>{this.checkMaxValue()},1e3)}stopUpdating(){clearInterval(this.maxValueCheckingInterval),this.maxValueCheckingInterval=void 0}onOptionsChanged(t){if("classifier"===t){this.elementClasifications.clear(),this.classificationIndices.clear(),this.boxes.clear();const t=new Set(this.currentIntervals);this.currentIntervals.clear(),this.populate(),t.forEach(t=>{this.currentIntervals.has(t)||(this.loggin&&console.log("Turning invisible",t),this.model.update(t,{v:[0,0]}))})}}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||i;this.content.data.forEach(t=>this.addElement(t))}addElement(t){const e=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,e);const i=this.weighted?this.toSingleValue(t.v):1,s=this.classifier?this.classifier(t):void 0;null!==s&&(this.elementClasifications.set(t.id,s),this.forBoxRange(e,e=>{e.values.set(t.id,i),this.updateBoxInterval(e)},{create:!0,classification:s}))}updateElement(t){const e=this.classifier?this.classifier(t):void 0;if(null===e)this.removeElement(t.id);else{this.elementClasifications.set(t.id,e);const i=this.elementBoxRanges.get(t.id);if(i){const s=this.getBoxRange(t.t);this.elementBoxRanges.set(t.id,s);const n=[];for(let s=i[0];s<=i[1];s++){const i=this.getBox(s,e);i&&(i.values.delete(t.id),n.push(s))}const a=this.weighted?this.toSingleValue(t.v):1;for(let i=s[0];i<=s[1];i++){this.requireBox(i,e).values.set(t.id,a),n.push(i)}n.forEach(t=>{const i=this.getBox(t,e);i&&this.updateBoxInterval(i)})}else this.addElement(t)}}removeElement(t){const e=this.elementBoxRanges.get(t),i=this.elementClasifications.get(t);if(this.elementBoxRanges.delete(t),e)for(let s=e[0];s<=e[1];s++){const e=this.getBox(s,i);e&&(e.values.delete(t),this.updateBoxInterval(e))}}requireClassificationIndex(t){return this.classificationIndices.has(t||null)||this.classificationIndices.set(t||null,this.classificationIndices.size),this.classificationIndices.get(t||null)}getBox(t,e){if(this.boxes.has(t)){return this.boxes.get(t).get(this.requireClassificationIndex(e))}}getBoxIndex(e){return this.mode?.fixedUnit?t(this.time0,e,this.mode?.fixedUnit):Math.floor((e-this.time0)/this.duration)}getIntervalId(t){const e=this.requireClassificationIndex(t.classification);return t.index+"#"+e}getBoxRange(t){if("number"==typeof t){const e=this.getBoxIndex(t);return[e,e]}return t.map(this.getBoxIndex)}createBox(t,i){let s,n;if(this.mode?.fixedUnit){const{startTime:i,endTime:a}=e(this.time0,this.mode?.fixedUnit,t);s=i,n=a}else s=this.time0+t*this.duration,n=this.time0+t*this.duration+this.duration;const a=this.requireClassificationIndex(i),o=this.getIntervalId({index:t,classification:i});this.boxes.has(t)||this.boxes.set(t,new Map);const l=this.boxes.get(t);l.has(a)&&console.warn("Box already exists..");const r={index:t,classification:i,start:s,end:n,values:new Map};return l.set(a,r),i&&this.registerClassification(i),this.currentIntervals.add(o),this.model.has(o)?(this.loggin&&console.log("Reusing",o),this.model.update(o,{attributes:{classification:i}})):(this.loggin&&console.log("Creating",o),this.model.add({id:o,attributes:{classification:i},t:[s,n],v:[0,0]})),r}requireBox(t,e){const i=this.getBox(t,e);return i||this.createBox(t,e)}forBoxRange(t,e,i){const s=i?.classification;for(let n=t[0];n<=t[1];n++){const t=i?.create?this.requireBox(n,s):this.getBox(n,s);t&&e(t)}}getBoxValue(t){return this.weighted?Array.from(t.values.values()).reduce((t,e)=>t+e):t.values.size}updateBoxInterval(t){const e=this.getIntervalId(t),i=this.model.get(e),s=this.getBoxValue(t);if(i)if(this.classifier){let i=0;const n=this.classOrder.map(e=>{const i=this.getIntervalId({index:t.index,classification:e});if(this.currentIntervals.has(i)){const t=this.model.get(i);return{classification:e,value:t?t.v[1]-t.v[0]:void 0,id:i}}return null}).filter(t=>null!==t);n.forEach(e=>{e.classification===t.classification?i+=s:i+=e.value||0}),i>this.maxEncountered&&(this.maxEncountered=i+100);let a=0,o=!1;n.forEach(n=>{o?n.value&&(this.loggin&&console.log("- Shifting",n.id),this.model.update(n.id,{v:this.inverted?[this.maxEncountered-a-n.value,this.maxEncountered-a]:[a,a+n.value],attributes:{classification:n.classification,percentage:n.value/i}}),a+=n.value):n.classification===t.classification?(this.loggin&&console.log("- Setting value",e),this.model.update(e,{v:this.inverted?[this.maxEncountered-a-s,this.maxEncountered-a]:[a,a+s],attributes:{classification:n.classification,percentage:s/i}}),o=!0,a+=s):n.value&&(this.loggin&&console.log("- Percentage",n.id),this.model.update(n.id,{attributes:{classification:n.classification,percentage:n.value/i}}),a+=n.value)})}else this.loggin&&console.log("- Setting value (no classification)",e),this.model.update(e,{v:this.inverted?[this.maxEncountered-s,0]:[0,s]})}toSingleValue(t){return"number"==typeof t?t:.5*(t[0]+t[1])}}
@@ -1 +1 @@
1
- import{Disposables as e}from"../../common/Disposables";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")}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 +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}}
1
+ import{getTimeOffset as t,getTimeUnitRange as e}from"../../common/TimeTools.js";import{ONE_HOUR as s}from"../../ticks/TimeSliderConstants.js";import{TimeSliderHistogram as i}from"./TimeSliderHistogram.js";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}}
package/demo/Common.d.ts CHANGED
@@ -5,8 +5,10 @@ import { TimeSliderPointsModel } from "../data/TimeSliderPointsModel";
5
5
  import { TimeSliderHistogramLayer, TimeSliderHistogramLayerOptions } from "../layer/TimeSliderHistogramLayer";
6
6
  import { TimeSliderIntervalsLayer, TimeSliderIntervalsLayerOptions } from "../layer/TimeSliderIntervalsLayer";
7
7
  import { TimeSliderPointsLayer, TimeSliderPointsLayerOptions } from "../layer/TimeSliderPointsLayer";
8
+ /** Where the demo data sets load their files from (the demo serves them next to its page) */
9
+ export declare const DEMO_DATA_URL = "./resources/data/";
8
10
  export declare function createDemoPointsLayer(model: TimeSliderPointsModel, options?: TimeSliderPointsLayerOptions): TimeSliderPointsLayer;
9
- export declare function createDemoIntervalsLayer(model: TimeSliderIntervalsModel, options?: TimeSliderIntervalsLayerOptions): TimeSliderIntervalsLayer<import("../data/TimeSliderElement").TimeSliderInterval<any>, {
11
+ export declare function createDemoIntervalsLayer(model: TimeSliderIntervalsModel, options?: TimeSliderIntervalsLayerOptions): TimeSliderIntervalsLayer<import("..").TimeSliderInterval<any>, {
10
12
  fill?: {
11
13
  color?: string;
12
14
  opacity?: number;
@@ -16,6 +18,8 @@ export declare function createDemoIntervalsLayer(model: TimeSliderIntervalsModel
16
18
  color?: string;
17
19
  opacity?: number;
18
20
  width?: number;
21
+ sides?: "all" | "vertical";
22
+ smoothing?: number;
19
23
  };
20
24
  }>;
21
25
  export declare function createDemoHistogramLayer(models: TimeSliderModel<any>[], options?: TimeSliderHistogramLayerOptions): TimeSliderHistogramLayer<CompositeTimeSliderModel | TimeSliderModel<any>>;
package/demo/Common.js CHANGED
@@ -1 +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}})}
1
+ import{CompositeTimeSliderModel as e}from"../data/CompositeTimeSliderModel.js";import{TimeSliderHistogramLayer as r}from"../layer/TimeSliderHistogramLayer.js";import{TimeSliderIntervalsLayer as o}from"../layer/TimeSliderIntervalsLayer.js";import{TimeSliderPointsLayer as t}from"../layer/TimeSliderPointsLayer.js";export const DEMO_DATA_URL="./resources/data/";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}})}
package/demo/Metrics.d.ts CHANGED
@@ -1,2 +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>>)[][];
1
+ export declare const METRICS_SINGLE_LAYERS: (import("..").TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[];
2
+ export declare const METRICS_MULTI_LAYERS: (import("..").TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[][];
package/demo/Metrics.js CHANGED
@@ -1 +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})]];
1
+ import{v4 as o}from"uuid";import{TimeSliderPointsModel as e}from"../data/TimeSliderPointsModel.js";import{createDemoHistogramLayer as n,createDemoPointsLayer as t}from"./Common.js";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})]];
package/demo/Nasdaq.d.ts CHANGED
@@ -1,3 +1,6 @@
1
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[][];
2
+ /** The stock prices of six Nasdaq companies, loaded from <dataUrl><company>.csv */
3
+ export declare function createNasdaqDemo(dataUrl?: string): {
4
+ single: (TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[];
5
+ multiple: TimeSliderPointsLayer[][];
6
+ };
package/demo/Nasdaq.js CHANGED
@@ -1 +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")}`}
1
+ import{v4 as e}from"uuid";import{TimeSliderPointsModel as t}from"../data/TimeSliderPointsModel.js";import{TimeSliderPointsLayer as a}from"../layer/TimeSliderPointsLayer.js";import{createDemoHistogramLayer as r,DEMO_DATA_URL as o}from"./Common.js";const n=[{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"}];export function createNasdaqDemo(l=o){const c=n.map(r=>{const o=function(a,r){const o=new t;return o.name=a,fetch(r+a.toLowerCase()+".csv").then(e=>e.text()).then(t=>{const r=t.split("\n");let n=1/0,i=-1/0;const l=[];for(let t=1;t<r.length;t++){const o=r[t];if(o.length>20){const[t,r]=o.split(","),c=parseFloat(r.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+" "+r,id:e()})}}l.forEach(e=>{e.v=100*(e.v-n)/(i-n),o.add(e)})}),o}(r.name,l),n=r.color,c={area:{color:"Apple"===r.name?"#ccc":i(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:{...c,area:{...c.area,height:.05,opacity:.5}}}),multiLayer:new a(o,{style:{...c,area:{...c.area,base:!0,opacity:1}}})}}),s=r(c.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=>n.find(t=>t.name===e.name?.split(" ")[0])?.name,styler:e=>{const t=n.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))+"%"});return{single:[...c.map(e=>e.layer),s],multiple:c.map(e=>[e.multiLayer])}}function i(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")}`}
package/demo/Quakes.d.ts CHANGED
@@ -1,3 +1,6 @@
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>>)[][];
1
+ /** Earthquakes and ocean temperatures, loaded from <dataUrl>quakes.json and <dataUrl>temperature.json */
2
+ export declare function createQuakesDemo(dataUrl?: string): {
3
+ single: (import("..").TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[];
4
+ multiple: (import("..").TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[][];
5
+ histogramLayer: import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>;
6
+ };
package/demo/Quakes.js CHANGED
@@ -1 +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}
1
+ import{v4 as e}from"uuid";import{getTimeUnitRange as t}from"../common/TimeTools.js";import{TimeSliderPointsModel as a}from"../data/TimeSliderPointsModel.js";import{getMagnitudeColors as o,getMagnitudeColors2 as r,getUltraFadedMagnitudeColors as n}from"../style/TimeSliderColors.js";import{createDemoHistogramLayer as i,createDemoPointsLayer as s,DEMO_DATA_URL as l}from"./Common.js";export function createQuakesDemo(t=l){const c=function(t){const o=new a;o.name="Quakes";let r=9999;return fetch(t+"quakes.json").then(e=>e.json()).then(t=>{t.features.forEach(t=>{const a=t.properties.mag,n=4+24*(a-6),i=t.geometry?.coordinates[2]||0;r=Math.min(r,i);const s={id:e(),t:t.properties.time,v:n,attributes:{depth:i,mag:a},name:t.properties.title};o.add(s)}),console.log({min:r})}),o}(t),d=m("global_anomaly",t),p=m("ocean_anomaly",t),u={area:{color:"#0fd",height:.2,opacity:1},line:{color:"#000",border:{color:"#0df"}},point:void 0},f=Array.from({length:10},(e,t)=>t.toString()),h=i([c],{min:0,max:.3,style:{inverted:!1,mode:{fixedUnit:"month"},classOrder:f},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(),...n()],labeler:e=>`Depth -${68.8*parseInt(e.attributes?.classification||"0")}m`});return{single:[s(p,{min:.8,max:1,style:u}),s(c,{min:.3,max:.8,style:{line:void 0,area:void 0}}),h],multiple:[[i([c],{min:.8,style:{mode:{autoUnits:!0},classOrder:f},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)}`}}),s(c,{max:.8,style:{line:void 0,area:void 0}})],[s(p,{style:u}),s(d,{style:{point:void 0,area:{color:"#df0",height:.2,opacity:1}}})]],histogramLayer:h}}function m(o,r){const n=new a;switch(o){case"global_temp_abs":n.name="Global Temperature";break;case"global_anomaly":n.name="Global Temperature Anomaly";break;case"ocean_temp_abs":n.name="Ocean Temperature";break;case"ocean_anomaly":n.name="Ocean Temperature Anomaly"}return fetch(r+"temperature.json").then(e=>e.json()).then(a=>{a.forEach(a=>{const r=a[o];if(null!==r){const i=new Date,[s,l]=a.date.split("-").map(e=>parseInt(e));i.setFullYear(s),i.setMonth(l-1),i.setDate(10);const m=t(i.getTime(),"month"),c=o.includes("abs")?10*(r-10):40*r+50,d={id:e(),t:.5*(m.startTime+m.endTime),v:c,name:a.date};n.add(d)}})}),n}
@@ -1,3 +1,5 @@
1
- export declare function QuakesFilters({ darkMode }: {
1
+ import { TimeSliderHistogramLayer } from "../layer/TimeSliderHistogramLayer";
2
+ export declare function QuakesFilters({ darkMode, histogramLayer: quakesHistogramLayer }: {
2
3
  darkMode: boolean;
4
+ histogramLayer: TimeSliderHistogramLayer;
3
5
  }): JSX.Element;
@@ -1 +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})))}
1
+ import t,{useEffect as e,useState as a}from"react";import{MaterialTextButton as n}from"../react/MaterialTextButton.js";const r=Array.from({length:10},(t,e)=>e.toString());function i(t,e){return Math.min(e.length-1,Math.max(0,Math.round(t)))}export function QuakesFilters({darkMode:o,histogramLayer:s}){const[m,l]=a(0),[c,p]=a(6),[u,g]=a("mag");return e(()=>{const t=t=>t.attributes.mag>c&&t.attributes.depth>m?0:10;s.histogram.classifier="mag"===u?e=>i(2.5*(e.attributes.mag-6),r)+t(e)+"":e=>i(e.attributes.depth/68.8,r)+t(e)+"",s.labeler="mag"===u?(t,e,a)=>{const n=s.getClassification(t,a),r=6+.4*parseInt(n||"0"),i=r+.4;return`Mag ${r.toFixed(1)}-${i.toFixed(1)}`}:(t,e,a)=>{const n=s.getClassification(t,a);return`Depth -${68.8*parseInt(n||"0")}m`}},[m,c,u,s]),t.createElement("div",{style:{zIndex:999,position:"absolute",inset:"88px 16px 16px",pointerEvents:"none"}},t.createElement("div",{className:"select-container",style:{backgroundColor:o?"#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:c,onChange:t=>p(Number(t.target.value))}),t.createElement(n,{text:"Random",onClick:()=>g("mag"),active:"mag"===u}),t.createElement(n,{text:"Magnitude",onClick:()=>g("depth"),active:"depth"===u})))}
package/demo/Random.d.ts CHANGED
@@ -1,38 +1,48 @@
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>>)[])[];
1
+ /** Random live measurements and tracks, simulated until stop() is called */
2
+ export declare function createRandomDemo(): {
3
+ single: (import("..").TimeSliderPointsLayer | import("..").TimeSliderIntervalsLayer<import("..").TimeSliderInterval<any>, {
4
+ fill?: {
5
+ color?: string;
6
+ opacity?: number;
7
+ };
8
+ border?: {
9
+ centered?: boolean;
10
+ color?: string;
11
+ opacity?: number;
12
+ width?: number;
13
+ sides?: "all" | "vertical";
14
+ smoothing?: number;
15
+ };
16
+ }> | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[];
17
+ multiple: ((import("..").TimeSliderPointsLayer | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[] | (import("..").TimeSliderPointsLayer | import("..").TimeSliderIntervalsLayer<import("..").TimeSliderInterval<any>, {
18
+ fill?: {
19
+ color?: string;
20
+ opacity?: number;
21
+ };
22
+ border?: {
23
+ centered?: boolean;
24
+ color?: string;
25
+ opacity?: number;
26
+ width?: number;
27
+ sides?: "all" | "vertical";
28
+ smoothing?: number;
29
+ };
30
+ }>)[] | (import("..").TimeSliderIntervalsLayer<import("..").TimeSliderInterval<any>, {
31
+ fill?: {
32
+ color?: string;
33
+ opacity?: number;
34
+ };
35
+ border?: {
36
+ centered?: boolean;
37
+ color?: string;
38
+ opacity?: number;
39
+ width?: number;
40
+ sides?: "all" | "vertical";
41
+ smoothing?: number;
42
+ };
43
+ }> | import("..").TimeSliderHistogramLayer<import("..").CompositeTimeSliderModel | import("..").TimeSliderModel<any>>)[])[];
44
+ stop: () => void;
45
+ };
36
46
  export declare function getDistinctColors(): string[];
37
47
  export declare function invertColor(color: string, opacity?: number): string;
38
48
  export declare function parseColor(color: string): [number, number, number];