| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | import { | 
					
						
							|  |  |  |   DeesElement, | 
					
						
							|  |  |  |   customElement, | 
					
						
							|  |  |  |   property, | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |   state, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   type TemplateResult, | 
					
						
							|  |  |  | } from '@design.estate/dees-element'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import * as domtools from '@design.estate/dees-domtools'; | 
					
						
							| 
									
										
										
										
											2025-09-19 15:26:21 +00:00
										 |  |  | import { demoFunc } from './demo.js'; | 
					
						
							|  |  |  | import { chartAreaStyles } from './styles.js'; | 
					
						
							|  |  |  | import { renderChartArea } from './template.js'; | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ApexCharts from 'apexcharts'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | declare global { | 
					
						
							|  |  |  |   interface HTMLElementTagNameMap { | 
					
						
							|  |  |  |     'dees-chart-area': DeesChartArea; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @customElement('dees-chart-area') | 
					
						
							|  |  |  | export class DeesChartArea extends DeesElement { | 
					
						
							|  |  |  |   public static demo = demoFunc; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |   // instance
 | 
					
						
							|  |  |  |   @state() | 
					
						
							|  |  |  |   public chart: ApexCharts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @property() | 
					
						
							| 
									
										
										
										
											2024-02-03 14:49:25 +01:00
										 |  |  |   public label: string = 'Untitled Chart'; | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   @property({ type: Array }) | 
					
						
							|  |  |  |   public series: ApexAxisChartSeries = []; | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   // Override getter to return internal chart data
 | 
					
						
							|  |  |  |   get chartSeries(): ApexAxisChartSeries { | 
					
						
							|  |  |  |     return this.internalChartData.length > 0 ? this.internalChartData : this.series; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |   @property({ attribute: false }) | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   public yAxisFormatter: (value: number) => string = (val) => `${val} Mbps`; | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   @property({ type: Number }) | 
					
						
							|  |  |  |   public rollingWindow: number = 0; // 0 means no rolling window
 | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   @property({ type: Boolean }) | 
					
						
							|  |  |  |   public realtimeMode: boolean = false; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   @property({ type: String }) | 
					
						
							|  |  |  |   public yAxisScaling: 'fixed' | 'dynamic' | 'percentage' = 'dynamic'; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   @property({ type: Number }) | 
					
						
							|  |  |  |   public yAxisMax: number = 100; // Used when yAxisScaling is 'fixed' or 'percentage'
 | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   @property({ type: Number }) | 
					
						
							|  |  |  |   public autoScrollInterval: number = 1000; // Auto-scroll interval in milliseconds (0 to disable)
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  |   private resizeObserver: ResizeObserver; | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |   private resizeTimeout: number; | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |   private internalChartData: ApexAxisChartSeries = []; | 
					
						
							|  |  |  |   private autoScrollTimer: number | null = null; | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |   private readonly DEBUG_RESIZE = false; // Set to true to enable resize debugging
 | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   // Chart color schemes
 | 
					
						
							|  |  |  |   private readonly CHART_COLORS = { | 
					
						
							|  |  |  |     dark: [ | 
					
						
							|  |  |  |       'hsl(217.2 91.2% 59.8%)', // Blue
 | 
					
						
							|  |  |  |       'hsl(173.4 80.4% 40%)',   // Teal
 | 
					
						
							|  |  |  |       'hsl(280.3 87.4% 66.7%)', // Purple
 | 
					
						
							|  |  |  |       'hsl(24.6 95% 53.1%)',    // Orange
 | 
					
						
							|  |  |  |     ], | 
					
						
							|  |  |  |     light: [ | 
					
						
							|  |  |  |       'hsl(222.2 47.4% 51.2%)', // Blue (shadcn primary)
 | 
					
						
							|  |  |  |       'hsl(142.1 76.2% 36.3%)', // Green (shadcn success)
 | 
					
						
							|  |  |  |       'hsl(280.3 47.7% 50.2%)', // Purple (muted)
 | 
					
						
							|  |  |  |       'hsl(20.5 90.2% 48.2%)',  // Orange (shadcn destructive variant)
 | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   constructor() { | 
					
						
							|  |  |  |     super(); | 
					
						
							|  |  |  |     domtools.elementBasic.setup(); | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |     this.resizeObserver = new ResizeObserver((entries) => { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |       // Debounce resize calls to prevent excessive updates
 | 
					
						
							|  |  |  |       if (this.resizeTimeout) { | 
					
						
							|  |  |  |         clearTimeout(this.resizeTimeout); | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |        | 
					
						
							|  |  |  |       this.resizeTimeout = window.setTimeout(() => { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         // Simply resize if we have a chart, since we're only observing the mainbox
 | 
					
						
							|  |  |  |         if (this.chart) { | 
					
						
							|  |  |  |           // Log resize event for debugging
 | 
					
						
							|  |  |  |           if (this.DEBUG_RESIZE && entries.length > 0) { | 
					
						
							|  |  |  |             const entry = entries[0]; | 
					
						
							|  |  |  |             console.log('DeesChartArea - Resize detected:', { | 
					
						
							|  |  |  |               width: entry.contentRect.width, | 
					
						
							|  |  |  |               height: entry.contentRect.height | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |           this.resizeChart(); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, 100); // 100ms debounce
 | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     // Note: ResizeObserver is now set up after chart initialization in firstUpdated()
 | 
					
						
							|  |  |  |     // to ensure proper timing and avoid race conditions
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2024-02-05 13:11:05 +01:00
										 |  |  |     this.registerGarbageFunction(async () => { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |       if (this.resizeTimeout) { | 
					
						
							|  |  |  |         clearTimeout(this.resizeTimeout); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       if (this.resizeObserver) { | 
					
						
							|  |  |  |         this.resizeObserver.disconnect(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |       this.stopAutoScroll(); | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |        | 
					
						
							|  |  |  |       // Critical: Destroy chart instance to prevent memory leak
 | 
					
						
							|  |  |  |       if (this.chart) { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |           this.chart.destroy(); | 
					
						
							|  |  |  |           this.chart = null; | 
					
						
							|  |  |  |         } catch (error) { | 
					
						
							|  |  |  |           console.error('Error destroying chart:', error); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   public async connectedCallback() { | 
					
						
							|  |  |  |     super.connectedCallback(); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Trigger resize when element is connected to DOM
 | 
					
						
							|  |  |  |     // This helps with dynamically added charts
 | 
					
						
							|  |  |  |     if (this.chart) { | 
					
						
							|  |  |  |       // Wait a frame for layout to settle
 | 
					
						
							|  |  |  |       await new Promise(resolve => requestAnimationFrame(resolve)); | 
					
						
							|  |  |  |       await this.resizeChart(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-19 15:26:21 +00:00
										 |  |  |   public static styles = chartAreaStyles; | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public render(): TemplateResult { | 
					
						
							| 
									
										
										
										
											2025-09-19 15:26:21 +00:00
										 |  |  |     return renderChartArea(this); | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-19 15:26:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   public async firstUpdated() { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |     await this.domtoolsPromise; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Wait for next animation frame to ensure layout is complete
 | 
					
						
							|  |  |  |     await new Promise(resolve => requestAnimationFrame(resolve)); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Get actual dimensions of the container
 | 
					
						
							|  |  |  |     const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox'); | 
					
						
							|  |  |  |     const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer'); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     if (!mainbox || !chartContainer) { | 
					
						
							|  |  |  |       console.error('Chart containers not found'); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Calculate initial dimensions
 | 
					
						
							|  |  |  |     const styleChartContainer = window.getComputedStyle(chartContainer); | 
					
						
							|  |  |  |     const paddingTop = parseInt(styleChartContainer.paddingTop, 10); | 
					
						
							|  |  |  |     const paddingBottom = parseInt(styleChartContainer.paddingBottom, 10); | 
					
						
							|  |  |  |     const paddingLeft = parseInt(styleChartContainer.paddingLeft, 10); | 
					
						
							|  |  |  |     const paddingRight = parseInt(styleChartContainer.paddingRight, 10); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     const initialWidth = mainbox.clientWidth - paddingLeft - paddingRight; | 
					
						
							|  |  |  |     const initialHeight = mainbox.offsetHeight - paddingTop - paddingBottom; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |     // Use provided series data or default demo data
 | 
					
						
							|  |  |  |     const chartSeries = this.series.length > 0 ? this.series : [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: 'cpu', | 
					
						
							|  |  |  |         data: [ | 
					
						
							|  |  |  |           { x: '2025-01-15T03:00:00', y: 25 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T07:00:00', y: 30 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T11:00:00', y: 20 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T15:00:00', y: 35 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T19:00:00', y: 25 }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: 'memory', | 
					
						
							|  |  |  |         data: [ | 
					
						
							|  |  |  |           { x: '2025-01-15T03:00:00', y: 10 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T07:00:00', y: 12 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T11:00:00', y: 10 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T15:00:00', y: 30 }, | 
					
						
							|  |  |  |           { x: '2025-01-15T19:00:00', y: 40 }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |     // Store internal data
 | 
					
						
							|  |  |  |     this.internalChartData = chartSeries; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     // Get current theme
 | 
					
						
							|  |  |  |     const isDark = !this.goBright; | 
					
						
							|  |  |  |     const theme = isDark ? 'dark' : 'light'; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |     var options: ApexCharts.ApexOptions = { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |       series: chartSeries, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |       chart: { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |         width: initialWidth || 100, // Use actual width or fallback
 | 
					
						
							|  |  |  |         height: initialHeight || 100, // Use actual height or fallback
 | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |         type: 'area', | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         background: 'transparent', // Transparent background to inherit from container
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |         toolbar: { | 
					
						
							|  |  |  |           show: false, // This line disables the toolbar
 | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |         animations: { | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |           enabled: !this.realtimeMode, // Disable animations in realtime mode
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |           speed: 400, | 
					
						
							|  |  |  |           animateGradually: { | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |             enabled: false, // Disable gradual animation for cleaner updates
 | 
					
						
							|  |  |  |             delay: 0 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |           }, | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |           dynamicAnimation: { | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |             enabled: !this.realtimeMode, | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |             speed: 350 | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         zoom: { | 
					
						
							|  |  |  |           enabled: false, // Disable zoom for cleaner interaction
 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         selection: { | 
					
						
							|  |  |  |           enabled: false, // Disable selection
 | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |       }, | 
					
						
							|  |  |  |       dataLabels: { | 
					
						
							|  |  |  |         enabled: false, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       stroke: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         width: 2, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |         curve: 'smooth', | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       xaxis: { | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         type: 'datetime', // Time-series data
 | 
					
						
							|  |  |  |         labels: { | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |           format: 'HH:mm:ss', // Time formatting with seconds
 | 
					
						
							|  |  |  |           datetimeUTC: false, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           style: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             colors: [isDark ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'], // Label color
 | 
					
						
							|  |  |  |             fontSize: '12px', | 
					
						
							|  |  |  |             fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', | 
					
						
							|  |  |  |             fontWeight: '400', | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         axisBorder: { | 
					
						
							|  |  |  |           show: false, // Hide x-axis border
 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         axisTicks: { | 
					
						
							|  |  |  |           show: false, // Hide x-axis ticks
 | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |       }, | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |       yaxis: { | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         min: 0, | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |         max: this.yAxisScaling === 'dynamic' ? undefined : this.yAxisMax, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         labels: { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |           formatter: this.yAxisFormatter, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           style: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             colors: [isDark ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'], // Label color
 | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |             fontSize: '12px', | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', | 
					
						
							|  |  |  |             fontWeight: '400', | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         axisBorder: { | 
					
						
							|  |  |  |           show: false, // Hide y-axis border
 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         axisTicks: { | 
					
						
							|  |  |  |           show: false, // Hide y-axis ticks
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |       tooltip: { | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         shared: true, // Enables the tooltip to display across series
 | 
					
						
							|  |  |  |         intersect: false, // Allows hovering anywhere on the chart
 | 
					
						
							|  |  |  |         followCursor: true, // Makes tooltip follow mouse even between points
 | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |         x: { | 
					
						
							|  |  |  |           format: 'dd/MM/yy HH:mm', | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         custom: ({ series, dataPointIndex, w }: any) => { | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           // Iterate through each series and get its value
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |           // Note: We can't access component instance here, so we'll use w.config.theme.mode
 | 
					
						
							|  |  |  |           const currentTheme = w.config.theme.mode; | 
					
						
							|  |  |  |           const isDarkMode = currentTheme === 'dark'; | 
					
						
							|  |  |  |           const bgColor = isDarkMode ? 'hsl(0 0% 9%)' : 'hsl(0 0% 100%)'; | 
					
						
							|  |  |  |           const textColor = isDarkMode ? 'hsl(0 0% 95%)' : 'hsl(0 0% 9%)'; | 
					
						
							|  |  |  |           const borderColor = isDarkMode ? 'hsl(0 0% 14.9%)' : 'hsl(0 0% 89.8%)'; | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           // Get formatter from chart config
 | 
					
						
							|  |  |  |           const formatter = w.config.yaxis[0]?.labels?.formatter || ((val: number) => val.toString()); | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           let tooltipContent = `<div style="padding: 12px; background: ${bgColor}; color: ${textColor}; border-radius: 6px; box-shadow: 0 2px 8px 0 hsl(0 0% 0% / ${isDarkMode ? '0.2' : '0.1'}); border: 1px solid ${borderColor};font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 12px;">`; | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |           series.forEach((s: number[], index: number) => { | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |             const label = w.globals.seriesNames[index]; // Get series label
 | 
					
						
							|  |  |  |             const value = s[dataPointIndex]; // Get value at data point
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             const color = w.globals.colors[index]; | 
					
						
							|  |  |  |             const formattedValue = formatter(value); | 
					
						
							|  |  |  |             tooltipContent += `<div style="display: flex; align-items: center; gap: 8px; margin: ${index > 0 ? '6px' : '0'} 0;">
 | 
					
						
							|  |  |  |               <span style="display: inline-block; width: 10px; height: 10px; background: ${color}; border-radius: 2px;"></span> | 
					
						
							|  |  |  |               <span style="font-weight: 500;">${label}:</span> | 
					
						
							|  |  |  |               <span style="margin-left: auto; font-weight: 600;">${formattedValue}</span> | 
					
						
							|  |  |  |             </div>`;
 | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           tooltipContent += `</div>`; | 
					
						
							|  |  |  |           return tooltipContent; | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |       }, | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |       grid: { | 
					
						
							|  |  |  |         xaxis: { | 
					
						
							|  |  |  |           lines: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             show: false, // Hide vertical grid lines for cleaner look
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         yaxis: { | 
					
						
							|  |  |  |           lines: { | 
					
						
							|  |  |  |             show: true, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         borderColor: isDark ? 'hsl(0 0% 14.9%)' : 'hsl(0 0% 94%)', // Very subtle grid lines
 | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |         strokeDashArray: 0, // Solid line
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |         padding: { | 
					
						
							|  |  |  |           top: 10, | 
					
						
							|  |  |  |           right: 20, | 
					
						
							|  |  |  |           bottom: 10, | 
					
						
							|  |  |  |           left: 20, | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |       fill: { | 
					
						
							|  |  |  |         type: 'gradient', // Gradient fill for the area
 | 
					
						
							|  |  |  |         gradient: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |           shade: isDark ? 'dark' : 'light', | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           type: 'vertical', | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |           shadeIntensity: 0.1, | 
					
						
							|  |  |  |           opacityFrom: isDark ? 0.2 : 0.3, | 
					
						
							|  |  |  |           opacityTo: 0, | 
					
						
							| 
									
										
										
										
											2025-01-15 16:00:03 +01:00
										 |  |  |           stops: [0, 100], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       colors: isDark ? this.CHART_COLORS.dark : this.CHART_COLORS.light, | 
					
						
							|  |  |  |       theme: { | 
					
						
							|  |  |  |         mode: theme, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     try { | 
					
						
							|  |  |  |       this.chart = new ApexCharts(this.shadowRoot.querySelector('.chartContainer'), options); | 
					
						
							|  |  |  |       await this.chart.render(); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Give the chart a moment to fully initialize before resizing
 | 
					
						
							|  |  |  |       await new Promise(resolve => setTimeout(resolve, 100)); | 
					
						
							|  |  |  |       await this.resizeChart(); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Ensure resize observer is watching the mainbox
 | 
					
						
							|  |  |  |       const mainbox = this.shadowRoot.querySelector('.mainbox'); | 
					
						
							|  |  |  |       if (mainbox && this.resizeObserver) { | 
					
						
							|  |  |  |         // Disconnect any previous observations
 | 
					
						
							|  |  |  |         this.resizeObserver.disconnect(); | 
					
						
							|  |  |  |         // Start observing the mainbox
 | 
					
						
							|  |  |  |         this.resizeObserver.observe(mainbox); | 
					
						
							|  |  |  |         if (this.DEBUG_RESIZE) { | 
					
						
							|  |  |  |           console.log('DeesChartArea - ResizeObserver attached to mainbox'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |       console.error('Failed to initialize chart:', error); | 
					
						
							|  |  |  |       // Optionally, you could set an error state here
 | 
					
						
							|  |  |  |       // this.chartState = 'error';
 | 
					
						
							|  |  |  |       // this.errorMessage = 'Failed to initialize chart';
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   public async updated(changedProperties: Map<string, any>) { | 
					
						
							|  |  |  |     super.updated(changedProperties); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     // Update chart theme when goBright changes
 | 
					
						
							|  |  |  |     if (changedProperties.has('goBright') && this.chart) { | 
					
						
							|  |  |  |       await this.updateChartTheme(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |     // Update chart if series data changes
 | 
					
						
							|  |  |  |     if (changedProperties.has('series') && this.chart && this.series.length > 0) { | 
					
						
							|  |  |  |       await this.updateSeries(this.series); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Update y-axis formatter if it changes
 | 
					
						
							|  |  |  |     if (changedProperties.has('yAxisFormatter') && this.chart) { | 
					
						
							|  |  |  |       await this.chart.updateOptions({ | 
					
						
							|  |  |  |         yaxis: { | 
					
						
							|  |  |  |           labels: { | 
					
						
							|  |  |  |             formatter: this.yAxisFormatter, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     // Handle realtime mode changes
 | 
					
						
							|  |  |  |     if (changedProperties.has('realtimeMode') && this.chart) { | 
					
						
							|  |  |  |       await this.chart.updateOptions({ | 
					
						
							|  |  |  |         chart: { | 
					
						
							|  |  |  |           animations: { | 
					
						
							|  |  |  |             enabled: !this.realtimeMode, | 
					
						
							|  |  |  |             speed: 400, | 
					
						
							|  |  |  |             animateGradually: { | 
					
						
							|  |  |  |               enabled: false, | 
					
						
							|  |  |  |               delay: 0 | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             dynamicAnimation: { | 
					
						
							|  |  |  |               enabled: !this.realtimeMode, | 
					
						
							|  |  |  |               speed: 350 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Start/stop auto-scroll based on realtime mode
 | 
					
						
							|  |  |  |       if (this.realtimeMode && this.rollingWindow > 0 && this.autoScrollInterval > 0) { | 
					
						
							|  |  |  |         this.startAutoScroll(); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         this.stopAutoScroll(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Handle auto-scroll interval changes
 | 
					
						
							|  |  |  |     if (changedProperties.has('autoScrollInterval') && this.chart) { | 
					
						
							|  |  |  |       this.stopAutoScroll(); | 
					
						
							|  |  |  |       if (this.realtimeMode && this.rollingWindow > 0 && this.autoScrollInterval > 0) { | 
					
						
							|  |  |  |         this.startAutoScroll(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // Handle y-axis scaling changes
 | 
					
						
							|  |  |  |     if ((changedProperties.has('yAxisScaling') || changedProperties.has('yAxisMax')) && this.chart) { | 
					
						
							|  |  |  |       await this.chart.updateOptions({ | 
					
						
							|  |  |  |         yaxis: { | 
					
						
							|  |  |  |           min: 0, | 
					
						
							|  |  |  |           max: this.yAxisScaling === 'dynamic' ? undefined : this.yAxisMax | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |   public async updateSeries(newSeries: ApexAxisChartSeries, animate: boolean = true) { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |     if (!this.chart) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     try { | 
					
						
							|  |  |  |       // Store the new data first
 | 
					
						
							|  |  |  |       this.internalChartData = newSeries; | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |        | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       // Handle rolling window if enabled
 | 
					
						
							|  |  |  |       if (this.rollingWindow > 0 && this.realtimeMode) { | 
					
						
							|  |  |  |         const now = Date.now(); | 
					
						
							|  |  |  |         const cutoffTime = now - this.rollingWindow; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Filter data to only include points within the rolling window
 | 
					
						
							|  |  |  |         const filteredSeries = newSeries.map(series => ({ | 
					
						
							|  |  |  |           name: series.name, | 
					
						
							|  |  |  |           data: (series.data as any[]).filter(point => { | 
					
						
							|  |  |  |             if (typeof point === 'object' && point !== null && 'x' in point) { | 
					
						
							|  |  |  |               return new Date(point.x).getTime() > cutoffTime; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |           }) | 
					
						
							|  |  |  |         })); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Only update if we have data
 | 
					
						
							|  |  |  |         if (filteredSeries.some(s => s.data.length > 0)) { | 
					
						
							|  |  |  |           // Handle y-axis scaling first
 | 
					
						
							|  |  |  |           if (this.yAxisScaling === 'dynamic') { | 
					
						
							|  |  |  |             const allValues = filteredSeries.flatMap(s => (s.data as any[]).map(d => d.y)); | 
					
						
							|  |  |  |             if (allValues.length > 0) { | 
					
						
							|  |  |  |               const maxValue = Math.max(...allValues); | 
					
						
							|  |  |  |               const dynamicMax = Math.ceil(maxValue * 1.1); | 
					
						
							|  |  |  |               await this.chart.updateOptions({ | 
					
						
							|  |  |  |                 yaxis: { | 
					
						
							|  |  |  |                   min: 0, | 
					
						
							|  |  |  |                   max: dynamicMax | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }, false, false); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |            | 
					
						
							|  |  |  |           await this.chart.updateSeries(filteredSeries, false); | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       } else { | 
					
						
							|  |  |  |         await this.chart.updateSeries(newSeries, animate); | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     } catch (error) { | 
					
						
							|  |  |  |       console.error('Failed to update chart series:', error); | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |   // Update just the x-axis for smooth scrolling in realtime mode
 | 
					
						
							|  |  |  |   // Public for advanced usage in demos, but typically handled automatically
 | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |   public async updateTimeWindow() { | 
					
						
							|  |  |  |     if (!this.chart || this.rollingWindow <= 0) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     const now = Date.now(); | 
					
						
							|  |  |  |     const cutoffTime = now - this.rollingWindow; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     await this.chart.updateOptions({ | 
					
						
							|  |  |  |       xaxis: { | 
					
						
							|  |  |  |         min: cutoffTime, | 
					
						
							|  |  |  |         max: now, | 
					
						
							|  |  |  |         labels: { | 
					
						
							|  |  |  |           format: 'HH:mm:ss', | 
					
						
							|  |  |  |           datetimeUTC: false, | 
					
						
							|  |  |  |           style: { | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |             colors: [!this.goBright ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'], | 
					
						
							|  |  |  |             fontSize: '12px', | 
					
						
							|  |  |  |             fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', | 
					
						
							|  |  |  |             fontWeight: '400', | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         tickAmount: 6, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, false, false); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |   public async appendData(newData: { data: any[] }[]) { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |     if (!this.chart) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |     // Use ApexCharts' appendData method for smoother real-time updates
 | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |     this.chart.appendData(newData); | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   public async updateOptions(options: ApexCharts.ApexOptions, redrawPaths?: boolean, animate?: boolean) { | 
					
						
							|  |  |  |     if (!this.chart) { | 
					
						
							|  |  |  |       return; | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-16 14:37:09 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     return this.chart.updateOptions(options, redrawPaths, animate); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:09:14 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  |   public async resizeChart() { | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |     if (!this.chart) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |     if (this.DEBUG_RESIZE) { | 
					
						
							|  |  |  |       console.log('DeesChartArea - resizeChart called'); | 
					
						
							| 
									
										
										
										
											2025-06-12 11:00:33 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox'); | 
					
						
							|  |  |  |       const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer'); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       if (!mainbox || !chartContainer) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       // Force layout recalculation
 | 
					
						
							|  |  |  |       void mainbox.offsetHeight; | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       // Get computed style of the element
 | 
					
						
							|  |  |  |       const styleChartContainer = window.getComputedStyle(chartContainer); | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       // Extract padding values
 | 
					
						
							|  |  |  |       const paddingTop = parseInt(styleChartContainer.paddingTop, 10); | 
					
						
							|  |  |  |       const paddingBottom = parseInt(styleChartContainer.paddingBottom, 10); | 
					
						
							|  |  |  |       const paddingLeft = parseInt(styleChartContainer.paddingLeft, 10); | 
					
						
							|  |  |  |       const paddingRight = parseInt(styleChartContainer.paddingRight, 10); | 
					
						
							| 
									
										
										
										
											2024-02-03 14:42:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |       // Calculate the actual width and height to use, subtracting padding
 | 
					
						
							|  |  |  |       const actualWidth = mainbox.clientWidth - paddingLeft - paddingRight; | 
					
						
							|  |  |  |       const actualHeight = mainbox.offsetHeight - paddingTop - paddingBottom; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       // Validate dimensions
 | 
					
						
							|  |  |  |       if (actualWidth > 0 && actualHeight > 0) { | 
					
						
							|  |  |  |         if (this.DEBUG_RESIZE) { | 
					
						
							|  |  |  |           console.log('DeesChartArea - Updating chart dimensions:', { | 
					
						
							|  |  |  |             width: actualWidth, | 
					
						
							|  |  |  |             height: actualHeight | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         await this.chart.updateOptions({ | 
					
						
							|  |  |  |           chart: { | 
					
						
							|  |  |  |             width: actualWidth, | 
					
						
							|  |  |  |             height: actualHeight, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, true, false); // Redraw paths but don't animate
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |       console.error('Failed to resize chart:', error); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Manually trigger a chart resize. Useful when automatic detection doesn't work. | 
					
						
							|  |  |  |    * This is a convenience method that can be called from outside the component. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   public async forceResize() { | 
					
						
							|  |  |  |     await this.resizeChart(); | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-06-16 22:23:22 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   private startAutoScroll() { | 
					
						
							|  |  |  |     if (this.autoScrollTimer) { | 
					
						
							|  |  |  |       return; // Already running
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     this.autoScrollTimer = window.setInterval(() => { | 
					
						
							|  |  |  |       this.updateTimeWindow(); | 
					
						
							|  |  |  |     }, this.autoScrollInterval); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   private stopAutoScroll() { | 
					
						
							|  |  |  |     if (this.autoScrollTimer) { | 
					
						
							|  |  |  |       window.clearInterval(this.autoScrollTimer); | 
					
						
							|  |  |  |       this.autoScrollTimer = null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-06-27 15:43:26 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   private async updateChartTheme() { | 
					
						
							|  |  |  |     if (!this.chart) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     const isDark = !this.goBright; | 
					
						
							|  |  |  |     const theme = isDark ? 'dark' : 'light'; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     await this.chart.updateOptions({ | 
					
						
							|  |  |  |       theme: { | 
					
						
							|  |  |  |         mode: theme, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       colors: isDark ? this.CHART_COLORS.dark : this.CHART_COLORS.light, | 
					
						
							|  |  |  |       xaxis: { | 
					
						
							|  |  |  |         labels: { | 
					
						
							|  |  |  |           style: { | 
					
						
							|  |  |  |             colors: [isDark ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'], | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       yaxis: { | 
					
						
							|  |  |  |         labels: { | 
					
						
							|  |  |  |           style: { | 
					
						
							|  |  |  |             colors: [isDark ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'], | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       grid: { | 
					
						
							|  |  |  |         borderColor: isDark ? 'hsl(0 0% 14.9%)' : 'hsl(0 0% 94%)', | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       fill: { | 
					
						
							|  |  |  |         gradient: { | 
					
						
							|  |  |  |           shade: isDark ? 'dark' : 'light', | 
					
						
							|  |  |  |           opacityFrom: isDark ? 0.2 : 0.3, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-02-03 11:26:15 +01:00
										 |  |  | } |