@smartnet360/svelte-components 0.0.11 → 0.0.12

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 (88) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaControls.svelte +424 -0
  2. package/dist/apps/antenna-pattern/components/AntennaControls.svelte.d.ts +16 -0
  3. package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte +62 -0
  4. package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte.d.ts +18 -0
  5. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +339 -0
  6. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte.d.ts +3 -0
  7. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +299 -0
  8. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte.d.ts +24 -0
  9. package/dist/apps/antenna-pattern/components/DbNotification.svelte +67 -0
  10. package/dist/apps/antenna-pattern/components/DbNotification.svelte.d.ts +18 -0
  11. package/dist/apps/antenna-pattern/components/JsonImporter.svelte +116 -0
  12. package/dist/apps/antenna-pattern/components/JsonImporter.svelte.d.ts +18 -0
  13. package/dist/apps/antenna-pattern/components/MSIConverter.svelte +209 -0
  14. package/dist/apps/antenna-pattern/components/MSIConverter.svelte.d.ts +18 -0
  15. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +252 -0
  16. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte.d.ts +22 -0
  17. package/dist/apps/antenna-pattern/db.d.ts +24 -0
  18. package/dist/apps/antenna-pattern/db.js +15 -0
  19. package/dist/apps/antenna-pattern/helpers/plotly-utils.d.ts +54 -0
  20. package/dist/apps/antenna-pattern/helpers/plotly-utils.js +324 -0
  21. package/dist/apps/antenna-pattern/index.d.ts +15 -0
  22. package/dist/apps/antenna-pattern/index.js +19 -0
  23. package/dist/apps/antenna-pattern/stores/antennas.d.ts +5 -0
  24. package/dist/apps/antenna-pattern/stores/antennas.js +14 -0
  25. package/dist/apps/antenna-pattern/stores/db-status.d.ts +28 -0
  26. package/dist/apps/antenna-pattern/stores/db-status.js +34 -0
  27. package/dist/apps/antenna-pattern/utils/db-utils.d.ts +9 -0
  28. package/dist/apps/antenna-pattern/utils/db-utils.js +180 -0
  29. package/dist/apps/antenna-pattern/utils/init-db.d.ts +2 -0
  30. package/dist/apps/antenna-pattern/utils/init-db.js +95 -0
  31. package/dist/apps/antenna-pattern/utils/msi-parser.d.ts +3 -0
  32. package/dist/apps/antenna-pattern/utils/msi-parser.js +197 -0
  33. package/dist/apps/antenna-pattern/utils/plotly-chart-utils.d.ts +101 -0
  34. package/dist/apps/antenna-pattern/utils/plotly-chart-utils.js +152 -0
  35. package/dist/apps/index.d.ts +1 -0
  36. package/dist/apps/index.js +6 -0
  37. package/dist/{Charts → core/Charts}/ChartComponent.svelte +131 -39
  38. package/dist/{Charts → core/Charts}/charts.model.d.ts +1 -1
  39. package/dist/{Desktop → core/Desktop}/GridRenderer.svelte +1 -1
  40. package/dist/core/index.d.ts +2 -0
  41. package/dist/core/index.js +6 -0
  42. package/dist/index.d.ts +2 -2
  43. package/dist/index.js +6 -2
  44. package/package.json +6 -2
  45. /package/dist/{Charts → core/Charts}/ChartCard.svelte +0 -0
  46. /package/dist/{Charts → core/Charts}/ChartCard.svelte.d.ts +0 -0
  47. /package/dist/{Charts → core/Charts}/ChartComponent.svelte.d.ts +0 -0
  48. /package/dist/{Charts → core/Charts}/adapt.d.ts +0 -0
  49. /package/dist/{Charts → core/Charts}/adapt.js +0 -0
  50. /package/dist/{Charts → core/Charts}/charts.model.js +0 -0
  51. /package/dist/{Charts → core/Charts}/data-utils.d.ts +0 -0
  52. /package/dist/{Charts → core/Charts}/data-utils.js +0 -0
  53. /package/dist/{Charts → core/Charts}/index.d.ts +0 -0
  54. /package/dist/{Charts → core/Charts}/index.js +0 -0
  55. /package/dist/{Charts → core/Charts}/plotly.d.ts +0 -0
  56. /package/dist/{Desktop → core/Desktop}/Desktop.svelte +0 -0
  57. /package/dist/{Desktop → core/Desktop}/Desktop.svelte.d.ts +0 -0
  58. /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte +0 -0
  59. /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte.d.ts +0 -0
  60. /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte +0 -0
  61. /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte.d.ts +0 -0
  62. /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte +0 -0
  63. /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte.d.ts +0 -0
  64. /package/dist/{Desktop → core/Desktop}/Grid/index.d.ts +0 -0
  65. /package/dist/{Desktop → core/Desktop}/Grid/index.js +0 -0
  66. /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.d.ts +0 -0
  67. /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.js +0 -0
  68. /package/dist/{Desktop → core/Desktop}/GridRenderer.svelte.d.ts +0 -0
  69. /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte +0 -0
  70. /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte.d.ts +0 -0
  71. /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte +0 -0
  72. /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte.d.ts +0 -0
  73. /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte +0 -0
  74. /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte.d.ts +0 -0
  75. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte +0 -0
  76. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte.d.ts +0 -0
  77. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte +0 -0
  78. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte.d.ts +0 -0
  79. /package/dist/{Desktop → core/Desktop}/GridSelector/index.d.ts +0 -0
  80. /package/dist/{Desktop → core/Desktop}/GridSelector/index.js +0 -0
  81. /package/dist/{Desktop → core/Desktop}/GridViewer.svelte +0 -0
  82. /package/dist/{Desktop → core/Desktop}/GridViewer.svelte.d.ts +0 -0
  83. /package/dist/{Desktop → core/Desktop}/gridLayouts.d.ts +0 -0
  84. /package/dist/{Desktop → core/Desktop}/gridLayouts.js +0 -0
  85. /package/dist/{Desktop → core/Desktop}/index.d.ts +0 -0
  86. /package/dist/{Desktop → core/Desktop}/index.js +0 -0
  87. /package/dist/{Desktop → core/Desktop}/launchHelpers.d.ts +0 -0
  88. /package/dist/{Desktop → core/Desktop}/launchHelpers.js +0 -0
