chart_js_rs/
lib.rs

1#![allow(non_snake_case)]
2#![doc = include_str!("../README.md")]
3
4pub mod bar;
5pub mod coordinate;
6pub mod doughnut;
7pub mod exports;
8pub mod functions;
9pub mod objects;
10pub mod pie;
11pub mod scatter;
12pub mod traits;
13
14#[cfg(feature = "workers")]
15pub mod worker;
16
17pub use objects::*;
18pub use traits::*;
19pub use utils::*;
20
21#[cfg(feature = "workers")]
22pub use worker_chart::*;
23
24#[doc(hidden)]
25mod utils;
26
27use exports::get_chart;
28use gloo_utils::format::JsValueSerdeExt;
29use serde::{de::DeserializeOwned, Serialize};
30
31#[cfg(feature = "workers")]
32use wasm_bindgen::{self, prelude::*};
33
34#[cfg(feature = "workers")]
35use web_sys::WorkerGlobalScope;
36
37pub trait ChartExt: DeserializeOwned + Serialize + Default {
38    type DS;
39
40    fn new(id: impl AsRef<str>) -> Self {
41        Self::default().id(id.as_ref().into())
42    }
43
44    fn get_id(&self) -> &str;
45    fn id(self, id: String) -> Self;
46
47    fn get_data(&mut self) -> &mut Self::DS;
48    fn data(mut self, data: impl Into<Self::DS>) -> Self {
49        *self.get_data() = data.into();
50        self
51    }
52
53    fn get_options(&mut self) -> &mut ChartOptions;
54    fn options(mut self, options: impl Into<ChartOptions>) -> Self {
55        *self.get_options() = options.into();
56        self
57    }
58
59    fn into_chart(self) -> Chart {
60        Chart {
61            obj: <::wasm_bindgen::JsValue as JsValueSerdeExt>::from_serde(&self)
62                .expect("Unable to serialize chart."),
63            id: self.get_id().into(),
64            mutate: false,
65            plugins: String::new(),
66            defaults: String::new(),
67        }
68    }
69
70    fn get_chart_from_id(id: &str) -> Option<Self> {
71        let chart = get_chart(id);
72
73        serde_wasm_bindgen::from_value(chart)
74            .inspect_err(|e| {
75                gloo_console::error!(e.to_string());
76            })
77            .ok()
78    }
79}
80
81#[cfg(feature = "workers")]
82pub fn is_worker() -> bool {
83    js_sys::global().dyn_into::<WorkerGlobalScope>().is_ok()
84}
85
86#[cfg(feature = "workers")]
87mod worker_chart {
88    use crate::*;
89
90    pub trait WorkerChartExt: ChartExt {
91        #[allow(async_fn_in_trait)]
92        async fn into_worker_chart(
93            self,
94            imports_block: &str,
95        ) -> Result<WorkerChart, Box<dyn std::error::Error>> {
96            Ok(WorkerChart {
97                obj: <::wasm_bindgen::JsValue as JsValueSerdeExt>::from_serde(&self)
98                    .expect("Unable to serialize chart."),
99                id: self.get_id().into(),
100                mutate: false,
101                plugins: String::new(),
102                defaults: String::new(),
103                worker: crate::worker::ChartWorker::new(imports_block).await?,
104            })
105        }
106    }
107    #[wasm_bindgen]
108    #[derive(Clone)]
109    #[must_use = "\nAppend .render_async()\n"]
110    pub struct WorkerChart {
111        pub(crate) obj: JsValue,
112        pub(crate) id: String,
113        pub(crate) mutate: bool,
114        pub(crate) plugins: String,
115        pub(crate) defaults: String,
116        pub(crate) worker: crate::worker::ChartWorker,
117    }
118    impl WorkerChart {
119        pub async fn render_async(self) -> Result<(), Box<dyn std::error::Error>> {
120            self.worker
121                .render(self.obj, &self.id, self.mutate, self.plugins, self.defaults)
122                .await
123        }
124
125        pub async fn update_async(self, animate: bool) -> Result<bool, Box<dyn std::error::Error>> {
126            self.worker.update(self.obj, &self.id, animate).await
127        }
128
129        #[must_use = "\nAppend .render_async()\n"]
130        pub fn mutate(&mut self) -> Self {
131            self.mutate = true;
132            self.clone()
133        }
134
135        #[must_use = "\nAppend .render_async()\n"]
136        pub fn plugins(&mut self, plugins: impl Into<String>) -> Self {
137            self.plugins = plugins.into();
138            self.clone()
139        }
140
141        #[must_use = "\nAppend .render_async()\n"]
142        pub fn defaults(&mut self, defaults: impl Into<String>) -> Self {
143            self.defaults = format!("{}\n{}", self.defaults, defaults.into());
144            self.to_owned()
145        }
146    }
147}