@smartnet360/svelte-components 0.0.85 → 0.0.86

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 (115) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaControls.svelte +1 -106
  2. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +0 -36
  3. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +0 -2
  4. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +0 -22
  5. package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +0 -2
  6. package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +0 -2
  7. package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +0 -2
  8. package/dist/apps/site-check/data-loader.js +0 -8
  9. package/dist/core/Charts/GlobalControls.svelte +0 -4
  10. package/dist/core/Desktop/Grid/ResizeHandle.svelte +0 -7
  11. package/dist/core/Desktop/Grid/resizeStore.js +0 -1
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +2 -0
  14. package/dist/map-v2/demo/DemoMap.svelte +0 -2
  15. package/dist/map-v2/demo/demo-cells.js +0 -1
  16. package/dist/map-v2/features/cells/layers/CellsLayer.svelte +7 -26
  17. package/dist/map-v2/features/cells/utils/cellTree.js +0 -29
  18. package/dist/map-v2/features/repeaters/layers/RepeaterLabelsLayer.svelte +3 -27
  19. package/dist/map-v2/features/repeaters/layers/RepeatersLayer.svelte +8 -25
  20. package/dist/map-v2/features/repeaters/utils/repeaterTree.js +0 -6
  21. package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +0 -8
  22. package/dist/map-v2/features/sites/utils/siteTreeUtils.js +0 -6
  23. package/dist/map-v3/core/components/Map.svelte +89 -0
  24. package/dist/map-v3/core/components/Map.svelte.d.ts +13 -0
  25. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte +103 -0
  26. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte.d.ts +15 -0
  27. package/dist/map-v3/core/controls/MapStyleControl.svelte +271 -0
  28. package/dist/map-v3/core/controls/MapStyleControl.svelte.d.ts +28 -0
  29. package/dist/map-v3/core/index.d.ts +3 -0
  30. package/dist/map-v3/core/index.js +3 -0
  31. package/dist/map-v3/core/stores/map.store.svelte.d.ts +8 -0
  32. package/dist/map-v3/core/stores/map.store.svelte.js +29 -0
  33. package/dist/map-v3/core/stores/viewport.store.svelte.d.ts +38 -0
  34. package/dist/map-v3/core/stores/viewport.store.svelte.js +107 -0
  35. package/dist/map-v3/demo/DemoMap.svelte +104 -0
  36. package/dist/map-v3/demo/DemoMap.svelte.d.ts +6 -0
  37. package/dist/map-v3/demo/demo-cells.d.ts +13 -0
  38. package/dist/map-v3/demo/demo-cells.js +130 -0
  39. package/dist/map-v3/demo/demo-data.d.ts +8 -0
  40. package/dist/map-v3/demo/demo-data.js +104 -0
  41. package/dist/map-v3/demo/demo-repeaters.d.ts +13 -0
  42. package/dist/map-v3/demo/demo-repeaters.js +73 -0
  43. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +208 -0
  44. package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +12 -0
  45. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte +229 -0
  46. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte.d.ts +7 -0
  47. package/dist/map-v3/features/cells/constants.d.ts +18 -0
  48. package/dist/map-v3/features/cells/constants.js +37 -0
  49. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +230 -0
  50. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte.d.ts +11 -0
  51. package/dist/map-v3/features/cells/layers/CellsLayer.svelte +194 -0
  52. package/dist/map-v3/features/cells/layers/CellsLayer.svelte.d.ts +11 -0
  53. package/dist/map-v3/features/cells/layers/index.d.ts +2 -0
  54. package/dist/map-v3/features/cells/layers/index.js +2 -0
  55. package/dist/map-v3/features/cells/logic/geometry.d.ts +12 -0
  56. package/dist/map-v3/features/cells/logic/geometry.js +35 -0
  57. package/dist/map-v3/features/cells/logic/grouping.d.ts +18 -0
  58. package/dist/map-v3/features/cells/logic/grouping.js +30 -0
  59. package/dist/map-v3/features/cells/logic/tree-adapter.d.ts +11 -0
  60. package/dist/map-v3/features/cells/logic/tree-adapter.js +53 -0
  61. package/dist/map-v3/features/cells/stores/cell.data.svelte.d.ts +9 -0
  62. package/dist/map-v3/features/cells/stores/cell.data.svelte.js +16 -0
  63. package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +25 -0
  64. package/dist/map-v3/features/cells/stores/cell.display.svelte.js +67 -0
  65. package/dist/map-v3/features/cells/stores/cell.registry.svelte.d.ts +23 -0
  66. package/dist/map-v3/features/cells/stores/cell.registry.svelte.js +68 -0
  67. package/dist/map-v3/features/cells/types.d.ts +62 -0
  68. package/dist/map-v3/features/cells/types.js +6 -0
  69. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +148 -0
  70. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte.d.ts +12 -0
  71. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte +209 -0
  72. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte.d.ts +7 -0
  73. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +177 -0
  74. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte.d.ts +11 -0
  75. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte +163 -0
  76. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte.d.ts +11 -0
  77. package/dist/map-v3/features/repeaters/logic/geometry.d.ts +3 -0
  78. package/dist/map-v3/features/repeaters/logic/geometry.js +23 -0
  79. package/dist/map-v3/features/repeaters/logic/grouping.d.ts +8 -0
  80. package/dist/map-v3/features/repeaters/logic/grouping.js +20 -0
  81. package/dist/map-v3/features/repeaters/logic/tree-adapter.d.ts +8 -0
  82. package/dist/map-v3/features/repeaters/logic/tree-adapter.js +43 -0
  83. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.d.ts +8 -0
  84. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.js +13 -0
  85. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.d.ts +21 -0
  86. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.js +64 -0
  87. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.d.ts +23 -0
  88. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.js +68 -0
  89. package/dist/map-v3/features/repeaters/types.d.ts +18 -0
  90. package/dist/map-v3/features/repeaters/types.js +1 -0
  91. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +119 -0
  92. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte.d.ts +12 -0
  93. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte +241 -0
  94. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte.d.ts +7 -0
  95. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +152 -0
  96. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte.d.ts +11 -0
  97. package/dist/map-v3/features/sites/layers/SitesLayer.svelte +132 -0
  98. package/dist/map-v3/features/sites/layers/SitesLayer.svelte.d.ts +11 -0
  99. package/dist/map-v3/features/sites/logic/tree-adapter.d.ts +9 -0
  100. package/dist/map-v3/features/sites/logic/tree-adapter.js +75 -0
  101. package/dist/map-v3/features/sites/stores/site.data.svelte.d.ts +8 -0
  102. package/dist/map-v3/features/sites/stores/site.data.svelte.js +40 -0
  103. package/dist/map-v3/features/sites/stores/site.display.svelte.d.ts +20 -0
  104. package/dist/map-v3/features/sites/stores/site.display.svelte.js +63 -0
  105. package/dist/map-v3/features/sites/stores/site.registry.svelte.d.ts +13 -0
  106. package/dist/map-v3/features/sites/stores/site.registry.svelte.js +83 -0
  107. package/dist/map-v3/features/sites/types.d.ts +12 -0
  108. package/dist/map-v3/features/sites/types.js +1 -0
  109. package/dist/map-v3/index.d.ts +26 -0
  110. package/dist/map-v3/index.js +31 -0
  111. package/dist/map-v3/shared/controls/MapControl.svelte +242 -0
  112. package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +27 -0
  113. package/dist/map-v3/shared/index.d.ts +1 -0
  114. package/dist/map-v3/shared/index.js +1 -0
  115. package/package.json +1 -1
