@smartnet360/svelte-components 0.0.95 → 0.0.96

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.
@@ -111,9 +111,29 @@
111
111
  <option value="logarithmic">Logarithmic (smooth)</option>
112
112
  <option value="percentage">Proportional (40%)</option>
113
113
  <option value="tiered">Tiered (4 levels)</option>
114
+ <option value="hybrid">Hybrid (stepped proportional)</option>
114
115
  </select>
115
116
  </div>
116
117
  </div>
118
+
119
+ <!-- Auto Size Base Multiplier -->
120
+ <div class="row align-items-center g-2 mb-3 ps-3">
121
+ <div class="col-4 text-secondary small">Base Size</div>
122
+ <div class="col-3 text-end">
123
+ <span class="badge bg-white text-muted border">{displayStore.autoSizeBase.toFixed(1)}x</span>
124
+ </div>
125
+ <div class="col-5">
126
+ <input
127
+ id="cell-autosize-base-slider"
128
+ type="range"
129
+ class="form-range w-100"
130
+ min="0.3"
131
+ max="2.0"
132
+ step="0.1"
133
+ bind:value={displayStore.autoSizeBase}
134
+ />
135
+ </div>
136
+ </div>
117
137
  {/if}
118
138
 
119
139
  <div class="border-top my-3"></div>
@@ -100,10 +100,14 @@
100
100
  // Initial setup
101
101
  addLayers();
102
102
 
103
- // Events for updating
103
+ // Events for updating - conditional based on auto-size
104
104
  map.on('style.load', addLayers);
105
- map.on('moveend', updateLayer);
106
- map.on('zoomend', updateLayer);
105
+
106
+ // Only listen to zoom/move events if NOT using auto-size
107
+ if (!displayStore.useAutoSize) {
108
+ map.on('moveend', updateLayer);
109
+ map.on('zoomend', updateLayer);
110
+ }
107
111
 
108
112
  // Cleanup
109
113
  return () => {
@@ -129,6 +133,7 @@
129
133
  const _layerGrouping = displayStore.layerGrouping;
130
134
  const _useAutoSize = displayStore.useAutoSize;
131
135
  const _autoSizeMode = displayStore.autoSizeMode;
136
+ const _autoSizeBase = displayStore.autoSizeBase;
132
137
 
133
138
  updateLayer();
134
139
  });
@@ -144,17 +149,17 @@
144
149
  }
145
150
 
