@smartnet360/svelte-components 0.0.79 → 0.0.81
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/map-v2/demo/DemoMap.svelte +3 -3
- package/dist/map-v2/shared/controls/FeatureSelectionControl.svelte +50 -31
- package/dist/map-v2/shared/controls/FeatureSelectionControl.svelte.d.ts +4 -0
- package/dist/map-v2/shared/controls/MapControl.svelte +7 -2
- package/dist/map-v2/shared/controls/MapControl.svelte.d.ts +2 -0
- package/dist/map-v2/shared/controls/featureSelectionStore.svelte.d.ts +5 -0
- package/dist/map-v2/shared/controls/featureSelectionStore.svelte.js +12 -3
- package/package.json +1 -1
|
@@ -232,11 +232,11 @@
|
|
|
232
232
|
<!-- Generic feature selection control - works with any layer -->
|
|
233
233
|
<FeatureSelectionControl
|
|
234
234
|
position="bottom-left"
|
|
235
|
-
title="
|
|
236
|
-
icon="
|
|
235
|
+
title="Cluster Tool"
|
|
236
|
+
icon="speedometer2"
|
|
237
237
|
iconOnlyWhenCollapsed={useIconHeaders}
|
|
238
238
|
onAction={handleProcessFeatures}
|
|
239
|
-
actionButtonLabel="Process
|
|
239
|
+
actionButtonLabel="Process Cluster"
|
|
240
240
|
featureIcon="pin-map-fill"
|
|
241
241
|
/>
|
|
242
242
|
|
|
@@ -33,16 +33,22 @@
|
|
|
33
33
|
actionButtonLabel?: string;
|
|
34
34
|
/** Feature icon (default: geo-alt-fill) */
|
|
35
35
|
featureIcon?: string;
|
|
36
|
+
/** Available property names to use as ID (default: ['id', 'siteId', 'cellName']) */
|
|
37
|
+
idPropertyOptions?: string[];
|
|
38
|
+
/** Default property to use as ID (default: 'id') */
|
|
39
|
+
defaultIdProperty?: string;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
let {
|
|
39
43
|
position = 'top-left',
|
|
40
|
-
title = '
|
|
41
|
-
icon = '
|
|
44
|
+
title = 'Cluster Tool',
|
|
45
|
+
icon = 'speedometer2',
|
|
42
46
|
iconOnlyWhenCollapsed = true,
|
|
43
47
|
onAction,
|
|
44
|
-
actionButtonLabel = 'Process',
|
|
45
|
-
featureIcon = 'geo-alt-fill'
|
|
48
|
+
actionButtonLabel = 'Process Cluster',
|
|
49
|
+
featureIcon = 'geo-alt-fill',
|
|
50
|
+
idPropertyOptions = ['siteId', 'cellName','id'],
|
|
51
|
+
defaultIdProperty = 'siteId'
|
|
46
52
|
}: Props = $props();
|
|
47
53
|
|
|
48
54
|
// Get map from context
|
|
@@ -53,10 +59,16 @@
|
|
|
53
59
|
const store = createFeatureSelectionStore();
|
|
54
60
|
console.log('[FeatureSelectionControl] Store created:', store);
|
|
55
61
|
|
|
62
|
+
// Set the ID property to use
|
|
63
|
+
store.setIdProperty(defaultIdProperty);
|
|
64
|
+
|
|
56
65
|
let selectedFeatures = $derived(store.getSelectedFeatures());
|
|
57
66
|
let selectionCount = $derived(store.count);
|
|
58
67
|
let hasSelection = $derived(selectionCount > 0);
|
|
59
68
|
|
|
69
|
+
// Track collapsed state
|
|
70
|
+
let isCollapsed = $state(false);
|
|
71
|
+
|
|
60
72
|
// Subscribe to map store and initialize when map becomes available
|
|
61
73
|
let unsubscribe: (() => void) | null = null;
|
|
62
74
|
|
|
@@ -69,6 +81,8 @@
|
|
|
69
81
|
if (map && !store['map']) {
|
|
70
82
|
console.log('[FeatureSelectionControl] Setting map on selection store');
|
|
71
83
|
store.setMap(map);
|
|
84
|
+
// Enable selection mode on mount (control starts collapsed=false by default)
|
|
85
|
+
store.enableSelectionMode();
|
|
72
86
|
}
|
|
73
87
|
});
|
|
74
88
|
});
|
|
@@ -82,8 +96,21 @@
|
|
|
82
96
|
store.destroy();
|
|
83
97
|
});
|
|
84
98
|
|
|
85
|
-
function
|
|
86
|
-
|
|
99
|
+
function handleCollapseToggle(collapsed: boolean) {
|
|
100
|
+
isCollapsed = collapsed;
|
|
101
|
+
// When control is expanded, enable selection mode
|
|
102
|
+
// When control is collapsed, disable selection mode
|
|
103
|
+
if (collapsed) {
|
|
104
|
+
store.disableSelectionMode();
|
|
105
|
+
} else {
|
|
106
|
+
store.enableSelectionMode();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function handleIdPropertyChange(event: Event) {
|
|
111
|
+
const target = event.target as HTMLSelectElement;
|
|
112
|
+
store.setIdProperty(target.value);
|
|
113
|
+
console.log('[FeatureSelectionControl] ID property changed to:', target.value);
|
|
87
114
|
}
|
|
88
115
|
|
|
89
116
|
function handleRemoveFeature(featureId: string) {
|
|
@@ -112,36 +139,27 @@
|
|
|
112
139
|
}
|
|
113
140
|
</script>
|
|
114
141
|
|
|
115
|
-
<MapControl {position} {title} {icon} {iconOnlyWhenCollapsed} collapsible={true}>
|
|
142
|
+
<MapControl {position} {title} {icon} {iconOnlyWhenCollapsed} collapsible={true} onCollapseToggle={handleCollapseToggle}>
|
|
116
143
|
<div class="feature-selection-control">
|
|
117
|
-
<!--
|
|
118
|
-
<div class="
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
{store.selectionMode ? 'ON' : 'OFF'}
|
|
131
|
-
</span>
|
|
132
|
-
</label>
|
|
133
|
-
</div>
|
|
134
|
-
{#if store.selectionMode}
|
|
135
|
-
<small class="text-muted d-block mt-1">
|
|
136
|
-
Click any feature on the map to select
|
|
137
|
-
</small>
|
|
138
|
-
{/if}
|
|
144
|
+
<!-- ID Property Selector -->
|
|
145
|
+
<div class="mb-3">
|
|
146
|
+
<label for="id-property-select" class="form-label small">Select By</label>
|
|
147
|
+
<select
|
|
148
|
+
id="id-property-select"
|
|
149
|
+
class="form-select form-select-sm"
|
|
150
|
+
value={store.idProperty}
|
|
151
|
+
onchange={handleIdPropertyChange}
|
|
152
|
+
>
|
|
153
|
+
{#each idPropertyOptions as option}
|
|
154
|
+
<option value={option}>{option}</option>
|
|
155
|
+
{/each}
|
|
156
|
+
</select>
|
|
139
157
|
</div>
|
|
140
158
|
|
|
141
159
|
<!-- Selection Stats -->
|
|
142
160
|
<div class="selection-stats mb-2">
|
|
143
161
|
<strong>{selectionCount}</strong>
|
|
144
|
-
{selectionCount === 1 ? '
|
|
162
|
+
{selectionCount === 1 ? 'item' : 'items'} selected
|
|
145
163
|
</div>
|
|
146
164
|
|
|
147
165
|
<!-- Action Buttons -->
|
|
@@ -195,7 +213,8 @@
|
|
|
195
213
|
{:else}
|
|
196
214
|
<div class="text-muted small text-center py-2">
|
|
197
215
|
<i class="bi bi-inbox"></i>
|
|
198
|
-
<div class="mt-1">No
|
|
216
|
+
<div class="mt-1">No items selected</div>
|
|
217
|
+
<div class="mt-1">Click on cells or sites</div>
|
|
199
218
|
</div>
|
|
200
219
|
{/if}
|
|
201
220
|
|
|
@@ -13,6 +13,10 @@ interface Props {
|
|
|
13
13
|
actionButtonLabel?: string;
|
|
14
14
|
/** Feature icon (default: geo-alt-fill) */
|
|
15
15
|
featureIcon?: string;
|
|
16
|
+
/** Available property names to use as ID (default: ['id', 'siteId', 'cellName']) */
|
|
17
|
+
idPropertyOptions?: string[];
|
|
18
|
+
/** Default property to use as ID (default: 'id') */
|
|
19
|
+
defaultIdProperty?: string;
|
|
16
20
|
}
|
|
17
21
|
declare const FeatureSelectionControl: import("svelte").Component<Props, {}, "">;
|
|
18
22
|
type FeatureSelectionControl = ReturnType<typeof FeatureSelectionControl>;
|
|
@@ -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 */
|
|
@@ -16,12 +16,17 @@ export declare class FeatureSelectionStore {
|
|
|
16
16
|
private selectedFeatures;
|
|
17
17
|
private map;
|
|
18
18
|
selectionMode: boolean;
|
|
19
|
+
idProperty: string;
|
|
19
20
|
private clickHandler;
|
|
20
21
|
constructor();
|
|
21
22
|
/**
|
|
22
23
|
* Initialize the store with a map instance
|
|
23
24
|
*/
|
|
24
25
|
setMap(mapInstance: MapboxMap): void;
|
|
26
|
+
/**
|
|
27
|
+
* Set which property to use as the ID
|
|
28
|
+
*/
|
|
29
|
+
setIdProperty(property: string): void;
|
|
25
30
|
/**
|
|
26
31
|
* Setup global click handler for any feature
|
|
27
32
|
*/
|
|
@@ -8,6 +8,7 @@ export class FeatureSelectionStore {
|
|
|
8
8
|
selectedFeatures = $state([]);
|
|
9
9
|
map = $state(null);
|
|
10
10
|
selectionMode = $state(false);
|
|
11
|
+
idProperty = $state('siteId'); // Default property to use as ID
|
|
11
12
|
clickHandler = null;
|
|
12
13
|
constructor() { }
|
|
13
14
|
/**
|
|
@@ -18,6 +19,13 @@ export class FeatureSelectionStore {
|
|
|
18
19
|
this.map = mapInstance;
|
|
19
20
|
this.setupClickHandler();
|
|
20
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Set which property to use as the ID
|
|
24
|
+
*/
|
|
25
|
+
setIdProperty(property) {
|
|
26
|
+
this.idProperty = property;
|
|
27
|
+
console.log('[FeatureSelection] ID property set to:', property);
|
|
28
|
+
}
|
|
21
29
|
/**
|
|
22
30
|
* Setup global click handler for any feature
|
|
23
31
|
*/
|
|
@@ -39,16 +47,17 @@ export class FeatureSelectionStore {
|
|
|
39
47
|
properties: feature.properties,
|
|
40
48
|
id: feature.id
|
|
41
49
|
});
|
|
42
|
-
|
|
50
|
+
// Use the configured property as the ID
|
|
51
|
+
const featureId = feature.properties?.[this.idProperty] || feature.id;
|
|
43
52
|
const siteId = feature.properties?.siteId;
|
|
44
53
|
const cellName = feature.properties?.cellName;
|
|
45
54
|
if (featureId) {
|
|
46
|
-
console.log('[FeatureSelection] Found feature with ID:', featureId, 'siteId:', siteId, 'cellName:', cellName);
|
|
55
|
+
console.log('[FeatureSelection] Found feature with ID (using', this.idProperty + '):', featureId, 'siteId:', siteId, 'cellName:', cellName);
|
|
47
56
|
this.toggleFeatureSelection(String(featureId), feature.layer?.id, feature.properties || undefined, siteId, cellName);
|
|
48
57
|
break; // Only select the topmost feature
|
|
49
58
|
}
|
|
50
59
|
else {
|
|
51
|
-
console.log('[FeatureSelection] Feature has no
|
|
60
|
+
console.log('[FeatureSelection] Feature has no', this.idProperty, 'property');
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
}
|