@smartnet360/svelte-components 0.0.11 → 0.0.13
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.
- package/dist/apps/antenna-pattern/components/AntennaControls.svelte +506 -0
- package/dist/apps/antenna-pattern/components/AntennaControls.svelte.d.ts +16 -0
- package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte +62 -0
- package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte.d.ts +18 -0
- package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +339 -0
- package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte.d.ts +3 -0
- package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +299 -0
- package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte.d.ts +24 -0
- package/dist/apps/antenna-pattern/components/DbNotification.svelte +67 -0
- package/dist/apps/antenna-pattern/components/DbNotification.svelte.d.ts +18 -0
- package/dist/apps/antenna-pattern/components/JsonImporter.svelte +116 -0
- package/dist/apps/antenna-pattern/components/JsonImporter.svelte.d.ts +18 -0
- package/dist/apps/antenna-pattern/components/MSIConverter.svelte +207 -0
- package/dist/apps/antenna-pattern/components/MSIConverter.svelte.d.ts +18 -0
- package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +252 -0
- package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte.d.ts +22 -0
- package/dist/apps/antenna-pattern/db.d.ts +24 -0
- package/dist/apps/antenna-pattern/db.js +15 -0
- package/dist/apps/antenna-pattern/helpers/plotly-utils.d.ts +54 -0
- package/dist/apps/antenna-pattern/helpers/plotly-utils.js +324 -0
- package/dist/apps/antenna-pattern/index.d.ts +15 -0
- package/dist/apps/antenna-pattern/index.js +19 -0
- package/dist/apps/antenna-pattern/stores/antennas.d.ts +5 -0
- package/dist/apps/antenna-pattern/stores/antennas.js +14 -0
- package/dist/apps/antenna-pattern/stores/db-status.d.ts +28 -0
- package/dist/apps/antenna-pattern/stores/db-status.js +34 -0
- package/dist/apps/antenna-pattern/utils/db-utils.d.ts +9 -0
- package/dist/apps/antenna-pattern/utils/db-utils.js +180 -0
- package/dist/apps/antenna-pattern/utils/init-db.d.ts +2 -0
- package/dist/apps/antenna-pattern/utils/init-db.js +95 -0
- package/dist/apps/antenna-pattern/utils/msi-parser.d.ts +3 -0
- package/dist/apps/antenna-pattern/utils/msi-parser.js +197 -0
- package/dist/apps/antenna-pattern/utils/plotly-chart-utils.d.ts +101 -0
- package/dist/apps/antenna-pattern/utils/plotly-chart-utils.js +152 -0
- package/dist/apps/index.d.ts +1 -0
- package/dist/apps/index.js +6 -0
- package/dist/{Charts → core/Charts}/ChartComponent.svelte +131 -39
- package/dist/{Charts → core/Charts}/charts.model.d.ts +1 -1
- package/dist/{Desktop → core/Desktop}/GridRenderer.svelte +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +6 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -2
- package/package.json +6 -2
- /package/dist/{Charts → core/Charts}/ChartCard.svelte +0 -0
- /package/dist/{Charts → core/Charts}/ChartCard.svelte.d.ts +0 -0
- /package/dist/{Charts → core/Charts}/ChartComponent.svelte.d.ts +0 -0
- /package/dist/{Charts → core/Charts}/adapt.d.ts +0 -0
- /package/dist/{Charts → core/Charts}/adapt.js +0 -0
- /package/dist/{Charts → core/Charts}/charts.model.js +0 -0
- /package/dist/{Charts → core/Charts}/data-utils.d.ts +0 -0
- /package/dist/{Charts → core/Charts}/data-utils.js +0 -0
- /package/dist/{Charts → core/Charts}/index.d.ts +0 -0
- /package/dist/{Charts → core/Charts}/index.js +0 -0
- /package/dist/{Charts → core/Charts}/plotly.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Desktop.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/Desktop.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/index.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/index.js +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.js +0 -0
- /package/dist/{Desktop → core/Desktop}/GridRenderer.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/index.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/GridSelector/index.js +0 -0
- /package/dist/{Desktop → core/Desktop}/GridViewer.svelte +0 -0
- /package/dist/{Desktop → core/Desktop}/GridViewer.svelte.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/gridLayouts.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/gridLayouts.js +0 -0
- /package/dist/{Desktop → core/Desktop}/index.d.ts +0 -0
- /package/dist/{Desktop → core/Desktop}/index.js +0 -0
- /package/dist/{Desktop → core/Desktop}/launchHelpers.d.ts +0 -0
- /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';
|
@@ -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
|
-
|
186
|
-
|
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
|
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
|
+
×
|
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:
|
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:
|
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:
|
447
|
-
right:
|
448
|
-
background: rgba(
|
449
|
-
|
450
|
-
border:
|
451
|
-
width:
|
452
|
-
height:
|
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
|
-
|
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(
|
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 '
|
8
|
+
import { Half, Quarter, ResizeHandle, resizeStore } from '../../index.js';
|
9
9
|
import type { GridConfiguration } from './gridLayouts.js';
|
10
10
|
|
11
11
|
// Props
|
package/dist/index.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
export
|
2
|
-
export
|
1
|
+
export * from './core/index.js';
|
2
|
+
export * from './apps/index.js';
|
package/dist/index.js
CHANGED
@@ -1,2 +1,6 @@
|
|
1
|
-
|
2
|
-
|
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.
|
3
|
+
"version": "0.0.13",
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|