gov-uk-dashboards 26.25.0__tar.gz → 26.26.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. {gov_uk_dashboards-26.25.0/gov_uk_dashboards.egg-info → gov_uk_dashboards-26.26.0}/PKG-INFO +1 -1
  2. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/context_card.py +4 -4
  3. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/time_series_chart.py +83 -11
  4. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0/gov_uk_dashboards.egg-info}/PKG-INFO +1 -1
  5. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/setup.py +1 -1
  6. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/LICENSE +0 -0
  7. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/MANIFEST.in +0 -0
  8. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/README.md +0 -0
  9. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/__init__.py +0 -0
  10. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/__init__.py +0 -0
  11. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/attach-event-to-dash.js +0 -0
  12. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/custom_map_style_functions.js +0 -0
  13. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/dashboard.css +0 -0
  14. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/download-map.js +0 -0
  15. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/fonts/bold-affa96571d-v2.woff +0 -0
  16. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
  17. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
  18. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/fonts/light-f591b13f7d-v2.woff +0 -0
  19. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/get_assets_folder.py +0 -0
  20. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/govuk-frontend-3.14.0.min.js +0 -0
  21. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/CHASE_icon.svg +0 -0
  22. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/DLUHC_WHITE_Master_AW_sm.png +0 -0
  23. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/MHCLG-favicon.png +0 -0
  24. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/MHCLG_favicon.png +0 -0
  25. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/dcms_coatofarms.png +0 -0
  26. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/dluhc_favicon.ico +0 -0
  27. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/explore_data_logo.svg +0 -0
  28. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/gov_favicon.ico +0 -0
  29. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/govuk-crest.svg +0 -0
  30. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/hm-government-logo.png +0 -0
  31. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/mhclg_coat_of_arms.png +0 -0
  32. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/mhclg_white_no_background.png +0 -0
  33. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/MedianAbsolute.png +0 -0
  34. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/how_to_1_selecting_data.png +0 -0
  35. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/how_to_2_viewing_tabs.png +0 -0
  36. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/how_to_3_viewing_charts.png +0 -0
  37. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/how_to_4_viewing_trends.png +0 -0
  38. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/images/oflog/how_to_5_viewing_tables.png +0 -0
  39. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/index.html +0 -0
  40. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/mobile-nav.js +0 -0
  41. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/register_maps +0 -0
  42. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/scripts.js +0 -0
  43. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/topojson/usa_110m.json +0 -0
  44. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/assets/topojson/world_110m.json +0 -0
  45. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/colours.py +0 -0
  46. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/__init__.py +0 -0
  47. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/__init__.py +0 -0
  48. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/apply_and_reset_filters_buttons.py +0 -0
  49. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/banners.py +0 -0
  50. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/card.py +0 -0
  51. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/card_full_width.py +0 -0
  52. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/collapsible_panel.py +0 -0
  53. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/comparison_la_filter_button.py +0 -0
  54. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/context_banner.py +0 -0
  55. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/dashboard_container.py +0 -0
  56. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/data_quality_banner.py +0 -0
  57. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/details.py +0 -0
  58. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/download_button.py +0 -0
  59. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/filter_panel.py +0 -0
  60. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/footer.py +0 -0
  61. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/graph.py +0 -0
  62. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/green_button.py +0 -0
  63. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/header.py +0 -0
  64. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/heading.py +0 -0
  65. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/home_page_link_button.py +0 -0
  66. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/html_list.py +0 -0
  67. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/key_value_pair.py +0 -0
  68. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/main_content.py +0 -0
  69. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/navbar.py +0 -0
  70. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/no_data_message.py +0 -0
  71. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/notification_banner.py +0 -0
  72. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/paragraph.py +0 -0
  73. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/phase_banner.py +0 -0
  74. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/row_component.py +0 -0
  75. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/side_navbar.py +0 -0
  76. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/table.py +0 -0
  77. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/tooltip.py +0 -0
  78. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/tooltip_title.py +0 -0
  79. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/visualisation_commentary.py +0 -0
  80. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/visualisation_title.py +0 -0
  81. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/dash/warning_text.py +0 -0
  82. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/__init__.py +0 -0
  83. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/display_chart_or_table_with_header.py +0 -0
  84. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/generate_dash_graph_from_figure.py +0 -0
  85. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/get_chart_for_download.py +0 -0
  86. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/plotting_helper_functions.py +0 -0
  87. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/helpers/update_layout_bgcolor_margin.py +0 -0
  88. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/leaflet/__init__.py +0 -0
  89. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/leaflet/leaflet_choropleth_map.py +0 -0
  90. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/__init__.py +0 -0
  91. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/captioned_figure.py +0 -0
  92. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/choropleth_map.py +0 -0
  93. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/enums.py +0 -0
  94. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/components/plotly/stacked_barchart.py +0 -0
  95. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/constants.py +0 -0
  96. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/__init__.py +0 -0
  97. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/enums/__init__.py +0 -0
  98. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/enums/dash_patterns.py +0 -0
  99. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/line_chart.py +0 -0
  100. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/styles/__init__.py +0 -0
  101. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/figures/styles/line_style.py +0 -0
  102. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/__init__.py +0 -0
  103. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/human_readable.py +0 -0
  104. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/number_formatting.py +0 -0
  105. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/round_and_add_prefix_and_suffix.py +0 -0
  106. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/rounding.py +0 -0
  107. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/formatting/text_functions.py +0 -0
  108. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/__init__.py +0 -0
  109. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/dap/__init__.py +0 -0
  110. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/dap/dap_deployment.py +0 -0
  111. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/dap/get_dataframe_from_cds.py +0 -0
  112. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/datetime_functions/__init__.py +0 -0
  113. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/datetime_functions/datetime_functions.py +0 -0
  114. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/download_functions/__init__.py +0 -0
  115. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/download_functions/convert_fig_to_image_and_download.py +0 -0
  116. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/download_functions/download_csv_with_headers.py +0 -0
  117. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/enable_basic_auth.py +0 -0
  118. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/http_headers.py +0 -0
  119. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/logging.py +0 -0
  120. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/testing_functions/__init__.py +0 -0
  121. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/testing_functions/barchart_data_test_assertions.py +0 -0
  122. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/testing_functions/data_test_assertions.py +0 -0
  123. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/testing_functions/data_test_helper_functions.py +0 -0
  124. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/testing_functions/timeseries_data_test_assertions.py +0 -0
  125. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/lib/warning_text_sensitive.py +0 -0
  126. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/log_kpi.py +0 -0
  127. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/symbols.py +0 -0
  128. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/template.html +0 -0
  129. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards/template.py +0 -0
  130. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards.egg-info/SOURCES.txt +0 -0
  131. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards.egg-info/dependency_links.txt +0 -0
  132. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards.egg-info/requires.txt +0 -0
  133. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/gov_uk_dashboards.egg-info/top_level.txt +0 -0
  134. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/pyproject.toml +0 -0
  135. {gov_uk_dashboards-26.25.0 → gov_uk_dashboards-26.26.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gov_uk_dashboards
3
- Version: 26.25.0
3
+ Version: 26.26.0
4
4
  Summary: Provides access to functionality common to creating a data dashboard.
5
5
  Author: Department for Levelling Up, Housing and Communities
6
6
  Description-Content-Type: text/markdown
@@ -624,8 +624,8 @@ class ContextCard:
624
624
  When True, comparison tags show the difference between the current VALUE and
625
625
  the comparison VALUE converted to weeks/days via `convert_days_to_weeks_and_days`.
626
626
  Tag prefix becomes:
627
- - "slower than ..." if percent-change is positive,
628
- - "faster than ..." if percent-change is negative,
627
+ - "longer than ..." if percent-change is positive,
628
+ - "shorter than ..." if percent-change is negative,
629
629
  - "unchanged from ..." if zero.
630
630
  Requires both current and comparison values to be present.
631
631
  NOTE: This cannot be True at the same time as `use_previous_value_rather_than_change`.
@@ -877,9 +877,9 @@ class ContextCard:
877
877
  )
