@smartnet360/svelte-components 0.0.84 → 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.
- package/dist/apps/antenna-pattern/components/AntennaControls.svelte +1 -106
- package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +0 -36
- package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +0 -2
- package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +0 -22
- package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +0 -2
- package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +0 -2
- package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +0 -2
- package/dist/apps/site-check/SiteCheck.svelte +60 -80
- package/dist/apps/site-check/data-loader.d.ts +9 -6
- package/dist/apps/site-check/data-loader.js +2 -11
- package/dist/apps/site-check/helper.d.ts +3 -2
- package/dist/apps/site-check/helper.js +7 -5
- package/dist/apps/site-check/index.d.ts +1 -1
- package/dist/apps/site-check/transforms.d.ts +4 -2
- package/dist/apps/site-check/transforms.js +49 -10
- package/dist/core/Charts/GlobalControls.svelte +0 -4
- package/dist/core/Desktop/Grid/ResizeHandle.svelte +0 -7
- package/dist/core/Desktop/Grid/resizeStore.js +0 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/map-v2/demo/DemoMap.svelte +0 -2
- package/dist/map-v2/demo/demo-cells.js +0 -1
- package/dist/map-v2/features/cells/layers/CellsLayer.svelte +7 -26
- package/dist/map-v2/features/cells/utils/cellTree.js +0 -29
- package/dist/map-v2/features/repeaters/layers/RepeaterLabelsLayer.svelte +3 -27
- package/dist/map-v2/features/repeaters/layers/RepeatersLayer.svelte +8 -25
- package/dist/map-v2/features/repeaters/utils/repeaterTree.js +0 -6
- package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +0 -8
- package/dist/map-v2/features/sites/utils/siteTreeUtils.js +0 -6
- package/dist/map-v3/core/components/Map.svelte +89 -0
- package/dist/map-v3/core/components/Map.svelte.d.ts +13 -0
- package/dist/map-v3/core/controls/FeatureSettingsControl.svelte +103 -0
- package/dist/map-v3/core/controls/FeatureSettingsControl.svelte.d.ts +15 -0
- package/dist/map-v3/core/controls/MapStyleControl.svelte +271 -0
- package/dist/map-v3/core/controls/MapStyleControl.svelte.d.ts +28 -0
- package/dist/map-v3/core/index.d.ts +3 -0
- package/dist/map-v3/core/index.js +3 -0
- package/dist/map-v3/core/stores/map.store.svelte.d.ts +8 -0
- package/dist/map-v3/core/stores/map.store.svelte.js +29 -0
- package/dist/map-v3/core/stores/viewport.store.svelte.d.ts +38 -0
- package/dist/map-v3/core/stores/viewport.store.svelte.js +107 -0
- package/dist/map-v3/demo/DemoMap.svelte +104 -0
- package/dist/map-v3/demo/DemoMap.svelte.d.ts +6 -0
- package/dist/map-v3/demo/demo-cells.d.ts +13 -0
- package/dist/map-v3/demo/demo-cells.js +130 -0
- package/dist/map-v3/demo/demo-data.d.ts +8 -0
- package/dist/map-v3/demo/demo-data.js +104 -0
- package/dist/map-v3/demo/demo-repeaters.d.ts +13 -0
- package/dist/map-v3/demo/demo-repeaters.js +73 -0
- package/dist/map-v3/features/cells/components/CellFilterControl.svelte +208 -0
- package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte +229 -0
- package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/cells/constants.d.ts +18 -0
- package/dist/map-v3/features/cells/constants.js +37 -0
- package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +230 -0
- package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/cells/layers/CellsLayer.svelte +194 -0
- package/dist/map-v3/features/cells/layers/CellsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/cells/layers/index.d.ts +2 -0
- package/dist/map-v3/features/cells/layers/index.js +2 -0
- package/dist/map-v3/features/cells/logic/geometry.d.ts +12 -0
- package/dist/map-v3/features/cells/logic/geometry.js +35 -0
- package/dist/map-v3/features/cells/logic/grouping.d.ts +18 -0
- package/dist/map-v3/features/cells/logic/grouping.js +30 -0
- package/dist/map-v3/features/cells/logic/tree-adapter.d.ts +11 -0
- package/dist/map-v3/features/cells/logic/tree-adapter.js +53 -0
- package/dist/map-v3/features/cells/stores/cell.data.svelte.d.ts +9 -0
- package/dist/map-v3/features/cells/stores/cell.data.svelte.js +16 -0
- package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +25 -0
- package/dist/map-v3/features/cells/stores/cell.display.svelte.js +67 -0
- package/dist/map-v3/features/cells/stores/cell.registry.svelte.d.ts +23 -0
- package/dist/map-v3/features/cells/stores/cell.registry.svelte.js +68 -0
- package/dist/map-v3/features/cells/types.d.ts +62 -0
- package/dist/map-v3/features/cells/types.js +6 -0
- package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +148 -0
- package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte +209 -0
- package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +177 -0
- package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte +163 -0
- package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/repeaters/logic/geometry.d.ts +3 -0
- package/dist/map-v3/features/repeaters/logic/geometry.js +23 -0
- package/dist/map-v3/features/repeaters/logic/grouping.d.ts +8 -0
- package/dist/map-v3/features/repeaters/logic/grouping.js +20 -0
- package/dist/map-v3/features/repeaters/logic/tree-adapter.d.ts +8 -0
- package/dist/map-v3/features/repeaters/logic/tree-adapter.js +43 -0
- package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.d.ts +8 -0
- package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.js +13 -0
- package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.d.ts +21 -0
- package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.js +64 -0
- package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.d.ts +23 -0
- package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.js +68 -0
- package/dist/map-v3/features/repeaters/types.d.ts +18 -0
- package/dist/map-v3/features/repeaters/types.js +1 -0
- package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +119 -0
- package/dist/map-v3/features/sites/components/SiteFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte +241 -0
- package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +152 -0
- package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/sites/layers/SitesLayer.svelte +132 -0
- package/dist/map-v3/features/sites/layers/SitesLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/sites/logic/tree-adapter.d.ts +9 -0
- package/dist/map-v3/features/sites/logic/tree-adapter.js +75 -0
- package/dist/map-v3/features/sites/stores/site.data.svelte.d.ts +8 -0
- package/dist/map-v3/features/sites/stores/site.data.svelte.js +40 -0
- package/dist/map-v3/features/sites/stores/site.display.svelte.d.ts +20 -0
- package/dist/map-v3/features/sites/stores/site.display.svelte.js +63 -0
- package/dist/map-v3/features/sites/stores/site.registry.svelte.d.ts +13 -0
- package/dist/map-v3/features/sites/stores/site.registry.svelte.js +83 -0
- package/dist/map-v3/features/sites/types.d.ts +12 -0
- package/dist/map-v3/features/sites/types.js +1 -0
- package/dist/map-v3/index.d.ts +26 -0
- package/dist/map-v3/index.js +31 -0
- package/dist/map-v3/shared/controls/MapControl.svelte +242 -0
- package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +27 -0
- package/dist/map-v3/shared/index.d.ts +1 -0
- package/dist/map-v3/shared/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy, untrack } from 'svelte';
|
|
3
|
+
import { MapControl } from '../../../shared';
|
|
4
|
+
import { createTreeStore } from '../../../../core/TreeView/tree.store';
|
|
5
|
+
import TreeView from '../../../../core/TreeView/TreeView.svelte';
|
|
6
|
+
import type { CellDataStore } from '../stores/cell.data.svelte';
|
|
7
|
+
import type { CellRegistry } from '../stores/cell.registry.svelte';
|
|
8
|
+
import type { CellDisplayStore } from '../stores/cell.display.svelte';
|
|
9
|
+
import type { CellGroupingField } from '../types';
|
|
10
|
+
import { buildCellTree } from '../logic/tree-adapter';
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
dataStore: CellDataStore;
|
|
14
|
+
registry: CellRegistry;
|
|
15
|
+
displayStore: CellDisplayStore;
|
|
16
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let { dataStore, registry, displayStore, position = 'top-left' }: Props = $props();
|
|
20
|
+
|
|
21
|
+
// Local State for Grouping
|
|
22
|
+
// let level1 = $state<CellGroupingField>('tech');
|
|
23
|
+
// let level2 = $state<CellGroupingField>('fband');
|
|
24
|
+
let includePlanned = $state(false);
|
|
25
|
+
|
|
26
|
+
const level1Options: CellGroupingField[] = ['tech', 'status', 'siteId'];
|
|
27
|
+
const level2Options: CellGroupingField[] = ['fband', 'frq', 'status', 'none'];
|
|
28
|
+
|
|
29
|
+
// Sync includePlanned with dataStore
|
|
30
|
+
$effect(() => {
|
|
31
|
+
// If includePlanned is true, we show ALL (filterOnAir = false)
|
|
32
|
+
// If includePlanned is false, we show ONLY On Air (filterOnAir = true)
|
|
33
|
+
dataStore.filterOnAir = !includePlanned;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Create Tree Store
|
|
37
|
+
// We recreate it whenever the cell data changes significantly (e.g. new file loaded)
|
|
38
|
+
// or when grouping configuration changes.
|
|
39
|
+
// We use untrack() to avoid recreating the tree when the registry changes (visibility toggles),
|
|
40
|
+
// as the tree itself drives those changes.
|
|
41
|
+
let treeStore = $derived.by(() => {
|
|
42
|
+
const _cells = dataStore.filteredCells;
|
|
43
|
+
const _l1 = displayStore.level1;
|
|
44
|
+
const _l2 = displayStore.level2;
|
|
45
|
+
|
|
46
|
+
return untrack(() => {
|
|
47
|
+
const nodes = buildCellTree(_cells, registry, _l1, _l2);
|
|
48
|
+
return createTreeStore({
|
|
49
|
+
nodes,
|
|
50
|
+
namespace: `${registry.namespace}:tree:${_l1}:${_l2}`,
|
|
51
|
+
persistState: true,
|
|
52
|
+
defaultExpandAll: true
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Sync Tree Selection -> Cell Registry Visibility
|
|
58
|
+
$effect(() => {
|
|
59
|
+
const unsubscribe = treeStore.subscribe((val) => {
|
|
60
|
+
// Iterate all leaf nodes to sync visibility
|
|
61
|
+
// This is a bit heavy but ensures consistency.
|
|
62
|
+
// Optimization: Only update changed nodes if we had a diff.
|
|
63
|
+
|
|
64
|
+
// We only care about leaf nodes (bands)
|
|
65
|
+
let changes = 0;
|
|
66
|
+
val.state.nodes.forEach((nodeState) => {
|
|
67
|
+
if (nodeState.node.children && nodeState.node.children.length > 0) return; // Skip folders
|
|
68
|
+
|
|
69
|
+
const groupId = nodeState.node.id;
|
|
70
|
+
// IMPORTANT: Read from checkedPaths set, NOT nodeState.checked (which is static/stale)
|
|
71
|
+
const isVisible = val.state.checkedPaths.has(nodeState.path);
|
|
72
|
+
|
|
73
|
+
// Update registry if different
|
|
74
|
+
const currentStyle = registry.getStyle(groupId, '#000'); // Color doesn't matter here
|
|
75
|
+
if (currentStyle.visible !== isVisible) {
|
|
76
|
+
// console.log(`[CellFilterControl] Syncing ${groupId}: ${currentStyle.visible} -> ${isVisible}`);
|
|
77
|
+
registry.toggleVisibility(groupId);
|
|
78
|
+
changes++;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
if (changes > 0) {
|
|
82
|
+
console.log(`[CellFilterControl] Synced ${changes} visibility changes to registry`);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return () => {
|
|
87
|
+
unsubscribe();
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
function handleColorChange(groupId: string, event: Event) {
|
|
92
|
+
const input = event.target as HTMLInputElement;
|
|
93
|
+
registry.setColor(groupId, input.value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getFieldLabel(field: string): string {
|
|
97
|
+
const labels: Record<string, string> = {
|
|
98
|
+
tech: 'Technology',
|
|
99
|
+
fband: 'Tech + Band',
|
|
100
|
+
frq: 'Frequency',
|
|
101
|
+
status: 'Status',
|
|
102
|
+
siteId: 'Site ID',
|
|
103
|
+
none: 'None'
|
|
104
|
+
};
|
|
105
|
+
return labels[field] || field;
|
|
106
|
+
}
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<MapControl {position} title="Layers" icon="radioactive" controlWidth="320px">
|
|
110
|
+
<div class="cell-filter-control">
|
|
111
|
+
<!-- Status Filter Checkbox -->
|
|
112
|
+
<div class="mb-3 px-1">
|
|
113
|
+
<div class="form-check">
|
|
114
|
+
<input
|
|
115
|
+
type="checkbox"
|
|
116
|
+
class="form-check-input"
|
|
117
|
+
id="includePlanned"
|
|
118
|
+
bind:checked={includePlanned}
|
|
119
|
+
/>
|
|
120
|
+
<label class="form-check-label small" for="includePlanned">
|
|
121
|
+
Include Planned Cells
|
|
122
|
+
<span class="text-muted ms-1">
|
|
123
|
+
({includePlanned ? 'All cells' : 'On Air only'})
|
|
124
|
+
</span>
|
|
125
|
+
</label>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<!-- Grouping Configuration -->
|
|
130
|
+
<div class="grouping-config mb-3 pb-2 border-bottom">
|
|
131
|
+
<div class="row g-2">
|
|
132
|
+
<!-- Level 1 Grouping -->
|
|
133
|
+
<div class="col-6">
|
|
134
|
+
<label for="level1-select" class="form-label small mb-1 text-muted">Level 1</label>
|
|
135
|
+
<select
|
|
136
|
+
id="level1-select"
|
|
137
|
+
class="form-select form-select-sm"
|
|
138
|
+
bind:value={displayStore.level1}
|
|
139
|
+
>
|
|
140
|
+
{#each level1Options as option}
|
|
141
|
+
<option value={option}>{getFieldLabel(option)}</option>
|
|
142
|
+
{/each}
|
|
143
|
+
</select>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<!-- Level 2 Grouping -->
|
|
147
|
+
<div class="col-6">
|
|
148
|
+
<label for="level2-select" class="form-label small mb-1 text-muted">Level 2</label>
|
|
149
|
+
<select
|
|
150
|
+
id="level2-select"
|
|
151
|
+
class="form-select form-select-sm"
|
|
152
|
+
bind:value={displayStore.level2}
|
|
153
|
+
>
|
|
154
|
+
{#each level2Options as option}
|
|
155
|
+
<option value={option}>{getFieldLabel(option)}</option>
|
|
156
|
+
{/each}
|
|
157
|
+
</select>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<!-- Tree View -->
|
|
163
|
+
<div class="cell-filter-tree">
|
|
164
|
+
{#if dataStore.filteredCells.length === 0}
|
|
165
|
+
<div class="text-muted p-3 text-center small">
|
|
166
|
+
No cells loaded.
|
|
167
|
+
</div>
|
|
168
|
+
{:else}
|
|
169
|
+
<TreeView showControls={false} store={$treeStore} height="300px">
|
|
170
|
+
{#snippet children({ node, state })}
|
|
171
|
+
<!-- Color Picker (Only for leaves) -->
|
|
172
|
+
{#if !node.children || node.children.length === 0}
|
|
173
|
+
<div
|
|
174
|
+
class="d-flex align-items-center"
|
|
175
|
+
role="group"
|
|
176
|
+
onclick={(e) => e.stopPropagation()}
|
|
177
|
+
onkeydown={(e) => e.stopPropagation()}
|
|
178
|
+
>
|
|
179
|
+
<input
|
|
180
|
+
type="color"
|
|
181
|
+
class="form-control form-control-color form-control-sm border-0 p-0"
|
|
182
|
+
style="width: 16px; height: 16px; min-height: 0;"
|
|
183
|
+
value={node.metadata?.color}
|
|
184
|
+
oninput={(e) => handleColorChange(node.id, e)}
|
|
185
|
+
title="Change color"
|
|
186
|
+
/>
|
|
187
|
+
</div>
|
|
188
|
+
{/if}
|
|
189
|
+
{/snippet}
|
|
190
|
+
</TreeView>
|
|
191
|
+
{/if}
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<!-- Stats Footer -->
|
|
195
|
+
<!-- <div class="cell-filter-stats text-center pt-2 mt-2 border-top">
|
|
196
|
+
<small class="text-muted">
|
|
197
|
+
Showing {dataStore.filteredCells.length} of {dataStore.rawCells.length} cells
|
|
198
|
+
</small>
|
|
199
|
+
</div> -->
|
|
200
|
+
</div>
|
|
201
|
+
</MapControl>
|
|
202
|
+
|
|
203
|
+
<style>
|
|
204
|
+
.cell-filter-control {
|
|
205
|
+
background: #fff;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
}
|
|
208
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CellDataStore } from '../stores/cell.data.svelte';
|
|
2
|
+
import type { CellRegistry } from '../stores/cell.registry.svelte';
|
|
3
|
+
import type { CellDisplayStore } from '../stores/cell.display.svelte';
|
|
4
|
+
interface Props {
|
|
5
|
+
dataStore: CellDataStore;
|
|
6
|
+
registry: CellRegistry;
|
|
7
|
+
displayStore: CellDisplayStore;
|
|
8
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
9
|
+
}
|
|
10
|
+
declare const CellFilterControl: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type CellFilterControl = ReturnType<typeof CellFilterControl>;
|
|
12
|
+
export default CellFilterControl;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CellDisplayStore } from '../stores/cell.display.svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
displayStore: CellDisplayStore;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { displayStore }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div class="card border-0 shadow-sm rounded-2">
|
|
12
|
+
<div class="card-body bg-light p-3">
|
|
13
|
+
<!-- Target Pixel Size (Radius) -->
|
|
14
|
+
<div class="row align-items-center g-2 mb-3">
|
|
15
|
+
<div class="col-4 text-secondary fw-semibold small text-uppercase">Pixel Size</div>
|
|
16
|
+
<div class="col-3 text-end">
|
|
17
|
+
<span class="badge bg-white text-muted border">{displayStore.targetPixelSize}px</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="col-5">
|
|
20
|
+
<input
|
|
21
|
+
id="cell-radius-slider"
|
|
22
|
+
type="range"
|
|
23
|
+
class="form-range w-100"
|
|
24
|
+
min="10"
|
|
25
|
+
max="200"
|
|
26
|
+
step="5"
|
|
27
|
+
bind:value={displayStore.targetPixelSize}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<!-- Line Width -->
|
|
33
|
+
<div class="row align-items-center g-2 mb-3">
|
|
34
|
+
<div class="col-4 text-secondary fw-semibold small text-uppercase">Line Width</div>
|
|
35
|
+
<div class="col-3 text-end">
|
|
36
|
+
<span class="badge bg-white text-muted border">{displayStore.lineWidth}px</span>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="col-5">
|
|
39
|
+
<input
|
|
40
|
+
id="cell-line-width-slider"
|
|
41
|
+
type="range"
|
|
42
|
+
class="form-range w-100"
|
|
43
|
+
min="0.5"
|
|
44
|
+
max="5"
|
|
45
|
+
step="0.5"
|
|
46
|
+
bind:value={displayStore.lineWidth}
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- Fill Opacity -->
|
|
52
|
+
<div class="row align-items-center g-2 mb-3">
|
|
53
|
+
<div class="col-4 text-secondary fw-semibold small text-uppercase">Fill Opacity</div>
|
|
54
|
+
<div class="col-3 text-end">
|
|
55
|
+
<span class="badge bg-white text-muted border">{Math.round(displayStore.fillOpacity * 100)}%</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="col-5">
|
|
58
|
+
<input
|
|
59
|
+
id="cell-opacity-slider"
|
|
60
|
+
type="range"
|
|
61
|
+
class="form-range w-100"
|
|
62
|
+
min="0"
|
|
63
|
+
max="1"
|
|
64
|
+
step="0.1"
|
|
65
|
+
bind:value={displayStore.fillOpacity}
|
|
66
|
+
/>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="border-top my-3"></div>
|
|
71
|
+
|
|
72
|
+
<!-- Show Labels -->
|
|
73
|
+
<div class="row align-items-center g-2 mb-3">
|
|
74
|
+
<div class="col-4 text-secondary fw-semibold small text-uppercase">Show Labels</div>
|
|
75
|
+
<div class="col-3"></div>
|
|
76
|
+
<div class="col-5">
|
|
77
|
+
<div class="form-check form-switch m-0 d-flex align-items-center justify-content-end">
|
|
78
|
+
<input
|
|
79
|
+
id="cell-labels-toggle"
|
|
80
|
+
type="checkbox"
|
|
81
|
+
class="form-check-input"
|
|
82
|
+
role="switch"
|
|
83
|
+
bind:checked={displayStore.showLabels}
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
{#if displayStore.showLabels}
|
|
90
|
+
<div class="ps-3 border-start border-2 mb-3">
|
|
91
|
+
<!-- 2G Labels -->
|
|
92
|
+
<div class="mb-2">
|
|
93
|
+
<div class="text-secondary fw-semibold small text-uppercase mb-1">2G Labels</div>
|
|
94
|
+
<div class="row g-1">
|
|
95
|
+
<div class="col-6">
|
|
96
|
+
<select class="form-select form-select-sm" bind:value={displayStore.labels2G.primary}>
|
|
97
|
+
<option value="cellName">Name</option>
|
|
98
|
+
<option value="cellID">Cell ID</option>
|
|
99
|
+
<option value="bcch">BCCH</option>
|
|
100
|
+
<option value="siteId">Site ID</option>
|
|
101
|
+
</select>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="col-6">
|
|
104
|
+
<select class="form-select form-select-sm" bind:value={displayStore.labels2G.secondary}>
|
|
105
|
+
<option value="none">None</option>
|
|
106
|
+
<option value="bcch">BCCH</option>
|
|
107
|
+
<option value="cellID">Cell ID</option>
|
|
108
|
+
<option value="siteId">Site ID</option>
|
|
109
|
+
</select>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<!-- 4G/5G Labels -->
|
|
115
|
+
<div class="mb-2">
|
|
116
|
+
<div class="text-secondary fw-semibold small text-uppercase mb-1">4G/5G Labels</div>
|
|
117
|
+
<div class="row g-1">
|
|
118
|
+
<div class="col-6">
|
|
119
|
+
<select class="form-select form-select-sm" bind:value={displayStore.labels4G.primary}>
|
|
120
|
+
<option value="cellName">Name</option>
|
|
121
|
+
<option value="pci1">PCI</option>
|
|
122
|
+
<option value="dlEarfn">EARFCN</option>
|
|
123
|
+
<option value="cellID">Cell ID</option>
|
|
124
|
+
</select>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="col-6">
|
|
127
|
+
<select class="form-select form-select-sm" bind:value={displayStore.labels4G.secondary}>
|
|
128
|
+
<option value="none">None</option>
|
|
129
|
+
<option value="pci1">PCI</option>
|
|
130
|
+
<option value="dlEarfn">EARFCN</option>
|
|
131
|
+
<option value="cellID">Cell ID</option>
|
|
132
|
+
</select>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
<!-- Label Distance -->
|
|
137
|
+
<div class="row align-items-center g-2 mb-2">
|
|
138
|
+
<div class="col-4 text-secondary small">Distance</div>
|
|
139
|
+
<div class="col-3 text-end">
|
|
140
|
+
<span class="badge bg-white text-muted border">{displayStore.labelPixelDistance}px</span>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="col-5">
|
|
143
|
+
<input
|
|
144
|
+
type="range"
|
|
145
|
+
class="form-range w-100"
|
|
146
|
+
min="10"
|
|
147
|
+
max="100"
|
|
148
|
+
step="5"
|
|
149
|
+
bind:value={displayStore.labelPixelDistance}
|
|
150
|
+
/>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- Font Size -->
|
|
155
|
+
<div class="row align-items-center g-2 mb-3">
|
|
156
|
+
<div class="col-4 text-secondary small">Font Size</div>
|
|
157
|
+
<div class="col-3 text-end">
|
|
158
|
+
<span class="badge bg-white text-muted border">{displayStore.labelFontSize}px</span>
|
|
159
|
+
</div>
|
|
160
|
+
<div class="col-5">
|
|
161
|
+
<input
|
|
162
|
+
type="range"
|
|
163
|
+
class="form-range w-100"
|
|
164
|
+
min="8"
|
|
165
|
+
max="24"
|
|
166
|
+
step="1"
|
|
167
|
+
bind:value={displayStore.labelFontSize}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<!-- Label Colors -->
|
|
173
|
+
<div class="row align-items-center g-2 mb-2">
|
|
174
|
+
<div class="col-4 text-secondary small">Color</div>
|
|
175
|
+
<div class="col-8">
|
|
176
|
+
<div class="input-group input-group-sm">
|
|
177
|
+
<input
|
|
178
|
+
type="color"
|
|
179
|
+
class="form-control form-control-color"
|
|
180
|
+
bind:value={displayStore.labelColor}
|
|
181
|
+
title="Label Color"
|
|
182
|
+
/>
|
|
183
|
+
<span class="input-group-text bg-white text-muted small flex-grow-1 font-monospace">
|
|
184
|
+
{displayStore.labelColor}
|
|
185
|
+
</span>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<!-- Halo Settings -->
|
|
191
|
+
<div class="row align-items-center g-2 mb-2">
|
|
192
|
+
<div class="col-4 text-secondary small">Halo</div>
|
|
193
|
+
<div class="col-8">
|
|
194
|
+
<div class="input-group input-group-sm">
|
|
195
|
+
<input
|
|
196
|
+
type="color"
|
|
197
|
+
class="form-control form-control-color"
|
|
198
|
+
bind:value={displayStore.labelHaloColor}
|
|
199
|
+
title="Halo Color"
|
|
200
|
+
/>
|
|
201
|
+
<span class="input-group-text bg-white text-muted small flex-grow-1 font-monospace">
|
|
202
|
+
{displayStore.labelHaloColor}
|
|
203
|
+
</span>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<div class="row align-items-center g-2 mb-3">
|
|
209
|
+
<div class="col-4 text-secondary small">Halo Width</div>
|
|
210
|
+
<div class="col-3 text-end">
|
|
211
|
+
<span class="badge bg-white text-muted border">{displayStore.labelHaloWidth}px</span>
|
|
212
|
+
</div>
|
|
213
|
+
<div class="col-5">
|
|
214
|
+
<input
|
|
215
|
+
type="range"
|
|
216
|
+
class="form-range w-100"
|
|
217
|
+
min="0"
|
|
218
|
+
max="5"
|
|
219
|
+
step="0.5"
|
|
220
|
+
bind:value={displayStore.labelHaloWidth}
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
</div>
|
|
227
|
+
{/if}
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CellDisplayStore } from '../stores/cell.display.svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
displayStore: CellDisplayStore;
|
|
4
|
+
}
|
|
5
|
+
declare const CellSettingsPanel: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type CellSettingsPanel = ReturnType<typeof CellSettingsPanel>;
|
|
7
|
+
export default CellSettingsPanel;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Z-Index Layer Ordering by Technology-Band
|
|
3
|
+
*
|
|
4
|
+
* Controls which sectors appear on top when overlapping
|
|
5
|
+
* Higher frequency bands typically rendered on top
|
|
6
|
+
*/
|
|
7
|
+
import type { TechnologyBandKey } from './types';
|
|
8
|
+
export declare const Z_INDEX_BY_BAND: Record<TechnologyBandKey, number>;
|
|
9
|
+
/**
|
|
10
|
+
* Base Z-Index for Mapbox layer ordering
|
|
11
|
+
* Cells should render below sites but above base map features
|
|
12
|
+
*/
|
|
13
|
+
export declare const CELL_FILL_Z_INDEX = 100;
|
|
14
|
+
export declare const CELL_LINE_Z_INDEX = 101;
|
|
15
|
+
/**
|
|
16
|
+
* Default colors for cyclical palette
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_PALETTE: string[];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Z-Index Layer Ordering by Technology-Band
|
|
3
|
+
*
|
|
4
|
+
* Controls which sectors appear on top when overlapping
|
|
5
|
+
* Higher frequency bands typically rendered on top
|
|
6
|
+
*/
|
|
7
|
+
export const Z_INDEX_BY_BAND = {
|
|
8
|
+
// 2G bands
|
|
9
|
+
'2G_900': 3,
|
|
10
|
+
'2G_1800': 7,
|
|
11
|
+
// 4G bands
|
|
12
|
+
'4G_700': 0,
|
|
13
|
+
'4G_800': 2,
|
|
14
|
+
'4G_900': 4,
|
|
15
|
+
'4G_1800': 8,
|
|
16
|
+
'4G_2100': 9,
|
|
17
|
+
'4G_2600': 11,
|
|
18
|
+
// 5G bands
|
|
19
|
+
'5G_700': 1,
|
|
20
|
+
'5G_2100': 10,
|
|
21
|
+
'5G_3500': 14
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Base Z-Index for Mapbox layer ordering
|
|
25
|
+
* Cells should render below sites but above base map features
|
|
26
|
+
*/
|
|
27
|
+
export const CELL_FILL_Z_INDEX = 100;
|
|
28
|
+
export const CELL_LINE_Z_INDEX = 101;
|
|
29
|
+
/**
|
|
30
|
+
* Default colors for cyclical palette
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_PALETTE = [
|
|
33
|
+
'#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231',
|
|
34
|
+
'#911eb4', '#46f0f0', '#f032e6', '#bcf60c', '#fabebe',
|
|
35
|
+
'#008080', '#e6beff', '#9a6324', '#fffac8', '#800000',
|
|
36
|
+
'#aaffc3', '#808000', '#ffd8b1', '#000075', '#808080'
|
|
37
|
+
];
|