import { DivIcon, type DivIconOptions, type PointExpression } from 'leaflet'; import { json, str, type PropDef } from '../core/props.ts'; import { emitIconChanged } from '../core/register.ts'; import { WithProps, type LeafletElementConstructor } from '../core/with-props.ts'; // Like leaflet-icon, rebuilt on every change -- including changes to the // markup, which is what the icon renders when `html` isn't set. const PROPS: { iconSize: PropDef; iconAnchor: PropDef; popupAnchor: PropDef; tooltipAnchor: PropDef; className: PropDef; html: PropDef; bgPos: PropDef; } = { iconSize: json([0, 0]), iconAnchor: json([0, 0]), popupAnchor: json([0, 0]), tooltipAnchor: json([0, 0]), className: str('leaflet-div-icon'), html: str(), bgPos: json([0, 0]), }; const Base: LeafletElementConstructor = WithProps(PROPS, { attach: 'none', recreate: true, }); /** * `` — a Leaflet `DivIcon` (a CSS-styled marker icon). Child * of ``; renders its own markup when `html` isn't set, and is * rebuilt on every change. */ export default class LeafletDivIconElement extends Base { declare readonly leafletObject?: DivIcon; #observer?: MutationObserver; createLeafletObject(options: DivIconOptions): DivIcon { return new DivIcon(this.innerHTML ? { ...options, html: this.innerHTML } : options); } connectedCallback(): void { super.connectedCallback(); this.#observer = new MutationObserver(() => { this.recreateLeafletObject(); }); this.#observer.observe(this, { childList: true, characterData: true, subtree: true }); } disconnectedCallback(): void { this.#observer?.disconnect(); this.#observer = undefined; super.disconnectedCallback(); emitIconChanged(this, null); } leafletObjectCreated(): void { emitIconChanged(this, this.leafletObject); } }