878
878
 
879
879
  if percentage_change > 0:
880
- comparison_period_text_prefix = "slower than "
880
+ comparison_period_text_prefix = "longer than "
881
881
  elif percentage_change < 0:
882
- comparison_period_text_prefix = "faster than "
882
+ comparison_period_text_prefix = "shorter than "
883
883
  else:
884
884
  comparison_period_text_prefix = "unchanged from "
885
885
 
@@ -64,6 +64,7 @@ class TimeSeriesChart:
64
64
  filtered_df: pl.DataFrame,
65
65
  trace_name_list: list[str],
66
66
  dashed_trace_name_list: list[str] = None,
67
+ trace_colour_groups: list[str, str] = None,
67
68
  initially_hidden_traces: Optional[list[str]] = None,
68
69
  hover_data_for_traces_with_different_hover_for_last_point: Optional[
69
70
  HoverDataByTrace
@@ -99,6 +100,7 @@ class TimeSeriesChart:
99
100
  self.filtered_df = filtered_df
100
101
  self.trace_name_list = trace_name_list
101
102
  self.dashed_trace_name_list = dashed_trace_name_list
103
+ self.trace_colour_groups = trace_colour_groups
102
104
  self.initially_hidden_traces = initially_hidden_traces
103
105
  self.legend_dict = legend_dict
104
106
  self.trace_name_column = trace_name_column
@@ -677,27 +679,97 @@ class TimeSeriesChart:
677
679
  return df_list
678
680
 
679
681
  def _get_colour_list(self):
680
- """Returns a list of colours."""
682
+ """Returns a list of colours (one per trace in trace_name_list).
683
+
684
+ If `trace_colour_groups` is provided, traces in the same group share a colour.
685
+ Traces not in any group get their own colour from the palette.
686
+ """
687
+ palette = self._get_base_palette()
688
+ palette = self._apply_colour_shift(palette)
689
+
690
+ groups = getattr(self, "trace_colour_groups", None) or []
691
+ if not groups:
692
+ return palette[: len(self.trace_name_list)]
693
+
694
+ trace_to_group_id = self._build_trace_to_group_id(groups)
695
+ return self._assign_colours_with_groups(palette, trace_to_group_id)
696
+
697
+ def _get_base_palette(self) -> list[str]:
681
698
  number_of_traces = len(self.trace_name_list)
682
699
  if number_of_traces == 2 and self.filled_traces_dict is None:
683
- colour_list = [
700
+ return [
684
701
  AFAccessibleColours.DARK_BLUE.value,
685
702
  AFAccessibleColours.ORANGE.value,
686
- ] # if 2 lines should use dark blue & orange as have highest contrast ratio
687
- else:
688
- colour_list = AFAccessibleColours.CATEGORICAL.value.copy()
703
+ ]
704
+ return AFAccessibleColours.CATEGORICAL.value.copy()
705
+
706
+ def _apply_colour_shift(self, palette: list[str]) -> list[str]:
707
+ """Apply number_of_traces_colour_shift_dict; may replace palette with explicit list."""
708
+ number_of_traces = len(self.trace_name_list)
689
709
  colour_shift_dict = (
690
710
  {"default": 0}
691
711
  if self.number_of_traces_colour_shift_dict is None
692
712
  else self.number_of_traces_colour_shift_dict
693
713
  )
694
-
695
714
  colour_shift_value = colour_shift_dict.get(
696
715
  number_of_traces, colour_shift_dict["default"]
697
716
  )
717
+
698
718
  if isinstance(colour_shift_value, list):
699
- return colour_shift_value # list of colours
700
- while colour_shift_value > 0:
701
- colour_list.append(colour_list.pop(0))
702
- colour_shift_value -= 1
703
- return colour_list
719
+ return colour_shift_value
720
+
721
+ # rotate left by colour_shift_value
722
+ shift = int(colour_shift_value)
723
+ if shift <= 0:
724
+ return palette
725
+
726
+ shift = shift % len(palette)
727
+ return palette[shift:] + palette[:shift]
728
+
729
+ def _build_trace_to_group_id(self, groups: list[list[str]]) -> dict[str, int]:
730
+ """Validate groups and return a mapping of trace -> group_id."""
731
+ trace_set = set(self.trace_name_list)
732
+ trace_to_group_id: dict[str, int] = {}
733
+
734
+ for group_id, group in enumerate(groups):
735
+ for trace in group:
736
+ if trace not in trace_set:
737
+ raise ValueError(
738
+ f"trace_colour_groups contains '{trace}', but it's not in trace_name_list."
739
+ )
740
+ if trace in trace_to_group_id:
741
+ raise ValueError(
742
+ f"Trace '{trace}' appears in more than one trace_colour_group."
743
+ )
744
+ trace_to_group_id[trace] = group_id
745
+
746
+ return trace_to_group_id
747
+
748
+ def _assign_colours_with_groups(
749
+ self,
750
+ palette: list[str],
751
+ trace_to_group_id: dict[str, int],
752
+ ) -> list[str]:
753
+ """Assign one colour per group (first-seen), and one per ungrouped trace."""
754
+ group_colour: dict[int, str] = {}
755
+ trace_colour: dict[str, str] = {}
756
+ colour_idx = 0
757
+
758
+ # assign colours to groups in order of first appearance in trace_name_list
759
+ for trace in self.trace_name_list:
760
+ group_id = trace_to_group_id.get(trace)
761
+ if group_id is not None and group_id not in group_colour:
762
+ group_colour[group_id] = palette[colour_idx % len(palette)]
763
+ colour_idx += 1
764
+
765
+ # apply group colours to grouped traces
766
+ for trace, group_id in trace_to_group_id.items():
767
+ trace_colour[trace] = group_colour[group_id]
768
+
769
+ # assign colours to ungrouped traces
770
+ for trace in self.trace_name_list:
771
+ if trace not in trace_colour:
772
+ trace_colour[trace] = palette[colour_idx % len(palette)]
773
+ colour_idx += 1
774
+
775
+ return [trace_colour[t] for t in self.trace_name_list]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gov_uk_dashboards
3
- Version: 26.25.0
3
+ Version: 26.26.0
4
4
  Summary: Provides access to functionality common to creating a data dashboard.
5
5
  Author: Department for Levelling Up, Housing and Communities
6
6
  Description-Content-Type: text/markdown
@@ -10,7 +10,7 @@ setup(
10
10
  author="Department for Levelling Up, Housing and Communities",
11
11
  description="Provides access to functionality common to creating a data dashboard.",
12
12
  name="gov_uk_dashboards",
13
- version="26.25.0",
13
+ version="26.26.0",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
16
16
  packages=find_packages(),