diff --git a/color-module/src/schemes/material_design_2/baseline.rs b/color-module/src/schemes/material_design_2/baseline.rs index c511d3d..6a0a9f0 100644 --- a/color-module/src/schemes/material_design_2/baseline.rs +++ b/color-module/src/schemes/material_design_2/baseline.rs @@ -81,6 +81,22 @@ impl M2BaselineColors { variable_lines } + pub fn to_css_auto_scheme_collection(&self) -> HashMap { + let mut variables = HashMap::new(); + + variables.extend(self.primary.to_css_auto_scheme_collection("primary")); + variables.extend(self.secondary.to_css_auto_scheme_collection("secondary")); + variables.extend(self.error.to_css_auto_scheme_collection("error")); + variables.extend(self.background.to_css_auto_scheme_collection("background")); + variables.extend(self.surface.to_css_auto_scheme_collection("surface")); + variables.insert("shadow".to_string(), self.shadow.clone()); + for (name, color_set) in &self.custom_colors { + variables.extend(color_set.to_css_auto_scheme_collection(&name.to_lowercase())); + } + + variables + } + pub fn to_scss_variable(&self) -> Vec { let mut variable_lines = Vec::new(); let prefix = if self.dark_set { "dark" } else { "light" }; diff --git a/color-module/src/schemes/material_design_2/color_set.rs b/color-module/src/schemes/material_design_2/color_set.rs index ff6d795..5597e2e 100644 --- a/color-module/src/schemes/material_design_2/color_set.rs +++ b/color-module/src/schemes/material_design_2/color_set.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde::Serialize; use crate::{convert::map_hsl_to_srgb_hex, errors}; @@ -82,6 +84,16 @@ impl M2ColorSet { variable_lines } + pub fn to_css_auto_scheme_collection(&self, name: &str) -> HashMap { + let mut variables = HashMap::new(); + + variables.insert(format!("{}", name), self.root.clone()); + variables.insert(format!("{}-variant", name), self.variant.clone()); + variables.insert(format!("on-{}", name), self.on.clone()); + + variables + } + pub fn to_scss_variable(&self, prefix: &str, name: &str) -> Vec { let mut variable_lines = Vec::new(); diff --git a/color-module/src/schemes/material_design_2/mod.rs b/color-module/src/schemes/material_design_2/mod.rs index 2d76ac9..d191734 100644 --- a/color-module/src/schemes/material_design_2/mod.rs +++ b/color-module/src/schemes/material_design_2/mod.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use baseline::M2BaselineColors; use palette::Hsl; use serde::Serialize; @@ -48,6 +50,34 @@ impl SchemeExport for MaterialDesign2Scheme { css_variables.join("\n") } + fn output_css_auto_scheme_variables(&self) -> String { + let mut auto_scheme_variables = Vec::new(); + let mut keys = HashSet::new(); + let light_baseline = self.light.to_css_auto_scheme_collection(); + let dark_baseline = self.dark.to_css_auto_scheme_collection(); + + auto_scheme_variables.push(format!("--color-white: #{};", self.white)); + auto_scheme_variables.push(format!("--color-black: #{};", self.black)); + + keys.extend(light_baseline.keys()); + keys.extend(dark_baseline.keys()); + for key in keys { + match (light_baseline.get(key), dark_baseline.get(key)) { + (Some(light), Some(dark)) => { + auto_scheme_variables.push(format!( + "--color-{}: light-dark(#{}, #{}):", + key, light, dark + )); + } + (Some(color), None) | (None, Some(color)) => { + auto_scheme_variables.push(format!("--color-{}: #{};", key, color)); + } + (None, None) => {} + } + } + auto_scheme_variables.join("\n") + } + fn output_scss_variables(&self) -> String { let mut scss_variables = Vec::new(); diff --git a/color-module/src/schemes/material_design_3/baseline.rs b/color-module/src/schemes/material_design_3/baseline.rs index 03fea58..79dccae 100644 --- a/color-module/src/schemes/material_design_3/baseline.rs +++ b/color-module/src/schemes/material_design_3/baseline.rs @@ -131,6 +131,25 @@ impl M3BaselineColors { css_variables } + pub fn to_css_auto_scheme_collection(&self) -> HashMap { + let mut collection = HashMap::new(); + + collection.extend(self.primary.to_css_auto_scheme_collection("primary")); + collection.extend(self.secondary.to_css_auto_scheme_collection("secondary")); + collection.extend(self.tertiary.to_css_auto_scheme_collection("tertiary")); + collection.extend(self.error.to_css_auto_scheme_collection("error")); + collection.extend(self.surface.to_css_auto_scheme_collection()); + collection.insert("outline".to_string(), self.outline.clone()); + collection.insert("outline-variant".to_string(), self.outline_variant.clone()); + collection.insert("scrim".to_string(), self.scrim.clone()); + collection.insert("shadow".to_string(), self.shadow.clone()); + for (name, color_set) in &self.customs { + collection.extend(color_set.to_css_auto_scheme_collection(&name.to_lowercase())); + } + + collection + } + pub fn to_scss_variables(&self) -> Vec { let mut scss_variables = Vec::new(); let prefix = if self.dark_set { "dark" } else { "light" }; diff --git a/color-module/src/schemes/material_design_3/color_set.rs b/color-module/src/schemes/material_design_3/color_set.rs index 9df5c42..e38e25f 100644 --- a/color-module/src/schemes/material_design_3/color_set.rs +++ b/color-module/src/schemes/material_design_3/color_set.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde::Serialize; use crate::convert::map_lch_to_srgb_hex; @@ -106,6 +108,25 @@ impl M3ColorSet { variable_lines } + pub fn to_css_auto_scheme_collection(&self, name: &str) -> HashMap { + let mut variables = HashMap::new(); + + variables.insert(format!("{}", name), self.root.clone()); + variables.insert(format!("on-{}", name), self.on_root.clone()); + variables.insert(format!("{}-container", name), self.container.clone()); + variables.insert(format!("on-{}-container", name), self.on_container.clone()); + variables.insert(format!("{}-fixed", name), self.fixed.clone()); + variables.insert(format!("{}-fixed-dim", name), self.fixed_dim.clone()); + variables.insert(format!("on-{}-fixed", name), self.on_fixed.clone()); + variables.insert( + format!("on-{}-fixed-variant", name), + self.fixed_variant.clone(), + ); + variables.insert(format!("inverse-{}", name), self.inverse.clone()); + + variables + } + pub fn to_scss_variables(&self, prefix: &str, name: &str) -> Vec { let mut variable_lines = Vec::new(); diff --git a/color-module/src/schemes/material_design_3/mod.rs b/color-module/src/schemes/material_design_3/mod.rs index c0fac24..fc69e63 100644 --- a/color-module/src/schemes/material_design_3/mod.rs +++ b/color-module/src/schemes/material_design_3/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::str::FromStr; pub use baseline::M3BaselineColors; @@ -111,6 +111,37 @@ impl SchemeExport for MaterialDesign3Scheme { css_variables.join("\n") } + fn output_css_auto_scheme_variables(&self) -> String { + let mut auto_scheme_variables = Vec::new(); + let mut keys = HashSet::new(); + let light_baseline = self.light_baseline.to_css_auto_scheme_collection(); + let dark_baseline = self.dark_baseline.to_css_auto_scheme_collection(); + + auto_scheme_variables.push(format!("--color-white: #{};", self.white)); + auto_scheme_variables.push(format!("--color-black: #{};", self.black)); + keys.extend(light_baseline.keys()); + keys.extend(dark_baseline.keys()); + for key in keys { + match (light_baseline.get(key), dark_baseline.get(key)) { + (Some(light), Some(dark)) => { + auto_scheme_variables.push(format!( + "--color-{}: light-dark(#{}, #{}):", + key, light, dark + )); + } + (Some(color), None) | (None, Some(color)) => { + auto_scheme_variables.push(format!("--color-{}: #{};", key, color)); + } + (None, None) => {} + } + } + for (name, swatch) in &self.swatches { + auto_scheme_variables.extend(swatch.to_css_variables(name)); + } + + auto_scheme_variables.join("\n") + } + fn output_scss_variables(&self) -> String { let mut scss_variables = Vec::new(); diff --git a/color-module/src/schemes/material_design_3/surface.rs b/color-module/src/schemes/material_design_3/surface.rs index f1907b6..8e1cbf3 100644 --- a/color-module/src/schemes/material_design_3/surface.rs +++ b/color-module/src/schemes/material_design_3/surface.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde::Serialize; use crate::convert::map_lch_to_srgb_hex; @@ -136,6 +138,35 @@ impl M3SurfaceSet { css_variables } + pub fn to_css_auto_scheme_collection(&self) -> HashMap { + let mut auto_scheme_collection = HashMap::new(); + + auto_scheme_collection.insert(format!("surface"), self.root.clone()); + auto_scheme_collection.insert(format!("surface-dim"), self.dim.clone()); + auto_scheme_collection.insert(format!("surface-bright"), self.bright.clone()); + auto_scheme_collection.insert(format!("surface-variant"), self.variant.clone()); + auto_scheme_collection.insert(format!("surface-container"), self.container.clone()); + auto_scheme_collection.insert( + format!("surface-container-lowest"), + self.container_lowest.clone(), + ); + auto_scheme_collection.insert(format!("surface-container-low"), self.container_low.clone()); + auto_scheme_collection.insert( + format!("surface-container-high"), + self.container_high.clone(), + ); + auto_scheme_collection.insert( + format!("surface-container-highest"), + self.container_highest.clone(), + ); + auto_scheme_collection.insert(format!("on-surface"), self.on_root.clone()); + auto_scheme_collection.insert(format!("on-surface-variant"), self.on_root_variant.clone()); + auto_scheme_collection.insert(format!("inverse-surface"), self.inverse.clone()); + auto_scheme_collection.insert(format!("inverse-on-surface"), self.on_inverse.clone()); + + auto_scheme_collection + } + pub fn to_scss_variables(&self, prefix: &str) -> Vec { let mut scss_variables = Vec::new(); diff --git a/color-module/src/schemes/mod.rs b/color-module/src/schemes/mod.rs index e1767fd..873f319 100644 --- a/color-module/src/schemes/mod.rs +++ b/color-module/src/schemes/mod.rs @@ -17,6 +17,7 @@ pub mod swatch_style; pub trait SchemeExport { fn output_css_variables(&self) -> String; + fn output_css_auto_scheme_variables(&self) -> String; fn output_scss_variables(&self) -> String; fn output_javascript_object(&self) -> String; } @@ -36,6 +37,7 @@ pub fn generate_material_design_3_scheme( Ok(serde_wasm_bindgen::to_value(&( scheme.clone(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) @@ -58,6 +60,7 @@ pub fn generate_material_design_2_scheme( Ok(serde_wasm_bindgen::to_value(&( scheme.clone(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) @@ -88,6 +91,7 @@ pub fn generate_q_scheme_automatically( Ok(serde_wasm_bindgen::to_value(&( scheme.clone(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) @@ -124,6 +128,7 @@ pub fn generate_q_scheme_manually( Ok(serde_wasm_bindgen::to_value(&( scheme.clone(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) @@ -139,6 +144,7 @@ pub fn generate_swatch_scheme( Ok(serde_wasm_bindgen::to_value(&( scheme.swatches(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) @@ -186,6 +192,7 @@ pub fn generate_material_design_3_dynamic_scheme( Ok(serde_wasm_bindgen::to_value(&( scheme.clone(), scheme.output_css_variables(), + scheme.output_css_auto_scheme_variables(), scheme.output_scss_variables(), scheme.output_javascript_object(), )) diff --git a/color-module/src/schemes/q_style/baseline.rs b/color-module/src/schemes/q_style/baseline.rs index 8c76345..87bbea8 100644 --- a/color-module/src/schemes/q_style/baseline.rs +++ b/color-module/src/schemes/q_style/baseline.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use palette::{ color_theory::{Analogous, Complementary, SplitComplementary, Tetradic, Triadic}, Oklch, ShiftHue, @@ -158,6 +160,37 @@ impl Baseline { variables } + pub fn to_css_auto_scheme_collection(&self) -> HashMap { + let mut collection = HashMap::new(); + + collection.extend(self.primary.to_css_auto_scheme_collection("primary")); + if let Some(secondary) = &self.secondary { + collection.extend(secondary.to_css_auto_scheme_collection("secondary")); + } + if let Some(tertiary) = &self.tertiary { + collection.extend(tertiary.to_css_auto_scheme_collection("tertiary")); + } + if let Some(accent) = &self.accent { + collection.extend(accent.to_css_auto_scheme_collection("accent")); + } + collection.extend(self.neutral.to_css_auto_scheme_collection("neutral")); + collection.extend(self.danger.to_css_auto_scheme_collection("danger")); + collection.extend(self.success.to_css_auto_scheme_collection("success")); + collection.extend(self.warning.to_css_auto_scheme_collection("warning")); + collection.extend(self.info.to_css_auto_scheme_collection("info")); + collection.extend(self.outline.to_css_auto_scheme_collection("outline")); + collection.insert( + "foreground".to_string(), + map_oklch_to_srgb_hex(&self.foreground), + ); + collection.insert( + "background".to_string(), + map_oklch_to_srgb_hex(&self.background), + ); + + collection + } + pub fn to_scss_variables(&self, prefix: &str) -> Vec { let mut variables = Vec::new(); diff --git a/color-module/src/schemes/q_style/color_set.rs b/color-module/src/schemes/q_style/color_set.rs index 2906797..845d08d 100644 --- a/color-module/src/schemes/q_style/color_set.rs +++ b/color-module/src/schemes/q_style/color_set.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use palette::{color_difference::Wcag21RelativeContrast, luma::Luma, Oklch}; use serde::{ser::SerializeStruct, Serialize}; @@ -179,6 +181,47 @@ impl ColorSet { variables } + pub fn to_css_auto_scheme_collection(&self, name: &str) -> HashMap { + let mut collection = HashMap::new(); + + collection.insert(format!("{}", name), map_oklch_to_srgb_hex(&self.root)); + collection.insert( + format!("{}-hover", name), + map_oklch_to_srgb_hex(&self.hover), + ); + collection.insert( + format!("{}-active", name), + map_oklch_to_srgb_hex(&self.active), + ); + collection.insert( + format!("{}-focus", name), + map_oklch_to_srgb_hex(&self.focus), + ); + collection.insert( + format!("{}-disabled", name), + map_oklch_to_srgb_hex(&self.disabled), + ); + collection.insert(format!("on-{}", name), map_oklch_to_srgb_hex(&self.on_root)); + collection.insert( + format!("on-{}-hover", name), + map_oklch_to_srgb_hex(&self.on_hover), + ); + collection.insert( + format!("on-{}-active", name), + map_oklch_to_srgb_hex(&self.on_active), + ); + collection.insert( + format!("on-{}-focus", name), + map_oklch_to_srgb_hex(&self.on_focus), + ); + collection.insert( + format!("on-{}-disabled", name), + map_oklch_to_srgb_hex(&self.on_disabled), + ); + + collection + } + pub fn to_scss_variables(&self, prefix: &str, name: &str) -> Vec { let mut variables = Vec::new(); diff --git a/color-module/src/schemes/q_style/mod.rs b/color-module/src/schemes/q_style/mod.rs index 908389b..808fc9d 100644 --- a/color-module/src/schemes/q_style/mod.rs +++ b/color-module/src/schemes/q_style/mod.rs @@ -1,4 +1,4 @@ -use std::str::FromStr; +use std::{collections::HashSet, str::FromStr}; use baseline::Baseline; use palette::FromColor; @@ -130,6 +130,32 @@ impl SchemeExport for QScheme { variables.join("\n") } + fn output_css_auto_scheme_variables(&self) -> String { + let mut collection = Vec::new(); + let mut keys = HashSet::new(); + let light_collection = self.light.to_css_auto_scheme_collection(); + let dark_collection = self.dark.to_css_auto_scheme_collection(); + + keys.extend(light_collection.keys()); + keys.extend(dark_collection.keys()); + for key in keys { + match (light_collection.get(key), dark_collection.get(key)) { + (Some(light), Some(dark)) => { + collection.push(format!( + "--color-{}: light-dark(#{}, #{});", + key, light, dark + )); + } + (Some(color), None) | (None, Some(color)) => { + collection.push(format!("--color-{}: #{}", key, color)); + } + (None, None) => {} + } + } + + collection.join("\n") + } + fn output_scss_variables(&self) -> String { let mut variables = Vec::new(); diff --git a/color-module/src/schemes/swatch_style/mod.rs b/color-module/src/schemes/swatch_style/mod.rs index 8fe6796..92db56e 100644 --- a/color-module/src/schemes/swatch_style/mod.rs +++ b/color-module/src/schemes/swatch_style/mod.rs @@ -1,6 +1,6 @@ use palette::FromColor; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::str::FromStr; pub use setting::SwatchSchemeSetting; @@ -93,6 +93,49 @@ impl SchemeExport for SwatchScheme { variables.join("\n") } + fn output_css_auto_scheme_variables(&self) -> String { + let mut variables = Vec::new(); + let mut keys = HashSet::new(); + let mut names = HashSet::new(); + let mut light_collections = HashMap::new(); + let mut dark_collections = HashMap::new(); + + names.extend(self.light.keys()); + names.extend(self.dark.keys()); + + for (name, swatch) in &self.light { + let collection = swatch.to_css_auto_scheme_collection(&name); + keys.extend(collection.keys().cloned()); + light_collections.insert(name.clone(), collection.clone()); + } + for (name, swatch) in &self.dark { + let collection = swatch.to_css_auto_scheme_collection(&name); + keys.extend(collection.keys().cloned()); + dark_collections.insert(name.clone(), collection.clone()); + } + + for name in names { + for key in keys.iter() { + match ( + light_collections.get(name).and_then(|lc| lc.get(key)), + dark_collections.get(name).and_then(|dc| dc.get(key)), + ) { + (Some(light), Some(dark)) => { + variables.push(format!( + "--color-{}-{}: light-dark(#{}, #{});", + name, key, light, dark + )); + } + (Some(color), None) | (None, Some(color)) => { + variables.push(format!("--color-{}-{}: #{};", name, key, color)); + } + (None, None) => {} + } + } + } + variables.join("\n") + } + fn output_scss_variables(&self) -> String { let mut variables = Vec::new(); diff --git a/color-module/src/schemes/swatch_style/swatch.rs b/color-module/src/schemes/swatch_style/swatch.rs index e90e392..8f02bb9 100644 --- a/color-module/src/schemes/swatch_style/swatch.rs +++ b/color-module/src/schemes/swatch_style/swatch.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use palette::Oklch; use crate::convert::map_oklch_to_srgb_hex; @@ -94,6 +96,17 @@ impl Swatch { variables } + pub fn to_css_auto_scheme_collection(&self, name: &str) -> HashMap { + let mut collection = HashMap::new(); + for (i, color) in self.swatch().iter().enumerate() { + collection.insert( + format!("{}-{}", name, i * 100), + map_oklch_to_srgb_hex(color), + ); + } + collection + } + pub fn to_scss_variables(&self, prefix: &str, name: &str) -> Vec { let mut variables = Vec::new(); for (i, color) in self.swatch().iter().enumerate() {