146
151
  function renderCells(map: mapboxgl.Map) {
147
- const bounds = map.getBounds();
148
- if (!bounds) return;
149
-
150
152
  const zoom = map.getZoom();
151
153
  const centerLat = map.getCenter().lat;
152
154
 
153
155
  console.log(`[CellsLayer] Rendering.. Zoom: ${zoom.toFixed(2)}, Cells: ${dataStore.filteredCells.length}`);
154
156
 
155
- // 1. Calculate base radius
157
+ // 1. Calculate base radius (only used in manual mode)
156
158
  const baseRadiusMeters = calculateRadiusInMeters(centerLat, zoom, displayStore.targetPixelSize);
157
- console.log(`[CellsLayer] Base radius: ${baseRadiusMeters.toFixed(2)}m for target ${displayStore.targetPixelSize}px`);
159
+
160
+ if (!displayStore.useAutoSize) {
161
+ console.log(`[CellsLayer] Base radius: ${baseRadiusMeters.toFixed(2)}m for target ${displayStore.targetPixelSize}px`);
162
+ }
158
163
 
159
164
  // 2. Group cells (Level 1=Tech, Level 2=Band for now hardcoded)
160
165
  // In real app, this comes from a store
@@ -173,43 +178,51 @@
173
178
  if (!style.visible) continue;
174
179
 
175
180
  for (const cell of cells) {
176
- // 4. BBox Filter (Simple point check)
177
- if (bounds.contains([cell.longitude, cell.latitude])) {
178
- // 5. Z-Index Lookup
179
- const zIndexKey = `${cell.tech}_${cell.frq}` as TechnologyBandKey;
180
- const zIndex = displayStore.currentZIndex[zIndexKey] ?? 10;
181
-
182
- // 6. Calculate radius with z-index scaling
183
- const MAX_Z = 35;
184
- let radiusMeters: number;
185
-
186
- if (displayStore.useAutoSize) {
187
- // Auto-size mode: get target radius for this site
188
- const siteDistance = dataStore.siteDistanceStore.getDistance(cell.siteId, 500);
189
- const autoRadius = calculateAutoRadius(siteDistance, displayStore.autoSizeMode);
190
-
191
- // Scale based on z-index for stacking visibility
192
- // Lower z-index (background) = larger, higher z-index (foreground) = smaller
193
- const scaleFactor = 1 + Math.max(0, MAX_Z - zIndex) * 0.08; // 8% per layer
194
- radiusMeters = autoRadius * scaleFactor;
195
- } else {
196
- // Manual mode: base from pixel size, then scale by z-index
197
- const scaleFactor = 1 + Math.max(0, MAX_Z - zIndex) * 0.08;
198
- radiusMeters = baseRadiusMeters * scaleFactor;
181
+ // 4. BBox Filter - SKIP if auto-size is enabled
182
+ if (!displayStore.useAutoSize) {
183
+ const bounds = map.getBounds();
184
+ if (!bounds || !bounds.contains([cell.longitude, cell.latitude])) {
185
+ continue;
199
186
  }
187
+ }
188
+
189
+ // 5. Z-Index Lookup
190
+ const zIndexKey = `${cell.tech}_${cell.frq}` as TechnologyBandKey;
191
+ const zIndex = displayStore.currentZIndex[zIndexKey] ?? 10;
192
+
193
+ // 6. Calculate radius with z-index scaling
194
+ const MAX_Z = 35;
195
+ let radiusMeters: number;
196
+
197
+ if (displayStore.useAutoSize) {
198
+ // Auto-size mode: get target radius for this site
199
+ const siteDistance = dataStore.siteDistanceStore.getDistance(cell.siteId, 500);
200
+ const autoRadius = calculateAutoRadius(siteDistance, displayStore.autoSizeMode);
201
+
202
+ // Apply base size multiplier
203
+ const baseAdjusted = autoRadius * displayStore.autoSizeBase;
204
+
205
+ // Scale based on z-index for stacking visibility
206
+ // Lower z-index (background) = larger, higher z-index (foreground) = smaller
207
+ const scaleFactor = 1 + Math.max(0, MAX_Z - zIndex) * 0.08; // 8% per layer
208
+ radiusMeters = baseAdjusted * scaleFactor;
209
+ } else {
210
+ // Manual mode: base from pixel size, then scale by z-index
211
+ const scaleFactor = 1 + Math.max(0, MAX_Z - zIndex) * 0.08;
212
+ radiusMeters = baseRadiusMeters * scaleFactor;
213
+ }
200
214
 
201
- // 7. Apply beamwidth boost from displayStore preset
202
- const beamwidthBoost = displayStore.currentBeamwidthBoost[zIndexKey] || 0;
203
- const adjustedBeamwidth = cell.beamwidth + beamwidthBoost;
215
+ // 7. Apply beamwidth boost from displayStore preset
216
+ const beamwidthBoost = displayStore.currentBeamwidthBoost[zIndexKey] || 0;
217
+ const adjustedBeamwidth = cell.beamwidth + beamwidthBoost;
204
218
 
205
- // 8. Generate Arc
206
- const feature = generateCellArc(cell, radiusMeters, zIndex, style.color, adjustedBeamwidth);
207
- features.push(feature);
208
- }
219
+ // 8. Generate Arc
220
+ const feature = generateCellArc(cell, radiusMeters, zIndex, style.color, adjustedBeamwidth);
221
+ features.push(feature);
209
222
  }
210
223
  }
211
224
 
212
- console.log(`[CellsLayer] Generated ${features.length} features in view`);
225
+ console.log(`[CellsLayer] Generated ${features.length} features ${displayStore.useAutoSize ? '(all cells)' : 'in view'}`);
213
226
 
214
227
  // 8. Update Source
215
228
  const source = map.getSource(sourceId) as mapboxgl.GeoJSONSource;
@@ -38,6 +38,29 @@ export function calculateAutoRadius(nearestSiteDistance, mode = 'logarithmic') {
38
38
  return 120;
39
39
  return 180;
40
40
  }
41
+ case 'hybrid': {
42
+ // Stepped proportional - tiers with proportional scaling within each tier
43
+ if (nearestSiteDistance < 300) {
44
+ // Tier 1: 0-300m → 30-50m radius
45
+ const ratio = nearestSiteDistance / 300;
46
+ return 30 + (ratio * 20);
47
+ }
48
+ else if (nearestSiteDistance < 600) {
49
+ // Tier 2: 300-600m → 50-80m radius
50
+ const ratio = (nearestSiteDistance - 300) / 300;
51
+ return 50 + (ratio * 30);
52
+ }
53
+ else if (nearestSiteDistance < 1200) {
54
+ // Tier 3: 600-1200m → 80-120m radius
55
+ const ratio = (nearestSiteDistance - 600) / 600;
56
+ return 80 + (ratio * 40);
57
+ }
58
+ else {
59
+ // Tier 4: 1200m+ → 120-180m radius
60
+ const ratio = Math.min((nearestSiteDistance - 1200) / 1200, 1);
61
+ return 120 + (ratio * 60);
62
+ }
63
+ }
41
64
  default:
42
65
  return 80;
43
66
  }