@@ -0,0 +1,101 @@
1
+ import type { Antenna } from '../db';
2
+ export interface PlotlyTraceData {
3
+ r: number[];
4
+ theta: number[];
5
+ type: 'scatterpolar';
6
+ mode: 'lines';
7
+ name: string;
8
+ line: {
9
+ color: string;
10
+ width: number;
11
+ dash?: string;
12
+ };
13
+ }
14
+ /**
15
+ * Convert antenna pattern data to Plotly trace format
16
+ */
17
+ export declare function convertAntennaPattern(pattern: number[], name: string, color: string, width?: number, mechanicalTilt?: number): PlotlyTraceData;
18
+ /**
19
+ * Get line color based on tilt values
20
+ */
21
+ export declare function getLineColor(eTilt: number, mTilt: number, baseColor: string): string;
22
+ /**
23
+ * Get line width based on tilt values
24
+ */
25
+ export declare function getLineWidth(eTilt: number, mTilt: number): number;
26
+ /**
27
+ * Create Plotly chart layout configuration
28
+ */
29
+ export declare function createChartLayout(title: string): {
30
+ title: {
31
+ text: string;
32
+ font: {
33
+ size: number;
34
+ color: string;
35
+ };
36
+ x: number;
37
+ y: number;
38
+ };
39
+ polar: {
40
+ radialaxis: {
41
+ visible: boolean;
42
+ range: number[];
43
+ tickfont: {
44
+ size: number;
45
+ color: string;
46
+ };
47
+ gridcolor: string;
48
+ linecolor: string;
49
+ tickmode: string;
50
+ tick0: number;
51
+ dtick: number;
52
+ ticksuffix: string;
53
+ };
54
+ angularaxis: {
55
+ visible: boolean;
56
+ tickfont: {
57
+ size: number;
58
+ color: string;
59
+ };
60
+ gridcolor: string;
61
+ linecolor: string;
62
+ direction: string;
63
+ period: number;
64
+ rotation: number;
65
+ ticksuffix: string;
66
+ };
67
+ bgcolor: string;
68
+ };
69
+ margin: {
70
+ t: number;
71
+ r: number;
72
+ b: number;
73
+ l: number;
74
+ };
75
+ height: number;
76
+ paper_bgcolor: string;
77
+ plot_bgcolor: string;
78
+ legend: {
79
+ orientation: string;
80
+ x: number;
81
+ y: number;
82
+ xanchor: string;
83
+ };
84
+ };
85
+ /**
86
+ * Create Plotly chart configuration
87
+ */
88
+ export declare function createChartConfig(): {
89
+ responsive: boolean;
90
+ displayModeBar: boolean;
91
+ displaylogo: boolean;
92
+ modeBarButtonsToRemove: string[];
93
+ };
94
+ /**
95
+ * Generate chart data for antenna patterns
96
+ */
97
+ export declare function createAntennaChartData(selectedAntenna: Antenna | null, selectedAntenna2: Antenna | null, viewMode: 'single' | 'compare', showHorizontalPatterns: boolean, showVerticalPatterns: boolean, ant1ElectricalTilt: number, ant1MechanicalTilt: number, ant2ElectricalTilt: number, ant2MechanicalTilt: number): PlotlyTraceData[];
98
+ /**
99
+ * Generate chart title based on viewing mode and selected antennas
100
+ */
101
+ export declare function generateChartTitle(viewMode: 'single' | 'compare', selectedAntenna: Antenna | null, selectedAntenna2: Antenna | null): string;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Convert antenna pattern data to Plotly trace format
3
+ */
4
+ export function convertAntennaPattern(pattern, name, color, width = 2, mechanicalTilt = 0) {
5
+ // Convert attenuation to dB (negate values)
6
+ let processedPattern = pattern.map(value => -value);
7
+ // Apply mechanical tilt by shifting the pattern
8
+ if (mechanicalTilt !== 0) {
9
+ const shiftedPattern = new Array(360).fill(0);
10
+ for (let i = 0; i < 360; i++) {
11
+ const sourceIndex = (i - mechanicalTilt + 360) % 360;
12
+ shiftedPattern[i] = processedPattern[sourceIndex] || 0;
13
+ }
14
+ processedPattern = shiftedPattern;
15
+ }
16
+ // Generate theta values (0-359 degrees) with 90° counter-clockwise rotation
17
+ const theta = Array.from({ length: pattern.length }, (_, i) => {
18
+ if (name.includes('Vertical')) {
19
+ return (i) % 360; // Rotate vertical patterns 180° (90° for axis + 90° counter-clockwise)
20
+ }
21
+ return (i) % 360; // Rotate horizontal patterns 90° counter-clockwise
22
+ });
23
+ return {
24
+ r: processedPattern,
25
+ theta,
26
+ type: 'scatterpolar',
27
+ mode: 'lines',
28
+ name,
29
+ line: {
30
+ color,
31
+ width,
32
+ dash: 'solid' // Always solid lines
33
+ }
34
+ };
35
+ }
36
+ /**
37
+ * Get line color based on tilt values
38
+ */
39
+ export function getLineColor(eTilt, mTilt, baseColor) {
40
+ // Always return the base color - no dynamic color changes
41
+ return baseColor;
42
+ }
43
+ /**
44
+ * Get line width based on tilt values
45
+ */
46
+ export function getLineWidth(eTilt, mTilt) {
47
+ // Always return fixed line width - no dynamic width changes
48
+ return 2;
49
+ }
50
+ /**
51
+ * Create Plotly chart layout configuration
52
+ */
53
+ export function createChartLayout(title) {
54
+ return {
55
+ title: {
56
+ text: title,
57
+ font: { size: 18, color: '#212529' },
58
+ x: 0.5,
59
+ y: 0.95
60
+ },
61
+ polar: {
62
+ radialaxis: {
63
+ visible: true,
64
+ range: [-70, 0],
65
+ tickfont: { size: 11, color: '#495057' },
66
+ gridcolor: 'rgba(108, 117, 125, 0.2)',
67
+ linecolor: 'rgba(108, 117, 125, 0.4)',
68
+ tickmode: 'linear',
69
+ tick0: -70,
70
+ dtick: 10,
71
+ ticksuffix: ' dB'
72
+ },
73
+ angularaxis: {
74
+ visible: true,
75
+ tickfont: { size: 11, color: '#495057' },
76
+ gridcolor: 'rgba(108, 117, 125, 0.2)',
77
+ linecolor: 'rgba(108, 117, 125, 0.4)',
78
+ direction: 'clockwise',
79
+ period: 360,
80
+ rotation: 0,
81
+ ticksuffix: '°'
82
+ },
83
+ bgcolor: 'rgba(248, 249, 250, 0.5)'
84
+ },
85
+ margin: { t: 60, r: 40, b: 60, l: 40 },
86
+ height: 600,
87
+ paper_bgcolor: 'rgba(255, 255, 255, 0.95)',
88
+ plot_bgcolor: 'rgba(248, 249, 250, 0.3)',
89
+ legend: {
90
+ orientation: 'h',
91
+ x: 0.5,
92
+ y: -0.1,
93
+ xanchor: 'center'
94
+ }
95
+ };
96
+ }
97
+ /**
98
+ * Create Plotly chart configuration
99
+ */
100
+ export function createChartConfig() {
101
+ return {
102
+ responsive: true,
103
+ displayModeBar: true,
104
+ displaylogo: false,
105
+ modeBarButtonsToRemove: [
106
+ 'zoom2d', 'pan2d', 'select2d', 'lasso2d',
107
+ 'zoomIn2d', 'zoomOut2d', 'autoScale2d',
108
+ 'resetScale2d', 'toggleSpikelines', 'toImage'
109
+ ]
110
+ };
111
+ }
112
+ /**
113
+ * Generate chart data for antenna patterns
114
+ */
115
+ export function createAntennaChartData(selectedAntenna, selectedAntenna2, viewMode, showHorizontalPatterns, showVerticalPatterns, ant1ElectricalTilt, ant1MechanicalTilt, ant2ElectricalTilt, ant2MechanicalTilt) {
116
+ const data = [];
117
+ // Create antenna 1 pattern data based on visibility settings
118
+ if (selectedAntenna) {
119
+ if (showHorizontalPatterns) {
120
+ const horizontalData1 = convertAntennaPattern(selectedAntenna.pattern || [], 'Antenna 1 - Horizontal', getLineColor(ant1ElectricalTilt, ant1MechanicalTilt, '#0066cc'), getLineWidth(ant1ElectricalTilt, ant1MechanicalTilt));
121
+ data.push(horizontalData1);
122
+ }
123
+ if (showVerticalPatterns) {
124
+ const verticalData1 = convertAntennaPattern(selectedAntenna.vertical_pattern || [], 'Antenna 1 - Vertical', getLineColor(ant1ElectricalTilt, ant1MechanicalTilt, '#003d7a'), getLineWidth(ant1ElectricalTilt, ant1MechanicalTilt), ant1MechanicalTilt);
125
+ data.push(verticalData1);
126
+ }
127
+ }
128
+ // Add second antenna if in compare mode and antenna 2 is selected
129
+ if (viewMode === 'compare' && selectedAntenna2) {
130
+ if (showHorizontalPatterns) {
131
+ const horizontalData2 = convertAntennaPattern(selectedAntenna2.pattern || [], 'Antenna 2 - Horizontal', getLineColor(ant2ElectricalTilt, ant2MechanicalTilt, '#ffd700'), getLineWidth(ant2ElectricalTilt, ant2MechanicalTilt));
132
+ data.push(horizontalData2);
133
+ }
134
+ if (showVerticalPatterns) {
135
+ const verticalData2 = convertAntennaPattern(selectedAntenna2.vertical_pattern || [], 'Antenna 2 - Vertical', getLineColor(ant2ElectricalTilt, ant2MechanicalTilt, '#e6c200'), getLineWidth(ant2ElectricalTilt, ant2MechanicalTilt), ant2MechanicalTilt);
136
+ data.push(verticalData2);
137
+ }
138
+ }
139
+ return data;
140
+ }
141
+ /**
142
+ * Generate chart title based on viewing mode and selected antennas
143
+ */
144
+ export function generateChartTitle(viewMode, selectedAntenna, selectedAntenna2) {
145
+ if (viewMode === 'compare' && selectedAntenna && selectedAntenna2) {
146
+ return `Compare: ${selectedAntenna.name} vs ${selectedAntenna2.name}`;
147
+ }
148
+ if (selectedAntenna) {
149
+ return `Antenna Pattern: ${selectedAntenna.name}`;
150
+ }
151
+ return 'Antenna Pattern Viewer';
152
+ }
@@ -0,0 +1 @@
1
+ export * from './antenna-pattern/index.js';
@@ -0,0 +1,6 @@
1
+ // Apps barrel export
2
+ // Re-export all app modules for clean consumption
3
+ // Antenna Pattern Analysis App
4
+ export * from './antenna-pattern/index.js';
5
+ // Test app (if needed for demos)
6
+ // export * from './test/index.js';
@@ -17,6 +17,7 @@
17
17
  const GRID_DIMENSIONS: Record<ChartGrid, { rows: number; columns: number }> = {
18
18
  '2x2': { rows: 2, columns: 2 },
19
19
  '3x3': { rows: 3, columns: 3 },
20
+ '4x4': { rows: 4, columns: 4 },
20
21
  '1x2': { rows: 1, columns: 2 },
21
22
  '1x4': { rows: 1, columns: 4 },
22
23
  '1x8': { rows: 1, columns: 8 }
@@ -53,6 +54,10 @@
53
54
 
54
55
  // Internal tab state management
55
56
  let activeTabId = $state(layout.sections[0]?.id || '');
57
+
58
+ // ScrollSpy state management
59
+ let activeSectionId = $state(layout.sections[0]?.id || '');
60
+ let scrollspyContent = $state<HTMLDivElement | null>(null);
56
61
 
57
62
  let componentElement: HTMLDivElement;
58
63
  let contextMenuElement = $state<HTMLDivElement | null>(null);
@@ -129,6 +134,59 @@
129
134
  }
