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