@smartnet360/svelte-components 0.0.80 → 0.0.82

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.
@@ -232,11 +232,11 @@
232
232
  <!-- Generic feature selection control - works with any layer -->
233
233
  <FeatureSelectionControl
234
234
  position="bottom-left"
235
- title="Any Feature"
236
- icon="cursor-fill"
235
+ title="Cluster Tool"
236
+ icon="speedometer2"
237
237
  iconOnlyWhenCollapsed={useIconHeaders}
238
238
  onAction={handleProcessFeatures}
239
- actionButtonLabel="Process Features"
239
+ actionButtonLabel="Process Cluster"
240
240
  featureIcon="pin-map-fill"
241
241
  />
242
242
 
@@ -51,6 +51,8 @@ export function cellsToGeoJSON(cells, currentZoom, baseRadius = 500, groupColorM
51
51
  cellID: cell.cellID,
52
52
  cellName: cell.cellName,
53
53
  siteId: cell.siteId,
54
+ latitude: cell.latitude,
55
+ longitude: cell.longitude,
54
56
  // Cell attributes
55
57
  tech: cell.tech,
56
58
  band: cell.frq,
@@ -14,6 +14,7 @@
14
14
 
15
15
  import { onMount, onDestroy, getContext } from 'svelte';
16
16
  import { get } from 'svelte/store';
17
+ import mapboxgl from 'mapbox-gl';
17
18
  import MapControl from './MapControl.svelte';
18
19
  import { createFeatureSelectionStore, type SelectedFeature } from './featureSelectionStore.svelte';
19
20
  import { MAP_CONTEXT_KEY, type MapStore } from '../../core/types';
@@ -41,13 +42,13 @@
41
42
 
42
43
  let {
43
44
  position = 'top-left',
44
- title = 'Feature Selection',
45
- icon = 'check2-square',
45
+ title = 'Cluster Tool',
46
+ icon = 'speedometer2',
46
47
  iconOnlyWhenCollapsed = true,
47
48
  onAction,
48
- actionButtonLabel = 'Process',
49
+ actionButtonLabel = 'Process Cluster',
49
50
  featureIcon = 'geo-alt-fill',
50
- idPropertyOptions = ['siteId', 'cellName','id'],
51
+ idPropertyOptions = ['siteId','sectorId', 'cellName','id'],
51
52
  defaultIdProperty = 'siteId'
52
53
  }: Props = $props();
53
54
 
@@ -66,6 +67,12 @@
66
67
  let selectionCount = $derived(store.count);
67
68
  let hasSelection = $derived(selectionCount > 0);
68
69
 
70
+ // Track collapsed state
71
+ let isCollapsed = $state(false);
72
+
73
+ // Track markers for selected features
74
+ let markers = new Map<string, mapboxgl.Marker>();
75
+
69
76
  // Subscribe to map store and initialize when map becomes available
70
77
  let unsubscribe: (() => void) | null = null;
71
78
 
@@ -78,6 +85,8 @@
78
85
  if (map && !store['map']) {
79
86
  console.log('[FeatureSelectionControl] Setting map on selection store');
80
87
  store.setMap(map);
88
+ // Enable selection mode on mount (control starts collapsed=false by default)
89
+ store.enableSelectionMode();
81
90
  }
82
91
  });
83
92
  });
@@ -87,12 +96,72 @@
87
96
  if (unsubscribe) {
88
97
  unsubscribe();
89
98
  }
99
+ // Remove all markers
100
+ clearAllMarkers();
90
101
  // Cleanup event handlers
91
102
  store.destroy();
92
103
  });
93
104
 