@@ -16,6 +16,7 @@
16
16
  import type { RepeaterStoreContext } from '../stores/repeaterStoreContext.svelte';
17
17
  import type { Repeater } from '../types';
18
18
  import * as turf from '@turf/turf';
19
+ import { log } from '../../../../core/logger';
19
20
 
20
21
  interface Props {
21
22
  /** Repeater store context */
@@ -66,18 +67,7 @@
66
67
  function buildLabelFeatures(): GeoJSON.FeatureCollection {
67
68
  const features: GeoJSON.Feature[] = [];
68
69
 
69
- console.log('RepeaterLabelsLayer: Building label features', {
70
- showLabels: store.showLabels,
71
- filteredRepeatersCount: store.filteredRepeaters.length,
72
- hasMap: !!map
73
- });
74
-
75
70
  if (!store.showLabels || store.filteredRepeaters.length === 0 || !map) {
76
- console.log('RepeaterLabelsLayer: Skipping labels -', {
77
- showLabels: store.showLabels,
78
- hasRepeaters: store.filteredRepeaters.length > 0,
79
- hasMap: !!map
80
- });
81
71
  return { type: 'FeatureCollection', features: [] };
82
72
  }
83
73
 
@@ -134,11 +124,7 @@
134
124
  });
135
125
  });
