dees-catalog/ts_web/elements/dees-chart-area.ts

267 lines
7.4 KiB
TypeScript

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`
<div class="mainbox">
<div class="chartTitle">${this.label}</div>
<div class="chartContainer"></div>
</div>
`;
}
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 = `<div style="padding: 10px; background: #1e1e2f; color: white; border-radius: 5px;">`;
tooltipContent += ``; // `<strong>Time:</strong> ${xValue}<br/>`;
series.forEach((s, index) => {
const label = w.globals.seriesNames[index]; // Get series label
const value = s[dataPointIndex]; // Get value at data point
tooltipContent += `<strong>${label}:</strong> ${value} Mbps<br/>`;
});
tooltipContent += `</div>`;
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,
},
});
}
}