@smartnet360/svelte-components 0.0.118 → 0.0.120

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 (61) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaDiagramsV2.svelte +412 -0
  2. package/dist/apps/antenna-pattern/components/AntennaDiagramsV2.svelte.d.ts +8 -0
  3. package/dist/apps/antenna-pattern/index.d.ts +3 -0
  4. package/dist/apps/antenna-pattern/index.js +4 -0
  5. package/dist/apps/antenna-pattern/types.d.ts +87 -0
  6. package/dist/apps/antenna-pattern/types.js +5 -0
  7. package/dist/apps/antenna-pattern/utils/antenna-helpers.d.ts +57 -0
  8. package/dist/apps/antenna-pattern/utils/antenna-helpers.js +140 -0
  9. package/dist/apps/antenna-tools/band-config.d.ts +53 -0
  10. package/dist/apps/antenna-tools/band-config.js +112 -0
  11. package/dist/apps/antenna-tools/components/AntennaControls.svelte +558 -0
  12. package/dist/apps/antenna-tools/components/AntennaControls.svelte.d.ts +16 -0
  13. package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte +304 -0
  14. package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte.d.ts +8 -0
  15. package/dist/apps/antenna-tools/components/AntennaTools.svelte +597 -0
  16. package/dist/apps/antenna-tools/components/AntennaTools.svelte.d.ts +42 -0
  17. package/dist/apps/antenna-tools/components/DatabaseViewer.svelte +278 -0
  18. package/dist/apps/antenna-tools/components/DatabaseViewer.svelte.d.ts +3 -0
  19. package/dist/apps/antenna-tools/components/DbNotification.svelte +67 -0
  20. package/dist/apps/antenna-tools/components/DbNotification.svelte.d.ts +18 -0
  21. package/dist/apps/antenna-tools/components/JsonImporter.svelte +115 -0
  22. package/dist/apps/antenna-tools/components/JsonImporter.svelte.d.ts +6 -0
  23. package/dist/apps/antenna-tools/components/MSIConverter.svelte +282 -0
  24. package/dist/apps/antenna-tools/components/MSIConverter.svelte.d.ts +6 -0
  25. package/dist/apps/antenna-tools/components/chart-engines/PolarAreaChart.svelte +123 -0
  26. package/dist/apps/antenna-tools/components/chart-engines/PolarAreaChart.svelte.d.ts +16 -0
  27. package/dist/apps/antenna-tools/components/chart-engines/PolarLineChart.svelte +123 -0
  28. package/dist/apps/antenna-tools/components/chart-engines/PolarLineChart.svelte.d.ts +16 -0
  29. package/dist/apps/antenna-tools/components/chart-engines/index.d.ts +9 -0
  30. package/dist/apps/antenna-tools/components/chart-engines/index.js +9 -0
  31. package/dist/apps/antenna-tools/components/index.d.ts +8 -0
  32. package/dist/apps/antenna-tools/components/index.js +10 -0
  33. package/dist/apps/antenna-tools/db.d.ts +28 -0
  34. package/dist/apps/antenna-tools/db.js +45 -0
  35. package/dist/apps/antenna-tools/index.d.ts +26 -0
  36. package/dist/apps/antenna-tools/index.js +40 -0
  37. package/dist/apps/antenna-tools/stores/antennas.d.ts +13 -0
  38. package/dist/apps/antenna-tools/stores/antennas.js +25 -0
  39. package/dist/apps/antenna-tools/stores/db-status.d.ts +32 -0
  40. package/dist/apps/antenna-tools/stores/db-status.js +38 -0
  41. package/dist/apps/antenna-tools/stores/index.d.ts +5 -0
  42. package/dist/apps/antenna-tools/stores/index.js +5 -0
  43. package/dist/apps/antenna-tools/types.d.ts +137 -0
  44. package/dist/apps/antenna-tools/types.js +16 -0
  45. package/dist/apps/antenna-tools/utils/antenna-helpers.d.ts +83 -0
  46. package/dist/apps/antenna-tools/utils/antenna-helpers.js +198 -0
  47. package/dist/apps/antenna-tools/utils/chart-engines/index.d.ts +5 -0
  48. package/dist/apps/antenna-tools/utils/chart-engines/index.js +5 -0
  49. package/dist/apps/antenna-tools/utils/chart-engines/polar-area-utils.d.ts +94 -0
  50. package/dist/apps/antenna-tools/utils/chart-engines/polar-area-utils.js +151 -0
  51. package/dist/apps/antenna-tools/utils/chart-engines/polar-line-utils.d.ts +93 -0
  52. package/dist/apps/antenna-tools/utils/chart-engines/polar-line-utils.js +139 -0
  53. package/dist/apps/antenna-tools/utils/db-utils.d.ts +50 -0
  54. package/dist/apps/antenna-tools/utils/db-utils.js +266 -0
  55. package/dist/apps/antenna-tools/utils/index.d.ts +7 -0
  56. package/dist/apps/antenna-tools/utils/index.js +7 -0
  57. package/dist/apps/antenna-tools/utils/msi-parser.d.ts +21 -0
  58. package/dist/apps/antenna-tools/utils/msi-parser.js +215 -0
  59. package/dist/apps/antenna-tools/utils/recent-antennas.d.ts +24 -0
  60. package/dist/apps/antenna-tools/utils/recent-antennas.js +64 -0
  61. package/package.json +1 -1
