From 142499bfca9ccf7eba96a629a9f5734c5967a7df Mon Sep 17 00:00:00 2001 From: Timmy Luong Date: Wed, 16 Jun 2021 10:37:29 -0700 Subject: [PATCH] feat: implement custom callback for static legend (#615) --- giraffe/README.md | 17 ++ giraffe/package.json | 2 +- giraffe/src/components/Legend.tsx | 41 ++++- giraffe/src/components/LegendStyles.ts | 77 ++++++-- giraffe/src/components/StaticLegendBox.tsx | 48 ++++- giraffe/src/components/Tooltip.tsx | 2 +- giraffe/src/constants/index.ts | 8 + giraffe/src/types/index.ts | 19 ++ .../{getTextMetrics.ts => textMetrics.ts} | 0 giraffe/src/utils/getMargins.ts | 2 +- giraffe/src/utils/getTicks.test.ts | 2 +- giraffe/src/utils/getTicks.ts | 2 +- .../{getTextMetrics.ts => textMetrics.ts} | 39 +++- stories/package.json | 2 +- stories/src/staticLegend.stories.tsx | 171 ++++++++++++++++++ 15 files changed, 391 insertions(+), 41 deletions(-) rename giraffe/src/utils/__mocks__/{getTextMetrics.ts => textMetrics.ts} (100%) rename giraffe/src/utils/{getTextMetrics.ts => textMetrics.ts} (56%) diff --git a/giraffe/README.md b/giraffe/README.md index d34f3e3c..20542438 100644 --- a/giraffe/README.md +++ b/giraffe/README.md @@ -432,6 +432,23 @@ When using the comma separated values (CSV) from the Flux query as the `fluxResp - **orientationThreshold**: _number. Optional. Defaults to undefined when excluded._ The number of columns in the legend that will determine the direction of columns in the legend. When _undefined_ or when the total number of columns is less than or equal to it, the columns in the tooltip will display horizontally. When the total number of columns is greater, the columns will display vertically. + - **renderEffect**: _function(object). Optional. Defaults to an empty function (no operation) when excluded._ A callback function that executes after each render. The purpose is to allow the consumer to adjust `config` properties based on certain aspects of the static legend. An example would be auto-adjusting the height of the static legend to fit its contents. This function is given an _options_ object as the argument which has the following properties: + - **totalHeight**: _number._ The height of the `` including the static legend. + + - **staticLegendHeight**: _number._ The height of the static legend. + + - **legendDataLength**: _number._ The total number of "fill" columns plus any additional columns added by the static legend to be rendered. + + - **lineCount**: _number._ The total number of rows, when in a horizontal orientation, excluding the header row. Or the total number of columns, when in a vertical orientation, excluding the header column. + + - **lineSpacingRatio**: _number._ The [relative unit length](https://developer.mozilla.org/en-US/docs/Web/CSS/length) in **em** of the spacing between rows. When in a horizontal orientation, this number in **em** is equal to the spacing. When in a vertical orientation, the spacing is twice this number in **em**. + + - **padding**: _number._ The default padding added around all of the content in the static legend. Does not include any padding that is applied by **style** or any other custom styling. + + - **headerTextMetrics**: _Object._ An object whose properties are estimates of the width and height in the header row (horizontal orientation) or header column (vertical orientation). + + - **sampleTextMetrics**: _Object._ An object whose properties are estimates of the width and height of each entry in an example row (horizontal orientation) or example column (vertical orientation). + - **style**: _Object. Optional._ An object containing the key-value pairs used for inline styling the class `.giraffe-static-legend` by using the [style property](https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style). Primarily used for adjusting `margin` and `padding`. May be used to add additional styling to Static Legend, but does not affect the following styles: `backgroundColor`, `border`, `bottom`, `color`, `cursor`, `font`, `height`, `left`, `opacity`, `overflow`, `position`, `right`, `top`, `width`. - **valueAxis**: _string. Optional. Defaults to 'y' when not included. Valid values are either 'x' or 'y'. This is to set where the 'values' that are displayed in the tooltip come from (which axis, x or y) diff --git a/giraffe/package.json b/giraffe/package.json index 943f3dff..d1f4cf47 100644 --- a/giraffe/package.json +++ b/giraffe/package.json @@ -1,6 +1,6 @@ { "name": "@influxdata/giraffe", - "version": "2.14.2", + "version": "2.15.0", "main": "dist/index.js", "module": "src/index.js", "license": "MIT", diff --git a/giraffe/src/components/Legend.tsx b/giraffe/src/components/Legend.tsx index f253118a..6025b2da 100644 --- a/giraffe/src/components/Legend.tsx +++ b/giraffe/src/components/Legend.tsx @@ -1,16 +1,22 @@ import React, {CSSProperties} from 'react' import {FunctionComponent} from 'react' -import {LegendData, Config} from '../types' +import {Config, LegendData, LegendType} from '../types' import {generateLegendStyles, LegendPillsStyles} from './LegendStyles' +import { + LEGEND_COLUMN_CLASSNAME, + STATIC_LEGEND_COLUMN_CLASSNAME, +} from '../constants' interface Props { + type: LegendType data: LegendData config: Config isScrollable?: boolean } export const Legend: FunctionComponent = ({ + type: legendType, data, config, isScrollable = false, @@ -48,6 +54,7 @@ export const Legend: FunctionComponent = ({ const maxLength = switchToVertical ? width : height const styles = generateLegendStyles( + legendType, isScrollable, columns, switchToVertical, @@ -62,9 +69,12 @@ export const Legend: FunctionComponent = ({ style={styles.table} data-testid="giraffe-legend-table" > - {!colorizeRows && } + {!colorizeRows && ( + + )} {columns.map(({name, values}, i) => ( = ({ } interface LegendColumnProps { + type: LegendType name: string maxLength: number values: string[] @@ -88,6 +99,7 @@ interface LegendColumnProps { } const LegendColumn: FunctionComponent = ({ + type: legendType, name, maxLength, values, @@ -96,14 +108,19 @@ const LegendColumn: FunctionComponent = ({ columnValueStyles, }) => { const valuesLimitedByPlotDimensions = values.slice(0, maxLength) + const classNameBase = + legendType === 'static' + ? STATIC_LEGEND_COLUMN_CLASSNAME + : LEGEND_COLUMN_CLASSNAME + return ( -
-
+
+
{name}
{valuesLimitedByPlotDimensions.map((value, i) => (
@@ -117,22 +134,28 @@ const LegendColumn: FunctionComponent = ({ LegendColumn.displayName = 'LegendColumn' interface LegendPillColumnProps { + type: LegendType styles: LegendPillsStyles } const LegendPillColumn: FunctionComponent = ({ + type: legendType, styles, }) => { const {column, header, value, pills} = styles + const classNameBase = + legendType === 'static' + ? STATIC_LEGEND_COLUMN_CLASSNAME + : LEGEND_COLUMN_CLASSNAME return ( -
-
+
+
 
{pills.map((pill, i) => ( -
-
+
+
))}
diff --git a/giraffe/src/components/LegendStyles.ts b/giraffe/src/components/LegendStyles.ts index bb6081e1..460bc6cd 100644 --- a/giraffe/src/components/LegendStyles.ts +++ b/giraffe/src/components/LegendStyles.ts @@ -1,9 +1,13 @@ import {CSSProperties} from 'react' -import {LegendData, ColumnType} from '../types' +import {ColumnType, LegendData, LegendType} from '../types' // Style Constants +import { + STATIC_LEGEND_LINE_SPACING_RATIO, + STATIC_LEGEND_SCROLL_PADDING, +} from '../constants' + const legendColumnGap = '12px' -const legendColumnPadding = '15px' const legendColumnMaxWidth = '200px' const legendTablePadding = '4px' @@ -37,6 +41,7 @@ export interface LegendStyles { } export const generateLegendStyles = ( + legendType: LegendType, isScrollable: boolean, legendData: LegendData, switchToVertical: boolean, @@ -60,13 +65,21 @@ export const generateLegendStyles = ( const headers = legendColumnHeaderStyle(switchToVertical, fontColor) const values = legendData.map(column => { return column.values.map((_, i) => - legendColumnValueStyle( - i, - column.colors, - colorizeRows, - fontBrightColor, - switchToVertical - ) + legendType === 'tooltip' + ? tooltipColumnValueStyle( + i, + column.colors, + colorizeRows, + fontBrightColor, + switchToVertical + ) + : staticLegendColumnValueStyle( + i, + column.colors, + colorizeRows, + fontBrightColor, + switchToVertical + ) ) }) @@ -119,9 +132,9 @@ const legendColumnStyle = ( } if (isScrollableColumn) { - columnStyle.paddingBottom = legendColumnPadding + columnStyle.paddingBottom = STATIC_LEGEND_SCROLL_PADDING if (index === columnCount) { - columnStyle.paddingRight = legendColumnPadding + columnStyle.paddingRight = STATIC_LEGEND_SCROLL_PADDING } } return columnStyle @@ -147,7 +160,7 @@ const legendColumnHeaderStyle = ( } } -const legendColumnValueStyle = ( +const tooltipColumnValueStyle = ( i: number, colors: string[], colorizeRows: boolean, @@ -186,6 +199,46 @@ const legendColumnValueStyle = ( } } +const staticLegendColumnValueStyle = ( + i: number, + colors: string[], + colorizeRows: boolean, + fontBrightColor: string, + switchToVertical: boolean +): React.CSSProperties => { + let color = fontBrightColor + + if (colorizeRows && colors) { + color = colors[i] + } + + if (switchToVertical) { + return { + maxWidth: legendColumnMaxWidth, + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + color, + display: 'table-cell', + padding: `${2 * STATIC_LEGEND_LINE_SPACING_RATIO}em`, + fontWeight: 600, + lineHeight: '1em', + } + } + + return { + maxWidth: legendColumnMaxWidth, + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + fontWeight: 600, + padding: `${STATIC_LEGEND_LINE_SPACING_RATIO}em`, + lineHeight: '1.25em', + height: '1.25em', + color, + } +} + const LegendPillsColumnStyles = ( switchToVertical: boolean, legendData: LegendData diff --git a/giraffe/src/components/StaticLegendBox.tsx b/giraffe/src/components/StaticLegendBox.tsx index 75c0a740..d7f0a68a 100644 --- a/giraffe/src/components/StaticLegendBox.tsx +++ b/giraffe/src/components/StaticLegendBox.tsx @@ -1,4 +1,4 @@ -import React, {FunctionComponent} from 'react' +import React, {FunctionComponent, useEffect, useMemo} from 'react' import { Formatter, LayerSpec, @@ -6,10 +6,17 @@ import { SizedConfig, StaticLegend, } from '../types' -import {CONFIG_DEFAULTS, STATIC_LEGEND_DEFAULTS} from '../constants/index' +import { + CONFIG_DEFAULTS, + STATIC_LEGEND_DEFAULTS, + STATIC_LEGEND_BOX_PADDING, + STATIC_LEGEND_LINE_SPACING_RATIO, + STATIC_LEGEND_SCROLL_PADDING, +} from '../constants/index' import {Legend} from './Legend' import {DapperScrollbars} from './DapperScrollbars' import {getLegendData} from '../utils/legend/staticLegend' +import {getStaticLegendTexMetrics} from '../utils/textMetrics' interface StaticLegendBoxProps extends StaticLegend { config: SizedConfig @@ -48,7 +55,10 @@ export const StaticLegendBox: FunctionComponent = props => const { config: configOverride, staticLegend: staticLegendOverride, - } = overrideLegendConfig(config, staticLegend) + } = useMemo(() => overrideLegendConfig(config, staticLegend), [ + config, + staticLegend, + ]) const {style = {}} = staticLegendOverride @@ -62,18 +72,31 @@ export const StaticLegendBox: FunctionComponent = props => const layerConfig = configOverride.layers[staticLegendOverride.layer] const valueColumnKey = layerConfig[staticLegendOverride.valueAxis] - const legendData = getLegendData( - layerConfig.type, - spec, - valueColumnKey, - columnFormatter + const legendData = useMemo( + () => + getLegendData(layerConfig.type, spec, valueColumnKey, columnFormatter), + [layerConfig.type, spec, valueColumnKey, columnFormatter] ) + useEffect(() => { + const {headerTextMetrics, sampleTextMetrics} = getStaticLegendTexMetrics() + staticLegendOverride.renderEffect({ + totalHeight: height + top, + staticLegendHeight: height, + legendDataLength: legendData.length, + lineCount: legendData.length ? legendData[0].values.length : 0, + lineSpacingRatio: STATIC_LEGEND_LINE_SPACING_RATIO, + padding: 2 * STATIC_LEGEND_BOX_PADDING + STATIC_LEGEND_SCROLL_PADDING, + headerTextMetrics, + sampleTextMetrics, + }) + }, [legendData, staticLegendOverride]) + return (
= props => data-testid="giraffe-static-legend" > - +
) diff --git a/giraffe/src/components/Tooltip.tsx b/giraffe/src/components/Tooltip.tsx index 63cb83fd..9689b458 100644 --- a/giraffe/src/components/Tooltip.tsx +++ b/giraffe/src/components/Tooltip.tsx @@ -43,7 +43,7 @@ export const Tooltip: FunctionComponent = ({data, config}) => { return null } - const tooltipContents = + const tooltipContents = return createPortal(
= { cursor: 'auto', heightRatio: 0.2, layer: 0, + renderEffect: () => {}, valueAxis: 'y', widthRatio: 1.0, } @@ -142,6 +143,13 @@ export const STATIC_LEGEND_MINIMUM_HEIGHT_RATIO = 0 export const STATIC_LEGEND_MAXIMUM_WIDTH_RATIO = 1.0 export const STATIC_LEGEND_MINIMUM_WIDTH_RATIO = 0 +export const STATIC_LEGEND_LINE_SPACING_RATIO = 1 / 6 +export const STATIC_LEGEND_BOX_PADDING = 10 +export const STATIC_LEGEND_SCROLL_PADDING = 15 + +export const STATIC_LEGEND_COLUMN_CLASSNAME = 'giraffe-static-legend-column' +export const LEGEND_COLUMN_CLASSNAME = 'giraffe-legend-column' + export const TOOLTIP_MINIMUM_OPACITY = 0 export const TOOLTIP_MAXIMUM_OPACITY = 1.0 diff --git a/giraffe/src/types/index.ts b/giraffe/src/types/index.ts index 214922a0..0a1bf454 100644 --- a/giraffe/src/types/index.ts +++ b/giraffe/src/types/index.ts @@ -93,6 +93,8 @@ export interface Config { yColumnType?: ColumnType } +export type LegendType = 'tooltip' | 'static' + export enum LegendPropertyNames { backgroundColor = 'legendBackgroundColor', border = 'legendBorder', @@ -124,11 +126,23 @@ export interface StaticLegend { message?: string opacity?: number orientationThreshold?: number + renderEffect?: (options: StaticLegendRenderEffectOptions) => void // no corresponding legend property, unique to static legend style?: CSSProperties // no correspinding legend property, unique to static legend valueAxis?: 'x' | 'y' // no corresponding legend property, unique to static legend widthRatio?: number // no corresponding legend property, unique to static legend } +export interface StaticLegendRenderEffectOptions { + totalHeight: number + staticLegendHeight: number + legendDataLength: number + lineCount: number + lineSpacingRatio: number + padding: number + headerTextMetrics: TextMetrics + sampleTextMetrics: TextMetrics +} + export interface InteractionHandlerArguments { clampedValueX: number hoverX: number @@ -847,6 +861,11 @@ export enum DomainLabel { Y = 'ys', } +export interface TextMetrics { + width: number + height: number +} + export type AxisTicks = Date[] | number[] export interface BandBorder { diff --git a/giraffe/src/utils/__mocks__/getTextMetrics.ts b/giraffe/src/utils/__mocks__/textMetrics.ts similarity index 100% rename from giraffe/src/utils/__mocks__/getTextMetrics.ts rename to giraffe/src/utils/__mocks__/textMetrics.ts diff --git a/giraffe/src/utils/getMargins.ts b/giraffe/src/utils/getMargins.ts index e9670efe..60fde0b1 100644 --- a/giraffe/src/utils/getMargins.ts +++ b/giraffe/src/utils/getMargins.ts @@ -1,4 +1,4 @@ -import {getTextMetrics} from './getTextMetrics' +import {getTextMetrics} from './textMetrics' import {maxBy} from './extrema' import { diff --git a/giraffe/src/utils/getTicks.test.ts b/giraffe/src/utils/getTicks.test.ts index 3e4621c5..becf54fb 100644 --- a/giraffe/src/utils/getTicks.test.ts +++ b/giraffe/src/utils/getTicks.test.ts @@ -7,7 +7,7 @@ import { getHorizontalTicks, } from './getTicks' -jest.mock('./getTextMetrics') +jest.mock('./textMetrics') describe('utils/getTicks', () => { const font = '10px sans-serif' diff --git a/giraffe/src/utils/getTicks.ts b/giraffe/src/utils/getTicks.ts index af6a5d57..a3918a3b 100644 --- a/giraffe/src/utils/getTicks.ts +++ b/giraffe/src/utils/getTicks.ts @@ -11,7 +11,7 @@ import {TIME, VALUE} from '../constants/columnKeys' import {TICK_COUNT_LIMIT} from '../constants' // Utils -import {getTextMetrics} from './getTextMetrics' +import {getTextMetrics} from './textMetrics' import {isFiniteNumber} from './isFiniteNumber' /* diff --git a/giraffe/src/utils/getTextMetrics.ts b/giraffe/src/utils/textMetrics.ts similarity index 56% rename from giraffe/src/utils/getTextMetrics.ts rename to giraffe/src/utils/textMetrics.ts index b263fe1a..c5e5ea8c 100644 --- a/giraffe/src/utils/getTextMetrics.ts +++ b/giraffe/src/utils/textMetrics.ts @@ -1,7 +1,5 @@ -export interface TextMetrics { - width: number - height: number -} +import {TextMetrics} from '../types' +import {STATIC_LEGEND_COLUMN_CLASSNAME} from '../constants' const addPaddingToSampleText = (text: string): string => { if (typeof text !== 'string') { @@ -49,3 +47,36 @@ export const getTextMetrics = (font: string, text: string): TextMetrics => { return metrics } + +interface StaticLegendTextMetrics { + headerTextMetrics: TextMetrics + sampleTextMetrics: TextMetrics +} + +export const getStaticLegendTexMetrics = (): StaticLegendTextMetrics => { + const sampleHeader = document.querySelector( + `.${STATIC_LEGEND_COLUMN_CLASSNAME}-header` + ) as HTMLElement + + const sampleValue = document.querySelector( + `.${STATIC_LEGEND_COLUMN_CLASSNAME}-value` + ) as HTMLElement + + const headerTextMetrics: TextMetrics = {height: 0, width: 0} + const sampleTextMetrics: TextMetrics = {height: 0, width: 0} + + if (sampleHeader) { + headerTextMetrics.height = sampleHeader.offsetHeight + headerTextMetrics.width = sampleHeader.offsetWidth + } + + if (sampleValue) { + sampleTextMetrics.height = sampleValue.offsetHeight + sampleTextMetrics.width = sampleValue.offsetWidth + } + + return { + headerTextMetrics, + sampleTextMetrics, + } +} diff --git a/stories/package.json b/stories/package.json index 23459cb4..a0dc0db8 100644 --- a/stories/package.json +++ b/stories/package.json @@ -1,6 +1,6 @@ { "name": "@influxdata/giraffe-stories", - "version": "2.13.2", + "version": "2.15.0", "license": "MIT", "scripts": { "lint": "eslint '{src,../giraffe/src}/**/*.{ts,tsx}'", diff --git a/stories/src/staticLegend.stories.tsx b/stories/src/staticLegend.stories.tsx index a90da33b..c794d466 100644 --- a/stories/src/staticLegend.stories.tsx +++ b/stories/src/staticLegend.stories.tsx @@ -37,6 +37,7 @@ import { import {columnAlignment} from './data/staticLegend' const maxValue = Math.random() * Math.floor(200) +let callCounter = 0 storiesOf('Static Legend', module) .addDecorator(withKnobs) @@ -740,3 +741,173 @@ storiesOf('Static Legend', module) ) }) + .add('render effect', () => { + const lines = number('Number of graph lines', 4) + const fillColumnsCount = number('Number of fill columns', 7) + const fillColumnNameLength = number('Length of fill column names', 4) + + const STATIC_LEGEND_HEIGHT_RATIO_NOT_SET = 0 + let staticLegendHeightRatio = STATIC_LEGEND_HEIGHT_RATIO_NOT_SET + staticLegendHeightRatio = number( + 'Static Legend Height', + staticLegendHeightRatio, + { + range: true, + min: 0, + max: 1, + step: 0.01, + } + ) + + const fixedWidth = number('Fixed Width') + const fixedHeight = number('Fixed Height') + const legendHide = boolean('Hide Tooltip?', false) + const staticLegendHide = boolean('Hide Static Legend?', false) + + const fixedPlotSize = {} + if (typeof fixedHeight === 'number' && typeof fixedWidth === 'number') { + fixedPlotSize['height'] = fixedHeight + fixedPlotSize['width'] = fixedWidth + } + const includeNegativeNumbers = boolean('Include negative numbers ?', false) + const position = select( + 'Line Position', + {stacked: 'stacked', overlaid: 'overlaid'}, + 'overlaid' + ) + const table = getRandomTable( + maxValue, + includeNegativeNumbers, + lines * 20, + 20, + fillColumnsCount, + fillColumnNameLength + ) + const colors = colorSchemeKnob() + const legendOrientationThreshold = tooltipOrientationThresholdKnob(20) + const staticLegendOrientationThreshold = number( + 'Static Legend Orientation Threshold', + 20 + ) + const legendColorizeRows = tooltipColorizeRowsKnob() + const staticLegendColorizeRows = boolean( + 'Static Legend Colorize Rows?', + true + ) + const legendFont = legendFontKnob() + const staticLegendFont = text('Static Legend Font', '12px sans-serif') + const staticLegendBorder = text('Static Legend Border', '1px solid orange') + const staticLegendBackgroundColor = text( + 'Static Legend Background Color', + 'transparent' + ) + const tickFont = tickFontKnob() + const x = xKnob(table) + const y = yKnob(table) + const valueAxisLabel = text('Value Axis Label', 'foo') + const xScale = xScaleKnob() + const yScale = yScaleKnob() + const timeZone = timeZoneKnob() + const timeFormat = select( + 'Time Format', + { + 'DD/MM/YYYY HH:mm:ss.sss': 'DD/MM/YYYY HH:mm:ss.sss', + 'MM/DD/YYYY HH:mm:ss.sss': 'MM/DD/YYYY HH:mm:ss.sss', + 'YYYY/MM/DD HH:mm:ss': 'YYYY/MM/DD HH:mm:ss', + 'YYYY-MM-DD HH:mm:ss ZZ': 'YYYY-MM-DD HH:mm:ss ZZ', + 'hh:mm a': 'hh:mm a', + 'HH:mm': 'HH:mm', + 'HH:mm:ss': 'HH:mm:ss', + 'HH:mm:ss ZZ': 'HH:mm:ss ZZ', + 'HH:mm:ss.sss': 'HH:mm:ss.sss', + 'MMMM D, YYYY HH:mm:ss': 'MMMM D, YYYY HH:mm:ss', + 'dddd, MMMM D, YYYY HH:mm:ss': 'dddd, MMMM D, YYYY HH:mm:ss', + }, + 'YYYY-MM-DD HH:mm:ss ZZ' + ) + const fill = fillKnob(table, findStringColumns(table)) + const interpolation = interpolationKnob() + const showAxes = showAxesKnob() + const lineWidth = number('Line Width', 1) + const shadeBelow = boolean('Shade Area', false) + const shadeBelowOpacity = number('Area Opacity', 0.1) + const hoverDimension = select( + 'Hover Dimension', + {auto: 'auto', x: 'x', y: 'y', xy: 'xy'}, + 'auto' + ) + const legendOpacity = number('Legend Opacity', 1.0, { + range: true, + min: 0, + max: 1.0, + step: 0.05, + }) + + const renderEffect = args => { + if (staticLegendHeightRatio === STATIC_LEGEND_HEIGHT_RATIO_NOT_SET) { + callCounter += 1 + + // eslint-disable-next-line + console.log('staticLegend.renderEffect: call counter', callCounter) + // eslint-disable-next-line + console.log('staticLegend.renderEffect: arguments', args) + // eslint-disable-next-line + console.log( + 'staticLegend.renderEffect: heightRatio', + staticLegendHeightRatio + ) + } + } + + const config: Config = { + ...fixedPlotSize, + table, + valueFormatters: { + _time: timeFormatter({timeZone, format: timeFormat}), + _value: val => + `${val.toFixed(2)}${ + valueAxisLabel ? ` ${valueAxisLabel}` : valueAxisLabel + }`, + }, + xScale, + yScale, + tickFont, + showAxes, + legendColorizeRows, + legendFont, + legendHide, + legendOpacity, + legendOrientationThreshold, + staticLegend: { + backgroundColor: staticLegendBackgroundColor, + border: staticLegendBorder, + colorizeRows: staticLegendColorizeRows, + font: staticLegendFont || legendFont, + heightRatio: staticLegendHeightRatio, + hide: staticLegendHide, + orientationThreshold: staticLegendOrientationThreshold, + renderEffect, + }, + layers: [ + { + type: 'line', + x, + y, + fill, + position, + interpolation, + colors, + lineWidth, + hoverDimension, + shadeBelow, + shadeBelowOpacity, + }, + ], + } + + return ( + + + + ) + })