Skip to main content

forge_charts/
lib.rs

1#![forbid(unsafe_code)]
2#![allow(
3    clippy::missing_errors_doc,
4    clippy::missing_panics_doc,
5    // Chart math: cast bounds are well below 2^53 for f64 mantissa;
6    // float comparisons in loop bounds are guarded by an epsilon; doc
7    // paragraphs in math code are intentionally long. Pedantic noise.
8    clippy::cast_possible_truncation,
9    clippy::cast_precision_loss,
10    clippy::cast_sign_loss,
11    clippy::cast_possible_wrap,
12    clippy::while_float,
13    clippy::float_cmp,
14    clippy::suboptimal_flops,
15    clippy::format_push_string,
16    clippy::doc_markdown,
17    clippy::too_long_first_doc_paragraph,
18    clippy::needless_pass_by_value,
19    clippy::module_name_repetitions
20)]
21
22//! Pure-Rust + SVG interactive charts for Leptos CSR.
23//!
24//! v0.1 ships one chart type — [`AreaChart`] — with the visual style
25//! of ApexCharts (gradient fills, soft axes, modern legend) but
26//! implemented entirely in Rust + SVG. No JS, no canvas, no Tailwind.
27//! Designed to be project-agnostic: no consumer types leak into the
28//! public API.
29//!
30//! ## Quick start
31//!
32//! ```ignore
33//! use leptos::prelude::*;
34//! use forge_charts::{AreaChart, Series, CHART_CSS};
35//!
36//! #[derive(Clone)]
37//! struct Datum { date: String, opened: u32, closed: u32 }
38//!
39//! #[component]
40//! fn MyChart(data: Signal<Vec<Datum>>) -> impl IntoView {
41//!     view! {
42//!         <Stylesheet text=CHART_CSS />
43//!         <AreaChart
44//!             data=data
45//!             x_label=|d: &Datum| d.date.clone()
46//!             y_values=|d: &Datum| vec![f64::from(d.opened), f64::from(d.closed)]
47//!             series=vec![
48//!                 Series::area("Opened", "opened"),
49//!                 Series::area("Closed", "closed"),
50//!             ]
51//!             height=320
52//!         />
53//!     }
54//! }
55//! ```
56//!
57//! ## Styling
58//!
59//! The crate ships a default stylesheet exposed as the [`CHART_CSS`]
60//! constant. Consumers inject it once via Leptos `<Stylesheet />` at
61//! the app root. CSS variables (`--charts-fg`, `--charts-grid-color`,
62//! `--charts-series-opened`, `--charts-series-closed`, …) let
63//! consumers theme without forking the stylesheet.
64//!
65//! ## Roadmap
66//!
67//! - **Phase B** (shipped): hover crosshair + consumer-provided
68//!   tooltip slot.
69//! - **Phase C** (shipped): drag-to-zoom + reset.
70//! - **Future**: Bar / Line variants, smooth Bezier curves, stacked
71//!   areas. Extract shared math when the second chart needs it.
72
73// All modules are internal implementation detail; the public surface
74// is the re-exports below. `pub(crate)` so the crate's SemVer surface
75// is the named items, not the module layout. The `unreachable_pub`
76// allow keeps the inner `pub fn` / `pub struct` markers as
77// module-local API documentation rather than forcing every item to
78// be `pub(crate)`.
79#[allow(unreachable_pub)]
80pub(crate) mod axis;
81#[allow(unreachable_pub)]
82pub(crate) mod chart;
83#[allow(unreachable_pub)]
84pub(crate) mod hover;
85#[allow(unreachable_pub)]
86pub(crate) mod path;
87#[allow(unreachable_pub)]
88pub(crate) mod scale;
89#[allow(unreachable_pub)]
90pub(crate) mod series;
91#[allow(unreachable_pub)]
92pub(crate) mod zoom;
93
94pub use chart::{AreaChart, TooltipSlot, YFormat, ZoomCommit};
95pub use hover::HoverState;
96pub use series::{Series, SeriesKind};
97pub use zoom::{MIN_ZOOM_SPAN, ZoomRange};
98
99/// Default stylesheet bundled with the crate. Inject once at the app
100/// root via `<Stylesheet text=CHART_CSS />` (Leptos meta).
101pub const CHART_CSS: &str = include_str!("charts.css");