@symfony/ux-google-map 2.27.0 → 2.28.1

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.
@@ -1,13 +1,15 @@
1
- import type { LoaderOptions } from '@googlemaps/js-api-loader';
2
- import type { CircleDefinition, Icon, InfoWindowDefinition, MapDefinition, MarkerDefinition, PolygonDefinition, PolylineDefinition, RectangleDefinition } from '@symfony/ux-map';
3
- import AbstractMapController from '@symfony/ux-map';
1
+ import { LoaderOptions } from '@googlemaps/js-api-loader';
2
+ import AbstractMapController, { MapDefinition, MarkerDefinition, PolygonDefinition, PolylineDefinition, CircleDefinition, RectangleDefinition, InfoWindowDefinition, Icon } from '@symfony/ux-map';
3
+
4
4
  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.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
+ declare class export_default 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> {
6
6
  providerOptionsValue: Pick<LoaderOptions, 'apiKey' | 'id' | 'language' | 'region' | 'nonce' | 'retries' | 'url' | 'version' | 'libraries'>;
7
7
  map: google.maps.Map;
8
8
  connect(): Promise<void>;
9
9
  centerValueChanged(): void;
10
10
  zoomValueChanged(): void;
11
+ minZoomValueChanged(): void;
12
+ maxZoomValueChanged(): void;
11
13
  protected dispatchEvent(name: string, payload?: Record<string, unknown>): void;
12
14
  protected doCreateMap({ definition }: {
13
15
  definition: MapDefinition<MapOptions, google.maps.MapOptions>;
@@ -44,4 +46,5 @@ export default class extends AbstractMapController<MapOptions, google.maps.MapOp
44
46
  }): void;
45
47
  private closeInfoWindowsExcept;
46
48
  }
47
- export {};
49
+
50
+ export { export_default as default };
@@ -1,394 +1,428 @@
1
- import { Loader } from '@googlemaps/js-api-loader';
2
- import { Controller } from '@hotwired/stimulus';
1
+ // src/map_controller.ts
2
+ import { Loader } from "@googlemaps/js-api-loader";
3
3
 
