import React, { useEffect, useState } from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; import LinePlot, { LinePlotProps } from '../../plots/LinePlot'; import { FacetedData, LinePlotData } from '../../types/plots'; import FacetedLinePlot from '../../plots/facetedPlots/FacetedLinePlot'; import AxisRangeControl from '../../components/plotControls/AxisRangeControl'; import { NumberRange, NumberOrDateRange, NumberOrTimeDelta, TimeDelta, } from '../../types/general'; import { Toggle } from '@veupathdb/coreui'; import { LinePlotDataSeries } from '../../types/plots'; export default { title: 'Plots/LinePlot', component: LinePlot, } as Meta; const modeValue: LinePlotDataSeries['mode'] = 'lines+markers'; const dataSet = { series: [ { x: [0, 2, 5, 8, 12], y: [4, 8, 3, 12, 11], name: 'Cats', }, { x: [0, 2, 5, 8, 12], y: [6, 11, 4, 10, 13], name: 'Dogs', }, ], }; const errorBarData = { series: [ { ...dataSet.series[0], yErrorBarUpper: [5, 9, 5, 14, 12.5], yErrorBarLower: [3, 6, 1, 10, 9.5], binLabel: ['[0,2)', '[2,5)', '[5,8)', '[8,12)', '[12,15)'], sampleSize: [5, 60, 43, 22, 11, 99], }, { ...dataSet.series[1], yErrorBarUpper: [7, 12, 6, 12, 14.5], yErrorBarLower: [5, 10, 2, 8, 11.5], binLabel: ['[0,2)', '[2,5)', '[5,8)', '[8,12)', '[12,15)'], sampleSize: [11, 22, 33, 44, 55, 66], }, ], }; const markerTooltipData = { series: [ { ...dataSet.series[0], extraTooltipText: ['n: 1', 'n: 2', 'n: 3', 'n: 4', 'n: 5'], mode: modeValue, }, { x: [0, 2, 5, 8, 12], y: [6, 8, 4, 10, 11], name: 'Dogs', extraTooltipText: ['n: 5', 'n: 4', 'n: 3', 'n: 2', 'n: 1'], mode: modeValue, }, { x: [0, 2, 5, 8, 12], y: [12, 10, 6, 1, 11], name: 'Turtles', extraTooltipText: ['n: 3', 'n: 6', 'n: 9', 'n: 12', 'n: 15'], mode: modeValue, }, ], }; const Template: Story = (args) => ; export const Basic = Template.bind({}); Basic.args = { data: dataSet, dependentAxisLabel: 'Awesomeness', independentAxisLabel: 'Age', legendTitle: 'Animal', title: 'Awesomeness of animals', }; export const ErrorBars = Template.bind({}); ErrorBars.args = { data: errorBarData, dependentAxisLabel: 'Awesomeness with error bars', independentAxisLabel: 'Age', legendTitle: 'Animal', title: 'Awesomeness of animals', }; export const EmptyData = Template.bind({}); EmptyData.args = { dependentAxisLabel: 'Dependent axis label', independentAxisLabel: 'Independent axis label', }; export const EmptyDataLoading = Template.bind({}); EmptyDataLoading.args = { dependentAxisLabel: 'Dependent axis label', independentAxisLabel: 'Independent axis label', showSpinner: true, }; export const NoDataOverlay = Template.bind({}); NoDataOverlay.args = { dependentAxisLabel: 'Dependent axis label', independentAxisLabel: 'Independent axis label', showNoDataOverlay: true, title: 'Awesomeness of animals', }; export const MarkerTooltips = Template.bind({}); MarkerTooltips.args = { data: markerTooltipData, dependentAxisLabel: 'Awesomeness', independentAxisLabel: 'Age', legendTitle: 'Animal', title: 'Awesomeness of animals', interactive: true, }; /** * FACETING */ const facetedData: FacetedData = { facets: [ { label: 'indoors', data: dataSet, }, { label: 'outdoors', data: dataSet, }, { label: 'space', data: dataSet, }, { label: 'volcano', data: dataSet, }, { label: 'underwater', data: dataSet, }, { label: 'imaginary', }, { label: 'No data', }, ], }; interface FacetedStoryProps { data: FacetedData; componentProps: LinePlotProps; modalComponentProps: LinePlotProps; } const FacetedTemplate: Story = ({ data, componentProps, modalComponentProps, }) => ( ); export const Faceted = FacetedTemplate.bind({}); Faceted.args = { data: facetedData, componentProps: { title: 'indoor and outdoor pets', containerStyles: { width: 300, height: 300, border: '1px solid #dadada', }, }, modalComponentProps: { containerStyles: { width: '85%', height: '100%', margin: 'auto', }, }, }; // testing log scale const dataSetLog = { series: [ { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], y: [33, 36, 35, 37, 35, 34, 35, 36, 33, 37, 35], name: 'data', }, ], }; const TemplateWithSelectedRangeControls: Story> = ( args ) => { const [dependentAxisRange, setDependentAxisRange] = useState< NumberOrDateRange | undefined >({ min: 1, max: 80 }); const [dependentAxisLogScale, setDependentAxisLogScale] = useState< boolean | undefined >(false); const handleDependentAxisRangeChange = async ( newRange?: NumberOrDateRange ) => { setDependentAxisRange(newRange); }; const onDependentAxisLogScaleChange = async (value?: boolean) => { setDependentAxisLogScale(value); }; return (
); }; export const LogScale = TemplateWithSelectedRangeControls.bind({}); LogScale.args = { containerStyles: { height: '450px', width: '750px', }, }; // testing svg text (tooltip) for a dependent axis label with html tags export const YAxisLabelWithHtml: Story> = ( args ) => { return ( Arithmetic mean:
Plasmodium asexual stages, by microscopy result' } /> ); }; YAxisLabelWithHtml.args = { containerStyles: { height: '450px', width: '750px', }, }; // test data for dateDataFormat const dateData = { series: [ { x: ['2017-01-01', '2018-01-01', '2019-01-01'], y: [0.5285, 0.5058, 0.4205], binLabel: [ '2017-01-01 - 2018-01-01', '2018-01-01 - 2019-01-01', '2019-01-01 - 2020-01-01', ], yErrorBarUpper: [0.5399, 0.5158, 0.4364], yErrorBarLower: [0.517, 0.4959, 0.4046], extraTooltipText: ['n: 3880/7342', 'n: 4932/9750', 'n: 1556/3700'], name: 'Data', mode: 'lines+markers', opacity: 0.7, marker: { color: 'rgb(136,34,85)', symbol: 'circle', }, line: { color: 'rgb(136,34,85)', shape: 'linear', }, }, ], binWidthSlider: { valueType: 'date', binWidth: { value: 1, unit: 'year', }, binWidthRange: { min: 1, max: 2, unit: 'year', }, binWidthStep: 1, }, }; // testing date data format, especially year export const dateDataFormat: Story = (args: any) => { return ( Arithmetic mean:
Plasmodium asexual stages, by microscopy result' } interactive={true} independentValueType={'date'} {...args} /> ); }; dateDataFormat.args = { containerStyles: { height: '450px', width: '750px', }, };