import { Icon, Marker, type MarkerOptions } from 'leaflet'; import { bool, num, str, type PropDef } from '../core/props.ts'; import { latLngProps } from '../core/shared-props.ts'; import { WithProps, type LeafletAddEventListener, type LeafletElementConstructor, type LeafletRemoveEventListener, } from '../core/with-props.ts'; import type { LeafletIconChangedEvent } from '../core/register.ts'; import type { MarkerEvents } from '../core/event-types.ts'; const PROPS: typeof latLngProps & { title: PropDef; alt: PropDef; draggable: PropDef; opacity: PropDef; zIndexOffset: PropDef; } = { ...latLngProps, // title and alt end up on the Leaflet renders, so live updates go there. title: str('', { set: (obj: Marker, value) => { const el = obj.getElement(); if (el) el.title = value; }, }), alt: str('', { set: (obj: Marker, value) => { const el = obj.getElement() as HTMLImageElement | undefined; if (el) el.alt = value; }, }), draggable: bool(false, { set(obj: Marker, value) { if (value) obj.dragging?.enable(); else obj.dragging?.disable(); }, }), opacity: num(1.0), zIndexOffset: num(), }; const Base: LeafletElementConstructor = WithProps(PROPS); /** `` — a Leaflet `Marker`. Accepts ``, ``, and `` / `` children. */ export default class LeafletMarkerElement extends Base { declare readonly leafletObject?: Marker; declare addEventListener: LeafletAddEventListener; declare removeEventListener: LeafletRemoveEventListener; createLeafletObject(options: MarkerOptions): Marker { return new Marker([this.lat, this.lng], options); } connectedCallback(): void { super.connectedCallback(); this.addEventListener('icon-changed', this.#onIconChanged); } disconnectedCallback(): void { this.removeEventListener('icon-changed', this.#onIconChanged); super.disconnectedCallback(); } // A or child announces itself this way. #onIconChanged = (e: LeafletIconChangedEvent) => { this.leafletObject?.setIcon(e.detail.icon ?? new Icon.Default()); }; }