@smartnet360/svelte-components 0.0.51 → 0.0.54
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/dist/apps/site-check/transforms.js +2 -2
- package/dist/core/Charts/ChartCard.svelte +6 -1
- package/dist/core/Charts/ChartComponent.svelte +8 -3
- package/dist/core/Charts/GlobalControls.svelte +116 -14
- package/dist/core/Charts/adapt.js +1 -1
- package/dist/core/Charts/charts.model.d.ts +3 -0
- package/dist/core/FeatureRegistry/index.js +1 -1
- package/dist/core/TreeView/TreeNode.svelte +40 -45
- package/dist/core/TreeView/TreeNode.svelte.d.ts +10 -0
- package/dist/core/TreeView/TreeView.svelte +14 -2
- package/dist/core/TreeView/TreeView.svelte.d.ts +10 -0
- package/dist/core/TreeView/tree-utils.d.ts +3 -0
- package/dist/core/TreeView/tree-utils.js +33 -9
- package/dist/core/TreeView/tree.store.js +49 -24
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/map/controls/MapControl.svelte +204 -0
- package/dist/map/controls/MapControl.svelte.d.ts +17 -0
- package/dist/map/controls/SiteFilterControl.svelte +126 -0
- package/dist/map/controls/SiteFilterControl.svelte.d.ts +16 -0
- package/dist/map/demo/DemoMap.svelte +98 -0
- package/dist/map/demo/DemoMap.svelte.d.ts +12 -0
- package/dist/map/demo/demo-data.d.ts +12 -0
- package/dist/map/demo/demo-data.js +220 -0
- package/dist/map/hooks/useCellData.d.ts +14 -0
- package/dist/map/hooks/useCellData.js +29 -0
- package/dist/map/hooks/useMapbox.d.ts +14 -0
- package/dist/map/hooks/useMapbox.js +29 -0
- package/dist/map/index.d.ts +27 -0
- package/dist/map/index.js +47 -0
- package/dist/map/layers/CellsLayer.svelte +242 -0
- package/dist/map/layers/CellsLayer.svelte.d.ts +21 -0
- package/dist/map/layers/CoverageLayer.svelte +37 -0
- package/dist/map/layers/CoverageLayer.svelte.d.ts +9 -0
- package/dist/map/layers/LayerBase.d.ts +42 -0
- package/dist/map/layers/LayerBase.js +58 -0
- package/dist/map/layers/SitesLayer.svelte +282 -0
- package/dist/map/layers/SitesLayer.svelte.d.ts +19 -0
- package/dist/map/providers/CellDataProvider.svelte +43 -0
- package/dist/map/providers/CellDataProvider.svelte.d.ts +12 -0
- package/dist/map/providers/MapboxProvider.svelte +38 -0
- package/dist/map/providers/MapboxProvider.svelte.d.ts +9 -0
- package/dist/map/providers/providerHelpers.d.ts +17 -0
- package/dist/map/providers/providerHelpers.js +26 -0
- package/dist/map/stores/cellDataStore.d.ts +21 -0
- package/dist/map/stores/cellDataStore.js +53 -0
- package/dist/map/stores/interactions.d.ts +20 -0
- package/dist/map/stores/interactions.js +33 -0
- package/dist/map/stores/mapStore.d.ts +8 -0
- package/dist/map/stores/mapStore.js +10 -0
- package/dist/map/types.d.ts +115 -0
- package/dist/map/types.js +10 -0
- package/dist/map/utils/geojson.d.ts +20 -0
- package/dist/map/utils/geojson.js +78 -0
- package/dist/map/utils/mapboxHelpers.d.ts +51 -0
- package/dist/map/utils/mapboxHelpers.js +98 -0
- package/dist/map/utils/math.d.ts +40 -0
- package/dist/map/utils/math.js +95 -0
- package/dist/map/utils/siteTreeUtils.d.ts +27 -0
- package/dist/map/utils/siteTreeUtils.js +164 -0
- package/package.json +1 -1
- package/dist/core/Map/Map.svelte +0 -312
- package/dist/core/Map/Map.svelte.d.ts +0 -230
- package/dist/core/Map/index.d.ts +0 -9
- package/dist/core/Map/index.js +0 -9
- package/dist/core/Map/mapSettings.d.ts +0 -147
- package/dist/core/Map/mapSettings.js +0 -226
- package/dist/core/Map/mapStore.d.ts +0 -73
- package/dist/core/Map/mapStore.js +0 -136
- package/dist/core/Map/types.d.ts +0 -72
- package/dist/core/Map/types.js +0 -32
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for building and managing site filter tree
|
|
3
|
+
*/
|
|
4
|
+
const STORAGE_PREFIX = 'cellular:siteFilter';
|
|
5
|
+
/**
|
|
6
|
+
* Builds a hierarchical tree from flat site array
|
|
7
|
+
* Structure: All Sites -> Provider -> Feature Group
|
|
8
|
+
*/
|
|
9
|
+
export function buildSiteTree(sites) {
|
|
10
|
+
// Group sites by provider, then by feature group
|
|
11
|
+
const providerGroups = new Map();
|
|
12
|
+
sites.forEach((site) => {
|
|
13
|
+
if (!providerGroups.has(site.provider)) {
|
|
14
|
+
providerGroups.set(site.provider, new Map());
|
|
15
|
+
}
|
|
16
|
+
const featureGroups = providerGroups.get(site.provider);
|
|
17
|
+
if (!featureGroups.has(site.featureGroup)) {
|
|
18
|
+
featureGroups.set(site.featureGroup, []);
|
|
19
|
+
}
|
|
20
|
+
featureGroups.get(site.featureGroup).push(site);
|
|
21
|
+
});
|
|
22
|
+
// Load saved state from localStorage
|
|
23
|
+
const savedState = loadTreeState();
|
|
24
|
+
// Build tree structure
|
|
25
|
+
const children = [];
|
|
26
|
+
// Sort providers alphabetically
|
|
27
|
+
const sortedProviders = Array.from(providerGroups.keys()).sort();
|
|
28
|
+
sortedProviders.forEach((provider) => {
|
|
29
|
+
const featureGroups = providerGroups.get(provider);
|
|
30
|
+
const providerChildren = [];
|
|
31
|
+
// Sort feature groups alphabetically
|
|
32
|
+
const sortedFeatureGroups = Array.from(featureGroups.keys()).sort();
|
|
33
|
+
sortedFeatureGroups.forEach((featureGroup) => {
|
|
34
|
+
const groupSites = featureGroups.get(featureGroup);
|
|
35
|
+
const nodeId = `${provider}:${featureGroup}`;
|
|
36
|
+
providerChildren.push({
|
|
37
|
+
id: nodeId,
|
|
38
|
+
label: `${featureGroup} (${groupSites.length})`,
|
|
39
|
+
defaultChecked: savedState[nodeId] ?? true, // Default checked
|
|
40
|
+
children: [],
|
|
41
|
+
metadata: {
|
|
42
|
+
type: 'featureGroup',
|
|
43
|
+
provider,
|
|
44
|
+
featureGroup,
|
|
45
|
+
siteIds: groupSites.map((s) => s.id)
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const providerId = provider;
|
|
50
|
+
children.push({
|
|
51
|
+
id: providerId,
|
|
52
|
+
label: `${provider} (${Array.from(featureGroups.values()).flat().length})`,
|
|
53
|
+
defaultChecked: savedState[providerId] ?? true, // Default checked
|
|
54
|
+
children: providerChildren,
|
|
55
|
+
metadata: {
|
|
56
|
+
type: 'provider',
|
|
57
|
+
provider
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
// Root node
|
|
62
|
+
return {
|
|
63
|
+
id: 'all-sites',
|
|
64
|
+
label: `All Sites (${sites.length})`,
|
|
65
|
+
defaultChecked: savedState['all-sites'] ?? true, // Default checked
|
|
66
|
+
children,
|
|
67
|
+
metadata: {
|
|
68
|
+
type: 'root'
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Filters sites based on checked tree paths
|
|
74
|
+
*/
|
|
75
|
+
export function getFilteredSites(checkedPaths, allSites) {
|
|
76
|
+
console.log('getFilteredSites called with paths:', checkedPaths);
|
|
77
|
+
const checkedGroups = new Set();
|
|
78
|
+
const checkedProviders = new Set();
|
|
79
|
+
checkedPaths.forEach((path) => {
|
|
80
|
+
// TreeView adds parent prefixes, so paths look like:
|
|
81
|
+
// "all-sites:Verizon:Verizon:Urban Macro"
|
|
82
|
+
// We need to extract the actual provider:featureGroup
|
|
83
|
+
// Split by separator
|
|
84
|
+
const parts = path.split(':');
|
|
85
|
+
// Remove "all-sites" prefix if present
|
|
86
|
+
const filteredParts = parts.filter(p => p !== 'all-sites');
|
|
87
|
+
if (filteredParts.length === 3) {
|
|
88
|
+
// Format: [provider, provider, featureGroup]
|
|
89
|
+
// The provider is duplicated, extract it as provider:featureGroup
|
|
90
|
+
const provider = filteredParts[1];
|
|
91
|
+
const featureGroup = filteredParts[2];
|
|
92
|
+
checkedGroups.add(`${provider}:${featureGroup}`);
|
|
93
|
+
}
|
|
94
|
+
else if (filteredParts.length === 1) {
|
|
95
|
+
// Just a provider
|
|
96
|
+
checkedProviders.add(filteredParts[0]);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
console.log('Checked groups:', Array.from(checkedGroups));
|
|
100
|
+
console.log('Checked providers:', Array.from(checkedProviders));
|
|
101
|
+
// If "all-sites" is checked and it's the only thing, return all
|
|
102
|
+
if (checkedPaths.includes('all-sites') && checkedGroups.size === 0 && checkedProviders.size === 0) {
|
|
103
|
+
console.log('All sites root checked, returning all');
|
|
104
|
+
return allSites;
|
|
105
|
+
}
|
|
106
|
+
// If nothing is checked, return empty
|
|
107
|
+
if (checkedGroups.size === 0 && checkedProviders.size === 0) {
|
|
108
|
+
console.log('Nothing checked, returning empty');
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
// Filter sites based on checked groups or providers
|
|
112
|
+
const filtered = allSites.filter((site) => {
|
|
113
|
+
const key = `${site.provider}:${site.featureGroup}`;
|
|
114
|
+
// Include if the specific group is checked OR if the provider is checked
|
|
115
|
+
const included = checkedGroups.has(key) || checkedProviders.has(site.provider);
|
|
116
|
+
return included;
|
|
117
|
+
});
|
|
118
|
+
console.log('Filtered:', filtered.length, 'of', allSites.length, 'sites');
|
|
119
|
+
return filtered;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Saves tree checked paths to localStorage
|
|
123
|
+
*/
|
|
124
|
+
export function saveTreeState(checkedPaths) {
|
|
125
|
+
try {
|
|
126
|
+
localStorage.setItem(STORAGE_PREFIX, JSON.stringify(checkedPaths));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.warn('Failed to save tree state to localStorage:', error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Loads tree state from localStorage
|
|
134
|
+
* Returns map of node IDs to checked state
|
|
135
|
+
*/
|
|
136
|
+
export function loadTreeState() {
|
|
137
|
+
try {
|
|
138
|
+
const saved = localStorage.getItem(STORAGE_PREFIX);
|
|
139
|
+
if (saved) {
|
|
140
|
+
const paths = JSON.parse(saved);
|
|
141
|
+
// Convert paths to map for easier lookup during tree building
|
|
142
|
+
const stateMap = {};
|
|
143
|
+
paths.forEach((path) => {
|
|
144
|
+
stateMap[path] = true;
|
|
145
|
+
});
|
|
146
|
+
return stateMap;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.warn('Failed to load tree state from localStorage:', error);
|
|
151
|
+
}
|
|
152
|
+
return {};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Clears saved tree state
|
|
156
|
+
*/
|
|
157
|
+
export function clearTreeState() {
|
|
158
|
+
try {
|
|
159
|
+
localStorage.removeItem(STORAGE_PREFIX);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.warn('Failed to clear tree state from localStorage:', error);
|
|
163
|
+
}
|
|
164
|
+
}
|
package/package.json
CHANGED
package/dist/core/Map/Map.svelte
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
import mapboxgl from 'mapbox-gl';
|
|
4
|
-
import { MapboxOverlay } from '@deck.gl/mapbox';
|
|
5
|
-
import type { Layer } from '@deck.gl/core';
|
|
6
|
-
import { createMapStore, type MapStore } from './mapStore';
|
|
7
|
-
import { createSettingsStore } from '../Settings/store';
|
|
8
|
-
import { mapSettingsSchema } from './mapSettings';
|
|
9
|
-
import { MAP_STYLES, DEFAULT_MAP_OPTIONS, type MapOptions } from './types';
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
accessToken: string;
|
|
13
|
-
initialOptions?: Partial<MapOptions>;
|
|
14
|
-
namespace?: string;
|
|
15
|
-
layers?: Layer[];
|
|
16
|
-
mapStore?: MapStore;
|
|
17
|
-
onMapLoaded?: (map: mapboxgl.Map) => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let {
|
|
21
|
-
accessToken,
|
|
22
|
-
initialOptions = {},
|
|
23
|
-
namespace = 'map',
|
|
24
|
-
layers = [],
|
|
25
|
-
mapStore = $bindable(),
|
|
26
|
-
onMapLoaded
|
|
27
|
-
}: Props = $props();
|
|
28
|
-
|
|
29
|
-
// Container element
|
|
30
|
-
let container = $state<HTMLDivElement>();
|
|
31
|
-
let map = $state<mapboxgl.Map>();
|
|
32
|
-
let overlay = $state<MapboxOverlay>();
|
|
33
|
-
let styleLoaded = $state(false);
|
|
34
|
-
|
|
35
|
-
// Create stores if not provided
|
|
36
|
-
if (!mapStore) {
|
|
37
|
-
mapStore = createMapStore();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Create settings store
|
|
41
|
-
const settings = createSettingsStore(mapSettingsSchema, namespace);
|
|
42
|
-
|
|
43
|
-
// Reactive: Update layers when prop changes
|
|
44
|
-
$effect(() => {
|
|
45
|
-
if (mapStore && layers.length > 0) {
|
|
46
|
-
mapStore.setLayers(layers);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Reactive: Update map style when settings change
|
|
51
|
-
$effect(() => {
|
|
52
|
-
if (!map || !styleLoaded || !$settings.appearance.style) return;
|
|
53
|
-
|
|
54
|
-
const styleUrl = MAP_STYLES[$settings.appearance.style as keyof typeof MAP_STYLES];
|
|
55
|
-
if (styleUrl && map.getStyle()?.name !== styleUrl) {
|
|
56
|
-
styleLoaded = false; // Mark as not loaded during transition
|
|
57
|
-
map.setStyle(styleUrl);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Reactive: Update interaction handlers
|
|
62
|
-
$effect(() => {
|
|
63
|
-
const currentMap = map;
|
|
64
|
-
if (!currentMap) return;
|
|
65
|
-
|
|
66
|
-
const handlers = [
|
|
67
|
-
{ name: 'dragRotate', value: $settings.interaction.dragRotate },
|
|
68
|
-
{ name: 'touchZoomRotate', value: $settings.interaction.touchZoomRotate },
|
|
69
|
-
{ name: 'scrollZoom', value: $settings.interaction.scrollZoom },
|
|
70
|
-
{ name: 'doubleClickZoom', value: $settings.interaction.doubleClickZoom },
|
|
71
|
-
{ name: 'dragPan', value: $settings.interaction.dragPan }
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
handlers.forEach(({ name, value }) => {
|
|
75
|
-
const handler = currentMap[name as keyof mapboxgl.Map] as any;
|
|
76
|
-
if (handler) {
|
|
77
|
-
value ? handler.enable() : handler.disable();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Reactive: Update pitch and bearing
|
|
83
|
-
$effect(() => {
|
|
84
|
-
if (!map || !styleLoaded) return;
|
|
85
|
-
|
|
86
|
-
map.setPitch($settings.view.pitch as number);
|
|
87
|
-
map.setBearing($settings.view.bearing as number);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Reactive: Toggle 3D buildings
|
|
91
|
-
$effect(() => {
|
|
92
|
-
if (!map || !styleLoaded) return;
|
|
93
|
-
|
|
94
|
-
if ($settings.appearance.show3dBuildings) {
|
|
95
|
-
add3dBuildings();
|
|
96
|
-
} else if (map.getLayer('3d-buildings')) {
|
|
97
|
-
map.removeLayer('3d-buildings');
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Reactive: Toggle terrain
|
|
102
|
-
$effect(() => {
|
|
103
|
-
if (!map || !styleLoaded) return;
|
|
104
|
-
|
|
105
|
-
if ($settings.appearance.showTerrain) {
|
|
106
|
-
addTerrain();
|
|
107
|
-
} else if (map.getTerrain()) {
|
|
108
|
-
map.setTerrain(null);
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// One-time initialization using onMount (recommended for async/DOM-dependent setup)
|
|
113
|
-
onMount(() => {
|
|
114
|
-
if (!container) return;
|
|
115
|
-
|
|
116
|
-
// Set Mapbox access token
|
|
117
|
-
mapboxgl.accessToken = accessToken;
|
|
118
|
-
|
|
119
|
-
// Merge default options with initial options and settings
|
|
120
|
-
const options: MapOptions = {
|
|
121
|
-
...DEFAULT_MAP_OPTIONS,
|
|
122
|
-
...initialOptions,
|
|
123
|
-
accessToken
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Initialize Mapbox map
|
|
127
|
-
map = new mapboxgl.Map({
|
|
128
|
-
container,
|
|
129
|
-
style: MAP_STYLES[$settings.appearance.style as keyof typeof MAP_STYLES] || options.style,
|
|
130
|
-
center: options.center,
|
|
131
|
-
zoom: options.zoom,
|
|
132
|
-
pitch: $settings.view.pitch as number,
|
|
133
|
-
bearing: $settings.view.bearing as number,
|
|
134
|
-
minZoom: $settings.view.minZoom as number,
|
|
135
|
-
maxZoom: $settings.view.maxZoom as number,
|
|
136
|
-
antialias: $settings.performance.antialias as boolean,
|
|
137
|
-
maxTileCacheSize: $settings.performance.maxTileCacheSize as number,
|
|
138
|
-
fadeDuration: $settings.performance.fadeDuration as number
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// Add controls based on settings
|
|
142
|
-
if ($settings.controls.showNavigationControls) {
|
|
143
|
-
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if ($settings.controls.showScaleControl) {
|
|
147
|
-
map.addControl(new mapboxgl.ScaleControl(), 'bottom-left');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if ($settings.controls.showFullscreenControl) {
|
|
151
|
-
map.addControl(new mapboxgl.FullscreenControl(), 'top-right');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if ($settings.controls.showGeolocateControl) {
|
|
155
|
-
map.addControl(
|
|
156
|
-
new mapboxgl.GeolocateControl({
|
|
157
|
-
positionOptions: { enableHighAccuracy: true },
|
|
158
|
-
trackUserLocation: true,
|
|
159
|
-
showUserHeading: true
|
|
160
|
-
}),
|
|
161
|
-
'top-right'
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Initialize Deck.GL overlay
|
|
166
|
-
overlay = new MapboxOverlay({
|
|
167
|
-
interleaved: true,
|
|
168
|
-
layers: layers
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
map.addControl(overlay as any);
|
|
172
|
-
|
|
173
|
-
// Store map and overlay instances
|
|
174
|
-
if (mapStore) {
|
|
175
|
-
mapStore.setMap(map);
|
|
176
|
-
mapStore.setOverlay(overlay);
|
|
177
|
-
mapStore.setLayers(layers);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Map load event
|
|
181
|
-
map.on('load', () => {
|
|
182
|
-
if (!map) return;
|
|
183
|
-
|
|
184
|
-
styleLoaded = true;
|
|
185
|
-
|
|
186
|
-
if (mapStore) {
|
|
187
|
-
mapStore.setLoaded(true);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Add 3D buildings if enabled
|
|
191
|
-
if ($settings.appearance.show3dBuildings) {
|
|
192
|
-
add3dBuildings();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Add terrain if enabled
|
|
196
|
-
if ($settings.appearance.showTerrain) {
|
|
197
|
-
addTerrain();
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Call user callback
|
|
201
|
-
if (onMapLoaded) {
|
|
202
|
-
onMapLoaded(map);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// Track style loading for dynamic style changes
|
|
207
|
-
map.on('style.load', () => {
|
|
208
|
-
styleLoaded = true;
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Track view state changes
|
|
212
|
-
map.on('move', () => {
|
|
213
|
-
if (!map || !mapStore) return;
|
|
214
|
-
|
|
215
|
-
mapStore.updateViewState({
|
|
216
|
-
center: map.getCenter().toArray() as [number, number],
|
|
217
|
-
zoom: map.getZoom(),
|
|
218
|
-
pitch: map.getPitch(),
|
|
219
|
-
bearing: map.getBearing()
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Cleanup on destroy
|
|
224
|
-
return () => {
|
|
225
|
-
if (map) {
|
|
226
|
-
map.remove();
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
function add3dBuildings() {
|
|
232
|
-
if (!map) return;
|
|
233
|
-
if (!map.getLayer('3d-buildings')) {
|
|
234
|
-
const mapLayers = map.getStyle().layers;
|
|
235
|
-
const labelLayerId = mapLayers?.find(
|
|
236
|
-
(layer) => layer.type === 'symbol' && layer.layout?.['text-field']
|
|
237
|
-
)?.id;
|
|
238
|
-
|
|
239
|
-
map.addLayer(
|
|
240
|
-
{
|
|
241
|
-
id: '3d-buildings',
|
|
242
|
-
source: 'composite',
|
|
243
|
-
'source-layer': 'building',
|
|
244
|
-
filter: ['==', 'extrude', 'true'],
|
|
245
|
-
type: 'fill-extrusion',
|
|
246
|
-
minzoom: 15,
|
|
247
|
-
paint: {
|
|
248
|
-
'fill-extrusion-color': '#aaa',
|
|
249
|
-
'fill-extrusion-height': [
|
|
250
|
-
'interpolate',
|
|
251
|
-
['linear'],
|
|
252
|
-
['zoom'],
|
|
253
|
-
15,
|
|
254
|
-
0,
|
|
255
|
-
15.05,
|
|
256
|
-
['get', 'height']
|
|
257
|
-
],
|
|
258
|
-
'fill-extrusion-base': [
|
|
259
|
-
'interpolate',
|
|
260
|
-
['linear'],
|
|
261
|
-
['zoom'],
|
|
262
|
-
15,
|
|
263
|
-
0,
|
|
264
|
-
15.05,
|
|
265
|
-
['get', 'min_height']
|
|
266
|
-
],
|
|
267
|
-
'fill-extrusion-opacity': 0.6
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
labelLayerId
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function addTerrain() {
|
|
276
|
-
if (!map) return;
|
|
277
|
-
if (!map.getSource('mapbox-dem')) {
|
|
278
|
-
map.addSource('mapbox-dem', {
|
|
279
|
-
type: 'raster-dem',
|
|
280
|
-
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
|
|
281
|
-
tileSize: 512,
|
|
282
|
-
maxzoom: 14
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Export settings store for external access
|
|
290
|
-
export { settings };
|
|
291
|
-
</script>
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
<div class="map-container">
|
|
296
|
-
<div bind:this={container} class="map"></div>
|
|
297
|
-
</div>
|
|
298
|
-
|
|
299
|
-
<style>
|
|
300
|
-
.map-container {
|
|
301
|
-
width: 100%;
|
|
302
|
-
height: 100%;
|
|
303
|
-
position: relative;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.map {
|
|
307
|
-
width: 100%;
|
|
308
|
-
height: 100%;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/* Import Mapbox CSS - This should be in your app's global CSS */
|
|
312
|
-
</style>
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import type { Layer } from '@deck.gl/core';
|
|
2
|
-
import { type MapStore } from './mapStore';
|
|
3
|
-
import { type MapOptions } from './types';
|
|
4
|
-
interface Props {
|
|
5
|
-
accessToken: string;
|
|
6
|
-
initialOptions?: Partial<MapOptions>;
|
|
7
|
-
namespace?: string;
|
|
8
|
-
layers?: Layer[];
|
|
9
|
-
mapStore?: MapStore;
|
|
10
|
-
onMapLoaded?: (map: mapboxgl.Map) => void;
|
|
11
|
-
}
|
|
12
|
-
declare const Map: import("svelte").Component<Props, {
|
|
13
|
-
settings: {
|
|
14
|
-
subscribe: (this: void, run: import("svelte/store").Subscriber<import("..").InferSettingsType<{
|
|
15
|
-
segments: ({
|
|
16
|
-
id: string;
|
|
17
|
-
title: string;
|
|
18
|
-
icon: string;
|
|
19
|
-
description: string;
|
|
20
|
-
fields: ({
|
|
21
|
-
id: string;
|
|
22
|
-
type: "select";
|
|
23
|
-
label: string;
|
|
24
|
-
description: string;
|
|
25
|
-
defaultValue: string;
|
|
26
|
-
options: {
|
|
27
|
-
value: string;
|
|
28
|
-
label: string;
|
|
29
|
-
description: string;
|
|
30
|
-
}[];
|
|
31
|
-
} | {
|
|
32
|
-
id: string;
|
|
33
|
-
type: "boolean";
|
|
34
|
-
label: string;
|
|
35
|
-
description: string;
|
|
36
|
-
defaultValue: true;
|
|
37
|
-
options?: undefined;
|
|
38
|
-
} | {
|
|
39
|
-
id: string;
|
|
40
|
-
type: "boolean";
|
|
41
|
-
label: string;
|
|
42
|
-
description: string;
|
|
43
|
-
defaultValue: false;
|
|
44
|
-
options?: undefined;
|
|
45
|
-
})[];
|
|
46
|
-
} | {
|
|
47
|
-
id: string;
|
|
48
|
-
title: string;
|
|
49
|
-
icon: string;
|
|
50
|
-
description: string;
|
|
51
|
-
fields: ({
|
|
52
|
-
id: string;
|
|
53
|
-
type: "range";
|
|
54
|
-
label: string;
|
|
55
|
-
description: string;
|
|
56
|
-
defaultValue: number;
|
|
57
|
-
min: number;
|
|
58
|
-
max: number;
|
|
59
|
-
step: number;
|
|
60
|
-
showValue: true;
|
|
61
|
-
unit: string;
|
|
62
|
-
} | {
|
|
63
|
-
id: string;
|
|
64
|
-
type: "number";
|
|
65
|
-
label: string;
|
|
66
|
-
description: string;
|
|
67
|
-
defaultValue: number;
|
|
68
|
-
min: number;
|
|
69
|
-
max: number;
|
|
70
|
-
step: number;
|
|
71
|
-
showValue?: undefined;
|
|
72
|
-
unit?: undefined;
|
|
73
|
-
})[];
|
|
74
|
-
} | {
|
|
75
|
-
id: string;
|
|
76
|
-
title: string;
|
|
77
|
-
icon: string;
|
|
78
|
-
description: string;
|
|
79
|
-
fields: ({
|
|
80
|
-
id: string;
|
|
81
|
-
type: "select";
|
|
82
|
-
label: string;
|
|
83
|
-
description: string;
|
|
84
|
-
defaultValue: number;
|
|
85
|
-
options: {
|
|
86
|
-
value: number;
|
|
87
|
-
label: string;
|
|
88
|
-
}[];
|
|
89
|
-
min?: undefined;
|
|
90
|
-
max?: undefined;
|
|
91
|
-
step?: undefined;
|
|
92
|
-
unit?: undefined;
|
|
93
|
-
} | {
|
|
94
|
-
id: string;
|
|
95
|
-
type: "boolean";
|
|
96
|
-
label: string;
|
|
97
|
-
description: string;
|
|
98
|
-
defaultValue: true;
|
|
99
|
-
options?: undefined;
|
|
100
|
-
min?: undefined;
|
|
101
|
-
max?: undefined;
|
|
102
|
-
step?: undefined;
|
|
103
|
-
unit?: undefined;
|
|
104
|
-
} | {
|
|
105
|
-
id: string;
|
|
106
|
-
type: "number";
|
|
107
|
-
label: string;
|
|
108
|
-
description: string;
|
|
109
|
-
defaultValue: number;
|
|
110
|
-
min: number;
|
|
111
|
-
max: number;
|
|
112
|
-
step: number;
|
|
113
|
-
unit: string;
|
|
114
|
-
options?: undefined;
|
|
115
|
-
})[];
|
|
116
|
-
})[];
|
|
117
|
-
}>>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
118
|
-
update: (segmentId: string, fieldId: string, value: any) => void;
|
|
119
|
-
updateSegment: (segmentId: string, values: Record<string, any>) => void;
|
|
120
|
-
reset: (segmentId: string, fieldId: string) => void;
|
|
121
|
-
resetSegment: (segmentId: string) => void;
|
|
122
|
-
resetAll: () => void;
|
|
123
|
-
getValues: () => import("..").InferSettingsType<{
|
|
124
|
-
segments: ({
|
|
125
|
-
id: string;
|
|
126
|
-
title: string;
|
|
127
|
-
icon: string;
|
|
128
|
-
description: string;
|
|
129
|
-
fields: ({
|
|
130
|
-
id: string;
|
|
131
|
-
type: "select";
|
|
132
|
-
label: string;
|
|
133
|
-
description: string;
|
|
134
|
-
defaultValue: string;
|
|
135
|
-
options: {
|
|
136
|
-
value: string;
|
|
137
|
-
label: string;
|
|
138
|
-
description: string;
|
|
139
|
-
}[];
|
|
140
|
-
} | {
|
|
141
|
-
id: string;
|
|
142
|
-
type: "boolean";
|
|
143
|
-
label: string;
|
|
144
|
-
description: string;
|
|
145
|
-
defaultValue: true;
|
|
146
|
-
options?: undefined;
|
|
147
|
-
} | {
|
|
148
|
-
id: string;
|
|
149
|
-
type: "boolean";
|
|
150
|
-
label: string;
|
|
151
|
-
description: string;
|
|
152
|
-
defaultValue: false;
|
|
153
|
-
options?: undefined;
|
|
154
|
-
})[];
|
|
155
|
-
} | {
|
|
156
|
-
id: string;
|
|
157
|
-
title: string;
|
|
158
|
-
icon: string;
|
|
159
|
-
description: string;
|
|
160
|
-
fields: ({
|
|
161
|
-
id: string;
|
|
162
|
-
type: "range";
|
|
163
|
-
label: string;
|
|
164
|
-
description: string;
|
|
165
|
-
defaultValue: number;
|
|
166
|
-
min: number;
|
|
167
|
-
max: number;
|
|
168
|
-
step: number;
|
|
169
|
-
showValue: true;
|
|
170
|
-
unit: string;
|
|
171
|
-
} | {
|
|
172
|
-
id: string;
|
|
173
|
-
type: "number";
|
|
174
|
-
label: string;
|
|
175
|
-
description: string;
|
|
176
|
-
defaultValue: number;
|
|
177
|
-
min: number;
|
|
178
|
-
max: number;
|
|
179
|
-
step: number;
|
|
180
|
-
showValue?: undefined;
|
|
181
|
-
unit?: undefined;
|
|
182
|
-
})[];
|
|
183
|
-
} | {
|
|
184
|
-
id: string;
|
|
185
|
-
title: string;
|
|
186
|
-
icon: string;
|
|
187
|
-
description: string;
|
|
188
|
-
fields: ({
|
|
189
|
-
id: string;
|
|
190
|
-
type: "select";
|
|
191
|
-
label: string;
|
|
192
|
-
description: string;
|
|
193
|
-
defaultValue: number;
|
|
194
|
-
options: {
|
|
195
|
-
value: number;
|
|
196
|
-
label: string;
|
|
197
|
-
}[];
|
|
198
|
-
min?: undefined;
|
|
199
|
-
max?: undefined;
|
|
200
|
-
step?: undefined;
|
|
201
|
-
unit?: undefined;
|
|
202
|
-
} | {
|
|
203
|
-
id: string;
|
|
204
|
-
type: "boolean";
|
|
205
|
-
label: string;
|
|
206
|
-
description: string;
|
|
207
|
-
defaultValue: true;
|
|
208
|
-
options?: undefined;
|
|
209
|
-
min?: undefined;
|
|
210
|
-
max?: undefined;
|
|
211
|
-
step?: undefined;
|
|
212
|
-
unit?: undefined;
|
|
213
|
-
} | {
|
|
214
|
-
id: string;
|
|
215
|
-
type: "number";
|
|
216
|
-
label: string;
|
|
217
|
-
description: string;
|
|
218
|
-
defaultValue: number;
|
|
219
|
-
min: number;
|
|
220
|
-
max: number;
|
|
221
|
-
step: number;
|
|
222
|
-
unit: string;
|
|
223
|
-
options?: undefined;
|
|
224
|
-
})[];
|
|
225
|
-
})[];
|
|
226
|
-
}>;
|
|
227
|
-
};
|
|
228
|
-
}, "mapStore">;
|
|
229
|
-
type Map = ReturnType<typeof Map>;
|
|
230
|
-
export default Map;
|