stylist/yew/
mod.rs

1//! This module contains yew specific features.
2//!
3//! ## Usage in function components
4//!
5//! You can create a style and use it like this:
6//!
7//! ```rust
8//! use stylist::yew::use_style;
9//! use yew::prelude::*;
10//!
11//! #[function_component]
12//! fn MyStyledComponent() -> Html {
13//!     let style = use_style!("color: red;");
14//!     html! {<div class={style}>{"Hello World!"}</div>}
15//! }
16//! ```
17
18use yew::html::{Classes, IntoPropValue};
19
20/// A procedural macro to style a function component.
21///
22/// Specifically this introduces a specialized [`css!`](crate::css) macro
23/// that is aware of the contextual style manager.
24///
25/// For detailed arguments and usage see also the underlying
26/// [`function_component`](::yew::function_component) attribute in Yew.
27///
28/// # Example:
29///
30/// ```rust
31/// use std::borrow::Cow;
32///
33/// use stylist::yew::styled_component;
34/// use yew::prelude::*;
35///
36/// #[styled_component]
37/// fn MyStyledComponent() -> Html {
38///     html! {<div class={css!("color: red;")}>{"Hello World!"}</div>}
39/// }
40/// ```
41///
42/// # Note:
43///
44/// You don't need to import [`css!`](crate::css) inside of a `styled_component`.
45#[cfg(feature = "macros")]
46pub use stylist_macros::styled_component;
47
48/// A procedural macro to use a specialized, contextual [`css!`](crate::css) macro.
49///
50/// [`styled_component`] is implemented in terms of this, prefer that if possible.
51/// If you need to use [`function_component`](::yew::function_component) directly
52/// but still inject the contextual `css!` macro, use this.
53///
54/// You can also use the attribute on functions that have access to [Hooks] to enable
55/// the usage of a contextual `css!` in their body.
56///
57/// # Example:
58///
59/// ```rust
60/// use stylist::yew::styled_component_impl;
61/// use yew::prelude::*;
62///
63/// // Equivalent to #[styled_component(MyStyledComponent)]
64/// // This usage is discouraged, prefer `styled_component`
65/// #[styled_component_impl]
66/// #[function_component(MyStyledComponent)]
67/// fn my_styled_component() -> Html {
68///     html! {<div class={css!("color: red;")}>{"Hello World!"}</div>}
69/// }
70/// ```
71///
72/// [Hooks]: https://yew.rs/next/concepts/function-components#hooks
73#[cfg(feature = "macros")]
74pub use stylist_macros::styled_component_impl;
75
76/// A procedural macro hook that parses a string literal or an inline stylesheet to create auto
77/// updating [`Style`]s.
78///
79/// Please consult the documentation of the [`macros`](crate::macros) module for the supported
80/// syntax of this macro.
81///
82/// # Example
83///
84/// ```
85/// use stylist::yew::use_style;
86/// use yew::prelude::*;
87///
88/// #[function_component(Comp)]
89/// fn comp() -> Html {
90///     // Returns a Style instance.
91///     let style = use_style!("color: red;");
92///     html! {<div class={style}>{"Hello world!"}</div>}
93/// }
94/// ```
95#[cfg(feature = "yew_use_style")]
96pub use stylist_macros::use_style;
97
98use crate::ast::Sheet;
99use crate::manager::StyleManager;
100use crate::{Style, StyleSource};
101
102use yew::html::ImplicitClone;
103
104impl ImplicitClone for StyleManager {}
105
106mod global;
107mod hooks;
108mod provider;
109
110pub use global::{Global, GlobalProps};
111pub use provider::{ManagerProvider, ManagerProviderProps};
112
113pub use hooks::*;
114
115impl From<Style> for Classes {
116    fn from(style: Style) -> Self {
117        let mut classes = Self::new();
118        classes.push(style.get_class_name().to_string());
119        classes
120    }
121}
122
123impl From<StyleSource> for Classes {
124    fn from(style_src: StyleSource) -> Self {
125        let mut classes = Self::new();
126        #[cfg(all(debug_assertions, feature = "debug_style_locations"))]
127        let location = style_src.location.clone();
128        let style = style_src.into_style();
129        classes.push(style.get_class_name().to_string());
130        #[cfg(all(debug_assertions, feature = "debug_style_locations"))]
131        classes.push(location);
132        classes
133    }
134}
135
136impl IntoPropValue<Classes> for Style {
137    fn into_prop_value(self) -> Classes {
138        self.into()
139    }
140}
141
142impl IntoPropValue<Classes> for StyleSource {
143    fn into_prop_value(self) -> Classes {
144        self.into()
145    }
146}
147
148impl IntoPropValue<StyleSource> for Sheet {
149    fn into_prop_value(self) -> StyleSource {
150        self.into()
151    }
152}
153
154#[cfg_attr(documenting, doc(cfg(feature = "parser")))]
155#[cfg(feature = "parser")]
156mod feat_parser {
157    use std::borrow::Cow;
158
159    use super::*;
160    use stylist_core::ResultDisplay;
161
162    impl IntoPropValue<StyleSource> for String {
163        fn into_prop_value(self) -> StyleSource {
164            self.try_into()
165                .expect_display("couldn't parse style string")
166        }
167    }
168
169    impl<'a> IntoPropValue<StyleSource> for &'a str {
170        fn into_prop_value(self) -> StyleSource {
171            self.try_into()
172                .expect_display("couldn't parse style string")
173        }
174    }
175
176    impl<'a> IntoPropValue<StyleSource> for Cow<'a, str> {
177        fn into_prop_value(self) -> StyleSource {
178            self.try_into()
179                .expect_display("couldn't parse style string")
180        }
181    }
182}