maplibre-gl 6.2.0 → 6.4.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.
- package/dist/maplibre-gl-dev.mjs +1108 -427
- package/dist/maplibre-gl-dev.mjs.map +1 -1
- package/dist/maplibre-gl-shared-dev.mjs +359 -291
- package/dist/maplibre-gl-shared-dev.mjs.map +1 -1
- package/dist/maplibre-gl-shared.mjs +2 -2
- package/dist/maplibre-gl-shared.mjs.map +1 -1
- package/dist/maplibre-gl-worker-dev.mjs +23 -49
- package/dist/maplibre-gl-worker-dev.mjs.map +1 -1
- package/dist/maplibre-gl-worker.mjs +2 -2
- package/dist/maplibre-gl-worker.mjs.map +1 -1
- package/dist/maplibre-gl.css +1 -1
- package/dist/maplibre-gl.d.ts +467 -151
- package/dist/maplibre-gl.mjs +49 -49
- package/dist/maplibre-gl.mjs.map +1 -1
- package/package.json +12 -22
- package/src/data/bucket/fill_extrusion_bucket.ts +1 -13
- package/src/data/bucket/round_polygon_corners.test.ts +84 -36
- package/src/data/bucket/round_polygon_corners.ts +90 -39
- package/src/data/extent_bounds.ts +28 -1
- package/src/data/feature_index.bench.ts +21 -0
- package/src/data/segment.test.ts +2 -2
- package/src/geo/edge_insets.test.ts +1 -1
- package/src/geo/lng_lat.test.ts +7 -7
- package/src/geo/lng_lat_bounds.test.ts +4 -4
- package/src/geo/mercator_coordinate.test.ts +2 -2
- package/src/geo/projection/camera_helper.ts +5 -0
- package/src/geo/projection/globe_transform.test.ts +154 -1
- package/src/geo/projection/globe_transform.ts +7 -3
- package/src/geo/projection/globe_utils.ts +189 -2
- package/src/geo/projection/mercator_camera_helper.ts +1 -1
- package/src/geo/projection/mercator_transform.ts +21 -5
- package/src/geo/projection/vertical_perspective_camera_helper.test.ts +24 -0
- package/src/geo/projection/vertical_perspective_camera_helper.ts +71 -41
- package/src/geo/projection/vertical_perspective_transform.ts +7 -1
- package/src/geo/transform_interface.ts +13 -1
- package/src/index.ts +7 -2
- package/src/render/image_atlas.test.ts +180 -0
- package/src/render/image_atlas.ts +52 -6
- package/src/render/image_manager.test.ts +111 -0
- package/src/render/image_manager.ts +143 -144
- package/src/render/painter.ts +6 -14
- package/src/render/pattern_atlas.test.ts +131 -0
- package/src/render/pattern_atlas.ts +144 -0
- package/src/render/update_pattern_positions_in_program.test.ts +1 -1
- package/src/shaders/glsl/_prelude.vertex.glsl +10 -11
- package/src/shaders/glsl/_prelude.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/circle.vertex.glsl +4 -4
- package/src/shaders/glsl/circle.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/color_relief.fragment.glsl +1 -2
- package/src/shaders/glsl/color_relief.fragment.glsl.g.ts +1 -1
- package/src/shaders/glsl/fill_extrusion.vertex.glsl +3 -3
- package/src/shaders/glsl/fill_extrusion.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/fill_extrusion_pattern.vertex.glsl +5 -5
- package/src/shaders/glsl/fill_extrusion_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/heatmap.vertex.glsl +4 -4
- package/src/shaders/glsl/heatmap.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/hillshade_prepare.fragment.glsl +12 -12
- package/src/shaders/glsl/hillshade_prepare.fragment.glsl.g.ts +1 -1
- package/src/shaders/glsl/line.vertex.glsl +7 -7
- package/src/shaders/glsl/line.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/line_gradient.vertex.glsl +6 -6
- package/src/shaders/glsl/line_gradient.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/line_gradient_sdf.vertex.glsl +7 -7
- package/src/shaders/glsl/line_gradient_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/line_pattern.vertex.glsl +7 -7
- package/src/shaders/glsl/line_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/line_sdf.vertex.glsl +7 -7
- package/src/shaders/glsl/line_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/raster.fragment.glsl +4 -4
- package/src/shaders/glsl/raster.fragment.glsl.g.ts +1 -1
- package/src/shaders/glsl/raster.vertex.glsl +11 -6
- package/src/shaders/glsl/raster.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/symbol_icon.vertex.glsl +5 -5
- package/src/shaders/glsl/symbol_icon.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/symbol_sdf.vertex.glsl +5 -5
- package/src/shaders/glsl/symbol_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/symbol_text_and_icon.vertex.glsl +6 -6
- package/src/shaders/glsl/symbol_text_and_icon.vertex.glsl.g.ts +1 -1
- package/src/source/canvas_source.test.ts +31 -0
- package/src/source/canvas_source.ts +2 -1
- package/src/source/geojson_worker_source.test.ts +88 -0
- package/src/source/geojson_worker_source.ts +22 -39
- package/src/source/image_source.test.ts +246 -38
- package/src/source/image_source.ts +132 -19
- package/src/source/raster_dem_tile_source.test.ts +37 -3
- package/src/source/raster_dem_tile_source.ts +1 -2
- package/src/source/raster_dem_tile_worker_source.test.ts +1 -1
- package/src/source/raster_tile_source.test.ts +5 -26
- package/src/source/raster_tile_source.ts +4 -3
- package/src/source/vector_tile_worker_source.test.ts +94 -2
- package/src/source/vector_tile_worker_source.ts +18 -27
- package/src/source/video_source.test.ts +12 -8
- package/src/source/worker_tile.bench.ts +10 -0
- package/src/source/worker_tile.ts +0 -3
- package/src/style/create_style_layer.bench.ts +15 -0
- package/src/style/properties.bench.ts +81 -0
- package/src/style/style.test.ts +75 -10
- package/src/style/style.ts +37 -64
- package/src/style/style_image.ts +67 -9
- package/src/style/style_layer.bench.ts +65 -0
- package/src/style/style_layer.test.ts +1 -1
- package/src/style/style_layer.ts +2 -2
- package/src/style/validate_style.bench.ts +11 -0
- package/src/style/validate_style.test.ts +2 -2
- package/src/symbol/anchor.test.ts +2 -2
- package/src/symbol/collision_index.bench.ts +116 -0
- package/src/symbol/cross_tile_symbol_index.bench.ts +49 -0
- package/src/symbol/cross_tile_symbol_index.test.ts +31 -0
- package/src/symbol/cross_tile_symbol_index.ts +67 -37
- package/src/symbol/shaping.test.ts +2 -1
- package/src/symbol/symbol_layout.bench.ts +30 -0
- package/src/tile/tile_id.test.ts +1 -1
- package/src/tile/tile_manager.test.ts +69 -1
- package/src/tile/tile_manager.ts +16 -11
- package/src/ui/control/fullscreen_control.test.ts +10 -10
- package/src/ui/control/geolocate_control.test.ts +3 -5
- package/src/ui/control/globe_control.test.ts +6 -6
- package/src/ui/events.ts +1 -1
- package/src/ui/handler/scroll_zoom.test.ts +50 -0
- package/src/ui/handler/two_fingers_touch.test.ts +17 -6
- package/src/ui/handler_inertia.test.ts +91 -0
- package/src/ui/handler_inertia.ts +65 -14
- package/src/ui/handler_manager.test.ts +243 -3
- package/src/ui/handler_manager.ts +79 -16
- package/src/ui/map.ts +17 -3
- package/src/ui/map_tests/map_cross_window.test.ts +2 -2
- package/src/ui/map_tests/map_events.test.ts +3 -3
- package/src/ui/map_tests/map_images.test.ts +55 -0
- package/src/ui/map_tests/map_style.test.ts +9 -8
- package/src/ui/map_tests/map_webgl.test.ts +30 -0
- package/src/ui/marker.test.ts +177 -42
- package/src/ui/marker.ts +120 -10
- package/src/ui/popup.test.ts +14 -14
- package/src/util/evented.test.ts +33 -28
- package/src/util/evented.ts +69 -43
- package/src/util/image_request.ts +31 -1
- package/src/util/test/null_gl.ts +10 -0
- package/src/util/test/util.ts +2 -1
- package/src/util/util.test.ts +1 -1
- package/src/util/web_worker_transfer.test.ts +5 -5
- package/src/webgl/context.ts +20 -0
- package/src/webgl/draw/draw_background.ts +1 -1
- package/src/webgl/draw/draw_raster.ts +11 -6
- package/src/webgl/program/pattern.ts +3 -3
- package/src/webgl/program/raster_program.ts +11 -0
- package/src/webgl/program.ts +31 -16
- package/src/webgl/texture.test.ts +16 -1
- package/src/webgl/texture.ts +3 -0
- package/src/webgl/vertex_buffer.test.ts +17 -2
- package/src/webgl/vertex_buffer.ts +24 -13
package/src/ui/marker.ts
CHANGED
|
@@ -18,6 +18,19 @@ import type {PointLike} from './camera.ts';
|
|
|
18
18
|
*/
|
|
19
19
|
export type Alignment = 'map' | 'viewport' | 'auto';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Screen-pixel deltas applied when a focused draggable marker is moved with the arrow keys.
|
|
23
|
+
*/
|
|
24
|
+
const ARROW_KEY_DELTAS: Partial<Record<KeyboardEvent['key'], [number, number]>> = {
|
|
25
|
+
ArrowLeft: [-1, 0],
|
|
26
|
+
ArrowRight: [1, 0],
|
|
27
|
+
ArrowUp: [0, -1],
|
|
28
|
+
ArrowDown: [0, 1]
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const KEYBOARD_DRAG_SMALL_STEP = 1;
|
|
32
|
+
const KEYBOARD_DRAG_LARGE_STEP = 10;
|
|
33
|
+
|
|
21
34
|
/**
|
|
22
35
|
* The {@link Marker} options object
|
|
23
36
|
*/
|
|
@@ -52,6 +65,10 @@ export type MarkerOptions = {
|
|
|
52
65
|
scale?: number;
|
|
53
66
|
/**
|
|
54
67
|
* A boolean indicating whether or not a marker is able to be dragged to a new position on the map.
|
|
68
|
+
* A draggable default marker also becomes keyboard focusable and, while focused, moves by
|
|
69
|
+
* 1 screen pixel per arrow-key press (10 with Shift), firing the same `dragstart`/`drag`/`dragend`
|
|
70
|
+
* events as pointer dragging. Markers with a custom `element` keep their focusability and
|
|
71
|
+
* keyboard behavior application-owned.
|
|
55
72
|
* @defaultValue false
|
|
56
73
|
*/
|
|
57
74
|
draggable?: boolean;
|
|
@@ -222,12 +239,13 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
222
239
|
_rotation: number;
|
|
223
240
|
_pitchAlignment: Alignment;
|
|
224
241
|
_rotationAlignment: Alignment;
|
|
225
|
-
_originalTabIndex: string; // original tabindex of _element
|
|
226
242
|
_opacity: string;
|
|
227
243
|
_opacityWhenCovered: string;
|
|
228
244
|
_opacityTimeout: ReturnType<typeof setTimeout>;
|
|
229
245
|
_subpixelPositioning: boolean;
|
|
230
246
|
_roleManaged: boolean;
|
|
247
|
+
_tabIndexManaged: boolean;
|
|
248
|
+
_keyboardDragActive: boolean;
|
|
231
249
|
|
|
232
250
|
/**
|
|
233
251
|
* @param options - the options
|
|
@@ -243,6 +261,8 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
243
261
|
this._subpixelPositioning = options?.subpixelPositioning || false;
|
|
244
262
|
this._isDragging = false;
|
|
245
263
|
this._roleManaged = false;
|
|
264
|
+
this._tabIndexManaged = false;
|
|
265
|
+
this._keyboardDragActive = false;
|
|
246
266
|
this._state = 'inactive';
|
|
247
267
|
this._rotation = options?.rotation || 0;
|
|
248
268
|
this._rotationAlignment = options?.rotationAlignment || 'auto';
|
|
@@ -447,6 +467,12 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
447
467
|
delete this._map;
|
|
448
468
|
}
|
|
449
469
|
this._element.removeEventListener('click', this._onClick);
|
|
470
|
+
this._element.removeEventListener('keydown', this._onKeyDown);
|
|
471
|
+
this._element.removeEventListener('keyup', this._onKeyUp);
|
|
472
|
+
this._element.removeEventListener('blur', this._onBlur);
|
|
473
|
+
this._element.removeEventListener('keypress', this._onKeyPress);
|
|
474
|
+
// Drop any in-flight keyboard drag silently, like a pointer drag interrupted by remove().
|
|
475
|
+
this._keyboardDragActive = false;
|
|
450
476
|
this._element.remove();
|
|
451
477
|
if (this._popup) this._popup.remove();
|
|
452
478
|
return this;
|
|
@@ -520,10 +546,6 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
520
546
|
this._popup.remove();
|
|
521
547
|
this._popup = null;
|
|
522
548
|
this._element.removeEventListener('keypress', this._onKeyPress);
|
|
523
|
-
|
|
524
|
-
if (!this._originalTabIndex) {
|
|
525
|
-
this._element.removeAttribute('tabindex');
|
|
526
|
-
}
|
|
527
549
|
}
|
|
528
550
|
|
|
529
551
|
if (popup) {
|
|
@@ -544,13 +566,10 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
544
566
|
}
|
|
545
567
|
this._popup = popup;
|
|
546
568
|
|
|
547
|
-
this._originalTabIndex = this._element.getAttribute('tabindex');
|
|
548
|
-
if (!this._originalTabIndex) {
|
|
549
|
-
this._element.setAttribute('tabindex', '0');
|
|
550
|
-
}
|
|
551
569
|
this._element.addEventListener('keypress', this._onKeyPress);
|
|
552
570
|
}
|
|
553
571
|
|
|
572
|
+
this._updateTabIndex();
|
|
554
573
|
this._updateAccessibilityRole();
|
|
555
574
|
return this;
|
|
556
575
|
}
|
|
@@ -581,6 +600,57 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
581
600
|
}
|
|
582
601
|
};
|
|
583
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Move a focused draggable default marker with the arrow keys
|
|
605
|
+
* (1 screen pixel per keydown; 10 with Shift).
|
|
606
|
+
* Mirrors the pointer drag gesture: the position updates before `dragstart`
|
|
607
|
+
* fires on the first movement, every movement fires `drag`, and releasing
|
|
608
|
+
* the arrow key (or losing focus) fires `dragend`. Holding a key down
|
|
609
|
+
* produces repeated `drag` events within a single gesture.
|
|
610
|
+
*/
|
|
611
|
+
_onKeyDown = (e: KeyboardEvent): void => {
|
|
612
|
+
// Custom marker elements own their keyboard behavior (#7790).
|
|
613
|
+
if (!this._defaultMarker || !this._draggable || !this._map || !this._lngLat) return;
|
|
614
|
+
// Leave keys originating from elements nested inside the marker to the application.
|
|
615
|
+
if (e.composedPath()[0] !== this._element) return;
|
|
616
|
+
// Leave Alt/Ctrl/Meta shortcuts to the browser and the application.
|
|
617
|
+
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
618
|
+
|
|
619
|
+
const delta = ARROW_KEY_DELTAS[e.key];
|
|
620
|
+
if (!delta) return;
|
|
621
|
+
|
|
622
|
+
e.preventDefault();
|
|
623
|
+
// The marker element lives in the canvas container, so without this the
|
|
624
|
+
// map's KeyboardHandler would also pan (or rotate/pitch with Shift) the camera.
|
|
625
|
+
e.stopPropagation();
|
|
626
|
+
|
|
627
|
+
const step = e.shiftKey ? KEYBOARD_DRAG_LARGE_STEP : KEYBOARD_DRAG_SMALL_STEP;
|
|
628
|
+
const pos = this._map.project(this._lngLat);
|
|
629
|
+
this.setLngLat(this._map.unproject(new Point(pos.x + delta[0] * step, pos.y + delta[1] * step)));
|
|
630
|
+
|
|
631
|
+
if (!this._keyboardDragActive) {
|
|
632
|
+
this._keyboardDragActive = true;
|
|
633
|
+
this.fire(new MarkerDragEvent('dragstart'));
|
|
634
|
+
}
|
|
635
|
+
this.fire(new MarkerDragEvent('drag'));
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
_onKeyUp = (e: KeyboardEvent): void => {
|
|
639
|
+
if (!ARROW_KEY_DELTAS[e.key]) return;
|
|
640
|
+
this._endKeyboardDrag();
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
_onBlur = (): void => {
|
|
644
|
+
this._endKeyboardDrag();
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
_endKeyboardDrag(): void {
|
|
648
|
+
if (this._keyboardDragActive) {
|
|
649
|
+
this._keyboardDragActive = false;
|
|
650
|
+
this.fire(new MarkerDragEvent('dragend'));
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
584
654
|
_onMapClick = (e: MapMouseEvent): void => {
|
|
585
655
|
const targetElement = e.originalEvent.target;
|
|
586
656
|
const element = this._element;
|
|
@@ -851,7 +921,10 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
851
921
|
};
|
|
852
922
|
|
|
853
923
|
/**
|
|
854
|
-
* Sets the `draggable` property and functionality of the marker
|
|
924
|
+
* Sets the `draggable` property and functionality of the marker.
|
|
925
|
+
* A draggable default marker is also keyboard focusable and movable with the
|
|
926
|
+
* arrow keys (see {@link MarkerOptions.draggable}); custom marker elements keep
|
|
927
|
+
* their focusability and keyboard behavior application-owned.
|
|
855
928
|
* @param shouldBeDraggable - Turns drag functionality on/off
|
|
856
929
|
*/
|
|
857
930
|
setDraggable(shouldBeDraggable?: boolean): this {
|
|
@@ -870,6 +943,20 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
870
943
|
}
|
|
871
944
|
}
|
|
872
945
|
|
|
946
|
+
if (this._defaultMarker) {
|
|
947
|
+
if (this._draggable) {
|
|
948
|
+
this._element.addEventListener('keydown', this._onKeyDown);
|
|
949
|
+
this._element.addEventListener('keyup', this._onKeyUp);
|
|
950
|
+
this._element.addEventListener('blur', this._onBlur);
|
|
951
|
+
} else {
|
|
952
|
+
this._element.removeEventListener('keydown', this._onKeyDown);
|
|
953
|
+
this._element.removeEventListener('keyup', this._onKeyUp);
|
|
954
|
+
this._element.removeEventListener('blur', this._onBlur);
|
|
955
|
+
this._endKeyboardDrag();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
this._updateTabIndex();
|
|
873
960
|
this._updateAccessibilityRole();
|
|
874
961
|
return this;
|
|
875
962
|
}
|
|
@@ -882,6 +969,29 @@ export class Marker extends Evented<MarkerEventType> {
|
|
|
882
969
|
return this._draggable;
|
|
883
970
|
}
|
|
884
971
|
|
|
972
|
+
/**
|
|
973
|
+
* Keep the marker element focusable while it has built-in keyboard behavior.
|
|
974
|
+
* A popup makes any marker element interactive; dragging only manages
|
|
975
|
+
* focusability for the default marker so custom elements stay
|
|
976
|
+
* application-owned (#7790). A tabindex supplied by the application is
|
|
977
|
+
* never added, changed, or removed here.
|
|
978
|
+
*/
|
|
979
|
+
_updateTabIndex(): void {
|
|
980
|
+
const needsTabIndex = !!this._popup || (this._defaultMarker && this._draggable);
|
|
981
|
+
if (needsTabIndex) {
|
|
982
|
+
if (!this._element.hasAttribute('tabindex')) {
|
|
983
|
+
this._element.setAttribute('tabindex', '0');
|
|
984
|
+
this._tabIndexManaged = true;
|
|
985
|
+
}
|
|
986
|
+
} else if (this._tabIndexManaged) {
|
|
987
|
+
// Only remove the value we set; the application may have overridden it since.
|
|
988
|
+
if (this._element.getAttribute('tabindex') === '0') {
|
|
989
|
+
this._element.removeAttribute('tabindex');
|
|
990
|
+
}
|
|
991
|
+
this._tabIndexManaged = false;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
885
995
|
/**
|
|
886
996
|
* Keep the default marker role aligned with interactivity.
|
|
887
997
|
* Default markers need a role because `aria-label` is set in {@link Marker.addTo}.
|
package/src/ui/popup.test.ts
CHANGED
|
@@ -32,7 +32,7 @@ describe('popup', () => {
|
|
|
32
32
|
.addTo(map);
|
|
33
33
|
|
|
34
34
|
expect(popup.isOpen()).toBeTruthy();
|
|
35
|
-
expect(popup.getElement().classList.
|
|
35
|
+
expect(popup.getElement().classList).toContain('maplibregl-popup');
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test('Popup.addTo adds a .maplibregl-popup element', () => {
|
|
@@ -258,10 +258,10 @@ describe('popup', () => {
|
|
|
258
258
|
test('Popup provides LngLat accessors', () => {
|
|
259
259
|
expect(new Popup().getLngLat()).toBeUndefined();
|
|
260
260
|
|
|
261
|
-
expect(new Popup().setLngLat([1, 2]).getLngLat()
|
|
261
|
+
expect(new Popup().setLngLat([1, 2]).getLngLat()).toBeInstanceOf(LngLat);
|
|
262
262
|
expect(new Popup().setLngLat([1, 2]).getLngLat()).toEqual(new LngLat(1, 2));
|
|
263
263
|
|
|
264
|
-
expect(new Popup().setLngLat(new LngLat(1, 2)).getLngLat()
|
|
264
|
+
expect(new Popup().setLngLat(new LngLat(1, 2)).getLngLat()).toBeInstanceOf(LngLat);
|
|
265
265
|
expect(new Popup().setLngLat(new LngLat(1, 2)).getLngLat()).toEqual(new LngLat(1, 2));
|
|
266
266
|
|
|
267
267
|
});
|
|
@@ -382,7 +382,7 @@ describe('popup', () => {
|
|
|
382
382
|
.setText('Test')
|
|
383
383
|
.addTo(map);
|
|
384
384
|
|
|
385
|
-
expect(popup.getElement().classList.
|
|
385
|
+
expect(popup.getElement().classList).toContain('maplibregl-popup-anchor-top-left');
|
|
386
386
|
});
|
|
387
387
|
|
|
388
388
|
const cases = [
|
|
@@ -413,7 +413,7 @@ describe('popup', () => {
|
|
|
413
413
|
vi.spyOn(map, 'project').mockReturnValue(point);
|
|
414
414
|
popup.setLngLat([0, 0]);
|
|
415
415
|
|
|
416
|
-
expect(popup.getElement().classList.
|
|
416
|
+
expect(popup.getElement().classList).toContain(`maplibregl-popup-anchor-${anchor}`);
|
|
417
417
|
});
|
|
418
418
|
|
|
419
419
|
const transformCases = cases.map(([anchor, _point, transform]) => [anchor, transform] as const);
|
|
@@ -449,7 +449,7 @@ describe('popup', () => {
|
|
|
449
449
|
vi.spyOn(map, 'project').mockReturnValue(point);
|
|
450
450
|
popup.setLngLat([0, 0]);
|
|
451
451
|
|
|
452
|
-
expect(popup.getElement().classList.
|
|
452
|
+
expect(popup.getElement().classList).toContain('maplibregl-popup-anchor-top');
|
|
453
453
|
});
|
|
454
454
|
|
|
455
455
|
test('Popup is offset via a PointLike offset option', () => {
|
|
@@ -563,22 +563,22 @@ describe('popup', () => {
|
|
|
563
563
|
.addTo(map);
|
|
564
564
|
|
|
565
565
|
const popupContainer = popup.getElement();
|
|
566
|
-
expect(popupContainer.classList.
|
|
567
|
-
expect(popupContainer.classList.
|
|
566
|
+
expect(popupContainer.classList).toContain('some');
|
|
567
|
+
expect(popupContainer.classList).toContain('classes');
|
|
568
568
|
|
|
569
569
|
const addClassNameMethodPopupInstance = popup.addClassName('addedClass');
|
|
570
|
-
expect(popupContainer.classList.
|
|
570
|
+
expect(popupContainer.classList).toContain('addedClass');
|
|
571
571
|
expect(addClassNameMethodPopupInstance).toBeInstanceOf(Popup);
|
|
572
572
|
|
|
573
573
|
const removeClassNameMethodPopupInstance = popup.removeClassName('addedClass');
|
|
574
|
-
expect(
|
|
574
|
+
expect(popupContainer.classList).not.toContain('addedClass');
|
|
575
575
|
expect(removeClassNameMethodPopupInstance).toBeInstanceOf(Popup);
|
|
576
576
|
|
|
577
577
|
popup.toggleClassName('toggle');
|
|
578
|
-
expect(popupContainer.classList.
|
|
578
|
+
expect(popupContainer.classList).toContain('toggle');
|
|
579
579
|
|
|
580
580
|
popup.toggleClassName('toggle');
|
|
581
|
-
expect(
|
|
581
|
+
expect(popupContainer.classList).not.toContain('toggle');
|
|
582
582
|
|
|
583
583
|
expect(() => popup.addClassName('should throw exception')).toThrow(window.DOMException);
|
|
584
584
|
expect(() => popup.removeClassName('should throw exception')).toThrow(window.DOMException);
|
|
@@ -1063,8 +1063,8 @@ describe('popup', () => {
|
|
|
1063
1063
|
.trackPointer()
|
|
1064
1064
|
.addTo(map);
|
|
1065
1065
|
|
|
1066
|
-
expect(popup.getElement().classList.
|
|
1067
|
-
expect(map._canvasContainer.classList.
|
|
1066
|
+
expect(popup.getElement().classList).toContain('maplibregl-popup-track-pointer');
|
|
1067
|
+
expect(map._canvasContainer.classList).toContain('maplibregl-track-pointer');
|
|
1068
1068
|
|
|
1069
1069
|
popup.remove();
|
|
1070
1070
|
});
|
package/src/util/evented.test.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import {describe, test, expect, vi} from 'vitest';
|
|
2
2
|
import {Event, Evented} from './evented.ts';
|
|
3
3
|
|
|
4
|
+
class StubbedEvent extends Event<'a' | 'b'> {
|
|
5
|
+
foo?: string;
|
|
6
|
+
foz?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
// `Evented` is abstract, so use a minimal concrete subclass to exercise its behavior.
|
|
5
|
-
class StubbedEvented extends Evented {}
|
|
10
|
+
class StubbedEvented extends Evented<Record<StubbedEvent['type'], StubbedEvent>> {}
|
|
6
11
|
|
|
7
12
|
describe('Evented', () => {
|
|
8
13
|
|
|
@@ -10,8 +15,8 @@ describe('Evented', () => {
|
|
|
10
15
|
const evented = new StubbedEvented();
|
|
11
16
|
const listener = vi.fn();
|
|
12
17
|
evented.on('a', listener);
|
|
13
|
-
evented.fire(new
|
|
14
|
-
evented.fire(new
|
|
18
|
+
evented.fire(new StubbedEvent('a'));
|
|
19
|
+
evented.fire(new StubbedEvent('a'));
|
|
15
20
|
expect(listener).toHaveBeenCalledTimes(2);
|
|
16
21
|
});
|
|
17
22
|
|
|
@@ -19,8 +24,8 @@ describe('Evented', () => {
|
|
|
19
24
|
const evented = new StubbedEvented();
|
|
20
25
|
const listener = vi.fn();
|
|
21
26
|
evented.once('a', listener);
|
|
22
|
-
evented.fire(new
|
|
23
|
-
evented.fire(new
|
|
27
|
+
evented.fire(new StubbedEvent('a'));
|
|
28
|
+
evented.fire(new StubbedEvent('a'));
|
|
24
29
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
25
30
|
expect(evented.listens('a')).toBeFalsy();
|
|
26
31
|
});
|
|
@@ -29,17 +34,17 @@ describe('Evented', () => {
|
|
|
29
34
|
const evented = new StubbedEvented();
|
|
30
35
|
const listener = vi.fn();
|
|
31
36
|
const subscription = evented.on('a', listener);
|
|
32
|
-
evented.fire(new
|
|
37
|
+
evented.fire(new StubbedEvent('a'));
|
|
33
38
|
subscription.unsubscribe();
|
|
34
|
-
evented.fire(new
|
|
39
|
+
evented.fire(new StubbedEvent('a'));
|
|
35
40
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
36
41
|
});
|
|
37
42
|
|
|
38
43
|
test('returns a promise when no listener is provided to "once" method', async () => {
|
|
39
44
|
const evented = new StubbedEvented();
|
|
40
45
|
const promise = evented.once('a');
|
|
41
|
-
evented.fire(new
|
|
42
|
-
evented.fire(new
|
|
46
|
+
evented.fire(new StubbedEvent('a'));
|
|
47
|
+
evented.fire(new StubbedEvent('a'));
|
|
43
48
|
await promise;
|
|
44
49
|
expect(evented.listens('a')).toBeFalsy();
|
|
45
50
|
|
|
@@ -50,7 +55,7 @@ describe('Evented', () => {
|
|
|
50
55
|
evented.on('a', (data) => {
|
|
51
56
|
expect(data.foo).toBe('bar');
|
|
52
57
|
});
|
|
53
|
-
evented.fire(new
|
|
58
|
+
evented.fire(new StubbedEvent('a', {foo: 'bar'}));
|
|
54
59
|
|
|
55
60
|
});
|
|
56
61
|
|
|
@@ -59,7 +64,7 @@ describe('Evented', () => {
|
|
|
59
64
|
evented.on('a', (data) => {
|
|
60
65
|
expect(data.target).toBe(evented);
|
|
61
66
|
});
|
|
62
|
-
evented.fire(new
|
|
67
|
+
evented.fire(new StubbedEvent('a'));
|
|
63
68
|
|
|
64
69
|
});
|
|
65
70
|
|
|
@@ -68,7 +73,7 @@ describe('Evented', () => {
|
|
|
68
73
|
evented.on('a', (data) => {
|
|
69
74
|
expect(data.type).toBe('a');
|
|
70
75
|
});
|
|
71
|
-
evented.fire(new
|
|
76
|
+
evented.fire(new StubbedEvent('a'));
|
|
72
77
|
|
|
73
78
|
});
|
|
74
79
|
|
|
@@ -77,7 +82,7 @@ describe('Evented', () => {
|
|
|
77
82
|
const listener = vi.fn();
|
|
78
83
|
evented.on('a', listener);
|
|
79
84
|
evented.off('a', listener);
|
|
80
|
-
evented.fire(new
|
|
85
|
+
evented.fire(new StubbedEvent('a'));
|
|
81
86
|
expect(listener).not.toHaveBeenCalled();
|
|
82
87
|
});
|
|
83
88
|
|
|
@@ -86,7 +91,7 @@ describe('Evented', () => {
|
|
|
86
91
|
const listener = vi.fn();
|
|
87
92
|
evented.once('a', listener);
|
|
88
93
|
evented.off('a', listener);
|
|
89
|
-
evented.fire(new
|
|
94
|
+
evented.fire(new StubbedEvent('a'));
|
|
90
95
|
expect(listener).not.toHaveBeenCalled();
|
|
91
96
|
});
|
|
92
97
|
|
|
@@ -95,9 +100,9 @@ describe('Evented', () => {
|
|
|
95
100
|
const listener = vi.fn();
|
|
96
101
|
evented.once('a', () => {
|
|
97
102
|
listener();
|
|
98
|
-
evented.fire(new
|
|
103
|
+
evented.fire(new StubbedEvent('a'));
|
|
99
104
|
});
|
|
100
|
-
evented.fire(new
|
|
105
|
+
evented.fire(new StubbedEvent('a'));
|
|
101
106
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
102
107
|
});
|
|
103
108
|
|
|
@@ -124,7 +129,7 @@ describe('Evented', () => {
|
|
|
124
129
|
evented.on('a', () => {
|
|
125
130
|
evented.on('a', nestedListener);
|
|
126
131
|
});
|
|
127
|
-
evented.fire(new
|
|
132
|
+
evented.fire(new StubbedEvent('a'));
|
|
128
133
|
|
|
129
134
|
expect(nestedListener).not.toHaveBeenCalled();
|
|
130
135
|
});
|
|
@@ -147,7 +152,7 @@ describe('Evented', () => {
|
|
|
147
152
|
evented.on('a', listenerA);
|
|
148
153
|
evented.on('a', listenerB);
|
|
149
154
|
evented.on('a', listenerA);
|
|
150
|
-
evented.fire(new
|
|
155
|
+
evented.fire(new StubbedEvent('a'));
|
|
151
156
|
expect(listenerA).toHaveBeenCalledTimes(1);
|
|
152
157
|
expect(order).toEqual(['A', 'B']);
|
|
153
158
|
|
|
@@ -162,8 +167,8 @@ describe('evented parents', () => {
|
|
|
162
167
|
const eventedSink = new StubbedEvented();
|
|
163
168
|
eventedSource.setEventedParent(eventedSink);
|
|
164
169
|
eventedSink.on('a', listener);
|
|
165
|
-
eventedSource.fire(new
|
|
166
|
-
eventedSource.fire(new
|
|
170
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
171
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
167
172
|
expect(listener).toHaveBeenCalledTimes(2);
|
|
168
173
|
});
|
|
169
174
|
|
|
@@ -174,7 +179,7 @@ describe('evented parents', () => {
|
|
|
174
179
|
eventedSink.on('a', (data) => {
|
|
175
180
|
expect(data.foo).toBe('bar');
|
|
176
181
|
});
|
|
177
|
-
eventedSource.fire(new
|
|
182
|
+
eventedSource.fire(new StubbedEvent('a', {foo: 'bar'}));
|
|
178
183
|
|
|
179
184
|
});
|
|
180
185
|
|
|
@@ -185,7 +190,7 @@ describe('evented parents', () => {
|
|
|
185
190
|
eventedSink.on('a', (data) => {
|
|
186
191
|
expect(data.foz).toBe('baz');
|
|
187
192
|
});
|
|
188
|
-
eventedSource.fire(new
|
|
193
|
+
eventedSource.fire(new StubbedEvent('a', {foo: 'bar'}));
|
|
189
194
|
|
|
190
195
|
});
|
|
191
196
|
|
|
@@ -196,7 +201,7 @@ describe('evented parents', () => {
|
|
|
196
201
|
eventedSink.on('a', (data) => {
|
|
197
202
|
expect(data.foz).toBe('baz');
|
|
198
203
|
});
|
|
199
|
-
eventedSource.fire(new
|
|
204
|
+
eventedSource.fire(new StubbedEvent('a', {foo: 'bar'}));
|
|
200
205
|
|
|
201
206
|
});
|
|
202
207
|
|
|
@@ -208,7 +213,7 @@ describe('evented parents', () => {
|
|
|
208
213
|
eventedSink.on('a', (data) => {
|
|
209
214
|
expect(data.target).toBe(eventedSource);
|
|
210
215
|
});
|
|
211
|
-
eventedSource.fire(new
|
|
216
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
212
217
|
|
|
213
218
|
});
|
|
214
219
|
|
|
@@ -219,7 +224,7 @@ describe('evented parents', () => {
|
|
|
219
224
|
eventedSink.on('a', listener);
|
|
220
225
|
eventedSource.setEventedParent(eventedSink);
|
|
221
226
|
eventedSource.setEventedParent(null);
|
|
222
|
-
eventedSource.fire(new
|
|
227
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
223
228
|
expect(listener).not.toHaveBeenCalled();
|
|
224
229
|
});
|
|
225
230
|
|
|
@@ -236,11 +241,11 @@ describe('evented parents', () => {
|
|
|
236
241
|
const eventedSource = new StubbedEvented();
|
|
237
242
|
const eventedParent = new StubbedEvented();
|
|
238
243
|
let i = 0;
|
|
239
|
-
eventedSource.setEventedParent(eventedParent, () => i++);
|
|
244
|
+
eventedSource.setEventedParent(eventedParent, () => ({counter: i++}));
|
|
240
245
|
eventedSource.on('a', () => {});
|
|
241
|
-
eventedSource.fire(new
|
|
246
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
242
247
|
expect(i).toBe(1);
|
|
243
|
-
eventedSource.fire(new
|
|
248
|
+
eventedSource.fire(new StubbedEvent('a'));
|
|
244
249
|
expect(i).toBe(2);
|
|
245
250
|
|
|
246
251
|
});
|