Skip to content

Commit a4b71f1

Browse files
RedZapdos123WhiteMetagross
authored andcommitted
feat: type trace axis ids
Signed-off-by: RedZapdos123 <redzapdos123@example.com>
1 parent 4d3f8d6 commit a4b71f1

11 files changed

Lines changed: 215 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
55

66
https://github.com/plotly/plotly.rs/pull/350
77

8+
## [Unreleased]
9+
10+
### Fixed
11+
12+
- [#5583](https://github.com/plotly/plotly.rs/issues/5583) Add typed axis-id enums for trace `x_axis` and `y_axis` setters
13+
814
## [0.14.1] - 2026-02-15
915

1016
### Fixed

plotly/src/common/mod.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,114 @@ pub enum Reference {
893893
Paper,
894894
}
895895

896+
#[derive(Clone, Debug, PartialEq, Eq)]
897+
pub enum XAxisId {
898+
X1,
899+
X2,
900+
X3,
901+
X4,
902+
Custom(String),
903+
}
904+
905+
impl XAxisId {
906+
fn as_str(&self) -> &str {
907+
match self {
908+
Self::X1 => "x",
909+
Self::X2 => "x2",
910+
Self::X3 => "x3",
911+
Self::X4 => "x4",
912+
Self::Custom(value) => value.as_str(),
913+
}
914+
}
915+
}
916+
917+
impl Serialize for XAxisId {
918+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
919+
where
920+
S: Serializer,
921+
{
922+
serializer.serialize_str(self.as_str())
923+
}
924+
}
925+
926+
impl From<&str> for XAxisId {
927+
fn from(value: &str) -> Self {
928+
match value {
929+
"x" | "x1" => Self::X1,
930+
"x2" => Self::X2,
931+
"x3" => Self::X3,
932+
"x4" => Self::X4,
933+
_ => Self::Custom(value.to_string()),
934+
}
935+
}
936+
}
937+
938+
impl From<String> for XAxisId {
939+
fn from(value: String) -> Self {
940+
Self::from(value.as_str())
941+
}
942+
}
943+
944+
impl From<XAxisId> for String {
945+
fn from(value: XAxisId) -> Self {
946+
value.as_str().to_string()
947+
}
948+
}
949+
950+
#[derive(Clone, Debug, PartialEq, Eq)]
951+
pub enum YAxisId {
952+
Y1,
953+
Y2,
954+
Y3,
955+
Y4,
956+
Custom(String),
957+
}
958+
959+
impl YAxisId {
960+
fn as_str(&self) -> &str {
961+
match self {
962+
Self::Y1 => "y",
963+
Self::Y2 => "y2",
964+
Self::Y3 => "y3",
965+
Self::Y4 => "y4",
966+
Self::Custom(value) => value.as_str(),
967+
}
968+
}
969+
}
970+
971+
impl Serialize for YAxisId {
972+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
973+
where
974+
S: Serializer,
975+
{
976+
serializer.serialize_str(self.as_str())
977+
}
978+
}
979+
980+
impl From<&str> for YAxisId {
981+
fn from(value: &str) -> Self {
982+
match value {
983+
"y" | "y1" => Self::Y1,
984+
"y2" => Self::Y2,
985+
"y3" => Self::Y3,
986+
"y4" => Self::Y4,
987+
_ => Self::Custom(value.to_string()),
988+
}
989+
}
990+
}
991+
992+
impl From<String> for YAxisId {
993+
fn from(value: String) -> Self {
994+
Self::from(value.as_str())
995+
}
996+
}
997+
998+
impl From<YAxisId> for String {
999+
fn from(value: YAxisId) -> Self {
1000+
value.as_str().to_string()
1001+
}
1002+
}
1003+
8961004
#[derive(Serialize, Clone, Debug)]
8971005
pub struct Pad {
8981006
t: usize,
@@ -1799,6 +1907,22 @@ mod tests {
17991907
assert_eq!(to_value(Reference::Paper).unwrap(), json!("paper"));
18001908
}
18011909

1910+
#[test]
1911+
fn serialize_axis_id() {
1912+
assert_eq!(to_value(XAxisId::X1).unwrap(), json!("x"));
1913+
assert_eq!(to_value(XAxisId::X3).unwrap(), json!("x3"));
1914+
assert_eq!(
1915+
to_value(XAxisId::Custom("x7".to_string())).unwrap(),
1916+
json!("x7")
1917+
);
1918+
assert_eq!(to_value(YAxisId::Y1).unwrap(), json!("y"));
1919+
assert_eq!(to_value(YAxisId::Y4).unwrap(), json!("y4"));
1920+
assert_eq!(
1921+
to_value(YAxisId::Custom("y8".to_string())).unwrap(),
1922+
json!("y8")
1923+
);
1924+
}
1925+
18021926
#[test]
18031927
#[rustfmt::skip]
18041928
fn serialize_legend_group_title() {

plotly/src/traces/bar.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::Serialize;
66
use crate::{
77
common::{
88
Calendar, ConstrainText, Dim, ErrorData, Font, HoverInfo, Label, LegendGroupTitle, Marker,
9-
Orientation, PlotType, TextAnchor, TextPosition, Visible,
9+
Orientation, PlotType, TextAnchor, TextPosition, Visible, XAxisId, YAxisId,
1010
},
1111
Trace,
1212
};
@@ -69,9 +69,9 @@ where
6969
#[serde(rename = "hovertemplate")]
7070
hover_template: Option<Dim<String>>,
7171
#[serde(rename = "xaxis")]
72-
x_axis: Option<String>,
72+
x_axis: Option<XAxisId>,
7373
#[serde(rename = "yaxis")]
74-
y_axis: Option<String>,
74+
y_axis: Option<YAxisId>,
7575
orientation: Option<Orientation>,
7676
#[serde(rename = "alignmentgroup")]
7777
alignment_group: Option<String>,
@@ -179,9 +179,9 @@ mod tests {
179179
.text_template_array(vec!["text_template"])
180180
.visible(Visible::LegendOnly)
181181
.width(999.0)
182-
.x_axis("xaxis")
182+
.x_axis(XAxisId::from("xaxis"))
183183
.x_calendar(Calendar::Nanakshahi)
184-
.y_axis("yaxis")
184+
.y_axis(YAxisId::from("yaxis"))
185185
.y_calendar(Calendar::Ummalqura);
186186

187187
let expected = json!({

plotly/src/traces/box_plot.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
color::Color,
88
common::{
99
Calendar, Dim, HoverInfo, Label, LegendGroupTitle, Line, Marker, Orientation, PlotType,
10-
Visible,
10+
Visible, XAxisId, YAxisId,
1111
},
1212
Trace,
1313
};
@@ -124,9 +124,9 @@ where
124124
#[serde(rename = "hovertemplate")]
125125
hover_template: Option<Dim<String>>,
126126
#[serde(rename = "xaxis")]
127-
x_axis: Option<String>,
127+
x_axis: Option<XAxisId>,
128128
#[serde(rename = "yaxis")]
129-
y_axis: Option<String>,
129+
y_axis: Option<YAxisId>,
130130
orientation: Option<Orientation>,
131131
#[serde(rename = "alignmentgroup")]
132132
alignment_group: Option<String>,
@@ -307,9 +307,9 @@ mod tests {
307307
.visible(Visible::LegendOnly)
308308
.whisker_width(0.2)
309309
.width(50)
310-
.x_axis("xaxis")
310+
.x_axis(XAxisId::from("xaxis"))
311311
.x_calendar(Calendar::Chinese)
312-
.y_axis("yaxis")
312+
.y_axis(YAxisId::from("yaxis"))
313313
.y_calendar(Calendar::Coptic);
314314

315315
let expected = json!({

plotly/src/traces/candlestick.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
color::NamedColor,
88
common::{
99
Calendar, Dim, Direction, HoverInfo, Label, LegendGroupTitle, Line, PlotType, Visible,
10+
XAxisId, YAxisId,
1011
},
1112
Trace,
1213
};
@@ -72,9 +73,9 @@ where
7273
#[serde(rename = "hoverinfo")]
7374
hover_info: Option<HoverInfo>,
7475
#[serde(rename = "xaxis")]
75-
x_axis: Option<String>,
76+
x_axis: Option<XAxisId>,
7677
#[serde(rename = "yaxis")]
77-
y_axis: Option<String>,
78+
y_axis: Option<YAxisId>,
7879
line: Option<Line>,
7980
#[serde(rename = "whiskerwidth")]
8081
whisker_width: Option<f64>,
@@ -151,8 +152,8 @@ mod tests {
151152
.hover_text_array(vec!["hover", "text"])
152153
.hover_text("hover text")
153154
.hover_info(HoverInfo::Skip)
154-
.x_axis("x1")
155-
.y_axis("y1")
155+
.x_axis(XAxisId::from("x1"))
156+
.y_axis(YAxisId::from("y1"))
156157
.line(Line::new())
157158
.whisker_width(0.4)
158159
.increasing(Direction::Increasing { line: Line::new() })

plotly/src/traces/contour.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
color::Color,
88
common::{
99
Calendar, ColorBar, ColorScale, Dim, Font, HoverInfo, Label, LegendGroupTitle, Line,
10-
PlotType, Visible,
10+
PlotType, Visible, XAxisId, YAxisId,
1111
},
1212
private, Trace,
1313
};
@@ -137,9 +137,9 @@ where
137137
#[serde(rename = "hovertemplate")]
138138
hover_template: Option<Dim<String>>,
139139
#[serde(rename = "xaxis")]
140-
x_axis: Option<String>,
140+
x_axis: Option<XAxisId>,
141141
#[serde(rename = "yaxis")]
142-
y_axis: Option<String>,
142+
y_axis: Option<YAxisId>,
143143
line: Option<Line>,
144144
#[serde(rename = "colorbar")]
145145
color_bar: Option<ColorBar>,
@@ -403,8 +403,8 @@ where
403403
Box::new(self)
404404
}
405405

406-
pub fn x_axis(mut self, axis: &str) -> Box<Self> {
407-
self.x_axis = Some(axis.to_string());
406+
pub fn x_axis(mut self, axis: impl Into<XAxisId>) -> Box<Self> {
407+
self.x_axis = Some(axis.into());
408408
Box::new(self)
409409
}
410410

@@ -418,8 +418,8 @@ where
418418
Box::new(self)
419419
}
420420

421-
pub fn y_axis(mut self, axis: &str) -> Box<Self> {
422-
self.y_axis = Some(axis.to_string());
421+
pub fn y_axis(mut self, axis: impl Into<YAxisId>) -> Box<Self> {
422+
self.y_axis = Some(axis.into());
423423
Box::new(self)
424424
}
425425

@@ -598,11 +598,11 @@ mod tests {
598598
.transpose(true)
599599
.visible(Visible::True)
600600
.x(vec![0.0, 1.0])
601-
.x_axis("x0")
601+
.x_axis(XAxisId::from("x0"))
602602
.x_calendar(Calendar::Ethiopian)
603603
.x0(0.)
604604
.y(vec![2.0, 3.0])
605-
.y_axis("y0")
605+
.y_axis(YAxisId::from("y0"))
606606
.y_calendar(Calendar::Gregorian)
607607
.y0(0.)
608608
.zauto(false)

plotly/src/traces/heat_map.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use serde::Serialize;
66
use crate::{
77
common::{
88
Calendar, ColorBar, ColorScale, Dim, HoverInfo, Label, LegendGroupTitle, PlotType, Visible,
9+
XAxisId, YAxisId,
910
},
1011
private::{NumOrString, NumOrStringCollection},
1112
Trace,
@@ -106,14 +107,14 @@ where
106107
visible: Option<Visible>,
107108
x: Option<Vec<X>>,
108109
#[serde(rename = "xaxis")]
109-
x_axis: Option<String>,
110+
x_axis: Option<XAxisId>,
110111
#[serde(rename = "xcalendar")]
111112
x_calendar: Option<Calendar>,
112113
#[serde(rename = "xgap")]
113114
x_gap: Option<NumOrString>,
114115
y: Option<Vec<Y>>,
115116
#[serde(rename = "yaxis")]
116-
y_axis: Option<String>,
117+
y_axis: Option<YAxisId>,
117118
#[serde(rename = "ycalendar")]
118119
y_calendar: Option<Calendar>,
119120
#[serde(rename = "ygap")]
@@ -227,10 +228,10 @@ mod tests {
227228
.text_array(vec!["te", "xt"])
228229
.transpose(true)
229230
.visible(Visible::LegendOnly)
230-
.x_axis("x")
231+
.x_axis(XAxisId::from("x"))
231232
.x_calendar(Calendar::Hebrew)
232233
.x_gap(1.0)
233-
.y_axis("y")
234+
.y_axis(YAxisId::from("y"))
234235
.y_calendar(Calendar::Islamic)
235236
.y_gap("10")
236237
.zauto(true)

plotly/src/traces/histogram.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::ndarray::ArrayTraces;
1010
use crate::{
1111
common::{
1212
Calendar, Dim, ErrorData, HoverInfo, Label, LegendGroupTitle, Marker, Orientation,
13-
PlotType, Visible,
13+
PlotType, Visible, XAxisId, YAxisId,
1414
},
1515
Trace,
1616
};
@@ -155,14 +155,14 @@ where
155155
visible: Option<Visible>,
156156
x: Option<Vec<H>>,
157157
#[serde(rename = "xaxis")]
158-
x_axis: Option<String>,
158+
x_axis: Option<XAxisId>,
159159
#[serde(rename = "xbins")]
160160
x_bins: Option<Bins>,
161161
#[serde(rename = "xcalendar")]
162162
x_calendar: Option<Calendar>,
163163
y: Option<Vec<H>>,
164164
#[serde(rename = "yaxis")]
165-
y_axis: Option<String>,
165+
y_axis: Option<YAxisId>,
166166
#[serde(rename = "ybins")]
167167
y_bins: Option<Bins>,
168168
#[serde(rename = "ycalendar")]
@@ -419,10 +419,10 @@ mod tests {
419419
.text("text")
420420
.text_array(vec!["text_1", "text_2"])
421421
.visible(Visible::True)
422-
.x_axis("xaxis")
422+
.x_axis(XAxisId::from("xaxis"))
423423
.x_bins(Bins::new(1.0, 2.0, 1.0))
424424
.x_calendar(Calendar::Julian)
425-
.y_axis("yaxis")
425+
.y_axis(YAxisId::from("yaxis"))
426426
.y_bins(Bins::new(2.0, 3.0, 4.0))
427427
.y_calendar(Calendar::Mayan);
428428

0 commit comments

Comments
 (0)