Compare commits
9 Commits
3f2e655b1c
...
0bccda2c01
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bccda2c01 | ||
|
|
a0d02dd8a2 | ||
|
|
ff858ccbcd | ||
|
|
27f6d09ade | ||
|
|
d79a014916 | ||
|
|
b7ef02e7c3 | ||
|
|
b20fd30787 | ||
|
|
083c3d87a9 | ||
|
|
a25d1b03dd |
5
color-module/.cargo/config.toml
Normal file
5
color-module/.cargo/config.toml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[build]
|
||||||
|
rustflags = ["--cfg", "getrandom_backend=\"wasm_js\""]
|
||||||
|
|
||||||
|
[target.wasm32-unknown-unknown]
|
||||||
|
rustflags = ["--cfg", "getrandom_backend=\"wasm_js\""]
|
||||||
@@ -10,7 +10,7 @@ crate-type = ["cdylib"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
color-name = "1.1.0"
|
color-name = "1.1.0"
|
||||||
enum-iterator = "2.1.0"
|
enum-iterator = "2.1.0"
|
||||||
getrandom = { version = "0.3.3", features = ["wasm_js"] }
|
getrandom = { version = "0.3.4", features = ["wasm_js"] }
|
||||||
internment = { version = "0.8.6", features = ["arc"] }
|
internment = { version = "0.8.6", features = ["arc"] }
|
||||||
linked-hash-map = { version = "0.5.6", features = ["serde", "serde_impl"] }
|
linked-hash-map = { version = "0.5.6", features = ["serde", "serde_impl"] }
|
||||||
linked_hash_set = { version = "0.1.5", features = ["serde"] }
|
linked_hash_set = { version = "0.1.5", features = ["serde"] }
|
||||||
@@ -22,8 +22,12 @@ serde_repr = "0.1.20"
|
|||||||
strum = { version = "0.27.1", features = ["derive", "strum_macros"] }
|
strum = { version = "0.27.1", features = ["derive", "strum_macros"] }
|
||||||
strum_macros = "0.27.1"
|
strum_macros = "0.27.1"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
wasm-bindgen = { version = "0.2.99", features = ["serde", "serde_json", "serde-serialize"] }
|
wasm-bindgen = { version = "0.2.99", features = [
|
||||||
web-sys = {version = "0.3.77", features = ["console", "Window"]}
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde-serialize",
|
||||||
|
] }
|
||||||
|
web-sys = { version = "0.3.77", features = ["console", "Window"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3.49"
|
wasm-bindgen-test = "0.3.49"
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack build --release --target web -d ../color_functions
|
wasm-pack build --release --target web -d ../color_functions
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use baseline::Baseline;
|
|||||||
use linked_hash_set::LinkedHashSet;
|
use linked_hash_set::LinkedHashSet;
|
||||||
use palette::FromColor;
|
use palette::FromColor;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
use wasm_bindgen::{JsValue, prelude::wasm_bindgen};
|
||||||
|
|
||||||
use crate::{errors, parse_option_to_oklch, parse_to_oklch};
|
use crate::{errors, parse_option_to_oklch, parse_to_oklch};
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ mod neutral_swatch;
|
|||||||
mod scheme_setting;
|
mod scheme_setting;
|
||||||
|
|
||||||
pub use neutral_swatch::NeutralSwatch;
|
pub use neutral_swatch::NeutralSwatch;
|
||||||
pub use scheme_setting::{ColorExpand, ColorShifting, SchemeSetting, WACGSetting};
|
pub use scheme_setting::{ColorExpand, ColorShifting, SchemeSelect, SchemeSetting, WACGSetting};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct QScheme {
|
pub struct QScheme {
|
||||||
@@ -221,6 +221,20 @@ pub fn q_scheme_wacg_settings() -> Result<JsValue, String> {
|
|||||||
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
|
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn q_scheme_select_options() -> Result<JsValue, String> {
|
||||||
|
let options = enum_iterator::all::<SchemeSelect>()
|
||||||
|
.map(|option| {
|
||||||
|
serde_json::json!({
|
||||||
|
"label": option.label(),
|
||||||
|
"value": option as u8,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
serde_wasm_bindgen::to_value(&options).map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn q_scheme_default_settings() -> SchemeSetting {
|
pub fn q_scheme_default_settings() -> SchemeSetting {
|
||||||
SchemeSetting::default()
|
SchemeSetting::default()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use palette::Oklch;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
use wasm_bindgen::{prelude::wasm_bindgen, JsError, JsValue};
|
use wasm_bindgen::{JsError, JsValue, prelude::wasm_bindgen};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@@ -103,6 +103,7 @@ pub struct SchemeSetting {
|
|||||||
pub dark_convert: ColorShifting,
|
pub dark_convert: ColorShifting,
|
||||||
pub expand_method: ColorExpand,
|
pub expand_method: ColorExpand,
|
||||||
pub wacg_follows: WACGSetting,
|
pub wacg_follows: WACGSetting,
|
||||||
|
pub scheme_select: SchemeSelect,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Display, Sequence, Serialize_repr, Deserialize_repr)]
|
#[derive(Debug, Clone, Copy, Display, Sequence, Serialize_repr, Deserialize_repr)]
|
||||||
@@ -142,6 +143,33 @@ pub enum WACGSetting {
|
|||||||
HighContrast,
|
HighContrast,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Display, Sequence, Serialize_repr, Deserialize_repr)]
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum SchemeSelect {
|
||||||
|
Both,
|
||||||
|
Light,
|
||||||
|
Dark,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SchemeSelect {
|
||||||
|
pub fn label(&self) -> String {
|
||||||
|
match self {
|
||||||
|
SchemeSelect::Both => "Both".to_string(),
|
||||||
|
SchemeSelect::Light => "Light".to_string(),
|
||||||
|
SchemeSelect::Dark => "Dark".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn includes_light(&self) -> bool {
|
||||||
|
matches!(self, SchemeSelect::Both | SchemeSelect::Light)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn includes_dark(&self) -> bool {
|
||||||
|
matches!(self, SchemeSelect::Both | SchemeSelect::Dark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WACGSetting {
|
impl WACGSetting {
|
||||||
pub fn label(&self) -> String {
|
pub fn label(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
@@ -178,6 +206,7 @@ impl Default for SchemeSetting {
|
|||||||
},
|
},
|
||||||
expand_method: ColorExpand::AnalogousAndComplementary,
|
expand_method: ColorExpand::AnalogousAndComplementary,
|
||||||
wacg_follows: WACGSetting::AutomaticAAA,
|
wacg_follows: WACGSetting::AutomaticAAA,
|
||||||
|
scheme_select: SchemeSelect::Both,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,6 +222,7 @@ impl SchemeSetting {
|
|||||||
dark_convert: ColorShifting,
|
dark_convert: ColorShifting,
|
||||||
expand_method: ColorExpand,
|
expand_method: ColorExpand,
|
||||||
wacg_follows: WACGSetting,
|
wacg_follows: WACGSetting,
|
||||||
|
scheme_select: SchemeSelect,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SchemeSetting {
|
SchemeSetting {
|
||||||
hover,
|
hover,
|
||||||
@@ -202,6 +232,7 @@ impl SchemeSetting {
|
|||||||
dark_convert,
|
dark_convert,
|
||||||
expand_method,
|
expand_method,
|
||||||
wacg_follows,
|
wacg_follows,
|
||||||
|
scheme_select,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ pub struct Baseline {
|
|||||||
pub accent: Option<ColorUnit>,
|
pub accent: Option<ColorUnit>,
|
||||||
pub neutral: ColorSet,
|
pub neutral: ColorSet,
|
||||||
pub neutral_variant: ColorSet,
|
pub neutral_variant: ColorSet,
|
||||||
pub surface: ColorSet,
|
pub surface: [ColorSet; 6],
|
||||||
pub surface_variant: ColorSet,
|
|
||||||
#[serde(serialize_with = "crate::schemes::q_style_2::swatch::serialize_neutral_swatch")]
|
#[serde(serialize_with = "crate::schemes::q_style_2::swatch::serialize_neutral_swatch")]
|
||||||
pub neutral_swatch: Arc<NeutralSwatch>,
|
pub neutral_swatch: Arc<NeutralSwatch>,
|
||||||
pub danger: ColorUnit,
|
pub danger: ColorUnit,
|
||||||
@@ -121,6 +120,10 @@ pub struct Baseline {
|
|||||||
pub outline: Oklch,
|
pub outline: Oklch,
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
pub outline_variant: Oklch,
|
pub outline_variant: Oklch,
|
||||||
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
|
pub foreground: Oklch,
|
||||||
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
|
pub background: Oklch,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub neutral_lightness: f32,
|
pub neutral_lightness: f32,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
@@ -214,8 +217,6 @@ impl Baseline {
|
|||||||
|
|
||||||
let neutral_color = neutral_swatch.get(if is_dark { 0.35 } else { 0.65 });
|
let neutral_color = neutral_swatch.get(if is_dark { 0.35 } else { 0.65 });
|
||||||
let neutral_variant_color = neutral_swatch.get(if is_dark { 0.45 } else { 0.55 });
|
let neutral_variant_color = neutral_swatch.get(if is_dark { 0.45 } else { 0.55 });
|
||||||
let surface_color = neutral_swatch.get(if is_dark { 0.10 } else { 0.98 });
|
|
||||||
let surface_variant_color = neutral_swatch.get(if is_dark { 0.20 } else { 0.85 });
|
|
||||||
|
|
||||||
let neutral_set = ColorSet::new(
|
let neutral_set = ColorSet::new(
|
||||||
&neutral_color,
|
&neutral_color,
|
||||||
@@ -229,18 +230,66 @@ impl Baseline {
|
|||||||
reference_lightness,
|
reference_lightness,
|
||||||
settings,
|
settings,
|
||||||
);
|
);
|
||||||
let surface_set = ColorSet::new(
|
|
||||||
&surface_color,
|
// Calculate surface array
|
||||||
&neutral_swatch,
|
// 0-2: neutral_darkest to neutral_color (equally spaced)
|
||||||
reference_lightness,
|
// 3-5: neutral_color to neutral_lightest (equally spaced)
|
||||||
settings,
|
let neutral_darkest_percent = 0.0;
|
||||||
|
let neutral_color_percent = if is_dark { 0.35 } else { 0.65 };
|
||||||
|
let neutral_lightest_percent = 1.0;
|
||||||
|
|
||||||
|
let surface_0_color = neutral_swatch.get(
|
||||||
|
neutral_darkest_percent + (neutral_color_percent - neutral_darkest_percent) * 0.33,
|
||||||
);
|
);
|
||||||
let surface_variant_set = ColorSet::new(
|
let surface_1_color = neutral_swatch.get(
|
||||||
&surface_variant_color,
|
neutral_darkest_percent + (neutral_color_percent - neutral_darkest_percent) * 0.67,
|
||||||
&neutral_swatch,
|
|
||||||
reference_lightness,
|
|
||||||
settings,
|
|
||||||
);
|
);
|
||||||
|
let surface_2_color = neutral_swatch.get(neutral_color_percent);
|
||||||
|
|
||||||
|
let surface_3_color = neutral_swatch
|
||||||
|
.get(neutral_color_percent + (neutral_lightest_percent - neutral_color_percent) * 0.33);
|
||||||
|
let surface_4_color = neutral_swatch
|
||||||
|
.get(neutral_color_percent + (neutral_lightest_percent - neutral_color_percent) * 0.67);
|
||||||
|
let surface_5_color = neutral_swatch.get(neutral_lightest_percent);
|
||||||
|
|
||||||
|
let surface_array = [
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_0_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_1_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_2_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_3_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_4_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
ColorSet::new(
|
||||||
|
&surface_5_color,
|
||||||
|
&neutral_swatch,
|
||||||
|
reference_lightness,
|
||||||
|
settings,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
let primary_unit = ColorUnit::new(primary, &neutral_swatch, reference_lightness, settings);
|
let primary_unit = ColorUnit::new(primary, &neutral_swatch, reference_lightness, settings);
|
||||||
let secondary_unit = final_secondary
|
let secondary_unit = final_secondary
|
||||||
@@ -255,6 +304,19 @@ impl Baseline {
|
|||||||
let warn_unit = ColorUnit::new(warn, &neutral_swatch, reference_lightness, settings);
|
let warn_unit = ColorUnit::new(warn, &neutral_swatch, reference_lightness, settings);
|
||||||
let info_unit = ColorUnit::new(info, &neutral_swatch, reference_lightness, settings);
|
let info_unit = ColorUnit::new(info, &neutral_swatch, reference_lightness, settings);
|
||||||
|
|
||||||
|
// Initialize foreground and background
|
||||||
|
let (foreground, background) = if is_dark {
|
||||||
|
// Dark mode: foreground = neutral_lightest, background = neutral_darkest with +10% lightness
|
||||||
|
let background_darkest = Oklch {
|
||||||
|
l: (neutral_darkest.l * 1.2).min(1.0),
|
||||||
|
..*neutral_darkest
|
||||||
|
};
|
||||||
|
(*neutral_lightest, background_darkest)
|
||||||
|
} else {
|
||||||
|
// Light mode: foreground = neutral_darkest, background = neutral_lightest
|
||||||
|
(*neutral_darkest, *neutral_lightest)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
primary: primary_unit,
|
primary: primary_unit,
|
||||||
secondary: secondary_unit,
|
secondary: secondary_unit,
|
||||||
@@ -262,8 +324,7 @@ impl Baseline {
|
|||||||
accent: accent_unit,
|
accent: accent_unit,
|
||||||
neutral: neutral_set,
|
neutral: neutral_set,
|
||||||
neutral_variant: neutral_variant_set,
|
neutral_variant: neutral_variant_set,
|
||||||
surface: surface_set,
|
surface: surface_array,
|
||||||
surface_variant: surface_variant_set,
|
|
||||||
neutral_swatch,
|
neutral_swatch,
|
||||||
danger: danger_unit,
|
danger: danger_unit,
|
||||||
success: success_unit,
|
success: success_unit,
|
||||||
@@ -274,6 +335,8 @@ impl Baseline {
|
|||||||
overlay: overlay_color,
|
overlay: overlay_color,
|
||||||
outline: outline_color,
|
outline: outline_color,
|
||||||
outline_variant: outline_variant_color,
|
outline_variant: outline_variant_color,
|
||||||
|
foreground,
|
||||||
|
background,
|
||||||
neutral_lightness: reference_lightness,
|
neutral_lightness: reference_lightness,
|
||||||
scheme_settings: settings.clone(),
|
scheme_settings: settings.clone(),
|
||||||
is_dark,
|
is_dark,
|
||||||
@@ -320,11 +383,12 @@ impl Baseline {
|
|||||||
self.neutral_variant
|
self.neutral_variant
|
||||||
.to_css_variables(scheme_mode, "neutral-variant"),
|
.to_css_variables(scheme_mode, "neutral-variant"),
|
||||||
);
|
);
|
||||||
css_variables.extend(self.surface.to_css_variables(scheme_mode, "surface"));
|
|
||||||
css_variables.extend(
|
// Handle surface array [0-5]
|
||||||
self.surface_variant
|
for (index, surface_set) in self.surface.iter().enumerate() {
|
||||||
.to_css_variables(scheme_mode, "surface-variant"),
|
css_variables
|
||||||
);
|
.extend(surface_set.to_css_variables(scheme_mode, &format!("surface-{}", index)));
|
||||||
|
}
|
||||||
|
|
||||||
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
||||||
for (n, c) in neutral_swatch {
|
for (n, c) in neutral_swatch {
|
||||||
@@ -340,13 +404,21 @@ impl Baseline {
|
|||||||
map_oklch_to_srgb_hex(&self.overlay)
|
map_oklch_to_srgb_hex(&self.overlay)
|
||||||
));
|
));
|
||||||
css_variables.push(format!(
|
css_variables.push(format!(
|
||||||
"--color-{scheme_mode}-outlint: #{};",
|
"--color-{scheme_mode}-outline: #{};",
|
||||||
map_oklch_to_srgb_hex(&self.outline)
|
map_oklch_to_srgb_hex(&self.outline)
|
||||||
));
|
));
|
||||||
css_variables.push(format!(
|
css_variables.push(format!(
|
||||||
"--color-{scheme_mode}-outline-variant: #{};",
|
"--color-{scheme_mode}-outline-variant: #{};",
|
||||||
map_oklch_to_srgb_hex(&self.outline_variant)
|
map_oklch_to_srgb_hex(&self.outline_variant)
|
||||||
));
|
));
|
||||||
|
css_variables.push(format!(
|
||||||
|
"--color-{scheme_mode}-foreground: #{};",
|
||||||
|
map_oklch_to_srgb_hex(&self.foreground)
|
||||||
|
));
|
||||||
|
css_variables.push(format!(
|
||||||
|
"--color-{scheme_mode}-background: #{};",
|
||||||
|
map_oklch_to_srgb_hex(&self.background)
|
||||||
|
));
|
||||||
|
|
||||||
for (name, color_unit) in &self.custom_colors {
|
for (name, color_unit) in &self.custom_colors {
|
||||||
let lowercased_name = name.to_lowercase();
|
let lowercased_name = name.to_lowercase();
|
||||||
@@ -378,11 +450,12 @@ impl Baseline {
|
|||||||
self.neutral_variant
|
self.neutral_variant
|
||||||
.to_css_auto_scheme_collection("neutral-variant"),
|
.to_css_auto_scheme_collection("neutral-variant"),
|
||||||
);
|
);
|
||||||
css_variables.extend(self.surface.to_css_auto_scheme_collection("surface"));
|
|
||||||
css_variables.extend(
|
// Handle surface array [0-5]
|
||||||
self.surface_variant
|
for (index, surface_set) in self.surface.iter().enumerate() {
|
||||||
.to_css_auto_scheme_collection("surface-variant"),
|
css_variables
|
||||||
);
|
.extend(surface_set.to_css_auto_scheme_collection(&format!("surface-{}", index)));
|
||||||
|
}
|
||||||
|
|
||||||
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
||||||
for (n, c) in neutral_swatch {
|
for (n, c) in neutral_swatch {
|
||||||
@@ -396,6 +469,14 @@ impl Baseline {
|
|||||||
"outline-variant".to_string(),
|
"outline-variant".to_string(),
|
||||||
map_oklch_to_srgb_hex(&self.outline_variant),
|
map_oklch_to_srgb_hex(&self.outline_variant),
|
||||||
);
|
);
|
||||||
|
css_variables.insert(
|
||||||
|
"foreground".to_string(),
|
||||||
|
map_oklch_to_srgb_hex(&self.foreground),
|
||||||
|
);
|
||||||
|
css_variables.insert(
|
||||||
|
"background".to_string(),
|
||||||
|
map_oklch_to_srgb_hex(&self.background),
|
||||||
|
);
|
||||||
|
|
||||||
for (name, color) in &self.custom_colors {
|
for (name, color) in &self.custom_colors {
|
||||||
let lowercased_name = name.to_lowercase();
|
let lowercased_name = name.to_lowercase();
|
||||||
@@ -429,11 +510,12 @@ impl Baseline {
|
|||||||
self.neutral_variant
|
self.neutral_variant
|
||||||
.to_scss_variables(scheme_mode, "neutral-variant"),
|
.to_scss_variables(scheme_mode, "neutral-variant"),
|
||||||
);
|
);
|
||||||
scss_variables.extend(self.surface.to_scss_variables(scheme_mode, "surface"));
|
|
||||||
scss_variables.extend(
|
// Handle surface array [0-5]
|
||||||
self.surface_variant
|
for (index, surface_set) in self.surface.iter().enumerate() {
|
||||||
.to_scss_variables(scheme_mode, "surface-variant"),
|
scss_variables
|
||||||
);
|
.extend(surface_set.to_scss_variables(scheme_mode, &format!("surface-{}", index)));
|
||||||
|
}
|
||||||
|
|
||||||
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
let neutral_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
||||||
for (n, c) in neutral_swatch {
|
for (n, c) in neutral_swatch {
|
||||||
@@ -449,13 +531,21 @@ impl Baseline {
|
|||||||
map_oklch_to_srgb_hex(&self.overlay)
|
map_oklch_to_srgb_hex(&self.overlay)
|
||||||
));
|
));
|
||||||
scss_variables.push(format!(
|
scss_variables.push(format!(
|
||||||
"$color-{scheme_mode}-outlint: #{};",
|
"$color-{scheme_mode}-outline: #{};",
|
||||||
map_oklch_to_srgb_hex(&self.outline)
|
map_oklch_to_srgb_hex(&self.outline)
|
||||||
));
|
));
|
||||||
scss_variables.push(format!(
|
scss_variables.push(format!(
|
||||||
"$color-{scheme_mode}-outline-variant: #{};",
|
"$color-{scheme_mode}-outline-variant: #{};",
|
||||||
map_oklch_to_srgb_hex(&self.outline_variant)
|
map_oklch_to_srgb_hex(&self.outline_variant)
|
||||||
));
|
));
|
||||||
|
scss_variables.push(format!(
|
||||||
|
"$color-{scheme_mode}-foreground: #{};",
|
||||||
|
map_oklch_to_srgb_hex(&self.foreground)
|
||||||
|
));
|
||||||
|
scss_variables.push(format!(
|
||||||
|
"$color-{scheme_mode}-background: #{};",
|
||||||
|
map_oklch_to_srgb_hex(&self.background)
|
||||||
|
));
|
||||||
|
|
||||||
for (name, color) in &self.custom_colors {
|
for (name, color) in &self.custom_colors {
|
||||||
let lowercased_name = name.to_lowercase();
|
let lowercased_name = name.to_lowercase();
|
||||||
@@ -525,15 +615,15 @@ impl Baseline {
|
|||||||
{
|
{
|
||||||
javascript_fields.push(format!("{indent}{line:4}"));
|
javascript_fields.push(format!("{indent}{line:4}"));
|
||||||
}
|
}
|
||||||
for line in self.surface.to_javascript_fields("surface").iter() {
|
|
||||||
javascript_fields.push(format!("{indent}{line:4}"));
|
// Handle surface array [0-5]
|
||||||
}
|
for (index, surface_set) in self.surface.iter().enumerate() {
|
||||||
for line in self
|
for line in surface_set
|
||||||
.surface_variant
|
.to_javascript_fields(&format!("surface{}", index))
|
||||||
.to_javascript_fields("surface_variant")
|
.iter()
|
||||||
.iter()
|
{
|
||||||
{
|
javascript_fields.push(format!("{indent}{line:4}"));
|
||||||
javascript_fields.push(format!("{indent}{line:4}"));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let neurtal_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
let neurtal_swatch = generate_neutral_swatch_list(&self.neutral_swatch);
|
||||||
@@ -557,6 +647,14 @@ impl Baseline {
|
|||||||
"{indent}outlineVariant: '#{}',",
|
"{indent}outlineVariant: '#{}',",
|
||||||
map_oklch_to_srgb_hex(&self.outline_variant)
|
map_oklch_to_srgb_hex(&self.outline_variant)
|
||||||
));
|
));
|
||||||
|
javascript_fields.push(format!(
|
||||||
|
"{indent}foreground: '#{}',",
|
||||||
|
map_oklch_to_srgb_hex(&self.foreground)
|
||||||
|
));
|
||||||
|
javascript_fields.push(format!(
|
||||||
|
"{indent}background: '#{}',",
|
||||||
|
map_oklch_to_srgb_hex(&self.background)
|
||||||
|
));
|
||||||
|
|
||||||
for (name, color) in &self.custom_colors {
|
for (name, color) in &self.custom_colors {
|
||||||
let lowercased_name = name.to_lowercase();
|
let lowercased_name = name.to_lowercase();
|
||||||
|
|||||||
@@ -19,12 +19,6 @@ pub struct ColorSet {
|
|||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
pub root: Oklch,
|
pub root: Oklch,
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
pub active: Oklch,
|
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
|
||||||
pub focus: Oklch,
|
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
|
||||||
pub hover: Oklch,
|
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
|
||||||
pub disabled: Oklch,
|
pub disabled: Oklch,
|
||||||
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
#[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
|
||||||
pub on_root: Oklch,
|
pub on_root: Oklch,
|
||||||
@@ -88,12 +82,9 @@ impl ColorSet {
|
|||||||
let settings = Arc::clone(settings);
|
let settings = Arc::clone(settings);
|
||||||
|
|
||||||
let root = color.clone();
|
let root = color.clone();
|
||||||
let hover = color * settings.hover;
|
|
||||||
let active = color * settings.active;
|
|
||||||
let focus = color * settings.focus;
|
|
||||||
let disabled = color * settings.disabled;
|
let disabled = color * settings.disabled;
|
||||||
|
|
||||||
let color_list = &[&root, &hover, &active, &focus];
|
let color_list = &[&root];
|
||||||
|
|
||||||
let (on_root, on_disabled) = match settings.wacg_follows {
|
let (on_root, on_disabled) = match settings.wacg_follows {
|
||||||
WACGSetting::Fixed => (
|
WACGSetting::Fixed => (
|
||||||
@@ -116,9 +107,6 @@ impl ColorSet {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
root,
|
root,
|
||||||
active,
|
|
||||||
focus,
|
|
||||||
hover,
|
|
||||||
disabled,
|
disabled,
|
||||||
on_root,
|
on_root,
|
||||||
on_disabled,
|
on_disabled,
|
||||||
@@ -154,18 +142,6 @@ impl ColorSet {
|
|||||||
map_oklch_to_srgb_hex(&self.root)
|
map_oklch_to_srgb_hex(&self.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hover_hex(&self) -> String {
|
|
||||||
map_oklch_to_srgb_hex(&self.hover)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn active_hex(&self) -> String {
|
|
||||||
map_oklch_to_srgb_hex(&self.active)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn focus_hex(&self) -> String {
|
|
||||||
map_oklch_to_srgb_hex(&self.focus)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disabled_hex(&self) -> String {
|
fn disabled_hex(&self) -> String {
|
||||||
map_oklch_to_srgb_hex(&self.disabled)
|
map_oklch_to_srgb_hex(&self.disabled)
|
||||||
}
|
}
|
||||||
@@ -182,18 +158,6 @@ impl ColorSet {
|
|||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
|
|
||||||
variables.push(format!("--color-{prefix}-{name}: #{};", self.root_hex()));
|
variables.push(format!("--color-{prefix}-{name}: #{};", self.root_hex()));
|
||||||
variables.push(format!(
|
|
||||||
"--color-{prefix}-{name}-hover: #{};",
|
|
||||||
self.hover_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
|
||||||
"--color-{prefix}-{name}-active: #{};",
|
|
||||||
self.active_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
|
||||||
"--color-{prefix}-{name}-focus: #{};",
|
|
||||||
self.focus_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
variables.push(format!(
|
||||||
"--color-{prefix}-{name}-disabled: ${};",
|
"--color-{prefix}-{name}-disabled: ${};",
|
||||||
self.disabled_hex()
|
self.disabled_hex()
|
||||||
@@ -214,9 +178,6 @@ impl ColorSet {
|
|||||||
let mut collection = LinkedHashMap::new();
|
let mut collection = LinkedHashMap::new();
|
||||||
|
|
||||||
collection.insert(format!("{name}"), self.root_hex());
|
collection.insert(format!("{name}"), self.root_hex());
|
||||||
collection.insert(format!("{name}-hover"), self.hover_hex());
|
|
||||||
collection.insert(format!("{name}-active"), self.active_hex());
|
|
||||||
collection.insert(format!("{name}-focus"), self.focus_hex());
|
|
||||||
collection.insert(format!("{name}-disabled"), self.disabled_hex());
|
collection.insert(format!("{name}-disabled"), self.disabled_hex());
|
||||||
collection.insert(format!("on-{name}"), self.on_root_hex());
|
collection.insert(format!("on-{name}"), self.on_root_hex());
|
||||||
collection.insert(format!("on-{name}-disabled"), self.on_disabled_hex());
|
collection.insert(format!("on-{name}-disabled"), self.on_disabled_hex());
|
||||||
@@ -228,18 +189,6 @@ impl ColorSet {
|
|||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
|
|
||||||
variables.push(format!("&color-{prefix}-{name}: #{};", self.root_hex()));
|
variables.push(format!("&color-{prefix}-{name}: #{};", self.root_hex()));
|
||||||
variables.push(format!(
|
|
||||||
"$color-{prefix}-{name}-hover: #{};",
|
|
||||||
self.hover_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
|
||||||
"$color-{prefix}-{name}-active: #{};",
|
|
||||||
self.active_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
|
||||||
"$color-{prefix}-{name}-focus: ${};",
|
|
||||||
self.focus_hex()
|
|
||||||
));
|
|
||||||
variables.push(format!(
|
variables.push(format!(
|
||||||
"$color-{prefix}-{name}-disabled: #{};",
|
"$color-{prefix}-{name}-disabled: #{};",
|
||||||
self.disabled_hex()
|
self.disabled_hex()
|
||||||
@@ -267,9 +216,6 @@ impl ColorSet {
|
|||||||
+ &name[1..];
|
+ &name[1..];
|
||||||
|
|
||||||
variables.push(format!("{name}: '#{}',", self.root_hex()));
|
variables.push(format!("{name}: '#{}',", self.root_hex()));
|
||||||
variables.push(format!("{name}Hover: '#{}',", self.hover_hex()));
|
|
||||||
variables.push(format!("{name}Active: '#{}',", self.active_hex()));
|
|
||||||
variables.push(format!("{name}Focus: '#{}',", self.focus_hex()));
|
|
||||||
variables.push(format!("{name}Disabled: '#{}',", self.disabled_hex()));
|
variables.push(format!("{name}Disabled: '#{}',", self.disabled_hex()));
|
||||||
variables.push(format!("on{capitalized_name}: '#{}',", self.on_root_hex()));
|
variables.push(format!("on{capitalized_name}: '#{}',", self.on_root_hex()));
|
||||||
variables.push(format!(
|
variables.push(format!(
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ mod swatch;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct QScheme2 {
|
pub struct QScheme2 {
|
||||||
pub light: Baseline,
|
pub light: Option<Baseline>,
|
||||||
pub dark: Baseline,
|
pub dark: Option<Baseline>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
_settings: Arc<SchemeSetting>,
|
_settings: Arc<SchemeSetting>,
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,16 @@ impl QScheme2 {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
light: light_scheme,
|
light: if settings.scheme_select.includes_light() {
|
||||||
dark: dark_scheme,
|
Some(light_scheme)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
dark: if settings.scheme_select.includes_dark() {
|
||||||
|
Some(dark_scheme)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
_settings: settings,
|
_settings: settings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -89,9 +97,12 @@ impl QScheme2 {
|
|||||||
pub fn add_custom_color(&mut self, name: &str, color: &str) -> Result<(), errors::ColorError> {
|
pub fn add_custom_color(&mut self, name: &str, color: &str) -> Result<(), errors::ColorError> {
|
||||||
let custom_color = parse_to_oklch!(color);
|
let custom_color = parse_to_oklch!(color);
|
||||||
|
|
||||||
self.light.add_custom_color(name, &custom_color)?;
|
if let Some(light) = &mut self.light {
|
||||||
self.dark
|
light.add_custom_color(name, &custom_color)?;
|
||||||
.add_custom_color(name, &(custom_color * self._settings.dark_convert))?;
|
}
|
||||||
|
if let Some(dark) = &mut self.dark {
|
||||||
|
dark.add_custom_color(name, &(custom_color * self._settings.dark_convert))?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -101,8 +112,12 @@ impl SchemeExport for QScheme2 {
|
|||||||
fn output_css_variables(&self) -> String {
|
fn output_css_variables(&self) -> String {
|
||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
|
|
||||||
variables.extend(self.light.to_css_variables());
|
if let Some(light) = &self.light {
|
||||||
variables.extend(self.dark.to_css_variables());
|
variables.extend(light.to_css_variables());
|
||||||
|
}
|
||||||
|
if let Some(dark) = &self.dark {
|
||||||
|
variables.extend(dark.to_css_variables());
|
||||||
|
}
|
||||||
|
|
||||||
variables.join("\n")
|
variables.join("\n")
|
||||||
}
|
}
|
||||||
@@ -110,13 +125,25 @@ impl SchemeExport for QScheme2 {
|
|||||||
fn output_css_auto_scheme_variables(&self) -> String {
|
fn output_css_auto_scheme_variables(&self) -> String {
|
||||||
let mut collection = Vec::new();
|
let mut collection = Vec::new();
|
||||||
let mut keys = LinkedHashSet::new();
|
let mut keys = LinkedHashSet::new();
|
||||||
let light_collection = self.light.to_css_auto_scheme_collection();
|
let light_collection = self
|
||||||
let dark_collection = self.dark.to_css_auto_scheme_collection();
|
.light
|
||||||
|
.as_ref()
|
||||||
|
.map(|l| l.to_css_auto_scheme_collection());
|
||||||
|
let dark_collection = self
|
||||||
|
.dark
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| d.to_css_auto_scheme_collection());
|
||||||
|
|
||||||
keys.extend(light_collection.keys().cloned());
|
if let Some(ref light_col) = light_collection {
|
||||||
keys.extend(dark_collection.keys().cloned());
|
keys.extend(light_col.keys().cloned());
|
||||||
|
}
|
||||||
|
if let Some(ref dark_col) = dark_collection {
|
||||||
|
keys.extend(dark_col.keys().cloned());
|
||||||
|
}
|
||||||
for key in keys {
|
for key in keys {
|
||||||
match (light_collection.get(&key), dark_collection.get(&key)) {
|
let light_val = light_collection.as_ref().and_then(|l| l.get(&key));
|
||||||
|
let dark_val = dark_collection.as_ref().and_then(|d| d.get(&key));
|
||||||
|
match (light_val, dark_val) {
|
||||||
(Some(light), Some(dark)) => {
|
(Some(light), Some(dark)) => {
|
||||||
collection.push(format!("--color-{key}: light-dark(#{light}, #{dark});"));
|
collection.push(format!("--color-{key}: light-dark(#{light}, #{dark});"));
|
||||||
}
|
}
|
||||||
@@ -133,8 +160,12 @@ impl SchemeExport for QScheme2 {
|
|||||||
fn output_scss_variables(&self) -> String {
|
fn output_scss_variables(&self) -> String {
|
||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
|
|
||||||
variables.extend(self.light.to_scss_variables());
|
if let Some(light) = &self.light {
|
||||||
variables.extend(self.dark.to_scss_variables());
|
variables.extend(light.to_scss_variables());
|
||||||
|
}
|
||||||
|
if let Some(dark) = &self.dark {
|
||||||
|
variables.extend(dark.to_scss_variables());
|
||||||
|
}
|
||||||
|
|
||||||
variables.join("\n")
|
variables.join("\n")
|
||||||
}
|
}
|
||||||
@@ -144,11 +175,15 @@ impl SchemeExport for QScheme2 {
|
|||||||
|
|
||||||
let indent = " ".repeat(4);
|
let indent = " ".repeat(4);
|
||||||
javascript_object.push("{".to_string());
|
javascript_object.push("{".to_string());
|
||||||
for line in self.light.to_javascript_fields() {
|
if let Some(light) = &self.light {
|
||||||
javascript_object.push(format!("{indent}{line}"));
|
for line in light.to_javascript_fields() {
|
||||||
|
javascript_object.push(format!("{indent}{line}"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for line in self.dark.to_javascript_fields() {
|
if let Some(dark) = &self.dark {
|
||||||
javascript_object.push(format!("{indent}{line}"));
|
for line in dark.to_javascript_fields() {
|
||||||
|
javascript_object.push(format!("{indent}{line}"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
javascript_object.push("}".to_string());
|
javascript_object.push("}".to_string());
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,6 @@
|
|||||||
"lightningcss": "^1.28.2",
|
"lightningcss": "^1.28.2",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.8.3",
|
||||||
"typescript-eslint": "^8.18.2",
|
"typescript-eslint": "^8.18.2",
|
||||||
"vite": "^7.0.4"
|
"vite": "^6.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { ColorExpand, ColorShifting, SchemeSetting, WACGSetting } from 'color-module';
|
import { ColorExpand, ColorShifting, SchemeSelect, SchemeSetting, WACGSetting } from 'color-module';
|
||||||
import { includes, isEmpty, isNil } from 'lodash-es';
|
import { includes, isEmpty, isNil } from 'lodash-es';
|
||||||
import { useActionState, useCallback, useMemo, useState } from 'react';
|
import { useActionState, useCallback, useMemo, useState } from 'react';
|
||||||
import { useColorFunction } from '../../../ColorFunctionContext';
|
import { useColorFunction } from '../../../ColorFunctionContext';
|
||||||
import { FloatColorPicker } from '../../../components/FloatColorPicker';
|
import { FloatColorPicker } from '../../../components/FloatColorPicker';
|
||||||
|
import { HSegmentedControl } from '../../../components/HSegmentedControl';
|
||||||
import { NotificationType, useNotification } from '../../../components/Notifications';
|
import { NotificationType, useNotification } from '../../../components/Notifications';
|
||||||
import { ScrollArea } from '../../../components/ScrollArea';
|
import { ScrollArea } from '../../../components/ScrollArea';
|
||||||
import { VSegmentedControl } from '../../../components/VSegmentedControl';
|
import { VSegmentedControl } from '../../../components/VSegmentedControl';
|
||||||
@@ -57,6 +58,7 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
),
|
),
|
||||||
scheme.schemeStorage.source?.setting?.expand_method ?? defaultValues.expand_method,
|
scheme.schemeStorage.source?.setting?.expand_method ?? defaultValues.expand_method,
|
||||||
scheme.schemeStorage.source?.setting?.wacg_follows ?? defaultValues.wacg_follows,
|
scheme.schemeStorage.source?.setting?.wacg_follows ?? defaultValues.wacg_follows,
|
||||||
|
scheme.schemeStorage.source?.setting?.scheme_select ?? defaultValues.scheme_select,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return defaultValues;
|
return defaultValues;
|
||||||
@@ -84,6 +86,15 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}, []);
|
}, []);
|
||||||
|
const schemeStrategies = useMemo(() => {
|
||||||
|
try {
|
||||||
|
if (!colorFn) throw 'Web Assembly functions is not available';
|
||||||
|
return colorFn.q_scheme_select_options();
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[Q scheme builder]', e);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Custom Colors processing
|
// Custom Colors processing
|
||||||
const originalColors = useMemo(() => {
|
const originalColors = useMemo(() => {
|
||||||
@@ -127,18 +138,9 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
|
|
||||||
// collect scheme settings
|
// collect scheme settings
|
||||||
const schemeSetting = new SchemeSetting(
|
const schemeSetting = new SchemeSetting(
|
||||||
new ColorShifting(
|
new ColorShifting(0, 0),
|
||||||
Number(formData.get('hover_chroma')) / 100,
|
new ColorShifting(0, 0),
|
||||||
Number(formData.get('hover_lightness')) / 100,
|
new ColorShifting(0, 0),
|
||||||
),
|
|
||||||
new ColorShifting(
|
|
||||||
Number(formData.get('active_chroma')) / 100,
|
|
||||||
Number(formData.get('active_lightness')) / 100,
|
|
||||||
),
|
|
||||||
new ColorShifting(
|
|
||||||
Number(formData.get('focus_chroma')) / 100,
|
|
||||||
Number(formData.get('focus_lightness')) / 100,
|
|
||||||
),
|
|
||||||
new ColorShifting(
|
new ColorShifting(
|
||||||
Number(formData.get('disabled_chroma')) / 100,
|
Number(formData.get('disabled_chroma')) / 100,
|
||||||
Number(formData.get('disabled_lightness')) / 100,
|
Number(formData.get('disabled_lightness')) / 100,
|
||||||
@@ -149,6 +151,7 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
),
|
),
|
||||||
Number(formData.get('expanding')) as ColorExpand,
|
Number(formData.get('expanding')) as ColorExpand,
|
||||||
Number(formData.get('wacg')) as WACGSetting,
|
Number(formData.get('wacg')) as WACGSetting,
|
||||||
|
Number(formData.get('scheme_select')) as SchemeSelect,
|
||||||
);
|
);
|
||||||
const dumpedSetting = schemeSetting.toJsValue() as QSchemeSetting;
|
const dumpedSetting = schemeSetting.toJsValue() as QSchemeSetting;
|
||||||
|
|
||||||
@@ -221,14 +224,18 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
updateScheme((prev) => {
|
updateScheme((prev) => {
|
||||||
prev.schemeStorage.source = source;
|
prev.schemeStorage.source = source;
|
||||||
prev.schemeStorage.scheme = {
|
prev.schemeStorage.scheme = {
|
||||||
light: {
|
light: isNil(generatedScheme[0].light)
|
||||||
...generatedScheme[0].light,
|
? null
|
||||||
customColors: mapToObject(generatedScheme[0].light.customColors),
|
: {
|
||||||
},
|
...generatedScheme[0].light,
|
||||||
dark: {
|
customColors: mapToObject(generatedScheme[0].light.customColors),
|
||||||
...generatedScheme[0].dark,
|
},
|
||||||
customColors: mapToObject(generatedScheme[0].dark.customColors),
|
dark: isNil(generatedScheme[0].dark)
|
||||||
},
|
? null
|
||||||
|
: {
|
||||||
|
...generatedScheme[0].dark,
|
||||||
|
customColors: mapToObject(generatedScheme[0].dark.customColors),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
prev.schemeStorage.cssVariables = generatedScheme[1];
|
prev.schemeStorage.cssVariables = generatedScheme[1];
|
||||||
prev.schemeStorage.cssAutoSchemeVariables = generatedScheme[2];
|
prev.schemeStorage.cssAutoSchemeVariables = generatedScheme[2];
|
||||||
@@ -406,63 +413,6 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
<h5 className={styles.segment_title}>Automated parameters</h5>
|
<h5 className={styles.segment_title}>Automated parameters</h5>
|
||||||
<label style={{ gridColumn: 2 }}>Chroma shifting</label>
|
<label style={{ gridColumn: 2 }}>Chroma shifting</label>
|
||||||
<label style={{ gridColumn: 3 }}>Lightness shifting</label>
|
<label style={{ gridColumn: 3 }}>Lightness shifting</label>
|
||||||
<label className={styles.label}>Hover</label>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="hover_chroma"
|
|
||||||
defaultValue={((defaultSetting?.hover.chroma ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="hover_lightness"
|
|
||||||
defaultValue={((defaultSetting?.hover.lightness ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<label className={styles.label}>Active</label>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="active_chroma"
|
|
||||||
defaultValue={((defaultSetting?.active.chroma ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="active_lightness"
|
|
||||||
defaultValue={((defaultSetting?.active.lightness ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<label className={styles.label}>Focus</label>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="focus_chroma"
|
|
||||||
defaultValue={((defaultSetting?.focus.chroma ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<div className="input_wrapper">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="focus_lightness"
|
|
||||||
defaultValue={((defaultSetting?.focus.lightness ?? 0) * 100).toFixed(2)}
|
|
||||||
className={styles.parameter_input}
|
|
||||||
/>
|
|
||||||
<span>%</span>
|
|
||||||
</div>
|
|
||||||
<label className={styles.label}>Disabled</label>
|
<label className={styles.label}>Disabled</label>
|
||||||
<div className="input_wrapper">
|
<div className="input_wrapper">
|
||||||
<input
|
<input
|
||||||
@@ -518,6 +468,14 @@ export function Q2SchemeBuilder({ scheme, onBuildCompleted }: Q2SchemeBuilderPro
|
|||||||
defaultValue={defaultSetting?.wacg_follows}
|
defaultValue={defaultSetting?.wacg_follows}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<label className={styles.label}>Generate scheme</label>
|
||||||
|
<div style={{ gridColumn: '2 / span 2' }}>
|
||||||
|
<HSegmentedControl
|
||||||
|
options={schemeStrategies}
|
||||||
|
name="scheme_select"
|
||||||
|
defaultValue={defaultSetting?.scheme_select}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className={styles.button_row} style={{ gridColumn: '2 / span 2' }}>
|
<div className={styles.button_row} style={{ gridColumn: '2 / span 2' }}>
|
||||||
<button type="submit" className="primary">
|
<button type="submit" className="primary">
|
||||||
Build Scheme
|
Build Scheme
|
||||||
|
|||||||
@@ -24,9 +24,21 @@
|
|||||||
.preview_unit {
|
.preview_unit {
|
||||||
width: inherit;
|
width: inherit;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: var(--spacing-xs);
|
gap: var(--spacing-xs);
|
||||||
}
|
}
|
||||||
|
.preview_surface {
|
||||||
|
width: inherit;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, 1fr);
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
.surface_block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
justify-content: stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
.preview_indi_block {
|
.preview_indi_block {
|
||||||
width: inherit;
|
width: inherit;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
@@ -39,23 +39,14 @@ interface PreviewLineProps {
|
|||||||
|
|
||||||
const PreviewLine: FC<PreviewLineProps> = ({ name, unit }) => {
|
const PreviewLine: FC<PreviewLineProps> = ({ name, unit }) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.preview_unit}>
|
<>
|
||||||
<PreviewCell bg={unit.root} fg={unit.onRoot}>
|
<PreviewCell bg={unit.root} fg={unit.onRoot}>
|
||||||
{name}
|
{name}
|
||||||
</PreviewCell>
|
</PreviewCell>
|
||||||
<PreviewCell bg={unit.hover} fg={unit.onRoot}>
|
|
||||||
{name} Hover
|
|
||||||
</PreviewCell>
|
|
||||||
<PreviewCell bg={unit.active} fg={unit.onRoot}>
|
|
||||||
{name} Active
|
|
||||||
</PreviewCell>
|
|
||||||
<PreviewCell bg={unit.focus} fg={unit.onRoot}>
|
|
||||||
{name} Focus
|
|
||||||
</PreviewCell>
|
|
||||||
<PreviewCell bg={unit.disabled} fg={unit.onDisabled}>
|
<PreviewCell bg={unit.disabled} fg={unit.onDisabled}>
|
||||||
{name} Disabled
|
{name} Disabled
|
||||||
</PreviewCell>
|
</PreviewCell>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,8 +84,10 @@ interface PreviewSetProps {
|
|||||||
const PreviewSet: FC<PreviewSetProps> = ({ name, colorUnit }) => {
|
const PreviewSet: FC<PreviewSetProps> = ({ name, colorUnit }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PreviewLine name={name} unit={colorUnit.root} />
|
<div className={styles.preview_unit}>
|
||||||
<PreviewLine name={`${name} Surface`} unit={colorUnit.surface} />
|
<PreviewLine name={name} unit={colorUnit.root} />
|
||||||
|
<PreviewLine name={`${name} Surface`} unit={colorUnit.surface} />
|
||||||
|
</div>
|
||||||
<PreviewSwatchLine swatch={colorUnit.swatch} />
|
<PreviewSwatchLine swatch={colorUnit.swatch} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -119,8 +112,8 @@ const PreviewBlock: FC<PreviewBlockProps> = ({ baseline, title }) => {
|
|||||||
}, [baseline.customColors]);
|
}, [baseline.customColors]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.preview_block} style={{ backgroundColor: `#${baseline.surface.root}` }}>
|
<div className={styles.preview_block} style={{ backgroundColor: `#${baseline.background}` }}>
|
||||||
<h2 style={{ color: `#${baseline.surface.onRoot}` }}>{title}</h2>
|
<h2 style={{ color: `#${baseline.foreground}` }}>{title}</h2>
|
||||||
<PreviewSet name="Primary" colorUnit={baseline.primary} />
|
<PreviewSet name="Primary" colorUnit={baseline.primary} />
|
||||||
{baseline.secondary && <PreviewSet name="Secondary" colorUnit={baseline.secondary} />}
|
{baseline.secondary && <PreviewSet name="Secondary" colorUnit={baseline.secondary} />}
|
||||||
{baseline.tertiary && <PreviewSet name="Tertiary" colorUnit={baseline.tertiary} />}
|
{baseline.tertiary && <PreviewSet name="Tertiary" colorUnit={baseline.tertiary} />}
|
||||||
@@ -129,10 +122,17 @@ const PreviewBlock: FC<PreviewBlockProps> = ({ baseline, title }) => {
|
|||||||
<PreviewSet name="Success" colorUnit={baseline.success} />
|
<PreviewSet name="Success" colorUnit={baseline.success} />
|
||||||
<PreviewSet name="Warn" colorUnit={baseline.warn} />
|
<PreviewSet name="Warn" colorUnit={baseline.warn} />
|
||||||
<PreviewSet name="Info" colorUnit={baseline.info} />
|
<PreviewSet name="Info" colorUnit={baseline.info} />
|
||||||
<PreviewLine name="Neutral" unit={baseline.neutral} />
|
<div className={styles.preview_unit}>
|
||||||
<PreviewLine name="Neutral Variant" unit={baseline.neutralVariant} />
|
<PreviewLine name="Neutral" unit={baseline.neutral} />
|
||||||
<PreviewLine name="Surface" unit={baseline.surface} />
|
<PreviewLine name="Neutral Variant" unit={baseline.neutralVariant} />
|
||||||
<PreviewLine name="Surface Variant" unit={baseline.surfaceVariant} />
|
</div>
|
||||||
|
<div className={styles.preview_surface}>
|
||||||
|
{baseline.surface.map((surfaceSet, index) => (
|
||||||
|
<div className={styles.surface_block} key={index}>
|
||||||
|
<PreviewLine key={index} name={`Surface ${index + 1}`} unit={surfaceSet} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
<div className={styles.preview_indi_block}>
|
<div className={styles.preview_indi_block}>
|
||||||
<PreviewCell bg={baseline.shadow} fg={baseline.neutralVariant.onRoot}>
|
<PreviewCell bg={baseline.shadow} fg={baseline.neutralVariant.onRoot}>
|
||||||
Shadow
|
Shadow
|
||||||
@@ -162,10 +162,10 @@ const Q2SchemePreview: FC<PreviewProps> = ({ scheme }) => {
|
|||||||
<ScrollArea enableY>
|
<ScrollArea enableY>
|
||||||
<div className={styles.preview_layout}>
|
<div className={styles.preview_layout}>
|
||||||
<div className={styles.preview_layout}>
|
<div className={styles.preview_layout}>
|
||||||
{scheme.schemeStorage.scheme?.light && (
|
{scheme.schemeStorage.scheme?.light !== null && (
|
||||||
<PreviewBlock baseline={scheme.schemeStorage.scheme.light} title="Light Scheme" />
|
<PreviewBlock baseline={scheme.schemeStorage.scheme.light} title="Light Scheme" />
|
||||||
)}
|
)}
|
||||||
{scheme.schemeStorage.scheme?.dark && (
|
{scheme.schemeStorage.scheme?.dark !== null && (
|
||||||
<PreviewBlock baseline={scheme.schemeStorage.scheme.dark} title="Dark Scheme" />
|
<PreviewBlock baseline={scheme.schemeStorage.scheme.dark} title="Dark Scheme" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import { QSchemeSetting } from './q-scheme';
|
|||||||
|
|
||||||
export type Q2ColorSet = {
|
export type Q2ColorSet = {
|
||||||
root: string;
|
root: string;
|
||||||
hover: string;
|
|
||||||
active: string;
|
|
||||||
focus: string;
|
|
||||||
disabled: string;
|
disabled: string;
|
||||||
onRoot: string;
|
onRoot: string;
|
||||||
onDisabled: string;
|
onDisabled: string;
|
||||||
@@ -23,13 +20,14 @@ export type Q2Baseline = {
|
|||||||
accent: Q2ColorUnit | null;
|
accent: Q2ColorUnit | null;
|
||||||
neutral: Q2ColorSet;
|
neutral: Q2ColorSet;
|
||||||
neutralVariant: Q2ColorSet;
|
neutralVariant: Q2ColorSet;
|
||||||
surface: Q2ColorSet;
|
surface: Q2ColorSet[];
|
||||||
surfaceVariant: Q2ColorSet;
|
|
||||||
neutralSwatch: Record<string, string>;
|
neutralSwatch: Record<string, string>;
|
||||||
danger: Q2ColorUnit;
|
danger: Q2ColorUnit;
|
||||||
success: Q2ColorUnit;
|
success: Q2ColorUnit;
|
||||||
warn: Q2ColorUnit;
|
warn: Q2ColorUnit;
|
||||||
info: Q2ColorUnit;
|
info: Q2ColorUnit;
|
||||||
|
foreground: string;
|
||||||
|
background: string;
|
||||||
shadow: string;
|
shadow: string;
|
||||||
overlay: string;
|
overlay: string;
|
||||||
outline: string;
|
outline: string;
|
||||||
@@ -38,8 +36,8 @@ export type Q2Baseline = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Q2Scheme = {
|
export type Q2Scheme = {
|
||||||
light: Q2Baseline;
|
light: Q2Baseline | null;
|
||||||
dark: Q2Baseline;
|
dark: Q2Baseline | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Q2SchemeSource = {
|
export type Q2SchemeSource = {
|
||||||
|
|||||||
Reference in New Issue
Block a user