@smartnet360/svelte-components 0.0.124 → 0.0.126

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 (53) hide show
  1. package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte +4 -174
  2. package/dist/apps/antenna-tools/components/DatabaseViewer.svelte +2 -2
  3. package/dist/apps/antenna-tools/components/MSIConverter.svelte +302 -43
  4. package/dist/apps/antenna-tools/db.js +4 -0
  5. package/dist/apps/antenna-tools/utils/db-utils.d.ts +19 -0
  6. package/dist/apps/antenna-tools/utils/db-utils.js +108 -0
  7. package/dist/core/Auth/LoginForm.svelte +397 -0
  8. package/dist/core/Auth/LoginForm.svelte.d.ts +16 -0
  9. package/dist/core/Auth/auth.svelte.d.ts +22 -0
  10. package/dist/core/Auth/auth.svelte.js +229 -0
  11. package/dist/core/Auth/config.d.ts +25 -0
  12. package/dist/core/Auth/config.js +256 -0
  13. package/dist/core/Auth/index.d.ts +4 -0
  14. package/dist/core/Auth/index.js +5 -0
  15. package/dist/core/Auth/types.d.ts +140 -0
  16. package/dist/core/Auth/types.js +2 -0
  17. package/dist/core/LandingPage/App.svelte +102 -0
  18. package/dist/core/LandingPage/App.svelte.d.ts +20 -0
  19. package/dist/core/LandingPage/LandingPage.svelte +480 -0
  20. package/dist/core/LandingPage/LandingPage.svelte.d.ts +21 -0
  21. package/dist/core/LandingPage/index.d.ts +2 -0
  22. package/dist/core/LandingPage/index.js +3 -0
  23. package/dist/core/index.d.ts +2 -0
  24. package/dist/core/index.js +4 -0
  25. package/dist/map-v3/demo/DemoMap.svelte +18 -0
  26. package/dist/map-v3/demo/demo-custom-cells.d.ts +21 -0
  27. package/dist/map-v3/demo/demo-custom-cells.js +48 -0
  28. package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte +220 -0
  29. package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte.d.ts +15 -0
  30. package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte +306 -0
  31. package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte.d.ts +10 -0
  32. package/dist/map-v3/features/cells/custom/components/index.d.ts +5 -0
  33. package/dist/map-v3/features/cells/custom/components/index.js +5 -0
  34. package/dist/map-v3/features/cells/custom/index.d.ts +32 -0
  35. package/dist/map-v3/features/cells/custom/index.js +35 -0
  36. package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte +262 -0
  37. package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte.d.ts +10 -0
  38. package/dist/map-v3/features/cells/custom/layers/index.d.ts +4 -0
  39. package/dist/map-v3/features/cells/custom/layers/index.js +4 -0
  40. package/dist/map-v3/features/cells/custom/logic/csv-parser.d.ts +20 -0
  41. package/dist/map-v3/features/cells/custom/logic/csv-parser.js +164 -0
  42. package/dist/map-v3/features/cells/custom/logic/index.d.ts +5 -0
  43. package/dist/map-v3/features/cells/custom/logic/index.js +5 -0
  44. package/dist/map-v3/features/cells/custom/logic/tree-adapter.d.ts +24 -0
  45. package/dist/map-v3/features/cells/custom/logic/tree-adapter.js +67 -0
  46. package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.d.ts +78 -0
  47. package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.js +242 -0
  48. package/dist/map-v3/features/cells/custom/stores/index.d.ts +4 -0
  49. package/dist/map-v3/features/cells/custom/stores/index.js +4 -0
  50. package/dist/map-v3/features/cells/custom/types.d.ts +83 -0
  51. package/dist/map-v3/features/cells/custom/types.js +23 -0
  52. package/dist/map-v3/shared/controls/MapControl.svelte +27 -3
  53. package/package.json +1 -1
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Custom Cell Sets Store
3
+ *
4
+ * Manages multiple custom cell sets, each loaded from a CSV file.
5
+ * Resolves cell data from the parent CellDataStore.
6
+ */
7
+ import { browser } from '$app/environment';
8
+ import { CUSTOM_CELL_PALETTE } from '../types';
9
+ import { parseCustomCellsCsv, buildCellLookup } from '../logic/csv-parser';
10
+ /**
11
+ * Generate a unique ID for a new set
12
+ */
13
+ function generateSetId() {
14
+ return `set-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
15
+ }
16
+ /**
17
+ * Store for managing custom cell sets
18
+ */
19
+ export class CustomCellSetsStore {
20
+ /** All custom cell sets */
21
+ sets = $state([]);
22
+ /** Version counter for reactivity */
23
+ version = $state(0);
24
+ /** Reference to parent cell data store */
25
+ cellDataStore;
26
+ /** Storage key for persistence */
27
+ storageKey;
28
+ constructor(cellDataStore, namespace = 'default') {
29
+ this.cellDataStore = cellDataStore;
30
+ this.storageKey = `${namespace}:custom-cell-sets`;
31
+ if (browser) {
32
+ this.load();
33
+ // Auto-save on changes
34
+ $effect(() => {
35
+ // Read version to trigger on changes
36
+ const _v = this.version;
37
+ this.save();
38
+ });
39
+ // Re-resolve cells when main cell data changes
40
+ $effect(() => {
41
+ const cellCount = this.cellDataStore.rawCells.length;
42
+ if (cellCount > 0 && this.sets.length > 0) {
43
+ // Check if any cells need resolution
44
+ const needsResolution = this.sets.some(set => set.cells.some(c => !c.resolvedCell));
45
+ if (needsResolution) {
46
+ console.log('[CustomCellSetsStore] Re-resolving cells after main data loaded');
47
+ this.refreshResolutions();
48
+ }
49
+ }
50
+ });
51
+ }
52
+ }
53
+ /**
54
+ * Import a CSV file and create a new custom cell set
55
+ */
56
+ importFromCsv(csvContent, fileName) {
57
+ // Build lookup from all cells (unfiltered)
58
+ const cellLookup = buildCellLookup(this.cellDataStore.rawCells);
59
+ // Parse CSV
60
+ const result = parseCustomCellsCsv(csvContent, cellLookup);
61
+ return result;
62
+ }
63
+ /**
64
+ * Create a new set from import result
65
+ */
66
+ createSet(name, importResult) {
67
+ const id = generateSetId();
68
+ // Assign default colors to groups
69
+ const groupColors = {};
70
+ importResult.groups.forEach((group, idx) => {
71
+ groupColors[group] = CUSTOM_CELL_PALETTE[idx % CUSTOM_CELL_PALETTE.length];
72
+ });
73
+ const newSet = {
74
+ id,
75
+ name,
76
+ cells: importResult.cells,
77
+ unmatchedTxIds: importResult.unmatchedTxIds,
78
+ groups: importResult.groups,
79
+ extraColumns: importResult.extraColumns,
80
+ baseSize: 50,
81
+ opacity: 0.7,
82
+ defaultColor: CUSTOM_CELL_PALETTE[0],
83
+ groupColors,
84
+ visible: true,
85
+ visibleGroups: new Set(importResult.groups)
86
+ };
87
+ this.sets.push(newSet);
88
+ this.version++;
89
+ return newSet;
90
+ }
91
+ /**
92
+ * Remove a set by ID
93
+ */
94
+ removeSet(setId) {
95
+ const index = this.sets.findIndex(s => s.id === setId);
96
+ if (index !== -1) {
97
+ // Use filter to create a new array for proper reactivity
98
+ this.sets = this.sets.filter(s => s.id !== setId);
99
+ this.version++;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ /**
105
+ * Get a set by ID
106
+ */
107
+ getSet(setId) {
108
+ return this.sets.find(s => s.id === setId);
109
+ }
110
+ /**
111
+ * Toggle set visibility
112
+ */
113
+ toggleSetVisibility(setId) {
114
+ const set = this.getSet(setId);
115
+ if (set) {
116
+ set.visible = !set.visible;
117
+ this.version++;
118
+ }
119
+ }
120
+ /**
121
+ * Toggle group visibility within a set
122
+ */
123
+ toggleGroupVisibility(setId, group) {
124
+ const set = this.getSet(setId);
125
+ if (set) {
126
+ if (set.visibleGroups.has(group)) {
127
+ set.visibleGroups.delete(group);
128
+ }
129
+ else {
130
+ set.visibleGroups.add(group);
131
+ }
132
+ this.version++;
133
+ }
134
+ }
135
+ /**
136
+ * Set group color
137
+ */
138
+ setGroupColor(setId, group, color) {
139
+ const set = this.getSet(setId);
140
+ if (set) {
141
+ set.groupColors[group] = color;
142
+ this.version++;
143
+ }
144
+ }
145
+ /**
146
+ * Update set display settings
147
+ */
148
+ updateSetSettings(setId, settings) {
149
+ const set = this.getSet(setId);
150
+ if (set) {
151
+ if (settings.baseSize !== undefined)
152
+ set.baseSize = settings.baseSize;
153
+ if (settings.opacity !== undefined)
154
+ set.opacity = settings.opacity;
155
+ if (settings.defaultColor !== undefined)
156
+ set.defaultColor = settings.defaultColor;
157
+ this.version++;
158
+ }
159
+ }
160
+ /**
161
+ * Rename a set
162
+ */
163
+ renameSet(setId, newName) {
164
+ const set = this.getSet(setId);
165
+ if (set) {
166
+ set.name = newName;
167
+ this.version++;
168
+ }
169
+ }
170
+ /**
171
+ * Get visible cells for a set (filtered by visible groups)
172
+ */
173
+ getVisibleCells(setId) {
174
+ const set = this.getSet(setId);
175
+ if (!set || !set.visible)
176
+ return [];
177
+ return set.cells.filter(c => c.resolvedCell && set.visibleGroups.has(c.customGroup));
178
+ }
179
+ /**
180
+ * Re-resolve cells after main cell data changes
181
+ */
182
+ refreshResolutions() {
183
+ const cellLookup = buildCellLookup(this.cellDataStore.rawCells);
184
+ for (const set of this.sets) {
185
+ for (const cell of set.cells) {
186
+ cell.resolvedCell = cellLookup.get(cell.txId);
187
+ }
188
+ }
189
+ this.version++;
190
+ }
191
+ /**
192
+ * Load from localStorage
193
+ */
194
+ load() {
195
+ try {
196
+ const stored = localStorage.getItem(this.storageKey);
197
+ if (stored) {
198
+ const data = JSON.parse(stored);
199
+ // Reconstruct sets with proper Set objects
200
+ this.sets = data.map((setData) => ({
201
+ ...setData,
202
+ visibleGroups: new Set(setData.visibleGroups || []),
203
+ cells: setData.cells || []
204
+ }));
205
+ // Re-resolve cells
206
+ this.refreshResolutions();
207
+ }
208
+ }
209
+ catch (e) {
210
+ console.warn('[CustomCellSetsStore] Failed to load from storage', e);
211
+ }
212
+ }
213
+ /**
214
+ * Save to localStorage
215
+ */
216
+ save() {
217
+ try {
218
+ // Convert Sets to arrays for JSON serialization
219
+ const data = this.sets.map(set => ({
220
+ ...set,
221
+ visibleGroups: Array.from(set.visibleGroups),
222
+ // Don't persist resolved cells - will re-resolve on load
223
+ cells: set.cells.map(c => ({
224
+ txId: c.txId,
225
+ customGroup: c.customGroup,
226
+ sizeFactor: c.sizeFactor,
227
+ extraFields: c.extraFields
228
+ }))
229
+ }));
230
+ localStorage.setItem(this.storageKey, JSON.stringify(data));
231
+ }
232
+ catch (e) {
233
+ console.warn('[CustomCellSetsStore] Failed to save to storage', e);
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * Factory function to create a custom cell sets store
239
+ */
240
+ export function createCustomCellSetsStore(cellDataStore, namespace = 'default') {
241
+ return new CustomCellSetsStore(cellDataStore, namespace);
242
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Custom Cells Stores - Barrel Export
3
+ */
4
+ export { CustomCellSetsStore, createCustomCellSetsStore } from './custom-cell-sets.svelte';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Custom Cells Stores - Barrel Export
3
+ */
4
+ export { CustomCellSetsStore, createCustomCellSetsStore } from './custom-cell-sets.svelte';
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Custom Cells Feature - Type Definitions
3
+ *
4
+ * Types for ad-hoc cell layers loaded from CSV files.
5
+ * Custom cells reference existing cells by txId and add custom grouping/sizing.
6
+ */
7
+ import type { Cell } from '../../../../shared/demo';
8
+ /**
9
+ * A custom cell entry from CSV import
10
+ */
11
+ export interface CustomCell {
12
+ /** Required: Reference to cell in main data store */
13
+ txId: string;
14
+ /** Grouping field for TreeView (defaults to 'default' if not in CSV) */
15
+ customGroup: string;
16
+ /** Size multiplier for arc radius (defaults to 1) */
17
+ sizeFactor: number;
18
+ /** Any additional columns from CSV for tooltips */
19
+ extraFields: Record<string, string | number>;
20
+ /** Resolved cell data from main store (populated after import) */
21
+ resolvedCell?: Cell;
22
+ }
23
+ /**
24
+ * Import result from CSV parsing
25
+ */
26
+ export interface CustomCellImportResult {
27
+ /** Successfully parsed and matched cells */
28
+ cells: CustomCell[];
29
+ /** Cell IDs that weren't found in main data store */
30
+ unmatchedTxIds: string[];
31
+ /** Discovered custom groups */
32
+ groups: string[];
33
+ /** Extra column names found in CSV */
34
+ extraColumns: string[];
35
+ /** Total rows in CSV */
36
+ totalRows: number;
37
+ }
38
+ /**
39
+ * A custom cell set - represents one uploaded CSV
40
+ */
41
+ export interface CustomCellSet {
42
+ /** Unique identifier for this set */
43
+ id: string;
44
+ /** Display name (from filename or user input) */
45
+ name: string;
46
+ /** Cells in this set with resolved data */
47
+ cells: CustomCell[];
48
+ /** Cell IDs that weren't found during import */
49
+ unmatchedTxIds: string[];
50
+ /** All custom groups in this set */
51
+ groups: string[];
52
+ /** Extra column names for tooltip display */
53
+ extraColumns: string[];
54
+ /** Base arc radius in pixels (multiplied by sizeFactor per cell) */
55
+ baseSize: number;
56
+ /** Layer opacity (0-1) */
57
+ opacity: number;
58
+ /** Default color for groups without override */
59
+ defaultColor: string;
60
+ /** Per-group color overrides */
61
+ groupColors: Record<string, string>;
62
+ /** Whether this set's layer is visible */
63
+ visible: boolean;
64
+ /** Which groups are currently visible */
65
+ visibleGroups: Set<string>;
66
+ }
67
+ /**
68
+ * Configuration for creating a new custom cell set
69
+ */
70
+ export interface CustomCellSetConfig {
71
+ name: string;
72
+ cells: CustomCell[];
73
+ unmatchedTxIds?: string[];
74
+ groups?: string[];
75
+ extraColumns?: string[];
76
+ baseSize?: number;
77
+ opacity?: number;
78
+ defaultColor?: string;
79
+ }
80
+ /**
81
+ * Default color palette for custom cell groups
82
+ */
83
+ export declare const CUSTOM_CELL_PALETTE: string[];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Custom Cells Feature - Type Definitions
3
+ *
4
+ * Types for ad-hoc cell layers loaded from CSV files.
5
+ * Custom cells reference existing cells by txId and add custom grouping/sizing.
6
+ */
7
+ /**
8
+ * Default color palette for custom cell groups
9
+ */
10
+ export const CUSTOM_CELL_PALETTE = [
11
+ '#e41a1c', // Red
12
+ '#377eb8', // Blue
13
+ '#4daf4a', // Green
14
+ '#984ea3', // Purple
15
+ '#ff7f00', // Orange
16
+ '#ffff33', // Yellow
17
+ '#a65628', // Brown
18
+ '#f781bf', // Pink
19
+ '#999999', // Gray
20
+ '#66c2a5', // Teal
21
+ '#fc8d62', // Coral
22
+ '#8da0cb', // Periwinkle
23
+ ];
@@ -60,6 +60,7 @@
60
60
  let controlElement: HTMLDivElement;
61
61
  let collapsed = $state(initiallyCollapsed);
62
62
  let control: IControl | null = null;
63
+ let isAdded = false;
63
64
 
64
65
  // Reactively add/remove control when map becomes available/unavailable
65
66
  $effect(() => {
@@ -67,13 +68,29 @@
67
68
  if (map && controlElement) {
68
69
  addControl(map);
69
70
  return () => {
71
+ console.log(`[MapControl] Effect cleanup called for: ${title}`);
70
72
  removeControl(map);
71
73
  };
72
74
  }
73
75
  });
74
76
 
77
+ // Ensure control is removed when component is destroyed
78
+ onDestroy(() => {
79
+ console.log(`[MapControl] onDestroy called for: ${title}`);
80
+ const map = mapStore?.map;
81
+ if (map) {
82
+ removeControl(map);
83
+ }
84
+ // Also explicitly remove from DOM as fallback
85
+ // (Mapbox moves the element to its own container)
86
+ if (controlElement?.parentNode) {
87
+ controlElement.parentNode.removeChild(controlElement);
88
+ }
89
+ });
90
+
75
91
  function addControl(map: MapboxMap) {
76
- if (control) return;
92
+ if (control || isAdded) return;
93
+ isAdded = true;
77
94
 
78
95
  // Create a custom Mapbox control
79
96
  control = {
@@ -81,7 +98,7 @@
81
98
  return controlElement;
82
99
  },
83
100
  onRemove: () => {
84
- // Cleanup handled in onDestroy/effect cleanup
101
+ // Mapbox will remove the element from its container
85
102
  }
86
103
  };
87
104
 
@@ -90,12 +107,19 @@
90
107
 
91
108
  function removeControl(map: MapboxMap) {
92
109
  if (control) {
110
+ console.log(`[MapControl] Removing control: ${title}`);
93
111
  try {
94
112
  map.removeControl(control);
95
113
  } catch (e) {
96
- // Control may already be removed or map destroyed
114
+ console.log(`[MapControl] Error removing control (may already be removed): ${title}`, e);
97
115
  }
98
116
  control = null;
117
+ isAdded = false;
118
+ }
119
+ // Fallback: ensure element is removed from DOM
120
+ if (controlElement?.parentNode) {
121
+ console.log(`[MapControl] Fallback DOM removal for: ${title}`);
122
+ controlElement.parentNode.removeChild(controlElement);
99
123
  }
100
124
  }
101
125
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.124",
3
+ "version": "0.0.126",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",