@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.
- package/CHANGELOG.md +8 -0
- package/dist/src/cluster-renderer.d.ts +1 -1
- package/dist/src/district-layer.d.ts +1 -1
- package/dist/src/district-layer.js +1 -1
- package/dist/src/district-style.d.ts +1 -1
- package/dist/src/explorer-data.d.ts +1 -1
- package/dist/src/guide-map.js +3 -3
- package/dist/src/interactive/configuration-controller.d.ts +21 -0
- package/dist/src/interactive/configuration-controller.js +43 -0
- package/dist/src/{district-controller.d.ts → interactive/district-controller.d.ts} +12 -12
- package/dist/src/{district-controller.js → interactive/district-controller.js} +9 -9
- package/dist/src/{explorer-sidebar.d.ts → interactive/explorer-sidebar.d.ts} +6 -6
- package/dist/src/{explorer-sidebar.js → interactive/explorer-sidebar.js} +4 -4
- package/dist/src/{label-coordinator.d.ts → interactive/label-coordinator.d.ts} +7 -7
- package/dist/src/{label-coordinator.js → interactive/label-coordinator.js} +2 -2
- package/dist/src/{label-renderer.d.ts → interactive/label-renderer.d.ts} +2 -2
- package/dist/src/{label-renderer.js → interactive/label-renderer.js} +2 -2
- package/dist/src/{explorer-controls.d.ts → interactive/map-controls.d.ts} +4 -4
- package/dist/src/{explorer-controls.js → interactive/map-controls.js} +4 -4
- package/dist/src/{explorer-core.d.ts → interactive/map-engine.d.ts} +9 -8
- package/dist/src/{explorer-core.js → interactive/map-engine.js} +154 -140
- package/dist/src/{explorer-shell.d.ts → interactive/map-shell.d.ts} +2 -2
- package/dist/src/{explorer-shell.js → interactive/map-shell.js} +2 -2
- package/dist/src/{marker-controller.d.ts → interactive/marker-controller.d.ts} +8 -8
- package/dist/src/{marker-controller.js → interactive/marker-controller.js} +3 -3
- package/dist/src/{marker-layer.d.ts → interactive/marker-renderer.d.ts} +3 -3
- package/dist/src/{marker-layer.js → interactive/marker-renderer.js} +2 -2
- package/dist/src/map.js +15 -38
- package/dist/src/marker-catalog.d.ts +2 -2
- package/dist/src/{layers.d.ts → rendering/svg-layers.d.ts} +5 -5
- package/dist/src/{layers.js → rendering/svg-layers.js} +1 -1
- package/dist/src/{map-core.d.ts → rendering/svg-map-renderer.d.ts} +4 -4
- package/dist/src/{map-core.js → rendering/svg-map-renderer.js} +6 -6
- package/dist/src/static-labels.d.ts +1 -1
- package/dist/src/static-labels.js +1 -1
- package/dist/src/static.d.ts +2 -2
- package/dist/src/static.js +1 -1
- package/dist/src/transit.js +1 -1
- package/dist/src/types.d.ts +2 -2
- package/llms-full.txt +29 -21
- package/llms.txt +1 -1
- package/package.json +1 -1
- /package/dist/src/{svg.d.ts → rendering/svg-primitives.d.ts} +0 -0
- /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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 {
|
package/dist/src/guide-map.js
CHANGED
|
@@ -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
|
|
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 '
|
|
2
|
-
import { prepareDistrictStyles } from '
|
|
3
|
-
import type { InteractiveSFMapData } from '
|
|
4
|
-
import type { normalizeFeatures } from '
|
|
5
|
-
import type { LabelItem } from '
|
|
6
|
-
import type { CameraOptions, DistrictSelection, DistrictYear, NeighborhoodExplorerOptions } from '
|
|
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
|
-
|
|
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("
|
|
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(
|
|
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(
|
|
60
|
-
readonly styles: ReadonlyMap<number, import("
|
|
61
|
-
commitStyles(style: ((district: import(
|
|
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 '
|
|
2
|
-
import { renderDistrictAppearance } from '
|
|
3
|
-
import { createDistrictMorph } from '
|
|
4
|
-
import { prepareDistrictStyles } from '
|
|
5
|
-
import { createDistrictTransition } from '
|
|
6
|
-
import { svgElement } from '
|
|
7
|
-
import { getLayerPathsWithData } from '
|
|
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,
|
|
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
|
-
|
|
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 '
|
|
2
|
-
import type { InteractiveSFMapData } from '
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
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
|
-
|
|
17
|
-
|
|
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 '
|
|
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
|
|
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
|
|
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 {
|
|
78
|
+
return { updateSelectionDetail, updateNeighborhoodResults, destroy: releaseDownloads };
|
|
79
79
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { View } from '
|
|
2
|
-
import type { normalizeFeatures } from '
|
|
3
|
-
import { type LabelItem } from '
|
|
4
|
-
import type { createMarkerCatalog } from '
|
|
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-
|
|
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 '
|
|
2
|
-
import { labelCandidates, styleLabels, } from '
|
|
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 '
|
|
2
|
-
import type { RenderLabel } from '
|
|
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 '
|
|
2
|
-
import { layoutLabels } from '
|
|
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 {
|
|
2
|
-
import type {
|
|
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
|
-
|
|
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
|
|
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 '
|
|
2
|
-
import { attachNavigation } from '
|
|
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
|
|
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',
|
|
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 '
|
|
2
|
-
import type { MapConfiguration } from '
|
|
3
|
-
import type { InteractiveSFMapData } from '
|
|
4
|
-
import type {
|
|
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 {
|
|
7
|
-
export type { ExplorerMode, NeighborhoodExplorerElement, NeighborhoodExplorerOptions, } from '
|
|
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
|
-
|
|
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
|
|
20
|
+
export declare function createMapEngine(options: NeighborhoodExplorerOptions | undefined, data: InteractiveSFMapData, ui: {
|
|
20
21
|
createShell: typeof createMapShell;
|
|
21
22
|
createSidebar?: typeof createExplorerSidebar;
|
|
22
23
|
}): MapEngineElement;
|