@smartnet360/svelte-components 0.0.22 → 0.0.23
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/utils/msi-parser.js +18 -1
- package/dist/cellular/CellularChartsView.svelte +293 -0
- package/dist/cellular/CellularChartsView.svelte.d.ts +7 -0
- package/dist/cellular/HierarchicalTree.svelte +469 -0
- package/dist/cellular/HierarchicalTree.svelte.d.ts +9 -0
- package/dist/cellular/SiteTree.svelte +286 -0
- package/dist/cellular/SiteTree.svelte.d.ts +11 -0
- package/dist/cellular/cellular-transforms.d.ts +25 -0
- package/dist/cellular/cellular-transforms.js +129 -0
- package/dist/cellular/cellular.model.d.ts +63 -0
- package/dist/cellular/cellular.model.js +6 -0
- package/dist/cellular/index.d.ts +11 -0
- package/dist/cellular/index.js +11 -0
- package/dist/cellular/mock-cellular-data.d.ts +13 -0
- package/dist/cellular/mock-cellular-data.js +241 -0
- package/dist/core/TreeChartView/TreeChartView.svelte +208 -0
- package/dist/core/TreeChartView/TreeChartView.svelte.d.ts +42 -0
- package/dist/core/TreeChartView/index.d.ts +7 -0
- package/dist/core/TreeChartView/index.js +7 -0
- package/dist/core/TreeView/TreeNode.svelte +173 -0
- package/dist/core/TreeView/TreeNode.svelte.d.ts +10 -0
- package/dist/core/TreeView/TreeView.svelte +163 -0
- package/dist/core/TreeView/TreeView.svelte.d.ts +10 -0
- package/dist/core/TreeView/index.d.ts +48 -0
- package/dist/core/TreeView/index.js +50 -0
- package/dist/core/TreeView/tree-utils.d.ts +56 -0
- package/dist/core/TreeView/tree-utils.js +194 -0
- package/dist/core/TreeView/tree.model.d.ts +104 -0
- package/dist/core/TreeView/tree.model.js +5 -0
- package/dist/core/TreeView/tree.store.d.ts +10 -0
- package/dist/core/TreeView/tree.store.js +225 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/package.json +1 -1
@@ -0,0 +1,286 @@
|
|
1
|
+
<svelte:options runes={true} />
|
2
|
+
|
3
|
+
<script lang="ts">
|
4
|
+
import type { CellularSite, VisibilityState } from './cellular.model.js';
|
5
|
+
import { getBandColor, getBandLabel } from './mock-cellular-data.js';
|
6
|
+
|
7
|
+
interface Props {
|
8
|
+
sites: CellularSite[];
|
9
|
+
visibility: VisibilityState;
|
10
|
+
onToggleSite: (siteId: string) => void;
|
11
|
+
onToggleSector: (siteId: string, sectorId: string) => void;
|
12
|
+
onToggleCell: (siteId: string, sectorId: string, band: number) => void;
|
13
|
+
}
|
14
|
+
|
15
|
+
let { sites, visibility, onToggleSite, onToggleSector, onToggleCell }: Props = $props();
|
16
|
+
|
17
|
+
// Track expanded/collapsed state for UI only
|
18
|
+
let expandedSites = $state<Set<string>>(new Set(sites.map(s => s.siteId)));
|
19
|
+
let expandedSectors = $state<Set<string>>(new Set());
|
20
|
+
|
21
|
+
function toggleSiteExpand(siteId: string) {
|
22
|
+
if (expandedSites.has(siteId)) {
|
23
|
+
expandedSites.delete(siteId);
|
24
|
+
} else {
|
25
|
+
expandedSites.add(siteId);
|
26
|
+
}
|
27
|
+
expandedSites = new Set(expandedSites); // Trigger reactivity
|
28
|
+
}
|
29
|
+
|
30
|
+
function toggleSectorExpand(siteId: string, sectorId: string) {
|
31
|
+
const key = `${siteId}:${sectorId}`;
|
32
|
+
if (expandedSectors.has(key)) {
|
33
|
+
expandedSectors.delete(key);
|
34
|
+
} else {
|
35
|
+
expandedSectors.add(key);
|
36
|
+
}
|
37
|
+
expandedSectors = new Set(expandedSectors); // Trigger reactivity
|
38
|
+
}
|
39
|
+
|
40
|
+
function getSectorKey(siteId: string, sectorId: string): string {
|
41
|
+
return `${siteId}:${sectorId}`;
|
42
|
+
}
|
43
|
+
|
44
|
+
function getCellKey(siteId: string, sectorId: string, band: number): string {
|
45
|
+
return `${siteId}:${sectorId}:${band}`;
|
46
|
+
}
|
47
|
+
</script>
|
48
|
+
|
49
|
+
<div class="site-tree">
|
50
|
+
<div class="tree-header">
|
51
|
+
<h6 class="mb-0">Site Selection</h6>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
<div class="tree-content">
|
55
|
+
{#each sites as site}
|
56
|
+
{@const isSiteVisible = visibility.sites[site.siteId] ?? true}
|
57
|
+
{@const isSiteExpanded = expandedSites.has(site.siteId)}
|
58
|
+
|
59
|
+
<div class="tree-site">
|
60
|
+
<!-- Site Level -->
|
61
|
+
<div class="tree-item site-item">
|
62
|
+
<button
|
63
|
+
class="expand-btn"
|
64
|
+
onclick={() => toggleSiteExpand(site.siteId)}
|
65
|
+
aria-label={isSiteExpanded ? 'Collapse' : 'Expand'}
|
66
|
+
>
|
67
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
|
68
|
+
{#if isSiteExpanded}
|
69
|
+
<path d="M2 4l4 4 4-4z" />
|
70
|
+
{:else}
|
71
|
+
<path d="M4 2l4 4-4 4z" />
|
72
|
+
{/if}
|
73
|
+
</svg>
|
74
|
+
</button>
|
75
|
+
|
76
|
+
<input
|
77
|
+
type="checkbox"
|
78
|
+
class="form-check-input"
|
79
|
+
id="site-{site.siteId}"
|
80
|
+
checked={isSiteVisible}
|
81
|
+
onchange={() => onToggleSite(site.siteId)}
|
82
|
+
/>
|
83
|
+
|
84
|
+
<label class="tree-label" for="site-{site.siteId}">
|
85
|
+
<strong>{site.siteName}</strong>
|
86
|
+
</label>
|
87
|
+
</div>
|
88
|
+
|
89
|
+
<!-- Sectors -->
|
90
|
+
{#if isSiteExpanded}
|
91
|
+
<div class="tree-children">
|
92
|
+
{#each site.sectors as sector}
|
93
|
+
{@const sectorKey = getSectorKey(site.siteId, sector.sectorId)}
|
94
|
+
{@const isSectorVisible = visibility.sectors[sectorKey] ?? true}
|
95
|
+
{@const isSectorExpanded = expandedSectors.has(sectorKey)}
|
96
|
+
|
97
|
+
<div class="tree-sector">
|
98
|
+
<!-- Sector Level -->
|
99
|
+
<div class="tree-item sector-item">
|
100
|
+
<button
|
101
|
+
class="expand-btn"
|
102
|
+
onclick={() => toggleSectorExpand(site.siteId, sector.sectorId)}
|
103
|
+
aria-label={isSectorExpanded ? 'Collapse' : 'Expand'}
|
104
|
+
>
|
105
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
|
106
|
+
{#if isSectorExpanded}
|
107
|
+
<path d="M2 4l4 4 4-4z" />
|
108
|
+
{:else}
|
109
|
+
<path d="M4 2l4 4-4 4z" />
|
110
|
+
{/if}
|
111
|
+
</svg>
|
112
|
+
</button>
|
113
|
+
|
114
|
+
<input
|
115
|
+
type="checkbox"
|
116
|
+
class="form-check-input"
|
117
|
+
id="sector-{sectorKey}"
|
118
|
+
checked={isSectorVisible}
|
119
|
+
onchange={() => onToggleSector(site.siteId, sector.sectorId)}
|
120
|
+
/>
|
121
|
+
|
122
|
+
<label class="tree-label" for="sector-{sectorKey}">
|
123
|
+
{sector.sectorName}
|
124
|
+
</label>
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<!-- Cells (Frequency Bands) -->
|
128
|
+
{#if isSectorExpanded}
|
129
|
+
<div class="tree-children">
|
130
|
+
{#each sector.cells as cell}
|
131
|
+
{@const cellKey = getCellKey(site.siteId, sector.sectorId, cell.band)}
|
132
|
+
{@const isCellVisible = visibility.cells[cellKey] ?? true}
|
133
|
+
|
134
|
+
<div class="tree-item cell-item">
|
135
|
+
<span class="expand-spacer"></span>
|
136
|
+
|
137
|
+
<input
|
138
|
+
type="checkbox"
|
139
|
+
class="form-check-input"
|
140
|
+
id="cell-{cellKey}"
|
141
|
+
checked={isCellVisible}
|
142
|
+
onchange={() => onToggleCell(site.siteId, sector.sectorId, cell.band)}
|
143
|
+
/>
|
144
|
+
|
145
|
+
<label class="tree-label" for="cell-{cellKey}">
|
146
|
+
<span
|
147
|
+
class="band-indicator"
|
148
|
+
style:background-color={getBandColor(cell.band)}
|
149
|
+
></span>
|
150
|
+
{getBandLabel(cell.band)}
|
151
|
+
</label>
|
152
|
+
</div>
|
153
|
+
{/each}
|
154
|
+
</div>
|
155
|
+
{/if}
|
156
|
+
</div>
|
157
|
+
{/each}
|
158
|
+
</div>
|
159
|
+
{/if}
|
160
|
+
</div>
|
161
|
+
{/each}
|
162
|
+
</div>
|
163
|
+
</div>
|
164
|
+
|
165
|
+
<style>
|
166
|
+
.site-tree {
|
167
|
+
height: 100%;
|
168
|
+
display: flex;
|
169
|
+
flex-direction: column;
|
170
|
+
background-color: #f8f9fa;
|
171
|
+
border-right: 1px solid #dee2e6;
|
172
|
+
}
|
173
|
+
|
174
|
+
.tree-header {
|
175
|
+
padding: 0.75rem 1rem;
|
176
|
+
border-bottom: 1px solid #dee2e6;
|
177
|
+
background-color: #fff;
|
178
|
+
}
|
179
|
+
|
180
|
+
.tree-content {
|
181
|
+
flex: 1;
|
182
|
+
overflow-y: auto;
|
183
|
+
padding: 0.5rem;
|
184
|
+
}
|
185
|
+
|
186
|
+
.tree-site {
|
187
|
+
margin-bottom: 0.5rem;
|
188
|
+
}
|
189
|
+
|
190
|
+
.tree-item {
|
191
|
+
display: flex;
|
192
|
+
align-items: center;
|
193
|
+
gap: 0.5rem;
|
194
|
+
padding: 0.375rem 0.5rem;
|
195
|
+
border-radius: 0.25rem;
|
196
|
+
transition: background-color 0.15s ease;
|
197
|
+
}
|
198
|
+
|
199
|
+
.tree-item:hover {
|
200
|
+
background-color: rgba(0, 0, 0, 0.05);
|
201
|
+
}
|
202
|
+
|
203
|
+
.site-item {
|
204
|
+
font-size: 0.95rem;
|
205
|
+
}
|
206
|
+
|
207
|
+
.sector-item {
|
208
|
+
font-size: 0.9rem;
|
209
|
+
margin-left: 1rem;
|
210
|
+
}
|
211
|
+
|
212
|
+
.cell-item {
|
213
|
+
font-size: 0.85rem;
|
214
|
+
margin-left: 2rem;
|
215
|
+
}
|
216
|
+
|
217
|
+
.expand-btn {
|
218
|
+
background: none;
|
219
|
+
border: none;
|
220
|
+
padding: 0;
|
221
|
+
width: 1rem;
|
222
|
+
height: 1rem;
|
223
|
+
display: flex;
|
224
|
+
align-items: center;
|
225
|
+
justify-content: center;
|
226
|
+
cursor: pointer;
|
227
|
+
color: #6c757d;
|
228
|
+
flex-shrink: 0;
|
229
|
+
}
|
230
|
+
|
231
|
+
.expand-btn:hover {
|
232
|
+
color: #495057;
|
233
|
+
}
|
234
|
+
|
235
|
+
.expand-spacer {
|
236
|
+
width: 1rem;
|
237
|
+
flex-shrink: 0;
|
238
|
+
}
|
239
|
+
|
240
|
+
.form-check-input {
|
241
|
+
cursor: pointer;
|
242
|
+
flex-shrink: 0;
|
243
|
+
margin: 0;
|
244
|
+
}
|
245
|
+
|
246
|
+
.tree-label {
|
247
|
+
cursor: pointer;
|
248
|
+
margin: 0;
|
249
|
+
user-select: none;
|
250
|
+
flex: 1;
|
251
|
+
display: flex;
|
252
|
+
align-items: center;
|
253
|
+
gap: 0.5rem;
|
254
|
+
}
|
255
|
+
|
256
|
+
.tree-children {
|
257
|
+
margin-top: 0.25rem;
|
258
|
+
}
|
259
|
+
|
260
|
+
.band-indicator {
|
261
|
+
display: inline-block;
|
262
|
+
width: 0.75rem;
|
263
|
+
height: 0.75rem;
|
264
|
+
border-radius: 50%;
|
265
|
+
flex-shrink: 0;
|
266
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
267
|
+
}
|
268
|
+
|
269
|
+
/* Scrollbar styling */
|
270
|
+
.tree-content::-webkit-scrollbar {
|
271
|
+
width: 0.5rem;
|
272
|
+
}
|
273
|
+
|
274
|
+
.tree-content::-webkit-scrollbar-track {
|
275
|
+
background: #f1f1f1;
|
276
|
+
}
|
277
|
+
|
278
|
+
.tree-content::-webkit-scrollbar-thumb {
|
279
|
+
background: #888;
|
280
|
+
border-radius: 0.25rem;
|
281
|
+
}
|
282
|
+
|
283
|
+
.tree-content::-webkit-scrollbar-thumb:hover {
|
284
|
+
background: #555;
|
285
|
+
}
|
286
|
+
</style>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import type { CellularSite, VisibilityState } from './cellular.model.js';
|
2
|
+
interface Props {
|
3
|
+
sites: CellularSite[];
|
4
|
+
visibility: VisibilityState;
|
5
|
+
onToggleSite: (siteId: string) => void;
|
6
|
+
onToggleSector: (siteId: string, sectorId: string) => void;
|
7
|
+
onToggleCell: (siteId: string, sectorId: string, band: number) => void;
|
8
|
+
}
|
9
|
+
declare const SiteTree: import("svelte").Component<Props, {}, "">;
|
10
|
+
type SiteTree = ReturnType<typeof SiteTree>;
|
11
|
+
export default SiteTree;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/**
|
2
|
+
* Cellular Data Transformation Utilities
|
3
|
+
*
|
4
|
+
* These functions transform cellular site data into formats needed by TreeChartView.
|
5
|
+
* This is consumer-specific logic, not part of the generic library.
|
6
|
+
*/
|
7
|
+
import type { CellularSite, CellLine } from './cellular.model';
|
8
|
+
import type { TreeNode } from '../core/TreeView/tree.model';
|
9
|
+
import type { Layout } from '../core/Charts/charts.model';
|
10
|
+
/**
|
11
|
+
* Transform cellular sites into TreeNode structure
|
12
|
+
*/
|
13
|
+
export declare function cellularSitesToTreeNodes(sites: CellularSite[]): TreeNode[];
|
14
|
+
/**
|
15
|
+
* Flatten cellular sites into cell lines with visibility
|
16
|
+
*/
|
17
|
+
export declare function flattenCellularSites(sites: CellularSite[], checkedPaths: Set<string>): CellLine[];
|
18
|
+
/**
|
19
|
+
* Transform cell lines into chart data format
|
20
|
+
*/
|
21
|
+
export declare function cellLinesToChartData(cellLines: CellLine[]): any[];
|
22
|
+
/**
|
23
|
+
* Build chart layout from cell lines
|
24
|
+
*/
|
25
|
+
export declare function buildCellularChartLayout(cellLines: CellLine[]): Layout;
|
@@ -0,0 +1,129 @@
|
|
1
|
+
/**
|
2
|
+
* Cellular Data Transformation Utilities
|
3
|
+
*
|
4
|
+
* These functions transform cellular site data into formats needed by TreeChartView.
|
5
|
+
* This is consumer-specific logic, not part of the generic library.
|
6
|
+
*/
|
7
|
+
import { getBandColor, getBandLabel } from './mock-cellular-data';
|
8
|
+
/**
|
9
|
+
* Transform cellular sites into TreeNode structure
|
10
|
+
*/
|
11
|
+
export function cellularSitesToTreeNodes(sites) {
|
12
|
+
return sites.map(site => ({
|
13
|
+
id: site.siteId,
|
14
|
+
label: site.siteName,
|
15
|
+
icon: '📡',
|
16
|
+
defaultExpanded: false,
|
17
|
+
defaultChecked: true,
|
18
|
+
children: site.sectors.map(sector => ({
|
19
|
+
id: sector.sectorId,
|
20
|
+
label: sector.sectorName,
|
21
|
+
icon: '📶',
|
22
|
+
defaultExpanded: false,
|
23
|
+
defaultChecked: true,
|
24
|
+
children: sector.cells.map(cell => ({
|
25
|
+
id: String(cell.band),
|
26
|
+
label: getBandLabel(cell.band),
|
27
|
+
icon: '📻',
|
28
|
+
defaultChecked: true,
|
29
|
+
metadata: {
|
30
|
+
band: cell.band,
|
31
|
+
color: getBandColor(cell.band)
|
32
|
+
}
|
33
|
+
}))
|
34
|
+
}))
|
35
|
+
}));
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Flatten cellular sites into cell lines with visibility
|
39
|
+
*/
|
40
|
+
export function flattenCellularSites(sites, checkedPaths) {
|
41
|
+
const lines = [];
|
42
|
+
sites.forEach(site => {
|
43
|
+
site.sectors.forEach(sector => {
|
44
|
+
sector.cells.forEach(cell => {
|
45
|
+
// Path construction matches tree-utils.ts flattenTree logic
|
46
|
+
const cellKey = `${site.siteId}:${sector.sectorId}:${cell.band}`;
|
47
|
+
const isVisible = checkedPaths.has(cellKey);
|
48
|
+
lines.push({
|
49
|
+
siteId: site.siteId,
|
50
|
+
siteName: site.siteName,
|
51
|
+
sectorId: sector.sectorId,
|
52
|
+
sectorName: sector.sectorName,
|
53
|
+
cellId: cell.cellId,
|
54
|
+
band: cell.band,
|
55
|
+
label: `${site.siteName} - ${sector.sectorName} - ${getBandLabel(cell.band)}`,
|
56
|
+
color: getBandColor(cell.band),
|
57
|
+
kpis: cell.kpis,
|
58
|
+
visible: isVisible
|
59
|
+
});
|
60
|
+
});
|
61
|
+
});
|
62
|
+
});
|
63
|
+
return lines;
|
64
|
+
}
|
65
|
+
/**
|
66
|
+
* Transform cell lines into chart data format
|
67
|
+
*/
|
68
|
+
export function cellLinesToChartData(cellLines) {
|
69
|
+
const data = [];
|
70
|
+
cellLines.forEach(line => {
|
71
|
+
const timestamps = new Set(line.kpis.throughput.map(kpi => kpi.timestamp));
|
72
|
+
timestamps.forEach(timestamp => {
|
73
|
+
const throughputPoint = line.kpis.throughput.find(kpi => kpi.timestamp === timestamp);
|
74
|
+
const taPoint = line.kpis.timingAdvance.find(kpi => kpi.timestamp === timestamp);
|
75
|
+
if (throughputPoint && taPoint) {
|
76
|
+
data.push({
|
77
|
+
TIMESTAMP: timestamp,
|
78
|
+
[`DL_THROUGHPUT_${line.cellId}`]: throughputPoint.value,
|
79
|
+
[`AVG_TA_${line.cellId}`]: taPoint.value,
|
80
|
+
_cellId: line.cellId,
|
81
|
+
_label: line.label,
|
82
|
+
_color: line.color
|
83
|
+
});
|
84
|
+
}
|
85
|
+
});
|
86
|
+
});
|
87
|
+
return data;
|
88
|
+
}
|
89
|
+
/**
|
90
|
+
* Build chart layout from cell lines
|
91
|
+
*/
|
92
|
+
export function buildCellularChartLayout(cellLines) {
|
93
|
+
const throughputKPIs = cellLines.map(line => ({
|
94
|
+
rawName: `DL_THROUGHPUT_${line.cellId}`,
|
95
|
+
name: line.label,
|
96
|
+
scale: 'absolute',
|
97
|
+
unit: 'Mbps',
|
98
|
+
color: line.color
|
99
|
+
}));
|
100
|
+
const taKPIs = cellLines.map(line => ({
|
101
|
+
rawName: `AVG_TA_${line.cellId}`,
|
102
|
+
name: line.label,
|
103
|
+
scale: 'absolute',
|
104
|
+
unit: 'μs',
|
105
|
+
color: line.color
|
106
|
+
}));
|
107
|
+
return {
|
108
|
+
layoutName: 'Cellular Network KPIs',
|
109
|
+
sections: [
|
110
|
+
{
|
111
|
+
id: 'cellular-kpis',
|
112
|
+
title: 'Network Performance',
|
113
|
+
grid: '1x2',
|
114
|
+
charts: [
|
115
|
+
{
|
116
|
+
title: 'Downlink Throughput',
|
117
|
+
yLeft: throughputKPIs,
|
118
|
+
yRight: []
|
119
|
+
},
|
120
|
+
{
|
121
|
+
title: 'Average Timing Advance',
|
122
|
+
yLeft: taKPIs,
|
123
|
+
yRight: []
|
124
|
+
}
|
125
|
+
]
|
126
|
+
}
|
127
|
+
]
|
128
|
+
};
|
129
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/**
|
2
|
+
* Cellular Network Data Models
|
3
|
+
*
|
4
|
+
* Represents hierarchical structure: Site → Sector → Cell (per frequency band)
|
5
|
+
*/
|
6
|
+
export type FrequencyBand = 700 | 800 | 900 | 1800 | 2100 | 2600 | 3500;
|
7
|
+
export interface KPIData {
|
8
|
+
timestamp: string;
|
9
|
+
value: number;
|
10
|
+
}
|
11
|
+
export interface CellKPIs {
|
12
|
+
throughput: KPIData[];
|
13
|
+
timingAdvance: KPIData[];
|
14
|
+
[key: string]: KPIData[];
|
15
|
+
}
|
16
|
+
export interface Cell {
|
17
|
+
cellId: string;
|
18
|
+
band: FrequencyBand;
|
19
|
+
kpis: CellKPIs;
|
20
|
+
}
|
21
|
+
export interface Sector {
|
22
|
+
sectorId: string;
|
23
|
+
sectorName: string;
|
24
|
+
azimuth?: number;
|
25
|
+
cells: Cell[];
|
26
|
+
}
|
27
|
+
export interface CellularSite {
|
28
|
+
siteId: string;
|
29
|
+
siteName: string;
|
30
|
+
sectors: Sector[];
|
31
|
+
}
|
32
|
+
/**
|
33
|
+
* Flattened view of a cell for chart rendering
|
34
|
+
* Includes full hierarchy path and visibility state
|
35
|
+
*/
|
36
|
+
export interface CellLine {
|
37
|
+
siteId: string;
|
38
|
+
siteName: string;
|
39
|
+
sectorId: string;
|
40
|
+
sectorName: string;
|
41
|
+
cellId: string;
|
42
|
+
band: FrequencyBand;
|
43
|
+
label: string;
|
44
|
+
color?: string;
|
45
|
+
kpis: CellKPIs;
|
46
|
+
visible: boolean;
|
47
|
+
}
|
48
|
+
/**
|
49
|
+
* Visibility state for hierarchical control
|
50
|
+
*/
|
51
|
+
export interface VisibilityState {
|
52
|
+
sites: Record<string, boolean>;
|
53
|
+
sectors: Record<string, boolean>;
|
54
|
+
cells: Record<string, boolean>;
|
55
|
+
}
|
56
|
+
/**
|
57
|
+
* Configuration for cellular charts view
|
58
|
+
*/
|
59
|
+
export interface CellularChartsConfig {
|
60
|
+
sites: CellularSite[];
|
61
|
+
kpis: string[];
|
62
|
+
colorScheme?: 'by-band' | 'by-site' | 'unique';
|
63
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/**
|
2
|
+
* Cellular Network Visualization Library
|
3
|
+
*
|
4
|
+
* Provides components for visualizing cellular site data with hierarchical
|
5
|
+
* site/sector/cell selection and KPI charting.
|
6
|
+
*/
|
7
|
+
export { default as CellularChartsView } from './CellularChartsView.svelte';
|
8
|
+
export { default as SiteTree } from './SiteTree.svelte';
|
9
|
+
export * from './cellular.model.js';
|
10
|
+
export * from './mock-cellular-data.js';
|
11
|
+
export * from './cellular-transforms.js';
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/**
|
2
|
+
* Cellular Network Visualization Library
|
3
|
+
*
|
4
|
+
* Provides components for visualizing cellular site data with hierarchical
|
5
|
+
* site/sector/cell selection and KPI charting.
|
6
|
+
*/
|
7
|
+
export { default as CellularChartsView } from './CellularChartsView.svelte';
|
8
|
+
export { default as SiteTree } from './SiteTree.svelte';
|
9
|
+
export * from './cellular.model.js';
|
10
|
+
export * from './mock-cellular-data.js';
|
11
|
+
export * from './cellular-transforms.js';
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import type { CellularSite, FrequencyBand } from './cellular.model.js';
|
2
|
+
/**
|
3
|
+
* Generate mock cellular sites for testing
|
4
|
+
*/
|
5
|
+
export declare function generateMockCellularData(): CellularSite[];
|
6
|
+
/**
|
7
|
+
* Get color for frequency band (consistent color scheme)
|
8
|
+
*/
|
9
|
+
export declare function getBandColor(band: FrequencyBand): string;
|
10
|
+
/**
|
11
|
+
* Get label for frequency band
|
12
|
+
*/
|
13
|
+
export declare function getBandLabel(band: FrequencyBand): string;
|