import { Polyline, type PolylineOptions } from 'leaflet'; import { bool, num, type PropDef } from '../core/props.ts'; import { pathProps, style, type Styleable } from '../core/shared-props.ts'; import { WithProps, type LeafletAddEventListener, type LeafletElementConstructor, type LeafletRemoveEventListener, } from '../core/with-props.ts'; import type { PathEvents } from '../core/event-types.ts'; import type { LeafletLineRemoveEvent, LeafletLineSyncEvent } from '../core/register.ts'; import { VertexTracker } from '../core/vertex-tracker.ts'; const PROPS: typeof pathProps & { fill: PropDef; smoothFactor: PropDef; noClip: PropDef; } = { ...pathProps, // Unlike closed shapes, a polyline is unfilled by default. fill: bool(false, { set: style('fill') }), smoothFactor: num(1.0), noClip: bool(), }; const Base: LeafletElementConstructor = WithProps(PROPS); /** `` — a Leaflet `Polyline`. Vertices come from `` children, not an attribute. */ export default class LeafletPolylineElement extends Base { declare readonly leafletObject?: Polyline; declare addEventListener: LeafletAddEventListener; declare removeEventListener: LeafletRemoveEventListener; #vertices = new VertexTracker(); createLeafletObject(options: PolylineOptions): Polyline { return new Polyline(this.#vertices.coords(), options); } // Vertices come from children rather than an attribute -- // each one announces its own position via leaflet-line-sync/-remove, we // never read a child's state directly. connectedCallback(): void { super.connectedCallback(); this.addEventListener('leaflet-line-sync', this.#onLineSync); this.addEventListener('leaflet-line-remove', this.#onLineRemove); } disconnectedCallback(): void { this.removeEventListener('leaflet-line-sync', this.#onLineSync); this.removeEventListener('leaflet-line-remove', this.#onLineRemove); super.disconnectedCallback(); } #onLineSync = (e: LeafletLineSyncEvent) => { this.#vertices.sync(e.detail.element, e.detail.latlng); this.leafletObject?.setLatLngs(this.#vertices.coords()); }; #onLineRemove = (e: LeafletLineRemoveEvent) => { this.#vertices.remove(e.detail.element); this.leafletObject?.setLatLngs(this.#vertices.coords()); }; }