@kahwee/sf-map-svg 5.1.2 → 5.1.4

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 (44) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/src/cluster-renderer.d.ts +1 -1
  3. package/dist/src/district-layer.d.ts +1 -1
  4. package/dist/src/district-layer.js +1 -1
  5. package/dist/src/district-style.d.ts +1 -1
  6. package/dist/src/explorer-data.d.ts +1 -1
  7. package/dist/src/guide-map.js +3 -3
  8. package/dist/src/interactive/configuration-controller.d.ts +21 -0
  9. package/dist/src/interactive/configuration-controller.js +43 -0
  10. package/dist/src/{district-controller.d.ts → interactive/district-controller.d.ts} +12 -12
  11. package/dist/src/{district-controller.js → interactive/district-controller.js} +9 -9
  12. package/dist/src/{explorer-sidebar.d.ts → interactive/explorer-sidebar.d.ts} +6 -6
  13. package/dist/src/{explorer-sidebar.js → interactive/explorer-sidebar.js} +4 -4
  14. package/dist/src/{label-coordinator.d.ts → interactive/label-coordinator.d.ts} +7 -7
  15. package/dist/src/{label-coordinator.js → interactive/label-coordinator.js} +2 -2
  16. package/dist/src/{label-renderer.d.ts → interactive/label-renderer.d.ts} +2 -2
  17. package/dist/src/{label-renderer.js → interactive/label-renderer.js} +2 -2
  18. package/dist/src/{explorer-controls.d.ts → interactive/map-controls.d.ts} +4 -4
  19. package/dist/src/{explorer-controls.js → interactive/map-controls.js} +4 -4
  20. package/dist/src/{explorer-core.d.ts → interactive/map-engine.d.ts} +9 -8
  21. package/dist/src/{explorer-core.js → interactive/map-engine.js} +154 -140
  22. package/dist/src/{explorer-shell.d.ts → interactive/map-shell.d.ts} +2 -2
  23. package/dist/src/{explorer-shell.js → interactive/map-shell.js} +2 -2
  24. package/dist/src/{marker-controller.d.ts → interactive/marker-controller.d.ts} +8 -8
  25. package/dist/src/{marker-controller.js → interactive/marker-controller.js} +3 -3
  26. package/dist/src/{marker-layer.d.ts → interactive/marker-renderer.d.ts} +3 -3
  27. package/dist/src/{marker-layer.js → interactive/marker-renderer.js} +2 -2
  28. package/dist/src/map.js +15 -38
  29. package/dist/src/marker-catalog.d.ts +2 -2
  30. package/dist/src/{layers.d.ts → rendering/svg-layers.d.ts} +5 -5
  31. package/dist/src/{layers.js → rendering/svg-layers.js} +1 -1
  32. package/dist/src/{map-core.d.ts → rendering/svg-map-renderer.d.ts} +4 -4
  33. package/dist/src/{map-core.js → rendering/svg-map-renderer.js} +6 -6
  34. package/dist/src/static-labels.d.ts +1 -1
  35. package/dist/src/static-labels.js +1 -1
  36. package/dist/src/static.d.ts +2 -2
  37. package/dist/src/static.js +1 -1
  38. package/dist/src/transit.js +1 -1
  39. package/dist/src/types.d.ts +2 -2
  40. package/llms-full.txt +29 -21
  41. package/llms.txt +1 -1
  42. package/package.json +1 -1
  43. /package/dist/src/{svg.d.ts → rendering/svg-primitives.d.ts} +0 -0
  44. /package/dist/src/{svg.js → rendering/svg-primitives.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ User-visible changes are recorded here. Unreleased entries describe changes on `
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 5.1.4 — 2026-11-05
8
+
9
+ - Group internal browser controllers, renderers and shells under `src/interactive`, and SVG generation under `src/rendering`. Rename the general map engine, controls and marker renderer to match their responsibilities; clarify selection-detail, neighborhood-results and layer-composition operations. Keep public package entry points unchanged.
10
+
11
+ ## 5.1.3 — 2026-11-05
12
+
13
+ - Give configuration snapshots and revisions a dedicated internal owner. Split presentation preparation from a guarded, single-use commit, rejecting stale or disposed updates before mutating presentation. Preserve public configuration and reset behavior.
14
+
7
15
  ## 5.1.2 — 2026-11-05
8
16
 
9
17
  - Separate marker selection, activation and focus recovery into an internal controller; separate label candidate caching, screen-space collision layout and metrics invalidation into a label coordinator. Preserve the public API and shared animation frame scheduling.
@@ -1,5 +1,5 @@
1
1
  import type { normalizeFeatures } from './features.js';
2
- import type { MarkerItem, MarkerVisual } from './marker-layer.js';
2
+ import type { MarkerItem, MarkerVisual } from './interactive/marker-renderer.js';
3
3
  import type { createMarkerNavigation } from './marker-navigation.js';
4
4
  import type { MapViewport } from './types.js';
5
5
  interface ClusterState {
@@ -1,4 +1,4 @@
1
- import type { DistrictRowData } from './map-core.js';
1
+ import type { DistrictRowData } from './rendering/svg-map-renderer.js';
2
2
  import type { DistrictStyle, DistrictYear, SFMapOptions } from './types.js';
3
3
  /** Apply prepared styles and interaction state without invoking consumer callbacks. */
4
4
  export declare function renderDistrictAppearance({ svg, rows, styles, selectedDistrict, hoveredDistrict, year, theme, colors, fills, lines, }: {
@@ -1,4 +1,4 @@
1
- import { districtColors } from './map-core.js';
1
+ import { districtColors } from './rendering/svg-map-renderer.js';
2
2
  /** Apply prepared styles and interaction state without invoking consumer callbacks. */
3
3
  export function renderDistrictAppearance({ svg, rows, styles, selectedDistrict, hoveredDistrict, year, theme, colors, fills, lines, }) {
4
4
  for (const row of rows) {
@@ -1,4 +1,4 @@
1
- import type { DistrictRowData } from './map-core.js';
1
+ import type { DistrictRowData } from './rendering/svg-map-renderer.js';
2
2
  import type { DistrictStyle, SFMapOptions } from './types.js';
3
3
  /** Evaluate user code once and copy its result before changing the map. */
4
4
  export declare function prepareDistrictStyles(rows: readonly DistrictRowData[], callback: SFMapOptions['districtStyle']): ReadonlyMap<number, DistrictStyle>;
@@ -1,5 +1,5 @@
1
1
  import type { DistrictProperties, FeatureCollection, NeighborhoodProperties, NeighborhoodSource } from '../data/types.js';
2
- import type { SFMapData } from './map-core.js';
2
+ import type { SFMapData } from './rendering/svg-map-renderer.js';
3
3
  import type { DistrictYear } from './types.js';
4
4
  /** Geographic inputs for the data-injected interactive map entry point. */
5
5
  export interface InteractiveSFMapData {
@@ -1,7 +1,7 @@
1
1
  import { expandMapOptions, prepareConfiguration } from './configuration.js';
2
- import { createNeighborhoodExplorerCore } from './explorer-core.js';
3
- import { createMapShell } from './explorer-shell.js';
4
2
  import { guideMapData } from './guide-data.js';
3
+ import { createMapEngine } from './interactive/map-engine.js';
4
+ import { createMapShell } from './interactive/map-shell.js';
5
5
  import { createMap } from './map.js';
6
6
  import { guideOptions } from './presets.js';
7
7
  import { validateExplorerOptions } from './validation.js';
@@ -62,7 +62,7 @@ function mountFrame(frame, map) {
62
62
  /** Element-based compatibility API. Prefer createGuideController for new integrations. */
63
63
  export function createGuideMap(options = {}) {
64
64
  validateExplorerOptions(options);
65
- return createNeighborhoodExplorerCore({
65
+ return createMapEngine({
66
66
  mode: 'neighborhoods',
67
67
  ...options,
68
68
  layers: {
@@ -0,0 +1,21 @@
1
+ import { prepareConfiguration } from '../configuration.js';
2
+ import type { MapConfiguration } from '../controller-types.js';
3
+ import type { NeighborhoodExplorerElement } from '../types.js';
4
+ /** A prepared engine update may commit once, only while all revisions remain current. */
5
+ export interface PreparedPresentation {
6
+ commit(onCommit: () => void, isCurrent: () => boolean): boolean;
7
+ }
8
+ export interface ConfigurationTarget extends Pick<NeighborhoodExplorerElement, 'setFeatures' | 'setLayers' | 'setControls'> {
9
+ preparePresentation(patch: MapConfiguration): PreparedPresentation | undefined;
10
+ }
11
+ /** Own the public configuration snapshot and invalidate stale updates before DOM mutation. */
12
+ export declare function createConfigurationController(initial: ReturnType<typeof prepareConfiguration>, element: ConfigurationTarget, isDestroyed: () => boolean): {
13
+ configure: (patch: MapConfiguration) => boolean;
14
+ readonly current: {
15
+ features: import("../types.js").MapFeatures;
16
+ layers: import("../types.js").InteractiveLayers;
17
+ controls: import("../controller-types.js").MapControls;
18
+ appearance: import("../controller-types.js").MapAppearance;
19
+ };
20
+ invalidate(): void;
21
+ };
@@ -0,0 +1,43 @@
1
+ import { prepareConfiguration } from '../configuration.js';
2
+ import { controlKeys, layerKeys } from '../features.js';
3
+ /** Own the public configuration snapshot and invalidate stale updates before DOM mutation. */
4
+ export function createConfigurationController(initial, element, isDestroyed) {
5
+ let config = initial;
6
+ let configurationRevision = 0;
7
+ function configure(patch) {
8
+ const revision = ++configurationRevision;
9
+ const next = prepareConfiguration(config, patch);
10
+ const hasFeatures = 'features' in patch, hasLayers = 'layers' in patch, hasControls = 'controls' in patch;
11
+ const layers = Object.fromEntries(layerKeys.map((key) => [key, next.layers[key]]));
12
+ const controls = Object.fromEntries(controlKeys.map((key) => [key, next.controls[key]]));
13
+ const features = patch.features === undefined
14
+ ? next.features
15
+ : Object.fromEntries(Object.keys(patch.features).map((key) => [
16
+ key,
17
+ next.features[key],
18
+ ]));
19
+ const presentation = element.preparePresentation({
20
+ ...patch,
21
+ ...('appearance' in patch ? { appearance: next.appearance } : {}),
22
+ });
23
+ const committed = presentation?.commit(() => {
24
+ config = next;
25
+ if (hasFeatures)
26
+ element.setFeatures(features);
27
+ if (hasLayers)
28
+ element.setLayers(layers);
29
+ if (hasControls)
30
+ element.setControls(controls);
31
+ }, () => !isDestroyed() && revision === configurationRevision);
32
+ return committed === true && !isDestroyed() && revision === configurationRevision;
33
+ }
34
+ return {
35
+ configure,
36
+ get current() {
37
+ return config;
38
+ },
39
+ invalidate() {
40
+ configurationRevision++;
41
+ },
42
+ };
43
+ }
@@ -1,9 +1,9 @@
1
- import type { Geometry, Position } from '../data/types.js';
2
- import { prepareDistrictStyles } from './district-style.js';
3
- import type { InteractiveSFMapData } from './explorer-data.js';
4
- import type { normalizeFeatures } from './features.js';
5
- import type { LabelItem } from './label-candidates.js';
6
- import type { CameraOptions, DistrictSelection, DistrictYear, NeighborhoodExplorerOptions } from './types.js';
1
+ import type { Geometry, Position } from '../../data/types.js';
2
+ import { prepareDistrictStyles } from '../district-style.js';
3
+ import type { InteractiveSFMapData } from '../explorer-data.js';
4
+ import type { normalizeFeatures } from '../features.js';
5
+ import type { LabelItem } from '../label-candidates.js';
6
+ import type { CameraOptions, DistrictSelection, DistrictYear, NeighborhoodExplorerOptions } from '../types.js';
7
7
  type Host = {
8
8
  root: HTMLElement;
9
9
  svg: SVGSVGElement;
@@ -23,12 +23,12 @@ type Host = {
23
23
  fitGeometry(geometry: Geometry, padding: undefined, options: CameraOptions): void;
24
24
  project(point: Position): [number, number];
25
25
  setLabels(items: LabelItem[]): void;
26
- updateComposition(): void;
26
+ syncLayerComposition(): void;
27
27
  scheduleLabels(): void;
28
28
  };
29
29
  /** Owns district selection, styles, revisions and cancellable motion. */
30
30
  export declare function createDistrictController(host: Host, initialDistrictStyle: NeighborhoodExplorerOptions['districtStyle']): {
31
- districtRow: (id: number) => import("./map-core.js").DistrictRowData | undefined;
31
+ districtRow: (id: number) => import("../rendering/svg-map-renderer.js").DistrictRowData | undefined;
32
32
  districtSelection: (id: number | null) => DistrictSelection | {
33
33
  id: null;
34
34
  year: DistrictYear;
@@ -40,7 +40,7 @@ export declare function createDistrictController(host: Host, initialDistrictStyl
40
40
  fit?: boolean;
41
41
  } & CameraOptions) => boolean;
42
42
  activateDistrict: (id: number) => boolean;
43
- setDistrictStyle: (style: ((district: import('./map-core.js').DistrictRowData) => import("./types.js").DistrictStyle) | undefined) => void;
43
+ setDistrictStyle: (style: ((district: import("../rendering/svg-map-renderer.js").DistrictRowData) => import("../types.js").DistrictStyle) | undefined) => void;
44
44
  setDistrictYear: (next: DistrictYear, options?: CameraOptions, preparedStyles?: ReturnType<typeof prepareDistrictStyles>) => void;
45
45
  transition: {
46
46
  cancel(): void;
@@ -56,9 +56,9 @@ export declare function createDistrictController(host: Host, initialDistrictStyl
56
56
  };
57
57
  readonly revision: number;
58
58
  invalidate(): void;
59
- readonly style: ((district: import('./map-core.js').DistrictRowData) => import("./types.js").DistrictStyle) | undefined;
60
- readonly styles: ReadonlyMap<number, import("./types.js").DistrictStyle>;
61
- commitStyles(style: ((district: import('./map-core.js').DistrictRowData) => import("./types.js").DistrictStyle) | undefined, styles: ReadonlyMap<number, import("./types.js").DistrictStyle>): void;
59
+ readonly style: ((district: import("../rendering/svg-map-renderer.js").DistrictRowData) => import("../types.js").DistrictStyle) | undefined;
60
+ readonly styles: ReadonlyMap<number, import("../types.js").DistrictStyle>;
61
+ commitStyles(style: ((district: import("../rendering/svg-map-renderer.js").DistrictRowData) => import("../types.js").DistrictStyle) | undefined, styles: ReadonlyMap<number, import("../types.js").DistrictStyle>): void;
62
62
  hovered: number | null;
63
63
  };
64
64
  export {};
@@ -1,13 +1,13 @@
1
- import { validateCameraOptions } from './camera.js';
2
- import { renderDistrictAppearance } from './district-layer.js';
3
- import { createDistrictMorph } from './district-morph.js';
4
- import { prepareDistrictStyles } from './district-style.js';
5
- import { createDistrictTransition } from './district-transition.js';
6
- import { svgElement } from './dom.js';
7
- import { getLayerPathsWithData } from './map-core.js';
1
+ import { validateCameraOptions } from '../camera.js';
2
+ import { renderDistrictAppearance } from '../district-layer.js';
3
+ import { createDistrictMorph } from '../district-morph.js';
4
+ import { prepareDistrictStyles } from '../district-style.js';
5
+ import { createDistrictTransition } from '../district-transition.js';
6
+ import { svgElement } from '../dom.js';
7
+ import { getLayerPathsWithData } from '../rendering/svg-map-renderer.js';
8
8
  /** Owns district selection, styles, revisions and cancellable motion. */
9
9
  export function createDistrictController(host, initialDistrictStyle) {
10
- const { root, svg, status, data, districtLayers, reducedMotion, enabled, fitGeometry, updateComposition, scheduleLabels, } = host;
10
+ const { root, svg, status, data, districtLayers, reducedMotion, enabled, fitGeometry, syncLayerComposition, scheduleLabels, } = host;
11
11
  const districtMorph = createDistrictMorph();
12
12
  let selectedDistrict = null;
13
13
  let hoveredDistrict = null;
@@ -160,7 +160,7 @@ export function createDistrictController(host, initialDistrictStyle) {
160
160
  if (selectedDistrict === null)
161
161
  delete root.dataset.selectedDistrict;
162
162
  updateDistrictAppearance();
163
- updateComposition();
163
+ syncLayerComposition();
164
164
  if (morph && lineLayer && previousOutlines)
165
165
  districtMorph.start(lineLayer, previousOutlines, {
166
166
  duration: morph.duration,
@@ -1,7 +1,7 @@
1
- import type { NeighborhoodFeature, NeighborhoodSource } from '../data/types.js';
2
- import type { InteractiveSFMapData } from './explorer-data.js';
3
- import type { createExplorerShell } from './explorer-shell.js';
4
- import type { DistrictYear, ExplorerMode } from './types.js';
1
+ import type { NeighborhoodFeature, NeighborhoodSource } from '../../data/types.js';
2
+ import type { InteractiveSFMapData } from '../explorer-data.js';
3
+ import type { DistrictYear, ExplorerMode } from '../types.js';
4
+ import type { createExplorerShell } from './map-shell.js';
5
5
  interface SidebarState {
6
6
  mode: ExplorerMode;
7
7
  year: DistrictYear;
@@ -13,8 +13,8 @@ export declare function createExplorerSidebar({ detail, results, search, count,
13
13
  id: string;
14
14
  canonicalName: string;
15
15
  }[]): {
16
- updateDetail: ({ mode, year, source, selected }: SidebarState) => void;
17
- updateResults: ({ source, selected }: SidebarState) => void;
16
+ updateSelectionDetail: ({ mode, year, source, selected }: SidebarState) => void;
17
+ updateNeighborhoodResults: ({ source, selected }: SidebarState) => void;
18
18
  destroy: () => void;
19
19
  };
20
20
  export {};
@@ -1,4 +1,4 @@
1
- import { element } from './dom.js';
1
+ import { element } from '../dom.js';
2
2
  /** Render sidebar snapshots and own every download URL until replacement or disposal. */
3
3
  export function createExplorerSidebar({ detail, results, search, count, }, data, chrome, emptyResults, searchNeighborhoods) {
4
4
  const downloads = new Set();
@@ -15,7 +15,7 @@ export function createExplorerSidebar({ detail, results, search, count, }, data,
15
15
  link.download = filename;
16
16
  return link;
17
17
  }
18
- function updateDetail({ mode, year, source, selected }) {
18
+ function updateSelectionDetail({ mode, year, source, selected }) {
19
19
  releaseDownloads();
20
20
  if (chrome === 'map')
21
21
  return;
@@ -53,7 +53,7 @@ export function createExplorerSidebar({ detail, results, search, count, }, data,
53
53
  provenance.append(element('summary', 'About these boundaries'), element('p', collection.definition.description));
54
54
  detail.append(provenance);
55
55
  }
56
- function updateResults({ source, selected }) {
56
+ function updateNeighborhoodResults({ source, selected }) {
57
57
  if (chrome === 'map')
58
58
  return;
59
59
  const activeElement = document.activeElement;
@@ -75,5 +75,5 @@ export function createExplorerSidebar({ detail, results, search, count, }, data,
75
75
  if (!matches.length)
76
76
  results.append(element('p', emptyResults ?? 'No matches. Try another name or definition source.', 'sf-explorer-note'));
77
77
  }
78
- return { updateDetail, updateResults, destroy: releaseDownloads };
78
+ return { updateSelectionDetail, updateNeighborhoodResults, destroy: releaseDownloads };
79
79
  }
@@ -1,11 +1,11 @@
1
- import type { View } from './explorer-layout.js';
2
- import type { normalizeFeatures } from './features.js';
3
- import { type LabelItem } from './label-candidates.js';
4
- import type { createMarkerCatalog } from './marker-catalog.js';
1
+ import type { View } from '../explorer-layout.js';
2
+ import type { normalizeFeatures } from '../features.js';
3
+ import { type LabelItem } from '../label-candidates.js';
4
+ import type { createMarkerCatalog } from '../marker-catalog.js';
5
+ import type { createNeighborhoodLayer } from '../neighborhood-layer.js';
6
+ import type { ExplorerMode, InteractiveLayers, NeighborhoodExplorerOptions } from '../types.js';
5
7
  import type { createMarkerController } from './marker-controller.js';
6
- import type { MarkerItem, MarkerVisual } from './marker-layer.js';
7
- import type { createNeighborhoodLayer } from './neighborhood-layer.js';
8
- import type { ExplorerMode, InteractiveLayers, NeighborhoodExplorerOptions } from './types.js';
8
+ import type { MarkerItem, MarkerVisual } from './marker-renderer.js';
9
9
  interface LabelHost {
10
10
  root: HTMLElement;
11
11
  canvas: HTMLElement;
@@ -1,5 +1,5 @@
1
- import { setAttributeIfChanged } from './dom.js';
2
- import { labelCandidates, styleLabels, } from './label-candidates.js';
1
+ import { setAttributeIfChanged } from '../dom.js';
2
+ import { labelCandidates, styleLabels, } from '../label-candidates.js';
3
3
  import { createLabelRenderer } from './label-renderer.js';
4
4
  /** Own candidate caching, screen-space collision layout and label metrics invalidation. */
5
5
  export function createLabelCoordinator(host) {
@@ -1,5 +1,5 @@
1
- import type { Bounds } from '../data/types.js';
2
- import type { RenderLabel } from './label-candidates.js';
1
+ import type { Bounds } from '../../data/types.js';
2
+ import type { RenderLabel } from '../label-candidates.js';
3
3
  /** Reuse text nodes and screen-space metrics throughout a camera animation. */
4
4
  export declare function createLabelRenderer(layer: SVGGElement): {
5
5
  invalidateMetrics(): void;
@@ -1,5 +1,5 @@
1
- import { setAttributeIfChanged } from './dom.js';
2
- import { layoutLabels } from './explorer-layout.js';
1
+ import { setAttributeIfChanged } from '../dom.js';
2
+ import { layoutLabels } from '../explorer-layout.js';
3
3
  /** Reuse text nodes and screen-space metrics throughout a camera animation. */
4
4
  export function createLabelRenderer(layer) {
5
5
  const entries = new Map();
@@ -1,5 +1,5 @@
1
- import type { createExplorerShell } from './explorer-shell.js';
2
- import type { MapViewport, NeighborhoodExplorerElement, NeighborhoodExplorerOptions } from './types.js';
1
+ import type { MapViewport, NeighborhoodExplorerElement, NeighborhoodExplorerOptions } from '../types.js';
2
+ import type { createExplorerShell } from './map-shell.js';
3
3
  type Controls = NonNullable<NeighborhoodExplorerOptions['controls']>;
4
4
  type Shell = Pick<ReturnType<typeof createExplorerShell>, 'root' | 'toolbar' | 'canvas' | 'hint' | 'status' | 'modeSelect' | 'sourceSelect' | 'search' | 'results' | 'neighborhoodSelect' | 'markerSelect'>;
5
5
  type Commands = Pick<NeighborhoodExplorerElement, 'getViewport' | 'zoomBy' | 'resetView' | 'setLabels' | 'stopAnimation' | 'setMode' | 'setSource' | 'selectNeighborhood' | 'selectMarker'> & {
@@ -10,13 +10,13 @@ type Commands = Pick<NeighborhoodExplorerElement, 'getViewport' | 'zoomBy' | 're
10
10
  getLabels(): boolean;
11
11
  moveView(view: MapViewport): void;
12
12
  setView(view: MapViewport): void;
13
- updateResults(): void;
13
+ updateNeighborhoodResults(): void;
14
14
  search(query: string): string | undefined;
15
15
  };
16
16
  /** Own toolbar and form events, touch navigation and control visibility.
17
17
  * Commands read current map state; all listeners share the map's disposal signal.
18
18
  */
19
- export declare function createExplorerControls({ root, toolbar, canvas, hint, status, modeSelect, sourceSelect, search, results, neighborhoodSelect, markerSelect, }: Shell, { svg, signal, strings, isDestroyed, getLabels, getViewport, moveView, zoomBy, resetView, setLabels, stopAnimation, setView, setMode, setSource, selectNeighborhood, selectMarker, updateResults, search: findNeighborhood, }: Commands): {
19
+ export declare function createMapControls({ root, toolbar, canvas, hint, status, modeSelect, sourceSelect, search, results, neighborhoodSelect, markerSelect, }: Shell, { svg, signal, strings, isDestroyed, getLabels, getViewport, moveView, zoomBy, resetView, setLabels, stopAnimation, setView, setMode, setSource, selectNeighborhood, selectMarker, updateNeighborhoodResults, search: findNeighborhood, }: Commands): {
20
20
  setTouchNavigation: (enabled: boolean) => void;
21
21
  cancelNavigation: () => void;
22
22
  update(controls: Controls): void;
@@ -1,9 +1,9 @@
1
- import { element } from './dom.js';
2
- import { attachNavigation } from './navigation.js';
1
+ import { element } from '../dom.js';
2
+ import { attachNavigation } from '../navigation.js';
3
3
  /** Own toolbar and form events, touch navigation and control visibility.
4
4
  * Commands read current map state; all listeners share the map's disposal signal.
5
5
  */
6
- export function createExplorerControls({ root, toolbar, canvas, hint, status, modeSelect, sourceSelect, search, results, neighborhoodSelect, markerSelect, }, { svg, signal, strings, isDestroyed, getLabels, getViewport, moveView, zoomBy, resetView, setLabels, stopAnimation, setView, setMode, setSource, selectNeighborhood, selectMarker, updateResults, search: findNeighborhood, }) {
6
+ export function createMapControls({ root, toolbar, canvas, hint, status, modeSelect, sourceSelect, search, results, neighborhoodSelect, markerSelect, }, { svg, signal, strings, isDestroyed, getLabels, getViewport, moveView, zoomBy, resetView, setLabels, stopAnimation, setView, setMode, setSource, selectNeighborhood, selectMarker, updateNeighborhoodResults, search: findNeighborhood, }) {
7
7
  function listen(node, event, handler) {
8
8
  node.addEventListener(event, (incoming) => handler(incoming), { signal });
9
9
  }
@@ -63,7 +63,7 @@ export function createExplorerControls({ root, toolbar, canvas, hint, status, mo
63
63
  if (next === 'neighborhoods' || next === 'districts' || next === 'basemap')
64
64
  setMode(next);
65
65
  });
66
- listen(search, 'input', updateResults);
66
+ listen(search, 'input', updateNeighborhoodResults);
67
67
  listen(search, 'keydown', (event) => {
68
68
  if (event.key === 'Enter') {
69
69
  const match = findNeighborhood(search.value);
@@ -1,13 +1,14 @@
1
- import type { NeighborhoodSource } from '../data/types.js';
2
- import type { MapConfiguration } from './controller-types.js';
3
- import type { InteractiveSFMapData } from './explorer-data.js';
4
- import type { createMapShell } from './explorer-shell.js';
1
+ import type { NeighborhoodSource } from '../../data/types.js';
2
+ import type { MapConfiguration } from '../controller-types.js';
3
+ import type { InteractiveSFMapData } from '../explorer-data.js';
4
+ import type { DistrictYear, ExplorerMode, NeighborhoodExplorerElement, NeighborhoodExplorerOptions } from '../types.js';
5
+ import type { PreparedPresentation } from './configuration-controller.js';
5
6
  import type { createExplorerSidebar } from './explorer-sidebar.js';
6
- import type { DistrictYear, ExplorerMode, NeighborhoodExplorerElement, NeighborhoodExplorerOptions } from './types.js';
7
- export type { ExplorerMode, NeighborhoodExplorerElement, NeighborhoodExplorerOptions, } from './types.js';
7
+ import type { createMapShell } from './map-shell.js';
8
+ export type { ExplorerMode, NeighborhoodExplorerElement, NeighborhoodExplorerOptions, } from '../types.js';
8
9
  /** Private bridge between the renderer and its public lifecycle controller. */
9
10
  type MapEngineElement = NeighborhoodExplorerElement & {
10
- applyPresentation(patch: MapConfiguration, onCommit?: () => void, isCurrent?: () => boolean): boolean;
11
+ preparePresentation(patch: MapConfiguration): PreparedPresentation | undefined;
11
12
  getMapState(): {
12
13
  mode: ExplorerMode;
13
14
  source: NeighborhoodSource;
@@ -16,7 +17,7 @@ type MapEngineElement = NeighborhoodExplorerElement & {
16
17
  };
17
18
  };
18
19
  /** Create an offline, browser-only neighborhood explorer. Call destroy() before disposal. */
19
- export declare function createNeighborhoodExplorerCore(options: NeighborhoodExplorerOptions | undefined, data: InteractiveSFMapData, ui: {
20
+ export declare function createMapEngine(options: NeighborhoodExplorerOptions | undefined, data: InteractiveSFMapData, ui: {
20
21
  createShell: typeof createMapShell;
21
22
  createSidebar?: typeof createExplorerSidebar;
22
23
  }): MapEngineElement;