@kahwee/sf-map-svg 5.1.3 → 6.0.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +1 -5
  3. package/dist/data/README.md +1 -1
  4. package/dist/src/cluster-renderer.d.ts +1 -1
  5. package/dist/src/district-layer.d.ts +4 -4
  6. package/dist/src/district-layer.js +1 -1
  7. package/dist/src/district-style.d.ts +3 -3
  8. package/dist/src/explorer-data.d.ts +1 -1
  9. package/dist/src/guide-map.d.ts +0 -7
  10. package/dist/src/guide-map.js +0 -33
  11. package/dist/src/guide-static.d.ts +4 -4
  12. package/dist/src/guide-static.js +14 -11
  13. package/dist/src/guide.d.ts +2 -2
  14. package/dist/src/guide.js +1 -1
  15. package/dist/src/{configuration-controller.d.ts → interactive/configuration-controller.d.ts} +7 -7
  16. package/dist/src/{configuration-controller.js → interactive/configuration-controller.js} +2 -2
  17. package/dist/src/{district-controller.d.ts → interactive/district-controller.d.ts} +12 -12
  18. package/dist/src/{district-controller.js → interactive/district-controller.js} +9 -9
  19. package/dist/src/{explorer-sidebar.d.ts → interactive/explorer-sidebar.d.ts} +6 -6
  20. package/dist/src/{explorer-sidebar.js → interactive/explorer-sidebar.js} +4 -4
  21. package/dist/src/{label-coordinator.d.ts → interactive/label-coordinator.d.ts} +7 -7
  22. package/dist/src/{label-coordinator.js → interactive/label-coordinator.js} +2 -2
  23. package/dist/src/{label-renderer.d.ts → interactive/label-renderer.d.ts} +2 -2
  24. package/dist/src/{label-renderer.js → interactive/label-renderer.js} +2 -2
  25. package/dist/src/{explorer-controls.d.ts → interactive/map-controls.d.ts} +4 -4
  26. package/dist/src/{explorer-controls.js → interactive/map-controls.js} +4 -4
  27. package/dist/src/{explorer-core.d.ts → interactive/map-engine.d.ts} +7 -7
  28. package/dist/src/{explorer-core.js → interactive/map-engine.js} +40 -40
  29. package/dist/src/{explorer-shell.d.ts → interactive/map-shell.d.ts} +2 -2
  30. package/dist/src/{explorer-shell.js → interactive/map-shell.js} +2 -2
  31. package/dist/src/{marker-controller.d.ts → interactive/marker-controller.d.ts} +8 -8
  32. package/dist/src/{marker-controller.js → interactive/marker-controller.js} +3 -3
  33. package/dist/src/{marker-layer.d.ts → interactive/marker-renderer.d.ts} +3 -3
  34. package/dist/src/{marker-layer.js → interactive/marker-renderer.js} +2 -2
  35. package/dist/src/map.js +4 -4
  36. package/dist/src/marker-catalog.d.ts +2 -2
  37. package/dist/src/palettes.d.ts +2 -2
  38. package/dist/src/{layers.d.ts → rendering/svg-layers.d.ts} +7 -7
  39. package/dist/src/{layers.js → rendering/svg-layers.js} +1 -1
  40. package/dist/src/{map-core.d.ts → rendering/svg-map-renderer.d.ts} +7 -7
  41. package/dist/src/{map-core.js → rendering/svg-map-renderer.js} +6 -6
  42. package/dist/src/static-animation.d.ts +2 -2
  43. package/dist/src/static-labels.d.ts +3 -3
  44. package/dist/src/static-labels.js +2 -2
  45. package/dist/src/static.d.ts +6 -6
  46. package/dist/src/static.js +4 -9
  47. package/dist/src/transit.js +1 -1
  48. package/dist/src/types.d.ts +13 -11
  49. package/docs/API.md +7 -11
  50. package/docs/EXAMPLES.md +2 -7
  51. package/docs/api-audit.md +3 -3
  52. package/docs/consumer-integration.md +1 -1
  53. package/docs/developer-guide.md +1 -6
  54. package/docs/migration-v6.md +57 -0
  55. package/llms-full.txt +132 -82
  56. package/llms.txt +2 -1
  57. package/package.json +2 -1
  58. /package/dist/src/{svg.d.ts → rendering/svg-primitives.d.ts} +0 -0
  59. /package/dist/src/{svg.js → rendering/svg-primitives.js} +0 -0
package/docs/API.md CHANGED
@@ -54,9 +54,9 @@ const { svg } = renderMap(staticMapData, presentation);
54
54
  const map = createMap(fullMapData, presentation);