136
126
 
137
- console.log('RepeaterLabelsLayer: Built features', {
138
- totalRepeaters: store.filteredRepeaters.length,
139
- visibleInViewport: visibleRepeaters.length,
140
- featuresGenerated: features.length
141
- });
127
+ log('RepeaterLabelsLayer features:', features.length, 'of', visibleRepeaters.length, 'visible repeaters');
142
128
 
143
129
  return { type: 'FeatureCollection', features };
144
130
  }
@@ -151,15 +137,7 @@
151
137
 
152
138
  const geojson = buildLabelFeatures();
153
139
 
154
- console.log('RepeaterLabelsLayer: Updating labels', {
155
- sourceExists: !!map.getSource(sourceId),
156
- layerExists: !!map.getLayer(layerId),
157
- featureCount: geojson.features.length,
158
- currentZoom: map.getZoom(),
159
- minLabelZoom: store.minLabelZoom,
160
- labelSize: store.labelSize,
161
- labelColor: store.labelColor
162
- });
140
+ log('RepeaterLabelsLayer: Updating', geojson.features.length, 'labels');
163
141
 
164
142
  const source = map.getSource(sourceId) as mapboxgl.GeoJSONSource;
165
143
  source.setData(geojson);
@@ -171,8 +149,6 @@
171
149
  map.setPaintProperty(layerId, 'text-halo-color', store.labelHaloColor);
172
150
  map.setPaintProperty(layerId, 'text-halo-width', store.labelHaloWidth);
173
151
  map.setLayerZoomRange(layerId, store.minLabelZoom, 24);
174
-
175
- console.log('RepeaterLabelsLayer: Updated layer properties');
176
152
  }
177
153
  }
178
154
 
@@ -18,6 +18,7 @@
18
18
  import { repeatersToGeoJSON } from '../utils/repeaterGeoJSON';
19
19
  import { REPEATER_FILL_Z_INDEX, REPEATER_LINE_Z_INDEX } from '../constants/zIndex';
20
20
  import { Z_INDEX_BY_BAND } from '../constants/techBandZOrder';
21
+ import { log } from '../../../../core/logger';
21
22
 