130
135
  }
131
136
 
137
+ // ScrollSpy functionality
138
+ function updateActiveSection() {
139
+ const content = scrollspyContent;
140
+ if (!content || mode !== 'scrollspy') return;
141
+
142
+ const scrollTop = content.scrollTop;
143
+ const containerHeight = content.clientHeight;
144
+
145
+ // Find which section is most visible
146
+ let mostVisibleSection = layout.sections[0]?.id || '';
147
+ let maxVisibleArea = 0;
148
+
149
+ layout.sections.forEach(section => {
150
+ const element = content.querySelector(`#${section.id}`) as HTMLElement;
151
+ if (!element) return;
152
+
153
+ const rect = element.getBoundingClientRect();
154
+ const containerRect = content.getBoundingClientRect();
155
+
156
+ // Calculate visible area of this section
157
+ const visibleTop = Math.max(0, containerRect.top - rect.top);
158
+ const visibleBottom = Math.min(rect.height, containerRect.bottom - rect.top);
159
+ const visibleArea = Math.max(0, visibleBottom - visibleTop);
160
+
161
+ if (visibleArea > maxVisibleArea) {
162
+ maxVisibleArea = visibleArea;
163
+ mostVisibleSection = section.id;
164
+ }
165
+ });
166
+
167
+ if (mostVisibleSection !== activeSectionId) {
168
+ activeSectionId = mostVisibleSection;
169
+ }
170
+ }
171
+
172
+ function scrollToSection(sectionId: string, event?: Event) {
173
+ if (event) {
174
+ event.preventDefault();
175
+ }
176
+
177
+ const content = scrollspyContent;
178
+ if (!content) return;
179
+
180
+ const element = content.querySelector(`#${sectionId}`) as HTMLElement;
181
+ if (element) {
182
+ element.scrollIntoView({
183
+ behavior: 'smooth',
184
+ block: 'start'
185
+ });
186
+ activeSectionId = sectionId;
187
+ }
188
+ }
189
+
132
190
  onMount(() => {
133
191
  const handleKeydown = (event: KeyboardEvent) => {
134
192
  if (event.key === 'Escape') {
@@ -146,12 +204,26 @@
146
204
  closeContextMenu();
147
205
  };
148
206
 
207
+ const handleScrollSpyScroll = () => {
208
+ updateActiveSection();
209
+ };
210
+
149
211
  window.addEventListener('keydown', handleKeydown);
150
212
  window.addEventListener('click', handleGlobalClick);
213
+
214
+ // Add scroll listener for scrollspy mode
215
+ if (scrollspyContent && mode === 'scrollspy') {
216
+ scrollspyContent.addEventListener('scroll', handleScrollSpyScroll);
217
+ // Initialize active section
218
+ updateActiveSection();
219
+ }
151
220
 
152
221
  return () => {
153
222
  window.removeEventListener('keydown', handleKeydown);
154
223
  window.removeEventListener('click', handleGlobalClick);
224
+ if (scrollspyContent) {
225
+ scrollspyContent.removeEventListener('scroll', handleScrollSpyScroll);
226
+ }
155
227
  };
156
228
  });
157
229
  </script>
@@ -182,29 +254,8 @@
182
254
  {/snippet}
183
255
 
184
256
  <div class="chart-component" bind:this={componentElement}>
185
- {#if zoomedChart}
186
- {@const activeZoom = zoomedChart as ZoomState}
187
- <div
188
- class="zoom-overlay"
189
- role="button"
190
- tabindex="0"
191
- onclick={handleOverlayClick}
192
- onkeydown={handleOverlayKeydown}
193
- >
194
- <div class="zoom-container">
195
- <button type="button" class="zoom-close" onclick={exitZoom} aria-label="Exit zoom">×</button>
196
- <ChartCard
197
- chart={activeZoom.chart}
198
- {data}
199
- {markers}
200
- {plotlyLayout}
201
- {enableAdaptation}
202
- sectionId={activeZoom.section.id}
203
- on:chartcontextmenu={(event) => handleChartContextMenu(event.detail, activeZoom.section)}
204
- />
205
- </div>
206
- </div>
207
- {:else if mode === 'tabs'}
257
+ <!-- Always render the main content (tabs or scrollspy) -->
258
+ {#if mode === 'tabs'}
208
259
  <!-- Tab Mode with Navigation -->
209
260
  <div class="tabs-container">
210
261
  <!-- Tab Navigation -->
@@ -247,14 +298,20 @@
247
298
  <ul class="nav nav-pills">
248
299
  {#each layout.sections as section}
249
300
  <li class="nav-item">
250
- <a class="nav-link" href="#{section.id}">{section.title}</a>
301
+ <a
302
+ class="nav-link {section.id === activeSectionId ? 'active' : ''}"
303
+ href="#{section.id}"
304
+ onclick={(e) => scrollToSection(section.id, e)}
305
+ >
306
+ {section.title}
307
+ </a>
251
308
  </li>
252
309
  {/each}
253
310
  </ul>
254
311
  </nav>
255
312
 
256
313
  <!-- ScrollSpy Content -->
257
- <div class="scrollspy-content">
314
+ <div class="scrollspy-content" bind:this={scrollspyContent}>
258
315
  {#each layout.sections as section}
259
316
  <div class="section-content" id="{section.id}">
260
317
  <!-- Chart Grid -->
@@ -265,6 +322,33 @@
265
322
  </div>
266
323
  {/if}
267
324
 
325
+ <!-- Zoom Overlay - rendered on top when active -->
326
+ {#if zoomedChart}
327
+ {@const activeZoom = zoomedChart as ZoomState}
328
+ <div
329
+ class="zoom-overlay"
330
+ role="button"
331
+ tabindex="0"
332
+ onclick={handleOverlayClick}
333
+ onkeydown={handleOverlayKeydown}
334
+ >
335
+ <div class="zoom-container">
336
+ <button type="button" class="zoom-close" onclick={exitZoom} aria-label="Exit zoom">
337
+ &times;
338
+ </button>
339
+ <ChartCard
340
+ chart={activeZoom.chart}
341
+ {data}
342
+ {markers}
343
+ {plotlyLayout}
344
+ {enableAdaptation}
345
+ sectionId={activeZoom.section.id}
346
+ on:chartcontextmenu={(event) => handleChartContextMenu(event.detail, activeZoom.section)}
347
+ />
348
+ </div>
349
+ </div>
350
+ {/if}
351
+
268
352
  {#if contextMenu.visible}
269
353
  <div
270
354
  class="chart-context-menu"
@@ -423,7 +507,7 @@
423
507
  justify-content: center;
424
508
  background: rgba(0, 0, 0, 0.4);
425
509
  z-index: 15;
426
- padding: 1.5rem;
510
+ padding: 0.5rem;
427
511
  box-sizing: border-box;
428
512
  }
429
513
 
@@ -431,7 +515,7 @@
431
515
  position: relative;
432
516
  width: 100%;
433
517
  height: 100%;
434
- max-width: 1200px;
518
+ max-width: 100%;
435
519
  max-height: 100%;
436
520
  display: flex;
437
521
  flex-direction: column;
@@ -443,26 +527,34 @@
443
527
 
444
528
  .zoom-close {
445
529
  position: absolute;
446
- top: 0.5rem;
447
- right: 0.5rem;
448
- background: rgba(0, 0, 0, 0.6);
449
- color: #ffffff;
450
- border: none;
451
- width: 2rem;
452
- height: 2rem;
453
- border-radius: 50%;
530
+ top: 1rem;
531
+ right: 1rem;
532
+ background: rgba(255, 255, 255, 0.9);
533
+ border: 1px solid rgba(0, 0, 0, 0.1);
534
+ border-radius: 8px;
535
+ width: 2.5rem;
536
+ height: 2.5rem;
454
537
  cursor: pointer;
455
- font-size: 1.25rem;
456
- line-height: 1;
457
538
  display: flex;
458
539
  align-items: center;
459
540
  justify-content: center;
460
- transition: background 0.2s ease;
541
+ backdrop-filter: blur(8px);
542
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
543
+ transition: all 0.2s ease;
461
544
  z-index: 1;
545
+ opacity: 0.8;
462
546
  }
463
547
 
464
548
  .zoom-close:hover {
465
- background: rgba(0, 0, 0, 0.75);
549
+ background: rgba(255, 255, 255, 1);
550
+ border-color: rgba(0, 0, 0, 0.2);
551
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
552
+ opacity: 1;
553
+ transform: scale(1.05);
554
+ }
555
+
556
+ .zoom-close:active {
557
+ transform: scale(0.95);
466
558
  }
467
559
 
468
560
  /* Chart grid adapts to layout configuration */
@@ -7,7 +7,7 @@ export interface KPI {
7
7
  color?: string;
8
8
  }
9
9
  export type ChartPosition = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
10
- export type ChartGrid = "2x2" | "3x3" | "1x2" | "1x4" | "1x8";
10
+ export type ChartGrid = "2x2" | "3x3" | "4x4" | "1x2" | "1x4" | "1x8";
11
11
  export interface Chart {
12
12
  pos?: ChartPosition;
13
13
  title: string;
@@ -5,7 +5,7 @@
5
5
  * Reusable component that renders a GridConfiguration using Half/Quarter components.
6
6
  * Can be used in full-screen mode, embedded in other apps, or anywhere else.
7
7
  */
8
- import { Half, Quarter, ResizeHandle, resizeStore } from '../index.js';
8
+ import { Half, Quarter, ResizeHandle, resizeStore } from '../../index.js';
9
9
  import type { GridConfiguration } from './gridLayouts.js';
10
10
 
11
11
  // Props
@@ -0,0 +1,2 @@
1
+ export * from './Desktop/index.js';
2
+ export * from './Charts/index.js';
@@ -0,0 +1,6 @@
1
+ // Core component library exports
2
+ // This barrel export consolidates Desktop and Charts components
3
+ // Desktop orchestration components
4
+ export * from './Desktop/index.js';
5
+ // Chart visualization components
6
+ export * from './Charts/index.js';
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { Half, Quarter, ResizeHandle, resizeStore, Desktop, GridSelector, GridRenderer, GridViewer, type ComponentConfig, getAllLayouts, getLayoutById, getLayoutsByCategory, getLayoutsOrdered, validateComponentAssignments, createGridConfiguration, type GridLayoutDefinition, type GridSlot, type ComponentAssignment, type GridConfiguration, createWindowLauncher, createTabLauncher, createNavigationLauncher, createModalLauncher } from './Desktop/index.js';
2
- export { ChartComponent, ChartCard, type Layout, type Section, type Chart, type KPI, type Mode, type Scale, type ChartMarker, createTimeSeriesTrace, getYAxisTitle, formatValue, processKPIData, createDefaultPlotlyLayout } from './Charts/index.js';
1
+ export * from './core/index.js';
2
+ export * from './apps/index.js';
package/dist/index.js CHANGED
@@ -1,2 +1,6 @@
1
- export { Half, Quarter, ResizeHandle, resizeStore, Desktop, GridSelector, GridRenderer, GridViewer, getAllLayouts, getLayoutById, getLayoutsByCategory, getLayoutsOrdered, validateComponentAssignments, createGridConfiguration, createWindowLauncher, createTabLauncher, createNavigationLauncher, createModalLauncher } from './Desktop/index.js';
2
- export { ChartComponent, ChartCard, createTimeSeriesTrace, getYAxisTitle, formatValue, processKPIData, createDefaultPlotlyLayout } from './Charts/index.js';
1
+ // Main library export - clean barrel export pattern
2
+ // This approach keeps the main index clean and allows for easy expansion
3
+ // Core components (Desktop orchestration + Charts)
4
+ export * from './core/index.js';
5
+ // Complete applications
6
+ export * from './apps/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -61,6 +61,10 @@
61
61
  ],
62
62
  "dependencies": {
63
63
  "bootstrap": "^5.2.3",
64
- "plotly.js-dist-min": "^3.1.0"
64
+ "plotly.js-dist-min": "^3.1.0",
65
+ "@sveltejs/adapter-static": "^3.0.9",
66
+ "bootstrap-icons": "^1.13.1",
67
+ "chart.js": "^4.4.9",
68
+ "dexie": "^4.0.11"
65
69
  }
66
70
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes