storybook/stories/stylings/24_texture_multiple_series.story.tsx (138 lines of code) (raw):
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { boolean, color, number, button } from '@storybook/addon-knobs';
import React, { useState } from 'react';
import type { TexturedStyles } from '@elastic/charts';
import { Axis, Chart, CurveType, Position, Settings, TextureShape, SeriesType } from '@elastic/charts';
import { getRandomNumberGenerator, SeededDataGenerator, getRandomEntryFn } from '@elastic/charts/src/mocks/utils';
import type { ChartsStory } from '../../types';
import { useBaseTheme } from '../../use_base_theme';
import { customKnobs } from '../utils/knobs';
const group = {
random: 'Randomized parameters',
default: 'Default parameters',
};
const dg = new SeededDataGenerator();
const rng = getRandomNumberGenerator();
const getRandomEntry = getRandomEntryFn();
interface Random {
shape: boolean;
rotation: boolean;
shapeRotation: boolean;
size: boolean;
spacing: {
x: boolean;
y: boolean;
};
offset: {
x: boolean;
y: boolean;
};
}
const getDefaultTextureKnobs = (): TexturedStyles => ({
shape: customKnobs.fromEnum('Shape', TextureShape, TextureShape.Circle, {
group: group.default,
}),
strokeWidth: number('Stroke width', 1, { min: 0, max: 10, step: 0.5 }, group.default),
rotation: number('Rotation (degrees)', 45, { min: -365, max: 365 }, group.default),
shapeRotation: number('Shape rotation (degrees)', 0, { min: -365, max: 365 }, group.default),
size: number('Shape size', 20, { min: 0 }, group.default),
opacity: number('Opacity', 1, { min: 0, max: 1, step: 0.1 }, group.default),
spacing: {
x: number('Shape spacing - x', 10, { min: 0 }, group.default),
y: number('Shape spacing - y', 10, { min: 0 }, group.default),
},
offset: {
x: number('Pattern offset - x', 0, {}, group.default),
y: number('Pattern offset - y', 0, {}, group.default),
global: true,
},
});
const getRandomKnobs = (): Random => ({
shape: boolean('Shape', true, group.random),
rotation: boolean('Rotation', false, group.random),
shapeRotation: boolean('Shape rotation', false, group.random),
size: boolean('Size', true, group.random),
spacing: {
x: boolean('X spacing', false, group.random),
y: boolean('Y spacing', false, group.random),
},
offset: {
x: boolean('X offset', false, group.random),
y: boolean('Y offset', false, group.random),
},
});
const getTexture = (randomize: Random): Partial<TexturedStyles> => ({
shape: randomize.shape ? getRandomEntry(TextureShape) : undefined,
rotation: randomize.rotation ? rng(0, 365) : undefined,
shapeRotation: randomize.shapeRotation ? rng(0, 365) : undefined,
size: randomize.size ? rng(5, 30) : undefined,
spacing: {
x: randomize.spacing.x ? rng(0, 30) : undefined,
y: randomize.spacing.y ? rng(0, 30) : undefined,
},
offset: {
x: randomize.offset.x ? rng(0, 30) : undefined,
y: randomize.offset.y ? rng(0, 30) : undefined,
},
});
const data = new Array(10).fill(0).map(() => dg.generateBasicSeries(10, 10));
export const Example: ChartsStory = (_, { title, description }) => {
const [count, setCount] = useState(0);
button('Randomize', () => setCount((i) => i + 1), group.random);
const n = number('Total series', 4, { min: 0, max: 10, step: 1 }) ?? 2;
const showLegend = boolean('Show legend', false);
const showFill = boolean('Show series fill', false);
const chartColor = color('Chart color', 'rgba(0,0,0,1)');
const random = getRandomKnobs();
const [Series] = customKnobs.enum.xySeries('Series type', 'area', {
exclude: [SeriesType.Bubble, SeriesType.Line],
});
const texture = getDefaultTextureKnobs();
return (
<Chart title={title} description={description} data-count={count}>
<Settings
showLegend={showLegend}
theme={{
areaSeriesStyle: {
area: {
texture,
fill: showFill ? undefined : 'transparent',
},
},
barSeriesStyle: {
rect: {
texture,
fill: showFill ? undefined : 'transparent',
},
rectBorder: {
visible: true,
strokeWidth: 2,
},
},
}}
baseTheme={useBaseTheme()}
/>
<Axis id="bottom" position={Position.Bottom} />
<Axis id="left" position={Position.Left} />
{new Array(n).fill(0).map((v, i) => (
<Series
key={i}
id={`series-${i}`}
areaSeriesStyle={{
area: {
texture: getTexture(random),
},
}}
barSeriesStyle={{
rect: {
texture: getTexture(random),
},
}}
xAccessor="x"
yAccessors={['y']}
color={chartColor}
stackAccessors={['yes']}
data={data[i]}
curve={CurveType.CURVE_MONOTONE_X}
/>
))}
</Chart>
);
};