refactor: replace any with generics in NumProp and BoolOffProp

Make NumProp and BoolOffProp generic (NumProp<T>, BoolOffProp<T>)
instead of using any, with T inferred from callback parameters at
call sites via the num<T>() and off<T>() factory helpers. Remove
unused num import from leaflet-tile-layer-wms. Fix prettier
formatting issues.
main
Buddy 3 months ago
parent f95cc3b1f6
commit d8bdc2dcfa

@ -55,10 +55,14 @@ const PROPS = defineProps({
transform3DLimit: num(8388608),
// Boolean defaults-true → disable-* attribute; handler-based options have live mapSet
scrollWheelZoom: off((m: LMap, v: boolean) => (v ? m.scrollWheelZoom.enable() : m.scrollWheelZoom.disable())),
scrollWheelZoom: off((m: LMap, v: boolean) =>
v ? m.scrollWheelZoom.enable() : m.scrollWheelZoom.disable(),
),
dragging: off((m: LMap, v: boolean) => (v ? m.dragging.enable() : m.dragging.disable())),
touchZoom: off((m: LMap, v: boolean) => (v ? m.touchZoom.enable() : m.touchZoom.disable())),
doubleClickZoom: off((m: LMap, v: boolean) => (v ? m.doubleClickZoom.enable() : m.doubleClickZoom.disable())),
doubleClickZoom: off((m: LMap, v: boolean) =>
v ? m.doubleClickZoom.enable() : m.doubleClickZoom.disable(),
),
boxZoom: off((m: LMap, v: boolean) => (v ? m.boxZoom.enable() : m.boxZoom.disable())),
keyboard: off((m: LMap, v: boolean) => (v ? m.keyboard.enable() : m.keyboard.disable())),
closePopupOnClick: off(),

@ -3,7 +3,7 @@ import { buildOptions, buildAttrMap, setLayerAttr, parseAttributeValue } from '.
import { WithProps } from '../core/with-props.ts';
import { registerChildren, unregisterChildren } from '../core/register.ts';
import { defineProps, num, str, on } from '../core/props.ts';
import { defineProps, str, on } from '../core/props.ts';
const PROPS = defineProps({
url: str(),
@ -22,10 +22,7 @@ export default class LeafletTileLayerWMS extends WithProps(HTMLElement, PROPS) {
connectedCallback() {
const url = this.getAttribute('url') || '';
this.#obj = new TileLayer.WMS(
url,
buildOptions(this, PROPS, ['url']),
);
this.#obj = new TileLayer.WMS(url, buildOptions(this, PROPS, ['url']));
registerChildren(this, this.#obj);
}

@ -2,7 +2,7 @@ import { Path } from 'leaflet';
import { parseAttributeValue } from './utils.ts';
// The set of HTML attribute names that map to Leaflet Path style options.
// These are handled specially because Leaflet exposes them through
// These are handled especially because Leaflet exposes them through
// setStyle() rather than individual setter methods, and they are shared
// across many vector components (polyline, polygon, circle, rectangle).
const PATH_STYLE_ATTRS = new Set([

@ -1,9 +1,9 @@
export type NumProp = {
export type NumProp<T = unknown> = {
kind: 'num';
attr: string;
default: number;
mapGet?: (m: any) => number | undefined;
mapSet?: (m: any, v: number) => void;
mapGet?: (m: T) => number | undefined;
mapSet?: (m: T, v: number) => void;
viewState?: boolean;
event?: string;
};
@ -19,13 +19,13 @@ export type BoolOnProp = {
attr: string;
};
export type BoolOffProp = {
export type BoolOffProp<T = unknown> = {
kind: 'bool-off';
attr: string;
mapSet?: (m: any, enabled: boolean) => void;
mapSet?: (m: T, enabled: boolean) => void;
};
export type PropDef = NumProp | StrProp | BoolOnProp | BoolOffProp;
export type PropDef = NumProp<unknown> | StrProp | BoolOnProp | BoolOffProp<unknown>;
export type PropTypeOf<T extends PropDef> = T extends NumProp
? number
@ -41,29 +41,36 @@ export type PropTypesFromTable<T extends Record<string, PropDef>> = {
type OptionalAttr<T> = Omit<T, 'attr'> & { attr?: string };
type NumPropInput = OptionalAttr<NumProp>;
type NumPropInput<T = unknown> = OptionalAttr<NumProp<T>>;
type StrPropInput = OptionalAttr<StrProp>;
type BoolOnPropInput = OptionalAttr<BoolOnProp>;
type BoolOffPropInput = OptionalAttr<BoolOffProp>;
type BoolOffPropInput<T = unknown> = OptionalAttr<BoolOffProp<T>>;
type PropDefInput = NumPropInput | StrPropInput | BoolOnPropInput | BoolOffPropInput;
type PropDefInput =
| NumPropInput<unknown>
| StrPropInput
| BoolOnPropInput
| BoolOffPropInput<unknown>;
type PropDefFromInput<T> =
T extends { kind: 'num' } ? NumProp
: T extends { kind: 'str' } ? StrProp
: T extends { kind: 'bool-off' } ? BoolOffProp
T extends NumPropInput<infer U>
? NumProp<U>
: T extends { kind: 'str' }
? StrProp
: T extends BoolOffPropInput<infer U>
? BoolOffProp<U>
: BoolOnProp;
function camelToKebab(s: string): string {
return s.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
return s.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase());
}
export function num(
export function num<T = unknown>(
def: number = 0,
opts?: string | (Omit<NumProp, 'kind' | 'default' | 'attr'> & { attr?: string }),
): NumPropInput {
opts?: string | (Omit<NumProp<T>, 'kind' | 'default' | 'attr'> & { attr?: string }),
): NumPropInput<T> {
if (typeof opts === 'string') opts = { attr: opts };
return { kind: 'num', default: def, ...opts };
return { kind: 'num', default: def, ...opts } as NumPropInput<T>;
}
export function str(def: string = '', attr?: string): StrPropInput {
@ -74,19 +81,20 @@ export function on(attr?: string): BoolOnPropInput {
return { kind: 'bool-on', ...(attr ? { attr } : {}) };
}
export function off(mapSet?: (m: any, enabled: boolean) => void): BoolOffPropInput {
return { kind: 'bool-off', ...(mapSet ? { mapSet } : {}) };
export function off<T = unknown>(mapSet?: (m: T, enabled: boolean) => void): BoolOffPropInput<T> {
return { kind: 'bool-off', ...(mapSet ? { mapSet } : {}) } as BoolOffPropInput<T>;
}
export function defineProps<T extends Record<string, PropDefInput>>(
export function defineProps<T extends Record<string, unknown>>(
input: T,
): { [K in keyof T]: PropDefFromInput<T[K]> } {
const output = {} as Record<string, PropDef>;
for (const key of Object.keys(input)) {
const val = input[key] as PropDefInput;
const { attr: override, ...rest } = val as any;
const attr = override ?? (rest.kind === 'bool-off' ? 'disable-' + camelToKebab(key) : camelToKebab(key));
const { attr: override, ...rest } = val as unknown as Record<string, unknown>;
const attr =
override ?? (rest.kind === 'bool-off' ? 'disable-' + camelToKebab(key) : camelToKebab(key));
output[key] = { ...rest, attr } as PropDef;
}
return output as any;
return output as unknown as { [K in keyof T]: PropDefFromInput<T[K]> };
}

Loading…
Cancel
Save