detaxine_charts/lib.rs
1//! # Detaxine Charts
2//!
3//! `detaxine-charts` is a high-performance, canvas-based charting library for
4//! [Leptos](https://leptos.dev). Every chart is responsive by default, supports
5//! tooltips on hover, and redraws automatically on window resize.
6//!
7//! ## Available Charts
8//!
9//! | Component | Description |
10//! |---|---|
11//! | [`BarChart`] | Vertical bar chart with configurable colors |
12//! | [`PieChart`] | Classic pie chart with hit-tested hover tooltips |
13//! | [`DoughnutChart`] | Pie chart with a hollow center |
14//! | [`LineCurveChart`] | Multi-series line chart with optional bezier curves and area fill |
15//! | [`CandlestickChart`] | OHLC candlestick chart with zoom and pan |
16//!
17//!
18//! ## Live Demo
19//!
20//! [https://elonaire.github.io/detaxine-charts/](https://elonaire.github.io/detaxine-charts/)
21//!
22//! ## Usage
23//!
24//! Add the crate to your `Cargo.toml`:
25//!
26//! ```toml
27//! [dependencies]
28//! detaxine-charts = "0.8.22"
29//! ```
30//!
31//! Each chart is behind a feature flag so you only compile what you need:
32//!
33//! ```toml
34//! [dependencies]
35//! detaxine-charts = { version = "0.8.22", features = ["BarChart", "LineCurveChart"] }
36//! ```
37//!
38//! Available features: `BarChart`, `PieChart`, `DoughnutChart`, `LineCurveChart`, `CandlestickChart`.
39//! Omitting features entirely enables all charts.
40//!
41//! ## Quick Start
42//!
43//! ```rust
44//! use leptos::prelude::*;
45//! use detaxine_charts::{bar_chart::{BarChart, BarChartConfig, DataPoint}, use_chart_data};
46//!
47//! #[component]
48//! fn App() -> impl IntoView {
49//! view! {
50//! <BarChart
51//! data=use_chart_data(vec![
52//! DataPoint::new("Jan", 120),
53//! DataPoint::new("Feb", 85),
54//! DataPoint::new("Mar", 200),
55//! ]).signal()
56//! config=BarChartConfig::new("#4f46e5", "#e5e7eb", "#111827")
57//! />
58//! }
59//! }
60//! ```
61//!
62//! ## Chart Examples
63//!
64//! ### [`BarChart`]
65//!
66//! ```rust
67//! use leptos::prelude::*;
68//! use detaxine_charts::{bar_chart::{BarChart, BarChartConfig, DataPoint}, use_chart_data};
69//!
70//! #[component]
71//! fn MyBarChart() -> impl IntoView {
72//! view! {
73//! <BarChart
74//! data=use_chart_data(vec![
75//! DataPoint::new("Q1", 42000),
76//! DataPoint::new("Q2", 58000),
77//! DataPoint::new("Q3", 51000),
78//! DataPoint::new("Q4", 73000),
79//! ]).signal()
80//! config=BarChartConfig::new("#4f46e5", "#e5e7eb", "#111827")
81//! />
82//! }
83//! }
84//! ```
85//!
86//! ### [`PieChart`]
87//!
88//! ```rust
89//! use leptos::prelude::*;
90//! use detaxine_charts::{pie_chart::{PieChart, PieChartConfig, DataPoint}, use_chart_data};
91//!
92//! #[component]
93//! fn MyPieChart() -> impl IntoView {
94//! view! {
95//! <PieChart
96//! data=use_chart_data(vec![
97//! DataPoint::new("Housing", 35, "#4f46e5"),
98//! DataPoint::new("Food", 20, "#e11d48"),
99//! DataPoint::new("Transport", 15, "#0891b2"),
100//! DataPoint::new("Savings", 8, "#9333ea"),
101//! ]).signal()
102//! config=PieChartConfig { show_legend: true }
103//! />
104//! }
105//! }
106//! ```
107//!
108//! ### [`DoughnutChart`]
109//!
110//! ```rust
111//! use leptos::prelude::*;
112//! use detaxine_charts::{doughnut_chart::{DoughnutChart, DoughnutChartConfig}, use_chart_data};
113//!
114//! #[component]
115//! fn MyDoughnutChart() -> impl IntoView {
116//! view! {
117//! <DoughnutChart
118//! data=use_chart_data(vec![
119//! ("Housing".to_string(), 35, "#4f46e5".to_string()),
120//! ("Food".to_string(), 20, "#e11d48".to_string()),
121//! ("Transport".to_string(), 15, "#0891b2".to_string()),
122//! ("Savings".to_string(), 8, "#9333ea".to_string()),
123//! ]).signal()
124//! config=DoughnutChartConfig { show_legend: true }
125//! />
126//! }
127//! }
128//! ```
129//!
130//! ### [`LineCurveChart`]
131//!
132//! ```rust
133//! use leptos::prelude::*;
134//! use detaxine_charts::{line_chart::{LineCurveChart, LineCurveChartConfig, DataPoint, Series}, use_chart_data};
135//!
136//! #[component]
137//! fn MyLineChart() -> impl IntoView {
138//! view! {
139//! <LineCurveChart
140//! data=use_chart_data(vec![
141//! (
142//! Series::new("Revenue", "#4f46e5"),
143//! vec![
144//! DataPoint::new(120),
145//! DataPoint::new(85),
146//! DataPoint::new(200),
147//! DataPoint::new(150),
148//! ],
149//! ),
150//! (
151//! Series::new("Expenses", "#e11d48"),
152//! vec![
153//! DataPoint::new(80),
154//! DataPoint::new(90),
155//! DataPoint::new(110),
156//! DataPoint::new(95),
157//! ],
158//! ),
159//! ]).signal()
160//! x=use_chart_data(vec![
161//! "Jan".to_string(), "Feb".to_string(),
162//! "Mar".to_string(), "Apr".to_string(),
163//! ]).signal()
164//! config=LineCurveChartConfig {
165//! show_area_chart: true,
166//! x_axis_title: "Month".to_string(),
167//! y_axis_title: "Amount ($)".to_string(),
168//! ..Default::default()
169//! }
170//! />
171//! }
172//! }
173//! ```
174//!
175//! ### [`CandlestickChart`]
176//!
177//! ```rust
178//! use leptos::prelude::*;
179//! use detaxine_charts::{candlestick_chart::{CandlestickChart, CandlestickChartConfig, Candle}, use_chart_data};
180//!
181//! #[component]
182//! fn MyCandlestickChart() -> impl IntoView {
183//! view! {
184//! <CandlestickChart
185//! data=use_chart_data(vec![
186//! Candle::new("Mon", 172.30, 174.50, 170.80, 173.20),
187//! Candle::new("Tue", 173.20, 176.80, 172.50, 176.10),
188//! Candle::new("Wed", 176.10, 177.30, 173.40, 174.00),
189//! Candle::new("Thu", 174.00, 175.20, 171.60, 172.10),
190//! Candle::new("Fri", 172.10, 173.80, 169.90, 170.50),
191//! ]).signal()
192//! config=CandlestickChartConfig {
193//! bullish_color: "#16a34a".to_string(),
194//! bearish_color: "#e11d48".to_string(),
195//! wick_color: "#6b7280".to_string(),
196//! show_grid: true,
197//! }
198//! />
199//! }
200//! }
201//! ```
202//!
203//! ## Design Notes
204//!
205//! - **Canvas-based rendering** - all charts draw to an HTML5 `<canvas>` element
206//! via `web_sys`, giving full control over pixel output with no DOM overhead.
207//! - **Device pixel ratio aware** - canvases are scaled by `window.devicePixelRatio`
208//! so charts are sharp on HiDPI and Retina displays.
209//! - **Responsive** - each chart listens for `window.resize` and redraws to fit
210//! its parent container width automatically.
211//! - **HTML tooltip overlay** - tooltips are absolutely positioned `<div>` elements
212//! rather than canvas-drawn text, making them easy to style with CSS.
213//! - **Geometry-driven hit testing** - after each draw, shape positions are stored
214//! in a [`StoredValue`](leptos::StoredValue) and used for precise mouse hit
215//! detection on hover.
216
217pub mod charts;
218pub mod utils;
219
220pub use utils::hooks::use_chart_data::use_chart_data;
221
222#[cfg(feature = "BarChart")]
223pub use charts::bar_chart::bar_chart;
224#[cfg(feature = "CandlestickChart")]
225pub use charts::candlestick_chart::candlestick_chart;
226#[cfg(feature = "DoughnutChart")]
227pub use charts::doughnut_chart::doughnut_chart;
228#[cfg(feature = "LineCurveChart")]
229pub use charts::line_chart::line_chart;
230#[cfg(feature = "PieChart")]
231pub use charts::pie_chart::pie_chart;