94
- function handleToggleMode() {
95
- store.toggleSelectionMode();
105
+ // Update markers when selected features change
106
+ $effect(() => {
107
+ updateMarkers(selectedFeatures);
108
+ });
109
+
110
+ function updateMarkers(features: SelectedFeature[]) {
111
+ console.log('[FeatureSelectionControl] Updating markers for', features.length, 'features');
112
+
113
+ // Get current map
114
+ const map = get(mapStore);
115
+ if (!map) return;
116
+
117
+ // Remove markers that are no longer in the selection
118
+ const currentIds = new Set(features.map(f => f.id));
119
+ for (const [id, marker] of markers.entries()) {
120
+ if (!currentIds.has(id)) {
121
+ marker.remove();
122
+ markers.delete(id);
123
+ console.log('[FeatureSelectionControl] Removed marker for', id);
124
+ }
125
+ }
126
+
127
+ // Add markers for new selections
128
+ for (const feature of features) {
129
+ if (!markers.has(feature.id)) {
130
+ // Try to extract coordinates from properties
131
+ const lat = feature.properties?.latitude || feature.properties?.lat;
132
+ const lon = feature.properties?.longitude || feature.properties?.lon || feature.properties?.lng;
133
+
134
+ if (lat && lon) {
135
+ const marker = new mapboxgl.Marker({ color: '#FF6B35' })
136
+ .setLngLat([lon, lat])
137
+ .addTo(map);
138
+
139
+ markers.set(feature.id, marker);
140
+ console.log('[FeatureSelectionControl] Added marker for', feature.id, 'at', [lon, lat]);
141
+ } else {
142
+ console.warn('[FeatureSelectionControl] No coordinates found for feature', feature.id);
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ function clearAllMarkers() {
149
+ for (const marker of markers.values()) {
150
+ marker.remove();
151
+ }
152
+ markers.clear();
153
+ console.log('[FeatureSelectionControl] All markers cleared');
154
+ }
155
+
156
+ function handleCollapseToggle(collapsed: boolean) {
157
+ isCollapsed = collapsed;
158
+ // When control is expanded, enable selection mode
159
+ // When control is collapsed, disable selection mode
160
+ if (collapsed) {
161
+ store.disableSelectionMode();
162
+ } else {
163
+ store.enableSelectionMode();
164
+ }
96
165
  }
97
166
 
98
167
  function handleIdPropertyChange(event: Event) {
@@ -107,6 +176,7 @@
107
176
 
108
177
  function handleClearAll() {
109
178
  store.clearSelection();
179
+ clearAllMarkers();
110
180
  }
111
181
 
112
182
  async function handleCopy() {
@@ -127,32 +197,8 @@
127
197
  }
128
198
  </script>
129
199
 
130
- <MapControl {position} {title} {icon} {iconOnlyWhenCollapsed} collapsible={true}>
200
+ <MapControl {position} {title} {icon} {iconOnlyWhenCollapsed} collapsible={true} onCollapseToggle={handleCollapseToggle}>
131
201
  <div class="feature-selection-control">
132
- <!-- Selection Mode Toggle -->
133
- <div class="selection-mode-toggle mb-3">
134
- <div class="form-check form-switch">
135
- <input
136
- type="checkbox"
137
- class="form-check-input"
138
- id="feature-selection-mode-toggle"
139
- checked={store.selectionMode}
140
- onchange={handleToggleMode}
141
- />
142
- <label class="form-check-label" for="feature-selection-mode-toggle">
143
- Selection Mode
144
- <span class="badge ms-2" class:bg-success={store.selectionMode} class:bg-secondary={!store.selectionMode}>
145
- {store.selectionMode ? 'ON' : 'OFF'}
146
- </span>
147
- </label>
148
- </div>
149
- {#if store.selectionMode}
150
- <small class="text-muted d-block mt-1">
151
- Click any feature on the map to select
152
- </small>
153
- {/if}
154
- </div>
155
-
156
202
  <!-- ID Property Selector -->
157
203
  <div class="mb-3">
158
204
  <label for="id-property-select" class="form-label small">Select By</label>
@@ -171,7 +217,7 @@
171
217
  <!-- Selection Stats -->
172
218
  <div class="selection-stats mb-2">
173
219
  <strong>{selectionCount}</strong>
174
- {selectionCount === 1 ? 'feature' : 'features'} selected
220
+ {selectionCount === 1 ? 'item' : 'items'} selected
175
221
  </div>
176
222
 
177
223
  <!-- Action Buttons -->
@@ -225,7 +271,8 @@
225
271
  {:else}
226
272
  <div class="text-muted small text-center py-2">
227
273
  <i class="bi bi-inbox"></i>
228
- <div class="mt-1">No features selected</div>
274
+ <div class="mt-1">No items selected</div>
275
+ <div class="mt-1">Click on cells or sites</div>
229
276
  </div>
230
277
  {/if}
231
278
 
@@ -27,6 +27,8 @@
27
27
  collapsible?: boolean;
28
28
  /** Initial collapsed state */
29
29
  initiallyCollapsed?: boolean;
30
+ /** Optional callback when collapse state changes */
31
+ onCollapseToggle?: (collapsed: boolean) => void;
30
32
  /** Custom CSS class for the container */
31
33
  className?: string;
32
34
  /** Child content */
@@ -44,13 +46,12 @@
44
46
  iconOnlyWhenCollapsed = true,
45
47
  collapsible = true,
46
48
  initiallyCollapsed = true,
49
+ onCollapseToggle,
47
50
  className = '',
48
51
  children,
49
52
  edgeOffset = '12px',
50
53
  controlWidth = '420px'
51
54
  }: Props = $props();
52
-
53
-
54
55
  const mapStore = tryUseMapbox();
55
56
 
56
57
  if (!mapStore) {
@@ -113,6 +114,10 @@
113
114
 
114
115
  function toggleCollapse() {
115
116
  collapsed = !collapsed;
117
+ // Call the callback if provided
118
+ if (onCollapseToggle) {
119
+ onCollapseToggle(collapsed);
120
+ }
116
121
  }
117
122
  </script>
118
123
 
@@ -11,6 +11,8 @@ interface Props {
11
11
  collapsible?: boolean;
12
12
  /** Initial collapsed state */
13
13
  initiallyCollapsed?: boolean;
14
+ /** Optional callback when collapse state changes */
15
+ onCollapseToggle?: (collapsed: boolean) => void;
14
16
  /** Custom CSS class for the container */
15
17
  className?: string;
16
18
  /** Child content */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.80",
3
+ "version": "0.0.82",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",