v4.3.1 · on npm
SF MapSVG

Documentation · API reference

The API, in full.

Every entry point, option, method and event, with defaults. For explanations and patterns, start with the guide. Types ship with the package; this page follows them.

Package @kahwee/sf-map-svgMarkdown referenceLLM documentationv4.3.1 · on npm

This reference describes @kahwee/sf-map-svg 4.3.1, the version used throughout this site. Examples and options below match this version.

Entry points

Import from the smallest entry that has what you need. Data entries export frozen objects; clone before editing.

Import fromExportsPurpose
@kahwee/sf-map-svgcreateMap, renderMap, getLayerPathsThe data-free root.
/staticrenderMap, getLayerPathsServer-safe rendering with no DOM.
/mapcreateMapThe interactive controller alone.
/data/staticstaticMapDataComplete geography for static maps.
/data/fullfullMapDataComplete geography for interactive maps.
/datacoast, districtMaps, neighborhoodCollections, neighborhoodSources, getNeighborhood, searchNeighborhoods, catalog, …Datasets and lookup helpers.
/data/coast, /data/districts, /data/realtor, /data/sf-find, /data/analysis, /data/landmarks, /data/highways, /data/roads, /data/stations, /data/lookup, /data/catalogone dataset eachCompose your own geography.
/geometryrawProject, geometryPath, positionsProjection and path helpers.
/guide, /guide/map, /guide/data, /guide/static, /guide/detailedcreateGuideController, mountGuideController, createGuideMap, mountGuideMap, guideMapData, createGuideSVG, createGuideShell, loadGuideDetailedDataLightweight guide presets.
/presetsguideOptionsGuide configuration without data.
/transitcreateTransitAnimationThe schematic BART animation.

renderMap

renderMap(data: StaticMapInput, options?: StaticMapOptions) → { svg: string; project: (position) => [x, y]; viewBox: [0, 0, width, height] }

Renders a self-contained SVG string with no DOM. project converts [lng, lat] into the SVG’s coordinates.

OptionType · defaultDescription
layers, appearanceStaticMapLayers, StaticMapAppearanceShared presentation vocabulary. Grouped keys override flat keys; static appearance supports theme, colors and districtStyle. Neighborhood labels remain browser-only.
sourceNeighborhoodSourceSelect a supplied definition when using source-aware MapData (including fullMapData). SFAR is preferred by default; unavailable sources fail. Compact StaticMapData already chooses its neighborhoods.
year2002 | 2012 | 2022 · 2022District map year.
theme'districts' | 'transit' · 'districts'Soft district palette or quiet transit palette.
width, heightnumber · 800SVG size and view box.
paddingnumber · 28Space around the fitted city.
districtFillsboolean · trueColored district areas.
districtLinesboolean · trueDistrict outlines.
districtLabelsboolean · trueDistrict number badges.
districtStyle(district) => { fill?, stroke?, opacity? }Per-district style, evaluated once per district.
neighborhoodLinesboolean · falseDashed outlines of data.neighborhoods (SFAR in the presets).
landmarksboolean · falsePark boundaries and names.
highwaysboolean · falseHighway lines.
keyRoadsboolean · falseSelected road corridors.
roadLabelsboolean · same as keyRoadsRoad names.
bartStationsboolean · falseThe eight BART stations in the city.
labelsboolean · trueHide every visible label while keeping titles.
markersreadonly MapMarker[] · []Points drawn above everything else.
overlaysreadonly MapOverlay[] · []Your own lines and polygons.
colorsPartial<Record<ColorKey, string>>water, land, district, neighborhood, highway, road, park, landmark, bart, label, marker, selected.
animationboolean | { duration?, delay? } · falseSelf-contained draw-in. duration defaults to 2400 ms and scales the sequence.
titlestring · 'San Francisco map'Accessible title.
idPrefixstring · generatedPrefix for element ids and animation scope.

getLayerPaths

getLayerPaths(data: StaticMapInput, options?: StaticMapOptions) → { year, viewBox, project, coast, districts, neighborhoods, highways, landmarks, keyRoads, bartStations }

Returns fitted path strings and points for each layer without building SVG markup, for canvas renderers and custom drawings.

createMap

createMap(data: MapData, options?: MapOptions) → MapController

