From 3477e74a839c0e6a8d7d00acc62a2a44440b35e6 Mon Sep 17 00:00:00 2001 From: CodingPhoenixx Date: Fri, 13 Feb 2026 17:42:20 +0100 Subject: [PATCH] fixed some alignment --- flightscore/src/components/line-chart.ts | 281 +++++++++++++---------- 1 file changed, 155 insertions(+), 126 deletions(-) diff --git a/flightscore/src/components/line-chart.ts b/flightscore/src/components/line-chart.ts index b7286cd..e97c070 100644 --- a/flightscore/src/components/line-chart.ts +++ b/flightscore/src/components/line-chart.ts @@ -2,16 +2,17 @@ import { LitElement, html, css, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; export interface LineSeries { - label: string; - color?: string; - points: { x: number; y: number }[]; + label: string; + color?: string; + points: { x: number; y: number }[]; } @customElement('line-chart') export class LineChart extends LitElement { - static styles = css` -:host { - display: inline-flex; + static styles = css` + :host { + display: block; + width: 100%; } .chart-wrapper { @@ -23,6 +24,8 @@ export class LineChart extends LitElement { flex-direction: column; gap: 1.25rem; transition: border-color 0.25s ease; + height: 100%; + box-sizing: border-box; } .chart-wrapper:hover { @@ -37,6 +40,7 @@ export class LineChart extends LitElement { display: flex; justify-content: space-between; align-items: baseline; + flex-shrink: 0; } .title { @@ -52,10 +56,16 @@ export class LineChart extends LitElement { margin: 0; } -.svg-container { + .svg-container { width: 100%; - overflow: visible; + min-height: 0; + flex: 1 1 auto; aspect-ratio: 500 / 300; + overflow: visible; + } + + :host([style*='height']) .svg-container { + aspect-ratio: unset; } svg { @@ -64,6 +74,7 @@ export class LineChart extends LitElement { overflow: visible; display: block; } + .grid-line { stroke: var(--color-border); stroke-width: 0.5; @@ -97,6 +108,7 @@ export class LineChart extends LitElement { display: flex; gap: 1rem; flex-wrap: wrap; + flex-shrink: 0; } .legend-item { @@ -119,154 +131,171 @@ export class LineChart extends LitElement { } `; - @property() heading = ''; - @property() subtitle = ''; - @property() xLabel = 'X'; - @property() yLabel = 'Y'; - @property({ type: Array }) series: LineSeries[] = []; - @property({ type: Boolean }) showArea = false; + @property() heading = ''; + @property() subtitle = ''; + @property() xLabel = 'X'; + @property() yLabel = 'Y'; + @property({ type: Array }) series: LineSeries[] = []; + @property({ type: Boolean }) showArea = false; - private defaultColors = [ - 'var(--color-accent)', - '#30a46c', - '#e79d13', - '#e5484d', - '#6e56cf', - '#0091ff', - ]; + private defaultColors = [ + 'var(--color-accent)', + '#30a46c', + '#e79d13', + '#e5484d', + '#6e56cf', + '#0091ff', + ]; - private padding = { top: 20, right: 25, bottom: 40, left: 45 }; - private width = 500; - private height = 300; + private padding = { top: 20, right: 25, bottom: 40, left: 45 }; + private width = 500; + private height = 300; - private niceScale(min: number, max: number, ticks: number) { - const range = max - min || 1; - const rough = range / ticks; - const mag = Math.pow(10, Math.floor(Math.log10(rough))); - const norm = rough / mag; - let step: number; - if (norm <= 1.5) step = 1 * mag; - else if (norm <= 3) step = 2 * mag; - else if (norm <= 7) step = 5 * mag; - else step = 10 * mag; - const nMin = Math.floor(min / step) * step; - const nMax = Math.ceil(max / step) * step; - return { min: nMin, max: nMax, step }; - } + private niceScale(min: number, max: number, ticks: number) { + const range = max - min || 1; + const rough = range / ticks; + const mag = Math.pow(10, Math.floor(Math.log10(rough))); + const norm = rough / mag; + let step: number; + if (norm <= 1.5) step = 1 * mag; + else if (norm <= 3) step = 2 * mag; + else if (norm <= 7) step = 5 * mag; + else step = 10 * mag; + const nMin = Math.floor(min / step) * step; + const nMax = Math.ceil(max / step) * step; + return { min: nMin, max: nMax, step }; + } - render() { - const p = this.padding; - const w = this.width - p.left - p.right; - const h = this.height - p.top - p.bottom; + render() { + const p = this.padding; + const w = this.width - p.left - p.right; + const h = this.height - p.top - p.bottom; - const allPts = this.series.flatMap((s) => s.points); - const xs = allPts.map((d) => d.x); - const ys = allPts.map((d) => d.y); - const rawXMin = Math.min(...xs, 0); - const rawXMax = Math.max(...xs, 1); - const rawYMin = Math.min(...ys, 0); - const rawYMax = Math.max(...ys, 1); + const allPts = this.series.flatMap((s) => s.points); + const xs = allPts.map((d) => d.x); + const ys = allPts.map((d) => d.y); + const rawXMin = Math.min(...xs, 0); + const rawXMax = Math.max(...xs, 1); + const rawYMin = Math.min(...ys, 0); + const rawYMax = Math.max(...ys, 1); - const xScale = this.niceScale(rawXMin, rawXMax, 5); - const yScale = this.niceScale(rawYMin, rawYMax, 5); + const xScale = this.niceScale(rawXMin, rawXMax, 5); + const yScale = this.niceScale(rawYMin, rawYMax, 5); - const sx = (v: number) => - p.left + ((v - xScale.min) / (xScale.max - xScale.min)) * w; - const sy = (v: number) => - p.top + - h - - ((v - yScale.min) / (yScale.max - yScale.min)) * h; + const sx = (v: number) => + p.left + ((v - xScale.min) / (xScale.max - xScale.min)) * w; + const sy = (v: number) => + p.top + h - ((v - yScale.min) / (yScale.max - yScale.min)) * h; - const gridLines = []; - for ( - let val = yScale.min; - val <= yScale.max + yScale.step * 0.01; - val += yScale.step - ) { - const y = sy(val); - gridLines.push(svg` + const gridLines = []; + for ( + let val = yScale.min; + val <= yScale.max + yScale.step * 0.01; + val += yScale.step + ) { + const y = sy(val); + gridLines.push(svg` ${Math.round(val)} `); - } - for ( - let val = xScale.min; - val <= xScale.max + xScale.step * 0.01; - val += xScale.step - ) { - const x = sx(val); - gridLines.push(svg` + } + for ( + let val = xScale.min; + val <= xScale.max + xScale.step * 0.01; + val += xScale.step + ) { + const x = sx(val); + gridLines.push(svg` ${Math.round(val)} `); - } + } - const baseLine = sy(yScale.min); + const baseLine = sy(yScale.min); - const lines = this.series.map((s, i) => { - const color = - s.color || this.defaultColors[i % this.defaultColors.length]; - const sorted = [...s.points].sort((a, b) => a.x - b.x); - if (!sorted.length) return svg``; + const lines = this.series.map((s, i) => { + const color = + s.color || this.defaultColors[i % this.defaultColors.length]; + const sorted = [...s.points].sort((a, b) => a.x - b.x); + if (!sorted.length) return svg``; - const d = sorted - .map((pt, j) => `${j === 0 ? 'M' : 'L'}${sx(pt.x)},${sy(pt.y)}`) - .join(' '); + const d = sorted + .map( + (pt, j) => + `${j === 0 ? 'M' : 'L'}${sx(pt.x)},${sy(pt.y)}` + ) + .join(' '); - const areaD = - `M${sx(sorted[0].x)},${baseLine} ` + - sorted.map((pt) => `L${sx(pt.x)},${sy(pt.y)}`).join(' ') + - ` L${sx(sorted[sorted.length - 1].x)},${baseLine} Z`; + const areaD = + `M${sx(sorted[0].x)},${baseLine} ` + + sorted.map((pt) => `L${sx(pt.x)},${sy(pt.y)}`).join(' ') + + ` L${sx(sorted[sorted.length - 1].x)},${baseLine} Z`; - return svg` + return svg` ${this.showArea ? svg`` : null} `; - }); + }); - return html` -
+ return html` +
${this.heading || this.subtitle - ? html` -
- ${this.heading + ? html` +
+ ${this.heading ? html`

${this.heading}

` : null} - ${this.subtitle + ${this.subtitle ? html`

${this.subtitle}

` : null} -
- ` - : null} +
+ ` + : null}
- - ${gridLines} ${lines} - - ${this.xLabel} - - - ${this.yLabel} - - + + ${gridLines} ${lines} + + ${this.xLabel} + + + ${this.yLabel} + +
${this.series.length > 1 - ? html` -
- ${this.series.map( - (s, i) => html` -
- - ${s.label} -
+ ? html` +
+ ${this.series.map( + (s, i) => html` +
+ + ${s.label} +
+ ` + )} +
` - )} -
- ` - : null} -
+ : null} +
`; - } + } } \ No newline at end of file