Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit efe1666

Browse files
committedJun 23, 2025··
feature #2861 [Map] Allows Map options customization in ux:map:pre-connect event (e.g.: zoom, options, bridgeOptions...) (Kocal)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [Map] Allows Map options customization in `ux:map:pre-connect` event (e.g.: `zoom`, `options`, `bridgeOptions`...) | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Docs? | yes <!-- required for new features --> | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT <!-- Replace this notice by a description of your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - For new features, provide some code snippets to help understand usage. - Features and deprecations must be submitted against branch main. - Update/add documentation as required (we can help!) - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> This feature allows users to override the options passed to `L.Map()` or `new google.maps.Map()` trough the `ux:map:pre-connect` event. The configurable options are: - zoom - center - options - bridgeOptions, not injected by default, but can be defined on-the-fly This is a blocking step for #2810, but also for one of my need when I wanted to persist the zoom/center in the URL, to share my map (https://hugo.alliau.me/places 😛) : ```js _onMapPreConnect = (event) => { const { L } = event.detail; if (window.location.hash) { try { const state = Object.fromEntries(new URLSearchParams(window.location.hash.slice(1))); const zoom = Number(state.z); const center = state.center.split(",").map(Number); event.detail.zoom = zoom; event.detail.center = L.latLng(center[0], center[1]); } catch (e) { console.error("Invalid state in URL hash:", e); } } } _onMapConnect = (event) => { const { map } = event.detail; const updateState = () => { const center = map.getCenter(); const zoom = map.getZoom(); const state = { z: zoom, center: [center.lat.toFixed(5), center.lng.toFixed(5)], }; window.history.replaceState(state, "", `#${new URLSearchParams(state).toString()}`); }; map.addEventListener("zoom", () => updateState()); map.addEventListener("move", () => updateState()); }; ``` Commits ------- afc7db6 [Map] Add missing doc for Circle and Rectangle b0463b7 [Map] Allows Map options customization in `ux:map:pre-connect` event (e.g.: `zoom`, `options`, `bridgeOptions`...)
2 parents 523c591 + afc7db6 commit efe1666

File tree

12 files changed

+194
-82
lines changed

12 files changed

+194
-82
lines changed
 

