diff --git a/src/components/leaflet-image-overlay.ts b/src/components/leaflet-image-overlay.ts index 5107a2f..4b7bb66 100644 --- a/src/components/leaflet-image-overlay.ts +++ b/src/components/leaflet-image-overlay.ts @@ -1,5 +1,5 @@ import { ImageOverlay, LatLngBounds, LatLngExpression } from 'leaflet'; -import { buildOptions, parseAttributeValue, parseBoundsAttr } from '../core/utils.js'; +import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -17,9 +17,7 @@ const PROPS = { className: { kind: 'str', attr: 'class-name', default: '' }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletImageOverlay extends withProps(HTMLElement, PROPS) { #obj?: ImageOverlay; @@ -50,15 +48,7 @@ export class LeafletImageOverlay extends withProps(HTMLElement, PROPS) { const el = this.#obj.getElement(); if (el) (el as HTMLImageElement).alt = val ?? ''; } else { - const propName = PROP_BY_ATTR.get(name); - if (!propName) return; - const setter = - `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof ImageOverlay; - if (typeof this.#obj[setter] === 'function') { - const spec = PROPS[propName as keyof typeof PROPS]; - const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); - (this.#obj[setter] as (v: unknown) => void)(value); - } + setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val); } } } diff --git a/src/components/leaflet-marker.ts b/src/components/leaflet-marker.ts index a44936a..7f4caeb 100644 --- a/src/components/leaflet-marker.ts +++ b/src/components/leaflet-marker.ts @@ -1,5 +1,5 @@ import { Marker } from 'leaflet'; -import { buildOptions, numAttr, parseAttributeValue } from '../core/utils.js'; +import { buildOptions, numAttr, buildAttrMap, setLayerAttr } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -15,9 +15,7 @@ const PROPS = { zIndexOffset: { kind: 'num', attr: 'z-index-offset', default: 0 }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletMarker extends withProps(HTMLElement, PROPS) { #obj?: Marker; @@ -53,12 +51,7 @@ export class LeafletMarker extends withProps(HTMLElement, PROPS) { const el = this.#obj.getElement(); if (el) (el as HTMLImageElement).alt = val ?? ''; } else { - const propName = PROP_BY_ATTR.get(name); - if (!propName) return; - const setter = `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof Marker; - if (typeof this.#obj[setter] === 'function') { - (this.#obj[setter] as (v: unknown) => void)(parseAttributeValue(val)); - } + setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val); } } diff --git a/src/components/leaflet-svg-overlay.ts b/src/components/leaflet-svg-overlay.ts index e72ec82..b760e7b 100644 --- a/src/components/leaflet-svg-overlay.ts +++ b/src/components/leaflet-svg-overlay.ts @@ -1,5 +1,5 @@ import { SVGOverlay, LatLngBounds, LatLngExpression } from 'leaflet'; -import { buildOptions, parseAttributeValue, parseBoundsAttr } from '../core/utils.js'; +import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -14,9 +14,7 @@ const PROPS = { className: { kind: 'str', attr: 'class-name', default: '' }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletSVGOverlay extends withProps(HTMLElement, PROPS) { #obj?: SVGOverlay; @@ -43,15 +41,7 @@ export class LeafletSVGOverlay extends withProps(HTMLElement, PROPS) { if (name === 'bounds') { this.#obj.setBounds(new LatLngBounds(parseBoundsAttr(this) as LatLngExpression[])); } else { - const propName = PROP_BY_ATTR.get(name); - if (!propName) return; - const setter = - `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof SVGOverlay; - if (typeof this.#obj[setter] === 'function') { - const spec = PROPS[propName as keyof typeof PROPS]; - const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); - (this.#obj[setter] as (v: unknown) => void)(value); - } + setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val); } } } diff --git a/src/components/leaflet-tile-layer-wms.ts b/src/components/leaflet-tile-layer-wms.ts index 1ae7100..bd2ef40 100644 --- a/src/components/leaflet-tile-layer-wms.ts +++ b/src/components/leaflet-tile-layer-wms.ts @@ -1,5 +1,5 @@ import { TileLayer } from 'leaflet'; -import { buildOptions, parseAttributeValue } from '../core/utils.js'; +import { buildOptions, buildAttrMap, setLayerAttr, parseAttributeValue } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -15,9 +15,7 @@ const PROPS = { uppercase: { kind: 'bool-on', attr: 'uppercase' }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletTileLayerWMS extends withProps(HTMLElement, PROPS) { #obj?: TileLayer.WMS; @@ -44,13 +42,8 @@ export class LeafletTileLayerWMS extends withProps(HTMLElement, PROPS) { } else { const propName = PROP_BY_ATTR.get(name); if (!propName) return; - const setter = - `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof TileLayer.WMS; const spec = PROPS[propName as keyof typeof PROPS]; - if (typeof this.#obj[setter] === 'function') { - const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); - (this.#obj[setter] as (v: unknown) => void)(value); - } else { + if (!setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val)) { const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); (this.#obj.setParams as unknown as (params: Record) => void)({ [propName]: value, diff --git a/src/components/leaflet-tile-layer.ts b/src/components/leaflet-tile-layer.ts index 1244cab..555ca6b 100644 --- a/src/components/leaflet-tile-layer.ts +++ b/src/components/leaflet-tile-layer.ts @@ -1,5 +1,5 @@ import { TileLayer } from 'leaflet'; -import { buildOptions, parseAttributeValue } from '../core/utils.js'; +import { buildOptions, buildAttrMap, setLayerAttr } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -14,9 +14,7 @@ const PROPS = { zIndex: { kind: 'num', attr: 'z-index', default: 0 }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletTileLayer extends withProps(HTMLElement, PROPS) { #obj?: TileLayer; @@ -38,13 +36,7 @@ export class LeafletTileLayer extends withProps(HTMLElement, PROPS) { if (name === 'url') { if (val) this.#obj.setUrl(val); } else { - const propName = PROP_BY_ATTR.get(name); - if (!propName) return; - const setter = - `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof TileLayer; - if (typeof this.#obj[setter] === 'function') { - (this.#obj[setter] as (v: unknown) => void)(parseAttributeValue(val)); - } + setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val); } } } diff --git a/src/components/leaflet-video-overlay.ts b/src/components/leaflet-video-overlay.ts index 6c246a1..62ffa1c 100644 --- a/src/components/leaflet-video-overlay.ts +++ b/src/components/leaflet-video-overlay.ts @@ -1,5 +1,5 @@ import { VideoOverlay, LatLngBounds, LatLngExpression } from 'leaflet'; -import { buildOptions, parseAttributeValue, parseBoundsAttr } from '../core/utils.js'; +import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../core/utils.js'; import { withProps } from '../core/with-props.js'; import { registerChildren, unregisterChildren } from '../core/register.js'; @@ -18,9 +18,7 @@ const PROPS = { playsInline: { kind: 'bool-on', attr: 'playsinline' }, } satisfies Record; -const PROP_BY_ATTR = new Map( - Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]), -); +const PROP_BY_ATTR = buildAttrMap(PROPS); export class LeafletVideoOverlay extends withProps(HTMLElement, PROPS) { #obj?: VideoOverlay; @@ -61,15 +59,7 @@ export class LeafletVideoOverlay extends withProps(HTMLElement, PROPS) { else if (name === 'playsinline') el.playsInline = val !== null; } } else { - const propName = PROP_BY_ATTR.get(name); - if (!propName) return; - const setter = - `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}` as keyof VideoOverlay; - if (typeof this.#obj[setter] === 'function') { - const spec = PROPS[propName as keyof typeof PROPS]; - const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); - (this.#obj[setter] as (v: unknown) => void)(value); - } + setLayerAttr(this.#obj!, PROPS, PROP_BY_ATTR, name, val); } } diff --git a/src/core/utils.ts b/src/core/utils.ts index 6f48d5a..769e318 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -50,6 +50,30 @@ export function parseBoundsAttr(el: HTMLElement): LatLngBoundsExpression { return raw ? (JSON.parse(raw) as LatLngBoundsExpression) : []; } +export function buildAttrMap(props: Record): Map { + return new Map(Object.entries(props).map(([name, spec]) => [spec.attr, name])); +} + +export function setLayerAttr( + obj: object, + props: Record, + attrMap: Map, + name: string, + val: string | null, +): boolean { + const propName = attrMap.get(name); + if (!propName) return false; + const spec = props[propName as keyof typeof props]; + const setter = `set${propName.charAt(0).toUpperCase()}${propName.slice(1)}`; + const fn = (obj as Record)[setter]; + if (typeof fn === 'function') { + const value = spec.kind === 'bool-on' ? val !== null : parseAttributeValue(val); + (fn as (v: unknown) => void)(value); + return true; + } + return false; +} + export function buildOptions( el: HTMLElement, props: Record,