import { Control, ControlPosition, Layer } from 'leaflet'; import { defineProps, str } from '../core/props.ts'; import { WithProps, registerWithParent } from '../core/utils.ts'; import { LeafletRegisterEvent } from '../core/register.ts'; const PROPS = defineProps({ position: str('topright'), }); export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) { #obj?: Control.Layers; connectedCallback() { const baseLayers: Record = {}; const overlays: Record = {}; const uncheckedLayers: Layer[] = []; for (const child of this.querySelectorAll(':scope > *')) { const layer = (child as unknown as { leafletObject?: Layer }).leafletObject; const name = child.getAttribute('name'); if (!name || !layer) continue; const base = child.getAttribute('type') === 'base'; const checked = child.hasAttribute('checked'); (base ? baseLayers : overlays)[name] = layer; if (!checked) uncheckedLayers.push(layer); } const map = this.#map; for (const layer of uncheckedLayers) map?.removeLayer(layer); this.#obj = new Control.Layers(baseLayers, overlays, { position: this.getAttribute('position') as ControlPosition | undefined, collapsed: !this.hasAttribute('collapsed') || this.getAttribute('collapsed') !== 'false', autoZIndex: !this.hasAttribute('auto-z-index') || this.getAttribute('auto-z-index') !== 'false', hideSingleBase: this.hasAttribute('hide-single-base'), sortLayers: this.hasAttribute('sort-layers'), }); registerWithParent(this, this.#obj); this.addEventListener('leaflet-register', this.#onChildRegister); } disconnectedCallback() { this.removeEventListener('leaflet-register', this.#onChildRegister); this.#obj?.remove(); this.#obj = undefined; } attributeChangedCallback(name: string) { if (name === 'position' && this.#obj) { this.#obj.setPosition(this.getAttribute('position') as ControlPosition); } } get leafletObject() { 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; const layer = e.detail.leafletObject; const name = el.getAttribute('name'); if (!name || !layer) return; const base = el.getAttribute('type') === 'base'; const checked = el.hasAttribute('checked'); if (base) this.#obj!.addBaseLayer(layer, name); else this.#obj!.addOverlay(layer, name); if (checked) this.#map?.addLayer(layer); }; } customElements.define('leaflet-control-layers', LeafletControlLayers);