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.
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
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<string, Marker>;
|
|
alt: PropDef<string, Marker>;
|
|
draggable: PropDef<boolean, Marker>;
|
|
opacity: PropDef<number>;
|
|
zIndexOffset: PropDef<number>;
|
|
} = {
|
|
...latLngProps,
|
|
// title and alt end up on the <img> 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<Marker, typeof PROPS> = WithProps(PROPS);
|
|
|
|
/** `<leaflet-marker>` — a Leaflet `Marker`. Accepts `<leaflet-popup>`, `<leaflet-tooltip>`, and `<leaflet-icon>` / `<leaflet-div-icon>` children. */
|
|
export default class LeafletMarkerElement extends Base {
|
|
declare readonly leafletObject?: Marker;
|
|
declare addEventListener: LeafletAddEventListener<MarkerEvents>;
|
|
declare removeEventListener: LeafletRemoveEventListener<MarkerEvents>;
|
|
|
|
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 <leaflet-icon> or <leaflet-div-icon> child announces itself this way.
|
|
#onIconChanged = (e: LeafletIconChangedEvent) => {
|
|
this.leafletObject?.setIcon(e.detail.icon ?? new Icon.Default());
|
|
};
|
|
}
|