@mappedin/marker-cluster 6.0.1-beta.41 → 6.0.1-beta.42

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.
@@ -0,0 +1,249 @@
1
+ // Generated by dts-bundle v0.7.3
2
+ // Dependencies for this module:
3
+ // ../marker-cluster/@mappedin/mappedin-js
4
+ // ../marker-cluster/rbush
5
+
6
+ declare module '@mappedin/marker-cluster' {
7
+ /**
8
+ * Main entry point for the marker cluster package.
9
+ */
10
+ export { MarkerCluster } from '@mappedin/marker-cluster/marker-cluster/src/marker-cluster';
11
+ /**
12
+ * Utility types for working with this package.
13
+ */
14
+ export type { ClusterInformation, ClusterFn } from '@mappedin/marker-cluster/marker-cluster/src/types/misc';
15
+ export type { IClusterAlgorithm, OptionsOf } from '@mappedin/marker-cluster/marker-cluster/src/types/algorithm';
16
+ export type { MarkerClusterOptions } from '@mappedin/marker-cluster/marker-cluster/src/types/options';
17
+ /**
18
+ * Extra utilities for building custom algorithms.
19
+ */
20
+ export { ScreenDistanceClustering, type ScreenDistanceClusteringOptions, } from '@mappedin/marker-cluster/marker-cluster/src/algorithms/screen-distance-clustering';
21
+ export { PointRBush } from '@mappedin/marker-cluster/marker-cluster/src/utils/point-rbush';
22
+ }
23
+
24
+ declare module '@mappedin/marker-cluster/marker-cluster/src/marker-cluster' {
25
+ import type { MapView, Marker } from '@mappedin/mappedin-js';
26
+ import type { MarkerClusterOptions } from '@mappedin/marker-cluster/marker-cluster/src/types/options';
27
+ import type { ClusterInformation, ClusterFn } from '@mappedin/marker-cluster/marker-cluster/src/types/misc';
28
+ import type { IClusterAlgorithm } from '@mappedin/marker-cluster/marker-cluster/src/types/algorithm';
29
+ import { ScreenDistanceClustering } from '@mappedin/marker-cluster/marker-cluster/src/algorithms/screen-distance-clustering';
30
+ /**
31
+ * A class that groups together {@link Marker} objects that are close to each other.
32
+ */
33
+ export class MarkerCluster<Algorithm extends IClusterAlgorithm = ScreenDistanceClustering> {
34
+ #private;
35
+ readonly id: string;
36
+ /**
37
+ * Create a new {@link MarkerCluster}.
38
+ *
39
+ * @param mapView - A {@link MapView} object.
40
+ * @param clusterMarkerFn - A function that accepts accepts {@link ClusterInformation} and returns a cluster {@link Marker} representing multiple contained within the cluster.
41
+ * @param options - Optional {@link MarkerClusterOptions} for controlling the clustering behavior.
42
+ *
43
+ * Example:
44
+ * ```ts
45
+ * const mapView = show3dMap(...);
46
+ *
47
+ * const markers = new Array(100).fill(0).map((_, i) => mapView.Markers.add(new Coordinate(...), i.toString(), { rank: 'always-visible' }));
48
+ *
49
+ * const cluster = new MarkerCluster(mapView, ({ markers, center }) =>
50
+ * mapView.Markers.add(center, markers.length.toString(), { rank: 'always-visible' }),
51
+ * );
52
+ * ```
53
+ */
54
+ constructor(mapView: MapView, clusterMarkerFn: ClusterFn, options?: MarkerClusterOptions<Algorithm>);
55
+ /**
56
+ * An array of {@link ClusterInformation} objects representing all unique clusters of markers.
57
+ */
58
+ get clusters(): ClusterInformation[];
59
+ /**
60
+ * Add an existing {@link Marker} to the cluster.
61
+ */
62
+ add: (marker: Marker) => void;
63
+ /**
64
+ * Remove an existing {@link Marker} from the cluster.
65
+ */
66
+ remove: (marker: Marker) => void;
67
+ /**
68
+ * Check if a {@link Marker} is in the cluster.
69
+ */
70
+ has: (marker: Marker) => boolean;
71
+ destroy: () => void;
72
+ }
73
+ }
74
+
75
+ declare module '@mappedin/marker-cluster/marker-cluster/src/types/misc' {
76
+ import type { Coordinate, Marker } from '@mappedin/mappedin-js';
77
+ /**
78
+ * A point in screen space associated with a {@link Marker}.
79
+ */
80
+ export type MarkerPoint = {
81
+ x: number;
82
+ y: number;
83
+ markerId: string;
84
+ };
85
+ /**
86
+ * Information about a group of {@link Marker}s that are close to each other.
87
+ */
88
+ export type ClusterInformation = {
89
+ id: string;
90
+ markers: Marker[];
91
+ center: Coordinate;
92
+ };
93
+ /**
94
+ * A function that executes on a new cluster of markers.
95
+ *
96
+ * @param cluster - A {@link ClusterInformation} object containing the markers that are part of the cluster.
97
+ * @returns A {@link Marker} to display for the cluster. Returns null if no marker should be displayed.
98
+ */
99
+ export type ClusterFn = (cluster: ClusterInformation) => Marker | null;
100
+ }
101
+
102
+ declare module '@mappedin/marker-cluster/marker-cluster/src/types/algorithm' {
103
+ import type { Marker } from '@mappedin/mappedin-js';
104
+ /**
105
+ * A algorithm that accepts an array of {@link Marker} objects and returns 2D array of clusters.
106
+ */
107
+ export interface IClusterAlgorithm<AlgorithmOptions extends Record<string, unknown> = Record<string, unknown>> {
108
+ /**
109
+ * Set the options for the clustering algorithm.
110
+ */
111
+ setOptions(options: AlgorithmOptions): void;
112
+ /**
113
+ * Set the {@link Marker}s that should be considered for clustering.
114
+ */
115
+ load(markers: Marker[]): void;
116
+ /**
117
+ * Get a 2D array of {@link Marker}s that are close to each other.
118
+ */
119
+ getClusters(): Marker[][];
120
+ /**
121
+ * Destroy the algorithm and free up resources.
122
+ */
123
+ destroy(): void;
124
+ }
125
+ /**
126
+ * Get the options type for a {@link IClusterAlgorithm}.
127
+ */
128
+ export type OptionsOf<Algorithm extends IClusterAlgorithm> = Algorithm extends IClusterAlgorithm<infer Options> ? Options : never;
129
+ }
130
+
131
+ declare module '@mappedin/marker-cluster/marker-cluster/src/types/options' {
132
+ import type { Floor } from '@mappedin/mappedin-js';
133
+ import type { IClusterAlgorithm, OptionsOf } from '@mappedin/marker-cluster/marker-cluster/src/types/algorithm';
134
+ import type { ScreenDistanceClustering } from '@mappedin/marker-cluster/marker-cluster/src/algorithms/screen-distance-clustering';
135
+ /**
136
+ * Options for a {@link MarkerCluster}.
137
+ */
138
+ export type MarkerClusterOptions<Algorithm extends IClusterAlgorithm = ScreenDistanceClustering> = Partial<{
139
+ /**
140
+ * The floor the clustered marker is on. If unspecified, the floor of the first added marker will be used.
141
+ */
142
+ floor: Floor | null;
143
+ /**
144
+ * The minimum number of markers in a cluster.
145
+ *
146
+ * @default 2
147
+ */
148
+ minSize: number;
149
+ /**
150
+ * The debounce time in milliseconds for computing clusters when the camera is moving. If set to 0, the clusters will
151
+ * be computed on every camera frame. This could lead to performance issues if there are a lot of markers.
152
+ *
153
+ * @default 50
154
+ */
155
+ debounce: number;
156
+ /**
157
+ * Whether the original markers should be hidden when clustered together.
158
+ *
159
+ * @default true
160
+ */
161
+ hideClusteredMarkers: boolean;
162
+ /**
163
+ * A custom algorithm to use for clustering.
164
+ *
165
+ * @default ScreenDistanceClustering
166
+ */
167
+ algorithm: Algorithm;
168
+ /**
169
+ * Options for the algorithm.
170
+ */
171
+ algorithmOptions: OptionsOf<Algorithm>;
172
+ /**
173
+ * @hidden
174
+ * @internal
175
+ */
176
+ debug: boolean;
177
+ }>;
178
+ }
179
+
180
+ declare module '@mappedin/marker-cluster/marker-cluster/src/algorithms/screen-distance-clustering' {
181
+ import type { Marker, MapView } from '@mappedin/mappedin-js';
182
+ import type { IClusterAlgorithm } from '@mappedin/marker-cluster/marker-cluster/src/types/algorithm';
183
+ /**
184
+ * Options for the {@link ScreenDistanceClustering} algorithm.
185
+ */
186
+ export type ScreenDistanceClusteringOptions = Partial<{
187
+ /**
188
+ * The distance in pixels that a marker should be from another marker to be considered part of the same cluster.
189
+ */
190
+ threshold: number;
191
+ }>;
192
+ /**
193
+ * Cluster {@link Marker}s that are close together on screen.
194
+ */
195
+ export class ScreenDistanceClustering implements IClusterAlgorithm<ScreenDistanceClusteringOptions> {
196
+ #private;
197
+ /**
198
+ * Create a new {@link ScreenDistanceClustering} instance.
199
+ *
200
+ * @param mapView - The {@link MapView} instance.
201
+ */
202
+ constructor(mapView: MapView);
203
+ setOptions(options: ScreenDistanceClusteringOptions): void;
204
+ load(markers: Marker[]): void;
205
+ getClusters(): Marker[][];
206
+ destroy(): void;
207
+ }
208
+ }
209
+
210
+ declare module '@mappedin/marker-cluster/marker-cluster/src/utils/point-rbush' {
211
+ import RBush from 'rbush';
212
+ /**
213
+ * An extension of RBush that works for XY points. This implementation also lets you
214
+ * `peak` at an arbitrary point in the tree.
215
+ */
216
+ export class PointRBush<Point extends {
217
+ x: number;
218
+ y: number;
219
+ }> extends RBush<Point> {
220
+ #private;
221
+ get size(): number;
222
+ load: (items: Point[]) => RBush<Point>;
223
+ insert: (item: Point) => RBush<Point>;
224
+ remove: (item: Point) => RBush<Point>;
225
+ clear: () => RBush<Point>;
226
+ /**
227
+ * Look at an arbitrary item.
228
+ */
229
+ peek: () => any;
230
+ /**
231
+ * Check if an item is in the tree.
232
+ */
233
+ has: (item: Point) => boolean;
234
+ /**
235
+ * Find an item in the tree that matches the predicate.
236
+ */
237
+ find: (predicate: (item: Point) => boolean) => Point | undefined;
238
+ toBBox: (item: Point) => {
239
+ minX: number;
240
+ minY: number;
241
+ maxX: number;
242
+ maxY: number;
243
+ };
244
+ compareMinX: (a: Point, b: Point) => number;
245
+ compareMinY: (a: Point, b: Point) => number;
246
+ equals: (a: Point, b: Point) => boolean;
247
+ }
248
+ }
249
+
@@ -0,0 +1 @@
1
+ var et=Object.defineProperty;var rt=n=>{throw TypeError(n)};var ct=(n,t,r)=>t in n?et(n,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[t]=r;var i=(n,t)=>et(n,"name",{value:t,configurable:!0});var d=(n,t,r)=>ct(n,typeof t!="symbol"?t+"":t,r),st=(n,t,r)=>t.has(n)||rt("Cannot "+r);var e=(n,t,r)=>(st(n,t,"read from private field"),r?r.call(n):t.get(n)),a=(n,t,r)=>t.has(n)?rt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(n):t.set(n,r),f=(n,t,r,s)=>(st(n,t,"write to private field"),s?s.call(n,r):t.set(n,r),r);var h={env:{NODE_ENV:"production",npm_package_version:"6.0.1-beta.42"}};var S="[MappedinJS]";var mt={logState:h.env.NODE_ENV==="test"?3:0,log(...n){this.logState<=0&&console.log(S,...n)},warn(...n){this.logState<=1&&console.warn(S,...n)},error(...n){this.logState<=2&&console.error(S,...n)},assert(...n){console.assert(...n)},time(n){console.time(n)},timeEnd(n){console.timeEnd(n)},throw(n,t){throw new Error("".concat(S," ").concat(n),t)}},G=mt;var X=class X extends Error{};i(X,"InvalidTokenError");var q=X;q.prototype.name="InvalidTokenError";function nt(n,t,r=!1){let s=null,o=0;return function(...l){o++,o===1&&r===!0&&n(...l);let m=i(()=>{(!r||o>1)&&n(...l),s=null,o=0},"later");clearTimeout(s),s=setTimeout(m,t)}}i(nt,"debounce");var H=[0,4,6,8,10],W=i(()=>{let n=new Array(16).fill(0),t=Math.random()*4294967296;for(let s=0;s<n.length;s++)s>0&&(s&3)===0&&(t=Math.random()*4294967296),n[s]=t>>>((s&3)<<3)&255;let r=n.map(s=>s.toString(16).padStart(2,"0"));return r[6]="4"+r[6][1],r[8]=["8","9","a","b"].includes(r[7][0])?r[7]:"a"+r[7][1],H.map((s,o)=>r.slice(s,o===H.length-1?void 0:H[o+1]).join("")).join("-")},"randomId");var L=["red","blue","green","purple","orange","pink","brown","gray","black","magenta","cyan","silver","maroon","teal","aqua"],it=i((n,t,r)=>'<div style="background-color:'.concat(t,";color:white;width:").concat(r,"px;height:").concat(r,"px;border-radius:50%;text-align:center;line-height:").concat(r,"px;border:1px solid white;font-size:").concat(Math.floor(r*.7),'px;">').concat(n,"</div>"),"debugMarkerFn");import{Coordinate as ot}from"@mappedin/mappedin-js";var _=i(n=>parseFloat(n.toFixed(8)),"trimCoordValue"),at=i((n,t)=>{if(n.length===0)return new ot({latitude:0,longitude:0});let r=n.reduce((o,l)=>o+l.latitude,0)/n.length,s=n.reduce((o,l)=>o+l.longitude,0)/n.length;return new ot({latitude:_(r),longitude:_(s),floorId:t!=null?t:n[0].floorId})},"averageCoords"),ut=i((n,t)=>n.length===0?"":[...n.map(r=>r.id).sort(),_(t.latitude),_(t.longitude),t.floorId].filter(r=>r!=null).join("-"),"getClusterId"),lt=i((n,t)=>{if(t<=0)throw new Error("Buffer must be greater than 0");return{minX:n.x-t/2,minY:n.y-t/2,maxX:n.x+t/2,maxY:n.y+t/2}},"bufferPoint");import ft from"rbush";var B=i(n=>"".concat(n.x,",").concat(n.y),"serializePoint"),g,Z=class Z extends ft{constructor(){super(...arguments);a(this,g,new Map);d(this,"load",i(r=>{for(let s of r)e(this,g).set(B(s),s);return super.load(r)},"load"));d(this,"insert",i(r=>(e(this,g).set(B(r),r),super.insert(r)),"insert"));d(this,"remove",i(r=>(e(this,g).delete(B(r)),super.remove(r)),"remove"));d(this,"clear",i(()=>(e(this,g).clear(),super.clear()),"clear"));d(this,"peek",i(()=>e(this,g).values().next().value,"peek"));d(this,"has",i(r=>e(this,g).has(B(r)),"has"));d(this,"find",i(r=>{for(let s of e(this,g).values())if(r(s))return s},"find"));d(this,"toBBox",i(r=>({minX:r.x,minY:r.y,maxX:r.x,maxY:r.y}),"toBBox"));d(this,"compareMinX",i((r,s)=>r.x-s.x,"compareMinX"));d(this,"compareMinY",i((r,s)=>r.y-s.y,"compareMinY"));d(this,"equals",i((r,s)=>r.x===s.x&&r.y===s.y,"equals"))}get size(){return e(this,g).size}};g=new WeakMap,i(Z,"PointRBush");var w=Z;var N,b,M,y,x,V,R,Q=class Q{constructor(t){a(this,N);a(this,b,{threshold:100});a(this,M,new w);a(this,y,new Map);a(this,x,[]);a(this,V,i(()=>[...e(this,y).values()].map(t=>({...e(this,N).getScreenCoordinateFromCoordinate(t.target.anchorTarget),markerId:t.id})),"#getScreenCoordinates"));a(this,R,i(t=>{let r=[t];e(this,M).remove(t);let s=e(this,M).search(lt(t,e(this,b).threshold));if(s.length===0)return r;r.push(...s);for(let o of s)e(this,M).remove(o);return r},"#resolveNeighbours"));f(this,N,t)}setOptions(t){if(t.threshold!=null&&t.threshold<=0)throw new Error("Cluster threshold must be greater than 0");f(this,b,{...e(this,b),...t})}load(t){e(this,y).clear();for(let r of t)e(this,y).set(r.id,r)}getClusters(){var l;let t=e(this,V).call(this);e(this,M).clear(),e(this,M).load(t);let r=e(this,M),s=[],o=[];for(;r.size>0;){let m=(l=r.find(k=>e(this,x).includes(k)))!=null?l:r.peek();if(m==null)break;o.push(m);let dt=e(this,R).call(this,m).map(k=>e(this,y).get(k.markerId)).filter(k=>k!=null);s.push(dt)}return f(this,x,o),s}destroy(){e(this,y).clear(),e(this,M).clear(),f(this,x,[])}};N=new WeakMap,b=new WeakMap,M=new WeakMap,y=new WeakMap,x=new WeakMap,V=new WeakMap,R=new WeakMap,i(Q,"ScreenDistanceClustering");var C=Q;var E,p,c,u,A,D,F,$,Y,J,U,K,P,T,I,O,v,tt=class tt{constructor(t,r,s){d(this,"id",W());a(this,E);a(this,p);a(this,c);a(this,u,{singleMarkersById:new Map,clustersById:new Map,clusterMarkersByClusterId:new Map,debugMarkersByClusterId:new Map,debugColorsByClusterId:new Map});a(this,A);a(this,D);a(this,F,i(()=>[...e(this,u).singleMarkersById.values()],"#getMarkers"));a(this,$,i(t=>{e(this,p).updateState(t,{enabled:!1})},"#hideMarker"));a(this,Y,i(t=>{e(this,p).updateState(t,{enabled:!0})},"#showMarker"));a(this,J,i(()=>{let t=e(this,c).algorithm;return t.load(e(this,F).call(this)),t.getClusters()},"#getClusteredMarkers"));a(this,U,i(t=>{var s;let r=at(t.map(o=>o.target.anchorTarget),(s=e(this,c).floor)==null?void 0:s.id);return{id:ut(t,r),markers:t,center:r}},"#createCluster"));a(this,K,i(t=>{var o;let r=(o=e(this,u).debugColorsByClusterId.get(t.id))!=null?o:L[0],s=e(this,A).call(this,t);s!=null&&e(this,u).clusterMarkersByClusterId.set(t.id,s);for(let l of t.markers)e(this,c).debug&&(l.contentEl.style.outline="2px solid ".concat(r)),e(this,c).hideClusteredMarkers&&e(this,$).call(this,l);if(e(this,c).debug){(s==null?void 0:s.contentEl.firstChild)instanceof HTMLElement&&(s.contentEl.firstChild.style.opacity="0.25");let l=e(this,p).Markers.add(t.center,it(t.markers.length.toString(),r,20),{rank:"always-visible",zIndex:99});e(this,u).debugMarkersByClusterId.set(t.id,l)}},"#addClusterMarkers"));a(this,P,i(t=>{let r=e(this,u).clusterMarkersByClusterId.get(t.id);if(r!=null&&(e(this,p).Markers.remove(r),e(this,u).clusterMarkersByClusterId.delete(t.id)),e(this,c).debug){let s=e(this,u).debugMarkersByClusterId.get(t.id);s!=null&&(e(this,p).Markers.remove(s),e(this,u).debugMarkersByClusterId.delete(t.id))}for(let s of t.markers)e(this,Y).call(this,s)},"#removeClusterMarkers"));a(this,T,i(()=>{let t=new Map(e(this,u).clustersById),r=[],s=e(this,J).call(this);for(let o=0;o<s.length;o++){let l=s[o];if(l.length<e(this,c).minSize)continue;let m=e(this,U).call(this,l);e(this,u).clustersById.has(m.id)?t.delete(m.id):r.push(m)}for(let o of t.values())e(this,P).call(this,o),e(this,u).clustersById.delete(o.id),e(this,c).debug&&e(this,u).debugColorsByClusterId.delete(o.id);for(let o of r){if(e(this,c).debug){let l=L[Math.floor(Math.random()*L.length)];e(this,u).debugColorsByClusterId.set(o.id,l)}e(this,K).call(this,o),e(this,u).clustersById.set(o.id,o)}},"#updateImmediately"));a(this,I,i(()=>{e(this,c).debounce===0?e(this,T).call(this):e(this,D).call(this)},"#update"));a(this,O,i(()=>{e(this,I).call(this)},"#handleCameraChange"));a(this,v,i(()=>{e(this,T).call(this)},"#handleFocus"));d(this,"add",i(t=>{var r,s;if(e(this,c).floor==null)e(this,c).floor=(s=e(this,E).getById("floor",(r=t.target.anchorTarget.floorId)!=null?r:""))!=null?s:null;else if(e(this,c).floor.id!==t.target.anchorTarget.floorId)throw new Error("Cannot cluster markers on different floors!");e(this,u).singleMarkersById.set(t.id,t),e(this,I).call(this)},"add"));d(this,"remove",i(t=>{if(!e(this,u).singleMarkersById.has(t.id)){G.log("Cannot remove marker ".concat(t.id," because it is not in the cluster!"));return}e(this,u).singleMarkersById.delete(t.id),e(this,I).call(this)},"remove"));d(this,"has",i(t=>e(this,u).singleMarkersById.has(t.id),"has"));d(this,"destroy",i(()=>{e(this,c).algorithm.destroy(),e(this,p).off("camera-change",e(this,O)),window.removeEventListener("focus",e(this,v));for(let[,t]of e(this,u).clustersById)e(this,P).call(this,t);for(let t of Object.values(e(this,u)))if(t instanceof Map)t.clear();else throw new Error("Encountered unexpected data type in cache! Potentially failed to clean up MarkerCluster.")},"destroy"));var l,m;let o;if((s==null?void 0:s.algorithm)==null){let z=new C(t);z.setOptions((l=s==null?void 0:s.algorithmOptions)!=null?l:{}),o=z}else o=s.algorithm,o.setOptions((m=s==null?void 0:s.algorithmOptions)!=null?m:{});if(f(this,c,{floor:null,minSize:2,debounce:50,debug:!1,hideClusteredMarkers:!0,...s,algorithm:o}),f(this,p,t),f(this,E,Object.values(e(this,p).getMapData())[0]),e(this,E)==null)throw new Error("No map data found in MapView!");f(this,A,r),f(this,D,nt(e(this,T),e(this,c).debounce)),e(this,p).on("camera-change",e(this,O)),window.addEventListener("focus",e(this,v))}get clusters(){return[...e(this,u).clustersById.values()]}};E=new WeakMap,p=new WeakMap,c=new WeakMap,u=new WeakMap,A=new WeakMap,D=new WeakMap,F=new WeakMap,$=new WeakMap,Y=new WeakMap,J=new WeakMap,U=new WeakMap,K=new WeakMap,P=new WeakMap,T=new WeakMap,I=new WeakMap,O=new WeakMap,v=new WeakMap,i(tt,"MarkerCluster");var j=tt;export{j as MarkerCluster,w as PointRBush,C as ScreenDistanceClustering};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mappedin/marker-cluster",
3
- "version": "6.0.1-beta.41",
3
+ "version": "6.0.1-beta.42",
4
4
  "homepage": "https://developer.mappedin.com/",
5
5
  "private": false,
6
6
  "main": "lib/esm/index.js",
@@ -30,5 +30,5 @@
30
30
  "volta": {
31
31
  "extends": "../../package.json"
32
32
  },
33
- "gitHead": "94497273d292bce0d4ea80036d26e177c6e4ed54"
33
+ "gitHead": "e839267a471e8db3dabbc18328468d24dee9b1a0"
34
34
  }