@react-google-maps/marker-clusterer 2.9.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { Cluster } from './Cluster'
4
4
 
5
5
  import { ClusterIconStyle, ClusterIconInfo } from './types'
6
6
 
7
- export class ClusterIcon {
7
+ export class ClusterIcon extends google.maps.OverlayView {
8
8
  cluster: Cluster
9
9
  className: string
10
10
  clusterClassName: string
@@ -25,144 +25,179 @@ export class ClusterIcon {
25
25
  fontStyle: string
26
26
  fontFamily: string
27
27
  backgroundPosition: string
28
+ cMouseDownInCluster: boolean | null
29
+ cDraggingMapByCluster: boolean | null
30
+ timeOut: number | null
28
31
 
29
32
  boundsChangedListener: google.maps.MapsEventListener | null
30
33
 
31
34
  constructor(cluster: Cluster, styles: ClusterIconStyle[]) {
35
+ super()
32
36
  cluster.getClusterer().extend(ClusterIcon, google.maps.OverlayView)
37
+
33
38
  this.cluster = cluster
39
+
34
40
  this.clusterClassName = this.cluster.getClusterer().getClusterClass()
41
+
35
42
  this.className = this.clusterClassName
43
+
36
44
  this.styles = styles
45
+
37
46
  this.center = undefined
47
+
38
48
  this.div = null
49
+
39
50
  this.sums = null
51
+
40
52
  this.visible = false
53
+
41
54
  this.boundsChangedListener = null
55
+
42
56
  this.url = ''
57
+
43
58
  this.height = 0
44
59
  this.width = 0
60
+
45
61
  this.anchorText = [0, 0]
46
62
  this.anchorIcon = [0, 0]
63
+
47
64
  this.textColor = 'black'
48
65
  this.textSize = 11
49
66
  this.textDecoration = 'none'
50
67
  this.fontWeight = 'bold'
51
68
  this.fontStyle = 'normal'
52
69
  this.fontFamily = 'Arial,sans-serif'
70
+
53
71
  this.backgroundPosition = '0 0'
54
- // @ts-ignore
72
+
73
+ this.cMouseDownInCluster = null
74
+ this.cDraggingMapByCluster = null
75
+ this.timeOut = null
76
+
77
+
55
78
  this.setMap(cluster.getMap()) // Note: this causes onAdd to be called
56
79
  }
57
80
 
58
- onAdd() {
59
- let cMouseDownInCluster: boolean
60
- let cDraggingMapByCluster: boolean
81
+ onBoundsChanged() {
82
+ this.cDraggingMapByCluster = this.cMouseDownInCluster
83
+ }
61
84
 
85
+ onMouseDown() {
86
+ this.cMouseDownInCluster = true
87
+
88
+ this.cDraggingMapByCluster = false
89
+ }
90
+
91
+ onClick(event: Event) {
92
+ this.cMouseDownInCluster = false
93
+
94
+ if (!this.cDraggingMapByCluster) {
95
+ const markerClusterer = this.cluster.getClusterer()
96
+
97
+ /**
98
+ * This event is fired when a cluster marker is clicked.
99
+ * @name MarkerClusterer#click
100
+ * @param {Cluster} c The cluster that was clicked.
101
+ * @event
102
+ */
103
+ google.maps.event.trigger(markerClusterer, 'click', this.cluster)
104
+ google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster) // deprecated name
105
+
106
+ // The default click handler follows. Disable it by setting
107
+ // the zoomOnClick property to false.
108
+ if (markerClusterer.getZoomOnClick()) {
109
+ // Zoom into the cluster.
110
+ const maxZoom = markerClusterer.getMaxZoom()
111
+
112
+ const bounds = this.cluster.getBounds()
113
+
114
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
115
+ // @ts-ignore
116
+ markerClusterer.getMap().fitBounds(bounds)
117
+
118
+ // There is a fix for Issue 170 here:
119
+ this.timeOut = window.setTimeout(() => {
120
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
121
+ // @ts-ignore
122
+ markerClusterer.getMap().fitBounds(bounds)
123
+
124
+ // Don't zoom beyond the max zoom level
125
+ if (
126
+ maxZoom !== null &&
127
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
128
+ // @ts-ignore
129
+ markerClusterer.getMap().getZoom() > maxZoom
130
+ ) {
131
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
132
+ // @ts-ignore
133
+ markerClusterer.getMap().setZoom(maxZoom + 1)
134
+ }
135
+ }, 100)
136
+ }
137
+
138
+ // Prevent event propagation to the map:
139
+ event.cancelBubble = true
140
+
141
+ if (event.stopPropagation) {
142
+ event.stopPropagation()
143
+ }
144
+ }
145
+ }
146
+
147
+ onMouseOver() {
148
+ /**
149
+ * This event is fired when the mouse moves over a cluster marker.
150
+ * @name MarkerClusterer#mouseover
151
+ * @param {Cluster} c The cluster that the mouse moved over.
152
+ * @event
153
+ */
154
+ google.maps.event.trigger(
155
+ this.cluster.getClusterer(),
156
+ 'mouseover',
157
+ this.cluster
158
+ )
159
+ }
160
+
161
+ onMouseOut() {
162
+ /**
163
+ * This event is fired when the mouse moves out of a cluster marker.
164
+ * @name MarkerClusterer#mouseout
165
+ * @param {Cluster} c The cluster that the mouse moved out of.
166
+ * @event
167
+ */
168
+ google.maps.event.trigger(
169
+ this.cluster.getClusterer(),
170
+ 'mouseout',
171
+ this.cluster
172
+ )
173
+ }
174
+
175
+ onAdd() {
62
176
  this.div = document.createElement('div')
63
177
  this.div.className = this.className
64
178
  if (this.visible) {
65
179
  this.show()
66
180
  }
67
181
 
182
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
68
183
  // @ts-ignore
69
184
  this.getPanes().overlayMouseTarget.appendChild(this.div)
70
-
71
185
  // Fix for Issue 157
72
186
  this.boundsChangedListener = google.maps.event.addListener(
187
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
73
188
  // @ts-ignore
74
189
  this.getMap(),
75
- 'boundschanged',
76
- function boundsChanged() {
77
- cDraggingMapByCluster = cMouseDownInCluster
78
- }
190
+ 'bounds_changed',
191
+ this.onBoundsChanged
79
192
  )
80
193
 
81
- google.maps.event.addDomListener(this.div, 'mousedown', function onMouseDown() {
82
- cMouseDownInCluster = true
83
- cDraggingMapByCluster = false
84
- })
85
-
86
- google.maps.event.addDomListener(
87
- this.div,
88
- 'click',
89
- (event: Event) => {
90
- cMouseDownInCluster = false
91
-
92
- if (!cDraggingMapByCluster) {
93
- const markerClusterer = this.cluster.getClusterer()
94
-
95
- /**
96
- * This event is fired when a cluster marker is clicked.
97
- * @name MarkerClusterer#click
98
- * @param {Cluster} c The cluster that was clicked.
99
- * @event
100
- */
101
- google.maps.event.trigger(markerClusterer, 'click', this.cluster)
102
- google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster) // deprecated name
103
-
104
- // The default click handler follows. Disable it by setting
105
- // the zoomOnClick property to false.
106
- if (markerClusterer.getZoomOnClick()) {
107
- // Zoom into the cluster.
108
- const maxZoom = markerClusterer.getMaxZoom()
109
-
110
- const bounds = this.cluster.getBounds()
194
+ this.div.addEventListener('mousedown', this.onMouseDown)
111
195
 
112
- // @ts-ignore
113
- markerClusterer.getMap().fitBounds(bounds)
114
-
115
- // There is a fix for Issue 170 here:
116
- setTimeout(function timeout() {
117
- // @ts-ignore
118
- markerClusterer.getMap().fitBounds(bounds)
119
-
120
- // Don't zoom beyond the max zoom level
121
- // @ts-ignore
122
- if (maxZoom !== null && markerClusterer.getMap().getZoom() > maxZoom) {
123
- // @ts-ignore
124
- markerClusterer.getMap().setZoom(maxZoom + 1)
125
- }
126
- }, 100)
127
- }
196
+ this.div.addEventListener('click', this.onClick)
128
197
 
129
- // Prevent event propagation to the map:
130
- event.cancelBubble = true
198
+ this.div.addEventListener('mouseover', this.onMouseOver)
131
199
 
132
- if (event.stopPropagation) {
133
- event.stopPropagation()
134
- }
135
- }
136
- }
137
- )
138
-
139
- google.maps.event.addDomListener(
140
- this.div,
141
- 'mouseover',
142
- () => {
143
- /**
144
- * This event is fired when the mouse moves over a cluster marker.
145
- * @name MarkerClusterer#mouseover
146
- * @param {Cluster} c The cluster that the mouse moved over.
147
- * @event
148
- */
149
- google.maps.event.trigger(this.cluster.getClusterer(), 'mouseover', this.cluster)
150
- }
151
- )
152
-
153
- google.maps.event.addDomListener(
154
- this.div,
155
- 'mouseout',
156
- () => {
157
- /**
158
- * This event is fired when the mouse moves out of a cluster marker.
159
- * @name MarkerClusterer#mouseout
160
- * @param {Cluster} c The cluster that the mouse moved out of.
161
- * @event
162
- */
163
- google.maps.event.trigger(this.cluster.getClusterer(), 'mouseout', this.cluster)
164
- }
165
- )
200
+ this.div.addEventListener('mouseout', this.onMouseOut)
166
201
  }
167
202
 
168
203
  onRemove() {
@@ -173,20 +208,32 @@ export class ClusterIcon {
173
208
  google.maps.event.removeListener(this.boundsChangedListener)
174
209
  }
175
210
 
176
- google.maps.event.clearInstanceListeners(this.div)
211
+ this.div.removeEventListener('mousedown', this.onMouseDown)
212
+
213
+ this.div.removeEventListener('click', this.onClick)
214
+
215
+ this.div.removeEventListener('mouseover', this.onMouseOver)
216
+
217
+ this.div.removeEventListener('mouseout', this.onMouseOut)
177
218
 
178
219
  this.div.parentNode.removeChild(this.div)
179
220
 
221
+ if (this.timeOut !== null) {
222
+ window.clearTimeout(this.timeOut)
223
+
224
+ this.timeOut = null
225
+ }
226
+
180
227
  this.div = null
181
228
  }
182
229
  }
183
230
 
184
231
  draw() {
185
232
  if (this.visible && this.div !== null && this.center) {
186
- const { x, y } = this.getPosFromLatLng(this.center)
233
+ const pos = this.getPosFromLatLng(this.center)
187
234
 
188
- this.div.style.top = y + 'px'
189
- this.div.style.left = x + 'px'
235
+ this.div.style.top = pos !== null ? `${pos.y}px` : '0'
236
+ this.div.style.left = pos !== null ? `${pos.x}px` : '0'
190
237
  }
191
238
  }
192
239
 
@@ -210,7 +257,11 @@ export class ClusterIcon {
210
257
 
211
258
  const pos = this.getPosFromLatLng(this.center)
212
259
 
213
- if (this.sums === null || typeof this.sums.title === 'undefined' || this.sums.title === '') {
260
+ if (
261
+ this.sums === null ||
262
+ typeof this.sums.title === 'undefined' ||
263
+ this.sums.title === ''
264
+ ) {
214
265
  divTitle = this.cluster.getClusterer().getTitle()
215
266
  } else {
216
267
  divTitle = this.sums.title
@@ -218,12 +269,15 @@ export class ClusterIcon {
218
269
 
219
270
  this.div.style.cursor = 'pointer'
220
271
  this.div.style.position = 'absolute'
221
- this.div.style.top = `${pos.y}px`
222
- this.div.style.left = `${pos.x}px`
272
+
273
+ this.div.style.top = pos !== null ? `${pos.y}px` : '0'
274
+ this.div.style.left = pos !== null ? `${pos.x}px` : '0'
275
+
223
276
  this.div.style.width = `${this.width}px`
224
277
  this.div.style.height = `${this.height}px`
225
278
 
226
279
  const img = document.createElement('img')
280
+
227
281
  img.alt = divTitle
228
282
  img.src = this.url
229
283
  img.style.position = 'absolute'
@@ -231,10 +285,13 @@ export class ClusterIcon {
231
285
  img.style.left = `${spriteH}px`
232
286
 
233
287
  if (!this.cluster.getClusterer().enableRetinaIcons) {
234
- img.style.clip = `rect(-${spriteV}px, -${spriteH + this.width}px, -${spriteV + this.height}, -${spriteH})`
288
+ img.style.clip = `rect(-${spriteV}px, -${spriteH + this.width}px, -${
289
+ spriteV + this.height
290
+ }, -${spriteH})`
235
291
  }
236
292
 
237
293
  const textElm = document.createElement('div')
294
+
238
295
  textElm.style.position = 'absolute'
239
296
  textElm.style.top = `${this.anchorText[0]}px`
240
297
  textElm.style.left = `${this.anchorText[1]}px`
@@ -250,9 +307,12 @@ export class ClusterIcon {
250
307
  textElm.innerText = `${this.sums?.text}`
251
308
 
252
309
  this.div.innerHTML = ''
310
+
253
311
  this.div.appendChild(img)
254
312
  this.div.appendChild(textElm)
313
+
255
314
  this.div.title = divTitle
315
+
256
316
  this.div.style.display = ''
257
317
  }
258
318
 
@@ -261,14 +321,18 @@ export class ClusterIcon {
261
321
 
262
322
  useStyle(sums: ClusterIconInfo) {
263
323
  this.sums = sums
324
+
264
325
  const styles = this.cluster.getClusterer().getStyles()
265
- const style = styles[Math.min(styles.length - 1, Math.max(0, sums.index - 1))]
326
+
327
+ const style =
328
+ styles[Math.min(styles.length - 1, Math.max(0, sums.index - 1))]
266
329
 
267
330
  this.url = style.url
268
331
  this.height = style.height
269
332
  this.width = style.width
270
333
 
271
- if (style.className) this.className = `${this.clusterClassName} ${style.className}`
334
+ if (style.className)
335
+ this.className = `${this.clusterClassName} ${style.className}`
272
336
 
273
337
  this.anchorText = style.anchorText || [0, 0]
274
338
  this.anchorIcon = style.anchorIcon || [this.height / 2, this.width / 2]
@@ -292,17 +356,14 @@ export class ClusterIcon {
292
356
  this.center = center
293
357
  }
294
358
 
295
- getPosFromLatLng(latlng: google.maps.LatLng): google.maps.Point {
296
- // @ts-ignore
359
+ getPosFromLatLng(latlng: google.maps.LatLng): google.maps.Point | null {
297
360
  const pos = this.getProjection().fromLatLngToDivPixel(latlng)
298
361
 
299
- pos.x -= this.anchorIcon[1]
300
-
301
- pos.y -= this.anchorIcon[0]
362
+ if (pos !== null) {
363
+ pos.x -= this.anchorIcon[1]
302
364
 
303
- // pos.x = pos.x
304
-
305
- // pos.y = pos.y
365
+ pos.y -= this.anchorIcon[0]
366
+ }
306
367
 
307
368
  return pos
308
369
  }
package/src/Clusterer.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  /* global google */
2
2
  /* eslint-disable filenames/match-regex */
3
3
  import { Cluster } from './Cluster'
4
+ import { ClusterIcon } from './ClusterIcon'
4
5
 
5
6
  import {
6
7
  MarkerExtended,
@@ -44,7 +45,7 @@ const IMAGE_SIZES = [53, 56, 66, 78, 90]
44
45
 
45
46
  const CLUSTERER_CLASS = 'cluster'
46
47
 
47
- export class Clusterer {
48
+ export class Clusterer extends google.maps.OverlayView {
48
49
  markers: MarkerExtended[]
49
50
  clusters: Cluster[]
50
51
  listeners: google.maps.MapsEventListener[]
@@ -73,6 +74,8 @@ export class Clusterer {
73
74
  optMarkers: MarkerExtended[] = [],
74
75
  optOptions: ClustererOptions = {}
75
76
  ) {
77
+ super()
78
+
76
79
  this.extend(Clusterer, google.maps.OverlayView)
77
80
 
78
81
  this.markers = []
@@ -134,50 +137,56 @@ export class Clusterer {
134
137
  this.setupStyles()
135
138
 
136
139
  this.addMarkers(optMarkers, true)
140
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
137
141
  // @ts-ignore
138
142
  this.setMap(map) // Note: this causes onAdd to be called
139
143
  }
140
144
 
145
+ onZoomChanged() {
146
+ this.resetViewport(false)
147
+
148
+ // Workaround for this Google bug: when map is at level 0 and "-" of
149
+ // zoom slider is clicked, a "zoom_changed" event is fired even though
150
+ // the map doesn't zoom out any further. In this situation, no "idle"
151
+ // event is triggered so the cluster markers that have been removed
152
+ // do not get redrawn. Same goes for a zoom in at maxZoom.
153
+ if (
154
+ this.getMap()?.getZoom() === (this.get('minZoom') || 0) ||
155
+
156
+ this.getMap()?.getZoom() === this.get('maxZoom')
157
+ ) {
158
+ google.maps.event.trigger(this, 'idle')
159
+ }
160
+ }
161
+
162
+ onIdle() {
163
+ this.redraw()
164
+ }
165
+
141
166
  onAdd() {
142
- // @ts-ignore
143
- this.activeMap = this.getMap()
167
+ const map = this.getMap()
168
+
169
+ this.activeMap = map
144
170
 
145
171
  this.ready = true
146
172
 
147
173
  this.repaint()
148
174
 
149
- // Add the map event listeners
150
- this.listeners = [
151
- google.maps.event.addListener(
152
- // @ts-ignore
153
- this.getMap(),
154
- 'zoom_changed',
155
- () => {
156
- this.resetViewport(false)
157
- // Workaround for this Google bug: when map is at level 0 and "-" of
158
- // zoom slider is clicked, a "zoom_changed" event is fired even though
159
- // the map doesn't zoom out any further. In this situation, no "idle"
160
- // event is triggered so the cluster markers that have been removed
161
- // do not get redrawn. Same goes for a zoom in at maxZoom.
162
- if (
163
- // @ts-ignore
164
- this.getMap().getZoom() === (this.get('minZoom') || 0) ||
165
- // @ts-ignore
166
- this.getMap().getZoom() === this.get('maxZoom')
167
- ) {
168
- google.maps.event.trigger(this, 'idle')
169
- }
170
- }
171
- ),
172
- google.maps.event.addListener(
173
- // @ts-ignore
174
- this.getMap(),
175
- 'idle',
176
- () => {
177
- this.redraw()
178
- }
179
- ),
180
- ]
175
+ if (map !== null) {
176
+ // Add the map event listeners
177
+ this.listeners = [
178
+ google.maps.event.addListener(
179
+ map,
180
+ 'zoom_changed',
181
+ this.onZoomChanged
182
+ ),
183
+ google.maps.event.addListener(
184
+ map,
185
+ 'idle',
186
+ this.onIdle
187
+ ),
188
+ ]
189
+ }
181
190
  }
182
191
 
183
192
  onRemove() {
@@ -236,6 +245,7 @@ export class Clusterer {
236
245
  }
237
246
  }
238
247
 
248
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
239
249
  // @ts-ignore
240
250
  this.getMap().fitBounds(bounds)
241
251
  }
@@ -489,6 +499,7 @@ export class Clusterer {
489
499
  }
490
500
 
491
501
  getExtendedBounds(bounds: google.maps.LatLngBounds): google.maps.LatLngBounds {
502
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
492
503
  // @ts-ignore
493
504
  const projection = this.getProjection()
494
505
  // Convert the points to pixels and the extend out by the grid size.
@@ -497,27 +508,43 @@ export class Clusterer {
497
508
  new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng())
498
509
  )
499
510
 
500
- trPix.x += this.gridSize
501
- trPix.y -= this.gridSize
511
+ if (trPix !== null) {
512
+ trPix.x += this.gridSize
513
+ trPix.y -= this.gridSize
514
+ }
502
515
 
503
516
  const blPix = projection.fromLatLngToDivPixel(
504
517
  // Turn the bounds into latlng.
505
518
  new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng())
506
519
  )
507
520
 
508
- blPix.x -= this.gridSize
509
- blPix.y += this.gridSize
521
+ if (blPix !== null) {
522
+ blPix.x -= this.gridSize
523
+ blPix.y += this.gridSize
524
+ }
525
+
510
526
 
511
527
  // Extend the bounds to contain the new bounds.
512
- bounds.extend(
528
+ if (trPix !== null) {
513
529
  // Convert the pixel points back to LatLng nw
514
- projection.fromDivPixelToLatLng(trPix)
515
- )
530
+ const point1 = projection.fromDivPixelToLatLng(trPix)
516
531
 
517
- bounds.extend(
532
+ if (point1 !== null) {
533
+ bounds.extend(point1)
534
+ }
535
+ }
536
+
537
+ if (blPix !== null) {
518
538
  // Convert the pixel points back to LatLng sw
519
- projection.fromDivPixelToLatLng(blPix)
520
- )
539
+ const point2 = projection.fromDivPixelToLatLng(blPix)
540
+
541
+ if (point2 !== null) {
542
+ bounds.extend(
543
+ point2
544
+ )
545
+ }
546
+ }
547
+
521
548
 
522
549
  return bounds
523
550
  }
@@ -628,44 +655,42 @@ export class Clusterer {
628
655
  if (this.timerRefStatic !== null) {
629
656
  window.clearTimeout(this.timerRefStatic)
630
657
 
658
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
631
659
  // @ts-ignore
632
660
  delete this.timerRefStatic
633
661
  }
634
662
  }
635
663
 
664
+ const map = this.getMap()
665
+
666
+ const bounds = map !== null && 'getBounds' in map ? map.getBounds() : null
667
+
636
668
  // Get our current map view bounds.
637
669
  // Create a new bounds object so we don't affect the map.
638
670
  //
639
671
  // See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:
640
672
  const mapBounds =
673
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
641
674
  // @ts-ignore
642
- this.getMap().getZoom() > 3
675
+ map.getZoom() > 3
643
676
  ? new google.maps.LatLngBounds(
644
- // @ts-ignore
645
- this.getMap()
646
- .getBounds()
647
- .getSouthWest(),
648
- // @ts-ignore
649
- this.getMap()
650
- .getBounds()
651
- .getNorthEast()
677
+ bounds?.getSouthWest(),
678
+ bounds?.getNorthEast()
652
679
  )
653
680
  : new google.maps.LatLngBounds(
654
681
  new google.maps.LatLng(85.02070771743472, -178.48388434375),
655
682
  new google.maps.LatLng(-85.08136444384544, 178.00048865625)
656
683
  )
657
684
 
658
- const bounds = this.getExtendedBounds(mapBounds)
685
+ const extendedMapBounds = this.getExtendedBounds(mapBounds)
659
686
 
660
687
  const iLast = Math.min(iFirst + this.batchSize, this.markers.length)
661
688
 
662
689
  for (let i = iFirst; i < iLast; i++) {
663
690
  const marker = this.markers[i]
664
691
 
665
- if (!marker.isAdded && this.isMarkerInBounds(marker, bounds)) {
666
- if (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible())) {
667
- this.addToClosestCluster(marker)
668
- }
692
+ if (!marker.isAdded && this.isMarkerInBounds(marker, extendedMapBounds) && (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible()))) {
693
+ this.addToClosestCluster(marker)
669
694
  }
670
695
  }
671
696
 
@@ -694,16 +719,13 @@ export class Clusterer {
694
719
  }
695
720
  }
696
721
 
697
- extend(obj1: any, obj2: any): any {
698
- return function applyExtend(object: any) {
699
- // eslint-disable-next-line guard-for-in
722
+ extend<A extends typeof ClusterIcon | typeof Clusterer>(obj1: A, obj2: typeof google.maps.OverlayView) {
723
+ return function applyExtend(this: A, object: typeof google.maps.OverlayView) {
700
724
  for (const property in object.prototype) {
701
- // @ts-ignore
702
- this.prototype[property] = object.prototype[property]
725
+ this.prototype.set(property, object.prototype.get(property))
703
726
  }
704
727
 
705
- // @ts-ignore
706
728
  return this
707
- }.apply(obj1, [obj2])
729
+ }.apply<A, [typeof google.maps.OverlayView], any>(obj1, [obj2])
708
730
  }
709
731
  }
package/src/index.ts CHANGED
@@ -43,9 +43,9 @@ export { Cluster } from './Cluster'
43
43
  export { ClusterIcon } from './ClusterIcon'
44
44
 
45
45
  export {
46
- ClusterIconInfo,
47
- ClusterIconStyle,
48
- MarkerExtended,
49
- TCalculator,
50
- ClustererOptions,
46
+ type ClusterIconInfo,
47
+ type ClusterIconStyle,
48
+ type MarkerExtended,
49
+ type TCalculator,
50
+ type ClustererOptions,
51
51
  } from './types'