82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
import cx from 'clsx';
|
|
import { useMemo, useState } from 'react';
|
|
import { useColorFunction } from '../ColorFunctionContext';
|
|
import { ColorPicker } from '../components/ColorPicker';
|
|
import { FlexColorStand } from '../components/FlexColorStand';
|
|
import { HSegmentedControl } from '../components/HSegmentedControl';
|
|
import { LabeledPicker } from '../components/LabeledPicker';
|
|
import { ScrollArea } from '../components/ScrollArea';
|
|
import styles from './Mixer.module.css';
|
|
|
|
type ColorModes = 'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch';
|
|
|
|
export function Mixer() {
|
|
const { colorFn } = useColorFunction();
|
|
const [basicColor, setBasicColor] = useState('000000');
|
|
const [mixColor, setMixColor] = useState('000000');
|
|
const [mixRatio, setMixRatio] = useState(0);
|
|
const [mode, setMode] = useState<ColorModes>('hex');
|
|
const mixedColor = useMemo(() => {
|
|
try {
|
|
if (!colorFn) {
|
|
return '000000';
|
|
}
|
|
const mixed = colorFn.mix(basicColor, mixColor, mixRatio / 100);
|
|
return mixed;
|
|
} catch (e) {
|
|
console.error('[Mix Color]', e);
|
|
}
|
|
return '000000';
|
|
}, [basicColor, mixColor, mixRatio]);
|
|
|
|
return (
|
|
<div className={cx('workspace', styles.mixer_workspace)}>
|
|
<header>
|
|
<h3>Color Mixer</h3>
|
|
<p>Make a new color by mixing two colors.</p>
|
|
</header>
|
|
<ScrollArea enableY>
|
|
<div className={styles.mixer_content}>
|
|
<div className={styles.mixer_column}>
|
|
<h5>Basic Color</h5>
|
|
<ColorPicker color={basicColor} onSelect={setBasicColor} />
|
|
</div>
|
|
<div className={styles.mixer_column}>
|
|
<h5>Mix Color</h5>
|
|
<ColorPicker color={mixColor} onSelect={setMixColor} />
|
|
<LabeledPicker
|
|
title="Mix Ratio"
|
|
value={mixRatio}
|
|
onChange={setMixRatio}
|
|
min={0}
|
|
max={100}
|
|
step={1}
|
|
unit="%"
|
|
/>
|
|
</div>
|
|
<div className={styles.mixer_column}>
|
|
<h5>Mix Result</h5>
|
|
<div className={styles.colors_booth}>
|
|
<FlexColorStand color={mixedColor} valueMode={mode} />
|
|
</div>
|
|
<div className={styles.color_value_mode}>
|
|
<label>Copy color value in</label>
|
|
<HSegmentedControl
|
|
options={[
|
|
{ label: 'HEX', value: 'hex' },
|
|
{ label: 'RGB', value: 'rgb' },
|
|
{ label: 'HSL', value: 'hsl' },
|
|
{ label: 'LAB', value: 'lab' },
|
|
{ label: 'OKLCH', value: 'oklch' },
|
|
]}
|
|
value={mode}
|
|
onChange={(v) => setMode(v as ColorModes)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ScrollArea>
|
|
</div>
|
|
);
|
|
}
|