@@ -9,6 +9,7 @@ export declare class CellDisplayStore {
9
9
  layerGrouping: LayerGroupingPreset;
10
10
  useAutoSize: boolean;
11
11
  autoSizeMode: AutoSizeMode;
12
+ autoSizeBase: number;
12
13
  level1: CellGroupingField;
13
14
  level2: CellGroupingField;
14
15
  currentZIndex: Record<string, number>;
@@ -11,6 +11,7 @@ export class CellDisplayStore {
11
11
  // Auto-size settings
12
12
  useAutoSize = $state(false);
13
13
  autoSizeMode = $state('logarithmic');
14
+ autoSizeBase = $state(1.0);
14
15
  // Grouping
15
16
  level1 = $state('tech');
16
17
  level2 = $state('fband');
@@ -40,6 +41,7 @@ export class CellDisplayStore {
40
41
  this.layerGrouping = parsed.layerGrouping ?? 'frequency';
41
42
  this.useAutoSize = parsed.useAutoSize ?? false;
42
43
  this.autoSizeMode = parsed.autoSizeMode ?? 'logarithmic';
44
+ this.autoSizeBase = parsed.autoSizeBase ?? 1.0;
43
45
  this.level1 = parsed.level1 ?? 'tech';
44
46
  this.level2 = parsed.level2 ?? 'fband';
45
47
  this.labelPixelDistance = parsed.labelPixelDistance ?? 60;
@@ -64,6 +66,7 @@ export class CellDisplayStore {
64
66
  layerGrouping: this.layerGrouping,
65
67
  useAutoSize: this.useAutoSize,
66
68
  autoSizeMode: this.autoSizeMode,
69
+ autoSizeBase: this.autoSizeBase,
67
70
  level1: this.level1,
68
71
  level2: this.level2,
69
72
  labelPixelDistance: this.labelPixelDistance,
@@ -63,7 +63,7 @@ export type CellGroupingField = 'tech' | 'fband' | 'frq' | 'status' | 'siteId' |
63
63
  /**
64
64
  * Auto-size calculation modes
65
65
  */
66
- export type AutoSizeMode = 'logarithmic' | 'percentage' | 'tiered';
66
+ export type AutoSizeMode = 'logarithmic' | 'percentage' | 'tiered' | 'hybrid';
67
67
  /**
68
68
  * Site distance data for auto-sizing
69
69
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.95",
3
+ "version": "0.0.96",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",