import { DeesElement, css, cssManager, customElement, html, property, state, type CSSResult, type TemplateResult, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; import { demoFunc } from './dees-chart-area.demo.js'; 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; // instance @state() public chart: ApexCharts; @property() public label: string = 'Untitled Chart'; private resizeObserver: ResizeObserver; constructor() { super(); domtools.elementBasic.setup(); this.resizeObserver = new ResizeObserver((entries) => { for (let entry of entries) { if (entry.target.classList.contains('mainbox')) { this.resizeChart(); // Call resizeChart when the .mainbox size changes } } }); this.registerStartupFunction(async () => { this.updateComplete.then(() => { const mainbox = this.shadowRoot.querySelector('.mainbox'); if (mainbox) { this.resizeObserver.observe(mainbox); // Start observing the .mainbox element } }); }); this.registerGarbageFunction(async () => { this.resizeObserver.disconnect(); }); } public static styles = [ cssManager.defaultStyles, css` :host { font-family: 'Geist Sans', sans-serif; color: #ccc; font-weight: 600; font-size: 12px; } .mainbox { position: relative; width: 100%; height: 400px; background: #111; border-radius: 8px; } .chartTitle { position: absolute; top: 0; left: 0; width: 100%; text-align: center; padding-top: 16px; } .chartContainer { position: absolute; top: 0px; left: 0px; bottom: 0px; right: 0px; padding: 32px 16px 16px 0px; } `, ]; public render(): TemplateResult { return html`
${this.label}
`; } public async firstUpdated() { const domtoolsInstance = await this.domtoolsPromise; var options: ApexCharts.ApexOptions = { 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 }, ], }, ], chart: { width: 0, // Adjusted for responsive width height: 0, // Adjusted for responsive height type: 'area', toolbar: { show: false, // This line disables the toolbar }, }, dataLabels: { enabled: false, }, stroke: { width: 1, curve: 'smooth', }, xaxis: { type: 'datetime', // Time-series data labels: { format: 'hh:mm A', // Time formatting style: { colors: '#9e9e9e', // Label color fontSize: '12px', }, }, axisBorder: { show: false, // Hide x-axis border }, axisTicks: { show: false, // Hide x-axis ticks }, }, yaxis: { min: 0, labels: { formatter: function (val: number) { return `${val} Mbps`; // Format Y-axis labels }, style: { colors: '#9e9e9e', // Label color fontSize: '12px', }, }, axisBorder: { show: false, // Hide y-axis border }, axisTicks: { show: false, // Hide y-axis ticks }, }, tooltip: { 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 x: { format: 'dd/MM/yy HH:mm', }, custom: function ({ series, seriesIndex, dataPointIndex, w }) { // Get the x value const xValue = w.globals.labels[dataPointIndex]; // Iterate through each series and get its value let tooltipContent = `
`; tooltipContent += ``; // `Time: ${xValue}
`; series.forEach((s, index) => { const label = w.globals.seriesNames[index]; // Get series label const value = s[dataPointIndex]; // Get value at data point tooltipContent += `${label}: ${value} Mbps
`; }); tooltipContent += `
`; return tooltipContent; }, }, grid: { xaxis: { lines: { show: true, // This enables the grid lines along the x-axis }, }, yaxis: { lines: { show: true, }, }, borderColor: '#333', // Set the color of the grid lines strokeDashArray: 0, // Solid line row: { colors: [], // This can be used to alternate the shading of the horizontal rows opacity: 0.1, }, column: { colors: [], // For vertical column bands, not needed here but available for customization opacity: 0.1, }, }, fill: { type: 'gradient', // Gradient fill for the area gradient: { shade: 'dark', type: 'vertical', gradientToColors: ['#9c27b0'], // Gradient color ending stops: [0, 100], }, }, }; this.chart = new ApexCharts(this.shadowRoot.querySelector('.chartContainer'), options); await this.chart.render(); await this.resizeChart(); } public async resizeChart() { const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox'); const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer'); // Get computed style of the element const styleMainbox = window.getComputedStyle(mainbox); const styleChartContainer = window.getComputedStyle(chartContainer); // 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); // Calculate the actual width and height to use, subtracting padding const actualWidth = mainbox.clientWidth - paddingLeft - paddingRight; const actualHeight = mainbox.offsetHeight - paddingTop - paddingBottom; await this.chart.updateOptions({ chart: { width: actualWidth, height: actualHeight, }, }); } }