Creates an interactive map. Mount controller.element. Unknown options throw, so typos surface immediately.

OptionType · defaultDescription
mode'basemap' | 'neighborhoods' | 'districts' · 'basemap'What the map is about; sets default layers and selection.
source'realtor' | 'sf-find' | 'analysis' · 'realtor'Neighborhood definition.
neighborhoodstringSelect a neighborhood by name or alias at start.
year2002 | 2012 | 2022 · 2022District map year.
labelsboolean · trueVisible labels.
layersInteractiveLayersSee layers.
controlsMapControlsSee controls.
featuresMapFeaturesSee features.
appearanceMapAppearanceSee appearance. Update live with configure.
markersreadonly MapMarker[]Initial markers.
overlaysreadonly MapOverlay[]Initial overlays.
legend{ builtins?, hidden?, items? }Legend entries.
stringsPartial<Record<StringKey, string>>Replace interface text for translation.
attribution'full' | 'compact' · 'full'Source credit style.
fitPaddingnumber | MapPadding · 24Screen pixels kept clear when fitting.
selectableNeighborhoodsboolean · trueWhether neighborhoods respond to selection.

features

Opt-in behaviors. Pass true for defaults or an object to tune them. Change them at runtime with map.configure({ features }). Reduced motion always takes precedence.

FeatureOptions · defaultsDescription
motion{ duration: 320 }Ease the camera.
markerEntrance{ duration: 420, stagger: 35 }Animate new markers in.
selectedMarkerRing{ color, width: 2, gap: 3 }Ring around the selected marker.
clustering{ radius: 32 }Screen-space marker clusters with an accessible chooser.
layerTransitions{ duration: 360 }Fade layer switches; crossfade setSource and setDistrictStyle.
districtMorph{ duration: 1100 }Morph outlines on setDistrictYear.
northArrowbooleanShow a north arrow.
scaleBarbooleanShow an approximate scale bar.

layers

Each key is a boolean override. Omitted keys follow the mode: district layers show in 'districts', neighborhood layers in 'neighborhoods', and the rest show in every mode.

KeyDefaultDraws
districtFills, districtLines, districtLabelsdistricts modeDistrict areas, outlines and numbers.
neighborhoodLines, neighborhoodLabelsneighborhoods modeNeighborhood outlines and names.
landmarksonParks.
highways, keyRoads, roadLabelsonRoads and their names.
bartStationsonBART stations.

controls

Independent switches for the map’s own interface: zoom, pan, reset, labels, touch, legend, neighborhoodPicker, markerPicker, help and status. Hiding a picker means you should provide your own accessible list. Attribution always remains.

appearance

Update with map.configure({ appearance }) while preserving camera, selection and focus. Token objects merge by key; appearance: undefined resets the group.

KeyType · defaultDescription
theme'districts' | 'transit' · 'transit'Base palette.
colorsPartial<Record<ColorKey, string>>As in renderMap.
districtStyle(district) => DistrictStyleInitial choropleth; change with setDistrictStyle.
labelStyle{ fontFamily?, fontWeight?, haloColor? }Label typography.
labelSize{ min?: 11, max?: 12 }Screen-pixel label sizes, 8 to 32.
areaStyle{ selectedFill?, selectedStroke?, hoverFill?, hoverStroke? }Neighborhood highlight colors.
style{ ink?, surface?, accent?, border?, focus?, controlGap?, font? }Tokens for the map’s controls. CSS variables work.
markerRadius, markerHitSizenumber · 6, 44Marker size and touch target, in screen pixels.
markerColor, selectedMarkerColorstringMarker colors.

MapController

