use std::collections::HashMap;
use crate::prelude::*;
#[derive(Clone, PartialEq)]
pub struct StyleConfig {
pub class_prefix: String,
pub extra_classes: Vec<String>,
pub component_overrides: HashMap<String, String>,
}
#[derive(Clone, Default)]
pub struct StyleContext {
pub config: StyleConfig,
}
impl StyleContext {
pub fn class_prefix(&self) -> String {
self.config.class_prefix.clone()
}
pub fn extra_classes_string(&self) -> String {
self.config.extra_classes.join(" ")
}
pub fn get_override_class(&self, component_name: &str) -> Option<String> {
self.config.component_overrides.get(component_name).cloned()
}
pub fn get_component_class(&self, component_name: &str, base_class: &str) -> String {
let mut classes = vec![base_class.to_string()];
if let Some(override_class) = self.get_override_class(component_name) {
classes.push(override_class);
}
classes.join(" ")
}
}
#[derive(Debug, Clone)]
pub struct StyleProviderProps {
pub class_prefix: String,
pub extra_classes: Vec<String>,
pub component_overrides: HashMap<String, String>,
pub children: Vec<VNode>,
}
impl Default for StyleProviderProps {
fn default() -> Self {
Self {
class_prefix: "hi".to_string(),
extra_classes: Vec::new(),
component_overrides: HashMap::new(),
children: Vec::new(),
}
}
}
#[allow(non_snake_case)]
pub fn StyleProvider(props: StyleProviderProps) -> VNode {
let context = StyleContext {
config: StyleConfig {
class_prefix: props.class_prefix,
extra_classes: props.extra_classes,
component_overrides: props.component_overrides,
},
};
provide_context(context.clone());
let css_vars = format!("--hi-style-class-prefix: {};", context.config.class_prefix);
let extra_classes_str = context.config.extra_classes.join(" ");
let class = format!("hi-style-provider {}", extra_classes_str);
rsx! {
div {
class: class,
style: css_vars,
..props.children
}
}
}
pub fn use_style() -> StyleContext {
consume_context()
}
pub fn try_use_style() -> Option<StyleContext> {
use_context::<StyleContext>().map(|ctx| ctx.get().clone())
}
pub fn use_component_class(component_name: &str, base_class: &str) -> String {
if let Some(ctx) = try_use_style() {
ctx.get_component_class(component_name, base_class)
} else {
base_class.to_string()
}
}
impl Default for StyleConfig {
fn default() -> Self {
Self {
class_prefix: "hi".to_string(),
extra_classes: Vec::new(),
component_overrides: HashMap::new(),
}
}
}