import React, { PureComponent, ChangeEvent } from 'react'; import { Threshold } from '../../types'; import { ColorPicker } from '..'; import { PanelOptionsGroup } from '..'; import { colors } from '../../utils'; import { ThemeContext } from '../../themes/ThemeContext'; import { getColorFromHexRgbOrName } from '../../utils/namedColorsPalette'; export interface Props { thresholds: Threshold[]; onChange: (thresholds: Threshold[]) => void; } interface State { thresholds: Threshold[]; } export class ThresholdsEditor extends PureComponent { constructor(props: Props) { super(props); const addDefaultThreshold = this.props.thresholds.length === 0; const thresholds: Threshold[] = addDefaultThreshold ? [{ index: 0, value: -Infinity, color: colors[0] }] : props.thresholds; this.state = { thresholds }; if (addDefaultThreshold) { this.onChange(); } } onAddThreshold = (index: number) => { const { thresholds } = this.state; const maxValue = 100; const minValue = 0; if (index === 0) { return; } const newThresholds = thresholds.map(threshold => { if (threshold.index >= index) { const index = threshold.index + 1; threshold = { ...threshold, index }; } return threshold; }); // Setting value to a value between the previous thresholds const beforeThreshold = newThresholds.filter(t => t.index === index - 1 && t.index !== 0)[0]; const afterThreshold = newThresholds.filter(t => t.index === index + 1 && t.index !== 0)[0]; const beforeThresholdValue = beforeThreshold !== undefined ? beforeThreshold.value : minValue; const afterThresholdValue = afterThreshold !== undefined ? afterThreshold.value : maxValue; const value = afterThresholdValue - (afterThresholdValue - beforeThresholdValue) / 2; // Set a color const color = colors.filter(c => !newThresholds.some(t => t.color === c))[1]; this.setState( { thresholds: this.sortThresholds([ ...newThresholds, { color, index, value: value as number, }, ]), }, () => this.onChange() ); }; onRemoveThreshold = (threshold: Threshold) => { if (threshold.index === 0) { return; } this.setState( prevState => { const newThresholds = prevState.thresholds.map(t => { if (t.index > threshold.index) { const index = t.index - 1; t = { ...t, index }; } return t; }); return { thresholds: newThresholds.filter(t => t !== threshold), }; }, () => this.onChange() ); }; onChangeThresholdValue = (event: ChangeEvent, threshold: Threshold) => { if (threshold.index === 0) { return; } const { thresholds } = this.state; const cleanValue = event.target.value.replace(/,/g, '.'); const parsedValue = parseFloat(cleanValue); const value = isNaN(parsedValue) ? '' : parsedValue; const newThresholds = thresholds.map(t => { if (t === threshold && t.index !== 0) { t = { ...t, value: value as number }; } return t; }); this.setState({ thresholds: newThresholds }); }; onChangeThresholdColor = (threshold: Threshold, color: string) => { const { thresholds } = this.state; const newThresholds = thresholds.map(t => { if (t === threshold) { t = { ...t, color: color }; } return t; }); this.setState( { thresholds: newThresholds, }, () => this.onChange() ); }; onBlur = () => { this.setState(prevState => { const sortThresholds = this.sortThresholds([...prevState.thresholds]); let index = 0; sortThresholds.forEach(t => { t.index = index++; }); return { thresholds: sortThresholds }; }); this.onChange(); }; onChange = () => { this.props.onChange(this.state.thresholds); }; sortThresholds = (thresholds: Threshold[]) => { return thresholds.sort((t1, t2) => { return t1.value - t2.value; }); }; renderInput = (threshold: Threshold) => { return (
{threshold.color && (
this.onChangeThresholdColor(threshold, color)} />
)}
{threshold.index === 0 && (
)} {threshold.index > 0 && ( <>
this.onChangeThresholdValue(event, threshold)} value={threshold.value} onBlur={this.onBlur} readOnly={threshold.index === 0} />
this.onRemoveThreshold(threshold)}>
)}
); }; render() { const { thresholds } = this.state; return ( {theme => { return (
{thresholds .slice(0) .reverse() .map((threshold, index) => { return (
this.onAddThreshold(threshold.index + 1)} >
{this.renderInput(threshold)}
); })}
); }} ); } }