@kahwee/sf-map-svg 4.1.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +11 -15
- package/dist/src/appearance.d.ts +5 -0
- package/dist/src/appearance.js +54 -0
- package/dist/src/configuration.d.ts +3 -1
- package/dist/src/configuration.js +32 -23
- package/dist/src/controller-types.d.ts +81 -8
- package/dist/src/explorer-core.d.ts +14 -2
- package/dist/src/explorer-core.js +174 -38
- package/dist/src/guide-map.js +1 -1
- package/dist/src/guide-static.js +3 -3
- package/dist/src/map-core.d.ts +14 -0
- package/dist/src/map-core.js +4 -1
- package/dist/src/map.js +164 -18
- package/dist/src/static.d.ts +6 -3
- package/dist/src/static.js +57 -2
- package/dist/src/types.d.ts +10 -2
- package/docs/API.md +67 -1
- package/docs/api-audit.md +7 -7
- package/docs/consumer-integration.md +35 -11
- package/docs/developer-guide.md +6 -4
- package/llms-full.txt +263 -54
- package/llms.txt +1 -1
- package/package.json +3 -2
package/dist/src/static.js
CHANGED
|
@@ -1,9 +1,64 @@
|
|
|
1
|
+
import { prepareAppearance } from './appearance.js';
|
|
2
|
+
import { validateSwitchPatch } from './features.js';
|
|
1
3
|
import { createSFMapWithData, getLayerPathsWithData } from './map-core.js';
|
|
4
|
+
import { assertOptions } from './validation.js';
|
|
2
5
|
/** Server-safe SVG rendering with explicit data; returns SVG plus projection helpers. */
|
|
3
6
|
export function renderMap(data, options = {}) {
|
|
4
|
-
|
|
7
|
+
const prepared = expandStaticOptions(options);
|
|
8
|
+
return createSFMapWithData(prepared, staticInput(data, prepared));
|
|
5
9
|
}
|
|
6
10
|
/** Project canonical layer geometry without constructing an SVG string. */
|
|
7
11
|
export function getLayerPaths(data, options = {}) {
|
|
8
|
-
|
|
12
|
+
const prepared = expandStaticOptions(options);
|
|
13
|
+
return getLayerPathsWithData(prepared, staticInput(data, prepared));
|
|
14
|
+
}
|
|
15
|
+
/** Borrow immutable geometry, deriving only the renderer's lightweight neighborhood rows. */
|
|
16
|
+
function staticInput(data, options) {
|
|
17
|
+
if (options.source !== undefined && !['realtor', 'sf-find', 'analysis'].includes(options.source))
|
|
18
|
+
throw new RangeError('Unknown neighborhood source.');
|
|
19
|
+
if (!('map' in data)) {
|
|
20
|
+
if (options.source !== undefined)
|
|
21
|
+
throw new TypeError('source requires source-aware MapData; compact StaticMapData already chooses its geography.');
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
const source = options.source ??
|
|
25
|
+
['realtor', 'sf-find', 'analysis'].find((candidate) => !!data.neighborhoods[candidate]);
|
|
26
|
+
if (source === undefined)
|
|
27
|
+
return data.map;
|
|
28
|
+
const collection = data.neighborhoods[source];
|
|
29
|
+
if (!collection)
|
|
30
|
+
throw new RangeError(`No ${source} neighborhood dataset was supplied.`);
|
|
31
|
+
return {
|
|
32
|
+
...data.map,
|
|
33
|
+
neighborhoods: collection.features.map(({ geometry, properties }) => ({
|
|
34
|
+
name: properties.sourceName,
|
|
35
|
+
geometry,
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Grouped keys override flat compatibility keys; omitted keys preserve renderer defaults. */
|
|
40
|
+
function expandStaticOptions(options) {
|
|
41
|
+
assertOptions(options, 'static map');
|
|
42
|
+
if (options.layers !== undefined)
|
|
43
|
+
validateSwitchPatch(options.layers, [
|
|
44
|
+
'districtFills',
|
|
45
|
+
'districtLines',
|
|
46
|
+
'districtLabels',
|
|
47
|
+
'neighborhoodLines',
|
|
48
|
+
'landmarks',
|
|
49
|
+
'bartStations',
|
|
50
|
+
'highways',
|
|
51
|
+
'keyRoads',
|
|
52
|
+
'roadLabels',
|
|
53
|
+
]);
|
|
54
|
+
if (options.appearance !== undefined) {
|
|
55
|
+
assertOptions(options.appearance, 'static appearance', ['theme', 'colors', 'districtStyle']);
|
|
56
|
+
}
|
|
57
|
+
const { layers, appearance, ...flat } = options;
|
|
58
|
+
const supplied = (group = {}) => Object.fromEntries(Object.entries(group).filter(([, value]) => value !== undefined));
|
|
59
|
+
return {
|
|
60
|
+
...flat,
|
|
61
|
+
...supplied(layers),
|
|
62
|
+
...supplied(appearance === undefined ? undefined : prepareAppearance({}, appearance)),
|
|
63
|
+
};
|
|
9
64
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -33,11 +33,16 @@ export interface MapOverlay {
|
|
|
33
33
|
label?: string;
|
|
34
34
|
}
|
|
35
35
|
export interface SFMapOptions {
|
|
36
|
+
/** Grouped presentation; supplied keys take precedence over flat compatibility options. */
|
|
37
|
+
layers?: StaticMapLayers;
|
|
38
|
+
appearance?: StaticMapAppearance;
|
|
36
39
|
theme?: 'districts' | 'transit';
|
|
37
40
|
width?: number;
|
|
38
41
|
height?: number;
|
|
39
42
|
padding?: number;
|
|
40
43
|
year?: DistrictYear;
|
|
44
|
+
/** Select a supplied neighborhood definition when rendering source-aware MapData. */
|
|
45
|
+
source?: NeighborhoodSource;
|
|
41
46
|
districtLines?: boolean;
|
|
42
47
|
neighborhoodLines?: boolean;
|
|
43
48
|
districtFills?: boolean;
|
|
@@ -51,7 +56,7 @@ export interface SFMapOptions {
|
|
|
51
56
|
roadLabels?: boolean;
|
|
52
57
|
landmarks?: boolean;
|
|
53
58
|
bartStations?: boolean;
|
|
54
|
-
markers?: MapMarker[];
|
|
59
|
+
markers?: readonly MapMarker[];
|
|
55
60
|
overlays?: readonly MapOverlay[];
|
|
56
61
|
title?: string;
|
|
57
62
|
idPrefix?: string;
|
|
@@ -67,6 +72,9 @@ export interface SFMapOptions {
|
|
|
67
72
|
};
|
|
68
73
|
colors?: Partial<Record<'water' | 'land' | 'district' | 'neighborhood' | 'highway' | 'road' | 'park' | 'landmark' | 'bart' | 'label' | 'marker' | 'selected', string>>;
|
|
69
74
|
}
|
|
75
|
+
/** Presentation supported by both the static and interactive renderers. */
|
|
76
|
+
export type StaticMapLayers = Omit<InteractiveLayers, 'neighborhoodLabels'>;
|
|
77
|
+
export type StaticMapAppearance = Pick<SFMapOptions, 'theme' | 'colors' | 'districtStyle'>;
|
|
70
78
|
/** Serializable viewport in the interactive map's fixed 800 × 800 projected space. */
|
|
71
79
|
export type MapViewport = readonly [x: number, y: number, size: number];
|
|
72
80
|
export type ExplorerMode = 'neighborhoods' | 'districts' | 'basemap';
|
|
@@ -245,4 +253,4 @@ export interface NeighborhoodExplorerElement extends HTMLElement {
|
|
|
245
253
|
export interface TransitAnimationElement extends HTMLElement {
|
|
246
254
|
destroy(): void;
|
|
247
255
|
}
|
|
248
|
-
export type { MapAppearance, MapCamera, MapConfiguration, MapController, MapEvents, MapOptions, } from './controller-types.js';
|
|
256
|
+
export type { MapAppearance, MapCamera, MapCapabilities, MapConfiguration, MapConfigurationSnapshot, MapController, MapControls, MapEvents, MapFeatureReference, MapOptions, MapSelectionChange, MapViewUpdateOptions, ResolvedMapConfiguration, } from './controller-types.js';
|
package/docs/API.md
CHANGED
|
@@ -6,7 +6,22 @@ and event types are exported by [src/api.ts](../src/api.ts) and defined in
|
|
|
6
6
|
|
|
7
7
|
## Static maps
|
|
8
8
|
|
|
9
|
-
Static
|
|
9
|
+
Static maps accept compact `StaticMapData` or the same source-aware `MapData` as interactive maps. With `MapData`, `source` selects a supplied neighborhood definition; SFAR realtor is preferred by default, followed by SF Find and analysis when available. A requested unavailable source throws before styling callbacks run. Compact `StaticMapData` already chooses its neighborhoods, so it rejects a `source` option. Both data shapes retain the static renderer defaults.
|
|
10
|
+
|
|
11
|
+
Static maps accept the same grouped presentation vocabulary as interactive maps:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const presentation = {
|
|
15
|
+
layers: { landmarks: true, bartStations: true },
|
|
16
|
+
appearance: { theme: 'districts' as const, colors: { water: '#e7f0f3' } },
|
|
17
|
+
};
|
|
18
|
+
const { svg } = renderMap(staticMapData, presentation);
|
|
19
|
+
const map = createMap(fullMapData, presentation);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Static `layers` supports every interactive layer switch except `neighborhoodLabels`. Static `appearance` supports `theme`, `colors`, and `districtStyle`; browser typography, area interaction styles, and screen-space marker sizing remain interactive settings. Unknown grouped keys are rejected. Supplied grouped keys override flat compatibility keys; omitted or `undefined` grouped keys preserve the flat value or renderer default. The two renderers retain their existing defaults. Marker arrays accept readonly inputs.
|
|
23
|
+
|
|
24
|
+
Flat compatibility options include `theme`, `width`, `height`, `padding`, `year` (2002, 2012, 2022), `districtLines`, `districtFills`, `districtStyle`, `districtLabels`, `neighborhoodLines`, `labels`, `highways`, `keyRoads`, `roadLabels`, `landmarks`, `bartStations`, `markers`, `overlays`, `title`, `idPrefix`, `colors`, and `animation`. Each optional layer is independent. User-supplied text and attributes are escaped in SVG output.
|
|
10
25
|
|
|
11
26
|
Custom district IDs must be finite numbers. An empty `labelPoints` array uses the district's primary `label` position.
|
|
12
27
|
|
|
@@ -31,3 +46,54 @@ For the guide preset with the same controller API, use `createGuideController(op
|
|
|
31
46
|
Two opt-in features animate the map's lines and layers. `features.layerTransitions` fades layers as `configure({ layers })` and `setMode()` switch them, crossfades neighborhood boundaries when `setSource()` changes the definition, and crossfades district fills on `setDistrictStyle()`. `features.districtMorph` moves district outlines from one map year to the next on `setDistrictYear()`, then settles on the exact published geometry; pass `{ animate: false }` for an instant change. Both default off, own and cancel their animations, and yield to reduced motion.
|
|
32
47
|
|
|
33
48
|
District style callbacks are evaluated once per district at construction and on style or year updates. Hover, selection, and layer toggles reuse the prepared styles; call `setDistrictStyle()` again when external styling data changes. Invalid styles leave the current map unchanged. District fades respect reduced motion and are removed on interruption or destruction.
|
|
49
|
+
|
|
50
|
+
## Live configuration and inspection
|
|
51
|
+
|
|
52
|
+
`map.configure({ appearance, mode, source, year, labels, layers, features, controls })` updates an existing map. Appearance updates preserve the camera, selections, retained marker nodes, and keyboard focus. Mode/source changes through `configure` preserve the camera; the `setMode(mode, { resetView: false })` and `setSource(source, { resetView: false })` convenience methods use the same atomic update path and preserve the camera. Omit the second argument to retain their existing reset behavior. Invalid view-update options fail before changing configuration. Switching neighborhood source clears the neighborhood selection. Changing district year retains a selected district when it exists in the new year. Unsupported datasets, invalid appearance values, and invalid district-style callback results fail during preparation before commit. A reentrant styling callback can supersede the pending patch.
|
|
53
|
+
|
|
54
|
+
Appearance token objects (`colors`, `style`, `labelStyle`, `labelSize`, `areaStyle`) merge supplied keys; other appearance properties replace. Omitted keys retain their value, an explicit `undefined` property removes that override, and `appearance: undefined` resets the whole appearance group. Feature objects retain their existing replacement semantics. Mode/source/year/labels ignore `undefined`; reset them with an explicit value. Patch types explicitly permit these resets with TypeScript’s `exactOptionalPropertyTypes` enabled.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
map.configure({
|
|
58
|
+
appearance: { colors: { water: '#142d45' }, labelStyle: { fontFamily: 'Georgia,serif' } },
|
|
59
|
+
layers: { bartStations: false },
|
|
60
|
+
});
|
|
61
|
+
map.configure({ appearance: undefined }); // restore construction defaults, not initial overrides
|
|
62
|
+
|
|
63
|
+
const overrides = map.getConfiguration();
|
|
64
|
+
const effective = map.getResolvedConfiguration();
|
|
65
|
+
const available = map.getCapabilities();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`getConfiguration()` returns the current mode, source, year and master labels, together with detached feature, layer, control, and appearance overrides; district style callbacks retain their function identity. `getResolvedConfiguration()` adds the current mode, source, year and master labels and resolves **layer switches** through mode defaults, available data, and the master label switch. Appearance/control fields remain overrides. It does not claim that every label is visible: zoom and collision filtering still apply. `getCapabilities()` returns supplied `sources`, usable district `years`, and layer data availability for the current source/year, independent of visibility overrides. These reads throw after destruction.
|
|
69
|
+
|
|
70
|
+
## Common selection event
|
|
71
|
+
|
|
72
|
+
`selectionchange` adds a consistent envelope without changing existing event payloads:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
map.on('selectionchange', (event) => {
|
|
76
|
+
// kind narrows current and previous to the corresponding selection type.
|
|
77
|
+
if (event.kind === 'marker') console.log(event.current?.id, event.previous?.id);
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`kind` is `marker`, `neighborhood`, or `district`. `current` and `previous` are detached selection snapshots or `null`. The event follows committed selection changes, including clearing and a changed district vintage; it does not represent every activation. Existing `markerchange`, `neighborhoodchange`, and `districtchange` events remain supported.
|
|
82
|
+
|
|
83
|
+
## Source-aware feature selection
|
|
84
|
+
|
|
85
|
+
`selectFeature(reference, options)` accepts one typed identity for each selectable kind:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
map.selectFeature({ kind: 'marker', id: 'ferry' }, { fit: false });
|
|
89
|
+
map.selectFeature({ kind: 'neighborhood', source: 'realtor', id: 'inner-mission' });
|
|
90
|
+
map.selectFeature({ kind: 'district', year: 2022, id: 3 });
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Neighborhood IDs are exact source-scoped feature IDs, rather than display names or aliases. District identity includes the boundary year. This operation returns `false` for a missing feature or a source/year other than the map's current supplied geography; it never silently switches definitions or years. Choose geography through `configure` first. An `id` of `null` clears that kind in the referenced current geography. Malformed references throw. Existing `selectMarker`, `selectNeighborhood`, and `selectDistrict` shortcuts remain supported.
|
|
94
|
+
|
|
95
|
+
## Coordinates and units
|
|
96
|
+
|
|
97
|
+
GeoJSON and static projection inputs use `[longitude, latitude]` in WGS84; markers use `{ lng, lat }`. Static `project` returns SVG units. `projectToScreen(lng, lat)` returns pixels relative to the mounted canvas. Camera viewports and pan deltas use the fixed 800 × 800 projected map space, independent of canvas size. Marker radius uses screen pixels in browser maps and SVG units in static output.
|
|
98
|
+
|
|
99
|
+
Explore presentation options in the [live map design playground](https://kahwee.github.io/sf-map-svg/playground.html). The page identifies its package version; released builds use compatible options for that installed version.
|
package/docs/api-audit.md
CHANGED
|
@@ -19,7 +19,8 @@ unbounded geographic data can never fail.
|
|
|
19
19
|
| Clustering and selected/focused markers | Selected/focused pins remain individually reachable. Coincident alternatives remain available through the chooser. |
|
|
20
20
|
| Marker entrance and reduced motion | Entrances are optional, independent of camera motion, and cancel on preference changes or disposal. Stable IDs avoid repeated entrances on filtering. |
|
|
21
21
|
| Hiding touch control while gestures are enabled | Returns touch scrolling to the page. Other toolbar controls remain independent. |
|
|
22
|
-
|
|
|
22
|
+
| Convenience mode/source setters | Share the atomic configuration path. `{ resetView: false }` preserves the camera; omitted options retain the historic reset. Invalid options and unavailable geography leave state unchanged. |
|
|
23
|
+
| Runtime patch omitted/false/undefined | Omitted retains; false disables boolean switches; undefined removes group/key overrides. Top-level mode/source/year/labels set to undefined retain their current values. Nested feature objects replace, rather than deep-merge. |
|
|
23
24
|
| Compact shell and full attribution | Rejected before replacement. Use `createGuideController` for full attribution. Control overrides are honored and may deliberately alter layout. |
|
|
24
25
|
| District style callbacks | Prepare and copy every style before committing. Hover/selection reuse the results; call `setDistrictStyle()` to refresh changed external data. Reentrant updates or destruction supersede pending work. |
|
|
25
26
|
| Rapid district year changes | Both outgoing layers are tracked, inert, and removed on interruption, completion, reduced-motion changes, or destruction. Zero duration creates no transition copies. |
|
|
@@ -29,6 +30,8 @@ unbounded geographic data can never fail.
|
|
|
29
30
|
| Guide controllers and compatibility factories | `createGuideController`/`mountGuideController` share grouped options and lifecycle with `createMap`. Existing element factories retain flat options and their return types. |
|
|
30
31
|
| Layer hidden and bundle cost | Visibility never unloads imported geography. Use narrow entrypoints or data injection to save bytes. |
|
|
31
32
|
|
|
33
|
+
Live appearance patches prepare values, district styles and source replacement before committing; token objects merge by key. Styling callbacks that issue a newer presentation update supersede the pending patch. Resolved layer reads distinguish visibility settings from data availability and from zoom/collision label filtering. The additive selection envelope preserves existing event contracts.
|
|
34
|
+
|
|
32
35
|
## Failure boundaries and regression evidence
|
|
33
36
|
|
|
34
37
|
| Surface | Adversarial checks and behavior |
|
|
@@ -54,7 +57,7 @@ exceptions are not transactional validation errors and do not roll back an alrea
|
|
|
54
57
|
committed change. Direct mutation of the returned DOM can invalidate invariants;
|
|
55
58
|
use the public methods and `overlayElement` extension point.
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
Static grouped layers and appearance reject unknown keys, while flat compatibility options retain their existing surface; strict
|
|
58
61
|
interactive option-key validation is not a claim that all static options share the
|
|
59
62
|
same schema. Host layout, delayed images, fonts, and application cards need their
|
|
60
63
|
own CLS tests. The scale bar is an approximate local Mercator scale, not survey
|
|
@@ -70,9 +73,6 @@ Exercise enable/disable round trips and callbacks that synchronously request a
|
|
|
70
73
|
second update. Add published-type and bundle regressions when the import graph or
|
|
71
74
|
public types change. Update this matrix when introducing a new interaction.
|
|
72
75
|
|
|
73
|
-
## Verification
|
|
76
|
+
## Verification
|
|
74
77
|
|
|
75
|
-
-
|
|
76
|
-
- `pnpm test:stories:coverage` runs Chromium stories and reports browser coverage.
|
|
77
|
-
- `pnpm demo`, `pnpm build-storybook`, `pnpm test:package`, and `pnpm test:visual` cover examples, rendered stories, packed consumer imports, and reviewed map screenshots.
|
|
78
|
-
- The packed consumer asserts removed compatibility entry points are absent.
|
|
78
|
+
Follow the [validation and release runbook](https://github.com/kahwee/sf-map-svg/blob/main/docs/maintenance.md#validation-by-change). The packed consumer also asserts that removed compatibility entry points remain absent.
|
|
@@ -1,23 +1,47 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Embedding and progressive enhancement
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
For basic mounting, events and cleanup, start with the [developer guide](developer-guide.md). The root controller takes explicit geography; the guide entry offers a smaller preset with the same grouped `configure()`, `camera`, `on()`, and `destroy()` contract. See the [migration guide](migration-v3.md) for removed v2 imports.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Render a guide before JavaScript loads
|
|
6
|
+
|
|
7
|
+
On the server or in a build step, render a compact frame:
|
|
6
8
|
|
|
7
9
|
```ts
|
|
8
|
-
import {
|
|
10
|
+
import { createGuideShell } from '@kahwee/sf-map-svg/guide/static';
|
|
11
|
+
|
|
12
|
+
const markup = createGuideShell({ title: 'Explore San Francisco' });
|
|
13
|
+
// Insert markup into your server-rendered HTML.
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The shell uses an 800 × 800 projection with 28 units of padding, matching the interactive map. Use `createGuideSVG()` for custom dimensions. Rendering is offline, with zero runtime dependencies.
|
|
17
|
+
|
|
18
|
+
## Enhance the existing frame
|
|
19
|
+
|
|
20
|
+
In your browser entry, mount the controller into that shell:
|
|
9
21
|
|
|
10
|
-
|
|
22
|
+
```ts
|
|
23
|
+
import { mountGuideController } from '@kahwee/sf-map-svg/guide';
|
|
24
|
+
|
|
25
|
+
const shell = document.querySelector<HTMLElement>('.sf-guide-shell');
|
|
26
|
+
if (!shell) throw new Error('Missing guide shell');
|
|
27
|
+
const guide = mountGuideController(shell, {
|
|
28
|
+
attribution: 'compact',
|
|
11
29
|
features: { motion: { duration: 400 }, markerEntrance: true },
|
|
12
30
|
appearance: { theme: 'transit' },
|
|
13
31
|
});
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
|
|
32
|
+
|
|
33
|
+
// Call before your application removes the containing view.
|
|
34
|
+
function disposeGuide() {
|
|
35
|
+
guide.destroy();
|
|
36
|
+
}
|
|
17
37
|
```
|
|
18
38
|
|
|
19
|
-
|
|
39
|
+
Compact attribution is required for an existing shell. Invalid configuration leaves its static frame intact. `destroy()` disposes listeners and animation work; your application owns removal of the containing view. Motion is opt-in and follows reduced-motion preferences.
|
|
40
|
+
|
|
41
|
+
For a new browser-only guide, use `createGuideController()` and mount its `.element` as shown in the developer guide. Existing `createGuideMap()` and `mountGuideMap()` retain their augmented-element return types and flat options for compatibility.
|
|
42
|
+
|
|
43
|
+
## Choose the data boundary
|
|
20
44
|
|
|
21
|
-
|
|
45
|
+
`createMap(guideMapData, guideOptions)` remains available through `/guide/data` and `/presets`. For server rendering, pass `guideMapData.map` or `/data/static` to `renderMap()`. Use `/data/full` when interactive lookup collections are needed. The guide's detailed geography loads only on an explicit `loadGuideDetailedData()` call; enabling a layer does not download it.
|
|
22
46
|
|
|
23
|
-
|
|
47
|
+
See the [exact API contract](API.md), [worked examples](EXAMPLES.md), and [bundle measurements](guide-bundle-report.md).
|
package/docs/developer-guide.md
CHANGED
|
@@ -80,7 +80,7 @@ function disposeMap() {
|
|
|
80
80
|
| Visible labels | On | On, subject to zoom/collisions |
|
|
81
81
|
| Motion features | Static animation off | Off; opt in via `features` |
|
|
82
82
|
|
|
83
|
-
A layer switch does not download missing geography. `fullMapData` has `.map` for static rendering and separate lookup collections for interactive use. `staticMapData` is already a static data object. Use `renderMap(guideMapData
|
|
83
|
+
A layer switch does not download missing geography. `fullMapData` has `.map` for static rendering and separate lookup collections for interactive use. `staticMapData` is already a static data object. Use `renderMap(guideMapData, options)` or `renderMap(fullMapData, { source: 'sf-find' })` to share source-aware geography with the browser controller. Passing `.map` remains supported as compact static geography; it already chooses its neighborhoods and does not accept a `source` option.
|
|
84
84
|
|
|
85
85
|
SFAR realtor neighborhoods are the default when supplied. If only an alternative collection is supplied, the controller selects that available source. Choose `source` explicitly when comparing definitions. Sources retain separate identities; they are not interchangeable polygons.
|
|
86
86
|
|
|
@@ -88,13 +88,15 @@ SFAR realtor neighborhoods are the default when supplied. If only an alternative
|
|
|
88
88
|
|
|
89
89
|
| Change | Call |
|
|
90
90
|
| --- | --- |
|
|
91
|
-
|
|
|
91
|
+
| Presentation, layers, controls, behaviors | `map.configure({ layers, controls, features, appearance, mode, source, year, labels })` |
|
|
92
92
|
| Map mode or neighborhood source | `map.setMode(mode)`, `map.setSource(source)` |
|
|
93
93
|
| District boundaries or choropleth | `map.setDistrictYear(year)`, `map.setDistrictStyle(callback)` |
|
|
94
94
|
| Master text visibility | `map.setLabels(visible)` |
|
|
95
95
|
| Markers or route overlays | `map.setMarkers(items)`, `map.setOverlays(items)` |
|
|
96
96
|
| Camera | `map.camera.set/pan/zoom/fit/reset(...)` |
|
|
97
|
-
| Palette, typography, control styling |
|
|
97
|
+
| Palette, typography, control styling | `map.configure({ appearance })`; retains camera, selection and focus |
|
|
98
|
+
|
|
99
|
+
Appearance token objects merge by key; `undefined` removes an override and `appearance: undefined` resets the group. Static maps accept grouped `layers` and the shared `appearance` keys (`theme`, `colors`, `districtStyle`) too. See [the API contract](API.md#live-configuration-and-inspection) and [the design playground](https://kahwee.github.io/sf-map-svg/playground.html).
|
|
98
100
|
|
|
99
101
|
`configure` merges supplied keys; omitted keys keep their existing values. Set a layer or control key to `undefined` to remove its override. Set a whole group to `undefined` to reset that group. Set a feature to `false` to disable it. Explicit layer overrides keep winning after mode changes.
|
|
100
102
|
|
|
@@ -105,7 +107,7 @@ map.configure({ features: { motion: false } });
|
|
|
105
107
|
map.configure({ layers: undefined }); // clear all explicit layer overrides
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
`getConfiguration()` returns a detached snapshot of
|
|
110
|
+
`getConfiguration()` returns current mode/source/year/labels and a detached snapshot of the presentation groups, including explicit layer and appearance overrides. Camera and selection remain separate runtime state. Use `getResolvedConfiguration()` for current mode/source/year/labels and effective layer switches, and `getCapabilities()` for supplied geography. Invalid configuration patches leave the current map unchanged. Convenience methods use the same atomic update path: pass `map.setMode(mode, { resetView: false })` or `map.setSource(source, { resetView: false })` to keep the camera. Their default still resets the view.
|
|
109
111
|
|
|
110
112
|
## Markers, routes and camera coordinates
|
|
111
113
|
|