@smartnet360/svelte-components 0.0.87 → 0.0.89

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 (34) hide show
  1. package/dist/map-v3/core/components/MapStoreBridge.svelte +25 -0
  2. package/dist/map-v3/core/components/MapStoreBridge.svelte.d.ts +8 -0
  3. package/dist/map-v3/core/index.d.ts +1 -0
  4. package/dist/map-v3/core/index.js +1 -0
  5. package/dist/map-v3/demo/DemoMap.svelte +10 -0
  6. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +24 -6
  7. package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +3 -0
  8. package/dist/map-v3/features/cells/constants/statusStyles.d.ts +14 -0
  9. package/dist/map-v3/features/cells/constants/statusStyles.js +49 -0
  10. package/dist/map-v3/features/cells/constants.d.ts +1 -0
  11. package/dist/map-v3/features/cells/constants.js +54 -13
  12. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +7 -2
  13. package/dist/map-v3/features/cells/layers/CellsLayer.svelte +28 -12
  14. package/dist/map-v3/features/cells/logic/geometry.d.ts +1 -1
  15. package/dist/map-v3/features/cells/logic/geometry.js +26 -5
  16. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +14 -0
  17. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +57 -26
  18. package/dist/map-v3/features/selection/components/FeatureSelectionControl.svelte +309 -0
  19. package/dist/map-v3/features/selection/components/FeatureSelectionControl.svelte.d.ts +20 -0
  20. package/dist/map-v3/features/selection/index.d.ts +9 -0
  21. package/dist/map-v3/features/selection/index.js +10 -0
  22. package/dist/map-v3/features/selection/layers/SelectionHighlightLayers.svelte +209 -0
  23. package/dist/map-v3/features/selection/layers/SelectionHighlightLayers.svelte.d.ts +13 -0
  24. package/dist/map-v3/features/selection/stores/selection.store.svelte.d.ts +84 -0
  25. package/dist/map-v3/features/selection/stores/selection.store.svelte.js +174 -0
  26. package/dist/map-v3/features/selection/types.d.ts +25 -0
  27. package/dist/map-v3/features/selection/types.js +4 -0
  28. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +14 -0
  29. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +57 -26
  30. package/dist/map-v3/index.d.ts +1 -0
  31. package/dist/map-v3/index.js +2 -0
  32. package/dist/map-v3/shared/controls/MapControl.svelte +37 -10
  33. package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +2 -0
  34. package/package.json +1 -1
