Skip to content

Commit 1b754fc

Browse files
authored
Merge pull request #474 from palewire/main
feat(charts): auto-enable mixed colors when color_negative is set
2 parents 546ea02 + 72cacb3 commit 1b754fc

1 file changed

Lines changed: 29 additions & 9 deletions

File tree

datawrapper/charts/annos.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any, Literal
22

3-
from pydantic import BaseModel, ConfigDict, Field, field_validator
3+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
44

55
from .enums import ArrowHead, ConnectorLineType, LineInterpolation, StrokeWidth
66

@@ -321,8 +321,10 @@ class AreaFill(BaseModel):
321321
#: The line to fill upwards to
322322
to_column: str = Field(alias="to", description="The line to fill upwards to")
323323

324-
#: The color of the fill
325-
color: str = Field(default="#15607a", description="The color of the fill")
324+
#: The color of the fill (hex string or palette index)
325+
color: str | int = Field(
326+
default=0, description="The color of the fill (hex string or palette index)"
327+
)
326328

327329
#: The opacity of the fill
328330
opacity: float = Field(default=0.3, description="The opacity of the fill")
@@ -334,11 +336,11 @@ class AreaFill(BaseModel):
334336
description="Whether to use different colors when there are negative values",
335337
)
336338

337-
#: The color of the fill when it is negative
338-
color_negative: str = Field(
339-
default="#cc0000",
339+
#: The color of the fill when it is negative (hex string or palette index, None = disabled)
340+
color_negative: str | int | None = Field(
341+
default=None,
340342
alias="colorNegative",
341-
description="The color of the fill when it is negative",
343+
description="The color of the fill when it is negative (hex string or palette index, None = disabled)",
342344
)
343345

344346
#: The interpolation method to use when drawing lines
@@ -360,21 +362,39 @@ def validate_interpolation(
360362
)
361363
return v
362364

365+
@model_validator(mode="after")
366+
def auto_enable_mixed_colors(self) -> "AreaFill":
367+
"""Auto-enable use_mixed_colors when color_negative is provided.
368+
369+
If a user provides a color_negative value (not None),
370+
automatically enable use_mixed_colors to make the feature work as expected.
371+
"""
372+
# Only auto-enable if color_negative is provided and use_mixed_colors is False
373+
if self.color_negative is not None and not self.use_mixed_colors:
374+
self.use_mixed_colors = True
375+
return self
376+
363377
def serialize_model(self) -> dict:
364378
"""Serialize the model to a dictionary for the Datawrapper API.
365379
366380
Note: The 'id' field is not included in the output as it's used as the dict key.
381+
Only includes colorNegative if it's not None.
367382
"""
368-
return {
383+
result = {
369384
"from": self.from_column,
370385
"to": self.to_column,
371386
"color": self.color,
372387
"opacity": self.opacity,
373388
"useMixedColors": self.use_mixed_colors,
374-
"colorNegative": self.color_negative,
375389
"interpolation": self.interpolation,
376390
}
377391

392+
# Only include colorNegative if it's provided (not None)
393+
if self.color_negative is not None:
394+
result["colorNegative"] = self.color_negative
395+
396+
return result
397+
378398
@classmethod
379399
def deserialize_model(cls, api_data: dict[str, dict] | list | None) -> list[dict]:
380400
"""Deserialize area fills from API response format.

0 commit comments

Comments
 (0)