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