@smartnet360/svelte-components 0.0.122 → 0.0.124

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 (28) hide show
  1. package/dist/apps/antenna-tools/band-config.d.ts +3 -2
  2. package/dist/apps/antenna-tools/band-config.js +6 -4
  3. package/dist/apps/antenna-tools/components/AntennaControls.svelte +71 -9
  4. package/dist/apps/antenna-tools/components/AntennaControls.svelte.d.ts +2 -0
  5. package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte +5 -2
  6. package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte.d.ts +3 -0
  7. package/dist/apps/antenna-tools/components/AntennaTools.svelte +55 -85
  8. package/dist/apps/antenna-tools/components/AntennaTools.svelte.d.ts +5 -3
  9. package/dist/apps/antenna-tools/components/DatabaseViewer.svelte +3 -6
  10. package/dist/apps/antenna-tools/components/MSIConverter.svelte +123 -15
  11. package/dist/apps/antenna-tools/components/MSIConverter.svelte.d.ts +3 -0
  12. package/dist/apps/antenna-tools/types.d.ts +8 -3
  13. package/dist/apps/antenna-tools/types.js +14 -8
  14. package/dist/apps/antenna-tools/utils/db-utils.d.ts +3 -2
  15. package/dist/apps/antenna-tools/utils/db-utils.js +3 -2
  16. package/dist/apps/antenna-tools/utils/msi-parser.d.ts +50 -2
  17. package/dist/apps/antenna-tools/utils/msi-parser.js +110 -27
  18. package/dist/apps/index.d.ts +2 -0
  19. package/dist/apps/index.js +1 -0
  20. package/dist/core/Benchmark/Benchmark.svelte +662 -0
  21. package/dist/core/Benchmark/Benchmark.svelte.d.ts +3 -0
  22. package/dist/core/Benchmark/benchmark-utils.d.ts +48 -0
  23. package/dist/core/Benchmark/benchmark-utils.js +80 -0
  24. package/dist/core/Benchmark/index.d.ts +2 -0
  25. package/dist/core/Benchmark/index.js +3 -0
  26. package/dist/core/index.d.ts +1 -0
  27. package/dist/core/index.js +2 -0
  28. package/package.json +1 -1
@@ -23,15 +23,16 @@ export declare function isFrequencyInStandardBand(frequencyMHz: number): boolean
23
23
  * Purge antennas - keep only one per band (closest to center frequency)
24
24
  *
25
25
  * For each antenna name + tilt combination:
26
- * - For each standard band, find antennas within the band's frequency range
26
+ * - For each band, find antennas within the band's frequency range
27
27
  * - Keep only the one closest to the center frequency
28
28
  * - Update frequency to band name (700, 800, etc.)
29
29
  * - Store original frequency in originalFrequency field
30
30
  *
31
31
  * @param rawAntennas - Antennas parsed from MSI files (with actual MHz frequencies)
32
+ * @param bands - Optional custom band definitions (defaults to STANDARD_BANDS)
32
33
  * @returns Purged antennas with band names as frequencies
33
34
  */
34
- export declare function purgeAntennas(rawAntennas: RawAntenna[]): Antenna[];
35
+ export declare function purgeAntennas(rawAntennas: RawAntenna[], bands?: BandDefinition[]): Antenna[];
35
36
  /**
36
37
  * Get purge statistics
37
38
  */
