From f85e67547dd90a6ff78766cec906dbaa901f01ba Mon Sep 17 00:00:00 2001 From: Buddy Date: Wed, 10 Jun 2026 07:22:02 -0700 Subject: [PATCH] refactor: use events for control-layers layer add/remove instead of DOM traversal Replace the #map getter (which used closest("leaflet-map") + leafletObject) with two new custom events: leaflet-add-layer and leaflet-remove-layer. The map listens for them and delegates to map.addLayer/removeLayer. This removes the coupling between leaflet-control-layers and the map element, aligning with the existing leaflet-register event protocol. --- src/components/leaflet-control-layers.ts | 31 ++++++++---------------- src/components/leaflet-map.ts | 14 ++++++++++- src/core/register.ts | 4 +++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/components/leaflet-control-layers.ts b/src/components/leaflet-control-layers.ts index ffaa4c1..4b774cf 100644 --- a/src/components/leaflet-control-layers.ts +++ b/src/components/leaflet-control-layers.ts @@ -25,8 +25,11 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) { if (!checked) uncheckedLayers.push(layer); } - const map = this.#map; - for (const layer of uncheckedLayers) map?.removeLayer(layer); + for (const layer of uncheckedLayers) { + this.dispatchEvent( + new CustomEvent('leaflet-remove-layer', { bubbles: true, detail: { layer } }), + ); + } this.#obj = new Control.Layers(baseLayers, overlays, { position: this.getAttribute('position') as ControlPosition | undefined, @@ -57,24 +60,6 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) { return this.#obj; } - get #map(): - | { - removeLayer(l: Layer): unknown; - addLayer(l: Layer): unknown; - } - | undefined { - const mapEl = this.closest('leaflet-map'); - if (!mapEl) return undefined; - return ( - mapEl as unknown as { - leafletObject?: { - removeLayer(l: Layer): unknown; - addLayer(l: Layer): unknown; - }; - } - ).leafletObject; - } - #onChildRegister = (e: LeafletRegisterEvent) => { e.stopPropagation(); const el = e.detail.element; @@ -85,7 +70,11 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) { const checked = el.hasAttribute('checked'); if (base) this.#obj!.addBaseLayer(layer, name); else this.#obj!.addOverlay(layer, name); - if (checked) this.#map?.addLayer(layer); + if (checked) { + this.dispatchEvent( + new CustomEvent('leaflet-add-layer', { bubbles: true, detail: { layer } }), + ); + } }; } diff --git a/src/components/leaflet-map.ts b/src/components/leaflet-map.ts index 85d957f..cc4457c 100644 --- a/src/components/leaflet-map.ts +++ b/src/components/leaflet-map.ts @@ -1,4 +1,4 @@ -import { Icon, Map as LMap, MapOptions } from 'leaflet'; +import { Icon, Layer, Map as LMap, MapOptions } from 'leaflet'; import { defineProps, num, off, on, type NumProp, type PropDef } from '../core/props.ts'; import { LeafletRegisterEvent } from '../core/register.ts'; @@ -205,6 +205,8 @@ export class LeafletMap extends TypedBase { 'leaflet-register', this.#handleLeafletRegister as EventListenerOrEventListenerObject, ); + this.addEventListener('leaflet-add-layer', this.#onAddLayer); + this.addEventListener('leaflet-remove-layer', this.#onRemoveLayer); } disconnectedCallback() { @@ -214,6 +216,8 @@ export class LeafletMap extends TypedBase { 'leaflet-register', this.#handleLeafletRegister as EventListenerOrEventListenerObject, ); + this.removeEventListener('leaflet-add-layer', this.#onAddLayer); + this.removeEventListener('leaflet-remove-layer', this.#onRemoveLayer); if (!this.#map) return; for (const [event, handler] of this.#mapEventHandlers) { this.#map.off(event, handler); @@ -309,6 +313,14 @@ export class LeafletMap extends TypedBase { } }; + #onAddLayer = (e: Event) => { + this.#map?.addLayer((e as CustomEvent<{ layer: Layer }>).detail.layer); + }; + + #onRemoveLayer = (e: Event) => { + this.#map?.removeLayer((e as CustomEvent<{ layer: Layer }>).detail.layer); + }; + get leafletObject() { return this.#map; } diff --git a/src/core/register.ts b/src/core/register.ts index 39989ed..4f3e340 100644 --- a/src/core/register.ts +++ b/src/core/register.ts @@ -9,9 +9,13 @@ export type LeafletRegisterEvent = CustomEvent<{ element: HTMLElement; }>; +export type LeafletLayerEvent = CustomEvent<{ layer: Layer }>; + declare global { interface HTMLElementEventMap { 'leaflet-register': LeafletRegisterEvent; + 'leaflet-add-layer': LeafletLayerEvent; + 'leaflet-remove-layer': LeafletLayerEvent; } }