55
55
  ```
56
56
 
57
- Static `layers` supports every interactive layer switch. `neighborhoodLabels` applies to the opt-in `labelLayout` described below. Static `appearance` supports `theme`, `colors`, and `districtStyle`; browser typography, area interaction styles, and screen-space marker sizing remain interactive settings. Unknown keys and invalid values are rejected for both flat and grouped options. Supplied grouped keys override flat compatibility keys; omitted or `undefined` grouped keys preserve the flat value or renderer default. Undefined color tokens use the theme default instead of entering SVG attributes. The two renderers retain their existing defaults. Marker arrays accept readonly inputs.
57
+ Static `layers` supports every interactive layer switch. `neighborhoodLabels` applies to the opt-in `labelLayout` described below. Static `appearance` supports `theme`, `colors`, and `districtStyle`; browser typography, area interaction styles, and screen-space marker sizing remain interactive settings. Unknown keys and invalid values are rejected. Presentation belongs under `layers` and `appearance`; flat presentation keys are rejected. Omitted or `undefined` grouped keys preserve renderer defaults. Undefined color tokens use the theme default instead of entering SVG attributes. The two renderers retain their existing defaults. Marker arrays accept readonly inputs.
58
58
 
59
- Flat compatibility options include `theme`, `width`, `height`, `padding`, `year` (2002, 2012, 2022), `districtLines`, `districtFills`, `districtStyle`, `districtLabels`, `neighborhoodLines`, `neighborhoodLabels`, `labels`, `labelLayout`, `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.
59
+ Top-level static options are `width`, `height`, `padding`, `year`, `source`, `labels`, `labelLayout`, `markers`, `overlays`, `title`, `idPrefix`, and `animation`, alongside `layers` and `appearance`. Each optional layer is independent. User-supplied text and attributes are escaped in SVG output.
60
60
 
61
61
  Custom district IDs must be finite numbers. An empty `labelPoints` array uses the district's primary `label` position.
62
62
 
@@ -64,22 +64,18 @@ The SVG description names the selected neighborhood source for source-aware data
64
64
 
65
65
  `animation: true` (or `{ duration, delay }`) makes a static map draw itself with self-contained, scoped CSS: land fades in, the coast and lines draw, districts grow, then labels and points appear. It plays when the SVG is inserted into a page or loaded as an image, needs no JavaScript, and stays still under `prefers-reduced-motion`. Re-insert the markup to replay it. Default output is unchanged.
66
66
 
67
- Static `labelLayout: { width: 390 }` opts into shared interactive **overview** label priorities, sizes, anchors and collision rules. `width` must be a positive finite CSS canvas width; it does not alter the SVG viewBox. Set `neighborhoodLabels: true` (flat or under `layers`) to add area names in this layout. Guide SVGs and shells enable neighborhood names by default only when opting into `labelLayout`. `labels: false` remains the master switch. Default static output is unchanged.
67
+ Static `labelLayout: { width: 390 }` opts into shared interactive **overview** label priorities, sizes, anchors and collision rules. `width` must be a positive finite CSS canvas width; it does not alter the SVG viewBox. Set `layers: { neighborhoodLabels: true }` to add area names in this layout. Guide SVGs and shells enable neighborhood names by default only when opting into `labelLayout`. `labels: false` remains the master switch. Default static output is unchanged.
68
68
 
69
69
  For editorial previews, `labelLayout` also accepts `maxLabels` (a nonnegative safe integer), `haloColor` (an SVG color string), and `compact: { width, maxLabels }`. The compact width must be positive, finite, and smaller than the main layout width. Each layout places labels around pins independently, then chooses up to its budget for spatial coverage and nearby-pin context (selected marker first when it fits). Without a budget the existing overview order is unchanged. Equal spatial scores retain the original priority order. A zero budget hides text, never pins. The default halo remains white; use the land color for a quieter dark map.
70
70
 
71
71
  Compact mode embeds two label groups and a media query in the same SVG. At or below the compact width it shows the compact group; above it shows the main group. In an `<img>` or standalone SVG, the breakpoint follows the SVG viewport. In inline SVG it follows the document viewport, so use `<img>` for cards whose width differs from the page. No JavaScript, duplicated geometry, external fonts, or extra image requests are needed. The compact width is also its font-layout hint; very narrow images still scale the text. The interactive renderer continues to use its live collision layout after enhancement.
72
72
 
73
73
  ```js
74
- createGuideSVG({
75
- labelLayout: {
74
+ createGuideSVG({ labelLayout: {
76
75
  width: 800,
77
76
  haloColor: '#1b2c28',
78
77
  compact: { width: 480, maxLabels: 4 },
79
- },
80
- colors: { water: '#0a1412', land: '#1b2c28', label: '#d5e3e8' },
81
- markers: places,
82
- });
78
+ }, markers: places, appearance: { colors: { water: '#0a1412', land: '#1b2c28', label: '#d5e3e8' } } });
83
79
  ```
