perspective_viewer/components/style/style_provider.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
use web_sys::HtmlStyleElement;
use yew::prelude::*;
use yew::virtual_dom::VNode;
use super::style_cache::StyleCache;
#[derive(Properties, PartialEq)]
pub struct StyleProviderProps {
#[prop_or(true)]
pub is_shadow: bool,
pub children: Children,
}
/// A context which injects any CSS snippet registered within its tree, doing
/// so only once for each unqiue snippet name.
///
/// CSS can be registered within sub-components via the `<LocalStyle>` component
/// and `css!()` resource inlining macro.
pub struct StyleProvider {
cache: StyleCache,
}
impl Component for StyleProvider {
type Message = ();
type Properties = StyleProviderProps;
fn create(ctx: &Context<Self>) -> Self {
let cache = StyleCache::new(ctx.props().is_shadow);
Self { cache }
}
fn view(&self, ctx: &Context<Self>) -> Html {
let styles = self.cache.iter_styles();
html! {
<>
{ for styles.map(|x| {
html! {
<StyleKeyed key={ x.0 } elem={ x.1 } />
}
}) }
<ContextProvider<StyleCache> context={self.cache.clone()}>
{ for ctx.props().children.iter() }
</ContextProvider<StyleCache>>
</>
}
}
}
#[derive(Properties, PartialEq)]
struct StyleKeyedProps {
elem: HtmlStyleElement,
}
/// Necessary only to attach `key` to individual `HtmlStylElement` children,
/// as `yew` does not calculate list updates correctly for sequences of these
/// without keys.
#[function_component(StyleKeyed)]
fn style_renderer(props: &StyleKeyedProps) -> Html {
VNode::VRef(props.elem.clone().into())
}