dioxus_document/elements/
style.rs1use super::*;
2use crate::document;
3use dioxus_core::{use_hook, VNode};
4use dioxus_html as dioxus_elements;
5
6#[non_exhaustive]
7#[derive(Clone, Props, PartialEq)]
8pub struct StyleProps {
9 pub href: Option<String>,
11 pub media: Option<String>,
12 pub nonce: Option<String>,
13 pub title: Option<String>,
14 pub children: Element,
16 #[props(extends = style, extends = GlobalAttributes)]
17 pub additional_attributes: Vec<Attribute>,
18}
19
20impl StyleProps {
21 pub fn attributes(&self) -> Vec<(&'static str, String)> {
23 let mut attributes = Vec::new();
24 extend_attributes(&mut attributes, &self.additional_attributes);
25 if let Some(href) = &self.href {
26 attributes.push(("href", href.clone()));
27 }
28 if let Some(media) = &self.media {
29 attributes.push(("media", media.clone()));
30 }
31 if let Some(nonce) = &self.nonce {
32 attributes.push(("nonce", nonce.clone()));
33 }
34 if let Some(title) = &self.title {
35 attributes.push(("title", title.clone()));
36 }
37 attributes
38 }
39
40 pub fn style_contents(&self) -> Result<String, ExtractSingleTextNodeError<'_>> {
41 extract_single_text_node(&self.children)
42 }
43}
44
45#[component]
77pub fn Style(props: StyleProps) -> Element {
78 use_update_warning(&props, "Style {}");
79
80 use_hook(|| {
81 let document = document();
82 let mut insert_style = document.create_head_component();
83 if let Some(href) = &props.href {
84 if !should_insert_style(href) {
85 insert_style = false;
86 }
87 }
88 if !insert_style {
89 return;
90 }
91 let mut attributes = props.attributes();
92 match (&props.href, props.style_contents()) {
93 (_, Ok(_)) => document.create_style(props),
95 (Some(_), _) => {
97 attributes.push(("type", "text/css".into()));
98 attributes.push(("rel", "stylesheet".into()));
99 document.create_link(LinkProps {
100 media: props.media,
101 title: props.title,
102 r#type: Some("text/css".to_string()),
103 additional_attributes: props.additional_attributes,
104 href: props.href,
105 rel: Some("stylesheet".to_string()),
106 disabled: None,
107 r#as: None,
108 sizes: None,
109 crossorigin: None,
110 referrerpolicy: None,
111 fetchpriority: None,
112 hreflang: None,
113 integrity: None,
114 blocking: None,
115 onload: None,
116 });
117 }
118 (None, Err(err)) => err.log("Style"),
120 };
121 });
122
123 VNode::empty()
124}
125
126#[derive(Default, Clone)]
127struct StyleContext(DeduplicationContext);
128
129fn should_insert_style(href: &str) -> bool {
130 get_or_insert_root_context::<StyleContext>()
131 .0
132 .should_insert(href)
133}