@@ -41,21 +41,23 @@ function groupByNameAndTilt(antennas) {
41
41
  * Purge antennas - keep only one per band (closest to center frequency)
42
42
  *
43
43
  * For each antenna name + tilt combination:
44
- * - For each standard band, find antennas within the band's frequency range
44
+ * - For each band, find antennas within the band's frequency range
45
45
  * - Keep only the one closest to the center frequency
46
46
  * - Update frequency to band name (700, 800, etc.)
47
47
  * - Store original frequency in originalFrequency field
48
48
  *
49
49
  * @param rawAntennas - Antennas parsed from MSI files (with actual MHz frequencies)
50
+ * @param bands - Optional custom band definitions (defaults to STANDARD_BANDS)
50
51
  * @returns Purged antennas with band names as frequencies
51
52
  */
52
- export function purgeAntennas(rawAntennas) {
53
+ export function purgeAntennas(rawAntennas, bands) {
53
54
  const purged = [];
55
+ const bandsToUse = bands ?? STANDARD_BANDS;
54
56
  // Group by antenna name + tilt
55
57
  const groups = groupByNameAndTilt(rawAntennas);
56
58
  for (const [_key, group] of groups) {
57
- // For each standard band
58
- for (const band of STANDARD_BANDS) {
59
+ // For each band
60
+ for (const band of bandsToUse) {
59
61
  // Find antennas in this band's frequency range
60
62
  const inBand = group.filter(a => a.frequency >= band.dlMin && a.frequency <= band.dlMax);
61
63
  if (inBand.length === 0)
@@ -15,6 +15,8 @@
15
15
  onElectricalTiltChange?: (index: number) => void;
16
16
  onMechanicalTiltChange?: (tilt: number) => void;
17
17
  showStatus?: boolean;
18
+ /** Requested frequency from external mode - will be highlighted */
19
+ requestedFrequency?: number | null;
18
20
  }
19
21
 
20
22
  let {
@@ -27,7 +29,8 @@
27
29
  onAntennaChange,
28
30
  onElectricalTiltChange,
29
31
  onMechanicalTiltChange,
30
- showStatus = true
32
+ showStatus = true,
33
+ requestedFrequency = null
31
34
  }: Props = $props();
32
35
 
33
36
  // Internal state for slider values
@@ -36,6 +39,20 @@
36
39
  let internalSelectedAntenna = $state(selectedAntenna);
37
40
  let selectedFrequency = $state<number | null>(null);
38
41
 
42
+ // Check if requested frequency is available for the selected antenna
43
+ let frequencyError = $derived.by(() => {
44
+ if (!requestedFrequency || !internalSelectedAntenna) return null;
45
+
46
+ // Get all frequencies available for this antenna
47
+ const sameNameAntennas = antennas.filter(a => a.name === internalSelectedAntenna!.name);
48
+ const availableFreqs = [...new Set(sameNameAntennas.map(a => a.frequency))];
49
+
50
+ if (!availableFreqs.includes(requestedFrequency)) {
51
+ return `Requested frequency ${requestedFrequency} MHz is not available for this antenna. Available: ${availableFreqs.sort((a, b) => a - b).join(', ')} MHz`;
52
+ }
53
+ return null;
54
+ });
55
+
39
56
  // Update internal state when props change
40
57
  $effect(() => {
41
58
  internalElectricalTiltIndex = electricalTiltIndex;
@@ -305,18 +322,36 @@
305
322
  return colors[theme];
306
323
  }
307
324
 
325
+ // Type for frequency info with original frequency
326
+ interface FrequencyInfo {
327
+ band: number;
328
+ originalFrequency: number;
329
+ }
330
+
308
331
  // Get unique frequency bands for the selected antenna name
309
- let uniqueFrequencies = $state<number[]>([]);
332
+ let uniqueFrequencies = $state<FrequencyInfo[]>([]);
310
333
  $effect(() => {
311
334
  if (antennas.length > 0 && internalSelectedAntenna) {
312
335
  // Get frequencies only for the selected antenna name
313
336
  const sameNameAntennas = antennas.filter(a => a.name === internalSelectedAntenna!.name);
314
- const frequencies = [...new Set(sameNameAntennas.map(a => a.frequency))].sort((a, b) => a - b);
337
+
338
+ // Create unique frequency entries with original frequency
339
+ const freqMap = new Map<number, number>();
340
+ sameNameAntennas.forEach(a => {
341
+ // Keep the first original frequency for each band
342
+ if (!freqMap.has(a.frequency)) {
343
+ freqMap.set(a.frequency, a.originalFrequency);
344
+ }
345
+ });
346
+
347
+ const frequencies = Array.from(freqMap.entries())
348
+ .map(([band, orig]) => ({ band, originalFrequency: orig }))
349
+ .sort((a, b) => a.band - b.band);
315
350
  uniqueFrequencies = frequencies;
316
351
 
317
352
  // Auto-select frequency if there's only one option
318
353
  if (frequencies.length === 1) {
319
- selectedFrequency = frequencies[0];
354
+ selectedFrequency = frequencies[0].band;
320
355
  }
321
356
  } else {
322
357
  uniqueFrequencies = [];
@@ -348,10 +383,14 @@
348
383
  }
349
384
  });
350
385
 
351
- // Format frequency for display (700, 800 -> "700 MHz", "800 MHz")
386
+ // Format frequency for display (band [original] -> "700 [712]")
352
387
  function formatFrequency(freq: number): string {
353
388
  return `${freq} MHz`;
354
389
  }
390
+
391
+ function formatFrequencyWithOriginal(info: FrequencyInfo): string {
392
+ return `${info.band} [${info.originalFrequency}]`;
393
+ }
355
394
  </script>
356
395
 
357
396
  <div class="card h-100">
@@ -396,24 +435,47 @@
396
435
  {/if}
397
436
  </div>
398
437
 
438
+ <!-- Frequency Error Message -->
439
+ {#if frequencyError}
440
+ <div class="alert alert-danger py-2 mb-3" role="alert">
441
+ <i class="bi bi-exclamation-triangle-fill me-2"></i>
442
+ <small>{frequencyError}</small>
443
+ </div>
444
+ {/if}
445
+
399
446
  <!-- Frequency Band Filter -->
400
447
  {#if uniqueFrequencies.length > 1}
401
448
  <div class="mb-3">
402
449
  <div class="form-label">
403
450
  <strong>Frequency Band:</strong>
451
+ {#if requestedFrequency && !frequencyError}
452
+ <span class="badge bg-info ms-2">Requested: {requestedFrequency} MHz</span>
453
+ {/if}
404
454
  </div>
405
455
  <div class="d-flex flex-wrap gap-1">
406
- {#each uniqueFrequencies as freq}
456
+ {#each uniqueFrequencies as freqInfo}
457
+ {@const isRequested = requestedFrequency === freqInfo.band}
458
+ {@const isSelected = selectedFrequency === freqInfo.band}
407
459
  <button
408
460
  type="button"
409
- class="btn btn-sm {selectedFrequency === freq ? 'btn-primary' : 'btn-outline-secondary'}"
410
- onclick={() => handleFrequencyChange(freq)}
461
+ class="btn btn-sm {isSelected ? 'btn-primary' : isRequested ? 'btn-outline-info border-2' : 'btn-outline-secondary'}"
462
+ class:fw-bold={isRequested}
463
+ onclick={() => handleFrequencyChange(freqInfo.band)}
411
464
  >
412
- {formatFrequency(freq)}
465
+ {formatFrequencyWithOriginal(freqInfo)}
466
+ {#if isRequested && !isSelected}
467
+ <i class="bi bi-arrow-left-short"></i>
468
+ {/if}
413
469
  </button>
414
470
  {/each}
415
471
  </div>
416
472
  </div>
473
+ {:else if uniqueFrequencies.length === 1 && requestedFrequency && uniqueFrequencies[0].band !== requestedFrequency}
474
+ <!-- Single frequency but doesn't match requested -->
475
+ <div class="alert alert-warning py-2 mb-3" role="alert">
476
+ <i class="bi bi-exclamation-triangle-fill me-2"></i>
477
+ <small>Requested {requestedFrequency} MHz, but only {uniqueFrequencies[0].band} MHz available</small>
478
+ </div>
417
479
  {/if}
418
480
 
419
481
  <!-- Electrical Tilt Control -->
@@ -10,6 +10,8 @@ interface Props {
10
10
  onElectricalTiltChange?: (index: number) => void;
11
11
  onMechanicalTiltChange?: (tilt: number) => void;
12
12
  showStatus?: boolean;
13
+ /** Requested frequency from external mode - will be highlighted */
14
+ requestedFrequency?: number | null;
13
15
  }
14
16
  declare const AntennaControls: import("svelte").Component<Props, {}, "">;
15
17
  type AntennaControls = ReturnType<typeof AntennaControls>;
@@ -6,14 +6,17 @@
6
6
  import DbNotification from './DbNotification.svelte';
7
7
  import DatabaseViewer from './DatabaseViewer.svelte';
8
8
  import { exportAntennas, clearAllAntennas } from '../utils/db-utils';
9
+ import type { BandDefinition } from '../types';
9
10
 
10
11
  interface Props {
11
12
  show: boolean;
12
13
  onClose: () => void;
13
14
  onDataRefresh?: () => void;
15
+ /** Custom band definitions for purge (defaults to STANDARD_BANDS) */
16
+ customBands?: BandDefinition[];
14
17
  }
15
18
 
16
- let { show, onClose, onDataRefresh }: Props = $props();
19
+ let { show, onClose, onDataRefresh, customBands }: Props = $props();
17
20
 
18
21
  let activeTab = $state<'view' | 'import' | 'msi' | 'export' | 'manage'>('view');
19
22
  let showClearConfirm = $state(false);
@@ -147,7 +150,7 @@
147
150
  <div class="row">
148
151
  <div class="col-12">
149
152
  <h5 class="mb-3">Import MSI Pattern Files</h5>
150
- <MSIConverter onDataRefresh={handleDataRefresh} />
153
+ <MSIConverter onDataRefresh={handleDataRefresh} {customBands} />
151
154
  </div>
152
155
  </div>
153
156
  </div>
@@ -1,7 +1,10 @@
1
+ import type { BandDefinition } from '../types';
1
2
  interface Props {
2
3
  show: boolean;
3
4
  onClose: () => void;
4
5
  onDataRefresh?: () => void;
6
+ /** Custom band definitions for purge (defaults to STANDARD_BANDS) */
7
+ customBands?: BandDefinition[];
5
8
  }
6
9
  declare const AntennaSettingsModal: import("svelte").Component<Props, {}, "">;
7
10
  type AntennaSettingsModal = ReturnType<typeof AntennaSettingsModal>;
@@ -1,9 +1,9 @@
1
1
  <svelte:options runes={true} />
2
2
 
3
3
  <script lang="ts">
4
- import { onMount } from 'svelte';
4
+ import { onMount, untrack } from 'svelte';
5
5
  import { loadAntennas } from '../utils/db-utils';
6
- import type { Antenna, ExternalAntennaInput, ViewMode, PatternType, ChartEngineType, PatternDisplayMode } from '../types';
6
+ import type { Antenna, ExternalAntennaInput, ViewMode, PatternType, ChartEngineType, PatternDisplayMode, BandDefinition } from '../types';
7
7
  import AntennaControls from './AntennaControls.svelte';
8
8
  import AntennaSettingsModal from './AntennaSettingsModal.svelte';
9
9
  import { PolarLineChart, PolarAreaChart } from './chart-engines/index';
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * 2. Standalone Mode (default): User selects antennas from database
21
21
  * - Full UI with antenna selection dropdowns
22
- * - Settings modal for data management
22
+ * - Database modal for data management
23
23
  */
24
24
 
25
25
  interface Props {
@@ -50,8 +50,10 @@
50
50
  antenna1Label?: string;
51
51
  /** Label for antenna 2 (e.g., cell name) */
52
52
  antenna2Label?: string;
53
- /** Hide the settings button */
53
+ /** Hide the database button */
54
54
  hideSettings?: boolean;
55
+ /** Custom frequency band definitions for purge (defaults to STANDARD_BANDS with full 3GPP ranges) */
56
+ customBands?: BandDefinition[];
55
57
  }
56
58
 
57
59
  let {
@@ -70,6 +72,7 @@
70
72
  antenna1Label = undefined,
71
73
  antenna2Label = undefined,
72
74
  hideSettings = false,
75
+ customBands = undefined,
73
76
  }: Props = $props();
74
77
 
75
78
  // === Derived: Operating Mode ===
@@ -107,12 +110,13 @@
107
110
  if (externalAntenna1) {
108
111
  const found = findAntennaBySpec(antennas, externalAntenna1);
109
112
  if (found) {
110
- selectedAntenna = found;
111
- // Update available tilts
112
- updateAvailableTilts(found);
113
- // Set tilts from external spec
114
- ant1ElectricalTilt = findTiltIndex(availableElectricalTilts, externalAntenna1.electricalTilt ?? 0);
115
- ant1MechanicalTilt = externalAntenna1.mechanicalTilt ?? 0;
113
+ // Use untrack to prevent infinite loop from state updates
114
+ untrack(() => {
115
+ selectedAntenna = found;
116
+ updateAvailableTilts(found);
117
+ ant1ElectricalTilt = findTiltIndex(availableElectricalTilts, externalAntenna1.electricalTilt ?? 0);
118
+ ant1MechanicalTilt = externalAntenna1.mechanicalTilt ?? 0;
119
+ });
116
120
  } else {
117
121
  console.warn('[AntennaTools] External antenna 1 not found in database:', externalAntenna1.name);
118
122
  }
@@ -122,13 +126,14 @@
122
126
  if (externalAntenna2) {
123
127
  const found2 = findAntennaBySpec(antennas, externalAntenna2);
124
128
  if (found2) {
125
- selectedAntenna2 = found2;
126
- ant2ElectricalTilt = findTiltIndex(getAvailableTiltsForAntenna(found2), externalAntenna2.electricalTilt ?? 0);
127
- ant2MechanicalTilt = externalAntenna2.mechanicalTilt ?? 0;
128
- // Auto-switch to compare mode if antenna 2 is provided
129
- if (viewMode === 'single') {
130
- viewMode = 'compare';
131
- }
129
+ untrack(() => {
130
+ selectedAntenna2 = found2;
131
+ ant2ElectricalTilt = findTiltIndex(getAvailableTiltsForAntenna(found2), externalAntenna2.electricalTilt ?? 0);
132
+ ant2MechanicalTilt = externalAntenna2.mechanicalTilt ?? 0;
133
+ if (viewMode === 'single') {
134
+ viewMode = 'compare';
135
+ }
136
+ });
132
137
  }
133
138
  }
134
139
  }
@@ -452,40 +457,22 @@
452
457
  <div class="row">
453
458
  <!-- Left Column - Antenna 1 Controls -->
454
459
  <div class="col-md-3">
455
- {#if !isExternalMode}
456
- <AntennaControls
457
- antennas={antennas}
458
- selectedAntenna={selectedAntenna}
459
- antennaNumber={1}
460
- electricalTiltIndex={ant1ElectricalTilt}
461
- mechanicalTilt={ant1MechanicalTilt}
462
- colorTheme="primary"
463
- onAntennaChange={handleAntenna1Change}
464
- onElectricalTiltChange={handleTilt1Change}
465
- onMechanicalTiltChange={handleMechTilt1Change}
466
- />
467
- {:else}
468
- <!-- External mode: Show antenna info card -->
469
- <div class="card border-primary">
470
- <div class="card-header bg-primary text-white">
471
- <i class="bi bi-broadcast me-2"></i>
472
- {antenna1Label || 'Antenna 1'}
473
- </div>
474
- <div class="card-body">
475
- {#if selectedAntenna}
476
- <h6 class="card-title">{selectedAntenna.name}</h6>
477
- <div class="small text-muted">
478
- <div><strong>Band:</strong> {selectedAntenna.frequency}</div>
479
- <div><strong>E-Tilt:</strong> {availableElectricalTilts[ant1ElectricalTilt] || 0}°</div>
480
- <div><strong>M-Tilt:</strong> {ant1MechanicalTilt}°</div>
481
- {#if selectedAntenna.gain_dBd}
482
- <div><strong>Gain:</strong> {selectedAntenna.gain_dBd} dBd</div>
483
- {/if}
484
- </div>
485
- {:else}
486
- <p class="text-muted mb-0">Antenna not found in database</p>
487
- {/if}
488
- </div>
460
+ <!-- Show full controls in both modes - external mode just pre-selects the antenna -->
461
+ <AntennaControls
462
+ antennas={antennas}
463
+ selectedAntenna={selectedAntenna}
464
+ antennaNumber={1}
465
+ electricalTiltIndex={ant1ElectricalTilt}
466
+ mechanicalTilt={ant1MechanicalTilt}
467
+ colorTheme="primary"
468
+ onAntennaChange={handleAntenna1Change}
469
+ onElectricalTiltChange={handleTilt1Change}
470
+ onMechanicalTiltChange={handleMechTilt1Change}
471
+ requestedFrequency={isExternalMode ? externalAntenna1?.frequency : null}
472
+ />
473
+ {#if isExternalMode && antenna1Label}
474
+ <div class="badge bg-primary w-100 mt-2 py-2">
475
+ <i class="bi bi-link-45deg me-1"></i>{antenna1Label}
489
476
  </div>
490
477
  {/if}
491
478
  </div>
@@ -528,40 +515,22 @@
528
515
  <!-- Right Column - Antenna 2 Controls (only in compare mode) -->
529
516
  <div class="col-md-3">
530
517
  {#if viewMode === 'compare'}
531
- {#if !isExternalMode}
532
- <AntennaControls
533
- antennas={antennas}
534
- selectedAntenna={selectedAntenna2}
535
- antennaNumber={2}
536
- electricalTiltIndex={ant2ElectricalTilt}
537
- mechanicalTilt={ant2MechanicalTilt}
538
- colorTheme="warning"
539
- onAntennaChange={handleAntenna2Change}
540
- onElectricalTiltChange={handleTilt2Change}
541
- onMechanicalTiltChange={handleMechTilt2Change}
542
- />
543
- {:else}
544
- <!-- External mode: Show antenna 2 info card -->
545
- <div class="card border-warning">
546
- <div class="card-header bg-warning text-dark">
547
- <i class="bi bi-broadcast me-2"></i>
548
- {antenna2Label || 'Antenna 2'}
549
- </div>
550
- <div class="card-body">
551
- {#if selectedAntenna2}
552
- <h6 class="card-title">{selectedAntenna2.name}</h6>
553
- <div class="small text-muted">
554
- <div><strong>Band:</strong> {selectedAntenna2.frequency}</div>
555
- <div><strong>E-Tilt:</strong> {getAvailableTiltsForAntenna(selectedAntenna2)[ant2ElectricalTilt] || 0}°</div>
556
- <div><strong>M-Tilt:</strong> {ant2MechanicalTilt}°</div>
557
- {#if selectedAntenna2.gain_dBd}
558
- <div><strong>Gain:</strong> {selectedAntenna2.gain_dBd} dBd</div>
559
- {/if}
560
- </div>
561
- {:else}
562
- <p class="text-muted mb-0">Antenna not found in database</p>
563
- {/if}
564
- </div>
518
+ <!-- Show full controls in both modes -->
519
+ <AntennaControls
520
+ antennas={antennas}
521
+ selectedAntenna={selectedAntenna2}
522
+ antennaNumber={2}
523
+ electricalTiltIndex={ant2ElectricalTilt}
524
+ mechanicalTilt={ant2MechanicalTilt}
525
+ colorTheme="warning"
526
+ onAntennaChange={handleAntenna2Change}
527
+ onElectricalTiltChange={handleTilt2Change}
528
+ onMechanicalTiltChange={handleMechTilt2Change}
529
+ requestedFrequency={isExternalMode ? externalAntenna2?.frequency : null}
530
+ />
531
+ {#if isExternalMode && antenna2Label}
532
+ <div class="badge bg-warning text-dark w-100 mt-2 py-2">
533
+ <i class="bi bi-link-45deg me-1"></i>{antenna2Label}
565
534
  </div>
566
535
  {/if}
567
536
  {:else}
@@ -579,6 +548,7 @@
579
548
  show={showSettingsModal}
580
549
  onClose={closeSettings}
581
550
  onDataRefresh={handleDataRefresh}
551
+ {customBands}
582
552
  />
583
553
  {/if}
584
554
 
@@ -1,4 +1,4 @@
1
- import type { ExternalAntennaInput, ViewMode } from '../types';
1
+ import type { ExternalAntennaInput, ViewMode, BandDefinition } from '../types';
2
2
  /**
3
3
  * AntennaTools - Main antenna pattern visualization component
4
4
  *
@@ -9,7 +9,7 @@ import type { ExternalAntennaInput, ViewMode } from '../types';
9
9
  *
10
10
  * 2. Standalone Mode (default): User selects antennas from database
11
11
  * - Full UI with antenna selection dropdowns
12
- * - Settings modal for data management
12
+ * - Database modal for data management
13
13
  */
14
14
  interface Props {
15
15
  /** External antenna 1 specification (activates external mode) */
@@ -34,8 +34,10 @@ interface Props {
34
34
  antenna1Label?: string;
35
35
  /** Label for antenna 2 (e.g., cell name) */
36
36
  antenna2Label?: string;
37
- /** Hide the settings button */
37
+ /** Hide the database button */
38
38
  hideSettings?: boolean;
39
+ /** Custom frequency band definitions for purge (defaults to STANDARD_BANDS with full 3GPP ranges) */
40
+ customBands?: BandDefinition[];
39
41
  }
40
42
  declare const AntennaTools: import("svelte").Component<Props, {}, "">;
41
43
  type AntennaTools = ReturnType<typeof AntennaTools>;
@@ -187,8 +187,7 @@
187
187
  <thead class="table-light sticky-top">
188
188
  <tr>
189
189
  <th>Model Name</th>
190
- <th class="text-center" style="width: 80px;">Band</th>
191
- <th class="text-center" style="width: 100px;">Orig. Freq</th>
190
+ <th class="text-center" style="width: 120px;">Band [Orig]</th>
192
191
  <th class="text-center" style="width: 70px;">Tilt</th>
193
192
  <th class="text-center" style="width: 80px;">Gain</th>
194
193
  <th class="text-center" style="width: 60px;">H-Pts</th>
@@ -206,9 +205,7 @@
206
205
  </td>
207
206
  <td class="text-center">
208
207
  <span class="badge bg-primary">{antenna.frequency}</span>
209
- </td>
210
- <td class="text-center text-muted">
211
- {antenna.originalFrequency} MHz
208
+ <span class="text-muted small">[{antenna.originalFrequency}]</span>
212
209
  </td>
213
210
  <td class="text-center">
214
211
  {antenna.tilt}°
@@ -225,7 +222,7 @@
225
222
  </tr>
226
223
  {:else}
227
224
  <tr>
228
- <td colspan="7" class="text-center text-muted py-4">
225
+ <td colspan="6" class="text-center text-muted py-4">
229
226
  No antennas match your search criteria
230
227
  </td>
231
228
  </tr>