22
23
  interface Props {
23
24
  /** Repeater store context */
@@ -59,7 +60,7 @@
59
60
  viewportUpdateTimer = setTimeout(() => {
60
61
  if (!map) return;
61
62
  const newZoom = map.getZoom();
62
- console.log('RepeatersLayer: Viewport changed, updating to zoom:', newZoom);
63
+ log('RepeatersLayer: Viewport changed, updating to zoom:', newZoom);
63
64
  // Update zoom
64
65
  store.setCurrentZoom(newZoom);
65
66
  // Force $effect to re-run
@@ -74,8 +75,6 @@
74
75
  function initializeLayer() {
75
76
  if (!map) return;
76
77
 
77
- console.log('RepeatersLayer: initializeLayer called');
78
-
79
78
  // Set initial zoom
80
79
  store.setCurrentZoom(map.getZoom());
81
80
 
@@ -91,12 +90,9 @@
91
90
  }
92
91
 
93
92
  onMount(() => {
94
- console.log('RepeatersLayer: onMount, waiting for map...');
95
-
96
93
  // Subscribe to map store
97
94
  const unsubscribe = mapStore.subscribe((mapInstance) => {
98
95
  if (mapInstance && !map) {
99
- console.log('RepeatersLayer: Map available, initializing...');
100
96
  map = mapInstance;
101
97
 
102
98
  // Initial layer setup
@@ -137,19 +133,16 @@
137
133
  }
138
134
  });
139
135
 
140
- // Reactive: Update GeoJSON when repeaters/zoom/settings change
136
+ // Reactive: Update GeoJSON when repeaters/zoom/filters/settings change
141
137
  $effect(() => {
142
- // Track viewportVersion to force re-run on pan
138
+ // Track viewportVersion to force re-run on viewport changes
143
139
  viewportVersion;
144
140
 
145
- console.log('RepeatersLayer $effect triggered:', {
141
+ log('RepeatersLayer update:', {
146
142
  mounted,
147
143
  hasMap: !!map,
148
144
  showRepeaters: store.showRepeaters,
149
- filteredRepeatersCount: store.filteredRepeaters.length,
150
- currentZoom: store.currentZoom,
151
- baseRadius: store.baseRadius,
152
- viewportVersion
145
+ filteredCount: store.filteredRepeaters.length
153
146
  });
154
147
 
155
148
  if (!mounted || !map) {
@@ -180,10 +173,7 @@
180
173
  bounds.contains([repeater.longitude, repeater.latitude])
181
174
  );
182
175
 
183
- console.log('RepeatersLayer: Viewport filtering:', {
184
- totalFiltered: store.filteredRepeaters.length,
185
- visibleInViewport: visibleRepeaters.length
186
- });
176
+ log('RepeatersLayer viewport filter:', visibleRepeaters.length, 'of', store.filteredRepeaters.length);
187
177
 
188
178
  // Generate GeoJSON from visible repeaters only
189
179
  const geoJSON = repeatersToGeoJSON(
@@ -193,18 +183,13 @@
193
183
  store.techBandColorMap
194
184
  );
195
185
 
196
- console.log('RepeatersLayer: Generated GeoJSON:', {
197
- featureCount: geoJSON.features.length,
198
- firstFeature: geoJSON.features[0]
199
- });
186
+ log('RepeatersLayer GeoJSON:', geoJSON.features.length, 'features');
200
187
 
201
188
  // Update or create source
202
189
  const source = map.getSource(SOURCE_ID);
203
190
  if (source && source.type === 'geojson') {
204
- console.log('RepeatersLayer: Updating existing source');
205
191
  source.setData(geoJSON);
206
192
  } else {
207
- console.log('RepeatersLayer: Creating new source');
208
193
  map.addSource(SOURCE_ID, {
209
194
  type: 'geojson',
210
195
  data: geoJSON
@@ -228,7 +213,6 @@
228
213
 
229
214
  // Add fill layer if not exists
230
215
  if (!map.getLayer(fillLayerId)) {
231
- console.log(`RepeatersLayer: Creating fill layer for z-index ${zIndex}`);
232
216
  map.addLayer({
233
217
  id: fillLayerId,
234
218
  type: 'fill',
@@ -249,7 +233,6 @@
249
233
 
250
234
  // Add line layer if not exists
251
235
  if (!map.getLayer(lineLayerId)) {
252
- console.log(`RepeatersLayer: Creating line layer for z-index ${zIndex}`);
253
236
  map.addLayer({
254
237
  id: lineLayerId,
255
238
  type: 'line',
@@ -75,10 +75,8 @@ export function buildRepeaterTree(repeaters, colorMap) {
75
75
  */
76
76
  export function getFilteredRepeaters(checkedPaths) {
77
77
  const selected = new Set();
78
- console.log('getFilteredRepeaters - checkedPaths:', Array.from(checkedPaths));
79
78
  // If only root is checked, all tech:fbands are visible
80
79
  if (checkedPaths.has('root') && checkedPaths.size === 1) {
81
- console.log('Only root checked - returning empty set for "all visible"');
82
80
  return selected;
83
81
  }
84
82
  // Check each path - leaf nodes have tech:fband in their ID
@@ -86,14 +84,12 @@ export function getFilteredRepeaters(checkedPaths) {
86
84
  // Paths are like "root:2G:2G:GSM900" where the node ID is the last segment
87
85
  // The node ID for leaf nodes is "tech:fband" format
88
86
  const parts = path.split(':');
89
- console.log('Processing path:', path, 'parts:', parts);
90
87
  // Check if this is a leaf node (contains tech:fband format)
91
88
  // Leaf node IDs are like "2G:GSM900", "4G:LTE1800"
92
89
  // The path would be "root:2G:2G:GSM900" (root -> tech -> tech:fband)
93
90
  if (parts.length === 4 && parts[0] === 'root') {
94
91
  // This is a leaf node: root:tech:tech:fband
95
92
  const techBandKey = `${parts[2]}:${parts[3]}`;
96
- console.log('Adding tech:fband key:', techBandKey);
97
93
  selected.add(techBandKey);
98
94
  }
99
95
  else if (parts.length === 3 && parts[0] === 'root') {
@@ -101,11 +97,9 @@ export function getFilteredRepeaters(checkedPaths) {
101
97
  const nodeId = parts[2];
102
98
  if (nodeId && nodeId.includes(':')) {
103
99
  // This is already in tech:fband format
104
- console.log('Adding tech:fband key (alternative format):', nodeId);
105
100
  selected.add(nodeId);
106
101
  }
107
102
  }
108
103
  }
109
- console.log('getFilteredRepeaters - selected tech:bands:', Array.from(selected));
110
104
  return selected;
111
105
  }
@@ -45,10 +45,7 @@
45
45
  let treeStore = $state<Writable<TreeStoreValue> | null>(null);
46
46
 
47
47
  onMount(() => {
48
- console.log('SiteFilterControl: Mounted with', store.allSites.length, 'sites');
49
-
50
48
  if (store.allSites.length > 0) {
51
- console.log('SiteFilterControl: Building tree...');
52
49
  const treeNodes = buildSiteTree(store.allSites, store.groupColorMap);
53
50
 
54
51
  treeStore = createTreeStore({
@@ -57,17 +54,12 @@
57
54
  persistState: true,
58
55
  defaultExpandAll: false
59
56
  });
60
-
61
- console.log('SiteFilterControl: Tree store created');
62
57
 
63
58
  // Subscribe to tree changes and update siteStore
64
59
  if (treeStore) {
65
60
  const unsub = treeStore.subscribe((treeValue: TreeStoreValue) => {
66
61
  const checkedPaths = treeValue.getCheckedPaths();
67
- console.log('TreeStore updated, checked paths:', checkedPaths);
68
-
69
62
  const newFilteredSites = getFilteredSites(checkedPaths, store.allSites);
70
- console.log('Filtered sites count:', newFilteredSites.length, 'of', store.allSites.length);
71
63
 
72
64
  // Update the site store directly
73
65
  store.filteredSites = newFilteredSites;
@@ -74,7 +74,6 @@ export function buildSiteTree(sites, colorMap) {
74
74
  * Filters sites based on checked tree paths
75
75
  */
76
76
  export function getFilteredSites(checkedPaths, allSites) {
77
- console.log('getFilteredSites called with paths:', checkedPaths);
78
77
  const checkedGroups = new Set();
79
78
  const checkedProviders = new Set();
80
79
  checkedPaths.forEach((path) => {
@@ -97,16 +96,12 @@ export function getFilteredSites(checkedPaths, allSites) {
97
96
  checkedProviders.add(filteredParts[0]);
98
97
  }
99
98
  });
100
- console.log('Checked groups:', Array.from(checkedGroups));
101
- console.log('Checked providers:', Array.from(checkedProviders));
102
99
  // If "all-sites" is checked and it's the only thing, return all
103
100
  if (checkedPaths.includes('all-sites') && checkedGroups.size === 0 && checkedProviders.size === 0) {
104
- console.log('All sites root checked, returning all');
105
101
  return allSites;
106
102
  }
107
103
  // If nothing is checked, return empty
108
104
  if (checkedGroups.size === 0 && checkedProviders.size === 0) {
109
- console.log('Nothing checked, returning empty');
110
105
  return [];
111
106
  }
112
107
  // Filter sites based on checked groups or providers
@@ -116,6 +111,5 @@ export function getFilteredSites(checkedPaths, allSites) {
116
111
  const included = checkedGroups.has(key) || checkedProviders.has(site.provider);
117
112
  return included;
118
113
  });
119
- console.log('Filtered:', filtered.length, 'of', allSites.length, 'sites');
120
114
  return filtered;
121
115
  }
@@ -0,0 +1,89 @@
1
+ <script lang="ts">
2
+ import { setContext, onMount, onDestroy } from 'svelte';
3
+ import mapboxgl from 'mapbox-gl';
4
+ import 'mapbox-gl/dist/mapbox-gl.css';
5
+ import { createMapStore } from '../stores/map.store.svelte';
6
+ import { createViewportStore } from '../stores/viewport.store.svelte';
7
+
8
+ interface Props {
9
+ accessToken: string;
10
+ style?: string;
11
+ center?: [number, number];
12
+ zoom?: number;
13
+ class?: string;
14
+ children?: import('svelte').Snippet;
15
+ namespace?: string;
16
+ }
17
+
18
+ let {
19
+ accessToken,
20
+ style = 'mapbox://styles/mapbox/streets-v12',
21
+ center = [0, 0],
22
+ zoom = 2,
23
+ class: className = '',
24
+ children,
25
+ namespace = 'map'
26
+ }: Props = $props();
27
+
28
+ let mapContainer: HTMLDivElement;
29
+ const mapStore = createMapStore();
30
+
31
+ // Initialize viewport store with defaults from props
32
+ const viewportStore = createViewportStore(namespace, { center, zoom });
33
+
34
+ setContext('MAP_CONTEXT', mapStore);
35
+
36
+ onMount(() => {
37
+ mapboxgl.accessToken = accessToken;
38
+
39
+ // Use viewport store values for initialization
40
+ mapStore.init(mapContainer, {
41
+ style,
42
+ center: viewportStore.center,
43
+ zoom: viewportStore.zoom,
44
+ bearing: viewportStore.bearing,
45
+ pitch: viewportStore.pitch
46
+ });
47
+
48
+ // Sync Map -> Store
49
+ const map = mapStore.map;
50
+ if (map) {
51
+ const updateStore = () => {
52
+ viewportStore.updateViewport({
53
+ center: map.getCenter().toArray() as [number, number],
54
+ zoom: map.getZoom(),
55
+ bearing: map.getBearing(),
56
+ pitch: map.getPitch()
57
+ });
58
+ };
59
+
60
+ map.on('moveend', updateStore);
61
+ map.on('zoomend', updateStore);
62
+ map.on('rotateend', updateStore);
63
+ map.on('pitchend', updateStore);
64
+ }
65
+ });
66
+
67
+ onDestroy(() => {
68
+ mapStore.destroy();
69
+ });
70
+ </script>
71
+
72
+ <div class="map-wrapper {className}">
73
+ <div bind:this={mapContainer} class="map-instance"></div>
74
+ {#if mapStore.loaded}
75
+ {@render children?.()}
76
+ {/if}
77
+ </div>
78
+
79
+ <style>
80
+ .map-wrapper {
81
+ width: 100%;
82
+ height: 100%;
83
+ position: relative;
84
+ }
85
+ .map-instance {
86
+ width: 100%;
87
+ height: 100%;
88
+ }
89
+ </style>
@@ -0,0 +1,13 @@
1
+ import 'mapbox-gl/dist/mapbox-gl.css';
2
+ interface Props {
3
+ accessToken: string;
4
+ style?: string;
5
+ center?: [number, number];
6
+ zoom?: number;
7
+ class?: string;
8
+ children?: import('svelte').Snippet;
9
+ namespace?: string;
10
+ }
11
+ declare const Map: import("svelte").Component<Props, {}, "">;
12
+ type Map = ReturnType<typeof Map>;
13
+ export default Map;
@@ -0,0 +1,103 @@
1
+ <script lang="ts">
2
+ import { MapControl } from '../../shared';
3
+ import CellSettingsPanel from '../../features/cells/components/CellSettingsPanel.svelte';
4
+ import RepeaterSettingsPanel from '../../features/repeaters/components/RepeaterSettingsPanel.svelte';
5
+ import SiteSettingsPanel from '../../features/sites/components/SiteSettingsPanel.svelte';
6
+ import type { CellDisplayStore } from '../../features/cells/stores/cell.display.svelte';
7
+ import type { RepeaterDisplayStore } from '../../features/repeaters/stores/repeater.display.svelte';
8
+ import type { SiteDisplayStore } from '../../features/sites/stores/site.display.svelte';
9
+
10
+ interface Props {
11
+ cellDisplayStore: CellDisplayStore;
12
+ repeaterDisplayStore?: RepeaterDisplayStore;
13
+ siteDisplayStore?: SiteDisplayStore;
14
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
15
+ title?: string;
16
+ icon?: string;
17
+ initiallyCollapsed?: boolean;
18
+ }
19
+
20
+ let {
21
+ cellDisplayStore,
22
+ repeaterDisplayStore,
23
+ siteDisplayStore,
24
+ position = 'top-right',
25
+ title = 'Feature Settings',
26
+ icon = 'sliders',
27
+ initiallyCollapsed = true
28
+ }: Props = $props();
29
+ </script>
30
+
31
+ <MapControl {position} {title} {icon} {initiallyCollapsed} controlWidth="380px" edgeOffset="12px">
32
+ <div class="d-flex flex-column p-0">
33
+ <ul class="nav nav-tabs" id="settings-tabs" role="tablist">
34
+ <!-- Cell Tab -->
35
+ <li class="nav-item" role="presentation">
36
+ <button class="nav-link active" id="cell-tab" data-bs-toggle="tab" data-bs-target="#cell" type="button" role="tab">Cells</button>
37
+ </li>
38
+ <!-- Site Tab -->
39
+ {#if siteDisplayStore}
40
+ <li class="nav-item" role="presentation">
41
+ <button class="nav-link" id="site-tab" data-bs-toggle="tab" data-bs-target="#site" type="button" role="tab">Sites</button>
42
+ </li>
43
+ {/if}
44
+ <!-- Repeater Tab -->
45
+ {#if repeaterDisplayStore}
46
+ <li class="nav-item" role="presentation">
47
+ <button class="nav-link" id="repeater-tab" data-bs-toggle="tab" data-bs-target="#repeater" type="button" role="tab">Repeaters</button>
48
+ </li>
49
+ {/if}
50
+ </ul>
51
+
52
+ <div class="tab-content rounded-2 shadow-sm bg-white border p-2" id="settings-tab-content">
53
+ <!-- Cell Panel -->
54
+ <div class="tab-pane show active" id="cell" role="tabpanel">
55
+ <CellSettingsPanel displayStore={cellDisplayStore} />
56
+ </div>
57
+ <!-- Site Panel -->
58
+ {#if siteDisplayStore}
59
+ <div class="tab-pane" id="site" role="tabpanel">
60
+ <SiteSettingsPanel displayStore={siteDisplayStore} />
61
+ </div>
62
+ {/if}
63
+ <!-- Repeater Panel -->
64
+ {#if repeaterDisplayStore}
65
+ <div class="tab-pane" id="repeater" role="tabpanel">
66
+ <RepeaterSettingsPanel displayStore={repeaterDisplayStore} />
67
+ </div>
68
+ {/if}
69
+ </div>
70
+ </div>
71
+ </MapControl>
72
+
73
+ <style>
74
+ :global(.map-control-content) {
75
+ padding: 0.25rem;
76
+ }
77
+
78
+ .nav-tabs {
79
+ border-bottom: 1px solid #dee2e6;
80
+ }
81
+
82
+ .nav-link {
83
+ border: 1px solid transparent;
84
+ border-top-left-radius: 0.375rem;
85
+ border-top-right-radius: 0.375rem;
86
+ font-size: 0.95rem;
87
+ font-weight: 500;
88
+ padding: 0.5rem 1rem;
89
+ color: #6c757d;
90
+ white-space: nowrap;
91
+ min-width: fit-content;
92
+ }
93
+
94
+ .nav-link.active {
95
+ color: #495057;
96
+ background-color: #fff;
97
+ border-color: #dee2e6 #dee2e6 #fff;
98
+ }
99
+
100
+ .tab-content {
101
+ padding: 0;
102
+ }
103
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { CellDisplayStore } from '../../features/cells/stores/cell.display.svelte';
2
+ import type { RepeaterDisplayStore } from '../../features/repeaters/stores/repeater.display.svelte';
3
+ import type { SiteDisplayStore } from '../../features/sites/stores/site.display.svelte';
4
+ interface Props {
5
+ cellDisplayStore: CellDisplayStore;
6
+ repeaterDisplayStore?: RepeaterDisplayStore;
7
+ siteDisplayStore?: SiteDisplayStore;
8
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
9
+ title?: string;
10
+ icon?: string;
11
+ initiallyCollapsed?: boolean;
12
+ }
13
+ declare const FeatureSettingsControl: import("svelte").Component<Props, {}, "">;
14
+ type FeatureSettingsControl = ReturnType<typeof FeatureSettingsControl>;
15
+ export default FeatureSettingsControl;