refactor: replace PROPS literal tables with factory helpers
Add num(), str(), on() factory functions and defineProps() wrapper
to core/props.ts. Each helper returns a PropDef fragment without
'attr'; defineProps fills it in via camelToKebab(key), with an
optional override for edge cases like playsInline->playsinline.
Input types are derived from their canonical counterparts via
OptionalAttr<T> = Omit<T, 'attr'> & { attr?: string }, keeping
definitions in sync automatically.
Net effect: ~3800 chars removed across 18 component files, no
behavior change, full type inference preserved.
This commit is contained in:
parent
96037f22b6
commit
f615dceea3
@ -4,19 +4,19 @@ import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import { isPathStyleAttr, updatePathStyle } from '../core/path-style.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
lat: { kind: 'num', attr: 'lat', default: 0 },
|
||||
lng: { kind: 'num', attr: 'lng', default: 0 },
|
||||
radius: { kind: 'num', attr: 'radius', default: 10 },
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
lat: num(),
|
||||
lng: num(),
|
||||
radius: num(10),
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
});
|
||||
|
||||
export default class LeafletCircleMarker extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: CircleMarker;
|
||||
|
||||
@ -4,19 +4,19 @@ import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import { isPathStyleAttr, updatePathStyle } from '../core/path-style.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
lat: { kind: 'num', attr: 'lat', default: 0 },
|
||||
lng: { kind: 'num', attr: 'lng', default: 0 },
|
||||
radius: { kind: 'num', attr: 'radius', default: 1000 },
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
lat: num(),
|
||||
lng: num(),
|
||||
radius: num(1000),
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
});
|
||||
|
||||
export default class LeafletCircle extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Circle;
|
||||
|
||||
@ -2,12 +2,12 @@ import { Control, ControlPosition } from 'leaflet';
|
||||
import { registerWithParent } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, str } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
position: { kind: 'str', attr: 'position', default: 'bottomright' },
|
||||
prefix: { kind: 'str', attr: 'prefix', default: '' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
position: str('bottomright'),
|
||||
prefix: str(),
|
||||
});
|
||||
|
||||
export default class LeafletControlAttribution extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Control.Attribution;
|
||||
|
||||
@ -2,15 +2,15 @@ import { Control, ControlPosition } from 'leaflet';
|
||||
import { registerWithParent } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
position: { kind: 'str', attr: 'position', default: 'bottomleft' },
|
||||
maxWidth: { kind: 'num', attr: 'max-width', default: 100 },
|
||||
metric: { kind: 'bool-on', attr: 'metric' },
|
||||
imperial: { kind: 'bool-on', attr: 'imperial' },
|
||||
updateWhenIdle: { kind: 'bool-on', attr: 'update-when-idle' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
position: str('bottomleft'),
|
||||
maxWidth: num(100),
|
||||
metric: on(),
|
||||
imperial: on(),
|
||||
updateWhenIdle: on(),
|
||||
});
|
||||
|
||||
export default class LeafletControlScale extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Control.Scale;
|
||||
|
||||
@ -2,15 +2,15 @@ import { Control, ControlPosition } from 'leaflet';
|
||||
import { registerWithParent } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, str } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
position: { kind: 'str', attr: 'position', default: 'topleft' },
|
||||
zoomInText: { kind: 'str', attr: 'zoom-in-text', default: '+' },
|
||||
zoomInTitle: { kind: 'str', attr: 'zoom-in-title', default: 'Zoom in' },
|
||||
zoomOutText: { kind: 'str', attr: 'zoom-out-text', default: '-' },
|
||||
zoomOutTitle: { kind: 'str', attr: 'zoom-out-title', default: 'Zoom out' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
position: str('topleft'),
|
||||
zoomInText: str('+'),
|
||||
zoomInTitle: str('Zoom in'),
|
||||
zoomOutText: str('-'),
|
||||
zoomOutTitle: str('Zoom out'),
|
||||
});
|
||||
|
||||
export default class LeafletControlZoom extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Control.Zoom;
|
||||
|
||||
@ -3,23 +3,23 @@ import { buildOptions } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren, getChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
data: { kind: 'str', attr: 'data', default: '' },
|
||||
stroke: { kind: 'str', attr: 'stroke', default: '' },
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
lineCap: { kind: 'str', attr: 'line-cap', default: 'round' },
|
||||
lineJoin: { kind: 'str', attr: 'line-join', default: 'round' },
|
||||
dashArray: { kind: 'str', attr: 'dash-array', default: '' },
|
||||
dashOffset: { kind: 'str', attr: 'dash-offset', default: '' },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
fillRule: { kind: 'str', attr: 'fill-rule', default: 'evenodd' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
data: str(),
|
||||
stroke: str(),
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
lineCap: str('round'),
|
||||
lineJoin: str('round'),
|
||||
dashArray: str(),
|
||||
dashOffset: str(),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
fillRule: str('evenodd'),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = new Map<string, string>(
|
||||
Object.entries(PROPS).map(([name, spec]) => [spec.attr, name]),
|
||||
|
||||
@ -4,19 +4,19 @@ import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../co
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
url: { kind: 'str', attr: 'url', default: '' },
|
||||
bounds: { kind: 'str', attr: 'bounds', default: '' },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
alt: { kind: 'str', attr: 'alt', default: '' },
|
||||
interactive: { kind: 'bool-on', attr: 'interactive' },
|
||||
crossOrigin: { kind: 'str', attr: 'cross-origin', default: '' },
|
||||
errorOverlayUrl: { kind: 'str', attr: 'error-overlay-url', default: '' },
|
||||
zIndex: { kind: 'num', attr: 'z-index', default: 0 },
|
||||
className: { kind: 'str', attr: 'class-name', default: '' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
url: str(),
|
||||
bounds: str(),
|
||||
opacity: num(1.0),
|
||||
alt: str(),
|
||||
interactive: on(),
|
||||
crossOrigin: str(),
|
||||
errorOverlayUrl: str(),
|
||||
zIndex: num(),
|
||||
className: str(),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -3,17 +3,17 @@ import { buildOptions, numAttr, buildAttrMap, setLayerAttr } from '../core/utils
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
lat: { kind: 'num', attr: 'lat', default: 0 },
|
||||
lng: { kind: 'num', attr: 'lng', default: 0 },
|
||||
title: { kind: 'str', attr: 'title', default: '' },
|
||||
alt: { kind: 'str', attr: 'alt', default: '' },
|
||||
draggable: { kind: 'bool-on', attr: 'draggable' },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
zIndexOffset: { kind: 'num', attr: 'z-index-offset', default: 0 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
lat: num(),
|
||||
lng: num(),
|
||||
title: str(),
|
||||
alt: str(),
|
||||
draggable: on(),
|
||||
opacity: num(1.0),
|
||||
zIndexOffset: num(),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -4,17 +4,17 @@ import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import { isPathStyleAttr, updatePathStyle } from '../core/path-style.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
import type LeafletLine from './leaflet-line.ts';
|
||||
|
||||
const PROPS = {
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
});
|
||||
|
||||
export default class LeafletPolygon extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Polygon;
|
||||
|
||||
@ -4,17 +4,17 @@ import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import { isPathStyleAttr, updatePathStyle } from '../core/path-style.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
import type LeafletLine from './leaflet-line.ts';
|
||||
|
||||
const PROPS = {
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
});
|
||||
|
||||
export default class LeafletPolyline extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Polyline;
|
||||
|
||||
@ -2,18 +2,18 @@ import { Popup } from 'leaflet';
|
||||
import { registerWithParent, buildOptions, numAttr } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
lat: { kind: 'num', attr: 'lat', default: 0 },
|
||||
lng: { kind: 'num', attr: 'lng', default: 0 },
|
||||
maxWidth: { kind: 'num', attr: 'max-width', default: 300 },
|
||||
minWidth: { kind: 'num', attr: 'min-width', default: 50 },
|
||||
maxHeight: { kind: 'num', attr: 'max-height', default: 0 },
|
||||
autoPan: { kind: 'bool-on', attr: 'auto-pan' },
|
||||
closeButton: { kind: 'bool-on', attr: 'close-button' },
|
||||
autoClose: { kind: 'bool-on', attr: 'auto-close' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
lat: num(),
|
||||
lng: num(),
|
||||
maxWidth: num(300),
|
||||
minWidth: num(50),
|
||||
maxHeight: num(),
|
||||
autoPan: on(),
|
||||
closeButton: on(),
|
||||
autoClose: on(),
|
||||
});
|
||||
|
||||
export default class LeafletPopup extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Popup;
|
||||
|
||||
@ -4,17 +4,17 @@ import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import { isPathStyleAttr, updatePathStyle } from '../core/path-style.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
bounds: { kind: 'str', attr: 'bounds', default: '' },
|
||||
color: { kind: 'str', attr: 'color', default: '#3388ff' },
|
||||
weight: { kind: 'num', attr: 'weight', default: 3 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
fill: { kind: 'bool-on', attr: 'fill' },
|
||||
fillColor: { kind: 'str', attr: 'fill-color', default: '#3388ff' },
|
||||
fillOpacity: { kind: 'num', attr: 'fill-opacity', default: 0.2 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
bounds: str(),
|
||||
color: str('#3388ff'),
|
||||
weight: num(3),
|
||||
opacity: num(1.0),
|
||||
fill: on(),
|
||||
fillColor: str('#3388ff'),
|
||||
fillOpacity: num(0.2),
|
||||
});
|
||||
|
||||
export default class LeafletRectangle extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Rectangle;
|
||||
|
||||
@ -4,16 +4,16 @@ import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../co
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
bounds: { kind: 'str', attr: 'bounds', default: '' },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
interactive: { kind: 'bool-on', attr: 'interactive' },
|
||||
crossOrigin: { kind: 'str', attr: 'cross-origin', default: '' },
|
||||
zIndex: { kind: 'num', attr: 'z-index', default: 0 },
|
||||
className: { kind: 'str', attr: 'class-name', default: '' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
bounds: str(),
|
||||
opacity: num(1.0),
|
||||
interactive: on(),
|
||||
crossOrigin: str(),
|
||||
zIndex: num(),
|
||||
className: str(),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -3,17 +3,17 @@ import { buildOptions, buildAttrMap, setLayerAttr, parseAttributeValue } from '.
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
url: { kind: 'str', attr: 'url', default: '' },
|
||||
layers: { kind: 'str', attr: 'layers', default: '' },
|
||||
styles: { kind: 'str', attr: 'styles', default: '' },
|
||||
format: { kind: 'str', attr: 'format', default: 'image/jpeg' },
|
||||
transparent: { kind: 'bool-on', attr: 'transparent' },
|
||||
version: { kind: 'str', attr: 'version', default: '1.1.1' },
|
||||
uppercase: { kind: 'bool-on', attr: 'uppercase' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
url: str(),
|
||||
layers: str(),
|
||||
styles: str(),
|
||||
format: str('image/jpeg'),
|
||||
transparent: on(),
|
||||
version: str('1.1.1'),
|
||||
uppercase: on(),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -3,16 +3,16 @@ import { buildOptions, buildAttrMap, setLayerAttr } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
url: { kind: 'str', attr: 'url', default: '' },
|
||||
attribution: { kind: 'str', attr: 'attribution', default: '' },
|
||||
minZoom: { kind: 'num', attr: 'min-zoom', default: 0 },
|
||||
maxZoom: { kind: 'num', attr: 'max-zoom', default: 18 },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
zIndex: { kind: 'num', attr: 'z-index', default: 0 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
url: str(),
|
||||
attribution: str(),
|
||||
minZoom: num(),
|
||||
maxZoom: num(18),
|
||||
opacity: num(1.0),
|
||||
zIndex: num(),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -3,18 +3,18 @@ import type { TooltipOptions } from 'leaflet';
|
||||
import { registerWithParent, buildOptions, numAttr } from '../core/utils.ts';
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
lat: { kind: 'num', attr: 'lat', default: 0 },
|
||||
lng: { kind: 'num', attr: 'lng', default: 0 },
|
||||
pane: { kind: 'str', attr: 'pane', default: '' },
|
||||
offset: { kind: 'str', attr: 'offset', default: '' },
|
||||
direction: { kind: 'str', attr: 'direction', default: 'auto' },
|
||||
permanent: { kind: 'bool-on', attr: 'permanent' },
|
||||
sticky: { kind: 'bool-on', attr: 'sticky' },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
lat: num(),
|
||||
lng: num(),
|
||||
pane: str(),
|
||||
offset: str(),
|
||||
direction: str('auto'),
|
||||
permanent: on(),
|
||||
sticky: on(),
|
||||
opacity: num(1.0),
|
||||
});
|
||||
|
||||
export default class LeafletTooltip extends withProps(HTMLElement, PROPS) {
|
||||
#obj?: Tooltip;
|
||||
|
||||
@ -4,20 +4,20 @@ import { buildOptions, buildAttrMap, setLayerAttr, parseBoundsAttr } from '../co
|
||||
import { withProps } from '../core/with-props.ts';
|
||||
|
||||
import { registerChildren, unregisterChildren } from '../core/register.ts';
|
||||
import type { PropDef } from '../core/props.ts';
|
||||
import { defineProps, num, str, on } from '../core/props.ts';
|
||||
|
||||
const PROPS = {
|
||||
url: { kind: 'str', attr: 'url', default: '' },
|
||||
bounds: { kind: 'str', attr: 'bounds', default: '' },
|
||||
opacity: { kind: 'num', attr: 'opacity', default: 1.0 },
|
||||
alt: { kind: 'str', attr: 'alt', default: '' },
|
||||
interactive: { kind: 'bool-on', attr: 'interactive' },
|
||||
crossOrigin: { kind: 'str', attr: 'cross-origin', default: '' },
|
||||
loop: { kind: 'bool-on', attr: 'loop' },
|
||||
autoplay: { kind: 'bool-on', attr: 'autoplay' },
|
||||
muted: { kind: 'bool-on', attr: 'muted' },
|
||||
playsInline: { kind: 'bool-on', attr: 'playsinline' },
|
||||
} satisfies Record<string, PropDef>;
|
||||
const PROPS = defineProps({
|
||||
url: str(),
|
||||
bounds: str(),
|
||||
opacity: num(1.0),
|
||||
alt: str(),
|
||||
interactive: on(),
|
||||
crossOrigin: str(),
|
||||
loop: on(),
|
||||
autoplay: on(),
|
||||
muted: on(),
|
||||
playsInline: on('playsinline'),
|
||||
});
|
||||
|
||||
const PROP_BY_ATTR = buildAttrMap(PROPS);
|
||||
|
||||
|
||||
@ -31,3 +31,46 @@ export type PropTypeOf<T extends PropDef> = T extends NumProp
|
||||
export type PropTypesFromTable<T extends Record<string, PropDef>> = {
|
||||
[K in keyof T]: PropTypeOf<T[K]>;
|
||||
};
|
||||
|
||||
// --- Factory helpers ---
|
||||
|
||||
type OptionalAttr<T> = Omit<T, 'attr'> & { attr?: string };
|
||||
|
||||
type NumPropInput = OptionalAttr<NumProp>;
|
||||
type StrPropInput = OptionalAttr<StrProp>;
|
||||
type BoolOnPropInput = OptionalAttr<BoolOnProp>;
|
||||
|
||||
type PropDefInput = NumPropInput | StrPropInput | BoolOnPropInput;
|
||||
|
||||
type PropDefFromInput<T> =
|
||||
T extends { kind: 'num' } ? NumProp
|
||||
: T extends { kind: 'str' } ? StrProp
|
||||
: BoolOnProp;
|
||||
|
||||
function camelToKebab(s: string): string {
|
||||
return s.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
|
||||
}
|
||||
|
||||
export function num(def: number = 0, attr?: string): NumPropInput {
|
||||
return { kind: 'num', default: def, ...(attr ? { attr } : {}) };
|
||||
}
|
||||
|
||||
export function str(def: string = '', attr?: string): StrPropInput {
|
||||
return { kind: 'str', default: def, ...(attr ? { attr } : {}) };
|
||||
}
|
||||
|
||||
export function on(attr?: string): BoolOnPropInput {
|
||||
return { kind: 'bool-on', ...(attr ? { attr } : {}) };
|
||||
}
|
||||
|
||||
export function defineProps<T extends Record<string, PropDefInput>>(
|
||||
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;
|
||||
output[key] = { ...rest, attr: override ?? camelToKebab(key) } as PropDef;
|
||||
}
|
||||
return output as any;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user