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