diff --git a/color-module/src/lib.rs b/color-module/src/lib.rs index 9e81756..73fb211 100644 --- a/color-module/src/lib.rs +++ b/color-module/src/lib.rs @@ -1,10 +1,10 @@ use std::str::FromStr; use palette::{ + FromColor, Hsl, IntoColor, IsWithinBounds, Lab, Oklch, Srgb, cam16::{Cam16Jch, Parameters}, color_difference::Wcag21RelativeContrast, convert::FromColorUnclamped, - FromColor, Hsl, IntoColor, IsWithinBounds, Lab, Oklch, Srgb, }; use wasm_bindgen::prelude::*; @@ -14,6 +14,7 @@ mod color_differ; mod color_shifting; mod convert; mod errors; +mod foreign_serializer; mod palettes; mod reversing; mod schemes; @@ -139,10 +140,6 @@ pub fn wacg_relative_contrast(fg_color: &str, bg_color: &str) -> Result { - if $s { - $a - } else { - $b - } + if $s { $a } else { $b } }; } diff --git a/color-module/src/schemes/mod.rs b/color-module/src/schemes/mod.rs index f710f68..324ece0 100644 --- a/color-module/src/schemes/mod.rs +++ b/color-module/src/schemes/mod.rs @@ -1,11 +1,12 @@ use std::collections::HashMap; +use internment::Intern; use material_design_2::MaterialDesign2Scheme; use material_design_3::MaterialDesign3Scheme; -use material_design_3_dynamic::{build_baseline, build_dynamic_scheme, build_swatches, Variant}; +use material_design_3_dynamic::{Variant, build_baseline, build_dynamic_scheme, build_swatches}; use q_style::{QScheme, SchemeSetting}; use swatch_style::{SwatchEntry, SwatchSchemeSetting}; -use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use wasm_bindgen::{JsValue, prelude::wasm_bindgen}; use crate::{errors, schemes::q_style_2::QScheme2}; @@ -23,6 +24,10 @@ pub trait SchemeExport { fn output_javascript_object(&self) -> String; } +pub fn get_static_str(s: &str) -> &'static str { + Intern::new(s.to_string()).as_ref() +} + #[wasm_bindgen] pub fn generate_material_design_3_scheme( source_color: &str, diff --git a/color-module/src/schemes/q_style_2/baseline.rs b/color-module/src/schemes/q_style_2/baseline.rs index 9aa5a23..a3fee09 100644 --- a/color-module/src/schemes/q_style_2/baseline.rs +++ b/color-module/src/schemes/q_style_2/baseline.rs @@ -5,7 +5,7 @@ use palette::{ Oklch, ShiftHue, color_theory::{Analogous, Complementary, SplitComplementary, Tetradic, Triadic}, }; -use serde::{Serialize, ser::SerializeStruct}; +use serde::Serialize; use crate::{ convert::map_oklch_to_srgb_hex, @@ -16,7 +16,8 @@ use crate::{ }, }; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] pub struct ColorUnit { pub root: ColorSet, pub surface: ColorSet, @@ -82,20 +83,8 @@ impl ColorUnit { } } -impl Serialize for ColorUnit { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_struct("ColorUnit", 3)?; - state.serialize_field("root", &self.root)?; - state.serialize_field("surface", &self.surface)?; - state.serialize_field("swatch", &self.swatch)?; - state.end() - } -} - -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] pub struct Baseline { pub primary: ColorUnit, pub secondary: Option, @@ -105,18 +94,26 @@ pub struct Baseline { pub neutral_variant: ColorSet, pub surface: ColorSet, pub surface_variant: ColorSet, + #[serde(serialize_with = "crate::schemes::q_style_2::swatch::serialize_neutral_swatch")] pub neutral_swatch: Arc, pub danger: ColorUnit, pub success: ColorUnit, pub warn: ColorUnit, pub info: ColorUnit, pub custom_colors: HashMap, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub shadow: Oklch, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub overlay: Oklch, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub outline: Oklch, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub outline_variant: Oklch, + #[serde(skip)] pub neutral_lightness: f32, + #[serde(skip)] pub scheme_settings: Arc, + #[serde(skip)] pub is_dark: bool, } @@ -514,35 +511,3 @@ impl Baseline { javascript_fields } } - -impl Serialize for Baseline { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_struct("Baseline", 17)?; - - state.serialize_field("primary", &self.primary)?; - state.serialize_field("secondary", &self.secondary)?; - state.serialize_field("tertiary", &self.tertiary)?; - state.serialize_field("accent", &self.accent)?; - state.serialize_field("neutral", &self.neutral)?; - state.serialize_field("neutralVariant", &self.neutral_variant)?; - state.serialize_field("surface", &self.surface)?; - state.serialize_field("surfaceVariant", &self.surface_variant)?; - state.serialize_field("danger", &self.danger)?; - state.serialize_field("success", &self.success)?; - state.serialize_field("warn", &self.warn)?; - state.serialize_field("info", &self.info)?; - state.serialize_field("shadow", &map_oklch_to_srgb_hex(&self.shadow))?; - state.serialize_field("overlay", &map_oklch_to_srgb_hex(&self.overlay))?; - state.serialize_field("outline", &map_oklch_to_srgb_hex(&self.outline))?; - state.serialize_field( - "outlineVariant", - &map_oklch_to_srgb_hex(&self.outline_variant), - )?; - state.serialize_field("custom", &self.custom_colors)?; - - state.end() - } -} diff --git a/color-module/src/schemes/q_style_2/color_set.rs b/color-module/src/schemes/q_style_2/color_set.rs index ac23825..8589e9c 100644 --- a/color-module/src/schemes/q_style_2/color_set.rs +++ b/color-module/src/schemes/q_style_2/color_set.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use linked_hash_map::LinkedHashMap; use palette::{Oklch, color_difference::Wcag21RelativeContrast, luma::Luma}; -use serde::{Serialize, ser::SerializeStruct}; +use serde::Serialize; use crate::{ convert::{map_oklch_to_luma, map_oklch_to_srgb_hex}, @@ -13,17 +13,28 @@ use crate::{ }, }; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] pub struct ColorSet { + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub root: Oklch, + #[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, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub on_root: Oklch, + #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")] pub on_disabled: Oklch, + #[serde(skip)] pub neutral_swatch: Arc, + #[serde(skip)] pub neutral_lightness: f32, + #[serde(skip)] pub scheme_settings: Arc, } @@ -266,28 +277,3 @@ impl ColorSet { variables } } - -impl Serialize for ColorSet { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let root = map_oklch_to_srgb_hex(&self.root); - let hover = map_oklch_to_srgb_hex(&self.hover); - let active = map_oklch_to_srgb_hex(&self.active); - let focus = map_oklch_to_srgb_hex(&self.focus); - let disabled = map_oklch_to_srgb_hex(&self.disabled); - let on_root = map_oklch_to_srgb_hex(&self.on_root); - let on_disabled = map_oklch_to_srgb_hex(&self.on_disabled); - - let mut state = serializer.serialize_struct("ColorSet", 6)?; - state.serialize_field("root", &root)?; - state.serialize_field("hover", &hover)?; - state.serialize_field("active", &active)?; - state.serialize_field("focus", &focus)?; - state.serialize_field("disabled", &disabled)?; - state.serialize_field("onRoot", &on_root)?; - state.serialize_field("onDisabled", &on_disabled)?; - state.end() - } -} diff --git a/color-module/src/schemes/q_style_2/mod.rs b/color-module/src/schemes/q_style_2/mod.rs index feacded..b74ad80 100644 --- a/color-module/src/schemes/q_style_2/mod.rs +++ b/color-module/src/schemes/q_style_2/mod.rs @@ -6,7 +6,7 @@ use serde::Serialize; use crate::{ errors, parse_option_to_oklch, parse_to_oklch, - schemes::{q_style::SchemeSetting, q_style_2::baseline::Baseline, SchemeExport}, + schemes::{SchemeExport, q_style::SchemeSetting, q_style_2::baseline::Baseline}, }; mod baseline; diff --git a/color-module/src/schemes/q_style_2/swatch.rs b/color-module/src/schemes/q_style_2/swatch.rs index ce906af..dd0806a 100644 --- a/color-module/src/schemes/q_style_2/swatch.rs +++ b/color-module/src/schemes/q_style_2/swatch.rs @@ -1,9 +1,13 @@ -use internment::Intern; +use std::sync::Arc; + use linked_hash_map::LinkedHashMap; use palette::Oklch; -use serde::{Serialize, ser::SerializeStruct}; +use serde::{Serialize, Serializer, ser::SerializeStruct}; -use crate::convert::map_oklch_to_srgb_hex; +use crate::{ + convert::map_oklch_to_srgb_hex, + schemes::{get_static_str, q_style::NeutralSwatch}, +}; static SWATCH_LIGHTINGS: [u8; 16] = [ 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 75, 80, 85, 90, 95, 98, @@ -77,10 +81,6 @@ impl Swatch { } } -fn get_static_str(s: &str) -> &'static str { - Intern::new(s.to_string()).as_ref() -} - impl Serialize for Swatch { fn serialize(&self, serializer: S) -> Result where @@ -97,3 +97,23 @@ impl Serialize for Swatch { state.end() } } + +pub fn serialize_neutral_swatch( + swatch: &Arc, + serailizer: S, +) -> Result +where + S: Serializer, +{ + let swatch = swatch.clone(); + let mut swatch_struct = serailizer.serialize_struct("NeutralSwatch", SWATCH_LIGHTINGS.len())?; + + for l in SWATCH_LIGHTINGS { + let color = swatch.get((l as f32) / 100.0); + let color = map_oklch_to_srgb_hex(&color); + let key: &'static str = get_static_str(&format!("{l:02}")); + swatch_struct.serialize_field(key, &color)?; + } + + swatch_struct.end() +}