freya_components/
loader.rs1use freya_animation::prelude::*;
2use freya_core::prelude::*;
3use torin::size::Size;
4
5use crate::{
6 get_theme,
7 theming::component_themes::CircularLoaderThemePartial,
8};
9
10#[cfg_attr(feature = "docs",
29 doc = embed_doc_image::embed_image!("circular_loader", "images/gallery_circular_loader.png")
30)]
31#[derive(PartialEq)]
32pub struct CircularLoader {
33 pub(crate) theme: Option<CircularLoaderThemePartial>,
34 size: f32,
35 key: DiffKey,
36}
37
38impl KeyExt for CircularLoader {
39 fn write_key(&mut self) -> &mut DiffKey {
40 &mut self.key
41 }
42}
43
44impl Default for CircularLoader {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl CircularLoader {
51 pub fn new() -> Self {
52 Self {
53 size: 32.,
54 theme: None,
55 key: DiffKey::None,
56 }
57 }
58
59 pub fn size(mut self, size: f32) -> Self {
60 self.size = size;
61 self
62 }
63}
64
65impl Render for CircularLoader {
66 fn render(&self) -> impl IntoElement {
67 let theme = get_theme!(&self.theme, circular_loader);
68
69 let animation = use_animation(|conf| {
70 conf.on_creation(OnCreation::Run);
71 conf.on_finish(OnFinish::restart());
72 AnimNum::new(0.0, 360.0).time(650)
73 });
74
75 svg(Bytes::from_static(
76 r#"<svg viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg">
77 <circle class="spin" cx="300" cy="300" fill="none"
78 r="250" stroke-width="64" stroke="{color}"
79 stroke-dasharray="256 1400"
80 stroke-linecap="round" />
81 </svg>"#
82 .as_bytes(),
83 ))
84 .a11y_focusable(true)
85 .a11y_role(AccessibilityRole::ProgressIndicator)
86 .width(Size::px(self.size))
87 .height(Size::px(self.size))
88 .stroke(theme.primary_color)
89 .rotate(animation.get().value())
90 }
91
92 fn render_key(&self) -> DiffKey {
93 self.key.clone().or(self.default_key())
94 }
95}