Skip to main content

mcu_scheme/
scheme_neutral.rs

1// <FILE>crates/mcu-scheme/src/scheme_neutral.rs</FILE> - <DESC>Neutral color scheme</DESC>
2// <VERS>VERSION: 2.0.0</VERS>
3// <WCTX>Full implementation of neutral scheme wrapper</WCTX>
4// <CLOG>Implement SchemeNeutral wrapping DynamicScheme with Variant::Neutral</CLOG>
5
6use mcu_dynamiccolor::{DynamicScheme, DynamicSchemeOptions, Platform, SpecVersion, Variant};
7use mcu_hct::Hct;
8use std::ops::Deref;
9
10/// A neutral color scheme with subtle color shifts.
11///
12/// Generates a scheme that is mostly neutral with very subtle chromatic content.
13/// Best for conservative, professional designs.
14///
15/// # Example
16///
17/// ```
18/// use mcu_scheme::SchemeNeutral;
19/// use mcu_hct::Hct;
20///
21/// let source = Hct::from_int(0xFF0000FF); // Blue
22/// let scheme = SchemeNeutral::new(source, false, 0.0);
23/// assert!(!scheme.is_dark);
24/// ```
25pub struct SchemeNeutral {
26    scheme: DynamicScheme,
27}
28
29impl SchemeNeutral {
30    /// Create a new neutral scheme.
31    ///
32    /// # Arguments
33    ///
34    /// * `source_color_hct` - The source color in HCT color space
35    /// * `is_dark` - Whether to generate a dark mode scheme
36    /// * `contrast_level` - Contrast level from -1.0 (minimum) to 1.0 (maximum), 0.0 is standard
37    pub fn new(source_color_hct: Hct, is_dark: bool, contrast_level: f64) -> Self {
38        let scheme = DynamicScheme::new(DynamicSchemeOptions::new(
39            source_color_hct,
40            Variant::Neutral,
41            contrast_level,
42            is_dark,
43        ));
44        Self { scheme }
45    }
46
47    /// Create a new neutral scheme with full options.
48    ///
49    /// # Arguments
50    ///
51    /// * `source_color_hct` - The source color in HCT color space
52    /// * `is_dark` - Whether to generate a dark mode scheme
53    /// * `contrast_level` - Contrast level from -1.0 (minimum) to 1.0 (maximum), 0.0 is standard
54    /// * `platform` - Target platform (Phone or Watch)
55    /// * `spec_version` - Design spec version (2021 or 2025)
56    pub fn with_options(
57        source_color_hct: Hct,
58        is_dark: bool,
59        contrast_level: f64,
60        platform: Platform,
61        spec_version: SpecVersion,
62    ) -> Self {
63        let mut options =
64            DynamicSchemeOptions::new(source_color_hct, Variant::Neutral, contrast_level, is_dark);
65        options.platform = Some(platform);
66        options.spec_version = Some(spec_version);
67        Self {
68            scheme: DynamicScheme::new(options),
69        }
70    }
71}
72
73impl Deref for SchemeNeutral {
74    type Target = DynamicScheme;
75
76    fn deref(&self) -> &Self::Target {
77        &self.scheme
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_new_light_mode() {
87        let source = Hct::from_int(0xFF0000FF);
88        let scheme = SchemeNeutral::new(source, false, 0.0);
89
90        assert_eq!(scheme.variant, Variant::Neutral);
91        assert!(!scheme.is_dark);
92        assert_eq!(scheme.contrast_level, 0.0);
93    }
94
95    #[test]
96    fn test_new_dark_mode() {
97        let source = Hct::from_int(0xFF0000FF);
98        let scheme = SchemeNeutral::new(source, true, 0.0);
99
100        assert_eq!(scheme.variant, Variant::Neutral);
101        assert!(scheme.is_dark);
102    }
103
104    #[test]
105    fn test_contrast_levels() {
106        let source = Hct::from_int(0xFF0000FF);
107
108        let low = SchemeNeutral::new(source, false, -1.0);
109        assert_eq!(low.contrast_level, -1.0);
110
111        let high = SchemeNeutral::new(source, false, 1.0);
112        assert_eq!(high.contrast_level, 1.0);
113    }
114
115    #[test]
116    fn test_with_options() {
117        let source = Hct::from_int(0xFF0000FF);
118        let scheme =
119            SchemeNeutral::with_options(source, true, 0.5, Platform::Watch, SpecVersion::Spec2025);
120
121        assert_eq!(scheme.variant, Variant::Neutral);
122        assert!(scheme.is_dark);
123        assert_eq!(scheme.contrast_level, 0.5);
124        assert_eq!(scheme.platform, Platform::Watch);
125        assert_eq!(scheme.spec_version, SpecVersion::Spec2025);
126    }
127
128    #[test]
129    fn test_deref_access() {
130        let source = Hct::from_int(0xFF0000FF);
131        let scheme = SchemeNeutral::new(source, false, 0.0);
132
133        // Access DynamicScheme fields through Deref
134        let _primary = &scheme.primary_palette;
135        let _secondary = &scheme.secondary_palette;
136        let _argb = scheme.source_color_argb;
137    }
138}
139
140// <FILE>crates/mcu-scheme/src/scheme_neutral.rs</FILE> - <DESC>Neutral color scheme</DESC>
141// <VERS>END OF VERSION: 2.0.0</VERS>