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`
${this.subtitle}
` : null} -