@smartnet360/svelte-components 0.0.54 → 0.0.55
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/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/map-v2/core/controls/MapStyleControl.svelte +289 -0
- package/dist/map-v2/core/controls/MapStyleControl.svelte.d.ts +24 -0
- package/dist/{map → map-v2/core}/hooks/useMapbox.d.ts +1 -1
- package/dist/{map → map-v2/core}/hooks/useMapbox.js +1 -1
- package/dist/map-v2/core/index.d.ts +11 -0
- package/dist/map-v2/core/index.js +14 -0
- package/dist/map-v2/core/providers/MapboxProvider.svelte +140 -0
- package/dist/map-v2/core/providers/MapboxProvider.svelte.d.ts +33 -0
- package/dist/{map → map-v2/core}/stores/mapStore.d.ts +2 -2
- package/dist/{map → map-v2/core}/stores/mapStore.js +2 -2
- package/dist/map-v2/core/types.d.ts +13 -0
- package/dist/map-v2/core/types.js +7 -0
- package/dist/map-v2/demo/DemoMap.svelte +63 -0
- package/dist/{map → map-v2}/demo/DemoMap.svelte.d.ts +3 -4
- package/dist/map-v2/demo/demo-data.d.ts +8 -0
- package/dist/map-v2/demo/demo-data.js +128 -0
- package/dist/map-v2/demo/index.d.ts +7 -0
- package/dist/map-v2/demo/index.js +9 -0
- package/dist/{map → map-v2/features/sites}/controls/SiteFilterControl.svelte +26 -40
- package/dist/{map → map-v2/features/sites}/controls/SiteFilterControl.svelte.d.ts +4 -6
- package/dist/map-v2/features/sites/controls/SiteSizeSlider.svelte +185 -0
- package/dist/map-v2/features/sites/controls/SiteSizeSlider.svelte.d.ts +20 -0
- package/dist/map-v2/features/sites/index.d.ts +14 -0
- package/dist/map-v2/features/sites/index.js +16 -0
- package/dist/map-v2/features/sites/layers/SitesLayer.svelte +277 -0
- package/dist/map-v2/features/sites/layers/SitesLayer.svelte.d.ts +12 -0
- package/dist/map-v2/features/sites/stores/siteStore.d.ts +18 -0
- package/dist/map-v2/features/sites/stores/siteStore.js +36 -0
- package/dist/map-v2/features/sites/stores/siteStoreContext.svelte.d.ts +29 -0
- package/dist/map-v2/features/sites/stores/siteStoreContext.svelte.js +73 -0
- package/dist/map-v2/features/sites/types.d.ts +36 -0
- package/dist/map-v2/features/sites/types.js +4 -0
- package/dist/map-v2/features/sites/utils/siteGeoJSON.d.ts +31 -0
- package/dist/map-v2/features/sites/utils/siteGeoJSON.js +34 -0
- package/dist/map-v2/features/sites/utils/siteTreeUtils.d.ts +14 -0
- package/dist/{map → map-v2/features/sites}/utils/siteTreeUtils.js +3 -50
- package/dist/map-v2/index.d.ts +10 -0
- package/dist/map-v2/index.js +22 -0
- package/dist/{map → map-v2/shared}/controls/MapControl.svelte +1 -1
- package/dist/map-v2/shared/index.d.ts +7 -0
- package/dist/map-v2/shared/index.js +9 -0
- package/package.json +1 -1
- package/dist/map/demo/DemoMap.svelte +0 -98
- package/dist/map/demo/demo-data.d.ts +0 -12
- package/dist/map/demo/demo-data.js +0 -220
- package/dist/map/hooks/useCellData.d.ts +0 -14
- package/dist/map/hooks/useCellData.js +0 -29
- package/dist/map/index.d.ts +0 -27
- package/dist/map/index.js +0 -47
- package/dist/map/layers/CellsLayer.svelte +0 -242
- package/dist/map/layers/CellsLayer.svelte.d.ts +0 -21
- package/dist/map/layers/CoverageLayer.svelte +0 -37
- package/dist/map/layers/CoverageLayer.svelte.d.ts +0 -9
- package/dist/map/layers/LayerBase.d.ts +0 -42
- package/dist/map/layers/LayerBase.js +0 -58
- package/dist/map/layers/SitesLayer.svelte +0 -282
- package/dist/map/layers/SitesLayer.svelte.d.ts +0 -19
- package/dist/map/providers/CellDataProvider.svelte +0 -43
- package/dist/map/providers/CellDataProvider.svelte.d.ts +0 -12
- package/dist/map/providers/MapboxProvider.svelte +0 -38
- package/dist/map/providers/MapboxProvider.svelte.d.ts +0 -9
- package/dist/map/providers/providerHelpers.d.ts +0 -17
- package/dist/map/providers/providerHelpers.js +0 -26
- package/dist/map/stores/cellDataStore.d.ts +0 -21
- package/dist/map/stores/cellDataStore.js +0 -53
- package/dist/map/stores/interactions.d.ts +0 -20
- package/dist/map/stores/interactions.js +0 -33
- package/dist/map/types.d.ts +0 -115
- package/dist/map/types.js +0 -10
- package/dist/map/utils/geojson.d.ts +0 -20
- package/dist/map/utils/geojson.js +0 -78
- package/dist/map/utils/math.d.ts +0 -40
- package/dist/map/utils/math.js +0 -95
- package/dist/map/utils/siteTreeUtils.d.ts +0 -27
- /package/dist/{map → map-v2/shared}/controls/MapControl.svelte.d.ts +0 -0
- /package/dist/{map → map-v2/shared}/utils/mapboxHelpers.d.ts +0 -0
- /package/dist/{map → map-v2/shared}/utils/mapboxHelpers.js +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo cellular data for testing map-v2 site feature
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sample cellular sites (San Francisco area)
|
|
6
|
+
*/
|
|
7
|
+
export const demoSites = [
|
|
8
|
+
{
|
|
9
|
+
id: 'site-001',
|
|
10
|
+
name: 'Downtown Tower',
|
|
11
|
+
longitude: -122.4194,
|
|
12
|
+
latitude: 37.7749,
|
|
13
|
+
fbands: ['2100', '1800'],
|
|
14
|
+
technology: '5G',
|
|
15
|
+
properties: {
|
|
16
|
+
height: 45,
|
|
17
|
+
type: 'macro'
|
|
18
|
+
},
|
|
19
|
+
cellNames: ['cell-001-1', 'cell-001-2', 'cell-001-3'],
|
|
20
|
+
provider: 'Verizon',
|
|
21
|
+
featureGroup: 'Urban Macro'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'site-002',
|
|
25
|
+
name: 'Financial District',
|
|
26
|
+
longitude: -122.4008,
|
|
27
|
+
latitude: 37.7946,
|
|
28
|
+
fbands: ['1800', '850'],
|
|
29
|
+
technology: 'LTE',
|
|
30
|
+
properties: {
|
|
31
|
+
height: 60,
|
|
32
|
+
type: 'macro'
|
|
33
|
+
},
|
|
34
|
+
cellNames: ['cell-002-1', 'cell-002-2', 'cell-002-3'],
|
|
35
|
+
provider: 'AT&T',
|
|
36
|
+
featureGroup: 'Urban Macro'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'site-003',
|
|
40
|
+
name: 'Mission Bay',
|
|
41
|
+
longitude: -122.3912,
|
|
42
|
+
latitude: 37.7699,
|
|
43
|
+
fbands: ['2600'],
|
|
44
|
+
technology: '5G',
|
|
45
|
+
properties: {
|
|
46
|
+
height: 30,
|
|
47
|
+
type: 'micro'
|
|
48
|
+
},
|
|
49
|
+
cellNames: ['cell-003-1', 'cell-003-2'],
|
|
50
|
+
provider: 'T-Mobile',
|
|
51
|
+
featureGroup: 'Small Cell'
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'site-004',
|
|
55
|
+
name: 'Golden Gate Park',
|
|
56
|
+
longitude: -122.4862,
|
|
57
|
+
latitude: 37.7694,
|
|
58
|
+
fbands: ['850', '700'],
|
|
59
|
+
technology: 'LTE',
|
|
60
|
+
properties: {
|
|
61
|
+
height: 40,
|
|
62
|
+
type: 'macro'
|
|
63
|
+
},
|
|
64
|
+
cellNames: ['cell-004-1', 'cell-004-2', 'cell-004-3'],
|
|
65
|
+
provider: 'Verizon',
|
|
66
|
+
featureGroup: 'Rural Macro'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'site-005',
|
|
70
|
+
name: 'Presidio Heights',
|
|
71
|
+
longitude: -122.4545,
|
|
72
|
+
latitude: 37.7881,
|
|
73
|
+
fbands: ['2100', '850'],
|
|
74
|
+
technology: '5G',
|
|
75
|
+
properties: {
|
|
76
|
+
height: 35,
|
|
77
|
+
type: 'macro'
|
|
78
|
+
},
|
|
79
|
+
cellNames: ['cell-005-1', 'cell-005-2', 'cell-005-3'],
|
|
80
|
+
provider: 'AT&T',
|
|
81
|
+
featureGroup: 'Suburban Macro'
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'site-006',
|
|
85
|
+
name: 'Castro District',
|
|
86
|
+
longitude: -122.4352,
|
|
87
|
+
latitude: 37.7609,
|
|
88
|
+
fbands: ['1800'],
|
|
89
|
+
technology: 'LTE',
|
|
90
|
+
properties: {
|
|
91
|
+
height: 25,
|
|
92
|
+
type: 'micro'
|
|
93
|
+
},
|
|
94
|
+
cellNames: ['cell-006-1', 'cell-006-2'],
|
|
95
|
+
provider: 'T-Mobile',
|
|
96
|
+
featureGroup: 'Small Cell'
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'site-007',
|
|
100
|
+
name: 'Embarcadero',
|
|
101
|
+
longitude: -122.3959,
|
|
102
|
+
latitude: 37.7956,
|
|
103
|
+
fbands: ['2600', '2100'],
|
|
104
|
+
technology: '5G',
|
|
105
|
+
properties: {
|
|
106
|
+
height: 50,
|
|
107
|
+
type: 'macro'
|
|
108
|
+
},
|
|
109
|
+
cellNames: ['cell-007-1', 'cell-007-2', 'cell-007-3'],
|
|
110
|
+
provider: 'Verizon',
|
|
111
|
+
featureGroup: 'Urban Macro'
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'site-008',
|
|
115
|
+
name: 'Sunset District',
|
|
116
|
+
longitude: -122.4944,
|
|
117
|
+
latitude: 37.7599,
|
|
118
|
+
fbands: ['850', '700'],
|
|
119
|
+
technology: 'LTE',
|
|
120
|
+
properties: {
|
|
121
|
+
height: 38,
|
|
122
|
+
type: 'macro'
|
|
123
|
+
},
|
|
124
|
+
cellNames: ['cell-008-1', 'cell-008-2', 'cell-008-3'],
|
|
125
|
+
provider: 'AT&T',
|
|
126
|
+
featureGroup: 'Suburban Macro'
|
|
127
|
+
}
|
|
128
|
+
];
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* SiteFilterControl - TreeView-based site filtering control
|
|
3
|
+
* SiteFilterControl - TreeView-based site filtering control
|
|
4
4
|
*
|
|
5
5
|
* Displays a hierarchical tree: All Sites -> Provider -> Feature Group
|
|
6
|
-
*
|
|
6
|
+
* Updates siteStore.filteredSites based on checked state
|
|
7
|
+
* Persists state to localStorage
|
|
7
8
|
*
|
|
8
9
|
* Usage:
|
|
9
|
-
* <SiteFilterControl
|
|
10
|
-
* {sites}
|
|
11
|
-
* bind:filteredSites
|
|
12
|
-
* position="top-left"
|
|
13
|
-
* />
|
|
10
|
+
* <SiteFilterControl {store} position="top-left" />
|
|
14
11
|
*/
|
|
15
12
|
import { onMount } from 'svelte';
|
|
16
13
|
import type { Writable } from 'svelte/store';
|
|
17
|
-
import MapControl from '
|
|
18
|
-
import TreeView from '
|
|
19
|
-
import { createTreeStore } from '
|
|
20
|
-
import { buildSiteTree, getFilteredSites
|
|
21
|
-
import type {
|
|
22
|
-
import type { TreeStoreValue } from '
|
|
14
|
+
import MapControl from '../../../shared/controls/MapControl.svelte';
|
|
15
|
+
import TreeView from '../../../../core/TreeView/TreeView.svelte';
|
|
16
|
+
import { createTreeStore } from '../../../../core/TreeView/tree.store';
|
|
17
|
+
import { buildSiteTree, getFilteredSites } from '../utils/siteTreeUtils';
|
|
18
|
+
import type { SiteStoreContext } from '../stores/siteStoreContext.svelte';
|
|
19
|
+
import type { TreeStoreValue } from '../../../../core/TreeView/tree.model';
|
|
23
20
|
|
|
24
21
|
interface Props {
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
/** Filtered sites output */
|
|
28
|
-
filteredSites?: Site[];
|
|
22
|
+
/** Site store instance */
|
|
23
|
+
store: SiteStoreContext;
|
|
29
24
|
/** Control position on map */
|
|
30
25
|
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
31
26
|
/** Control title */
|
|
@@ -35,27 +30,20 @@
|
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
let {
|
|
38
|
-
|
|
39
|
-
filteredSites = $bindable([]),
|
|
33
|
+
store,
|
|
40
34
|
position = 'top-left',
|
|
41
35
|
title = 'Site Filter',
|
|
42
36
|
initiallyCollapsed = false
|
|
43
37
|
}: Props = $props();
|
|
44
38
|
|
|
45
39
|
let treeStore = $state<Writable<TreeStoreValue> | null>(null);
|
|
46
|
-
|
|
47
|
-
// Initialize filteredSites with all sites immediately
|
|
48
|
-
if (filteredSites.length === 0 && sites.length > 0) {
|
|
49
|
-
filteredSites = [...sites];
|
|
50
|
-
}
|
|
51
40
|
|
|
52
|
-
// Build tree and create store when sites change (run only once on mount)
|
|
53
41
|
onMount(() => {
|
|
54
|
-
console.log('SiteFilterControl: Mounted with',
|
|
42
|
+
console.log('SiteFilterControl: Mounted with', store.allSites.length, 'sites');
|
|
55
43
|
|
|
56
|
-
if (
|
|
44
|
+
if (store.allSites.length > 0) {
|
|
57
45
|
console.log('SiteFilterControl: Building tree...');
|
|
58
|
-
const treeNodes = buildSiteTree(
|
|
46
|
+
const treeNodes = buildSiteTree(store.allSites);
|
|
59
47
|
|
|
60
48
|
treeStore = createTreeStore({
|
|
61
49
|
nodes: [treeNodes],
|
|
@@ -66,19 +54,17 @@
|
|
|
66
54
|
|
|
67
55
|
console.log('SiteFilterControl: Tree store created');
|
|
68
56
|
|
|
69
|
-
// Subscribe to tree changes and update
|
|
57
|
+
// Subscribe to tree changes and update siteStore
|
|
70
58
|
if (treeStore) {
|
|
71
|
-
const unsub = treeStore.subscribe((
|
|
72
|
-
const checkedPaths =
|
|
59
|
+
const unsub = treeStore.subscribe((treeValue: TreeStoreValue) => {
|
|
60
|
+
const checkedPaths = treeValue.getCheckedPaths();
|
|
73
61
|
console.log('TreeStore updated, checked paths:', checkedPaths);
|
|
74
62
|
|
|
75
|
-
const newFilteredSites = getFilteredSites(checkedPaths,
|
|
76
|
-
console.log('Filtered sites count:', newFilteredSites.length, 'of',
|
|
77
|
-
|
|
78
|
-
filteredSites = newFilteredSites;
|
|
63
|
+
const newFilteredSites = getFilteredSites(checkedPaths, store.allSites);
|
|
64
|
+
console.log('Filtered sites count:', newFilteredSites.length, 'of', store.allSites.length);
|
|
79
65
|
|
|
80
|
-
//
|
|
81
|
-
|
|
66
|
+
// Update the site store directly
|
|
67
|
+
store.filteredSites = newFilteredSites;
|
|
82
68
|
});
|
|
83
69
|
|
|
84
70
|
return () => unsub();
|
|
@@ -92,11 +78,11 @@
|
|
|
92
78
|
<div class="site-filter-tree">
|
|
93
79
|
<TreeView store={$treeStore} showControls={false} />
|
|
94
80
|
|
|
95
|
-
|
|
81
|
+
<div class="site-filter-stats">
|
|
96
82
|
<small class="text-muted">
|
|
97
|
-
Showing {filteredSites.length} of {
|
|
83
|
+
Showing {store.filteredSites.length} of {store.allSites.length} sites
|
|
98
84
|
</small>
|
|
99
|
-
</div>
|
|
85
|
+
</div>
|
|
100
86
|
</div>
|
|
101
87
|
{:else}
|
|
102
88
|
<div class="text-muted small">Loading sites...</div>
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SiteStoreContext } from '../stores/siteStoreContext.svelte';
|
|
2
2
|
interface Props {
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
/** Filtered sites output */
|
|
6
|
-
filteredSites?: Site[];
|
|
3
|
+
/** Site store instance */
|
|
4
|
+
store: SiteStoreContext;
|
|
7
5
|
/** Control position on map */
|
|
8
6
|
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
9
7
|
/** Control title */
|
|
@@ -11,6 +9,6 @@ interface Props {
|
|
|
11
9
|
/** Initially collapsed? */
|
|
12
10
|
initiallyCollapsed?: boolean;
|
|
13
11
|
}
|
|
14
|
-
declare const SiteFilterControl: import("svelte").Component<Props, {}, "
|
|
12
|
+
declare const SiteFilterControl: import("svelte").Component<Props, {}, "">;
|
|
15
13
|
type SiteFilterControl = ReturnType<typeof SiteFilterControl>;
|
|
16
14
|
export default SiteFilterControl;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SiteSizeSlider - Control for adjusting site circle size
|
|
4
|
+
*
|
|
5
|
+
* Updates siteStore properties to control the display of site circles
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* <SiteSizeSlider {store} position="top-right" />
|
|
9
|
+
*/
|
|
10
|
+
import MapControl from '../../../shared/controls/MapControl.svelte';
|
|
11
|
+
import type { SiteStoreContext } from '../stores/siteStoreContext.svelte';
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
/** Site store instance */
|
|
15
|
+
store: SiteStoreContext;
|
|
16
|
+
/** Control position on map */
|
|
17
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
18
|
+
/** Control title */
|
|
19
|
+
title?: string;
|
|
20
|
+
/** Initially collapsed? */
|
|
21
|
+
initiallyCollapsed?: boolean;
|
|
22
|
+
/** Minimum size (default: 2) */
|
|
23
|
+
min?: number;
|
|
24
|
+
/** Maximum size (default: 20) */
|
|
25
|
+
max?: number;
|
|
26
|
+
/** Step increment (default: 1) */
|
|
27
|
+
step?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let {
|
|
31
|
+
store,
|
|
32
|
+
position = 'top-right',
|
|
33
|
+
title = 'Site Size',
|
|
34
|
+
initiallyCollapsed = false,
|
|
35
|
+
min = 2,
|
|
36
|
+
max = 20,
|
|
37
|
+
step = 1
|
|
38
|
+
}: Props = $props();
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<MapControl {position} {title} collapsible={true} {initiallyCollapsed}>
|
|
42
|
+
<div class="site-size-controls">
|
|
43
|
+
<!-- Size slider -->
|
|
44
|
+
<div class="control-row">
|
|
45
|
+
<label for="site-size-slider" class="control-label">
|
|
46
|
+
Circle Radius: <strong>{store.size}px</strong>
|
|
47
|
+
</label>
|
|
48
|
+
<input
|
|
49
|
+
id="site-size-slider"
|
|
50
|
+
type="range"
|
|
51
|
+
class="form-range"
|
|
52
|
+
{min}
|
|
53
|
+
{max}
|
|
54
|
+
{step}
|
|
55
|
+
bind:value={store.size}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<!-- Opacity slider -->
|
|
60
|
+
<div class="control-row">
|
|
61
|
+
<label for="site-opacity-slider" class="control-label">
|
|
62
|
+
Opacity: <strong>{Math.round(store.opacity * 100)}%</strong>
|
|
63
|
+
</label>
|
|
64
|
+
<input
|
|
65
|
+
id="site-opacity-slider"
|
|
66
|
+
type="range"
|
|
67
|
+
class="form-range"
|
|
68
|
+
min="0"
|
|
69
|
+
max="1"
|
|
70
|
+
step="0.1"
|
|
71
|
+
bind:value={store.opacity}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<!-- Circle Color -->
|
|
76
|
+
<div class="control-row">
|
|
77
|
+
<label for="site-color-picker" class="control-label">
|
|
78
|
+
Circle Color
|
|
79
|
+
</label>
|
|
80
|
+
<input
|
|
81
|
+
id="site-color-picker"
|
|
82
|
+
type="color"
|
|
83
|
+
class="form-control-color"
|
|
84
|
+
bind:value={store.color}
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<!-- Show labels checkbox -->
|
|
89
|
+
<div class="control-row">
|
|
90
|
+
<label for="site-show-labels" class="control-label">
|
|
91
|
+
Show Labels
|
|
92
|
+
</label>
|
|
93
|
+
<div class="form-check">
|
|
94
|
+
<input
|
|
95
|
+
id="site-show-labels"
|
|
96
|
+
type="checkbox"
|
|
97
|
+
class="form-check-input"
|
|
98
|
+
bind:checked={store.showLabels}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<!-- Label size slider (only visible when labels are shown) -->
|
|
104
|
+
{#if store.showLabels}
|
|
105
|
+
<div class="control-row">
|
|
106
|
+
<label for="label-size-slider" class="control-label">
|
|
107
|
+
Label Size: <strong>{store.labelSize}px</strong>
|
|
108
|
+
</label>
|
|
109
|
+
<input
|
|
110
|
+
id="label-size-slider"
|
|
111
|
+
type="range"
|
|
112
|
+
class="form-range"
|
|
113
|
+
min="8"
|
|
114
|
+
max="20"
|
|
115
|
+
step="1"
|
|
116
|
+
bind:value={store.labelSize}
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<!-- Label color picker -->
|
|
121
|
+
<div class="control-row">
|
|
122
|
+
<label for="label-color-picker" class="control-label">
|
|
123
|
+
Label Color
|
|
124
|
+
</label>
|
|
125
|
+
<input
|
|
126
|
+
id="label-color-picker"
|
|
127
|
+
type="color"
|
|
128
|
+
class="form-control-color"
|
|
129
|
+
bind:value={store.labelColor}
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
{/if}
|
|
133
|
+
</div>
|
|
134
|
+
</MapControl>
|
|
135
|
+
|
|
136
|
+
<style>
|
|
137
|
+
.site-size-controls {
|
|
138
|
+
width: 100%;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.control-row {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
margin-bottom: 12px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.control-row:last-child {
|
|
149
|
+
margin-bottom: 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.control-label {
|
|
153
|
+
width: 110px;
|
|
154
|
+
flex-shrink: 0;
|
|
155
|
+
font-size: 12px;
|
|
156
|
+
color: #555;
|
|
157
|
+
margin: 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.form-range {
|
|
161
|
+
flex: 1;
|
|
162
|
+
min-width: 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.form-check {
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
flex: 1;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.form-check-input {
|
|
172
|
+
cursor: pointer;
|
|
173
|
+
margin: 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.form-control-color {
|
|
177
|
+
flex: 1;
|
|
178
|
+
min-width: 0;
|
|
179
|
+
height: 32px;
|
|
180
|
+
padding: 2px;
|
|
181
|
+
border: 1px solid #dee2e6;
|
|
182
|
+
border-radius: 4px;
|
|
183
|
+
cursor: pointer;
|
|
184
|
+
}
|
|
185
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SiteStoreContext } from '../stores/siteStoreContext.svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Site store instance */
|
|
4
|
+
store: SiteStoreContext;
|
|
5
|
+
/** Control position on map */
|
|
6
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
7
|
+
/** Control title */
|
|
8
|
+
title?: string;
|
|
9
|
+
/** Initially collapsed? */
|
|
10
|
+
initiallyCollapsed?: boolean;
|
|
11
|
+
/** Minimum size (default: 2) */
|
|
12
|
+
min?: number;
|
|
13
|
+
/** Maximum size (default: 20) */
|
|
14
|
+
max?: number;
|
|
15
|
+
/** Step increment (default: 1) */
|
|
16
|
+
step?: number;
|
|
17
|
+
}
|
|
18
|
+
declare const SiteSizeSlider: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type SiteSizeSlider = ReturnType<typeof SiteSizeSlider>;
|
|
20
|
+
export default SiteSizeSlider;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site Feature - Public API
|
|
3
|
+
*
|
|
4
|
+
* Exports all site-related types, stores, components, and utilities
|
|
5
|
+
*/
|
|
6
|
+
export type { Site, SiteStoreValue } from './types';
|
|
7
|
+
export type { SiteStoreContext } from './stores/siteStoreContext.svelte';
|
|
8
|
+
export { createSiteStore } from './stores/siteStore';
|
|
9
|
+
export { createSiteStoreContext } from './stores/siteStoreContext.svelte';
|
|
10
|
+
export { default as SitesLayer } from './layers/SitesLayer.svelte';
|
|
11
|
+
export { default as SiteFilterControl } from './controls/SiteFilterControl.svelte';
|
|
12
|
+
export { default as SiteSizeSlider } from './controls/SiteSizeSlider.svelte';
|
|
13
|
+
export { sitesToGeoJSON, siteToFeature } from './utils/siteGeoJSON';
|
|
14
|
+
export { buildSiteTree, getFilteredSites } from './utils/siteTreeUtils';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site Feature - Public API
|
|
3
|
+
*
|
|
4
|
+
* Exports all site-related types, stores, components, and utilities
|
|
5
|
+
*/
|
|
6
|
+
// Store
|
|
7
|
+
export { createSiteStore } from './stores/siteStore';
|
|
8
|
+
export { createSiteStoreContext } from './stores/siteStoreContext.svelte';
|
|
9
|
+
// Layers
|
|
10
|
+
export { default as SitesLayer } from './layers/SitesLayer.svelte';
|
|
11
|
+
// Controls
|
|
12
|
+
export { default as SiteFilterControl } from './controls/SiteFilterControl.svelte';
|
|
13
|
+
export { default as SiteSizeSlider } from './controls/SiteSizeSlider.svelte';
|
|
14
|
+
// Utils
|
|
15
|
+
export { sitesToGeoJSON, siteToFeature } from './utils/siteGeoJSON';
|
|
16
|
+
export { buildSiteTree, getFilteredSites } from './utils/siteTreeUtils';
|