@@ -80,6 +80,24 @@ export type PolylineDefinition<PolylineOptions, InfoWindowOptions> = WithIdentif
8080 extra : Record < string , unknown > ;
8181} > ;
8282
83+ export type CircleDefinition < CircleOptions , InfoWindowOptions > = WithIdentifier < {
84+ infoWindow ?: InfoWindowWithoutPositionDefinition < InfoWindowOptions > ;
85+ center : Point ;
86+ radius : number ;
87+ title : string | null ;
88+ /**
89+ * Raw options passed to the circle constructor, specific to the map provider (e.g.: `L.circle()` for Leaflet).
90+ */
91+ rawOptions ?: CircleOptions ;
92+ /**
93+ * Extra data defined by the developer.
94+ * They are not directly used by the Stimulus controller, but they can be used by the developer with event listeners:
95+ * - `ux:map:circle:before-create`
96+ * - `ux:map:circle:after-create`
97+ */
98+ extra : Record < string , unknown > ;
99+ } > ;
100+
83101export type InfoWindowDefinition < InfoWindowOptions > = {
84102 headerContent : string | null ;
85103 content : string | null ;
@@ -116,6 +134,8 @@ export default abstract class<
116134 Polygon ,
117135 PolylineOptions ,
118136 Polyline ,
137+ CircleOptions ,
138+ Circle ,
119139> extends Controller < HTMLElement > {
120140 static values = {
121141 providerOptions : Object ,
@@ -125,6 +145,7 @@ export default abstract class<
125145 markers : Array ,
126146 polygons : Array ,
127147 polylines : Array ,
148+ circles : Array ,
128149 options : Object ,
129150 } ;
130151
@@ -134,6 +155,7 @@ export default abstract class<
134155 declare markersValue : Array < MarkerDefinition < MarkerOptions , InfoWindowOptions > > ;
135156 declare polygonsValue : Array < PolygonDefinition < PolygonOptions , InfoWindowOptions > > ;
136157 declare polylinesValue : Array < PolylineDefinition < PolylineOptions , InfoWindowOptions > > ;
158+ declare circlesValue : Array < CircleDefinition < CircleOptions , InfoWindowOptions > > ;
137159 declare optionsValue : MapOptions ;
138160
139161 declare hasCenterValue : boolean;
@@ -142,12 +164,14 @@ export default abstract class<
142164 declare hasMarkersValue : boolean;
143165 declare hasPolygonsValue : boolean;
144166 declare hasPolylinesValue : boolean;
167+ declare hasCirclesValue : boolean;
145168 declare hasOptionsValue : boolean;
146169
147170 protected map : Map ;
148171 protected markers = new Map < Identifier , Marker > ( ) ;
149172 protected polygons = new Map < Identifier , Polygon > ( ) ;
150173 protected polylines = new Map < Identifier , Polyline > ( ) ;
174+ protected circles = new Map < Identifier , Circle > ( ) ;
151175 protected infoWindows : Array < InfoWindow > = [ ] ;
152176
153177 private isConnected = false ;
@@ -160,6 +184,9 @@ export default abstract class<
160184 private createPolyline : ( {
161185 definition,
162186 } : { definition : PolylineDefinition < PolylineOptions , InfoWindowOptions > } ) = > Polyline ;
187+ private createCircle : ( {
188+ definition,
189+ } : { definition : CircleDefinition < CircleOptions , InfoWindowOptions > } ) = > Circle ;
163190
164191 protected abstract dispatchEvent ( name : string , payload : Record < string , unknown > ) : void ;
165192
@@ -171,6 +198,7 @@ export default abstract class<
171198 this . createMarker = this . createDrawingFactory ( 'marker' , this . markers , this . doCreateMarker . bind ( this ) ) ;
172199 this . createPolygon = this . createDrawingFactory ( 'polygon' , this . polygons , this . doCreatePolygon . bind ( this ) ) ;
173200 this . createPolyline = this . createDrawingFactory ( 'polyline' , this . polylines , this . doCreatePolyline . bind ( this ) ) ;
201+ this . createCircle = this . createDrawingFactory ( 'circle' , this . circles , this . doCreateCircle . bind ( this ) ) ;
174202
175203 this . map = this . doCreateMap ( {
176204 center : this . hasCenterValue ? this . centerValue : null ,
@@ -180,6 +208,7 @@ export default abstract class<
180208 this . markersValue . forEach ( ( definition ) => this . createMarker ( { definition } ) ) ;
181209 this . polygonsValue . forEach ( ( definition ) => this . createPolygon ( { definition } ) ) ;
182210 this . polylinesValue . forEach ( ( definition ) => this . createPolyline ( { definition } ) ) ;
211+ this . circlesValue . forEach ( ( definition ) => this . createCircle ( { definition } ) ) ;
183212
184213 if ( this . fitBoundsToMarkersValue ) {
185214 this . doFitBoundsToMarkers ( ) ;
@@ -190,6 +219,7 @@ export default abstract class<
190219 markers : [ ...this . markers . values ( ) ] ,
191220 polygons : [ ...this . polygons . values ( ) ] ,
192221 polylines : [ ...this . polylines . values ( ) ] ,
222+ circles : [ ...this . circles . values ( ) ] ,
193223 infoWindows : this . infoWindows ,
194224 } ) ;
195225
@@ -202,7 +232,7 @@ export default abstract class<
202232 element,
203233 } : {
204234 definition : InfoWindowWithoutPositionDefinition < InfoWindowOptions > ;
205- element: Marker | Polygon | Polyline ;
235+ element: Marker | Polygon | Polyline | Circle ;
206236 } ) : InfoWindow {
207237 this . dispatchEvent ( 'info-window:before-create' , { definition, element } ) ;
208238 const infoWindow = this . doCreateInfoWindow ( { definition, element } ) ;
@@ -248,6 +278,14 @@ export default abstract class<
248278 this . onDrawChanged ( this . polylines , this . polylinesValue , this . createPolyline , this . doRemovePolyline ) ;
249279 }
250280
281+ public circlesValueChanged ( ) : void {
282+ if ( ! this . isConnected ) {
283+ return ;
284+ }
285+
286+ this . onDrawChanged ( this . circles , this . circlesValue , this . createCircle , this . doRemoveCircle ) ;
287+ }
288+
251289 //endregion
252290
253291 //region Abstract factory methods to be implemented by the concrete classes, they are specific to the map provider
@@ -285,12 +323,20 @@ export default abstract class<
285323
286324 protected abstract doRemovePolyline ( polyline : Polyline ) : void ;
287325
326+ protected abstract doCreateCircle ( {
327+ definition,
328+ } : {
329+ definition : CircleDefinition < CircleOptions , InfoWindowOptions > ;
330+ } ) : Circle ;
331+
332+ protected abstract doRemoveCircle ( circle : Circle ) : void ;
333+
288334 protected abstract doCreateInfoWindow ( {
289335 definition,
290336 element,
291337 } : {
292338 definition : InfoWindowWithoutPositionDefinition < InfoWindowOptions > ;
293- element: Marker | Polygon | Polyline ;
339+ element: Marker | Polygon | Polyline | Circle ;
294340 } ) : InfoWindow ;
295341 protected abstract doCreateIcon ( {
296342 definition,
@@ -318,11 +364,20 @@ export default abstract class<
318364 draws : typeof this . polylines ,
319365 factory : typeof this . doCreatePolyline
320366 ) : typeof this . doCreatePolyline ;
367+ private createDrawingFactory (
368+ type : 'circle' ,
369+ draws : typeof this . circles ,
370+ factory : typeof this . doCreateCircle
371+ ) : typeof this . doCreateCircle ;
321372 private createDrawingFactory <
322- Factory extends typeof this . doCreateMarker | typeof this . doCreatePolygon | typeof this . doCreatePolyline ,
373+ Factory extends
374+ | typeof this . doCreateMarker
375+ | typeof this . doCreatePolygon
376+ | typeof this . doCreatePolyline
377+ | typeof this . doCreateCircle ,
323378 Draw extends ReturnType < Factory > ,
324379 > (
325- type : 'marker' | 'polygon' | 'polyline' ,
380+ type : 'marker' | 'polygon' | 'polyline' | 'circle' ,
326381 draws : globalThis . Map < WithIdentifier < any > , Draw > ,
327382 factory : Factory
328383 ) : Factory {
@@ -360,6 +415,12 @@ export default abstract class<
360415 factory : typeof this . createPolyline ,
361416 remover : typeof this . doRemovePolyline
362417 ) : void ;
418+ private onDrawChanged (
419+ draws : typeof this . circles ,
420+ newDrawDefinitions : typeof this . circlesValue ,
421+ factory : typeof this . createCircle ,
422+ remover : typeof this . doRemoveCircle
423+ ) : void ;
363424 private onDrawChanged < Draw , DrawDefinition extends WithIdentifier < Record < string , unknown > > > (
364425 draws : globalThis . Map < WithIdentifier < any > , Draw > ,
365426 newDrawDefinitions : Array < DrawDefinition > ,
0 commit comments