126 lines
4.4 KiB
TypeScript
126 lines
4.4 KiB
TypeScript
import cx from 'clsx';
|
|
import { useAtom } from 'jotai';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
import { ColorPicker } from '../components/ColorPicker';
|
|
import { HSegmentedControl } from '../components/HSegmentedControl';
|
|
import { Labeled } from '../components/Labeled';
|
|
import { LabeledPicker } from '../components/LabeledPicker';
|
|
import { ScrollArea } from '../components/ScrollArea';
|
|
import { Switch } from '../components/Switch';
|
|
import { PaletteColors } from '../page-components/auto-palette/PaletteColors';
|
|
import { currentPickedColor } from '../stores/colors';
|
|
import styles from './Palette.module.css';
|
|
|
|
type ColorModes = 'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch';
|
|
|
|
export function AutomaticPalette() {
|
|
const [selectedColor, setSelectedColor] = useAtom(currentPickedColor);
|
|
const [useReferenceColor, setUseReferenceColor] = useState(false);
|
|
const [swatchAmount, setSwatchAmount] = useState(5);
|
|
const maxBias = useMemo(
|
|
() => (swatchAmount > 3 ? Math.floor(swatchAmount / 2) - 1 : 0),
|
|
[swatchAmount],
|
|
);
|
|
const [referenceBias, setReferenceBias] = useState(0);
|
|
const [minLightness, setMinLightness] = useState(10);
|
|
const [maxLightness, setMaxLightness] = useState(90);
|
|
const [mode, setMode] = useState<ColorModes>('hex');
|
|
|
|
useEffect(() => {
|
|
if (useReferenceColor) {
|
|
setReferenceBias(0);
|
|
}
|
|
}, [swatchAmount, useReferenceColor]);
|
|
|
|
return (
|
|
<div className={cx('workspace', styles.palette_workspace)}>
|
|
<header>
|
|
<h3>Automatic Palette</h3>
|
|
<p>
|
|
Automatically generate a color palette suitable for UI color matching according to the
|
|
given color algorithm.
|
|
</p>
|
|
</header>
|
|
<ScrollArea enableY>
|
|
<section className={styles.palette_section}>
|
|
<aside className={styles.function_side}>
|
|
<div>
|
|
<h5>Reference Color</h5>
|
|
<ColorPicker color={selectedColor} onSelect={(color) => setSelectedColor(color)} />
|
|
</div>
|
|
<div>
|
|
<h5>Palette Setting</h5>
|
|
<Labeled label="Use Reference Color" inline>
|
|
<Switch checked={useReferenceColor} onChange={setUseReferenceColor} />
|
|
</Labeled>
|
|
<LabeledPicker
|
|
title="Swatch Amount"
|
|
min={3}
|
|
max={12}
|
|
step={1}
|
|
value={swatchAmount}
|
|
onChange={(value) => setSwatchAmount(value)}
|
|
/>
|
|
<LabeledPicker
|
|
title="Reference Bias"
|
|
min={-maxBias}
|
|
max={maxBias}
|
|
step={1}
|
|
value={referenceBias}
|
|
onChange={setReferenceBias}
|
|
disabled={!useReferenceColor || maxBias < 2}
|
|
/>
|
|
<LabeledPicker
|
|
title="Min Lightness"
|
|
min={0}
|
|
max={100}
|
|
step={1}
|
|
value={minLightness}
|
|
onChange={setMinLightness}
|
|
unit="%"
|
|
/>
|
|
<LabeledPicker
|
|
title="Max Lightness"
|
|
min={0}
|
|
max={100}
|
|
step={1}
|
|
value={maxLightness}
|
|
onChange={setMaxLightness}
|
|
unit="%"
|
|
/>
|
|
</div>
|
|
</aside>
|
|
<div className={styles.palette_content}>
|
|
<h5>Generated Palette</h5>
|
|
<div className={styles.colors_booth}>
|
|
<PaletteColors
|
|
color={selectedColor}
|
|
swatchAmount={swatchAmount}
|
|
min={minLightness / 100}
|
|
max={maxLightness / 100}
|
|
useReference={useReferenceColor}
|
|
referenceBias={referenceBias}
|
|
copyMode={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>
|
|
</section>
|
|
</ScrollArea>
|
|
</div>
|
|
);
|
|
}
|