diff --git a/tgui/packages/tgui/components/Chart.jsx b/tgui/packages/tgui/components/Chart.tsx similarity index 53% rename from tgui/packages/tgui/components/Chart.jsx rename to tgui/packages/tgui/components/Chart.tsx index 1e856135c659..205dc6fbec1a 100644 --- a/tgui/packages/tgui/components/Chart.jsx +++ b/tgui/packages/tgui/components/Chart.tsx @@ -5,28 +5,57 @@ */ import { map, zipWith } from 'common/collections'; -import { Component, createRef } from 'react'; -import { Box } from './Box'; +import { Component, createRef, RefObject } from 'react'; -const normalizeData = (data, scale, rangeX, rangeY) => { +import { Box, BoxProps } from './Box'; + +type Props = { + data: number[][]; +} & Partial<{ + fillColor: string; + rangeX: [number, number]; + rangeY: [number, number]; + strokeColor: string; + strokeWidth: number; +}> & + BoxProps; + +type State = { + viewBox: [number, number]; +}; + +type Point = number[]; +type Range = [number, number]; + +const normalizeData = ( + data: Point[], + scale: number[], + rangeX?: Range, + rangeY?: Range, +) => { if (data.length === 0) { return []; } + const min = zipWith(Math.min)(...data); const max = zipWith(Math.max)(...data); + if (rangeX !== undefined) { min[0] = rangeX[0]; max[0] = rangeX[1]; } + if (rangeY !== undefined) { min[1] = rangeY[0]; max[1] = rangeY[1]; } - const normalized = map((point) => { - return zipWith((value, min, max, scale) => { + + const normalized = map((point: Point) => { + return zipWith((value: number, min: number, max: number, scale: number) => { return ((value - min) / (max - min)) * scale; })(point, min, max, scale); })(data); + return normalized; }; @@ -39,21 +68,18 @@ const dataToPolylinePoints = (data) => { return points; }; -class LineChart extends Component { - constructor(props) { +class LineChart extends Component { + ref: RefObject; + state: State; + + constructor(props: Props) { super(props); this.ref = createRef(); this.state = { // Initial guess viewBox: [600, 200], }; - this.handleResize = () => { - const element = this.ref.current; - if (!element) return; - this.setState({ - viewBox: [element.offsetWidth, element.offsetHeight], - }); - }; + this.handleResize = this.handleResize.bind(this); } componentDidMount() { @@ -65,6 +91,16 @@ class LineChart extends Component { window.removeEventListener('resize', this.handleResize); } + handleResize = () => { + const element = this.ref.current; + if (!element) { + return; + } + this.setState({ + viewBox: [element.offsetWidth, element.offsetHeight], + }); + }; + render() { const { data = [], @@ -87,32 +123,32 @@ class LineChart extends Component { normalized.push([-strokeWidth, first[1]]); } const points = dataToPolylinePoints(normalized); + const divProps = { ...rest, className: '', ref: this.ref }; + return ( - {(props) => ( -
- - - -
- )} + + + + +
); } diff --git a/tgui/packages/tgui/interfaces/PowerMonitor.jsx b/tgui/packages/tgui/interfaces/PowerMonitor.jsx index 0e317e72d201..ece815d649c2 100644 --- a/tgui/packages/tgui/interfaces/PowerMonitor.jsx +++ b/tgui/packages/tgui/interfaces/PowerMonitor.jsx @@ -35,7 +35,7 @@ export const PowerMonitor = () => { export const PowerMonitorContent = (props) => { const { data } = useBackend(); - const { history } = data; + const { history = { supply: [], demand: [] } } = data; const [sortByField, setSortByField] = useLocalState('sortByField', null); const supply = history.supply[history.supply.length - 1] || 0; const demand = history.demand[history.demand.length - 1] || 0; @@ -87,7 +87,7 @@ export const PowerMonitorContent = (props) => { -
+