84
80
 
85
81
  See the [field-guide preview recipe](consumer-integration.md#editorial-map-previews) for a complete build-time example.
@@ -110,9 +106,9 @@ Visible markers and clusters share one tab stop. Use `[` and `]` to move focus,
110
106
 
111
107
  Activating coincident pins opens a place chooser, including when compact embeds hide the native marker picker. Clusters zoom when their members can separate at maximum zoom; otherwise they open the chooser. Escape or Close returns focus to the originating pin or cluster when it remains visible. Choosing a place selects its marker; replacing markers or destroying the map closes the chooser. `clusteractivate` still reports the activated cluster's markers.
112
108
 
113
- For a small guide, import `guideMapData` from `/guide/data` and pass it to `createMap`. The optional `/guide` entry also provides `createGuideMap`, `mountGuideMap`, and detailed-data loading for existing guide layouts. `/transit` provides the standalone schematic transit animation. See [examples](EXAMPLES.md) and [consumer integration](consumer-integration.md).
109
+ For a small guide, import `guideMapData` from `/guide/data` and pass it to `createMap`. The optional `/guide` entry also provides `createGuideController`, `mountGuideController`, and detailed-data loading for existing guide layouts. `/transit` provides the standalone schematic transit animation. See [examples](EXAMPLES.md) and [consumer integration](consumer-integration.md).
114
110
 
115
- For the guide preset with the same controller API, use `createGuideController(options)` from `/guide` (or `/guide/map`). It accepts grouped `MapOptions` and returns `MapController`; `mountGuideController(shell, options)` enhances a `createGuideShell()` container. Both use the lightweight guide geography. Existing `createGuideMap` and `mountGuideMap` calls retain their element-based API.
111
+ For the guide preset with the same controller API, use `createGuideController(options)` from `/guide` (or `/guide/map`). It accepts grouped `MapOptions` and returns `MapController`; `mountGuideController(shell, options)` enhances a `createGuideShell()` container. Both use the lightweight guide geography. See [migration to v6](migration-v6.md) for removed compatibility APIs.
116
112
 
117
113
  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.
118
114
 
package/docs/EXAMPLES.md CHANGED
@@ -20,18 +20,13 @@ import { writeFile } from 'node:fs/promises';
20
20
  import { renderMap } from '@kahwee/sf-map-svg';
21
21
  import { staticMapData } from '@kahwee/sf-map-svg/data/static';
22
22
 
23
- const svg = renderMap(staticMapData, {
24
- year: 2022,
25
- landmarks: true,
26
- bartStations: true,
27
- idPrefix: 'example',
28
- }).svg;
23
+ const svg = renderMap(staticMapData, { year: 2022, idPrefix: 'example', layers: { landmarks: true, bartStations: true } }).svg;
29
24
  await writeFile('districts.svg', svg);
30
25
  ```
31
26
 
32
27
  The static preset includes the packaged map layers without interactive lookup collections. For smaller bundles, pass selected data to the root or `/static` renderer. See the [static recipe](../README.md#static-svg).
33
28
 
34
- For an election choropleth, use `renderMap(data, { year, districtStyle })` or
29
+ For an election choropleth, use `renderMap(data, { year, appearance: { districtStyle } })` or
35
30
  `createMap({ map: data, districts: districtMaps, neighborhoods: {} }, options)`.
36
31
  The controller exposes `setDistrictYear`, `setDistrictStyle`, `selectDistrict`, and typed
37
32
  district events; `getLayerPaths(data, { year })` returns fitted paths without SVG markup.
package/docs/api-audit.md CHANGED
@@ -28,7 +28,7 @@ unbounded geographic data can never fail.
28
28
  | Label metrics and camera movement | Reuse screen-space text measurements and nodes across frames. Font loading invalidates measurements; hidden or removed candidates do not remain in the visible layer. |
29
29
  | Marker replacement | Reconcile stable IDs, preserve retained nodes/picker options and entrance animations, cancel removed entrances, and restore focus after reordering. Identical ordered values do not mutate the DOM or restart work. |
30
30
  | Camera and label scheduling | A shared frame advances the camera before rendering dependent labels, marker sizes, and clusters. State/events remain synchronous; cancellation preserves pending layout, and destruction cancels both kinds of work. |
31
- | Guide controllers and compatibility factories | `createGuideController`/`mountGuideController` share grouped options and lifecycle with `createMap`. Existing element factories retain flat options and their return types. |
31
+ | Guide controllers | `createGuideController`/`mountGuideController` share grouped options and lifecycle with `createMap`. Element compatibility factories were removed in v6. |
32
32
  | Layer hidden and bundle cost | Visibility never unloads imported geography. Use narrow entrypoints or data injection to save bytes. |
33
33
 
34
34
  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.
@@ -58,8 +58,8 @@ exceptions are not transactional validation errors and do not roll back an alrea
58
58
  committed change. Direct mutation of the returned DOM can invalidate invariants;
59
59
  use the public methods and `overlayElement` extension point.
60
60
 
61
- Static flat and grouped options reject unknown keys and invalid values before
62
- rendering. Grouped options take precedence over flat compatibility options;
61
+ Static grouped options reject unknown keys and invalid values before
62
+ rendering. Flat presentation keys were removed in v6;
63
63
  static and interactive schemas retain their documented differences. Host layout, delayed images, fonts, and application cards need their
64
64
  own CLS tests. The scale bar is an approximate local Mercator scale, not survey
65
65
  instrumentation. Coincident locations use a place chooser rather than spiderfying. Geographic
@@ -80,7 +80,7 @@ function disposeGuide() {
80
80
 
81
81
  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.
82
82
 
83
- 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.
83
+ For a new browser-only guide, use `createGuideController()` and mount its `.element` as shown in the developer guide. Both guide factories return controllers; mount `map.element` and dispose with `map.destroy()`.
84
84
 
85
85
  ## Choose the data boundary
86
86
 
@@ -22,12 +22,7 @@ import { writeFile } from 'node:fs/promises';
22
22
  import { renderMap } from '@kahwee/sf-map-svg/static';
23
23
  import { staticMapData } from '@kahwee/sf-map-svg/data/static';
24
24
 
25
- const { svg } = renderMap(staticMapData, {
26
- year: 2022,
27
- landmarks: true,
28
- bartStations: true,
29
- title: 'San Francisco districts, 2022',
30
- });
25
+ const { svg } = renderMap(staticMapData, { year: 2022, title: 'San Francisco districts, 2022', layers: { landmarks: true, bartStations: true } });
31
26
  await writeFile('san-francisco.svg', svg);
32
27
  ```
33
28
 
@@ -0,0 +1,57 @@
1
+ # Migrating to v6
2
+
3
+ Version 6 removes the remaining compatibility APIs. Geographic datasets, coordinate
4
+ conventions, defaults and rendering precision are unchanged.
5
+
6
+ ## Static presentation
7
+
8
+ Move flat geographic switches into `layers`, and `theme`, `colors` and
9
+ `districtStyle` into `appearance`. Flat presentation keys now throw.
10
+
11
+ ```js
12
+ const { svg } = renderMap(staticMapData, {
13
+ width: 800,
14
+ labels: true,
15
+ layers: { landmarks: true, bartStations: true, districtFills: false },
16
+ appearance: { theme: 'transit', colors: { water: '#e7f0f3' } },
17
+ });
18
+ ```
19
+
20
+ The same contract applies to `getLayerPaths`, `createGuideSVG` and
21
+ `createGuideShell`. Dimensions, year, source, master labels, label layout,
22
+ markers, overlays, title, ID prefix and animation remain top-level options.
23
+
24
+ ## Guide controllers
25
+
26
+ Replace `createGuideMap` with `createGuideController`, and `mountGuideMap` with
27
+ `mountGuideController`. Both return `MapController`; DOM methods live on `.element`.
28
+ The `InteractiveSFMapElement` and `InteractiveSFMapOptions` guide aliases are removed.
29
+ Use `MapController` and `MapOptions`.
30
+
31
+ ```js
32
+ import { createGuideController } from '@kahwee/sf-map-svg/guide';
33
+ const map = createGuideController({
34
+ features: { motion: true, clustering: true },
35
+ appearance: { colors: { water: '#e7f0f3' } },
36
+ });
37
+ document.querySelector('#map').append(map.element);
38
+ map.configure({ layers: { landmarks: false } });
39
+ map.camera.reset();
40
+ map.on('markerchange', ({ marker }) => console.log(marker));
41
+ // On unmount:
42
+ map.destroy();
43
+ map.element.remove();
44
+ ```
45
+
46
+ Use `configure` for feature, layer, control and appearance changes; use `camera`
47
+ for viewport operations. Replace construction callbacks with `map.on` subscriptions.
48
+ For static-shell enhancement, call `mountGuideController(shell, options)` and keep
49
+ the returned controller for disposal.
50
+
51
+ ## Site integrations
52
+
53
+ Pages builds require a v6-or-newer package and generate examples directly for that
54
+ contract. Older-package feature detection and flat-option fallback generation are
55
+ removed. Playground links must include `version: 1` in their design payload;
56
+ links produced by the current Share control already include it. Unversioned
57
+ handwritten links must add that field.