4
- const IconTypes = {
5
- Url: 'url',
6
- Svg: 'svg',
7
- UxIcon: 'ux-icon',
4
+ // ../../../../assets/dist/abstract_map_controller.js
5
+ import { Controller } from "@hotwired/stimulus";
6
+ var IconTypes = {
7
+ Url: "url",
8
+ Svg: "svg",
9
+ UxIcon: "ux-icon"
8
10
  };
9
- class default_1 extends Controller {
10
- constructor() {
11
- super(...arguments);
12
- this.markers = new Map();
13
- this.polygons = new Map();
14
- this.polylines = new Map();
15
- this.circles = new Map();
16
- this.rectangles = new Map();
17
- this.infoWindows = [];
18
- this.isConnected = false;
11
+ var abstract_map_controller_default = class extends Controller {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.markers = /* @__PURE__ */ new Map();
15
+ this.polygons = /* @__PURE__ */ new Map();
16
+ this.polylines = /* @__PURE__ */ new Map();
17
+ this.circles = /* @__PURE__ */ new Map();
18
+ this.rectangles = /* @__PURE__ */ new Map();
19
+ this.infoWindows = [];
20
+ this.isConnected = false;
21
+ }
22
+ connect() {
23
+ const extra = this.hasExtraValue ? this.extraValue : {};
24
+ const mapDefinition = {
25
+ center: this.hasCenterValue ? this.centerValue : null,
26
+ zoom: this.hasZoomValue ? this.zoomValue : null,
27
+ minZoom: this.hasMinZoomValue ? this.minZoomValue : null,
28
+ maxZoom: this.hasMaxZoomValue ? this.maxZoomValue : null,
29
+ options: this.optionsValue,
30
+ extra
31
+ };
32
+ this.dispatchEvent("pre-connect", mapDefinition);
33
+ this.createMarker = this.createDrawingFactory("marker", this.markers, this.doCreateMarker.bind(this));
34
+ this.createPolygon = this.createDrawingFactory("polygon", this.polygons, this.doCreatePolygon.bind(this));
35
+ this.createPolyline = this.createDrawingFactory("polyline", this.polylines, this.doCreatePolyline.bind(this));
36
+ this.createCircle = this.createDrawingFactory("circle", this.circles, this.doCreateCircle.bind(this));
37
+ this.createRectangle = this.createDrawingFactory("rectangle", this.rectangles, this.doCreateRectangle.bind(this));
38
+ this.map = this.doCreateMap({ definition: mapDefinition });
39
+ this.markersValue.forEach((definition) => this.createMarker({ definition }));
40
+ this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
41
+ this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));
42
+ this.circlesValue.forEach((definition) => this.createCircle({ definition }));
43
+ this.rectanglesValue.forEach((definition) => this.createRectangle({ definition }));
44
+ if (this.fitBoundsToMarkersValue) {
45
+ this.doFitBoundsToMarkers();
19
46
  }
20
- connect() {
21
- const extra = this.hasExtraValue ? this.extraValue : {};
22
- const mapDefinition = {
23
- center: this.hasCenterValue ? this.centerValue : null,
24
- zoom: this.hasZoomValue ? this.zoomValue : null,
25
- options: this.optionsValue,
26
- extra,
27
- };
28
- this.dispatchEvent('pre-connect', mapDefinition);
29
- this.createMarker = this.createDrawingFactory('marker', this.markers, this.doCreateMarker.bind(this));
30
- this.createPolygon = this.createDrawingFactory('polygon', this.polygons, this.doCreatePolygon.bind(this));
31
- this.createPolyline = this.createDrawingFactory('polyline', this.polylines, this.doCreatePolyline.bind(this));
32
- this.createCircle = this.createDrawingFactory('circle', this.circles, this.doCreateCircle.bind(this));
33
- this.createRectangle = this.createDrawingFactory('rectangle', this.rectangles, this.doCreateRectangle.bind(this));
34
- this.map = this.doCreateMap({ definition: mapDefinition });
35
- this.markersValue.forEach((definition) => this.createMarker({ definition }));
36
- this.polygonsValue.forEach((definition) => this.createPolygon({ definition }));
37
- this.polylinesValue.forEach((definition) => this.createPolyline({ definition }));
38
- this.circlesValue.forEach((definition) => this.createCircle({ definition }));
39
- this.rectanglesValue.forEach((definition) => this.createRectangle({ definition }));
40
- if (this.fitBoundsToMarkersValue) {
41
- this.doFitBoundsToMarkers();
42
- }
43
- this.dispatchEvent('connect', {
44
- map: this.map,
45
- markers: [...this.markers.values()],
46
- polygons: [...this.polygons.values()],
47
- polylines: [...this.polylines.values()],
48
- circles: [...this.circles.values()],
49
- rectangles: [...this.rectangles.values()],
50
- infoWindows: this.infoWindows,
51
- extra,
52
- });
53
- this.isConnected = true;
47
+ this.dispatchEvent("connect", {
48
+ map: this.map,
49
+ markers: [...this.markers.values()],
50
+ polygons: [...this.polygons.values()],
51
+ polylines: [...this.polylines.values()],
52
+ circles: [...this.circles.values()],
53
+ rectangles: [...this.rectangles.values()],
54
+ infoWindows: this.infoWindows,
55
+ extra
56
+ });
57
+ this.isConnected = true;
58
+ }
59
+ //region Public API
60
+ createInfoWindow({
61
+ definition,
62
+ element
63
+ }) {
64
+ this.dispatchEvent("info-window:before-create", { definition, element });
65
+ const infoWindow = this.doCreateInfoWindow({ definition, element });
66
+ this.dispatchEvent("info-window:after-create", { infoWindow, definition, element });
67
+ this.infoWindows.push(infoWindow);
68
+ return infoWindow;
69
+ }
70
+ markersValueChanged() {
71
+ if (!this.isConnected) {
72
+ return;
54
73
  }
55
- createInfoWindow({ definition, element, }) {
56
- this.dispatchEvent('info-window:before-create', { definition, element });
57
- const infoWindow = this.doCreateInfoWindow({ definition, element });
58
- this.dispatchEvent('info-window:after-create', { infoWindow, definition, element });
59
- this.infoWindows.push(infoWindow);
60
- return infoWindow;
74
+ this.onDrawChanged(this.markers, this.markersValue, this.createMarker, this.doRemoveMarker);
75
+ if (this.fitBoundsToMarkersValue) {
76
+ this.doFitBoundsToMarkers();
61
77
  }
62
- markersValueChanged() {
63
- if (!this.isConnected) {
64
- return;
65
- }
66
- this.onDrawChanged(this.markers, this.markersValue, this.createMarker, this.doRemoveMarker);
67
- if (this.fitBoundsToMarkersValue) {
68
- this.doFitBoundsToMarkers();
69
- }
78
+ }
79
+ polygonsValueChanged() {
80
+ if (!this.isConnected) {
81
+ return;
70
82
  }
71
- polygonsValueChanged() {
72
- if (!this.isConnected) {
73
- return;
74
- }
75
- this.onDrawChanged(this.polygons, this.polygonsValue, this.createPolygon, this.doRemovePolygon);
83
+ this.onDrawChanged(this.polygons, this.polygonsValue, this.createPolygon, this.doRemovePolygon);
84
+ }
85
+ polylinesValueChanged() {
86
+ if (!this.isConnected) {
87
+ return;
76
88
  }
77
- polylinesValueChanged() {
78
- if (!this.isConnected) {
79
- return;
80
- }
81
- this.onDrawChanged(this.polylines, this.polylinesValue, this.createPolyline, this.doRemovePolyline);
89
+ this.onDrawChanged(this.polylines, this.polylinesValue, this.createPolyline, this.doRemovePolyline);
90
+ }
91
+ circlesValueChanged() {
92
+ if (!this.isConnected) {
93
+ return;
82
94
  }
83
- circlesValueChanged() {
84
- if (!this.isConnected) {
85
- return;
86
- }
87
- this.onDrawChanged(this.circles, this.circlesValue, this.createCircle, this.doRemoveCircle);
95
+ this.onDrawChanged(this.circles, this.circlesValue, this.createCircle, this.doRemoveCircle);
96
+ }
97
+ rectanglesValueChanged() {
98
+ if (!this.isConnected) {
99
+ return;
88
100
  }
89
- rectanglesValueChanged() {
90
- if (!this.isConnected) {
91
- return;
92
- }
93
- this.onDrawChanged(this.rectangles, this.rectanglesValue, this.createRectangle, this.doRemoveRectangle);
94
- }
95
- createDrawingFactory(type, draws, factory) {
96
- const eventBefore = `${type}:before-create`;
97
- const eventAfter = `${type}:after-create`;
98
- return ({ definition }) => {
99
- this.dispatchEvent(eventBefore, { definition });
100
- if (typeof definition.rawOptions !== 'undefined') {
101
- console.warn(`[Symfony UX Map] The event "${eventBefore}" added a deprecated "rawOptions" property to the definition, it will be removed in a next major version, replace it with "bridgeOptions" instead.`, definition);
102
- }
103
- const drawing = factory({ definition });
104
- this.dispatchEvent(eventAfter, { [type]: drawing, definition });
105
- draws.set(definition['@id'], drawing);
106
- return drawing;
107
- };
108
- }
109
- onDrawChanged(draws, newDrawDefinitions, factory, remover) {
110
- const idsToRemove = new Set(draws.keys());
111
- newDrawDefinitions.forEach((definition) => {
112
- idsToRemove.delete(definition['@id']);
113
- });
114
- idsToRemove.forEach((id) => {
115
- const draw = draws.get(id);
116
- remover(draw);
117
- draws.delete(id);
118
- });
119
- newDrawDefinitions.forEach((definition) => {
120
- if (!draws.has(definition['@id'])) {
121
- factory({ definition });
122
- }
123
- });
124
- }
125
- }
126
- default_1.values = {
127
- providerOptions: Object,
128
- center: Object,
129
- zoom: Number,
130
- fitBoundsToMarkers: Boolean,
131
- markers: Array,
132
- polygons: Array,
133
- polylines: Array,
134
- circles: Array,
135
- rectangles: Array,
136
- options: Object,
137
- extra: Object,
101
+ this.onDrawChanged(this.rectangles, this.rectanglesValue, this.createRectangle, this.doRemoveRectangle);
102
+ }
103
+ createDrawingFactory(type, draws, factory) {
104
+ const eventBefore = `${type}:before-create`;
105
+ const eventAfter = `${type}:after-create`;
106
+ return ({ definition }) => {
107
+ this.dispatchEvent(eventBefore, { definition });
108
+ if (typeof definition.rawOptions !== "undefined") {
109
+ console.warn(
110
+ `[Symfony UX Map] The event "${eventBefore}" added a deprecated "rawOptions" property to the definition, it will be removed in a next major version, replace it with "bridgeOptions" instead.`,
111
+ definition
112
+ );
113
+ }
114
+ const drawing = factory({ definition });
115
+ this.dispatchEvent(eventAfter, { [type]: drawing, definition });
116
+ draws.set(definition["@id"], drawing);
117
+ return drawing;
118
+ };
119
+ }
120
+ onDrawChanged(draws, newDrawDefinitions, factory, remover) {
121
+ const idsToRemove = new Set(draws.keys());
122
+ newDrawDefinitions.forEach((definition) => {
123
+ idsToRemove.delete(definition["@id"]);
124
+ });
125
+ idsToRemove.forEach((id) => {
126
+ const draw = draws.get(id);
127
+ remover(draw);
128
+ draws.delete(id);
129
+ });
130
+ newDrawDefinitions.forEach((definition) => {
131
+ if (!draws.has(definition["@id"])) {
132
+ factory({ definition });
133
+ }
134
+ });
135
+ }
136
+ //endregion
137
+ };
138
+ abstract_map_controller_default.values = {
139
+ providerOptions: Object,
140
+ center: Object,
141
+ zoom: Number,
142
+ minZoom: Number,
143
+ maxZoom: Number,
144
+ fitBoundsToMarkers: Boolean,
145
+ markers: Array,
146
+ polygons: Array,
147
+ polylines: Array,
148
+ circles: Array,
149
+ rectangles: Array,
150
+ options: Object,
151
+ extra: Object
138
152
  };
139
153
 
140
- let _google;
141
- let _loading = false;
142
- let _loaded = false;
143
- let _onLoadedCallbacks = [];
144
- const parser = new DOMParser();
145
- class map_controller extends default_1 {
146
- async connect() {
147
- const onLoaded = () => super.connect();
148
- if (_loaded) {
149
- onLoaded();
150
- return;
151
- }
152
- if (_loading) {
153
- _onLoadedCallbacks.push(onLoaded);
154
- return;
155
- }
156
- _loading = true;
157
- _google = { maps: {} };
158
- let { libraries = [], ...loaderOptions } = this.providerOptionsValue;
159
- const loader = new Loader(loaderOptions);
160
- libraries = ['core', ...libraries.filter((library) => library !== 'core')];
161
- const librariesImplementations = await Promise.all(libraries.map((library) => loader.importLibrary(library)));
162
- librariesImplementations.map((libraryImplementation, index) => {
163
- if (typeof libraryImplementation !== 'object' || libraryImplementation === null) {
164
- return;
165
- }
166
- const library = libraries[index];
167
- if (['marker', 'places', 'geometry', 'journeySharing', 'drawing', 'visualization'].includes(library)) {
168
- _google.maps[library] = libraryImplementation;
169
- }
170
- else {
171
- _google.maps = { ..._google.maps, ...libraryImplementation };
172
- }
173
- });
174
- _loading = false;
175
- _loaded = true;
176
- onLoaded();
177
- _onLoadedCallbacks.forEach((callback) => callback());
178
- _onLoadedCallbacks = [];
154
+ // src/map_controller.ts
155
+ var _google;
156
+ var _loading = false;
157
+ var _loaded = false;
158
+ var _onLoadedCallbacks = [];
159
+ var parser = new DOMParser();
160
+ var map_controller_default = class extends abstract_map_controller_default {
161
+ async connect() {
162
+ const onLoaded = () => super.connect();
163
+ if (_loaded) {
164
+ onLoaded();
165
+ return;
179
166
  }
180
- centerValueChanged() {
181
- if (this.map && this.hasCenterValue && this.centerValue) {
182
- this.map.setCenter(this.centerValue);
183
- }
167
+ if (_loading) {
168
+ _onLoadedCallbacks.push(onLoaded);
169
+ return;
184
170
  }
185
- zoomValueChanged() {
186
- if (this.map && this.hasZoomValue && this.zoomValue) {
187
- this.map.setZoom(this.zoomValue);
188
- }
171
+ _loading = true;
172
+ _google = { maps: {} };
173
+ let { libraries = [], ...loaderOptions } = this.providerOptionsValue;
174
+ const loader = new Loader(loaderOptions);
175
+ libraries = ["core", ...libraries.filter((library) => library !== "core")];
176
+ const librariesImplementations = await Promise.all(libraries.map((library) => loader.importLibrary(library)));
177
+ librariesImplementations.map((libraryImplementation, index) => {
178
+ if (typeof libraryImplementation !== "object" || libraryImplementation === null) {
179
+ return;
180
+ }
181
+ const library = libraries[index];
182
+ if (["marker", "places", "geometry", "journeySharing", "drawing", "visualization"].includes(library)) {
183
+ _google.maps[library] = libraryImplementation;
184
+ } else {
185
+ _google.maps = { ..._google.maps, ...libraryImplementation };
186
+ }
187
+ });
188
+ _loading = false;
189
+ _loaded = true;
190
+ onLoaded();
191
+ _onLoadedCallbacks.forEach((callback) => callback());
192
+ _onLoadedCallbacks = [];
193
+ }
194
+ centerValueChanged() {
195
+ if (this.map && this.hasCenterValue && this.centerValue) {
196
+ this.map.setCenter(this.centerValue);
189
197
  }
190
- dispatchEvent(name, payload = {}) {
191
- payload.google = _google;
192
- this.dispatch(name, {
193
- prefix: 'ux:map',
194
- detail: payload,
195
- });
198
+ }
199
+ zoomValueChanged() {
200
+ if (this.map && this.hasZoomValue && this.zoomValue) {
201
+ this.map.setZoom(this.zoomValue);
196
202
  }
197
- doCreateMap({ definition }) {
198
- const { center, zoom, options, bridgeOptions = {} } = definition;
199
- options.zoomControl = typeof options.zoomControlOptions !== 'undefined';
200
- options.mapTypeControl = typeof options.mapTypeControlOptions !== 'undefined';
201
- options.streetViewControl = typeof options.streetViewControlOptions !== 'undefined';
202
- options.fullscreenControl = typeof options.fullscreenControlOptions !== 'undefined';
203
- return new _google.maps.Map(this.element, {
204
- center,
205
- zoom,
206
- ...options,
207
- ...bridgeOptions,
208
- });
203
+ }
204
+ minZoomValueChanged() {
205
+ if (this.map && this.hasMinZoomValue && this.minZoomValue) {
206
+ this.map.setOptions({ minZoom: this.minZoomValue });
209
207
  }
210
- doCreateMarker({ definition, }) {
211
- const { '@id': _id, position, title, infoWindow, icon, rawOptions = {}, bridgeOptions = {} } = definition;
212
- const marker = new _google.maps.marker.AdvancedMarkerElement({
213
- position,
214
- title,
215
- map: this.map,
216
- ...rawOptions,
217
- ...bridgeOptions,
218
- });
219
- if (infoWindow) {
220
- this.createInfoWindow({ definition: infoWindow, element: marker });
221
- }
222
- if (icon) {
223
- this.doCreateIcon({ definition: icon, element: marker });
224
- }
225
- return marker;
208
+ }
209
+ maxZoomValueChanged() {
210
+ if (this.map && this.hasMaxZoomValue && this.maxZoomValue) {
211
+ this.map.setOptions({ maxZoom: this.maxZoomValue });
226
212
  }
227
- doRemoveMarker(marker) {
228
- marker.map = null;
213
+ }
214
+ dispatchEvent(name, payload = {}) {
215
+ payload.google = _google;
216
+ this.dispatch(name, {
217
+ prefix: "ux:map",
218
+ detail: payload
219
+ });
220
+ }
221
+ doCreateMap({ definition }) {
222
+ const { center, zoom, minZoom, maxZoom, options, bridgeOptions = {} } = definition;
223
+ options.zoomControl = typeof options.zoomControlOptions !== "undefined";
224
+ options.mapTypeControl = typeof options.mapTypeControlOptions !== "undefined";
225
+ options.streetViewControl = typeof options.streetViewControlOptions !== "undefined";
226
+ options.fullscreenControl = typeof options.fullscreenControlOptions !== "undefined";
227
+ return new _google.maps.Map(this.element, {
228
+ center,
229
+ zoom,
230
+ minZoom,
231
+ maxZoom,
232
+ ...options,
233
+ ...bridgeOptions
234
+ });
235
+ }
236
+ doCreateMarker({
237
+ definition
238
+ }) {
239
+ const { "@id": _id, position, title, infoWindow, icon, rawOptions = {}, bridgeOptions = {} } = definition;
240
+ const marker = new _google.maps.marker.AdvancedMarkerElement({
241
+ position,
242
+ title,
243
+ map: this.map,
244
+ ...rawOptions,
245
+ ...bridgeOptions
246
+ });
247
+ if (infoWindow) {
248
+ this.createInfoWindow({ definition: infoWindow, element: marker });
229
249
  }
230
- doCreatePolygon({ definition, }) {
231
- const { '@id': _id, points, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
232
- const polygon = new _google.maps.Polygon({
233
- paths: points,
234
- map: this.map,
235
- ...rawOptions,
236
- ...bridgeOptions,
237
- });
238
- if (title) {
239
- polygon.set('title', title);
240
- }
241
- if (infoWindow) {
242
- this.createInfoWindow({ definition: infoWindow, element: polygon });
243
- }
244
- return polygon;
250
+ if (icon) {
251
+ this.doCreateIcon({ definition: icon, element: marker });
245
252
  }
246
- doRemovePolygon(polygon) {
247
- polygon.setMap(null);
253
+ return marker;
254
+ }
255
+ doRemoveMarker(marker) {
256
+ marker.map = null;
257
+ }
258
+ doCreatePolygon({
259
+ definition
260
+ }) {
261
+ const { "@id": _id, points, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
262
+ const polygon = new _google.maps.Polygon({
263
+ paths: points,
264
+ map: this.map,
265
+ ...rawOptions,
266
+ ...bridgeOptions
267
+ });
268
+ if (title) {
269
+ polygon.set("title", title);
248
270
  }
249
- doCreatePolyline({ definition, }) {
250
- const { '@id': _id, points, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
251
- const polyline = new _google.maps.Polyline({
252
- path: points,
253
- map: this.map,
254
- ...rawOptions,
255
- ...bridgeOptions,
256
- });
257
- if (title) {
258
- polyline.set('title', title);
259
- }
260
- if (infoWindow) {
261
- this.createInfoWindow({ definition: infoWindow, element: polyline });
262
- }
263
- return polyline;
271
+ if (infoWindow) {
272
+ this.createInfoWindow({ definition: infoWindow, element: polygon });
264
273
  }
265
- doRemovePolyline(polyline) {
266
- polyline.setMap(null);
274
+ return polygon;
275
+ }
276
+ doRemovePolygon(polygon) {
277
+ polygon.setMap(null);
278
+ }
279
+ doCreatePolyline({
280
+ definition
281
+ }) {
282
+ const { "@id": _id, points, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
283
+ const polyline = new _google.maps.Polyline({
284
+ path: points,
285
+ map: this.map,
286
+ ...rawOptions,
287
+ ...bridgeOptions
288
+ });
289
+ if (title) {
290
+ polyline.set("title", title);
267
291
  }
268
- doCreateCircle({ definition }) {
269
- const { '@id': _id, center, radius, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
270
- const circle = new _google.maps.Circle({
271
- center,
272
- radius,
273
- map: this.map,
274
- ...rawOptions,
275
- ...bridgeOptions,
276
- });
277
- if (title) {
278
- circle.set('title', title);
279
- }
280
- if (infoWindow) {
281
- this.createInfoWindow({ definition: infoWindow, element: circle });
282
- }
283
- return circle;
292
+ if (infoWindow) {
293
+ this.createInfoWindow({ definition: infoWindow, element: polyline });
284
294
  }
285
- doRemoveCircle(circle) {
286
- circle.setMap(null);
295
+ return polyline;
296
+ }
297
+ doRemovePolyline(polyline) {
298
+ polyline.setMap(null);
299
+ }
300
+ doCreateCircle({ definition }) {
301
+ const { "@id": _id, center, radius, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
302
+ const circle = new _google.maps.Circle({
303
+ center,
304
+ radius,
305
+ map: this.map,
306
+ ...rawOptions,
307
+ ...bridgeOptions
308
+ });
309
+ if (title) {
310
+ circle.set("title", title);
287
311
  }
288
- doCreateRectangle({ definition, }) {
289
- const { northEast, southWest, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
290
- const rectangle = new _google.maps.Rectangle({
291
- bounds: new _google.maps.LatLngBounds(southWest, northEast),
292
- map: this.map,
293
- ...rawOptions,
294
- ...bridgeOptions,
295
- });
296
- if (title) {
297
- rectangle.set('title', title);
298
- }
299
- if (infoWindow) {
300
- this.createInfoWindow({ definition: infoWindow, element: rectangle });
301
- }
302
- return rectangle;
312
+ if (infoWindow) {
313
+ this.createInfoWindow({ definition: infoWindow, element: circle });
303
314
  }
304
- doRemoveRectangle(rectangle) {
305
- rectangle.setMap(null);
315
+ return circle;
316
+ }
317
+ doRemoveCircle(circle) {
318
+ circle.setMap(null);
319
+ }
320
+ doCreateRectangle({
321
+ definition
322
+ }) {
323
+ const { northEast, southWest, title, infoWindow, rawOptions = {}, bridgeOptions = {} } = definition;
324
+ const rectangle = new _google.maps.Rectangle({
325
+ bounds: new _google.maps.LatLngBounds(southWest, northEast),
326
+ map: this.map,
327
+ ...rawOptions,
328
+ ...bridgeOptions
329
+ });
330
+ if (title) {
331
+ rectangle.set("title", title);
306
332
  }
307
- doCreateInfoWindow({ definition, element, }) {
308
- const { headerContent, content, opened, autoClose, rawOptions = {}, bridgeOptions = {} } = definition;
309
- let position = null;
310
- if (element instanceof google.maps.Circle) {
311
- position = element.getCenter();
312
- }
313
- else if (element instanceof google.maps.Rectangle) {
314
- position = element.getBounds()?.getCenter() || null;
315
- }
316
- else if (element instanceof google.maps.Polygon || element instanceof google.maps.Polyline) ;
317
- const infoWindowOptions = {
318
- headerContent: this.createTextOrElement(headerContent),
319
- content: this.createTextOrElement(content),
320
- position,
321
- ...rawOptions,
322
- ...bridgeOptions,
323
- };
324
- const infoWindow = new _google.maps.InfoWindow(infoWindowOptions);
325
- element.addListener('click', (event) => {
326
- if (autoClose) {
327
- this.closeInfoWindowsExcept(infoWindow);
328
- }
329
- if (infoWindowOptions.position === null) {
330
- infoWindow.setPosition(event.latLng);
331
- }
332
- infoWindow.open({ map: this.map, anchor: element });
333
- });
334
- if (opened) {
335
- if (autoClose) {
336
- this.closeInfoWindowsExcept(infoWindow);
337
- }
338
- infoWindow.open({ map: this.map, anchor: element });
339
- }
340
- return infoWindow;
333
+ if (infoWindow) {
334
+ this.createInfoWindow({ definition: infoWindow, element: rectangle });
341
335
  }
342
- doFitBoundsToMarkers() {
343
- if (this.markers.size === 0) {
344
- return;
345
- }
346
- const bounds = new google.maps.LatLngBounds();
347
- this.markers.forEach((marker) => {
348
- if (!marker.position) {
349
- return;
350
- }
351
- bounds.extend(marker.position);
352
- });
353
- this.map.fitBounds(bounds);
336
+ return rectangle;
337
+ }
338
+ doRemoveRectangle(rectangle) {
339
+ rectangle.setMap(null);
340
+ }
341
+ doCreateInfoWindow({
342
+ definition,
343
+ element
344
+ }) {
345
+ const { headerContent, content, opened, autoClose, rawOptions = {}, bridgeOptions = {} } = definition;
346
+ let position = null;
347
+ if (element instanceof google.maps.Circle) {
348
+ position = element.getCenter();
349
+ } else if (element instanceof google.maps.Rectangle) {
350
+ position = element.getBounds()?.getCenter() || null;
351
+ } else if (element instanceof google.maps.Polygon || element instanceof google.maps.Polyline) {
354
352
  }
355
- createTextOrElement(content) {
356
- if (!content) {
357
- return null;
358
- }
359
- if (content.includes('<')) {
360
- const div = document.createElement('div');
361
- div.innerHTML = content;
362
- return div;
363
- }
364
- return content;
353
+ const infoWindowOptions = {
354
+ headerContent: this.createTextOrElement(headerContent),
355
+ content: this.createTextOrElement(content),
356
+ position,
357
+ ...rawOptions,
358
+ ...bridgeOptions
359
+ };
360
+ const infoWindow = new _google.maps.InfoWindow(infoWindowOptions);
361
+ element.addListener("click", (event) => {
362
+ if (autoClose) {
363
+ this.closeInfoWindowsExcept(infoWindow);
364
+ }
365
+ if (infoWindowOptions.position === null) {
366
+ infoWindow.setPosition(event.latLng);
367
+ }
368
+ infoWindow.open({ map: this.map, anchor: element });
369
+ });
370
+ if (opened) {
371
+ if (autoClose) {
372
+ this.closeInfoWindowsExcept(infoWindow);
373
+ }
374
+ infoWindow.open({ map: this.map, anchor: element });
365
375
  }
366
- doCreateIcon({ definition, element }) {
367
- const { type, width, height } = definition;
368
- if (type === IconTypes.Svg) {
369
- element.content = parser.parseFromString(definition.html, 'image/svg+xml').documentElement;
370
- }
371
- else if (type === IconTypes.UxIcon) {
372
- element.content = parser.parseFromString(definition._generated_html, 'image/svg+xml').documentElement;
373
- }
374
- else if (type === IconTypes.Url) {
375
- const icon = document.createElement('img');
376
- icon.width = width;
377
- icon.height = height;
378
- icon.src = definition.url;
379
- element.content = icon;
380
- }
381
- else {
382
- throw new Error(`Unsupported icon type: ${type}.`);
383
- }
376
+ return infoWindow;
377
+ }
378
+ doFitBoundsToMarkers() {
379
+ if (this.markers.size === 0) {
380
+ return;
384
381
  }
385
- closeInfoWindowsExcept(infoWindow) {
386
- this.infoWindows.forEach((otherInfoWindow) => {
387
- if (otherInfoWindow !== infoWindow) {
388
- otherInfoWindow.close();
389
- }
390
- });
382
+ const bounds = new google.maps.LatLngBounds();
383
+ this.markers.forEach((marker) => {
384
+ if (!marker.position) {
385
+ return;
386
+ }
387
+ bounds.extend(marker.position);
388
+ });
389
+ this.map.fitBounds(bounds);
390
+ }
391
+ createTextOrElement(content) {
392
+ if (!content) {
393
+ return null;
391
394
  }
392
- }
393
-
394
- export { map_controller as default };
395
+ if (content.includes("<")) {
396
+ const div = document.createElement("div");
397
+ div.innerHTML = content;
398
+ return div;
399
+ }
400
+ return content;
401
+ }
402
+ doCreateIcon({ definition, element }) {
403
+ const { type, width, height } = definition;
404
+ if (type === IconTypes.Svg) {
405
+ element.content = parser.parseFromString(definition.html, "image/svg+xml").documentElement;
406
+ } else if (type === IconTypes.UxIcon) {
407
+ element.content = parser.parseFromString(definition._generated_html, "image/svg+xml").documentElement;
408
+ } else if (type === IconTypes.Url) {
409
+ const icon = document.createElement("img");
410
+ icon.width = width;
411
+ icon.height = height;
412
+ icon.src = definition.url;
413
+ element.content = icon;
414
+ } else {
415
+ throw new Error(`Unsupported icon type: ${type}.`);
416
+ }
417
+ }
418
+ closeInfoWindowsExcept(infoWindow) {
419
+ this.infoWindows.forEach((otherInfoWindow) => {
420
+ if (otherInfoWindow !== infoWindow) {
421
+ otherInfoWindow.close();
422
+ }
423
+ });
424
+ }
425
+ };
426
+ export {
427
+ map_controller_default as default
428
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@symfony/ux-google-map",
3
3
  "description": "GoogleMaps bridge for Symfony UX Map, integrate interactive maps in your Symfony applications",
4
4
  "license": "MIT",
5
- "version": "2.27.0",
5
+ "version": "2.28.1",
6
6
  "keywords": [
7
7
  "symfony-ux",
8
8
  "google-maps",
@@ -16,13 +16,6 @@
16
16
  ],
17
17
  "main": "dist/map_controller.js",
18
18
  "types": "dist/map_controller.d.ts",
19
- "scripts": {
20
- "build": "node ../../../../../../bin/build_package.js .",
21
- "watch": "node ../../../../../../bin/build_package.js . --watch",
22
- "test": "../../../../../../bin/test_package.sh .",
23
- "check": "biome check",
24
- "ci": "biome ci"
25
- },
26
19
  "symfony": {
27
20
  "controllers": {
28
21
  "map": {
@@ -50,7 +43,23 @@
50
43
  "devDependencies": {
51
44
  "@googlemaps/js-api-loader": "^1.16.6",
52
45
  "@hotwired/stimulus": "^3.0.0",
53
- "@symfony/ux-map": "2.27.0",
54
- "@types/google.maps": "^3.55.9"
46
+ "@testing-library/dom": "^10.4.0",
47
+ "@testing-library/jest-dom": "^6.6.3",
48
+ "@testing-library/user-event": "^14.6.1",
49
+ "@types/google.maps": "^3.55.9",
50
+ "@vitest/browser": "^3.2.4",
51
+ "jsdom": "^26.1.0",
52
+ "tslib": "^2.8.1",
53
+ "tsx": "^4.20.3",
54
+ "typescript": "^5.8.3",
55
+ "vitest": "^3.2.4",
56
+ "@symfony/ux-map": "2.28.1"
57
+ },
58
+ "scripts": {
59
+ "build": "tsx ../../../../../../bin/build_package.ts .",
60
+ "watch": "tsx ../../../../../../bin/build_package.ts . --watch",
61
+ "test": "../../../../../../bin/test_package.sh .",
62
+ "check": "biome check",
63
+ "ci": "biome ci"
55
64
  }
56
65
  }