‎src/Map/CHANGELOG.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ $map->addRectangle(new Rectangle(
2323
```
2424

2525
- Deprecate property `rawOptions` from `ux:map:*:before-create` events, in favor of `bridgeOptions` instead.
26+
- Map options can now be configured and overridden through the `ux:map:pre-connect` event:
27+
```js
28+
this.element.addEventListener('ux:map:pre-connect', (event) => {
29+
// Override the map center and zoom
30+
event.detail.zoom = 10;
31+
event.detail.center = { lat: 48.856613, lng: 2.352222 };
32+
33+
// Override the normalized `*Options` PHP classes (e.g. `GoogleMapOptions` or `LeafletMapOptions`)
34+
console.log(event.detail.options);
35+
36+
// Override the options specific to the renderer bridge (e.g. `google.maps.MapOptions` or `L.MapOptions`)
37+
event.detail.bridgeOptions = {
38+
// ...
39+
};
40+
});
41+
```
2642

2743
## 2.26
2844

‎src/Map/assets/dist/abstract_map_controller.d.ts‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ export type Icon = {
2626
type: typeof IconTypes.Svg;
2727
html: string;
2828
});
29+
export type MapDefinition<MapOptions, BridgeMapOptions> = {
30+
center: Point | null;
31+
zoom: number | null;
32+
options: MapOptions;
33+
bridgeOptions?: BridgeMapOptions;
34+
};
2935
export type MarkerDefinition<BridgeMarkerOptions, BridgeInfoWindowOptions> = WithIdentifier<{
3036
position: Point;
3137
title: string | null;
@@ -79,7 +85,7 @@ export type InfoWindowDefinition<BridgeInfoWindowOptions> = {
7985
bridgeOptions?: BridgeInfoWindowOptions;
8086
extra: Record<string, unknown>;
8187
};
82-
export default abstract class<MapOptions, BridgeMap, BridgeMarkerOptions, BridgeMarker, BridgeInfoWindowOptions, BridgeInfoWindow, BridgePolygonOptions, BridgePolygon, BridgePolylineOptions, BridgePolyline, BridgeCircleOptions, BridgeCircle, BridgeRectangleOptions, BridgeRectangle> extends Controller<HTMLElement> {
88+
export default abstract class<MapOptions, BridgeMapOptions, BridgeMap, BridgeMarkerOptions, BridgeMarker, BridgeInfoWindowOptions, BridgeInfoWindow, BridgePolygonOptions, BridgePolygon, BridgePolylineOptions, BridgePolyline, BridgeCircleOptions, BridgeCircle, BridgeRectangleOptions, BridgeRectangle> extends Controller<HTMLElement> {
8389
static values: {
8490
providerOptions: ObjectConstructor;
8591
center: ObjectConstructor;
@@ -136,10 +142,8 @@ export default abstract class<MapOptions, BridgeMap, BridgeMarkerOptions, Bridge
136142
polylinesValueChanged(): void;
137143
circlesValueChanged(): void;
138144
rectanglesValueChanged(): void;
139-
protected abstract doCreateMap({ center, zoom, options }: {
140-
center: Point | null;
141-
zoom: number | null;
142-
options: MapOptions;
145+
protected abstract doCreateMap({ definition }: {
146+
definition: MapDefinition<MapOptions, BridgeMapOptions>;
143147
}): BridgeMap;
144148
protected abstract doFitBoundsToMarkers(): void;
145149
protected abstract doCreateMarker({ definition }: {

‎src/Map/assets/dist/abstract_map_controller.js‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,18 @@ class default_1 extends Controller {
1717
this.isConnected = false;
1818
}
1919
connect() {
20-
const options = this.optionsValue;
21-
this.dispatchEvent('pre-connect', { options });
20+
const mapDefinition = {
21+
center: this.hasCenterValue ? this.centerValue : null,
22+
zoom: this.hasZoomValue ? this.zoomValue : null,
23+
options: this.optionsValue,
24+
};
25+
this.dispatchEvent('pre-connect', mapDefinition);
2226
this.createMarker = this.createDrawingFactory('marker', this.markers, this.doCreateMarker.bind(this));
2327
this.createPolygon = this.createDrawingFactory('polygon', this.polygons, this.doCreatePolygon.bind(this));
2428
this.createPolyline = this.createDrawingFactory('polyline', this.polylines, this.doCreatePolyline.bind(this));
2529
this.createCircle = this.createDrawingFactory('circle', this.circles, this.doCreateCircle.bind(this));
2630
this.createRectangle = this.createDrawingFactory('rectangle', this.rectangles, this.doCreateRectangle.bind(this));
27-
this.map = this.doCreateMap({
28-
center: this.hasCenterValue ? this.centerValue : null,
29-
zoom: this.hasZoomValue ? this.zoomValue : null,
30-
options,
31-
});
31+
this.map = this.doCreateMap({ definition: mapDefinition });
3232
this.markersValue.forEach((definition) => this.createMarker({ definition }));
3333
this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
3434
this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));

‎src/Map/assets/src/abstract_map_controller.ts‎

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ export type Icon = {
3737
}
3838
);
3939

40+
export type MapDefinition<MapOptions, BridgeMapOptions> = {
41+
center: Point | null;
42+
zoom: number | null;
43+
options: MapOptions;
44+
/**
45+
* Additional options passed to the Map constructor.
46+
* These options are specific to the Map Bridge, and can be defined through `ux:map:pre-connect` event.
47+
*/
48+
bridgeOptions?: BridgeMapOptions;
49+
};
50+
4051
export type MarkerDefinition<BridgeMarkerOptions, BridgeInfoWindowOptions> = WithIdentifier<{
4152
position: Point;
4253
title: string | null;
@@ -182,6 +193,7 @@ export type InfoWindowDefinition<BridgeInfoWindowOptions> = {
182193

183194
export default abstract class<
184195
MapOptions, // Normalized `*Options` PHP class from Bridge (to not be confused with the JS Map class options)
196+
BridgeMapOptions, // The options for the JavaScript Map class from Bridge
185197
BridgeMap, // The JavaScript Map class from Bridge (e.g.: `L.Map` for Leaflet, `google.maps.Map` for Google Maps)
186198
BridgeMarkerOptions, // The options for the JavaScript Marker class from Bridge
187199
BridgeMarker, // The JavaScript Marker class from Bridge
@@ -247,21 +259,20 @@ export default abstract class<
247259
protected abstract dispatchEvent(name: string, payload: Record<string, unknown>): void;
248260

249261
connect() {
250-
const options = this.optionsValue;
251-
252-
this.dispatchEvent('pre-connect', { options });
262+
const mapDefinition: MapDefinition<MapOptions, BridgeMapOptions> = {
263+
center: this.hasCenterValue ? this.centerValue : null,
264+
zoom: this.hasZoomValue ? this.zoomValue : null,
265+
options: this.optionsValue,
266+
};
267+
this.dispatchEvent('pre-connect', mapDefinition);
253268

254269
this.createMarker = this.createDrawingFactory('marker', this.markers, this.doCreateMarker.bind(this));
255270
this.createPolygon = this.createDrawingFactory('polygon', this.polygons, this.doCreatePolygon.bind(this));
256271
this.createPolyline = this.createDrawingFactory('polyline', this.polylines, this.doCreatePolyline.bind(this));
257272
this.createCircle = this.createDrawingFactory('circle', this.circles, this.doCreateCircle.bind(this));
258273
this.createRectangle = this.createDrawingFactory('rectangle', this.rectangles, this.doCreateRectangle.bind(this));
259274

260-
this.map = this.doCreateMap({
261-
center: this.hasCenterValue ? this.centerValue : null,
262-
zoom: this.hasZoomValue ? this.zoomValue : null,
263-
options,
264-
});
275+
this.map = this.doCreateMap({ definition: mapDefinition });
265276
this.markersValue.forEach((definition) => this.createMarker({ definition }));
266277
this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
267278
this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));
@@ -356,7 +367,7 @@ export default abstract class<
356367
//endregion
357368

358369
//region Abstract factory methods to be implemented by the concrete classes, they are specific to the map provider
359-
protected abstract doCreateMap({ center, zoom, options }: { center: Point | null; zoom: number | null; options: MapOptions }): BridgeMap;
370+
protected abstract doCreateMap({ definition }: { definition: MapDefinition<MapOptions, BridgeMapOptions> }): BridgeMap;
360371

361372
protected abstract doFitBoundsToMarkers(): void;
362373

‎src/Map/assets/test/abstract_map_controller.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ class MyMapController extends AbstractMapController {
1212
});
1313
}
1414

15-
doCreateMap({ center, zoom, options }) {
16-
return { map: 'map', center, zoom, options };
15+
doCreateMap({ definition }) {
16+
return { map: 'map', center: definition.center, zoom: definition.zoom, options: definition.options };
1717
}
1818

1919
doCreateMarker({ definition }) {

‎src/Map/doc/index.rst‎

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Configuration is done in your ``config/packages/ux_map.yaml`` file:
3333
# without to manually configure it in each map instance (through "new GoogleOptions(mapId: 'your_map_id')").
3434
default_map_id: null
3535
36-
The ``UX_MAP_DSN`` environment variable configure which renderer to use.
36+
The ``UX_MAP_DSN`` environment variable configure which renderer (Bridge) to use.
3737

3838
Map renderers
3939
~~~~~~~~~~~~~
@@ -362,6 +362,10 @@ Symfony UX Map allows you to extend its default behavior using a custom Stimulus
362362
this.element.addEventListener('ux:map:polygon:after-create', this._onPolygonAfterCreate);
363363
this.element.addEventListener('ux:map:polyline:before-create', this._onPolylineBeforeCreate);
364364
this.element.addEventListener('ux:map:polyline:after-create', this._onPolylineAfterCreate);
365+
this.element.addEventListener('ux:map:circle:before-create', this._onCircleBeforeCreate);
366+
this.element.addEventListener('ux:map:circle:after-create', this._onCircleAfterCreate);
367+
this.element.addEventListener('ux:map:rectangle:before-create', this._onRectangleBeforeCreate);
368+
this.element.addEventListener('ux:map:rectangle:after-create', this._onRectangleAfterCreate);
365369
}
366370
367371
disconnect() {
@@ -376,14 +380,31 @@ Symfony UX Map allows you to extend its default behavior using a custom Stimulus
376380
this.element.removeEventListener('ux:map:polygon:after-create', this._onPolygonAfterCreate);
377381
this.element.removeEventListener('ux:map:polyline:before-create', this._onPolylineBeforeCreate);
378382
this.element.removeEventListener('ux:map:polyline:after-create', this._onPolylineAfterCreate);
383+
this.element.removeEventListener('ux:map:circle:before-create', this._onCircleBeforeCreate);
384+
this.element.removeEventListener('ux:map:circle:after-create', this._onCircleAfterCreate);
385+
this.element.removeEventListener('ux:map:rectangle:before-create', this._onRectangleBeforeCreate);
386+
this.element.removeEventListener('ux:map:rectangle:after-create', this._onRectangleAfterCreate);
379387
}
380388
381389
/**
382390
* This event is triggered when the map is not created yet
383391
* You can use this event to configure the map before it is created
384392
*/
385393
_onPreConnect(event) {
394+
// You can read or write the zoom level
395+
console.log(event.detail.zoom);
396+
397+
// You can read or write the center of the map
398+
console.log(event.detail.center);
399+
400+
// You can read or write map options, specific to the Bridge, it represents the normalized `*Options` PHP class (e.g. `GoogleOptions`, `LeafletOptions`)
386401
console.log(event.detail.options);
402+
403+
// Finally, you can also set Bridge-specific options that will be used when creating the map.
404+
event.detail.bridgeOptions = {
405+
preferCanvas: true, // e.g. for Leaflet (https://leafletjs.com/reference.html#map-prefercanvas)
406+
backgroundColor: '#f0f0f0', // e.g. for Google Maps (https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.backgroundColor)
407+
}
387408
}
388409
389410
/**
@@ -442,6 +463,10 @@ Symfony UX Map allows you to extend its default behavior using a custom Stimulus
442463
console.log(event.detail.polygon);
443464
// ... or a polyline
444465
console.log(event.detail.polyline);
466+
// ... or a circle
467+
console.log(event.detail.circle);
468+
// ... or a rectangle
469+
console.log(event.detail.rectangle);
445470
}
446471
447472
/**
@@ -479,6 +504,26 @@ Symfony UX Map allows you to extend its default behavior using a custom Stimulus
479504
// The polyline instance
480505
console.log(event.detail.polyline);
481506
}
507+
508+
_onCircleBeforeCreate(event) {
509+
console.log(event.detail.definition);
510+
// { title: 'My circle', center: { lat: 48.8566, lng: 2.3522 }, radius: 1000, ... }
511+
}
512+
513+
_onCircleAfterCreate(event) {
514+
// The circle instance
515+
console.log(event.detail.circle);
516+
}
517+
518+
_onRectangleBeforeCreate(event) {
519+
console.log(event.detail.definition);
520+
// { title: 'My rectangle', southWest: { lat: 48.8566, lng: 2.3522 }, northEast: { lat: 45.7640, lng: 4.8357 }, ... }
521+
}
522+
523+
_onRectangleAfterCreate(event) {
524+
// The rectangle instance
525+
console.log(event.detail.rectangle);
526+
}
482527
}
483528
484529
Then, you can use this controller in your template:
@@ -521,6 +566,17 @@ events ``ux:map:*:before-create`` using the special ``bridgeOptions`` property:
521566
this.element.addEventListener('ux:map:info-window:before-create', this._onInfoWindowBeforeCreate);
522567
this.element.addEventListener('ux:map:polygon:before-create', this._onPolygonBeforeCreate);
523568
this.element.addEventListener('ux:map:polyline:before-create', this._onPolylineBeforeCreate);
569+
this.element.addEventListener('ux:map:circle:before-create', this._onCircleBeforeCreate);
570+
this.element.addEventListener('ux:map:rectangle:before-create', this._onRectangleBeforeCreate);
571+
}
572+
573+
disconnect() {
574+
this.element.removeEventListener('ux:map:marker:before-create', this._onMarkerBeforeCreate);
575+
this.element.removeEventListener('ux:map:info-window:before-create', this._onInfoWindowBeforeCreate);
576+
this.element.removeEventListener('ux:map:polygon:before-create', this._onPolygonBeforeCreate);
577+
this.element.removeEventListener('ux:map:polyline:before-create', this._onPolylineBeforeCreate);
578+
this.element.removeEventListener('ux:map:circle:before-create', this._onCircleBeforeCreate);
579+
this.element.removeEventListener('ux:map:rectangle:before-create', this._onRectangleBeforeCreate);
524580
}
525581
526582
_onMarkerBeforeCreate(event) {
@@ -578,6 +634,34 @@ events ``ux:map:*:before-create`` using the special ``bridgeOptions`` property:
578634
// ...
579635
};
580636
}
637+
638+
_onCircleBeforeCreate(event) {
639+
// When using Google Maps, to configure a `google.maps.Circle`
640+
event.detail.definition.bridgeOptions = {
641+
strokeColor: 'red',
642+
// ...
643+
};
644+
645+
// When using Leaflet, to configure a `L.Circle`
646+
event.detail.definition.bridgeOptions = {
647+
color: 'red',
648+
// ...
649+
};
650+
}
651+
652+
_onRectangleBeforeCreate(event) {
653+
// When using Google Maps, to configure a `google.maps.Rectangle`
654+
event.detail.definition.bridgeOptions = {
655+
strokeColor: 'red',
656+
// ...
657+
};
658+
659+
// When using Leaflet, to configure a `L.Rectangle`
660+
event.detail.definition.bridgeOptions = {
661+
color: 'red',
662+
// ...
663+
};
664+
}
581665
}
582666
583667
Advanced: Passing extra data from PHP to the Stimulus controller
@@ -591,7 +675,7 @@ These additional data points are defined and used exclusively by you; UX Map
591675
only forwards them to the Stimulus controller.
592676

593677
To pass extra data from PHP to the Stimulus controller, you must use the ``extra`` property
594-
available in ``Marker``, ``InfoWindow``, ``Polygon`` and ``Polyline`` instances::
678+
available in ``Marker``, ``InfoWindow``, ``Polygon``, ``Polyline``, ``Circle`` and ``Rectangle`` instances::
595679

596680
$map->addMarker(new Marker(
597681
position: new Point(48.822248, 2.337338),

‎src/Map/src/Bridge/Google/assets/dist/map_controller.d.ts‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
import type { LoaderOptions } from '@googlemaps/js-api-loader';
2-
import type { CircleDefinition, Icon, InfoWindowDefinition, MarkerDefinition, Point, PolygonDefinition, PolylineDefinition, RectangleDefinition } from '@symfony/ux-map';
2+
import type { CircleDefinition, Icon, InfoWindowDefinition, MapDefinition, MarkerDefinition, PolygonDefinition, PolylineDefinition, RectangleDefinition } from '@symfony/ux-map';
33
import AbstractMapController from '@symfony/ux-map';
44
type MapOptions = Pick<google.maps.MapOptions, 'mapId' | 'gestureHandling' | 'backgroundColor' | 'disableDoubleClickZoom' | 'zoomControl' | 'zoomControlOptions' | 'mapTypeControl' | 'mapTypeControlOptions' | 'streetViewControl' | 'streetViewControlOptions' | 'fullscreenControl' | 'fullscreenControlOptions'>;
5-
export default class extends AbstractMapController<MapOptions, google.maps.Map, google.maps.marker.AdvancedMarkerElementOptions, google.maps.marker.AdvancedMarkerElement, google.maps.InfoWindowOptions, google.maps.InfoWindow, google.maps.PolygonOptions, google.maps.Polygon, google.maps.PolylineOptions, google.maps.Polyline, google.maps.CircleOptions, google.maps.Circle, google.maps.RectangleOptions, google.maps.Rectangle> {
5+
export default class extends AbstractMapController<MapOptions, google.maps.MapOptions, google.maps.Map, google.maps.marker.AdvancedMarkerElementOptions, google.maps.marker.AdvancedMarkerElement, google.maps.InfoWindowOptions, google.maps.InfoWindow, google.maps.PolygonOptions, google.maps.Polygon, google.maps.PolylineOptions, google.maps.Polyline, google.maps.CircleOptions, google.maps.Circle, google.maps.RectangleOptions, google.maps.Rectangle> {
66
providerOptionsValue: Pick<LoaderOptions, 'apiKey' | 'id' | 'language' | 'region' | 'nonce' | 'retries' | 'url' | 'version' | 'libraries'>;
77
map: google.maps.Map;
8-
parser: DOMParser;
98
connect(): Promise<void>;
109
centerValueChanged(): void;
1110
zoomValueChanged(): void;
1211
protected dispatchEvent(name: string, payload?: Record<string, unknown>): void;
13-
protected doCreateMap({ center, zoom, options }: {
14-
center: Point | null;
15-
zoom: number | null;
16-
options: MapOptions;
12+
protected doCreateMap({ definition }: {
13+
definition: MapDefinition<MapOptions, google.maps.MapOptions>;
1714
}): google.maps.Map;
1815
protected doCreateMarker({ definition, }: {
1916
definition: MarkerDefinition<google.maps.marker.AdvancedMarkerElementOptions, google.maps.InfoWindowOptions>;

‎src/Map/src/Bridge/Google/assets/dist/map_controller.js‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ class default_1 extends Controller {
1818
this.isConnected = false;
1919
}
2020
connect() {
21-
const options = this.optionsValue;
22-
this.dispatchEvent('pre-connect', { options });
21+
const mapDefinition = {
22+
center: this.hasCenterValue ? this.centerValue : null,
23+
zoom: this.hasZoomValue ? this.zoomValue : null,
24+
options: this.optionsValue,
25+
};
26+
this.dispatchEvent('pre-connect', mapDefinition);
2327
this.createMarker = this.createDrawingFactory('marker', this.markers, this.doCreateMarker.bind(this));
2428
this.createPolygon = this.createDrawingFactory('polygon', this.polygons, this.doCreatePolygon.bind(this));
2529
this.createPolyline = this.createDrawingFactory('polyline', this.polylines, this.doCreatePolyline.bind(this));
2630
this.createCircle = this.createDrawingFactory('circle', this.circles, this.doCreateCircle.bind(this));
2731
this.createRectangle = this.createDrawingFactory('rectangle', this.rectangles, this.doCreateRectangle.bind(this));
28-
this.map = this.doCreateMap({
29-
center: this.hasCenterValue ? this.centerValue : null,
30-
zoom: this.hasZoomValue ? this.zoomValue : null,
31-
options,
32-
});
32+
this.map = this.doCreateMap({ definition: mapDefinition });
3333
this.markersValue.forEach((definition) => this.createMarker({ definition }));
3434
this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
3535
this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));
@@ -184,23 +184,23 @@ class map_controller extends default_1 {
184184
}
185185
}
186186
dispatchEvent(name, payload = {}) {
187+
payload.google = _google;
187188
this.dispatch(name, {
188189
prefix: 'ux:map',
189-
detail: {
190-
...payload,
191-
google: _google,
192-
},
190+
detail: payload,
193191
});
194192
}
195-
doCreateMap({ center, zoom, options }) {
193+
doCreateMap({ definition }) {
194+
const { center, zoom, options, bridgeOptions = {} } = definition;
196195
options.zoomControl = typeof options.zoomControlOptions !== 'undefined';
197196
options.mapTypeControl = typeof options.mapTypeControlOptions !== 'undefined';
198197
options.streetViewControl = typeof options.streetViewControlOptions !== 'undefined';
199198
options.fullscreenControl = typeof options.fullscreenControlOptions !== 'undefined';
200199
return new _google.maps.Map(this.element, {
201-
...options,
202200
center,
203201
zoom,
202+
...options,
203+
...bridgeOptions,
204204
});
205205
}
206206
doCreateMarker({ definition, }) {

‎src/Map/src/Bridge/Google/assets/src/map_controller.ts‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import type {
1313
CircleDefinition,
1414
Icon,
1515
InfoWindowDefinition,
16+
MapDefinition,
1617
MarkerDefinition,
17-
Point,
1818
PolygonDefinition,
1919
PolylineDefinition,
2020
RectangleDefinition,
@@ -48,6 +48,7 @@ const parser = new DOMParser();
4848

4949
export default class extends AbstractMapController<
5050
MapOptions,
51+
google.maps.MapOptions,
5152
google.maps.Map,
5253
google.maps.marker.AdvancedMarkerElementOptions,
5354
google.maps.marker.AdvancedMarkerElement,
@@ -66,8 +67,6 @@ export default class extends AbstractMapController<
6667

6768
declare map: google.maps.Map;
6869

69-
public parser: DOMParser;
70-
7170
async connect() {
7271
const onLoaded = () => super.connect();
7372

@@ -129,26 +128,27 @@ export default class extends AbstractMapController<
129128
}
130129

131130
protected dispatchEvent(name: string, payload: Record<string, unknown> = {}): void {
131+
payload.google = _google;
132132
this.dispatch(name, {
133133
prefix: 'ux:map',
134-
detail: {
135-
...payload,
136-
google: _google,
137-
},
134+
detail: payload,
138135
});
139136
}
140137

141-
protected doCreateMap({ center, zoom, options }: { center: Point | null; zoom: number | null; options: MapOptions }): google.maps.Map {
138+
protected doCreateMap({ definition }: { definition: MapDefinition<MapOptions, google.maps.MapOptions> }): google.maps.Map {
139+
const { center, zoom, options, bridgeOptions = {} } = definition;
140+
142141
// We assume the following control options are enabled if their options are set
143142
options.zoomControl = typeof options.zoomControlOptions !== 'undefined';
144143
options.mapTypeControl = typeof options.mapTypeControlOptions !== 'undefined';
145144
options.streetViewControl = typeof options.streetViewControlOptions !== 'undefined';
146145
options.fullscreenControl = typeof options.fullscreenControlOptions !== 'undefined';
147146

148147
return new _google.maps.Map(this.element, {
149-
...options,
150148
center,
151149
zoom,
150+
...options,
151+
...bridgeOptions,
152152
});
153153
}
154154

‎src/Map/src/Bridge/Leaflet/assets/dist/map_controller.d.ts‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import type { CircleDefinition, Icon, InfoWindowDefinition, MarkerDefinition, Point, PolygonDefinition, PolylineDefinition, RectangleDefinition } from '@symfony/ux-map';
1+
import type { CircleDefinition, Icon, InfoWindowDefinition, MapDefinition, MarkerDefinition, PolygonDefinition, PolylineDefinition, RectangleDefinition } from '@symfony/ux-map';
22
import AbstractMapController from '@symfony/ux-map';
33
import 'leaflet/dist/leaflet.min.css';
44
import type { CircleOptions, ControlPosition, MapOptions as LeafletMapOptions, MarkerOptions, PolylineOptions as PolygonOptions, PolylineOptions, PopupOptions, PolylineOptions as RectangleOptions } from 'leaflet';
55
import * as L from 'leaflet';
6-
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionControl' | 'zoomControl'> & {
6+
type MapOptions = Pick<LeafletMapOptions, 'attributionControl' | 'zoomControl'> & {
77
attributionControlOptions?: {
88
position: ControlPosition;
99
prefix: string | false;
@@ -21,16 +21,14 @@ type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionContro
2121
options: Record<string, unknown>;
2222
} | false;
2323
};
24-
export default class extends AbstractMapController<MapOptions, L.Map, MarkerOptions, L.Marker, PopupOptions, L.Popup, PolygonOptions, L.Polygon, PolylineOptions, L.Polyline, CircleOptions, L.Circle, RectangleOptions, L.Rectangle> {
24+
export default class extends AbstractMapController<MapOptions, LeafletMapOptions, L.Map, MarkerOptions, L.Marker, PopupOptions, L.Popup, PolygonOptions, L.Polygon, PolylineOptions, L.Polyline, CircleOptions, L.Circle, RectangleOptions, L.Rectangle> {
2525
map: L.Map;
2626
connect(): void;
2727
centerValueChanged(): void;
2828
zoomValueChanged(): void;
2929
protected dispatchEvent(name: string, payload?: Record<string, unknown>): void;
30-
protected doCreateMap({ center, zoom, options }: {
31-
center: Point | null;
32-
zoom: number | null;
33-
options: MapOptions;
30+
protected doCreateMap({ definition }: {
31+
definition: MapDefinition<MapOptions, LeafletMapOptions>;
3432
}): L.Map;
3533
protected doCreateMarker({ definition }: {
3634
definition: MarkerDefinition<MarkerOptions, PopupOptions>;

‎src/Map/src/Bridge/Leaflet/assets/dist/map_controller.js‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ class default_1 extends Controller {
1919
this.isConnected = false;
2020
}
2121
connect() {
22-
const options = this.optionsValue;
23-
this.dispatchEvent('pre-connect', { options });
22+
const mapDefinition = {
23+
center: this.hasCenterValue ? this.centerValue : null,
24+
zoom: this.hasZoomValue ? this.zoomValue : null,
25+
options: this.optionsValue,
26+
};
27+
this.dispatchEvent('pre-connect', mapDefinition);
2428
this.createMarker = this.createDrawingFactory('marker', this.markers, this.doCreateMarker.bind(this));
2529
this.createPolygon = this.createDrawingFactory('polygon', this.polygons, this.doCreatePolygon.bind(this));
2630
this.createPolyline = this.createDrawingFactory('polyline', this.polylines, this.doCreatePolyline.bind(this));
2731
this.createCircle = this.createDrawingFactory('circle', this.circles, this.doCreateCircle.bind(this));
2832
this.createRectangle = this.createDrawingFactory('rectangle', this.rectangles, this.doCreateRectangle.bind(this));
29-
this.map = this.doCreateMap({
30-
center: this.hasCenterValue ? this.centerValue : null,
31-
zoom: this.hasZoomValue ? this.zoomValue : null,
32-
options,
33-
});
33+
this.map = this.doCreateMap({ definition: mapDefinition });
3434
this.markersValue.forEach((definition) => this.createMarker({ definition }));
3535
this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
3636
this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));
@@ -156,21 +156,21 @@ class map_controller extends default_1 {
156156
}
157157
}
158158
dispatchEvent(name, payload = {}) {
159+
payload.L = L;
159160
this.dispatch(name, {
160161
prefix: 'ux:map',
161-
detail: {
162-
...payload,
163-
L,
164-
},
162+
detail: payload,
165163
});
166164
}
167-
doCreateMap({ center, zoom, options }) {
165+
doCreateMap({ definition }) {
166+
const { center, zoom, options, bridgeOptions = {} } = definition;
168167
const map = L.map(this.element, {
169-
...options,
170168
center: center === null ? undefined : center,
171169
zoom: zoom === null ? undefined : zoom,
172170
attributionControl: false,
173171
zoomControl: false,
172+
...options,
173+
...bridgeOptions,
174174
});
175175
if (options.tileLayer) {
176176
L.tileLayer(options.tileLayer.url, {

‎src/Map/src/Bridge/Leaflet/assets/src/map_controller.ts‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import type {
1111
CircleDefinition,
1212
Icon,
1313
InfoWindowDefinition,
14+
MapDefinition,
1415
MarkerDefinition,
15-
Point,
1616
PolygonDefinition,
1717
PolylineDefinition,
1818
RectangleDefinition,
@@ -32,7 +32,7 @@ import type {
3232
} from 'leaflet';
3333
import * as L from 'leaflet';
3434

35-
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionControl' | 'zoomControl'> & {
35+
type MapOptions = Pick<LeafletMapOptions, 'attributionControl' | 'zoomControl'> & {
3636
attributionControlOptions?: { position: ControlPosition; prefix: string | false };
3737
zoomControlOptions?: {
3838
position: ControlPosition;
@@ -46,6 +46,7 @@ type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionContro
4646

4747
export default class extends AbstractMapController<
4848
MapOptions,
49+
LeafletMapOptions,
4950
L.Map,
5051
MarkerOptions,
5152
L.Marker,
@@ -87,22 +88,23 @@ export default class extends AbstractMapController<
8788
}
8889

8990
protected dispatchEvent(name: string, payload: Record<string, unknown> = {}): void {
91+
payload.L = L;
9092
this.dispatch(name, {
9193
prefix: 'ux:map',
92-
detail: {
93-
...payload,
94-
L,
95-
},
94+
detail: payload,
9695
});
9796
}
9897

99-
protected doCreateMap({ center, zoom, options }: { center: Point | null; zoom: number | null; options: MapOptions }): L.Map {
98+
protected doCreateMap({ definition }: { definition: MapDefinition<MapOptions, LeafletMapOptions> }): L.Map {
99+
const { center, zoom, options, bridgeOptions = {} } = definition;
100+
100101
const map = L.map(this.element, {
101-
...options,
102102
center: center === null ? undefined : center,
103103
zoom: zoom === null ? undefined : zoom,
104104
attributionControl: false,
105105
zoomControl: false,
106+
...options,
107+
...bridgeOptions,
106108
});
107109

108110
if (options.tileLayer) {

0 commit comments

Comments
 (0)
Please sign in to comment.