@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.
Files changed (122) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaControls.svelte +1 -106
  2. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +0 -36
  3. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +0 -2
  4. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +0 -22
  5. package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +0 -2
  6. package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +0 -2
  7. package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +0 -2
  8. package/dist/apps/site-check/SiteCheck.svelte +60 -80
  9. package/dist/apps/site-check/data-loader.d.ts +9 -6
  10. package/dist/apps/site-check/data-loader.js +2 -11
  11. package/dist/apps/site-check/helper.d.ts +3 -2
  12. package/dist/apps/site-check/helper.js +7 -5
  13. package/dist/apps/site-check/index.d.ts +1 -1
  14. package/dist/apps/site-check/transforms.d.ts +4 -2
  15. package/dist/apps/site-check/transforms.js +49 -10
  16. package/dist/core/Charts/GlobalControls.svelte +0 -4
  17. package/dist/core/Desktop/Grid/ResizeHandle.svelte +0 -7
  18. package/dist/core/Desktop/Grid/resizeStore.js +0 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/map-v2/demo/DemoMap.svelte +0 -2
  22. package/dist/map-v2/demo/demo-cells.js +0 -1
  23. package/dist/map-v2/features/cells/layers/CellsLayer.svelte +7 -26
  24. package/dist/map-v2/features/cells/utils/cellTree.js +0 -29
  25. package/dist/map-v2/features/repeaters/layers/RepeaterLabelsLayer.svelte +3 -27
  26. package/dist/map-v2/features/repeaters/layers/RepeatersLayer.svelte +8 -25
  27. package/dist/map-v2/features/repeaters/utils/repeaterTree.js +0 -6
  28. package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +0 -8
  29. package/dist/map-v2/features/sites/utils/siteTreeUtils.js +0 -6
  30. package/dist/map-v3/core/components/Map.svelte +89 -0
  31. package/dist/map-v3/core/components/Map.svelte.d.ts +13 -0
  32. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte +103 -0
  33. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte.d.ts +15 -0
  34. package/dist/map-v3/core/controls/MapStyleControl.svelte +271 -0
  35. package/dist/map-v3/core/controls/MapStyleControl.svelte.d.ts +28 -0
  36. package/dist/map-v3/core/index.d.ts +3 -0
  37. package/dist/map-v3/core/index.js +3 -0
  38. package/dist/map-v3/core/stores/map.store.svelte.d.ts +8 -0
  39. package/dist/map-v3/core/stores/map.store.svelte.js +29 -0
  40. package/dist/map-v3/core/stores/viewport.store.svelte.d.ts +38 -0
  41. package/dist/map-v3/core/stores/viewport.store.svelte.js +107 -0
  42. package/dist/map-v3/demo/DemoMap.svelte +104 -0
  43. package/dist/map-v3/demo/DemoMap.svelte.d.ts +6 -0
  44. package/dist/map-v3/demo/demo-cells.d.ts +13 -0
  45. package/dist/map-v3/demo/demo-cells.js +130 -0
  46. package/dist/map-v3/demo/demo-data.d.ts +8 -0
  47. package/dist/map-v3/demo/demo-data.js +104 -0
  48. package/dist/map-v3/demo/demo-repeaters.d.ts +13 -0
  49. package/dist/map-v3/demo/demo-repeaters.js +73 -0
  50. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +208 -0
  51. package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +12 -0
  52. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte +229 -0
  53. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte.d.ts +7 -0
  54. package/dist/map-v3/features/cells/constants.d.ts +18 -0
  55. package/dist/map-v3/features/cells/constants.js +37 -0
  56. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +230 -0
  57. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte.d.ts +11 -0
  58. package/dist/map-v3/features/cells/layers/CellsLayer.svelte +194 -0
  59. package/dist/map-v3/features/cells/layers/CellsLayer.svelte.d.ts +11 -0
  60. package/dist/map-v3/features/cells/layers/index.d.ts +2 -0
  61. package/dist/map-v3/features/cells/layers/index.js +2 -0
  62. package/dist/map-v3/features/cells/logic/geometry.d.ts +12 -0
  63. package/dist/map-v3/features/cells/logic/geometry.js +35 -0
  64. package/dist/map-v3/features/cells/logic/grouping.d.ts +18 -0
  65. package/dist/map-v3/features/cells/logic/grouping.js +30 -0
  66. package/dist/map-v3/features/cells/logic/tree-adapter.d.ts +11 -0
  67. package/dist/map-v3/features/cells/logic/tree-adapter.js +53 -0
  68. package/dist/map-v3/features/cells/stores/cell.data.svelte.d.ts +9 -0
  69. package/dist/map-v3/features/cells/stores/cell.data.svelte.js +16 -0
  70. package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +25 -0
  71. package/dist/map-v3/features/cells/stores/cell.display.svelte.js +67 -0
  72. package/dist/map-v3/features/cells/stores/cell.registry.svelte.d.ts +23 -0
  73. package/dist/map-v3/features/cells/stores/cell.registry.svelte.js +68 -0
  74. package/dist/map-v3/features/cells/types.d.ts +62 -0
  75. package/dist/map-v3/features/cells/types.js +6 -0
  76. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +148 -0
  77. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte.d.ts +12 -0
  78. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte +209 -0
  79. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte.d.ts +7 -0
  80. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +177 -0
  81. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte.d.ts +11 -0
  82. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte +163 -0
  83. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte.d.ts +11 -0
  84. package/dist/map-v3/features/repeaters/logic/geometry.d.ts +3 -0
  85. package/dist/map-v3/features/repeaters/logic/geometry.js +23 -0
  86. package/dist/map-v3/features/repeaters/logic/grouping.d.ts +8 -0
  87. package/dist/map-v3/features/repeaters/logic/grouping.js +20 -0
  88. package/dist/map-v3/features/repeaters/logic/tree-adapter.d.ts +8 -0
  89. package/dist/map-v3/features/repeaters/logic/tree-adapter.js +43 -0
  90. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.d.ts +8 -0
  91. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.js +13 -0
  92. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.d.ts +21 -0
  93. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.js +64 -0
  94. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.d.ts +23 -0
  95. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.js +68 -0
  96. package/dist/map-v3/features/repeaters/types.d.ts +18 -0
  97. package/dist/map-v3/features/repeaters/types.js +1 -0
  98. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +119 -0
  99. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte.d.ts +12 -0
  100. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte +241 -0
  101. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte.d.ts +7 -0
  102. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +152 -0
  103. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte.d.ts +11 -0
  104. package/dist/map-v3/features/sites/layers/SitesLayer.svelte +132 -0
  105. package/dist/map-v3/features/sites/layers/SitesLayer.svelte.d.ts +11 -0
  106. package/dist/map-v3/features/sites/logic/tree-adapter.d.ts +9 -0
  107. package/dist/map-v3/features/sites/logic/tree-adapter.js +75 -0
  108. package/dist/map-v3/features/sites/stores/site.data.svelte.d.ts +8 -0
  109. package/dist/map-v3/features/sites/stores/site.data.svelte.js +40 -0
  110. package/dist/map-v3/features/sites/stores/site.display.svelte.d.ts +20 -0
  111. package/dist/map-v3/features/sites/stores/site.display.svelte.js +63 -0
  112. package/dist/map-v3/features/sites/stores/site.registry.svelte.d.ts +13 -0
  113. package/dist/map-v3/features/sites/stores/site.registry.svelte.js +83 -0
  114. package/dist/map-v3/features/sites/types.d.ts +12 -0
  115. package/dist/map-v3/features/sites/types.js +1 -0
  116. package/dist/map-v3/index.d.ts +26 -0
  117. package/dist/map-v3/index.js +31 -0
  118. package/dist/map-v3/shared/controls/MapControl.svelte +242 -0
  119. package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +27 -0
  120. package/dist/map-v3/shared/index.d.ts +1 -0
  121. package/dist/map-v3/shared/index.js +1 -0
  122. 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
+ ];