@smartnet360/svelte-components 0.0.50 → 0.0.53
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/site-check/SiteCheck.svelte +7 -1
- package/dist/apps/site-check/SiteCheck.svelte.d.ts +1 -0
- package/dist/apps/site-check/transforms.js +2 -2
- package/dist/core/Charts/ChartCard.svelte +6 -1
- package/dist/core/Charts/ChartComponent.svelte +11 -4
- package/dist/core/Charts/ChartComponent.svelte.d.ts +1 -0
- package/dist/core/Charts/GlobalControls.svelte +171 -25
- package/dist/core/Charts/GlobalControls.svelte.d.ts +1 -0
- package/dist/core/Charts/adapt.js +1 -1
- package/dist/core/Charts/charts.model.d.ts +3 -0
- package/dist/core/Charts/data-utils.js +8 -1
- package/dist/core/FeatureRegistry/index.js +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/map/controls/MapControl.svelte +204 -0
- package/dist/map/controls/MapControl.svelte.d.ts +17 -0
- package/dist/map/controls/SiteFilterControl.svelte +126 -0
- package/dist/map/controls/SiteFilterControl.svelte.d.ts +16 -0
- package/dist/map/demo/DemoMap.svelte +98 -0
- package/dist/map/demo/DemoMap.svelte.d.ts +12 -0
- package/dist/map/demo/demo-data.d.ts +12 -0
- package/dist/map/demo/demo-data.js +220 -0
- package/dist/map/hooks/useCellData.d.ts +14 -0
- package/dist/map/hooks/useCellData.js +29 -0
- package/dist/map/hooks/useMapbox.d.ts +14 -0
- package/dist/map/hooks/useMapbox.js +29 -0
- package/dist/map/index.d.ts +27 -0
- package/dist/map/index.js +47 -0
- package/dist/map/layers/CellsLayer.svelte +242 -0
- package/dist/map/layers/CellsLayer.svelte.d.ts +21 -0
- package/dist/map/layers/CoverageLayer.svelte +37 -0
- package/dist/map/layers/CoverageLayer.svelte.d.ts +9 -0
- package/dist/map/layers/LayerBase.d.ts +42 -0
- package/dist/map/layers/LayerBase.js +58 -0
- package/dist/map/layers/SitesLayer.svelte +282 -0
- package/dist/map/layers/SitesLayer.svelte.d.ts +19 -0
- package/dist/map/providers/CellDataProvider.svelte +43 -0
- package/dist/map/providers/CellDataProvider.svelte.d.ts +12 -0
- package/dist/map/providers/MapboxProvider.svelte +38 -0
- package/dist/map/providers/MapboxProvider.svelte.d.ts +9 -0
- package/dist/map/providers/providerHelpers.d.ts +17 -0
- package/dist/map/providers/providerHelpers.js +26 -0
- package/dist/map/stores/cellDataStore.d.ts +21 -0
- package/dist/map/stores/cellDataStore.js +53 -0
- package/dist/map/stores/interactions.d.ts +20 -0
- package/dist/map/stores/interactions.js +33 -0
- package/dist/map/stores/mapStore.d.ts +8 -0
- package/dist/map/stores/mapStore.js +10 -0
- package/dist/map/types.d.ts +115 -0
- package/dist/map/types.js +10 -0
- package/dist/map/utils/geojson.d.ts +20 -0
- package/dist/map/utils/geojson.js +78 -0
- package/dist/map/utils/mapboxHelpers.d.ts +51 -0
- package/dist/map/utils/mapboxHelpers.js +98 -0
- package/dist/map/utils/math.d.ts +40 -0
- package/dist/map/utils/math.js +95 -0
- package/dist/map/utils/siteTreeUtils.d.ts +27 -0
- package/dist/map/utils/siteTreeUtils.js +164 -0
- package/package.json +1 -1
- package/dist/core/Map/Map.svelte +0 -312
- package/dist/core/Map/Map.svelte.d.ts +0 -230
- package/dist/core/Map/index.d.ts +0 -9
- package/dist/core/Map/index.js +0 -9
- package/dist/core/Map/mapSettings.d.ts +0 -147
- package/dist/core/Map/mapSettings.js +0 -226
- package/dist/core/Map/mapStore.d.ts +0 -73
- package/dist/core/Map/mapStore.js +0 -136
- package/dist/core/Map/types.d.ts +0 -72
- package/dist/core/Map/types.js +0 -32
|
@@ -22,9 +22,13 @@
|
|
|
22
22
|
showGroupingSelector?: boolean; // Show/hide the grouping dropdown (default: true)
|
|
23
23
|
onSearch?: (searchTerm: string) => void; // Optional: Search callback (if provided, shows search box)
|
|
24
24
|
searchPlaceholder?: string; // Optional: Search box placeholder text (default: "Search...")
|
|
25
|
+
plotlyLayout?: Record<string, any>; // Optional Plotly layout configuration
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
let { rawData, multiCellLayout, singleLteLayout,
|
|
28
|
+
let { rawData, multiCellLayout, singleLteLayout,
|
|
29
|
+
singleNrLayout, baseMetrics, mode = "scrollspy", markers = [],
|
|
30
|
+
cellStyling = defaultCellStyling, initialGrouping = defaultTreeGrouping,
|
|
31
|
+
showGroupingSelector = true, onSearch, searchPlaceholder = "Search...", plotlyLayout }: Props = $props();
|
|
28
32
|
|
|
29
33
|
// Search state
|
|
30
34
|
let searchTerm = $state('');
|
|
@@ -319,6 +323,8 @@
|
|
|
319
323
|
markers={markers}
|
|
320
324
|
showGlobalControls={true}
|
|
321
325
|
enableAdaptation={true}
|
|
326
|
+
plotlyLayout={plotlyLayout}
|
|
327
|
+
persistSettings={true}
|
|
322
328
|
/>
|
|
323
329
|
{:else}
|
|
324
330
|
<div class="d-flex align-items-center justify-content-center h-100">
|
|
@@ -14,6 +14,7 @@ interface Props {
|
|
|
14
14
|
showGroupingSelector?: boolean;
|
|
15
15
|
onSearch?: (searchTerm: string) => void;
|
|
16
16
|
searchPlaceholder?: string;
|
|
17
|
+
plotlyLayout?: Record<string, any>;
|
|
17
18
|
}
|
|
18
19
|
declare const SiteCheck: import("svelte").Component<Props, {}, "">;
|
|
19
20
|
type SiteCheck = ReturnType<typeof SiteCheck>;
|
|
@@ -229,7 +229,7 @@ export function buildTreeNodes(data, grouping = { level0: 'site', level1: 'azimu
|
|
|
229
229
|
sector: record.sector,
|
|
230
230
|
azimuth: record.azimuth
|
|
231
231
|
},
|
|
232
|
-
defaultChecked:
|
|
232
|
+
defaultChecked: false // Start unselected
|
|
233
233
|
};
|
|
234
234
|
level1Node.children.push(cellNode);
|
|
235
235
|
});
|
|
@@ -293,7 +293,7 @@ function build2LevelTree(data, grouping) {
|
|
|
293
293
|
sector: record.sector,
|
|
294
294
|
azimuth: record.azimuth
|
|
295
295
|
},
|
|
296
|
-
defaultChecked:
|
|
296
|
+
defaultChecked: false // Start unselected
|
|
297
297
|
};
|
|
298
298
|
level0Node.children.push(cellNode);
|
|
299
299
|
});
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { adaptPlotlyLayout, addMarkersToLayout, type ContainerSize } from './adapt.js';
|
|
9
9
|
import { getKPIValues, type ProcessedChartData } from './data-processor.js';
|
|
10
10
|
import { log } from '../logger';
|
|
11
|
+
import { checkHealth, getMessage } from '../FeatureRegistry';
|
|
11
12
|
|
|
12
13
|
interface Props {
|
|
13
14
|
chart: ChartModel;
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
let chartDiv: HTMLElement;
|
|
40
41
|
let containerSize = $state<ContainerSize>({ width: 0, height: 0 });
|
|
41
42
|
let chartInitialized = $state(false); // Track if chart has been created
|
|
43
|
+
let isHealthy = $state(checkHealth('charts'));
|
|
42
44
|
|
|
43
45
|
function handleContextMenu(event: MouseEvent) {
|
|
44
46
|
event.preventDefault();
|
|
@@ -268,6 +270,7 @@
|
|
|
268
270
|
}
|
|
269
271
|
|
|
270
272
|
onMount(() => {
|
|
273
|
+
|
|
271
274
|
log('📈 ChartCard mounted', {
|
|
272
275
|
chartTitle: chart.title,
|
|
273
276
|
leftKPIs: chart.yLeft.length,
|
|
@@ -286,7 +289,9 @@
|
|
|
286
289
|
height: rect.height
|
|
287
290
|
});
|
|
288
291
|
}
|
|
289
|
-
|
|
292
|
+
if(!isHealthy){
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
290
295
|
renderChart();
|
|
291
296
|
|
|
292
297
|
// Set up ResizeObserver with debouncing to prevent excessive re-renders
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import GlobalControls from './GlobalControls.svelte';
|
|
8
8
|
import { getPreprocessedData, type ProcessedChartData } from './data-processor.js';
|
|
9
9
|
import { log } from '../logger';
|
|
10
|
+
import { checkHealth, getMessage } from '../FeatureRegistry';
|
|
10
11
|
|
|
11
12
|
interface Props {
|
|
12
13
|
layout: Layout;
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
plotlyLayout?: any; // Optional custom Plotly layout
|
|
17
18
|
enableAdaptation?: boolean; // Enable size-based adaptations
|
|
18
19
|
showGlobalControls?: boolean; // Show/hide global controls section (default: true)
|
|
20
|
+
persistSettings?: boolean; // Enable localStorage persistence for global controls (default: false)
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const GRID_DIMENSIONS: Record<ChartGrid, { rows: number; columns: number }> = {
|
|
@@ -54,8 +56,8 @@
|
|
|
54
56
|
section: Section;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
let { layout, data, mode, markers, plotlyLayout, enableAdaptation = true, showGlobalControls = true }: Props = $props();
|
|
58
|
-
|
|
59
|
+
let { layout, data, mode, markers, plotlyLayout, enableAdaptation = true, showGlobalControls = true, persistSettings = false }: Props = $props();
|
|
60
|
+
let isHealthy = $state(checkHealth('charts'));
|
|
59
61
|
// Log component initialization
|
|
60
62
|
$effect(() => {
|
|
61
63
|
log('📊 ChartComponent initialized', {
|
|
@@ -88,6 +90,9 @@
|
|
|
88
90
|
},
|
|
89
91
|
hoverMode: {
|
|
90
92
|
mode: layout.hoverMode ?? 'x' // Default to 'x' if not specified
|
|
93
|
+
},
|
|
94
|
+
adaptive: {
|
|
95
|
+
enabled: enableAdaptation // Initialize from prop, always present
|
|
91
96
|
}
|
|
92
97
|
});
|
|
93
98
|
|
|
@@ -272,6 +277,7 @@
|
|
|
272
277
|
}
|
|
273
278
|
|
|
274
279
|
onMount(() => {
|
|
280
|
+
|
|
275
281
|
const handleKeydown = (event: KeyboardEvent) => {
|
|
276
282
|
if (event.key === 'Escape') {
|
|
277
283
|
if (zoomedChart) {
|
|
@@ -328,7 +334,7 @@
|
|
|
328
334
|
{processedData}
|
|
329
335
|
{markers}
|
|
330
336
|
{plotlyLayout}
|
|
331
|
-
{
|
|
337
|
+
enableAdaptation={globalControls.adaptive?.enabled ?? true}
|
|
332
338
|
sectionId={section.id}
|
|
333
339
|
sectionMovingAverage={section.movingAverage}
|
|
334
340
|
layoutMovingAverage={layout.movingAverage}
|
|
@@ -353,6 +359,7 @@
|
|
|
353
359
|
onUpdate={handleControlsUpdate}
|
|
354
360
|
isExpanded={showControlsPanel}
|
|
355
361
|
onToggle={() => showControlsPanel = !showControlsPanel}
|
|
362
|
+
persistSettings={persistSettings}
|
|
356
363
|
/>
|
|
357
364
|
{/if}
|
|
358
365
|
|
|
@@ -447,7 +454,7 @@
|
|
|
447
454
|
{processedData}
|
|
448
455
|
{markers}
|
|
449
456
|
{plotlyLayout}
|
|
450
|
-
{
|
|
457
|
+
enableAdaptation={globalControls.adaptive?.enabled ?? true}
|
|
451
458
|
sectionId={activeZoom.section.id}
|
|
452
459
|
sectionMovingAverage={activeZoom.section.movingAverage}
|
|
453
460
|
layoutMovingAverage={layout.movingAverage}
|
|
@@ -7,6 +7,7 @@ interface Props {
|
|
|
7
7
|
plotlyLayout?: any;
|
|
8
8
|
enableAdaptation?: boolean;
|
|
9
9
|
showGlobalControls?: boolean;
|
|
10
|
+
persistSettings?: boolean;
|
|
10
11
|
}
|
|
11
12
|
declare const ChartComponent: import("svelte").Component<Props, {}, "">;
|
|
12
13
|
type ChartComponent = ReturnType<typeof ChartComponent>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<svelte:options runes={true} />
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
|
+
import { onMount } from 'svelte';
|
|
4
5
|
import type { GlobalChartControls, HoverMode } from './charts.model.js';
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
@@ -8,55 +9,110 @@
|
|
|
8
9
|
onUpdate: (controls: GlobalChartControls) => void;
|
|
9
10
|
isExpanded?: boolean;
|
|
10
11
|
onToggle?: () => void;
|
|
12
|
+
persistSettings?: boolean; // Optional: enable localStorage persistence
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
let { controls, onUpdate, isExpanded = false, onToggle }: Props = $props();
|
|
15
|
+
let { controls, onUpdate, isExpanded = false, onToggle, persistSettings = false }: Props = $props();
|
|
16
|
+
|
|
17
|
+
const STORAGE_KEY = 'chart-global-controls';
|
|
18
|
+
|
|
19
|
+
// Load saved settings on mount
|
|
20
|
+
onMount(() => {
|
|
21
|
+
if (persistSettings && typeof window !== 'undefined') {
|
|
22
|
+
try {
|
|
23
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
24
|
+
if (saved) {
|
|
25
|
+
const savedControls = JSON.parse(saved) as GlobalChartControls;
|
|
26
|
+
onUpdate(savedControls);
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn('Failed to load chart controls from localStorage:', error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Save settings to localStorage
|
|
35
|
+
function saveSettings(updatedControls: GlobalChartControls) {
|
|
36
|
+
if (persistSettings && typeof window !== 'undefined') {
|
|
37
|
+
try {
|
|
38
|
+
console.log('💾 Saving chart controls to localStorage:', updatedControls);
|
|
39
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedControls));
|
|
40
|
+
console.log('✅ Saved successfully');
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.warn('Failed to save chart controls to localStorage:', error);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
console.log('⚠️ Not saving: persistSettings =', persistSettings);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
14
48
|
|
|
15
49
|
function updateControls(updates: Partial<GlobalChartControls>) {
|
|
16
|
-
|
|
50
|
+
const newControls = {
|
|
17
51
|
...controls,
|
|
18
52
|
...updates
|
|
19
|
-
}
|
|
53
|
+
};
|
|
54
|
+
onUpdate(newControls);
|
|
55
|
+
saveSettings(newControls);
|
|
20
56
|
}
|
|
21
57
|
|
|
22
58
|
function updateMovingAverage(updates: Partial<NonNullable<GlobalChartControls['movingAverage']>>) {
|
|
23
|
-
|
|
59
|
+
const newControls = {
|
|
24
60
|
...controls,
|
|
25
61
|
movingAverage: {
|
|
26
62
|
...controls.movingAverage!,
|
|
27
63
|
...updates
|
|
28
64
|
}
|
|
29
|
-
}
|
|
65
|
+
};
|
|
66
|
+
onUpdate(newControls);
|
|
67
|
+
saveSettings(newControls);
|
|
30
68
|
}
|
|
31
69
|
|
|
32
70
|
function updateMarkers(updates: Partial<NonNullable<GlobalChartControls['markers']>>) {
|
|
33
|
-
|
|
71
|
+
const newControls = {
|
|
34
72
|
...controls,
|
|
35
73
|
markers: {
|
|
36
74
|
...controls.markers!,
|
|
37
75
|
...updates
|
|
38
76
|
}
|
|
39
|
-
}
|
|
77
|
+
};
|
|
78
|
+
onUpdate(newControls);
|
|
79
|
+
saveSettings(newControls);
|
|
40
80
|
}
|
|
41
81
|
|
|
42
82
|
function updateLegend(updates: Partial<NonNullable<GlobalChartControls['legend']>>) {
|
|
43
|
-
|
|
83
|
+
const newControls = {
|
|
44
84
|
...controls,
|
|
45
85
|
legend: {
|
|
46
86
|
...controls.legend!,
|
|
47
87
|
...updates
|
|
48
88
|
}
|
|
49
|
-
}
|
|
89
|
+
};
|
|
90
|
+
onUpdate(newControls);
|
|
91
|
+
saveSettings(newControls);
|
|
50
92
|
}
|
|
51
93
|
|
|
52
94
|
function updateHoverMode(updates: Partial<NonNullable<GlobalChartControls['hoverMode']>>) {
|
|
53
|
-
|
|
95
|
+
const newControls = {
|
|
54
96
|
...controls,
|
|
55
97
|
hoverMode: {
|
|
56
98
|
...controls.hoverMode!,
|
|
57
99
|
...updates
|
|
58
100
|
}
|
|
59
|
-
}
|
|
101
|
+
};
|
|
102
|
+
onUpdate(newControls);
|
|
103
|
+
saveSettings(newControls);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function updateAdaptive(updates: Partial<NonNullable<GlobalChartControls['adaptive']>>) {
|
|
107
|
+
const newControls = {
|
|
108
|
+
...controls,
|
|
109
|
+
adaptive: {
|
|
110
|
+
...controls.adaptive!,
|
|
111
|
+
...updates
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
onUpdate(newControls);
|
|
115
|
+
saveSettings(newControls);
|
|
60
116
|
}
|
|
61
117
|
</script>
|
|
62
118
|
|
|
@@ -102,7 +158,11 @@
|
|
|
102
158
|
checked={controls.markers.enabled}
|
|
103
159
|
onchange={() => updateMarkers({ enabled: !controls.markers!.enabled })}
|
|
104
160
|
/>
|
|
105
|
-
<label
|
|
161
|
+
<label
|
|
162
|
+
class="btn btn-outline-primary btn-sm"
|
|
163
|
+
for="markersToggle"
|
|
164
|
+
title="Show or hide data point markers on charts"
|
|
165
|
+
>
|
|
106
166
|
Markers
|
|
107
167
|
</label>
|
|
108
168
|
</div>
|
|
@@ -118,17 +178,41 @@
|
|
|
118
178
|
checked={controls.legend.enabled}
|
|
119
179
|
onchange={() => updateLegend({ enabled: !controls.legend!.enabled })}
|
|
120
180
|
/>
|
|
121
|
-
<label
|
|
181
|
+
<label
|
|
182
|
+
class="btn btn-outline-primary btn-sm"
|
|
183
|
+
for="legendToggle"
|
|
184
|
+
title="Show or hide the chart legend with series names"
|
|
185
|
+
>
|
|
122
186
|
Legend
|
|
123
187
|
</label>
|
|
124
188
|
</div>
|
|
125
189
|
{/if}
|
|
190
|
+
|
|
191
|
+
<!-- Adaptive Toggle (Always Present - Not Optional) -->
|
|
192
|
+
<div class="control-group-inline">
|
|
193
|
+
<input
|
|
194
|
+
type="checkbox"
|
|
195
|
+
class="btn-check"
|
|
196
|
+
id="adaptiveToggle"
|
|
197
|
+
checked={controls.adaptive?.enabled ?? true}
|
|
198
|
+
onchange={() => updateAdaptive({ enabled: !(controls.adaptive?.enabled ?? true) })}
|
|
199
|
+
/>
|
|
200
|
+
<label
|
|
201
|
+
class="btn btn-outline-primary btn-sm"
|
|
202
|
+
for="adaptiveToggle"
|
|
203
|
+
title="Enable adaptive chart display based on chart size and data density"
|
|
204
|
+
>
|
|
205
|
+
Adaptive
|
|
206
|
+
</label>
|
|
207
|
+
</div>
|
|
126
208
|
</div>
|
|
127
209
|
|
|
128
210
|
<!-- Hover Mode Controls -->
|
|
129
211
|
{#if controls.hoverMode}
|
|
130
212
|
<div class="control-group">
|
|
131
|
-
<div class="control-label"
|
|
213
|
+
<div class="control-label" title="Control how hover tooltips appear when you move your mouse over the chart">
|
|
214
|
+
Hover Mode
|
|
215
|
+
</div>
|
|
132
216
|
<div class="btn-group btn-group-sm" role="group" aria-label="Hover Mode">
|
|
133
217
|
<input
|
|
134
218
|
type="radio"
|
|
@@ -138,7 +222,13 @@
|
|
|
138
222
|
checked={controls.hoverMode.mode === 'x'}
|
|
139
223
|
onchange={() => updateHoverMode({ mode: 'x' })}
|
|
140
224
|
/>
|
|
141
|
-
<label
|
|
225
|
+
<label
|
|
226
|
+
class="btn btn-outline-primary"
|
|
227
|
+
for="hoverModeX"
|
|
228
|
+
title="Show all data points at the same X-axis position"
|
|
229
|
+
>
|
|
230
|
+
X-Axis
|
|
231
|
+
</label>
|
|
142
232
|
|
|
143
233
|
<!-- <input
|
|
144
234
|
type="radio"
|
|
@@ -158,7 +248,13 @@
|
|
|
158
248
|
checked={controls.hoverMode.mode === 'closest'}
|
|
159
249
|
onchange={() => updateHoverMode({ mode: 'closest' })}
|
|
160
250
|
/>
|
|
161
|
-
<label
|
|
251
|
+
<label
|
|
252
|
+
class="btn btn-outline-primary"
|
|
253
|
+
for="hoverModeClosest"
|
|
254
|
+
title="Show only the single closest data point to your cursor"
|
|
255
|
+
>
|
|
256
|
+
Closest
|
|
257
|
+
</label>
|
|
162
258
|
|
|
163
259
|
<input
|
|
164
260
|
type="radio"
|
|
@@ -168,7 +264,13 @@
|
|
|
168
264
|
checked={controls.hoverMode.mode === 'x unified'}
|
|
169
265
|
onchange={() => updateHoverMode({ mode: 'x unified' })}
|
|
170
266
|
/>
|
|
171
|
-
<label
|
|
267
|
+
<label
|
|
268
|
+
class="btn btn-outline-primary"
|
|
269
|
+
for="hoverModeXUnified"
|
|
270
|
+
title="Show all data points at the same X position with a single unified tooltip"
|
|
271
|
+
>
|
|
272
|
+
X-Unified
|
|
273
|
+
</label>
|
|
172
274
|
|
|
173
275
|
<!-- <input
|
|
174
276
|
type="radio"
|
|
@@ -188,7 +290,13 @@
|
|
|
188
290
|
checked={controls.hoverMode.mode === false}
|
|
189
291
|
onchange={() => updateHoverMode({ mode: false })}
|
|
190
292
|
/>
|
|
191
|
-
<label
|
|
293
|
+
<label
|
|
294
|
+
class="btn btn-outline-primary"
|
|
295
|
+
for="hoverModeFalse"
|
|
296
|
+
title="Disable hover tooltips completely"
|
|
297
|
+
>
|
|
298
|
+
Off
|
|
299
|
+
</label>
|
|
192
300
|
</div>
|
|
193
301
|
</div>
|
|
194
302
|
{/if}
|
|
@@ -204,7 +312,11 @@
|
|
|
204
312
|
checked={controls.movingAverage.enabled}
|
|
205
313
|
onchange={() => updateMovingAverage({ enabled: !controls.movingAverage!.enabled })}
|
|
206
314
|
/>
|
|
207
|
-
<label
|
|
315
|
+
<label
|
|
316
|
+
class="btn btn-outline-primary btn-sm"
|
|
317
|
+
for="maToggle"
|
|
318
|
+
title="Apply smoothing to chart data using moving average calculations"
|
|
319
|
+
>
|
|
208
320
|
Moving Average
|
|
209
321
|
</label>
|
|
210
322
|
|
|
@@ -220,7 +332,13 @@
|
|
|
220
332
|
checked={controls.movingAverage.windowOverride === undefined}
|
|
221
333
|
onchange={() => updateMovingAverage({ windowOverride: undefined })}
|
|
222
334
|
/>
|
|
223
|
-
<label
|
|
335
|
+
<label
|
|
336
|
+
class="btn btn-outline-primary"
|
|
337
|
+
for="maWindowAuto"
|
|
338
|
+
title="Default size from settings"
|
|
339
|
+
>
|
|
340
|
+
Auto
|
|
341
|
+
</label>
|
|
224
342
|
|
|
225
343
|
<input
|
|
226
344
|
type="radio"
|
|
@@ -230,7 +348,13 @@
|
|
|
230
348
|
checked={controls.movingAverage.windowOverride === 7}
|
|
231
349
|
onchange={() => updateMovingAverage({ windowOverride: 7 })}
|
|
232
350
|
/>
|
|
233
|
-
<label
|
|
351
|
+
<label
|
|
352
|
+
class="btn btn-outline-primary"
|
|
353
|
+
for="maWindow7"
|
|
354
|
+
title="Use a 7-period moving average window"
|
|
355
|
+
>
|
|
356
|
+
7
|
|
357
|
+
</label>
|
|
234
358
|
|
|
235
359
|
<input
|
|
236
360
|
type="radio"
|
|
@@ -240,7 +364,13 @@
|
|
|
240
364
|
checked={controls.movingAverage.windowOverride === 14}
|
|
241
365
|
onchange={() => updateMovingAverage({ windowOverride: 14 })}
|
|
242
366
|
/>
|
|
243
|
-
<label
|
|
367
|
+
<label
|
|
368
|
+
class="btn btn-outline-primary"
|
|
369
|
+
for="maWindow14"
|
|
370
|
+
title="Use a 14-period moving average window"
|
|
371
|
+
>
|
|
372
|
+
14
|
|
373
|
+
</label>
|
|
244
374
|
|
|
245
375
|
<input
|
|
246
376
|
type="radio"
|
|
@@ -250,7 +380,13 @@
|
|
|
250
380
|
checked={controls.movingAverage.windowOverride === 24}
|
|
251
381
|
onchange={() => updateMovingAverage({ windowOverride: 24 })}
|
|
252
382
|
/>
|
|
253
|
-
<label
|
|
383
|
+
<label
|
|
384
|
+
class="btn btn-outline-primary"
|
|
385
|
+
for="maWindow24"
|
|
386
|
+
title="Use a 24-period moving average window"
|
|
387
|
+
>
|
|
388
|
+
24
|
|
389
|
+
</label>
|
|
254
390
|
|
|
255
391
|
<input
|
|
256
392
|
type="radio"
|
|
@@ -260,7 +396,13 @@
|
|
|
260
396
|
checked={controls.movingAverage.windowOverride === 30}
|
|
261
397
|
onchange={() => updateMovingAverage({ windowOverride: 30 })}
|
|
262
398
|
/>
|
|
263
|
-
<label
|
|
399
|
+
<label
|
|
400
|
+
class="btn btn-outline-primary"
|
|
401
|
+
for="maWindow30"
|
|
402
|
+
title="Use a 30-period moving average window"
|
|
403
|
+
>
|
|
404
|
+
30
|
|
405
|
+
</label>
|
|
264
406
|
</div>
|
|
265
407
|
|
|
266
408
|
<!-- Show Original Toggle Button -->
|
|
@@ -271,7 +413,11 @@
|
|
|
271
413
|
checked={controls.movingAverage.showOriginal}
|
|
272
414
|
onchange={() => updateMovingAverage({ showOriginal: !controls.movingAverage!.showOriginal })}
|
|
273
415
|
/>
|
|
274
|
-
<label
|
|
416
|
+
<label
|
|
417
|
+
class="btn btn-outline-primary btn-sm ms-2"
|
|
418
|
+
for="showOriginal"
|
|
419
|
+
title="Display both the original data and the moving average together"
|
|
420
|
+
>
|
|
275
421
|
Show Original
|
|
276
422
|
</label>
|
|
277
423
|
</div>
|
|
@@ -4,6 +4,7 @@ interface Props {
|
|
|
4
4
|
onUpdate: (controls: GlobalChartControls) => void;
|
|
5
5
|
isExpanded?: boolean;
|
|
6
6
|
onToggle?: () => void;
|
|
7
|
+
persistSettings?: boolean;
|
|
7
8
|
}
|
|
8
9
|
declare const GlobalControls: import("svelte").Component<Props, {}, "">;
|
|
9
10
|
type GlobalControls = ReturnType<typeof GlobalControls>;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
function adaptHoverBehavior(layout, containerSize, chartInfo, originalHoverMode) {
|
|
10
10
|
const { width, height } = containerSize;
|
|
11
11
|
const isTiny = width < 250 || height < 200;
|
|
12
|
-
const isSmall = width <
|
|
12
|
+
const isSmall = width < 250 || height < 200;
|
|
13
13
|
const isMedium = width < 600 || height < 400;
|
|
14
14
|
const totalSeries = chartInfo.leftSeriesCount + chartInfo.rightSeriesCount;
|
|
15
15
|
// Only override hover mode in critical cases for performance/UX
|
|
@@ -302,7 +302,14 @@ export function createDefaultPlotlyLayout(title, hoverMode, coloredHover = true)
|
|
|
302
302
|
showgrid: true,
|
|
303
303
|
gridcolor: '#ecf0f1',
|
|
304
304
|
linecolor: '#bdc3c7',
|
|
305
|
-
tickfont: { size: 11 }
|
|
305
|
+
tickfont: { size: 11 },
|
|
306
|
+
// Show Y-axis marker with line when in 'closest' hover mode
|
|
307
|
+
// showspikes: hoverMode === 'closest',
|
|
308
|
+
// spikemode: 'marker', // Line to axis + triangle marker
|
|
309
|
+
// spikesnap: 'cursor', // Snap to cursor position
|
|
310
|
+
// spikethickness: 1, // Line thickness
|
|
311
|
+
// spikecolor: '#000000ff', // Primary blue color
|
|
312
|
+
// spikedash: 'dot' // Dotted line
|
|
306
313
|
},
|
|
307
314
|
margin: { l: 60, r: 60, t: 60, b: 50 },
|
|
308
315
|
paper_bgcolor: 'rgba(0,0,0,0)',
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export * from './Settings/index.js';
|
|
|
11
11
|
// Logger utility for debugging and monitoring
|
|
12
12
|
export * from './logger/index.js';
|
|
13
13
|
// Map component - Mapbox GL + Deck.GL integration
|
|
14
|
-
|
|
14
|
+
// TODO: Moved to top-level src/lib/map module
|
|
15
|
+
// export * from './Map/index.js';
|
|
15
16
|
// FeatureRegistry - Component access management
|
|
16
17
|
export * from './FeatureRegistry/index.js';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,5 +2,7 @@
|
|
|
2
2
|
// This approach keeps the main index clean and allows for easy expansion
|
|
3
3
|
// Core components (Desktop orchestration + Charts + TreeView)
|
|
4
4
|
export * from './core/index.js';
|
|
5
|
+
// Map components (Mapbox cellular visualization)
|
|
6
|
+
export * from './map/index.js';
|
|
5
7
|
// Complete applications
|
|
6
8
|
export * from './apps/index.js';
|