@@ -0,0 +1,412 @@
1
+ <svelte:options runes={true} />
2
+
3
+ <script lang="ts">
4
+ import { onMount } from 'svelte';
5
+ import { loadAntennas } from '../utils/db-utils';
6
+ import type { Antenna } from '../db';
7
+ import type {
8
+ ViewMode,
9
+ PatternType,
10
+ PatternDisplayMode,
11
+ ChartEngineType,
12
+ AntennaCompareInit
13
+ } from '../types';
14
+ import {
15
+ findAntennaByName,
16
+ collectAvailableTilts,
17
+ findTiltIndex
18
+ } from '../utils/antenna-helpers';
19
+ import AntennaControls from './AntennaControls.svelte';
20
+ import AntennaSettingsModal from './AntennaSettingsModal.svelte';
21
+ import { PolarLineChart, PolarAreaChart } from './chart-engines/index';
22
+
23
+ // ─────────────────────────────────────────────────────────────────────────────
24
+ // PROPS - Optional initialization from external sources
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+
27
+ interface Props {
28
+ /** Initial configuration for comparison mode */
29
+ init?: AntennaCompareInit;
30
+ }
31
+
32
+ let { init }: Props = $props();
33
+
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // STATE - Core reactive state
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+
38
+ // Data
39
+ let antennas = $state<Antenna[]>([]);
40
+ let isLoading = $state(true);
41
+ let error = $state<string | null>(null);
42
+
43
+ // Antenna 1 selection
44
+ let selectedAntenna1 = $state<Antenna | null>(null);
45
+ let ant1ElectricalTiltIndex = $state(0);
46
+ let ant1MechanicalTilt = $state(0);
47
+ let ant1AvailableTilts = $state<string[]>(['0']);
48
+
49
+ // Antenna 2 selection
50
+ let selectedAntenna2 = $state<Antenna | null>(null);
51
+ let ant2ElectricalTiltIndex = $state(0);
52
+ let ant2MechanicalTilt = $state(0);
53
+ let ant2AvailableTilts = $state<string[]>(['0']);
54
+
55
+ // View settings
56
+ let viewMode = $state<ViewMode>('single');
57
+ let patternType = $state<PatternType>('vertical');
58
+ let displayMode = $state<PatternDisplayMode>('normalized');
59
+ let chartEngine = $state<ChartEngineType>('polar-line');
60
+
61
+ // Settings modal
62
+ let showSettingsModal = $state(false);
63
+
64
+ // ─────────────────────────────────────────────────────────────────────────────
65
+ // DERIVED - Computed values
66
+ // ─────────────────────────────────────────────────────────────────────────────
67
+
68
+ /** Generate chart title based on current selection */
69
+ let chartTitle = $derived.by(() => {
70
+ if (viewMode === 'compare' && selectedAntenna1 && selectedAntenna2) {
71
+ const label1 = init?.label1 || selectedAntenna1.name;
72
+ const label2 = init?.label2 || selectedAntenna2.name;
73
+ return `${label1} vs ${label2}`;
74
+ }
75
+
76
+ if (selectedAntenna1) {
77
+ const label = init?.label1 || selectedAntenna1.name;
78
+ return `${label} - Pattern Analysis`;
79
+ }
80
+
81
+ return 'Antenna Pattern Analysis';
82
+ });
83
+
84
+ // ─────────────────────────────────────────────────────────────────────────────
85
+ // INITIALIZATION
86
+ // ─────────────────────────────────────────────────────────────────────────────
87
+
88
+ onMount(async () => {
89
+ try {
90
+ isLoading = true;
91
+ antennas = await loadAntennas();
92
+
93
+ if (antennas.length === 0) {
94
+ error = 'No antenna data found. Please load antenna files.';
95
+ return;
96
+ }
97
+
98
+ // Initialize with provided config or defaults
99
+ initializeAntennas();
100
+
101
+ } catch (e) {
102
+ error = e instanceof Error ? e.message : 'Failed to load antenna data';
103
+ console.error('[AntennaDiagrams] Initialization error:', e);
104
+ } finally {
105
+ isLoading = false;
106
+ }
107
+ });
108
+
109
+ /**
110
+ * Initialize antenna selections from init props or defaults
111
+ */
112
+ function initializeAntennas() {
113
+ // Set view mode from init or default
114
+ viewMode = init?.viewMode || 'single';
115
+
116
+ // Initialize Antenna 1
117
+ if (init?.antenna1Name) {
118
+ const result = findAntennaByName(antennas, init.antenna1Name);
119
+ selectedAntenna1 = result.antenna || antennas[0];
120
+
121
+ if (result.matchType === 'not-found') {
122
+ console.warn(`[AntennaDiagrams] Antenna 1 not found: "${init.antenna1Name}"`);
123
+ }
124
+ } else {
125
+ selectedAntenna1 = antennas[0];
126
+ }
127
+
128
+ // Collect available tilts for antenna 1
129
+ if (selectedAntenna1) {
130
+ ant1AvailableTilts = collectAvailableTilts(antennas, selectedAntenna1.name);
131
+ ant1ElectricalTiltIndex = findTiltIndex(ant1AvailableTilts, init?.etilt1 || 0);
132
+ ant1MechanicalTilt = init?.mtilt1 || 0;
133
+ }
134
+
135
+ // Initialize Antenna 2
136
+ if (init?.antenna2Name) {
137
+ const result = findAntennaByName(antennas, init.antenna2Name);
138
+ selectedAntenna2 = result.antenna || (antennas.length > 1 ? antennas[1] : antennas[0]);
139
+
140
+ if (result.matchType === 'not-found') {
141
+ console.warn(`[AntennaDiagrams] Antenna 2 not found: "${init.antenna2Name}"`);
142
+ }
143
+ } else {
144
+ selectedAntenna2 = antennas.length > 1 ? antennas[1] : antennas[0];
145
+ }
146
+
147
+ // Collect available tilts for antenna 2
148
+ if (selectedAntenna2) {
149
+ ant2AvailableTilts = collectAvailableTilts(antennas, selectedAntenna2.name);
150
+ ant2ElectricalTiltIndex = findTiltIndex(ant2AvailableTilts, init?.etilt2 || 0);
151
+ ant2MechanicalTilt = init?.mtilt2 || 0;
152
+ }
153
+ }
154
+
155
+ // ─────────────────────────────────────────────────────────────────────────────
156
+ // EVENT HANDLERS
157
+ // ─────────────────────────────────────────────────────────────────────────────
158
+
159
+ function handleAntenna1Change(antenna: Antenna | null) {
160
+ selectedAntenna1 = antenna;
161
+ if (antenna) {
162
+ ant1AvailableTilts = collectAvailableTilts(antennas, antenna.name);
163
+ }
164
+ }
165
+
166
+ function handleAntenna2Change(antenna: Antenna | null) {
167
+ selectedAntenna2 = antenna;
168
+ if (antenna) {
169
+ ant2AvailableTilts = collectAvailableTilts(antennas, antenna.name);
170
+ }
171
+ }
172
+
173
+ function handleTilt1Change(tiltIndex: number) {
174
+ ant1ElectricalTiltIndex = tiltIndex;
175
+ }
176
+
177
+ function handleTilt2Change(tiltIndex: number) {
178
+ ant2ElectricalTiltIndex = tiltIndex;
179
+ }
180
+
181
+ function handleMechTilt1Change(tilt: number) {
182
+ ant1MechanicalTilt = tilt;
183
+ }
184
+
185
+ function handleMechTilt2Change(tilt: number) {
186
+ ant2MechanicalTilt = tilt;
187
+ }
188
+
189
+ async function handleDataRefresh() {
190
+ try {
191
+ antennas = await loadAntennas();
192
+ if (antennas.length > 0) {
193
+ selectedAntenna1 = antennas[0];
194
+ selectedAntenna2 = antennas.length > 1 ? antennas[1] : antennas[0];
195
+ ant1ElectricalTiltIndex = 0;
196
+ ant2ElectricalTiltIndex = 0;
197
+ ant1MechanicalTilt = 0;
198
+ ant2MechanicalTilt = 0;
199
+ }
200
+ } catch (e) {
201
+ console.error('[AntennaDiagrams] Failed to refresh data:', e);
202
+ }
203
+ }
204
+ </script>
205
+
206
+ <!-- ═══════════════════════════════════════════════════════════════════════════ -->
207
+ <!-- TEMPLATE -->
208
+ <!-- ═══════════════════════════════════════════════════════════════════════════ -->
209
+
210
+ <div class="container-fluid mt-4">
211
+
212
+ {#if isLoading}
213
+ <!-- Loading State -->
214
+ <div class="text-center py-5">
215
+ <div class="spinner-border text-primary" role="status">
216
+ <span class="visually-hidden">Loading...</span>
217
+ </div>
218
+ <p class="mt-3 text-muted">Loading antenna data...</p>
219
+ </div>
220
+
221
+ {:else if error}
222
+ <!-- Error State -->
223
+ <div class="alert alert-warning d-flex align-items-center" role="alert">
224
+ <i class="bi bi-exclamation-triangle-fill me-2"></i>
225
+ <div>
226
+ {error}
227
+ <button type="button" class="btn btn-sm btn-outline-primary ms-3" onclick={() => showSettingsModal = true}>
228
+ Load Antenna Data
229
+ </button>
230
+ </div>
231
+ </div>
232
+
233
+ {:else}
234
+ <!-- Main Content -->
235
+
236
+ <!-- Control Bar -->
237
+ <div class="row mb-3 g-2">
238
+
239
+ <!-- View Mode -->
240
+ <div class="col-auto">
241
+ <div class="btn-group" role="group" aria-label="View mode">
242
+ <input type="radio" class="btn-check" id="viewSingle" bind:group={viewMode} value="single">
243
+ <label class="btn btn-outline-primary" for="viewSingle">
244
+ <i class="bi bi-square"></i> Single
245
+ </label>
246
+ <input type="radio" class="btn-check" id="viewCompare" bind:group={viewMode} value="compare">
247
+ <label class="btn btn-outline-primary" for="viewCompare">
248
+ <i class="bi bi-columns"></i> Compare
249
+ </label>
250
+ </div>
251
+ </div>
252
+
253
+ <!-- Chart Type -->
254
+ <div class="col-auto">
255
+ <div class="btn-group" role="group" aria-label="Chart type">
256
+ <input type="radio" class="btn-check" id="chartLine" bind:group={chartEngine} value="polar-line">
257
+ <label class="btn btn-outline-secondary" for="chartLine">Line</label>
258
+ <input type="radio" class="btn-check" id="chartArea" bind:group={chartEngine} value="polar-area">
259
+ <label class="btn btn-outline-secondary" for="chartArea">Area</label>
260
+ </div>
261
+ </div>
262
+
263
+ <!-- Display Mode -->
264
+ <div class="col-auto">
265
+ <div class="btn-group" role="group" aria-label="Display mode">
266
+ <input type="radio" class="btn-check" id="dispPattern" bind:group={displayMode} value="normalized">
267
+ <label class="btn btn-outline-secondary" for="dispPattern">Pattern</label>
268
+ <input type="radio" class="btn-check" id="dispGain" bind:group={displayMode} value="gain-adjusted">
269
+ <label class="btn btn-outline-secondary" for="dispGain">+Gain</label>
270
+ </div>
271
+ </div>
272
+
273
+ <!-- Pattern Type -->
274
+ <div class="col-auto">
275
+ <div class="btn-group" role="group" aria-label="Pattern type">
276
+ <input type="radio" class="btn-check" id="patHoriz" bind:group={patternType} value="horizontal">
277
+ <label class="btn btn-outline-secondary" for="patHoriz">Horizontal</label>
278
+ <input type="radio" class="btn-check" id="patVert" bind:group={patternType} value="vertical">
279
+ <label class="btn btn-outline-secondary" for="patVert">Vertical</label>
280
+ </div>
281
+ </div>
282
+
283
+ <!-- Spacer -->
284
+ <div class="col"></div>
285
+
286
+ <!-- Settings Button -->
287
+ <div class="col-auto">
288
+ <button
289
+ type="button"
290
+ class="btn btn-outline-secondary"
291
+ onclick={() => showSettingsModal = true}
292
+ aria-label="Antenna Settings"
293
+ >
294
+ <i class="bi bi-gear"></i>
295
+ </button>
296
+ </div>
297
+ </div>
298
+
299
+ <!-- Main Layout: Controls | Chart | Controls -->
300
+ <div class="row">
301
+
302
+ <!-- Antenna 1 Controls -->
303
+ <div class="col-lg-3 col-md-4">
304
+ <AntennaControls
305
+ {antennas}
306
+ selectedAntenna={selectedAntenna1}
307
+ antennaNumber={1}
308
+ electricalTiltIndex={ant1ElectricalTiltIndex}
309
+ mechanicalTilt={ant1MechanicalTilt}
310
+ colorTheme="primary"
311
+ onAntennaChange={handleAntenna1Change}
312
+ onElectricalTiltChange={handleTilt1Change}
313
+ onMechanicalTiltChange={handleMechTilt1Change}
314
+ />
315
+ </div>
316
+
317
+ <!-- Chart -->
318
+ <div class="col-lg-6 col-md-4">
319
+ <div class="chart-card">
320
+ {#if chartEngine === 'polar-line'}
321
+ <PolarLineChart
322
+ selectedAntenna={selectedAntenna1}
323
+ selectedAntenna2={selectedAntenna2}
324
+ {viewMode}
325
+ {patternType}
326
+ patternDisplayMode={displayMode}
327
+ ant1ElectricalTilt={ant1ElectricalTiltIndex}
328
+ ant1MechanicalTilt={ant1MechanicalTilt}
329
+ ant2ElectricalTilt={ant2ElectricalTiltIndex}
330
+ ant2MechanicalTilt={ant2MechanicalTilt}
331
+ title={chartTitle}
332
+ />
333
+ {:else if chartEngine === 'polar-area'}
334
+ <PolarAreaChart
335
+ selectedAntenna={selectedAntenna1}
336
+ selectedAntenna2={selectedAntenna2}
337
+ {viewMode}
338
+ {patternType}
339
+ patternDisplayMode={displayMode}
340
+ ant1ElectricalTilt={ant1ElectricalTiltIndex}
341
+ ant1MechanicalTilt={ant1MechanicalTilt}
342
+ ant2ElectricalTilt={ant2ElectricalTiltIndex}
343
+ ant2MechanicalTilt={ant2MechanicalTilt}
344
+ title={chartTitle}
345
+ />
346
+ {/if}
347
+ </div>
348
+ </div>
349
+
350
+ <!-- Antenna 2 Controls (Compare Mode) -->
351
+ <div class="col-lg-3 col-md-4">
352
+ {#if viewMode === 'compare'}
353
+ <AntennaControls
354
+ {antennas}
355
+ selectedAntenna={selectedAntenna2}
356
+ antennaNumber={2}
357
+ electricalTiltIndex={ant2ElectricalTiltIndex}
358
+ mechanicalTilt={ant2MechanicalTilt}
359
+ colorTheme="warning"
360
+ onAntennaChange={handleAntenna2Change}
361
+ onElectricalTiltChange={handleTilt2Change}
362
+ onMechanicalTiltChange={handleMechTilt2Change}
363
+ />
364
+ {:else}
365
+ <!-- Placeholder to maintain layout -->
366
+ <div class="empty-placeholder"></div>
367
+ {/if}
368
+ </div>
369
+ </div>
370
+ {/if}
371
+ </div>
372
+
373
+ <!-- Settings Modal -->
374
+ <AntennaSettingsModal
375
+ show={showSettingsModal}
376
+ onClose={() => showSettingsModal = false}
377
+ on:dataRefresh={handleDataRefresh}
378
+ />
379
+
380
+ <!-- ═══════════════════════════════════════════════════════════════════════════ -->
381
+ <!-- STYLES -->
382
+ <!-- ═══════════════════════════════════════════════════════════════════════════ -->
383
+
384
+ <style>
385
+ .chart-card {
386
+ background: white;
387
+ border-radius: 12px;
388
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
389
+ padding: 0.5rem;
390
+ }
391
+
392
+ .empty-placeholder {
393
+ min-height: 200px;
394
+ }
395
+
396
+ /* Bootstrap icon font (if not already loaded) */
397
+ .bi::before {
398
+ vertical-align: -0.125em;
399
+ }
400
+
401
+ /* Enhanced button group styling */
402
+ .btn-group .btn {
403
+ font-size: 0.875rem;
404
+ }
405
+
406
+ /* Responsive adjustments */
407
+ @media (max-width: 992px) {
408
+ .chart-card {
409
+ margin-bottom: 1rem;
410
+ }
411
+ }
412
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { AntennaCompareInit } from '../types';
2
+ interface Props {
3
+ /** Initial configuration for comparison mode */
4
+ init?: AntennaCompareInit;
5
+ }
6
+ declare const AntennaDiagramsV2: import("svelte").Component<Props, {}, "">;
7
+ type AntennaDiagramsV2 = ReturnType<typeof AntennaDiagramsV2>;
8
+ export default AntennaDiagramsV2;
@@ -1,6 +1,7 @@
1
1
  export { default as PlotlyRadarChart } from './components/PlotlyRadarChart.svelte';
2
2
  export { default as AntennaControls } from './components/AntennaControls.svelte';
3
3
  export { default as AntennaDiagrams } from './components/AntennaDiagrams.svelte';
4
+ export { default as AntennaDiagramsV2 } from './components/AntennaDiagramsV2.svelte';
4
5
  export { default as AntennaSettingsModal } from './components/AntennaSettingsModal.svelte';
5
6
  export { default as JsonImporter } from './components/JsonImporter.svelte';
6
7
  export { default as MSIConverter } from './components/MSIConverter.svelte';
@@ -10,8 +11,10 @@ export { PolarLineChart, PolarBarChart } from './components/chart-engines/index'
10
11
  export { antennas, selectedAntenna, searchQuery, filteredAntennas } from './stores/antennas';
11
12
  export { dbStatus, dataOperationStatus, updateDbStatus, trackDataOperation } from './stores/db-status';
12
13
  export { db, type Antenna } from './db';
14
+ export * from './types';
13
15
  export * from './utils/db-utils';
14
16
  export * from './utils/init-db';
15
17
  export * from './utils/msi-parser';
16
18
  export * from './utils/plotly-chart-utils';
17
19
  export * from './utils/load-static-antennas';
20
+ export * from './utils/antenna-helpers';
@@ -2,6 +2,7 @@
2
2
  export { default as PlotlyRadarChart } from './components/PlotlyRadarChart.svelte';
3
3
  export { default as AntennaControls } from './components/AntennaControls.svelte';
4
4
  export { default as AntennaDiagrams } from './components/AntennaDiagrams.svelte';
5
+ export { default as AntennaDiagramsV2 } from './components/AntennaDiagramsV2.svelte';
5
6
  export { default as AntennaSettingsModal } from './components/AntennaSettingsModal.svelte';
6
7
  export { default as JsonImporter } from './components/JsonImporter.svelte';
7
8
  export { default as MSIConverter } from './components/MSIConverter.svelte';
@@ -14,9 +15,12 @@ export { antennas, selectedAntenna, searchQuery, filteredAntennas } from './stor
14
15
  export { dbStatus, dataOperationStatus, updateDbStatus, trackDataOperation } from './stores/db-status';
15
16
  // Database and types
16
17
  export { db } from './db';
18
+ // Types
19
+ export * from './types';
17
20
  // Utilities
18
21
  export * from './utils/db-utils';
19
22
  export * from './utils/init-db';
20
23
  export * from './utils/msi-parser';
21
24
  export * from './utils/plotly-chart-utils';
22
25
  export * from './utils/load-static-antennas';
26
+ export * from './utils/antenna-helpers';
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Antenna Pattern Types
3
+ * Clean, centralized type definitions for the antenna pattern module
4
+ */
5
+ import type { Antenna } from './db';
6
+ /** View mode for antenna diagrams */
7
+ export type ViewMode = 'single' | 'compare';
8
+ /** Pattern type for radiation display */
9
+ export type PatternType = 'horizontal' | 'vertical';
10
+ /** Display mode for pattern visualization */
11
+ export type PatternDisplayMode = 'normalized' | 'gain-adjusted';
12
+ /** Chart engine type */
13
+ export type ChartEngineType = 'polar-line' | 'polar-bar' | 'polar-area';
14
+ /** Color theme for antenna controls */
15
+ export type ColorTheme = 'primary' | 'warning' | 'success' | 'info' | 'secondary';
16
+ /**
17
+ * Antenna selection state - tracks antenna, tilts, and available options
18
+ */
19
+ export interface AntennaSelection {
20
+ /** The selected antenna record */
21
+ antenna: Antenna | null;
22
+ /** Index into availableTilts array for electrical tilt */
23
+ electricalTiltIndex: number;
24
+ /** Mechanical tilt value in degrees */
25
+ mechanicalTilt: number;
26
+ /** Available electrical tilt values for this antenna model */
27
+ availableTilts: string[];
28
+ /** Available frequencies for this antenna model */
29
+ availableFrequencies: number[];
30
+ /** Custom label for display (e.g., cell name) */
31
+ label?: string;
32
+ }
33
+ /**
34
+ * Props for initializing AntennaDiagrams from external sources (URL params, etc.)
35
+ */
36
+ export interface AntennaCompareInit {
37
+ /** Antenna 1 name pattern to match */
38
+ antenna1Name?: string;
39
+ /** Antenna 2 name pattern to match */
40
+ antenna2Name?: string;
41
+ /** Electrical tilt VALUE for antenna 1 */
42
+ etilt1?: number;
43
+ /** Electrical tilt VALUE for antenna 2 */
44
+ etilt2?: number;
45
+ /** Mechanical tilt for antenna 1 */
46
+ mtilt1?: number;
47
+ /** Mechanical tilt for antenna 2 */
48
+ mtilt2?: number;
49
+ /** Initial view mode */
50
+ viewMode?: ViewMode;
51
+ /** Custom label for antenna 1 */
52
+ label1?: string;
53
+ /** Custom label for antenna 2 */
54
+ label2?: string;
55
+ }
56
+ /**
57
+ * Result of finding an antenna by name
58
+ */
59
+ export interface AntennaSearchResult {
60
+ antenna: Antenna | null;
61
+ matchType: 'exact' | 'case-insensitive' | 'partial' | 'not-found';
62
+ }
63
+ /**
64
+ * Complete state for the antenna diagram visualization
65
+ */
66
+ export interface AntennaDiagramState {
67
+ /** All loaded antennas */
68
+ antennas: Antenna[];
69
+ /** First antenna selection */
70
+ selection1: AntennaSelection;
71
+ /** Second antenna selection (for compare mode) */
72
+ selection2: AntennaSelection;
73
+ /** Current view mode */
74
+ viewMode: ViewMode;
75
+ /** Current pattern type */
76
+ patternType: PatternType;
77
+ /** Current display mode */
78
+ displayMode: PatternDisplayMode;
79
+ /** Current chart engine */
80
+ chartEngine: ChartEngineType;
81
+ /** Whether data is loading */
82
+ isLoading: boolean;
83
+ /** Error message if any */
84
+ error: string | null;
85
+ }
86
+ /** Re-export Antenna type for convenience */
87
+ export type { Antenna } from './db';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Antenna Pattern Types
3
+ * Clean, centralized type definitions for the antenna pattern module
4
+ */
5
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Antenna Data Utilities
3
+ * Helper functions for working with antenna data, tilts, and searches
4
+ */
5
+ import type { Antenna, AntennaSearchResult } from '../types';
6
+ /**
7
+ * Find an antenna by name with fallback matching strategies
8
+ * @param antennas - Array of all antennas
9
+ * @param name - Name pattern to search for
10
+ * @returns Search result with antenna and match type
11
+ */
12
+ export declare function findAntennaByName(antennas: Antenna[], name: string): AntennaSearchResult;
13
+ /**
14
+ * Collect all available electrical tilts for an antenna model
15
+ * Searches all antennas with the same name and extracts unique tilt values
16
+ * @param antennas - Array of all antennas
17
+ * @param antennaName - The antenna model name
18
+ * @param frequency - Optional frequency to filter by
19
+ * @returns Sorted array of tilt values as strings
20
+ */
21
+ export declare function collectAvailableTilts(antennas: Antenna[], antennaName: string, frequency?: number | null): string[];
22
+ /**
23
+ * Collect all available frequencies for an antenna model
24
+ * @param antennas - Array of all antennas
25
+ * @param antennaName - The antenna model name
26
+ * @returns Sorted array of unique frequencies
27
+ */
28
+ export declare function collectAvailableFrequencies(antennas: Antenna[], antennaName: string): number[];
29
+ /**
30
+ * Find the index of a tilt value in the available tilts array
31
+ * @param availableTilts - Array of available tilt values
32
+ * @param tiltValue - The tilt value to find (as number)
33
+ * @returns Index in the array, or 0 if not found
34
+ */
35
+ export declare function findTiltIndex(availableTilts: string[], tiltValue: number): number;
36
+ /**
37
+ * Get the tilt value at a given index
38
+ * @param availableTilts - Array of available tilt values
39
+ * @param index - Index to retrieve
40
+ * @returns Tilt value as number
41
+ */
42
+ export declare function getTiltValue(availableTilts: string[], index: number): number;
43
+ /**
44
+ * Find an antenna with specific name, frequency, and tilt
45
+ * @param antennas - Array of all antennas
46
+ * @param name - Antenna model name
47
+ * @param frequency - Target frequency (optional)
48
+ * @param tiltValue - Target tilt value
49
+ * @returns Matching antenna or null
50
+ */
51
+ export declare function findAntennaWithTilt(antennas: Antenna[], name: string, frequency: number | null, tiltValue: string): Antenna | null;
52
+ /**
53
+ * Get unique antenna models (by name)
54
+ * @param antennas - Array of all antennas
55
+ * @returns Array of unique antenna names
56
+ */
57
+ export declare function getUniqueAntennaModels(antennas: Antenna[]): string[];