Compare commits
14 Commits
60d1f82e09
...
b126858d8e
Author | SHA1 | Date | |
---|---|---|---|
|
b126858d8e | ||
|
7a8bbaa826 | ||
|
49bed04748 | ||
|
8573a5d372 | ||
|
b32884a31c | ||
|
a56d473148 | ||
|
8a55c73c83 | ||
|
4bcd84c358 | ||
|
4ba51e018d | ||
|
e90e88954a | ||
|
a980db505b | ||
|
44023fed29 | ||
|
bfd179c4aa | ||
|
b7a5c4a109 |
|
@ -16,9 +16,9 @@ impl ColorDifference for Cam16Jch<f32> {
|
|||
type Difference = HctDiffference;
|
||||
|
||||
fn difference(&self, other: &Self) -> Self::Difference {
|
||||
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
|
||||
let chroma = self.chroma - other.chroma;
|
||||
let lightness = self.lightness - other.lightness;
|
||||
let hue = other.hue.into_positive_degrees() - self.hue.into_positive_degrees();
|
||||
let chroma = other.chroma - self.chroma;
|
||||
let lightness = other.lightness - self.lightness;
|
||||
|
||||
HctDiffference {
|
||||
hue: Differ {
|
||||
|
@ -35,4 +35,38 @@ impl ColorDifference for Cam16Jch<f32> {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn difference_relative(&self, other: &Self) -> Self::Difference {
|
||||
let hue = if self.hue.into_positive_degrees() == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.hue.into_positive_degrees() - self.hue.into_positive_degrees())
|
||||
/ (360.0 - self.hue.into_positive_degrees())
|
||||
};
|
||||
let chroma = if self.chroma == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.chroma - self.chroma) / self.chroma
|
||||
};
|
||||
let lightness = if self.lightness == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.lightness - self.lightness) / (100.0 - self.lightness)
|
||||
};
|
||||
|
||||
HctDiffference {
|
||||
hue: Differ {
|
||||
delta: other.hue.into_positive_degrees() - self.hue.into_positive_degrees(),
|
||||
percent: hue,
|
||||
},
|
||||
chroma: Differ {
|
||||
delta: other.chroma - self.chroma,
|
||||
percent: chroma,
|
||||
},
|
||||
lightness: Differ {
|
||||
delta: other.lightness - self.lightness,
|
||||
percent: lightness,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ impl ColorDifference for Hsl {
|
|||
type Difference = HSLDifference;
|
||||
|
||||
fn difference(&self, other: &Self) -> Self::Difference {
|
||||
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
|
||||
let saturation = self.saturation - other.saturation;
|
||||
let lightness = self.lightness - other.lightness;
|
||||
let hue = other.hue.into_positive_degrees() - self.hue.into_positive_degrees();
|
||||
let saturation = other.saturation - self.saturation;
|
||||
let lightness = other.lightness - self.lightness;
|
||||
|
||||
HSLDifference {
|
||||
hue: Differ {
|
||||
|
@ -35,4 +35,38 @@ impl ColorDifference for Hsl {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn difference_relative(&self, other: &Self) -> Self::Difference {
|
||||
let hue = if self.hue.into_positive_degrees() == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.hue.into_positive_degrees() - self.hue.into_positive_degrees())
|
||||
/ (1.0 - self.hue.into_positive_degrees())
|
||||
};
|
||||
let saturation = if self.saturation == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.saturation - self.saturation) / (1.0 - self.saturation)
|
||||
};
|
||||
let lightness = if self.lightness == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.lightness - self.lightness) / (1.0 - self.lightness)
|
||||
};
|
||||
|
||||
HSLDifference {
|
||||
hue: Differ {
|
||||
delta: other.hue.into_positive_degrees() - self.hue.into_positive_degrees(),
|
||||
percent: hue,
|
||||
},
|
||||
saturation: Differ {
|
||||
delta: other.saturation - self.saturation,
|
||||
percent: saturation,
|
||||
},
|
||||
lightness: Differ {
|
||||
delta: other.lightness - self.lightness,
|
||||
percent: lightness,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,5 @@ pub trait ColorDifference {
|
|||
type Difference;
|
||||
|
||||
fn difference(&self, other: &Self) -> Self::Difference;
|
||||
fn difference_relative(&self, other: &Self) -> Self::Difference;
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ impl ColorDifference for Oklch {
|
|||
type Difference = OklchDifference;
|
||||
|
||||
fn difference(&self, other: &Self) -> Self::Difference {
|
||||
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
|
||||
let chroma = self.chroma - other.chroma;
|
||||
let lightness = self.l - other.l;
|
||||
let hue = other.hue.into_positive_degrees() - self.hue.into_positive_degrees();
|
||||
let chroma = other.chroma - self.chroma;
|
||||
let lightness = other.l - self.l;
|
||||
|
||||
OklchDifference {
|
||||
hue: Differ {
|
||||
|
@ -35,4 +35,38 @@ impl ColorDifference for Oklch {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn difference_relative(&self, other: &Self) -> Self::Difference {
|
||||
let hue = if self.hue.into_positive_degrees() == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.hue.into_positive_degrees() - self.hue.into_positive_degrees())
|
||||
/ (1.0 - self.hue.into_positive_degrees())
|
||||
};
|
||||
let chroma = if self.chroma == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.chroma - self.chroma) / self.chroma
|
||||
};
|
||||
let lightness = if self.l == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.l - self.l) / (1.0 - self.l)
|
||||
};
|
||||
|
||||
OklchDifference {
|
||||
hue: Differ {
|
||||
delta: other.hue.into_positive_degrees() - self.hue.into_positive_degrees(),
|
||||
percent: hue,
|
||||
},
|
||||
chroma: Differ {
|
||||
delta: other.chroma - self.chroma,
|
||||
percent: chroma,
|
||||
},
|
||||
lightness: Differ {
|
||||
delta: other.l - self.l,
|
||||
percent: lightness,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ impl ColorDifference for Srgb {
|
|||
type Difference = RGBDifference;
|
||||
|
||||
fn difference(&self, other: &Self) -> Self::Difference {
|
||||
let r = self.red - other.red;
|
||||
let g = self.green - other.green;
|
||||
let b = self.blue - other.blue;
|
||||
let r = other.red - self.red;
|
||||
let g = other.green - self.green;
|
||||
let b = other.blue - self.blue;
|
||||
|
||||
RGBDifference {
|
||||
r: Differ {
|
||||
|
@ -35,4 +35,37 @@ impl ColorDifference for Srgb {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn difference_relative(&self, other: &Self) -> Self::Difference {
|
||||
let r = if self.red == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.red - self.red) / (1.0 - self.red)
|
||||
};
|
||||
let g = if self.green == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.green - self.green) / (1.0 - self.green)
|
||||
};
|
||||
let b = if self.blue == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(other.blue - self.blue) / (1.0 - self.blue)
|
||||
};
|
||||
|
||||
RGBDifference {
|
||||
r: Differ {
|
||||
delta: other.red - self.red,
|
||||
percent: r,
|
||||
},
|
||||
g: Differ {
|
||||
delta: other.green - self.green,
|
||||
percent: g,
|
||||
},
|
||||
b: Differ {
|
||||
delta: other.blue - self.blue,
|
||||
percent: b,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -440,6 +440,20 @@ pub fn differ_in_rgb(
|
|||
Ok(srgb.difference(&other_srgb))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn relative_differ_in_rgb(
|
||||
color: &str,
|
||||
other: &str,
|
||||
) -> Result<color_differ::rgb::RGBDifference, errors::ColorError> {
|
||||
let srgb = Srgb::from_str(color)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
|
||||
.into_format::<f32>();
|
||||
let other_srgb = Srgb::from_str(other)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
|
||||
.into_format::<f32>();
|
||||
Ok(srgb.difference_relative(&other_srgb))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn differ_in_hsl(
|
||||
color: &str,
|
||||
|
@ -458,6 +472,24 @@ pub fn differ_in_hsl(
|
|||
Ok(hsl.difference(&other_hsl))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn relative_differ_in_hsl(
|
||||
color: &str,
|
||||
other: &str,
|
||||
) -> Result<color_differ::hsl::HSLDifference, errors::ColorError> {
|
||||
let hsl = Hsl::from_color(
|
||||
Srgb::from_str(color)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
|
||||
.into_format::<f32>(),
|
||||
);
|
||||
let other_hsl = Hsl::from_color(
|
||||
Srgb::from_str(other)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
|
||||
.into_format::<f32>(),
|
||||
);
|
||||
Ok(hsl.difference_relative(&other_hsl))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn differ_in_hct(
|
||||
color: &str,
|
||||
|
@ -480,6 +512,28 @@ pub fn differ_in_hct(
|
|||
Ok(hct.difference(&other_hct))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn relative_differ_in_hct(
|
||||
color: &str,
|
||||
other: &str,
|
||||
) -> Result<color_differ::cam16jch::HctDiffference, errors::ColorError> {
|
||||
let hct = Cam16Jch::from_xyz(
|
||||
Srgb::from_str(color)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
|
||||
.into_format::<f32>()
|
||||
.into_color(),
|
||||
Parameters::default_static_wp(40.0),
|
||||
);
|
||||
let other_hct = Cam16Jch::from_xyz(
|
||||
Srgb::from_str(other)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
|
||||
.into_format::<f32>()
|
||||
.into_color(),
|
||||
Parameters::default_static_wp(40.0),
|
||||
);
|
||||
Ok(hct.difference_relative(&other_hct))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn differ_in_oklch(
|
||||
color: &str,
|
||||
|
@ -498,6 +552,24 @@ pub fn differ_in_oklch(
|
|||
Ok(oklch.difference(&other_oklch))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn relative_differ_in_oklch(
|
||||
color: &str,
|
||||
other: &str,
|
||||
) -> Result<color_differ::oklch::OklchDifference, errors::ColorError> {
|
||||
let oklch = Oklch::from_color(
|
||||
Srgb::from_str(color)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
|
||||
.into_format::<f32>(),
|
||||
);
|
||||
let other_oklch = Oklch::from_color(
|
||||
Srgb::from_str(other)
|
||||
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
|
||||
.into_format::<f32>(),
|
||||
);
|
||||
Ok(oklch.difference_relative(&other_oklch))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn tint_scale(
|
||||
basic_color: &str,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { LightenDarken } from './pages/LightenDarken';
|
|||
import { MainLayout } from './pages/MainLayout';
|
||||
import { Mixer } from './pages/Mixer';
|
||||
import { NewScheme } from './pages/NewScheme';
|
||||
import { AutomaticPalette } from './pages/Palette';
|
||||
import { SchemeDetail } from './pages/SchemeDetail';
|
||||
import { SchemeNotFound } from './pages/SchemeNotFound';
|
||||
import { Schemes } from './pages/Schemes';
|
||||
|
@ -39,6 +40,7 @@ const routes = createBrowserRouter([
|
|||
{ path: 'tints-shades', element: <TintsShades /> },
|
||||
{ path: 'lighten-darken', element: <LightenDarken /> },
|
||||
{ path: 'mixer', element: <Mixer /> },
|
||||
{ path: 'palette', element: <AutomaticPalette /> },
|
||||
{ path: 'wacg', element: <WACGCheck /> },
|
||||
{ path: 'compare', element: <ColorCompare /> },
|
||||
{
|
||||
|
|
46
src/color_functions/color_module.d.ts
vendored
46
src/color_functions/color_module.d.ts
vendored
|
@ -31,9 +31,13 @@ export function tonal_darken_series(color: string, expand_amount: number, step:
|
|||
export function color_categories(): any;
|
||||
export function search_color_cards(tag: string, category?: string): any;
|
||||
export function differ_in_rgb(color: string, other: string): RGBDifference;
|
||||
export function relative_differ_in_rgb(color: string, other: string): RGBDifference;
|
||||
export function differ_in_hsl(color: string, other: string): HSLDifference;
|
||||
export function relative_differ_in_hsl(color: string, other: string): HSLDifference;
|
||||
export function differ_in_hct(color: string, other: string): HctDiffference;
|
||||
export function relative_differ_in_hct(color: string, other: string): HctDiffference;
|
||||
export function differ_in_oklch(color: string, other: string): OklchDifference;
|
||||
export function relative_differ_in_oklch(color: string, other: string): OklchDifference;
|
||||
export function tint_scale(basic_color: string, mixed_color: string): MixReversing;
|
||||
export function shade_scale(basic_color: string, mixed_color: string): MixReversing;
|
||||
export class Differ {
|
||||
|
@ -114,11 +118,20 @@ export interface InitOutput {
|
|||
readonly color_categories: () => [number, number, number];
|
||||
readonly search_color_cards: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly differ_in_rgb: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly relative_differ_in_rgb: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly differ_in_hsl: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly relative_differ_in_hsl: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly differ_in_hct: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly relative_differ_in_hct: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly differ_in_oklch: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly relative_differ_in_oklch: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly tint_scale: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly shade_scale: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
readonly __wbg_differ_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_differ_delta: (a: number) => number;
|
||||
readonly __wbg_set_differ_delta: (a: number, b: number) => void;
|
||||
readonly __wbg_get_differ_percent: (a: number) => number;
|
||||
readonly __wbg_set_differ_percent: (a: number, b: number) => void;
|
||||
readonly __wbg_mixreversing_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_mixreversing_r_factor: (a: number) => number;
|
||||
readonly __wbg_set_mixreversing_r_factor: (a: number, b: number) => void;
|
||||
|
@ -128,18 +141,6 @@ export interface InitOutput {
|
|||
readonly __wbg_set_mixreversing_b_factor: (a: number, b: number) => void;
|
||||
readonly __wbg_get_mixreversing_average: (a: number) => number;
|
||||
readonly __wbg_set_mixreversing_average: (a: number, b: number) => void;
|
||||
readonly __wbg_rgbdifference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_r: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_r: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_g: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_g: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_b: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_b: (a: number, b: number) => void;
|
||||
readonly __wbg_differ_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_differ_delta: (a: number) => number;
|
||||
readonly __wbg_set_differ_delta: (a: number, b: number) => void;
|
||||
readonly __wbg_get_differ_percent: (a: number) => number;
|
||||
readonly __wbg_set_differ_percent: (a: number, b: number) => void;
|
||||
readonly __wbg_oklchdifference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_oklchdifference_hue: (a: number) => number;
|
||||
readonly __wbg_set_oklchdifference_hue: (a: number, b: number) => void;
|
||||
|
@ -147,13 +148,13 @@ export interface InitOutput {
|
|||
readonly __wbg_set_oklchdifference_chroma: (a: number, b: number) => void;
|
||||
readonly __wbg_get_oklchdifference_lightness: (a: number) => number;
|
||||
readonly __wbg_set_oklchdifference_lightness: (a: number, b: number) => void;
|
||||
readonly __wbg_hctdiffference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_hue: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_hue: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_chroma: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_chroma: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_lightness: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_lightness: (a: number, b: number) => void;
|
||||
readonly __wbg_rgbdifference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_r: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_r: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_g: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_g: (a: number, b: number) => void;
|
||||
readonly __wbg_get_rgbdifference_b: (a: number) => number;
|
||||
readonly __wbg_set_rgbdifference_b: (a: number, b: number) => void;
|
||||
readonly __wbg_hsldifference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hsldifference_hue: (a: number) => number;
|
||||
readonly __wbg_set_hsldifference_hue: (a: number, b: number) => void;
|
||||
|
@ -161,6 +162,13 @@ export interface InitOutput {
|
|||
readonly __wbg_set_hsldifference_saturation: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hsldifference_lightness: (a: number) => number;
|
||||
readonly __wbg_set_hsldifference_lightness: (a: number, b: number) => void;
|
||||
readonly __wbg_hctdiffference_free: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_hue: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_hue: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_chroma: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_chroma: (a: number, b: number) => void;
|
||||
readonly __wbg_get_hctdiffference_lightness: (a: number) => number;
|
||||
readonly __wbg_set_hctdiffference_lightness: (a: number, b: number) => void;
|
||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
||||
|
|
|
@ -756,6 +756,23 @@ export function differ_in_rgb(color, other) {
|
|||
return RGBDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
* @returns {RGBDifference}
|
||||
*/
|
||||
export function relative_differ_in_rgb(color, other) {
|
||||
const ptr0 = passStringToWasm0(color, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(other, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.relative_differ_in_rgb(ptr0, len0, ptr1, len1);
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return RGBDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
|
@ -773,6 +790,23 @@ export function differ_in_hsl(color, other) {
|
|||
return HSLDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
* @returns {HSLDifference}
|
||||
*/
|
||||
export function relative_differ_in_hsl(color, other) {
|
||||
const ptr0 = passStringToWasm0(color, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(other, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.relative_differ_in_hsl(ptr0, len0, ptr1, len1);
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return HSLDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
|
@ -790,6 +824,23 @@ export function differ_in_hct(color, other) {
|
|||
return HctDiffference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
* @returns {HctDiffference}
|
||||
*/
|
||||
export function relative_differ_in_hct(color, other) {
|
||||
const ptr0 = passStringToWasm0(color, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(other, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.relative_differ_in_hct(ptr0, len0, ptr1, len1);
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return HctDiffference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
|
@ -807,6 +858,23 @@ export function differ_in_oklch(color, other) {
|
|||
return OklchDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @param {string} other
|
||||
* @returns {OklchDifference}
|
||||
*/
|
||||
export function relative_differ_in_oklch(color, other) {
|
||||
const ptr0 = passStringToWasm0(color, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(other, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.relative_differ_in_oklch(ptr0, len0, ptr1, len1);
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return OklchDifference.__wrap(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} basic_color
|
||||
* @param {string} mixed_color
|
||||
|
|
Binary file not shown.
42
src/color_functions/color_module_bg.wasm.d.ts
vendored
42
src/color_functions/color_module_bg.wasm.d.ts
vendored
|
@ -32,11 +32,20 @@ export const tonal_darken_series: (a: number, b: number, c: number, d: number) =
|
|||
export const color_categories: () => [number, number, number];
|
||||
export const search_color_cards: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const differ_in_rgb: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const relative_differ_in_rgb: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const differ_in_hsl: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const relative_differ_in_hsl: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const differ_in_hct: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const relative_differ_in_hct: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const differ_in_oklch: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const relative_differ_in_oklch: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const tint_scale: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const shade_scale: (a: number, b: number, c: number, d: number) => [number, number, number];
|
||||
export const __wbg_differ_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_differ_delta: (a: number) => number;
|
||||
export const __wbg_set_differ_delta: (a: number, b: number) => void;
|
||||
export const __wbg_get_differ_percent: (a: number) => number;
|
||||
export const __wbg_set_differ_percent: (a: number, b: number) => void;
|
||||
export const __wbg_mixreversing_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_mixreversing_r_factor: (a: number) => number;
|
||||
export const __wbg_set_mixreversing_r_factor: (a: number, b: number) => void;
|
||||
|
@ -46,18 +55,6 @@ export const __wbg_get_mixreversing_b_factor: (a: number) => number;
|
|||
export const __wbg_set_mixreversing_b_factor: (a: number, b: number) => void;
|
||||
export const __wbg_get_mixreversing_average: (a: number) => number;
|
||||
export const __wbg_set_mixreversing_average: (a: number, b: number) => void;
|
||||
export const __wbg_rgbdifference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_r: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_r: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_g: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_g: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_b: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_b: (a: number, b: number) => void;
|
||||
export const __wbg_differ_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_differ_delta: (a: number) => number;
|
||||
export const __wbg_set_differ_delta: (a: number, b: number) => void;
|
||||
export const __wbg_get_differ_percent: (a: number) => number;
|
||||
export const __wbg_set_differ_percent: (a: number, b: number) => void;
|
||||
export const __wbg_oklchdifference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_oklchdifference_hue: (a: number) => number;
|
||||
export const __wbg_set_oklchdifference_hue: (a: number, b: number) => void;
|
||||
|
@ -65,13 +62,13 @@ export const __wbg_get_oklchdifference_chroma: (a: number) => number;
|
|||
export const __wbg_set_oklchdifference_chroma: (a: number, b: number) => void;
|
||||
export const __wbg_get_oklchdifference_lightness: (a: number) => number;
|
||||
export const __wbg_set_oklchdifference_lightness: (a: number, b: number) => void;
|
||||
export const __wbg_hctdiffference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_hue: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_hue: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_chroma: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_chroma: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_lightness: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_lightness: (a: number, b: number) => void;
|
||||
export const __wbg_rgbdifference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_r: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_r: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_g: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_g: (a: number, b: number) => void;
|
||||
export const __wbg_get_rgbdifference_b: (a: number) => number;
|
||||
export const __wbg_set_rgbdifference_b: (a: number, b: number) => void;
|
||||
export const __wbg_hsldifference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_hsldifference_hue: (a: number) => number;
|
||||
export const __wbg_set_hsldifference_hue: (a: number, b: number) => void;
|
||||
|
@ -79,6 +76,13 @@ export const __wbg_get_hsldifference_saturation: (a: number) => number;
|
|||
export const __wbg_set_hsldifference_saturation: (a: number, b: number) => void;
|
||||
export const __wbg_get_hsldifference_lightness: (a: number) => number;
|
||||
export const __wbg_set_hsldifference_lightness: (a: number, b: number) => void;
|
||||
export const __wbg_hctdiffference_free: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_hue: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_hue: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_chroma: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_chroma: (a: number, b: number) => void;
|
||||
export const __wbg_get_hctdiffference_lightness: (a: number) => number;
|
||||
export const __wbg_set_hctdiffference_lightness: (a: number, b: number) => void;
|
||||
export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
export const __wbindgen_export_2: WebAssembly.Table;
|
||||
|
|
|
@ -384,6 +384,23 @@
|
|||
background: transparent;
|
||||
border-radius: var(--border-radius-xxs);
|
||||
}
|
||||
&[disabled] {
|
||||
cursor: not-allowed;
|
||||
&::-webkit-slider-thumb {
|
||||
background: oklch(from var(--color-primary-disabled) l c h / 70%);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&::-moz-range-thumb {
|
||||
background: oklch(from var(--color-primary-disabled) l c h / 70%);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&::-webkit-slider-runnable-track {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&::-moz-range-track {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
|
|
|
@ -5,12 +5,19 @@
|
|||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-xs);
|
||||
&.inline {
|
||||
flex-direction: row;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
label {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
font-size: var(--font-size-xs);
|
||||
.inline & {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import cx from 'clsx';
|
||||
import styles from './Labeled.module.css';
|
||||
|
||||
type LabeledProps = {
|
||||
label: string;
|
||||
inline?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export function Labeled({ label, children }: LabeledProps) {
|
||||
export function Labeled({ label, inline = false, children }: LabeledProps) {
|
||||
return (
|
||||
<div className={styles.labeled}>
|
||||
<div className={cx(styles.labeled, inline && styles.inline)}>
|
||||
<label>{label}</label>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -11,6 +11,7 @@ type LabeledPickerProps = {
|
|||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export function LabeledPicker({
|
||||
|
@ -21,6 +22,7 @@ export function LabeledPicker({
|
|||
min = 0,
|
||||
max = 100,
|
||||
step = 1,
|
||||
disabled = false,
|
||||
}: LabeledPickerProps) {
|
||||
const [pickerValue, setPickerValue] = useState(value ?? min);
|
||||
const handlePickerChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
@ -52,6 +54,7 @@ export function LabeledPicker({
|
|||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -152,7 +152,6 @@ export function ScrollArea({
|
|||
const [xScrollNeeded, setXScrollNeeded] = useState(false);
|
||||
const [yScrollNeeded, setYScrollNeeded] = useState(false);
|
||||
const handleWheel = (evt: WheelEvent) => {
|
||||
evt.preventDefault();
|
||||
const container = scrollContainerRef?.current;
|
||||
if (enableY && container) {
|
||||
const delta = evt.deltaY;
|
||||
|
|
|
@ -16,7 +16,7 @@ export function Switch({ checked = false, disabled = false, onChange }: SwitchPr
|
|||
setIsChecked((prev) => !prev);
|
||||
onChange?.(!isChecked);
|
||||
}
|
||||
}, [onChange, disabled]);
|
||||
}, [onChange, isChecked, disabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEqual(checked, isChecked)) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
margin-top: var(--spacing-s);
|
||||
}
|
||||
.element {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
|
|
@ -19,20 +19,28 @@ const defaultCompareResult: HctDiffference = {
|
|||
},
|
||||
};
|
||||
|
||||
export function HCTCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) {
|
||||
export function HCTCompare({
|
||||
basic = '000000',
|
||||
compare = '000000',
|
||||
mode = 'absolute',
|
||||
}: CompareMethodProps) {
|
||||
const { colorFn } = useColorFunction();
|
||||
const differ = useMemo(() => {
|
||||
if (!colorFn) {
|
||||
return defaultCompareResult;
|
||||
}
|
||||
try {
|
||||
const diff = colorFn.differ_in_hct(basic, compare);
|
||||
const diffFn = {
|
||||
absolute: colorFn.differ_in_hct,
|
||||
relative: colorFn.relative_differ_in_hct,
|
||||
};
|
||||
const diff = diffFn[mode](basic, compare);
|
||||
return diff;
|
||||
} catch (e) {
|
||||
console.error('[Compare in HCT]', e);
|
||||
}
|
||||
return defaultCompareResult;
|
||||
}, [basic, compare]);
|
||||
}, [basic, compare, mode]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -19,20 +19,28 @@ const defaultCompareResult: HSLDifference = {
|
|||
},
|
||||
};
|
||||
|
||||
export function HSLCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) {
|
||||
export function HSLCompare({
|
||||
basic = '000000',
|
||||
compare = '000000',
|
||||
mode = 'absolute',
|
||||
}: CompareMethodProps) {
|
||||
const { colorFn } = useColorFunction();
|
||||
const differ = useMemo(() => {
|
||||
if (!colorFn) {
|
||||
return defaultCompareResult;
|
||||
}
|
||||
try {
|
||||
const diff = colorFn.differ_in_hsl(basic, compare);
|
||||
const diffFn = {
|
||||
absolute: colorFn.differ_in_hsl,
|
||||
relative: colorFn.relative_differ_in_hsl,
|
||||
};
|
||||
const diff = diffFn[mode](basic, compare);
|
||||
return diff;
|
||||
} catch (e) {
|
||||
console.error('[Compare in HSL]', e);
|
||||
}
|
||||
return defaultCompareResult;
|
||||
}, [basic, compare]);
|
||||
}, [basic, compare, mode]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -19,20 +19,28 @@ const defaultCompareResult: OklchDifference = {
|
|||
},
|
||||
};
|
||||
|
||||
export function OklchCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) {
|
||||
export function OklchCompare({
|
||||
basic = '000000',
|
||||
compare = '000000',
|
||||
mode = 'absolute',
|
||||
}: CompareMethodProps) {
|
||||
const { colorFn } = useColorFunction();
|
||||
const differ = useMemo(() => {
|
||||
if (!colorFn) {
|
||||
return defaultCompareResult;
|
||||
}
|
||||
try {
|
||||
const diff = colorFn.differ_in_oklch(basic, compare);
|
||||
const diffFn = {
|
||||
absolute: colorFn.differ_in_oklch,
|
||||
relative: colorFn.relative_differ_in_oklch,
|
||||
};
|
||||
const diff = diffFn[mode](basic, compare);
|
||||
return diff;
|
||||
} catch (e) {
|
||||
console.error('[Compare in Oklch]', e);
|
||||
}
|
||||
return defaultCompareResult;
|
||||
}, [basic, compare]);
|
||||
}, [basic, compare, mode]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -19,14 +19,22 @@ const defaultCompareResult: RGBDifference = {
|
|||
},
|
||||
};
|
||||
|
||||
export function RGBCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) {
|
||||
export function RGBCompare({
|
||||
basic = '000000',
|
||||
compare = '000000',
|
||||
mode = 'absolute',
|
||||
}: CompareMethodProps) {
|
||||
const { colorFn } = useColorFunction();
|
||||
const differ = useMemo(() => {
|
||||
if (!colorFn) {
|
||||
return defaultCompareResult;
|
||||
}
|
||||
try {
|
||||
const diff = colorFn?.differ_in_rgb(basic, compare);
|
||||
const diffFn = {
|
||||
absolute: colorFn.differ_in_rgb,
|
||||
relative: colorFn.relative_differ_in_rgb,
|
||||
};
|
||||
const diff = diffFn[mode](basic, compare);
|
||||
return {
|
||||
r: {
|
||||
delta: Math.round(diff.r.delta * 255),
|
||||
|
@ -45,7 +53,7 @@ export function RGBCompare({ basic = '000000', compare = '000000' }: CompareMeth
|
|||
console.error('[Compare in RGB]', e);
|
||||
}
|
||||
return defaultCompareResult;
|
||||
}, [basic, compare]);
|
||||
}, [basic, compare, mode]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -46,7 +46,7 @@ export function ShadeScale({ basic = '000000', compare = '000000' }: CompareMeth
|
|||
</div>
|
||||
<div className={styles.elements}>
|
||||
<div className={styles.element}>
|
||||
<div className={cx(styles.element_name, styles.mean)}>F</div>
|
||||
<div className={cx(styles.element_name, styles.mean)}>Factor</div>
|
||||
<div className={styles.element_value}>{(mixFactors.average * 100).toFixed(2)}%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -46,7 +46,7 @@ export function TintScale({ basic = '000000', compare = '000000' }: CompareMetho
|
|||
</div>
|
||||
<div className={styles.elements}>
|
||||
<div className={styles.element}>
|
||||
<div className={cx(styles.element_name, styles.mean)}>F</div>
|
||||
<div className={cx(styles.element_name, styles.mean)}>Factor</div>
|
||||
<div className={styles.element_value}>{(mixFactors.average * 100).toFixed(2)}%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export type CompareMethodProps = {
|
||||
basic?: string;
|
||||
compare?: string;
|
||||
mode?: 'absolute' | 'relative';
|
||||
};
|
||||
|
|
|
@ -58,9 +58,9 @@ export function NavigationMenu() {
|
|||
</li>
|
||||
<li>
|
||||
<NavLink
|
||||
to="/chroma"
|
||||
to="/palette"
|
||||
className={({ isActive }) => cx(styles.nav_link, isActive && styles.active)}>
|
||||
Chromatography
|
||||
Auto Palette
|
||||
</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import cx from 'clsx';
|
||||
import { useState } from 'react';
|
||||
import { ColorPicker } from '../components/ColorPicker';
|
||||
import { HSegmentedControl } from '../components/HSegmentedControl';
|
||||
import { Labeled } from '../components/Labeled';
|
||||
import { ScrollArea } from '../components/ScrollArea';
|
||||
import { HCTCompare } from '../page-components/color-compare/HCTCompare';
|
||||
import { HSLCompare } from '../page-components/color-compare/HSLCompare';
|
||||
|
@ -13,6 +15,7 @@ import styles from './Compare.module.css';
|
|||
export function ColorCompare() {
|
||||
const [basicColor, setBasicColor] = useState('000000');
|
||||
const [compareColor, setCompareColor] = useState('000000');
|
||||
const [analysisMode, setMode] = useState<'relative' | 'absolute'>('relative');
|
||||
|
||||
return (
|
||||
<div className={cx('workspace', styles.compare_workspace)}>
|
||||
|
@ -34,10 +37,20 @@ export function ColorCompare() {
|
|||
</div>
|
||||
<div className={styles.compare_column}>
|
||||
<h5>Compare Result</h5>
|
||||
<RGBCompare basic={basicColor} compare={compareColor} />
|
||||
<HSLCompare basic={basicColor} compare={compareColor} />
|
||||
<HCTCompare basic={basicColor} compare={compareColor} />
|
||||
<OklchCompare basic={basicColor} compare={compareColor} />
|
||||
<Labeled label="Analysis Mode">
|
||||
<HSegmentedControl
|
||||
options={[
|
||||
{ label: 'Absolute', value: 'absolute' },
|
||||
{ label: 'Relative', value: 'relative' },
|
||||
]}
|
||||
value={analysisMode}
|
||||
onChange={setMode}
|
||||
/>
|
||||
</Labeled>
|
||||
<RGBCompare basic={basicColor} compare={compareColor} mode={analysisMode} />
|
||||
<HSLCompare basic={basicColor} compare={compareColor} mode={analysisMode} />
|
||||
<HCTCompare basic={basicColor} compare={compareColor} mode={analysisMode} />
|
||||
<OklchCompare basic={basicColor} compare={compareColor} mode={analysisMode} />
|
||||
<TintScale basic={basicColor} compare={compareColor} />
|
||||
<ShadeScale basic={basicColor} compare={compareColor} />
|
||||
</div>
|
||||
|
|
47
src/pages/Palette.module.css
Normal file
47
src/pages/Palette.module.css
Normal file
|
@ -0,0 +1,47 @@
|
|||
@layer pages {
|
||||
.palette_workspace {
|
||||
flex-direction: column;
|
||||
}
|
||||
.palette_section {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
.function_side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-m);
|
||||
font-size: var(--font-size-s);
|
||||
.mode_navigation {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
h5 {
|
||||
padding-block: var(--spacing-m);
|
||||
font-size: var(--font-size-m);
|
||||
}
|
||||
}
|
||||
.palette_content {
|
||||
flex: 1;
|
||||
padding: 0 var(--spacing-m);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-s);
|
||||
h5 {
|
||||
padding-block: var(--spacing-m);
|
||||
font-size: var(--font-size-m);
|
||||
}
|
||||
.color_value_mode {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--spacing-s);
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
}
|
||||
}
|
111
src/pages/Palette.tsx
Normal file
111
src/pages/Palette.tsx
Normal file
|
@ -0,0 +1,111 @@
|
|||
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 { currentPickedColor } from '../stores/colors';
|
||||
import styles from './Palette.module.css';
|
||||
|
||||
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<'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch'>('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={15}
|
||||
step={1}
|
||||
value={swatchAmount}
|
||||
onChange={(value) => setSwatchAmount(value)}
|
||||
/>
|
||||
<LabeledPicker
|
||||
title="Reference Bias"
|
||||
min={0}
|
||||
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.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' },
|
||||
]}
|
||||
valu={mode}
|
||||
onChange={setMode}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user