You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
leaflet-components/src/components/leaflet-control-layers.ts

82 lines
2.7 KiB
TypeScript

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<string, Layer> = {};
const overlays: Record<string, Layer> = {};
const inactiveLayers: 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 active = child.hasAttribute('active');
(base ? baseLayers : overlays)[name] = layer;
if (!active) inactiveLayers.push(layer);
}
for (const layer of inactiveLayers) {
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,
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;
}
#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 active = el.hasAttribute('active');
if (base) this.#obj!.addBaseLayer(layer, name);
else this.#obj!.addOverlay(layer, name);
if (active) {
this.dispatchEvent(
new CustomEvent('leaflet-add-layer', { bubbles: true, detail: { layer } }),
);
}
};
}
customElements.define('leaflet-control-layers', LeafletControlLayers);