Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
cfa4a46
feat: upgrade bundled plotly.js from 3.6.0 to 3.7.0
jqnatividad Jul 11, 2026
55a176b
chore(examples): pin plotly.js CDN links to 3.7.0
jqnatividad Jul 11, 2026
946d9de
refactor(traces): consolidate Selection/SelectionMarker into common
jqnatividad Jul 11, 2026
820896d
feat(traces): backfill legendrank/legendwidth/uirevision + grouping
jqnatividad Jul 11, 2026
b279955
feat(traces): backfill selection styling and zorder on cartesian traces
jqnatividad Jul 11, 2026
026165d
feat(traces): backfill date-axis period positioning attributes
jqnatividad Jul 11, 2026
2cc80db
feat(traces): add fillpattern and fillgradient to Scatter
jqnatividad Jul 11, 2026
119d330
docs(changelog): expand trace attribute backfill entry
jqnatividad Jul 11, 2026
a8c903d
fix(backfill): add legendrank/legendwidth to Sunburst, Treemap, Table
jqnatividad Jul 11, 2026
3c7fe38
docs(changelog): fill in backfill PR number (#421)
jqnatividad Jul 11, 2026
078b139
feat(traces): add Indicator, Histogram2d, Icicle trace types + layout…
jqnatividad Jul 11, 2026
c62820d
feat(indicator): expand GaugeAxis to full gauge.axis schema coverage
jqnatividad Jul 11, 2026
ef4cbca
fix(histogram2d): document z as 1D aggregation data, not a matrix
jqnatividad Jul 11, 2026
554f660
fix(indicator): use common::Ticks for GaugeAxis to allow disabling ticks
jqnatividad Jul 11, 2026
aa51275
feat(traces): add Splom + Parcats trace types
jqnatividad Jul 12, 2026
8598864
chore: rust fmt
jqnatividad Jul 12, 2026
2ea3d61
fix(parcats): use a parcats-specific ParcatsHoverInfo enum
jqnatividad Jul 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
- [[#414](https://github.com/plotly/plotly.rs/issues/414)] Add `DensityMap` (MapLibre `map` subplot) trace type — density heatmaps with full color-scale and hover support
- [[#417](https://github.com/plotly/plotly.rs/issues/417)] Add `ScatterMap` (MapLibre `map` subplot) trace type — the modern counterpart to `ScatterMapbox`
- [[#418](https://github.com/plotly/plotly.rs/issues/418)] Add native point clustering to `ScatterMap` via a `Cluster` option
- [[#421](https://github.com/plotly/plotly.rs/pull/421)] Backfill common trace attributes on the older trace types for plotly.js 3.7 parity:
- `legendrank`, `legendwidth`, `uirevision` on `Scatter`, `Bar`, `BoxPlot`, `Violin`, `Histogram`, `HeatMap`, `Contour`, `Candlestick`, `Ohlc`, `Scatter3D`, `Surface`, `ScatterPolar`, `Sunburst`, `Treemap`, `Table`; `offsetgroup`/`alignmentgroup` on `Scatter`
- `selected`/`unselected`/`selectedpoints` on `Scatter`, `Bar`, `BoxPlot`, `Histogram` (`selectedpoints` only on `Candlestick`, `Ohlc`)
- `zorder` on `Scatter`, `Bar`, `BoxPlot`, `Histogram`, `HeatMap`, `Contour`, `Candlestick`, `Ohlc`
- date-axis period positioning (`xperiod`/`xperiod0`/`xperiodalignment` and the `y` variants) on `Scatter`, `Bar`, `BoxPlot`, `HeatMap`, `Contour` (x-only on `Candlestick`, `Ohlc`), via a new `PeriodAlignment` enum
- `fillpattern` (reusing `Pattern`) and `fillgradient` (new `FillGradient` struct) on `Scatter`
- Consolidate the duplicated `Selection`/`SelectionMarker` structs into `common` (re-exported from their original modules for backward compatibility)
- [[#422](https://github.com/plotly/plotly.rs/issues/422)] Add `Indicator` trace type (number / delta / gauge KPI displays) with `Gauge`, `Delta`, `Number` config
- [[#422](https://github.com/plotly/plotly.rs/issues/422)] Add `Histogram2d` trace type (2D histogram heatmap) with `histfunc`/`histnorm`/`nbinsx`/`nbinsy`/`xbins`/`ybins`
- [[#422](https://github.com/plotly/plotly.rs/issues/422)] Add `Icicle` trace type (hierarchical icicle chart; sibling of `Treemap`/`Sunburst`)
- [[#422](https://github.com/plotly/plotly.rs/issues/422)] Add layout-level `uirevision` to preserve UI state (zoom/pan/selection) across re-renders (complements the trace-level `uirevision` added in #421)
- Add `Splom` trace type (scatter-plot matrix) with `SplomDimension`/`SplomAxis`/`SplomDiagonal` config and `showupperhalf`/`showlowerhalf` controls
- Add `Parcats` trace type (parallel categories) with `ParcatsDimension`/`ParcatsLine` config and `ParcatsLineShape`/`ParcatsArrangement`/`ParcatsHoverOn`/`ParcatsSortPaths`/`ParcatsHoverInfo` enums

### Changed

- [[#406](https://github.com/plotly/plotly.rs/issues/406)] Upgrade bundled plotly.js from 3.0.1 to 3.6.0
- [[#419](https://github.com/plotly/plotly.rs/issues/419)] Upgrade bundled plotly.js from 3.6.0 to 3.7.0

## [0.14.1] - 2026-02-15

Expand Down
180 changes: 90 additions & 90 deletions docs/book/plotly.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/book/theme/header.hbs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<script src="https://cdn.plot.ly/plotly-3.6.0.min.js"></script>
<script src="https://cdn.plot.ly/plotly-3.7.0.min.js"></script>
2 changes: 1 addition & 1 deletion examples/customization/multiple_plots_example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use plotly::{
fn main() {
let html: String = HtmlPage::new()
.with_title("Plotly-rs Multiple Plots")
.with_script_link("https://cdn.plot.ly/plotly-latest.min.js")
.with_script_link("https://cdn.plot.ly/plotly-3.7.0.min.js")
.with_header(1, "Multiple Plotly plots on the same HTML page")
.with_raw(first_plot())
.with_raw(second_plot())
Expand Down
2 changes: 1 addition & 1 deletion examples/wasm-yew/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<title>Plotly Yew</title>
<script src="https://cdn.plot.ly/plotly-2.14.0.min.js"></script>
<script src="https://cdn.plot.ly/plotly-3.7.0.min.js"></script>
</head>

<body></body>
Expand Down
2 changes: 1 addition & 1 deletion examples/wasm-yew/callback-example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<title>Plotly Yew</title>
<script src="https://cdn.plot.ly/plotly-2.14.0.min.js"></script>
<script src="https://cdn.plot.ly/plotly-3.7.0.min.js"></script>
</head>

<body></body>
Expand Down
180 changes: 90 additions & 90 deletions plotly/resource/plotly.min.js

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions plotly/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,16 @@ pub enum PlotType {
Contour,
HeatMap,
Histogram,
Histogram2d,
Histogram2dContour,
Icicle,
Image,
Indicator,
Mesh3D,
Ohlc,
Parcats,
Sankey,
Splom,
Surface,
DensityMapbox,
DensityMap,
Expand Down Expand Up @@ -645,6 +650,101 @@ impl Gradient {
}
}

/// Styles the marker of `selected`/`unselected` points, used by the
/// `selected` and `unselected` attributes of point-marker traces.
#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, Default)]
pub struct SelectionMarker {
color: Option<Box<dyn Color>>,
opacity: Option<f64>,
size: Option<Dim<usize>>,
}

/// Sets the style of `selected`/`unselected` points.
#[derive(Serialize, Clone, Debug, Default)]
pub struct Selection {
marker: SelectionMarker,
}

impl Selection {
pub fn new() -> Self {
Default::default()
}

/// Sets the marker color of un/selected points.
pub fn color<C: Color>(mut self, color: C) -> Self {
self.marker.color = Some(Box::new(color));
self
}

/// Sets the marker opacity of un/selected points.
pub fn opacity(mut self, opacity: f64) -> Self {
self.marker.opacity = Some(opacity);
self
}

/// Sets the marker size of un/selected points.
pub fn size(mut self, size: usize) -> Self {
self.marker.size = Some(Dim::Scalar(size));
self
}
}

/// Alignment of the period on a date axis, controlling where within each
/// period the point is drawn (used by the `xperiodalignment` /
/// `yperiodalignment` trace attributes).
#[derive(Serialize, Clone, Debug)]
#[serde(rename_all = "lowercase")]
pub enum PeriodAlignment {
Start,
Middle,
End,
}

/// Sets a fill gradient for a scatter trace's filled area, as an alternative to
/// a solid `fill_color`.
#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, Default)]
pub struct FillGradient {
#[serde(rename = "type")]
r#type: Option<GradientType>,
start: Option<f64>,
stop: Option<f64>,
#[serde(rename = "colorscale")]
color_scale: Option<ColorScale>,
}

impl FillGradient {
pub fn new() -> Self {
Default::default()
}

/// Sets the direction of the gradient (`radial`, `horizontal`, `vertical`).
pub fn type_(mut self, gradient_type: GradientType) -> Self {
self.r#type = Some(gradient_type);
self
}

/// Sets the gradient start value (in the units of the axis the gradient is
/// aligned with).
pub fn start(mut self, start: f64) -> Self {
self.start = Some(start);
self
}

/// Sets the gradient stop value.
pub fn stop(mut self, stop: f64) -> Self {
self.stop = Some(stop);
self
}

/// Sets the color scale used across the gradient.
pub fn color_scale(mut self, color_scale: ColorScale) -> Self {
self.color_scale = Some(color_scale);
self
}
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, FieldSetter)]
pub struct TickFormatStop {
Expand Down
13 changes: 13 additions & 0 deletions plotly/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use update_menu::UpdateMenu;

use crate::color::Color;
use crate::common::{Calendar, ColorScale, Font, Label, Orientation, Title};
use crate::private::NumOrString;

pub mod themes;
pub mod update_menu;
Expand Down Expand Up @@ -257,6 +258,12 @@ pub struct LayoutFields {
color_axis: Option<ColorAxis>,
#[serde(rename = "modebar")]
mode_bar: Option<ModeBar>,
/// Controls persistence of user-driven UI changes (zoom, pan, selection,
/// legend visibility) across `Plotly.react`/`newPlot` calls: state is kept
/// while `uirevision` is unchanged. Trace-level `uirevision` overrides per
/// trace.
#[serde(rename = "uirevision")]
ui_revision: Option<NumOrString>,
/// Determines the mode of hover interactions. If "closest", a single
/// hoverlabel will appear for the "closest" point within the
/// `hoverdistance`. If "x" (or "y"), multiple hoverlabels will appear for
Expand Down Expand Up @@ -654,6 +661,12 @@ mod tests {
assert_eq!(to_value(template).unwrap(), expected);
}

#[test]
fn serialize_layout_ui_revision() {
let layout = Layout::new().ui_revision("forever");
assert_eq!(to_value(layout).unwrap()["uirevision"], json!("forever"));
}

#[test]
fn serialize_layout() {
let layout = Layout::new()
Expand Down
10 changes: 6 additions & 4 deletions plotly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ pub use layout::Layout;
pub use plot::{Plot, Trace, Traces};
// Also provide easy access to modules which contain additional trace-specific types
pub use traces::{
box_plot, choropleth, choropleth_map, contour, density_map, heat_map, histogram, image, mesh3d,
sankey, scatter, scatter3d, scatter_map, scatter_mapbox, sunburst, surface, treemap, violin,
box_plot, choropleth, choropleth_map, contour, density_map, heat_map, histogram, histogram2d,
icicle, image, indicator, mesh3d, parcats, sankey, scatter, scatter3d, scatter_map,
scatter_mapbox, splom, sunburst, surface, treemap, violin,
};
// Bring the different trace types into the top-level scope
pub use traces::{
Bar, BoxPlot, Candlestick, Choropleth, ChoroplethMap, Contour, DensityMap, DensityMapbox,
HeatMap, Histogram, Image, Mesh3D, Ohlc, Pie, Sankey, Scatter, Scatter3D, ScatterGeo,
ScatterMap, ScatterMapbox, ScatterPolar, Sunburst, Surface, Table, Treemap, Violin,
HeatMap, Histogram, Histogram2d, Icicle, Image, Indicator, Mesh3D, Ohlc, Parcats, Pie, Sankey,
Scatter, Scatter3D, ScatterGeo, ScatterMap, ScatterMapbox, ScatterPolar, Splom, Sunburst,
Surface, Table, Treemap, Violin,
};

pub trait Restyle: serde::Serialize {}
Expand Down
4 changes: 2 additions & 2 deletions plotly/src/plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ impl Plot {
/// This function provides HTML script tags that load JavaScript libraries
/// from external CDN sources, requiring an internet connection to
/// function. The referenced sources include:
/// - Plotly.js library from CDN (version 3.6.0)
/// - Plotly.js library from CDN (version 3.7.0)
/// - MathJax tex-svg from jsDelivr CDN (version 3.2.2)
///
/// This is the default behavior when the `plotly_embed_js` feature is
Expand All @@ -767,7 +767,7 @@ impl Plot {
// Note that since 'tex-mml-chtml' conflicts with 'tex-svg' when generating
// Latex Titles we no longer include it.
r##"<script src="https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-svg.js"></script>
<script src="https://cdn.plot.ly/plotly-3.6.0.min.js"></script>
<script src="https://cdn.plot.ly/plotly-3.7.0.min.js"></script>
"##
.to_string()
}
Expand Down
50 changes: 49 additions & 1 deletion plotly/src/traces/bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ use serde::Serialize;
use crate::{
common::{
Calendar, ConstrainText, Dim, ErrorData, Font, HoverInfo, Label, LegendGroupTitle, Marker,
Orientation, PlotType, TextAnchor, TextPosition, Visible, XAxisId, YAxisId,
Orientation, PeriodAlignment, PlotType, Selection, TextAnchor, TextPosition, Visible,
XAxisId, YAxisId,
},
private::{NumOrString, NumOrStringCollection},
Trace,
};

Expand Down Expand Up @@ -105,6 +107,52 @@ where
x_calendar: Option<Calendar>,
#[serde(rename = "ycalendar")]
y_calendar: Option<Calendar>,
/// Sets the legend rank for this trace. Items and groups with smaller ranks
/// are presented on top/left side while with `"reversed"`
/// `legend.trace_order` they are on bottom/right side. The default
/// legendrank is 1000.
#[serde(rename = "legendrank")]
legend_rank: Option<usize>,
/// Sets the width (in px or fraction) of the legend for this trace.
#[serde(rename = "legendwidth")]
legend_width: Option<f64>,
/// Controls persistence of user-driven changes to the trace. Defaults to
/// `layout.uirevision`.
#[serde(rename = "uirevision")]
ui_revision: Option<NumOrString>,
/// Array of integer indices of the points in this trace that are selected.
#[serde(rename = "selectedpoints")]
selected_points: Option<NumOrStringCollection>,
/// Sets the style of selected points.
selected: Option<Selection>,
/// Sets the style of unselected points.
unselected: Option<Selection>,
/// Sets the layer on which this trace is displayed relative to other SVG
/// traces on the same subplot. A higher `zorder` appears on top.
#[serde(rename = "zorder")]
z_order: Option<i32>,
/// Only relevant when the corresponding axis `type` is "date". Sets the
/// period positioning in milliseconds or "M<n>" on the x axis.
#[serde(rename = "xperiod")]
x_period: Option<NumOrString>,
/// Only relevant when the axis `type` is "date". Sets the base for period
/// positioning on the x axis.
#[serde(rename = "xperiod0")]
x_period0: Option<NumOrString>,
/// Sets the alignment of data points on the x axis relative to the period.
#[serde(rename = "xperiodalignment")]
x_period_alignment: Option<PeriodAlignment>,
/// Only relevant when the corresponding axis `type` is "date". Sets the
/// period positioning in milliseconds or "M<n>" on the y axis.
#[serde(rename = "yperiod")]
y_period: Option<NumOrString>,
/// Only relevant when the axis `type` is "date". Sets the base for period
/// positioning on the y axis.
#[serde(rename = "yperiod0")]
y_period0: Option<NumOrString>,
/// Sets the alignment of data points on the y axis relative to the period.
#[serde(rename = "yperiodalignment")]
y_period_alignment: Option<PeriodAlignment>,
}

impl<X, Y> Bar<X, Y>
Expand Down
51 changes: 49 additions & 2 deletions plotly/src/traces/box_plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use serde::{Serialize, Serializer};
use crate::{
color::Color,
common::{
Calendar, Dim, HoverInfo, Label, LegendGroupTitle, Line, Marker, Orientation, PlotType,
Visible, XAxisId, YAxisId,
Calendar, Dim, HoverInfo, Label, LegendGroupTitle, Line, Marker, Orientation,
PeriodAlignment, PlotType, Selection, Visible, XAxisId, YAxisId,
},
private::{NumOrString, NumOrStringCollection},
Trace,
};

Expand Down Expand Up @@ -172,6 +173,52 @@ where
x_calendar: Option<Calendar>,
#[serde(rename = "ycalendar")]
y_calendar: Option<Calendar>,
/// Sets the legend rank for this trace. Items and groups with smaller ranks
/// are presented on top/left side while with `"reversed"`
/// `legend.trace_order` they are on bottom/right side. The default
/// legendrank is 1000.
#[serde(rename = "legendrank")]
legend_rank: Option<usize>,
/// Sets the width (in px or fraction) of the legend for this trace.
#[serde(rename = "legendwidth")]
legend_width: Option<f64>,
/// Controls persistence of user-driven changes to the trace. Defaults to
/// `layout.uirevision`.
#[serde(rename = "uirevision")]
ui_revision: Option<NumOrString>,
/// Array of integer indices of the points in this trace that are selected.
#[serde(rename = "selectedpoints")]
selected_points: Option<NumOrStringCollection>,
/// Sets the style of selected points.
selected: Option<Selection>,
/// Sets the style of unselected points.
unselected: Option<Selection>,
/// Sets the layer on which this trace is displayed relative to other SVG
/// traces on the same subplot. A higher `zorder` appears on top.
#[serde(rename = "zorder")]
z_order: Option<i32>,
/// Only relevant when the corresponding axis `type` is "date". Sets the
/// period positioning in milliseconds or "M<n>" on the x axis.
#[serde(rename = "xperiod")]
x_period: Option<NumOrString>,
/// Only relevant when the axis `type` is "date". Sets the base for period
/// positioning on the x axis.
#[serde(rename = "xperiod0")]
x_period0: Option<NumOrString>,
/// Sets the alignment of data points on the x axis relative to the period.
#[serde(rename = "xperiodalignment")]
x_period_alignment: Option<PeriodAlignment>,
/// Only relevant when the corresponding axis `type` is "date". Sets the
/// period positioning in milliseconds or "M<n>" on the y axis.
#[serde(rename = "yperiod")]
y_period: Option<NumOrString>,
/// Only relevant when the axis `type` is "date". Sets the base for period
/// positioning on the y axis.
#[serde(rename = "yperiod0")]
y_period0: Option<NumOrString>,
/// Sets the alignment of data points on the y axis relative to the period.
#[serde(rename = "yperiodalignment")]
y_period_alignment: Option<PeriodAlignment>,
}

impl<Y> BoxPlot<f64, Y>
Expand Down
Loading
Loading