MemberSignatureDescription
elementHTMLElementMount this.
overlayElementHTMLDivElementPositioned layer for your own HTML.
cameraMapCameraSee MapCamera.
destroyedbooleanTrue after destroy().
configure(patch: { features?, layers?, controls?, appearance?, mode?, source?, year?, labels? })Atomic runtime change; invalid patches change nothing. Omitted keys retain values; undefined groups reset.
getConfiguration() → snapshotCurrent mode/source/year/labels plus detached presentation overrides. Camera and selection are separate. Styling callbacks keep their identity.
getResolvedConfiguration() → ResolvedMapConfigurationCurrent mode/source/year/labels and effective layer switches; label collision and zoom rules still apply.
getCapabilities() → MapCapabilitiesSupplied sources, years and layer data availability, independent of visibility.
selectFeature(reference, options?) → booleanTyped kind/ID with neighborhood source or district year. Select only in current geography; mismatches return false without switching. A null ID clears that kind.
on(type, listener) → unsubscribeTyped events; see Events.
setMode(mode, options?)Switch mode; by default reset the camera. Pass { resetView: false } to preserve the camera. Setters share the atomic configuration path.
setSource(source, options?)Switch neighborhood definition; by default reset the camera. Pass { resetView: false } to preserve the camera. Setters share the atomic configuration path.
setDistrictYear(year, { animate?, duration? })Switch district map; morphs with districtMorph.
setDistrictStyle(style | undefined)Restyle districts.
setLabels(visible: boolean)Show or hide labels.
setMarkers, setOverlays(items)Replace items; markers reconcile by stable id.
selectMarker, selectNeighborhood, selectDistrict(id | name | null, { fit?, animate?, duration? }) → booleanSelect, optionally fitting the camera.
getSelectedMarker, getSelectedNeighborhood, getSelectedDistrict() → selection | nullDetached copies of the current selection.
setTouchNavigation(enabled: boolean)Engage map touch gestures.
projectToScreen(lng, lat) → { x, y, visible }Screen position of a point.
destroy()Idempotent; releases observers, listeners and animations. Does not remove host-owned DOM; other calls after destruction throw.

MapCamera

Viewports are [x, y, size] in the map’s fixed 800 × 800 projected space. Movement methods take { animate?, duration? }; get() and stop() take no arguments.

MethodSignatureDescription
get() → MapViewportCurrent viewport.
set(view, options)Move to a viewport.
fit(geometry, { padding?, … })Fit any GeoJSON geometry.
pan(x, y, options)Pan by projected units.
zoom(factor, options)Zoom about the center.
reset(options)Return to the whole city.
stop()Stop camera motion where it is.

Events

Subscribing
const unsubscribe = map.on('neighborhoodchange', ({ name, source }) => {
  console.log(name, source);
});
EventDetailWhen
selectionchange{ kind, current, previous }Common detached envelope for marker, neighborhood and district selection; null clears. Existing change events retain their payloads.
districtchange{ id, year, district }District selection changes.
districthover{ id, year, district }The hovered district changes.
districtactivate{ id, year, district }A district is clicked or activated by keyboard.
districtyearchange{ year, previousYear }The district map year changes.
neighborhoodchange{ id, name, source, feature }Neighborhood selection changes.
markerchange{ id, marker }Marker selection changes.
overlayactivate{ overlay }An overlay is activated.
clusteractivate{ markers }A marker cluster is activated.
viewportchange{ viewport }The camera moves.
mapresizeundefinedThe map’s size changes.

Types

TypeScript
interface MapMarker {
  id: string;
  lng: number;
  lat: number;
  label?: string;
  selected?: boolean;
  color?: string;
  radius?: number; // screen pixels (interactive), SVG units (static)
}

interface MapOverlay {
  id: string;
  geometry: LineString | MultiLineString | Polygon | MultiPolygon;
  stroke?: string;
  strokeWidth?: number;
  fill?: string;
  fillOpacity?: number;
  visible?: boolean;
  label?: string;
}

interface DistrictStyle {
  fill?: string;
  stroke?: string;
  opacity?: number;
}

type MapViewport = readonly [x: number, y: number, size: number];
type DistrictYear = 2002 | 2012 | 2022;
type NeighborhoodSource = 'realtor' | 'sf-find' | 'analysis';

Guide and transit

createGuideController(options?: MapOptions) → MapController mountGuideController(shell: HTMLElement, options?: MapOptions) → MapController createGuideSVG(options?: StaticMapOptions) → { svg, project, viewBox } createGuideShell(options?: StaticMapOptions) → string createTransitAnimation() → TransitAnimationElement

The guide entries wrap createMap with the lightweight guide geography and layout, and can progressively enhance a server-rendered shell. The transit entry returns a paused, keyboard-operable schematic BART animation; call destroy() when you remove it.