@@ -0,0 +1,309 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy, getContext } from 'svelte';
3
+ import { MapControl } from '../../../shared';
4
+ import type { MapStore } from '../../../core/stores/map.store.svelte';
5
+ import type { CellDataStore } from '../../cells/stores/cell.data.svelte';
6
+ import type { CellDisplayStore } from '../../cells/stores/cell.display.svelte';
7
+ import { createFeatureSelectionStore } from '../stores/selection.store.svelte';
8
+ import SelectionHighlightLayers from '../layers/SelectionHighlightLayers.svelte';
9
+ import type { SelectedFeature } from '../types';
10
+
11
+ interface Props {
12
+ cellDataStore?: CellDataStore;
13
+ cellDisplayStore?: CellDisplayStore;
14
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
15
+ title?: string;
16
+ icon?: string;
17
+ iconOnlyWhenCollapsed?: boolean;
18
+ onAction?: (featureIds: string[]) => void;
19
+ actionButtonLabel?: string;
20
+ featureIcon?: string;
21
+ idPropertyOptions?: string[];
22
+ defaultIdProperty?: string;
23
+ highlightColor?: string;
24
+ highlightWidth?: number;
25
+ }
26
+
27
+ let {
28
+ cellDataStore,
29
+ cellDisplayStore,
30
+ position = 'top-left',
31
+ title = 'Feature Selection',
32
+ icon = 'cursor-fill',
33
+ iconOnlyWhenCollapsed = true,
34
+ onAction,
35
+ actionButtonLabel = 'Process Selection',
36
+ featureIcon = 'geo-alt-fill',
37
+ idPropertyOptions = ['siteId', 'sectorId', 'cellName'],
38
+ defaultIdProperty = 'siteId',
39
+ highlightColor = '#FF6B00',
40
+ highlightWidth = 4
41
+ }: Props = $props();
42
+
43
+ const mapStore = getContext<MapStore>('MAP_CONTEXT');
44
+ const store = createFeatureSelectionStore();
45
+
46
+ store.setIdProperty(defaultIdProperty);
47
+
48
+ let selectedFeatures = $derived(store.getSelectedFeatures());
49
+ let selectionCount = $derived(store.count);
50
+ let hasSelection = $derived(selectionCount > 0);
51
+ let isCollapsed = $state(false);
52
+
53
+ $effect(() => {
54
+ const map = mapStore.map;
55
+ if (map && !store['map']) {
56
+ store.setMap(map);
57
+ store.enableSelectionMode();
58
+ }
59
+ });
60
+
61
+ onDestroy(() => {
62
+ store.destroy();
63
+ });
64
+
65
+ function handleCollapseToggle(collapsed: boolean) {
66
+ isCollapsed = collapsed;
67
+ if (collapsed) {
68
+ store.disableSelectionMode();
69
+ } else {
70
+ store.enableSelectionMode();
71
+ }
72
+ }
73
+
74
+ function handleIdPropertyChange(event: Event) {
75
+ const target = event.target as HTMLSelectElement;
76
+ store.setIdProperty(target.value);
77
+ }
78
+
79
+ function handleRemoveFeature(featureId: string) {
80
+ store.removeFeatureSelection(featureId);
81
+ }
82
+
83
+ function handleClearAll() {
84
+ store.clearSelection();
85
+ }
86
+
87
+ async function handleCopy() {
88
+ const ids = store.getSelectedIds().join(',');
89
+ try {
90
+ await navigator.clipboard.writeText(ids);
91
+ console.log('[FeatureSelection] Copied to clipboard:', ids);
92
+ } catch (err) {
93
+ console.error('[FeatureSelection] Failed to copy:', err);
94
+ }
95
+ }
96
+
97
+ function handleAction() {
98
+ if (onAction && hasSelection) {
99
+ const ids = store.getSelectedIds();
100
+ onAction(ids);
101
+ }
102
+ }
103
+ </script>
104
+
105
+ <MapControl
106
+ {position}
107
+ {title}
108
+ {icon}
109
+ {iconOnlyWhenCollapsed}
110
+ collapsible={true}
111
+ onCollapseToggle={handleCollapseToggle}
112
+ controlWidth="300px"
113
+ >
114
+ <div class="feature-selection-control">
115
+ <!-- ID Property Selector -->
116
+ <div class="mb-3">
117
+ <label for="id-property-select" class="form-label small fw-semibold">Select By</label>
118
+ <select
119
+ id="id-property-select"
120
+ class="form-select form-select-sm"
121
+ value={store.idProperty}
122
+ onchange={handleIdPropertyChange}
123
+ >
124
+ {#each idPropertyOptions as option}
125
+ <option value={option}>{option}</option>
126
+ {/each}
127
+ </select>
128
+ </div>
129
+
130
+ <!-- Selection Stats -->
131
+ <div class="selection-stats mb-2 text-secondary">
132
+ <strong>{selectionCount}</strong>
133
+ {selectionCount === 1 ? 'item' : 'items'} selected
134
+ </div>
135
+
136
+ <!-- Action Buttons -->
137
+ {#if hasSelection}
138
+ <div class="action-buttons mb-3">
139
+ <div class="btn-group w-100" role="group">
140
+ <button
141
+ type="button"
142
+ class="btn btn-sm btn-outline-danger"
143
+ onclick={handleClearAll}
144
+ title="Clear all"
145
+ >
146
+ <i class="bi bi-trash"></i> Clear
147
+ </button>
148
+ <button
149
+ type="button"
150
+ class="btn btn-sm btn-outline-secondary"
151
+ onclick={handleCopy}
152
+ title="Copy feature IDs"
153
+ >
154
+ <i class="bi bi-clipboard"></i> Copy
155
+ </button>
156
+ </div>
157
+ </div>
158
+ {/if}
159
+
160
+ <!-- Feature List -->
161
+ {#if hasSelection}
162
+ <div class="feature-list">
163
+ {#each selectedFeatures as feature (feature.id)}
164
+ <div class="feature-item">
165
+ <i class="bi bi-{featureIcon} feature-icon"></i>
166
+ <div class="feature-info">
167
+ <span class="feature-id">{feature.id}</span>
168
+ {#if feature.layerId}
169
+ <small class="feature-layer text-muted">{feature.layerId}</small>
170
+ {/if}
171
+ </div>
172
+ <button
173
+ type="button"
174
+ class="btn-remove"
175
+ onclick={() => handleRemoveFeature(feature.id)}
176
+ title="Remove"
177
+ aria-label="Remove {feature.id}"
178
+ >
179
+ <i class="bi bi-x"></i>
180
+ </button>
181
+ </div>
182
+ {/each}
183
+ </div>
184
+ {:else}
185
+ <div class="text-muted small text-center py-3">
186
+ <i class="bi bi-inbox" style="font-size: 2rem; opacity: 0.3;"></i>
187
+ <div class="mt-2">No items selected</div>
188
+ <div class="mt-1">Click on features to select</div>
189
+ </div>
190
+ {/if}
191
+
192
+ <!-- Action Button -->
193
+ {#if onAction}
194
+ <div class="mt-3">
195
+ <button
196
+ type="button"
197
+ class="btn btn-primary w-100"
198
+ disabled={!hasSelection}
199
+ onclick={handleAction}
200
+ >
201
+ <i class="bi bi-lightning-charge-fill"></i> {actionButtonLabel}
202
+ </button>
203
+ </div>
204
+ {/if}
205
+ </div>
206
+ </MapControl>
207
+
208
+ <!-- Highlight Layers -->
209
+ <SelectionHighlightLayers
210
+ {selectedFeatures}
211
+ {cellDataStore}
212
+ {cellDisplayStore}
213
+ {highlightColor}
214
+ {highlightWidth}
215
+ />
216
+
217
+ <style>
218
+ .feature-selection-control {
219
+ width: 100%;
220
+ }
221
+
222
+ .selection-stats {
223
+ font-size: 0.875rem;
224
+ color: #495057;
225
+ }
226
+
227
+ .feature-list {
228
+ max-height: 300px;
229
+ overflow-y: auto;
230
+ border: 1px solid #dee2e6;
231
+ border-radius: 4px;
232
+ padding: 0.5rem;
233
+ background: #fff;
234
+ }
235
+
236
+ .feature-item {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 0.5rem;
240
+ padding: 0.5rem;
241
+ border-bottom: 1px solid #f1f3f5;
242
+ transition: background-color 0.15s;
243
+ }
244
+
245
+ .feature-item:last-child {
246
+ border-bottom: none;
247
+ }
248
+
249
+ .feature-item:hover {
250
+ background-color: #f8f9fa;
251
+ }
252
+
253
+ .feature-icon {
254
+ font-size: 1rem;
255
+ flex-shrink: 0;
256
+ color: #0d6efd;
257
+ }
258
+
259
+ .feature-info {
260
+ flex: 1;
261
+ display: flex;
262
+ flex-direction: column;
263
+ gap: 0.125rem;
264
+ min-width: 0;
265
+ }
266
+
267
+ .feature-id {
268
+ font-family: 'Monaco', 'Courier New', monospace;
269
+ font-size: 0.875rem;
270
+ color: #212529;
271
+ white-space: nowrap;
272
+ overflow: hidden;
273
+ text-overflow: ellipsis;
274
+ }
275
+
276
+ .feature-layer {
277
+ font-size: 0.75rem;
278
+ white-space: nowrap;
279
+ overflow: hidden;
280
+ text-overflow: ellipsis;
281
+ }
282
+
283
+ .btn-remove {
284
+ background: none;
285
+ border: none;
286
+ color: #6c757d;
287
+ font-size: 1.25rem;
288
+ line-height: 1;
289
+ padding: 0;
290
+ width: 24px;
291
+ height: 24px;
292
+ display: flex;
293
+ align-items: center;
294
+ justify-content: center;
295
+ cursor: pointer;
296
+ border-radius: 4px;
297
+ transition: all 0.15s;
298
+ flex-shrink: 0;
299
+ }
300
+
301
+ .btn-remove:hover {
302
+ background-color: #ffe6e6;
303
+ color: #dc3545;
304
+ }
305
+
306
+ .btn-remove:active {
307
+ background-color: #ffcccc;
308
+ }
309
+ </style>
@@ -0,0 +1,20 @@
1
+ import type { CellDataStore } from '../../cells/stores/cell.data.svelte';
2
+ import type { CellDisplayStore } from '../../cells/stores/cell.display.svelte';
3
+ interface Props {
4
+ cellDataStore?: CellDataStore;
5
+ cellDisplayStore?: CellDisplayStore;
6
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
7
+ title?: string;
8
+ icon?: string;
9
+ iconOnlyWhenCollapsed?: boolean;
10
+ onAction?: (featureIds: string[]) => void;
11
+ actionButtonLabel?: string;
12
+ featureIcon?: string;
13
+ idPropertyOptions?: string[];
14
+ defaultIdProperty?: string;
15
+ highlightColor?: string;
16
+ highlightWidth?: number;
17
+ }
18
+ declare const FeatureSelectionControl: import("svelte").Component<Props, {}, "">;
19
+ type FeatureSelectionControl = ReturnType<typeof FeatureSelectionControl>;
20
+ export default FeatureSelectionControl;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Feature Selection - Public API
3
+ *
4
+ * Exports all selection-related components, stores, and types.
5
+ */
6
+ export type { SelectedFeature, SelectionStoreState } from './types';
7
+ export { createFeatureSelectionStore, FeatureSelectionStore } from './stores/selection.store.svelte';
8
+ export { default as FeatureSelectionControl } from './components/FeatureSelectionControl.svelte';
9
+ export { default as SelectionHighlightLayers } from './layers/SelectionHighlightLayers.svelte';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Feature Selection - Public API
3
+ *
4
+ * Exports all selection-related components, stores, and types.
5
+ */
6
+ // Store
7
+ export { createFeatureSelectionStore, FeatureSelectionStore } from './stores/selection.store.svelte';
8
+ // Components
9
+ export { default as FeatureSelectionControl } from './components/FeatureSelectionControl.svelte';
10
+ export { default as SelectionHighlightLayers } from './layers/SelectionHighlightLayers.svelte';
@@ -0,0 +1,209 @@
1
+ <script lang="ts">
2
+ import { getContext } from 'svelte';
3
+ import type { MapStore } from '../../../core/stores/map.store.svelte';
4
+ import type { CellDataStore } from '../../cells/stores/cell.data.svelte';
5
+ import type { CellDisplayStore } from '../../cells/stores/cell.display.svelte';
6
+ import type { SelectedFeature } from '../types';
7
+ import { generateCellArc, calculateRadiusInMeters } from '../../cells/logic/geometry';
8
+ import type mapboxgl from 'mapbox-gl';
9
+
10
+ interface Props {
11
+ selectedFeatures: SelectedFeature[];
12
+ cellDataStore?: CellDataStore;
13
+ cellDisplayStore?: CellDisplayStore;
14
+ highlightColor?: string;
15
+ highlightWidth?: number;
16
+ }
17
+
18
+ let {
19
+ selectedFeatures,
20
+ cellDataStore,
21
+ cellDisplayStore,
22
+ highlightColor = '#FF6B00',
23
+ highlightWidth = 4
24
+ }: Props = $props();
25
+
26
+ const mapStore = getContext<MapStore>('MAP_CONTEXT');
27
+
28
+ let cellsSourceId = 'cells-selection-source';
29
+ let cellsLayerId = 'cells-selection-highlight';
30
+ let sitesSourceId = 'sites-selection-source';
31
+ let sitesLayerId = 'sites-selection-highlight';
32
+
33
+ // Track current zoom level for radius calculation
34
+ let currentZoom = $state(13);
35
+ let centerLat = $state(0);
36
+
37
+ // Update zoom level when map changes
38
+ $effect(() => {
39
+ const map = mapStore.map;
40
+ if (!map) return;
41
+
42
+ const updateZoom = () => {
43
+ currentZoom = map.getZoom();
44
+ centerLat = map.getCenter().lat;
45
+ };
46
+
47
+ updateZoom();
48
+ map.on('zoom', updateZoom);
49
+ map.on('move', updateZoom);
50
+
51
+ return () => {
52
+ map.off('zoom', updateZoom);
53
+ map.off('move', updateZoom);
54
+ };
55
+ });
56
+
57
+ // Derive highlighted cells based on selected features
58
+ let highlightedCells = $derived.by(() => {
59
+ if (!cellDataStore) return [];
60
+
61
+ const cellIds = selectedFeatures
62
+ .filter(f => f.layerId === 'cells-layer')
63
+ .map(f => f.id);
64
+
65
+ if (cellIds.length === 0) return [];
66
+
67
+ return cellDataStore.filteredCells.filter(cell =>
68
+ cellIds.includes(cell.siteId) ||
69
+ cellIds.includes(cell.cellName) ||
70
+ cellIds.includes(cell.cellID)
71
+ );
72
+ });
73
+
74
+ // Derive highlighted sites based on selected features
75
+ // TODO: Add site highlighting when SiteDataStore is available
76
+ let highlightedSites = $derived.by(() => {
77
+ return [];
78
+ });
79
+
80
+ // Generate GeoJSON for cell highlights
81
+ let cellHighlightGeoJSON = $derived.by(() => {
82
+ if (!cellDisplayStore || highlightedCells.length === 0) {
83
+ return { type: 'FeatureCollection', features: [] };
84
+ }
85
+
86
+ // Calculate radius for current zoom level (same as CellsLayer does)
87
+ const radiusMeters = calculateRadiusInMeters(centerLat, currentZoom, cellDisplayStore.targetPixelSize);
88
+
89
+ const features = highlightedCells.map(cell =>
90
+ generateCellArc(cell, radiusMeters, 100, highlightColor)
91
+ );
92
+
93
+ return {
94
+ type: 'FeatureCollection' as const,
95
+ features
96
+ };
97
+ });
98
+
99
+ // Generate GeoJSON for site highlights
100
+ let siteHighlightGeoJSON = $derived.by(() => {
101
+ if (highlightedSites.length === 0) {
102
+ return { type: 'FeatureCollection', features: [] };
103
+ }
104
+
105
+ const features = highlightedSites.map((site: any) => ({
106
+ type: 'Feature' as const,
107
+ geometry: {
108
+ type: 'Point' as const,
109
+ coordinates: [site.longitude, site.latitude]
110
+ },
111
+ properties: { siteId: site.siteId }
112
+ }));
113
+
114
+ return {
115
+ type: 'FeatureCollection' as const,
116
+ features
117
+ };
118
+ });
119
+
120
+ // Initialize and manage layers
121
+ $effect(() => {
122
+ const map = mapStore.map;
123
+ if (!map) return;
124
+
125
+ const addLayers = () => {
126
+ // Cell Selection Highlight Layer
127
+ if (!map.getSource(cellsSourceId)) {
128
+ map.addSource(cellsSourceId, {
129
+ type: 'geojson',
130
+ data: { type: 'FeatureCollection', features: [] }
131
+ });
132
+ }
133
+
134
+ if (!map.getLayer(cellsLayerId)) {
135
+ map.addLayer({
136
+ id: cellsLayerId,
137
+ type: 'line',
138
+ source: cellsSourceId,
139
+ paint: {
140
+ 'line-color': highlightColor,
141
+ 'line-width': highlightWidth,
142
+ 'line-opacity': 1
143
+ }
144
+ });
145
+ }
146
+
147
+ // Site Selection Highlight Layer
148
+ if (!map.getSource(sitesSourceId)) {
149
+ map.addSource(sitesSourceId, {
150
+ type: 'geojson',
151
+ data: { type: 'FeatureCollection', features: [] }
152
+ });
153
+ }
154
+
155
+ if (!map.getLayer(sitesLayerId)) {
156
+ map.addLayer({
157
+ id: sitesLayerId,
158
+ type: 'circle',
159
+ source: sitesSourceId,
160
+ paint: {
161
+ 'circle-radius': 12,
162
+ 'circle-color': 'transparent',
163
+ 'circle-stroke-color': highlightColor,
164
+ 'circle-stroke-width': highlightWidth,
165
+ 'circle-stroke-opacity': 1
166
+ }
167
+ });
168
+ }
169
+ };
170
+
171
+ // Initial setup
172
+ addLayers();
173
+
174
+ // Events
175
+ map.on('style.load', addLayers);
176
+
177
+ // Cleanup
178
+ return () => {
179
+ map.off('style.load', addLayers);
180
+
181
+ if (map.getLayer(cellsLayerId)) map.removeLayer(cellsLayerId);
182
+ if (map.getLayer(sitesLayerId)) map.removeLayer(sitesLayerId);
183
+ if (map.getSource(cellsSourceId)) map.removeSource(cellsSourceId);
184
+ if (map.getSource(sitesSourceId)) map.removeSource(sitesSourceId);
185
+ };
186
+ });
187
+
188
+ // Update cell highlight source
189
+ $effect(() => {
190
+ const map = mapStore.map;
191
+ if (!map) return;
192
+
193
+ const source = map.getSource(cellsSourceId) as mapboxgl.GeoJSONSource;
194
+ if (source) {
195
+ source.setData(cellHighlightGeoJSON as any);
196
+ }
197
+ });
198
+
199
+ // Update site highlight source
200
+ $effect(() => {
201
+ const map = mapStore.map;
202
+ if (!map) return;
203
+
204
+ const source = map.getSource(sitesSourceId) as mapboxgl.GeoJSONSource;
205
+ if (source) {
206
+ source.setData(siteHighlightGeoJSON as any);
207
+ }
208
+ });
209
+ </script>
@@ -0,0 +1,13 @@
1
+ import type { CellDataStore } from '../../cells/stores/cell.data.svelte';
2
+ import type { CellDisplayStore } from '../../cells/stores/cell.display.svelte';
3
+ import type { SelectedFeature } from '../types';
4
+ interface Props {
5
+ selectedFeatures: SelectedFeature[];
6
+ cellDataStore?: CellDataStore;
7
+ cellDisplayStore?: CellDisplayStore;
8
+ highlightColor?: string;
9
+ highlightWidth?: number;
10
+ }
11
+ declare const SelectionHighlightLayers: import("svelte").Component<Props, {}, "">;
12
+ type SelectionHighlightLayers = ReturnType<typeof SelectionHighlightLayers>;
13
+ export default SelectionHighlightLayers;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Feature Selection Store - Svelte 5 Runes Implementation
3
+ *
4
+ * Manages selection of map features (cells, sites) with click detection.
5
+ */
6
+ import type { Map as MapboxMap } from 'mapbox-gl';
7
+ import type { SelectedFeature } from '../types';
8
+ export declare class FeatureSelectionStore {
9
+ private selectedFeatures;
10
+ private map;
11
+ selectionMode: boolean;
12
+ idProperty: string;
13
+ queryLayers: string[];
14
+ private clickHandler;
15
+ private onSelectionChange?;
16
+ /**
17
+ * Initialize the store with a map instance
18
+ */
19
+ setMap(mapInstance: MapboxMap): void;
20
+ /**
21
+ * Set which property to use as the ID
22
+ */
23
+ setIdProperty(property: string): void;
24
+ /**
25
+ * Set which layers to query for features
26
+ */
27
+ setQueryLayers(layers: string[]): void;
28
+ /**
29
+ * Register callback for selection changes
30
+ */
31
+ setSelectionChangeCallback(callback: (selected: SelectedFeature[]) => void): void;
32
+ /**
33
+ * Setup global click handler for any feature
34
+ */
35
+ private setupClickHandler;
36
+ /**
37
+ * Enable selection mode
38
+ */
39
+ enableSelectionMode(): void;
40
+ /**
41
+ * Disable selection mode
42
+ */
43
+ disableSelectionMode(): void;
44
+ /**
45
+ * Toggle a feature in the selection
46
+ */
47
+ toggleFeatureSelection(id: string, layerId?: string, properties?: Record<string, any>, siteId?: string, cellName?: string): void;
48
+ /**
49
+ * Add a feature to the selection
50
+ */
51
+ addFeatureSelection(id: string, layerId?: string, properties?: Record<string, any>, siteId?: string, cellName?: string): void;
52
+ /**
53
+ * Remove a feature from the selection
54
+ */
55
+ removeFeatureSelection(id: string): void;
56
+ /**
57
+ * Clear all selections
58
+ */
59
+ clearSelection(): void;
60
+ /**
61
+ * Get all selected features
62
+ */
63
+ getSelectedFeatures(): SelectedFeature[];
64
+ /**
65
+ * Get selected feature IDs only
66
+ */
67
+ getSelectedIds(): string[];
68
+ /**
69
+ * Check if a feature is selected
70
+ */
71
+ isFeatureSelected(id: string): boolean;
72
+ /**
73
+ * Get selection count
74
+ */
75
+ get count(): number;
76
+ /**
77
+ * Cleanup - remove event handlers
78
+ */
79
+ destroy(): void;
80
+ }
81
+ /**
82
+ * Factory function to create a new feature selection store
83
+ */
84
+ export declare function createFeatureSelectionStore(): FeatureSelectionStore;