@cdc/dashboard 4.26.3 → 4.26.5

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 (151) hide show
  1. package/CONFIG.md +219 -0
  2. package/README.md +60 -20
  3. package/dist/cdcdashboard-CY9IcPSi.es.js +6 -0
  4. package/dist/cdcdashboard-DlpiY3fQ.es.js +4 -0
  5. package/dist/cdcdashboard.js +61559 -58048
  6. package/examples/__data__/data-2.json +6 -0
  7. package/examples/__data__/data.json +6 -0
  8. package/examples/dashboard-conditions-filters-incomplete.json +221 -0
  9. package/examples/dashboard-missing-datasets-multi.json +174 -0
  10. package/examples/dashboard-missing-datasets-single.json +121 -0
  11. package/examples/dashboard-multi-dashboard-version-regression.json +146 -0
  12. package/examples/dashboard-shared-filter-row-delete-cleanup.json +186 -0
  13. package/examples/dashboard-stale-dataset-keys.json +181 -0
  14. package/examples/dashboard-tiered-filter-regression.json +190 -0
  15. package/examples/legend-issue.json +1 -1
  16. package/examples/minimal-example.json +34 -0
  17. package/examples/private/cfa-dashboard.json +651 -0
  18. package/examples/private/data-bite-wrap.json +6936 -0
  19. package/examples/private/dengue.json +4640 -0
  20. package/examples/private/link_to_file.json +16662 -0
  21. package/examples/private/multi-dash-fix.json +16963 -0
  22. package/examples/private/versions.json +41612 -0
  23. package/examples/sankey.json +3 -3
  24. package/examples/test-api-filter-reset.json +4 -4
  25. package/examples/tp5-test.json +86 -4
  26. package/examples/us-map-filter-example.json +1074 -0
  27. package/package.json +9 -9
  28. package/src/CdcDashboard.tsx +6 -2
  29. package/src/CdcDashboardComponent.tsx +179 -88
  30. package/src/DashboardCopyPasteContext.test.tsx +33 -0
  31. package/src/DashboardCopyPasteContext.tsx +48 -0
  32. package/src/_stories/Dashboard.EditorRegression.stories.tsx +72 -0
  33. package/src/_stories/Dashboard.Regression.stories.tsx +196 -0
  34. package/src/_stories/Dashboard.Zoom.stories.tsx +88 -0
  35. package/src/_stories/Dashboard.smoke.stories.tsx +33 -0
  36. package/src/_stories/Dashboard.stories.tsx +337 -2
  37. package/src/_stories/FilteredTextMigrationComparison.stories.tsx +87 -0
  38. package/src/_stories/_mock/dashboard-data-driven-colors.json +171 -0
  39. package/src/_stories/_mock/tp5-test.json +86 -5
  40. package/src/components/Column.test.tsx +176 -0
  41. package/src/components/Column.tsx +214 -13
  42. package/src/components/DashboardConditionModal.test.tsx +420 -0
  43. package/src/components/DashboardConditionModal.tsx +367 -0
  44. package/src/components/DashboardConditionSummary.tsx +59 -0
  45. package/src/components/DashboardEditors.tsx +23 -0
  46. package/src/components/DashboardFilters/DashboardFilters.test.tsx +267 -0
  47. package/src/components/DashboardFilters/DashboardFilters.tsx +193 -172
  48. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.test.tsx +164 -0
  49. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +46 -6
  50. package/src/components/DashboardFilters/DashboardFiltersEditor/components/APIModal.tsx +5 -3
  51. package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx +59 -58
  52. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.test.tsx +304 -0
  53. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +43 -36
  54. package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +2 -2
  55. package/src/components/DashboardFilters/DashboardFiltersWrapper.test.tsx +142 -0
  56. package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +32 -27
  57. package/src/components/DashboardFilters/dashboardfilter.styles.css +42 -27
  58. package/src/components/DataDesignerModal.tsx +2 -1
  59. package/src/components/ExpandCollapseButtons.tsx +6 -4
  60. package/src/components/Grid.tsx +12 -7
  61. package/src/components/Header/Header.tsx +36 -17
  62. package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +141 -140
  63. package/src/components/Row.test.tsx +228 -0
  64. package/src/components/Row.tsx +104 -28
  65. package/src/components/VisualizationRow.test.tsx +396 -0
  66. package/src/components/VisualizationRow.tsx +177 -51
  67. package/src/components/VisualizationsPanel/VisualizationsPanel.test.tsx +49 -0
  68. package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +14 -13
  69. package/src/components/Widget/Widget.test.tsx +218 -0
  70. package/src/components/Widget/Widget.tsx +123 -20
  71. package/src/components/Widget/widget.styles.css +58 -14
  72. package/src/components/dashboard-condition-modal.css +76 -0
  73. package/src/components/dashboard-condition-summary.css +87 -0
  74. package/src/data/initial-state.js +1 -0
  75. package/src/helpers/addValuesToDashboardFilters.ts +3 -5
  76. package/src/helpers/addVisualization.ts +17 -4
  77. package/src/helpers/cloneDashboardWidget.ts +127 -0
  78. package/src/helpers/dashboardColumnWidgets.ts +99 -0
  79. package/src/helpers/dashboardConditionUi.ts +47 -0
  80. package/src/helpers/dashboardConditions.ts +200 -0
  81. package/src/helpers/dashboardFilterTargets.ts +156 -0
  82. package/src/helpers/filterData.ts +4 -9
  83. package/src/helpers/filterVisibility.ts +20 -0
  84. package/src/helpers/formatConfigBeforeSave.ts +2 -2
  85. package/src/helpers/getFilteredData.ts +18 -5
  86. package/src/helpers/getUpdateConfig.ts +43 -12
  87. package/src/helpers/getVizRowColumnLocator.ts +11 -1
  88. package/src/helpers/iconHash.tsx +9 -3
  89. package/src/helpers/mapDataToConfig.ts +31 -29
  90. package/src/helpers/reloadURLHelpers.ts +25 -5
  91. package/src/helpers/removeDashboardFilter.ts +33 -33
  92. package/src/helpers/tests/addVisualization.test.ts +53 -9
  93. package/src/helpers/tests/cloneDashboardWidget.test.ts +136 -0
  94. package/src/helpers/tests/dashboardColumnWidgets.test.ts +99 -0
  95. package/src/helpers/tests/dashboardConditionUi.test.ts +41 -0
  96. package/src/helpers/tests/dashboardConditions.test.ts +428 -0
  97. package/src/helpers/tests/formatConfigBeforeSave.test.ts +51 -0
  98. package/src/helpers/tests/getFilteredData.test.ts +265 -86
  99. package/src/helpers/tests/getUpdateConfig.test.ts +338 -0
  100. package/src/helpers/tests/reloadURLHelpers.test.ts +394 -238
  101. package/src/index.tsx +6 -3
  102. package/src/scss/grid.scss +281 -22
  103. package/src/scss/main.scss +215 -64
  104. package/src/store/dashboard.actions.ts +17 -4
  105. package/src/store/dashboard.reducer.test.ts +538 -0
  106. package/src/store/dashboard.reducer.ts +136 -22
  107. package/src/test/CdcDashboard.test.jsx +24 -0
  108. package/src/test/CdcDashboard.test.tsx +148 -0
  109. package/src/test/CdcDashboardComponent.test.tsx +935 -2
  110. package/src/types/ConfigRow.ts +15 -0
  111. package/src/types/DashboardFilters.ts +4 -0
  112. package/src/types/SharedFilter.ts +2 -0
  113. package/tests/fixtures/dashboard-config-with-metadata.json +1 -1
  114. package/dist/cdcdashboard-vr9HZwRt.es.js +0 -6
  115. package/examples/DEV-6574.json +0 -2224
  116. package/examples/api-dashboard-data.json +0 -272
  117. package/examples/api-dashboard-years.json +0 -11
  118. package/examples/api-geographies-data.json +0 -11
  119. package/examples/chart-data.json +0 -5409
  120. package/examples/custom/css/respiratory.css +0 -236
  121. package/examples/custom/js/respiratory.js +0 -242
  122. package/examples/default-data.json +0 -368
  123. package/examples/default-filter-control.json +0 -209
  124. package/examples/default-multi-dataset-shared-filter.json +0 -1729
  125. package/examples/default-multi-dataset.json +0 -506
  126. package/examples/ed-visits-county-file.json +0 -402
  127. package/examples/filters/Alabama.json +0 -72
  128. package/examples/filters/Alaska.json +0 -1737
  129. package/examples/filters/Arkansas.json +0 -4713
  130. package/examples/filters/California.json +0 -212
  131. package/examples/filters/Colorado.json +0 -1500
  132. package/examples/filters/Connecticut.json +0 -559
  133. package/examples/filters/Delaware.json +0 -63
  134. package/examples/filters/DistrictofColumbia.json +0 -63
  135. package/examples/filters/Florida.json +0 -4217
  136. package/examples/filters/States.json +0 -146
  137. package/examples/state-level.json +0 -90136
  138. package/examples/state-points.json +0 -10474
  139. package/examples/temp-example-data.json +0 -130
  140. package/examples/test-dashboard-simple.json +0 -503
  141. package/examples/test-example.json +0 -752
  142. package/examples/test-file.json +0 -147
  143. package/examples/test.json +0 -752
  144. package/examples/testing.json +0 -94456
  145. /package/examples/{data → __data__}/data-with-metadata.json +0 -0
  146. /package/examples/{legend-issue-data.json → __data__/legend-issue-data.json} +0 -0
  147. /package/examples/api-test/{categories.json → __data__/categories.json} +0 -0
  148. /package/examples/api-test/{chart-data.json → __data__/chart-data.json} +0 -0
  149. /package/examples/api-test/{topics.json → __data__/topics.json} +0 -0
  150. /package/examples/api-test/{years.json → __data__/years.json} +0 -0
  151. /package/src/_stories/{Dashboard.Pages.stories.tsx → Dashboard.Pages.smoke.stories.tsx} +0 -0
package/CONFIG.md ADDED
@@ -0,0 +1,219 @@
1
+ # `@cdc/dashboard` Configuration Reference
2
+
3
+ This document describes the supported configuration contract for `@cdc/dashboard`.
4
+
5
+ Shared nested types used by this package are documented in the [`@cdc/core` config reference](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/core/CONFIG.md).
6
+
7
+ To follow those shared types locally, use `packages/core/CONFIG.md` in this monorepo or `node_modules/@cdc/core/CONFIG.md` in an installed app. If neither path is available, use the GitHub link above.
8
+
9
+ ## Organization
10
+
11
+ The config is documented in the order users usually author a dashboard:
12
+
13
+ | Section | Covers |
14
+ | --- | --- |
15
+ | Identity and data source | How the dashboard is identified and where its data comes from |
16
+ | Dashboard shell | Title, theme, and shared dashboard chrome |
17
+ | Layout and visualization placement | Rows, columns, and widget placement |
18
+ | Dashboard filters widget | The `dashboardFilters` visualization that renders shared filters |
19
+ | Shared filters | Dashboard-level filter state and filter options |
20
+ | Table and download controls | Shared table/download settings used by the dashboard shell |
21
+ | Multi-dashboard support | Tabbed dashboard sets and the active tab |
22
+ | Fields You Can Ignore | Runtime, editor, and migrated artifacts |
23
+
24
+ ## Minimum Working Config
25
+
26
+ Use the example in [README.md](./README.md) for the copy-pasteable minimum config. The source of truth lives at `packages/dashboard/examples/minimal-example.json`, and the README block is kept in sync with automated tests.
27
+
28
+ ## Identity and Data Source
29
+
30
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
31
+ | --- | --- | --- | --- | --- | --- |
32
+ | `type` | `string` | Yes | None | Identifies the package. | Must be `dashboard`. |
33
+ | `version` | `string` | No | None | Saved COVE version for migration logic. | Use a semantic COVE version for authored configs so migrations can reason about saved-version order. |
34
+ | `locale` | `string` | No | `en-US` after migration/runtime preparation | Locale used by dashboard-level table date and number formatting and copied into child visualizations by migration. | Any valid `Intl` locale is accepted. |
35
+ | `data` | `object[]` | No | `[]` | Legacy inline data used to seed the dashboard when named datasets are not provided. | An empty array is enough for a dashboard that only renders markup or chrome. |
36
+ | `dataUrl` | `string` | No | None | Remote data source for legacy single-dataset dashboards. | When present, the loader fetches data at runtime. |
37
+ | `datasets` | `Record<string, DataSet>` | No | None | Named datasets used by the dashboard and its child visualizations. | Each child viz points at a dataset with `dataKey`. |
38
+ | `datasets.*.loadQueryParam` | `string` | No | None | Browser query-string parameter appended to that dataset's `dataUrl` at load time. | Used for dataset URLs that need to be varied by the embedding page's query string. |
39
+
40
+ Rows, datasets, and child visualizations also use the shared [`ConfigureData`](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/core/CONFIG.md#configuredata) fields described in the core reference. Named dataset entries use shared [`DataSet`](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/core/CONFIG.md#dataset).
41
+
42
+ ### Legacy Single-Dataset Fields
43
+
44
+ Older dashboard configs may store single-dataset metadata at the top level instead of under `datasets`.
45
+
46
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
47
+ | --- | --- | --- | --- | --- | --- |
48
+ | `dataDescription` | `Partial<DataDescription>` | No | None | Shared data-shaping metadata for legacy top-level `data` or `dataUrl`. | See shared [`DataDescription`](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/core/CONFIG.md#datadescription). Prefer `datasets.*.dataDescription` in new configs. |
49
+
50
+ During load and save cleanup, current dashboard flows prefer named `datasets`. Legacy top-level single-dataset file/runtime fields such as `dataFileName`, `dataFileSourceType`, and `formattedData` may still appear in old configs, but they are listed in `Fields You Can Ignore` rather than treated as authorable dashboard fields.
51
+
52
+ ## Dashboard Shell
53
+
54
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
55
+ | --- | --- | --- | --- | --- | --- |
56
+ | `dashboard.title` | `string` | No | `''` | Title shown in the dashboard header and table anchors. | Hidden when empty. |
57
+ | `dashboard.description` | `string` | No | `''` | Optional dashboard description rendered under the title. | Accepts HTML when the consuming app renders trusted markup. |
58
+ | `dashboard.theme` | `string` | No | `theme-blue` | Shared theme token for the dashboard shell. | See shared theme values in `@cdc/core`. |
59
+ | `dashboard.titleStyle` | `string` | No | `small` when the full dashboard initial state is used | Header size/style for the dashboard title. | `legacy`, `large`, `small`. If a partial `dashboard` object is shallow-merged without `titleStyle`, the field may remain undefined instead of receiving the initial-state value. |
60
+ | `dashboard.sharedFilters` | `SharedFilter[]` | No | `[]` | Dashboard-level filters that can drive multiple visualizations. | See the Shared Filters section below. |
61
+
62
+ ## Layout And Visualization Placement
63
+
64
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
65
+ | --- | --- | --- | --- | --- | --- |
66
+ | `rows` | `ConfigRow[]` | Yes | `[{ columns: [{ width: 12 }] }]` in practice | Layout rows that place widgets on the page. | The dashboard can render without explicit row chrome, but it needs at least one row for visible widgets. |
67
+ | `rows[].columns[]` | `object` | Yes | None | Column slots inside each row. | A column is populated when `widget` points to a visualization key, or when `conditionalWidgets` holds one or more candidate widgets. |
68
+ | `rows[].columns[].width` | `number` | Yes for visible columns | None | Column width in the dashboard grid. | `12` is a full-width column. Empty placeholder columns may omit `width` and are ignored by rendering. |
69
+ | `rows[].columns[].widget` | `string` | No | None | Visualization key rendered in that slot in simple mode. | Must match a key in `visualizations`. Ignored when `conditionalWidgets.length > 0`. |
70
+ | `rows[].columns[].toggleName` | `string` | No | Visualization type label | User-visible label for a widget in toggle rows. | Only meaningful when the parent row has `toggle: true`. When omitted, runtime falls back to labels such as `chart`, `map`, or `table`, not the child widget title. |
71
+ | `rows[].columns[].conditionalWidgets` | `ConditionalWidget[]` | No | None | Ordered candidate widgets for one column slot. | First matching entry wins. If no entry matches, the column renders empty. |
72
+ | `rows[].dashboardCondition` | `DashboardCondition` | No | None | Optional post-filter visibility rule for the entire row. | Evaluated after shared dashboard filtering; unresolved inputs hide the row. Not supported on toggle or multi-viz rows in v1. |
73
+ | `rows[].toggle` | `boolean` | No | `false` | Turns a row into a toggle row. | Only one column is shown at a time. |
74
+ | `rows[].equalHeight` | `boolean` | No | `false` | Forces equal-height cards within the row. | TP5 layouts may also trigger equalization automatically. |
75
+ | `rows[].multiVizColumn` | `string` | No | None | Column used to split one visualization into multiple cards. | Used by multi-viz dashboard flows. |
76
+ | `rows[].expandCollapseAllButtons` | `boolean` | No | `false` | Adds expand/collapse-all controls to multi-viz rows. | Only meaningful when `multiVizColumn` is set. |
77
+ | `visualizations` | `Record<string, AnyVisualization>` | Yes | `{}` in practice | Child visualizations rendered by the dashboard. | Each nested config follows the child package contract for `chart`, `map`, `data-bite`, `waffle-chart`, `markup-include`, `table`, or `dashboardFilters`. Legacy saved `filtered-text` configs migrate to `markup-include` in Phase 1; new authored text should use `markup-include`. |
78
+
79
+ Rows also accept the shared `ConfigureData` fields from the core reference, which the editor uses when a row owns its own dataset.
80
+
81
+ ## Dashboard Filters Widget
82
+
83
+ The dashboard package includes a `dashboardFilters` visualization that renders shared filters in the dashboard shell.
84
+
85
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
86
+ | --- | --- | --- | --- | --- | --- |
87
+ | `visualizations.*.type` | `string` | Yes | None | Must identify the widget as a dashboard filter panel. | Must be `dashboardFilters`. |
88
+ | `visualizations.*.visualizationType` | `string` | No | Usually `dashboardFilters` | Visualization identifier used by some dashboard-filter load paths. | Keep this aligned with `type` for dashboard filter widgets. |
89
+ | `visualizations.*.sharedFilterIndexes` | `number[]` | Yes | None | Indexes into `dashboard.sharedFilters` that this widget renders. | Order matters and matches the visual order in the panel. |
90
+ | `visualizations.*.filterBehavior` | `FilterBehavior` | No | `Filter Change` | Controls whether selections apply immediately or wait for confirmation. | `Apply Button`, `Filter Change` |
91
+ | `visualizations.*.filterIntro` | `string` | No | `''` | Helper text shown above this dashboard filter widget's controls. | Supports the same parsed HTML treatment used by visualization filter intro text. |
92
+ | `visualizations.*.applyFiltersButtonText` | `string` | No | `GO!` | Label for the apply button when apply-button behavior is enabled. | Only used when `filterBehavior` is `Apply Button`. |
93
+ | `visualizations.*.autoLoad` | `boolean` | No | `false` | Auto-selects and loads API-backed URL filter values for this dashboard-filter widget. | Mainly used with `Filter Change` widgets after parent-filter updates or query-parameter seeding; it is not limited to apply-button dashboards. |
94
+ | `visualizations.*.showClearButton` | `boolean` | No | `true` | Shows the clear-filters button in apply-button mode. | Only used when `filterBehavior` is `Apply Button`. |
95
+ | `visualizations.*.visual.grayBackground` | `boolean` | No | `false` | Wraps the rendered dashboard filters in the grey callout background treatment. | Uses the shared callout styling with dashboard-filter background color `#f4f8fa`. |
96
+
97
+ ## Shared Filters
98
+
99
+ Dashboard filters are split between the dashboard shell and the `dashboardFilters` widget that renders them.
100
+
101
+ Dashboard `SharedFilter` objects are a distinct dashboard-owned contract. They reuse a few primitive ideas from core filter helpers, but they are not the same shape as core `VizFilter`. Runtime/cache state such as active selections is listed in `Fields You Can Ignore`; data-filter value lists can be authored or preserved as described below.
102
+
103
+ ### Common Filter Fields
104
+
105
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
106
+ | --- | --- | --- | --- | --- | --- |
107
+ | `dashboard.sharedFilters[].key` | `string` | Yes | None | Human-readable filter label and stable key. | Used as the display label and editor key. |
108
+ | `dashboard.sharedFilters[].type` | `string` | No | `''` | Filter mode. | `datafilter`, `urlfilter`, or empty while configuring. |
109
+ | `dashboard.sharedFilters[].filterStyle` | `string` | No | `dropdown` | Filter control style. | `combobox`, `dropdown`, `multi-select`, `nested-dropdown`, `tab-simple` |
110
+ | `dashboard.sharedFilters[].note` | `string` | No | None | Optional helper text shown under the filter label and above the control. | Parsed as trusted inline HTML. |
111
+ | `dashboard.sharedFilters[].showDropdown` | `boolean` | No | Editor-seeded `true` | Shows the filter control in the dashboard. | The editor usually writes this field, but normal runtime value generation does not default missing `showDropdown` for data filters. Hiding the dropdown does not hide an individual URL filter, nested-dropdown, or tab-simple renderer, but a dashboard filter widget renders nothing when all referenced filters are hidden. |
112
+ | `dashboard.sharedFilters[].order` | `string` | No | `asc` | Sort order for generated filter values. | `cust`, `desc`, `asc`, `column`. `column` is exposed by the editor, but dashboard value generation currently does not apply column-based ordering. |
113
+ | `dashboard.sharedFilters[].orderedValues` | `string[]` | No | None | Custom display order when `order` is `cust`. | Preserved by editor and runtime sort helpers. |
114
+ | `dashboard.sharedFilters[].parents` | `string[]` | No | `[]` | Parent filter labels for nested filter chains. | Used by cascading URL and data filters. |
115
+ | `dashboard.sharedFilters[].usedBy` | `(string \| number)[]` | No | None | Widgets or rows that consume the filter. | Numbers refer to row indexes; strings refer to visualization keys. Dashboard conditions inherit the same row or widget target as the content they control. Missing `usedBy` and `usedBy: []` are unscoped/global for row, visualization, and dashboard-condition filtered-data paths. |
116
+ | `dashboard.sharedFilters[].setByQueryParameter` | `string` | No | None | Query-string parameter used to seed the active value. | Used by both data and URL filters for deep links and parent-child filter flows. |
117
+ | `dashboard.sharedFilters[].defaultValue` | `string` | No | None | Default selection when no other active value is available. | Used by data and nested-dropdown filters. |
118
+ | `dashboard.sharedFilters[].resetLabel` | `string` | No | None | Reset option label. | Often shown as `All`, `Reset`, or similar. |
119
+ | `dashboard.sharedFilters[].labels` | `Record<string, string>` | No | None | Alternate display labels for raw values. | Shared label mapping from `@cdc/core`. |
120
+ | `dashboard.sharedFilters[].selectLimit` | `number` | No | `5` in multi-select UI | Maximum selections allowed in multi-select mode. | Only used when `filterStyle` is `multi-select`. |
121
+ | `dashboard.sharedFilters[].displaySubgroupingOnly` | `boolean` | No | `false` | Shows only subgrouping controls for nested-dropdown filters. | Only used by nested dropdown flows. |
122
+ | `dashboard.sharedFilters[].subGrouping` | `SubGrouping` | No | None | Nested dropdown subgroup state. | Used by data and URL nested-dropdown filters. Dashboard honors `subGrouping.defaultValue`; see `SubGrouping` below for persisted option metadata. |
123
+
124
+ ### Data Filter Fields
125
+
126
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
127
+ | --- | --- | --- | --- | --- | --- |
128
+ | `dashboard.sharedFilters[].columnName` | `string` | Yes for `datafilter` | None | Source column used to generate filter values. | Must exist in the active dataset. |
129
+ | `dashboard.sharedFilters[].values` | `string[]` | No | Generated from data when omitted | Values shown by data filters. | Preconfigured non-empty values are preserved; URL-filter values are generated from API state and usually do not need to be authored. |
130
+ | `dashboard.sharedFilters[].setBy` | `string` | No | None | Visualization key that seeds the filter from its selected datum. | Only used by data filters. |
131
+
132
+ ### URL Filter Fields
133
+
134
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
135
+ | --- | --- | --- | --- | --- | --- |
136
+ | `dashboard.sharedFilters[].apiFilter` | `APIFilter` | Yes for API-backed URL filters | None | Metadata for remote option loading. | See notes below. |
137
+ | `dashboard.sharedFilters[].filterBy` | `string` | No | None | URL filter behavior. | `Query String` or `File Name` |
138
+ | `dashboard.sharedFilters[].queryParameter` | `string` | No | None | Query-string parameter name to update. | Used by `Query String` URL filters. |
139
+ | `dashboard.sharedFilters[].datasetKey` | `string` | No | None | Dataset key whose filename should be rewritten. | Required when `filterBy` is `File Name`. |
140
+ | `dashboard.sharedFilters[].fileName` | `string` | No | None | File-name template for file-name URL filters. | Can include `${query}` as a placeholder for the active filter value. |
141
+ | `dashboard.sharedFilters[].whitespaceReplacement` | `string` | No | `Keep Spaces` | How spaces are rewritten in file-name filters. | `Keep Spaces`, `Remove Spaces`, `Replace With Underscore` |
142
+
143
+ ## Dashboard Conditions
144
+
145
+ Dashboard conditions are optional visibility rules owned by rows and conditional widget entries.
146
+
147
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
148
+ | --- | --- | --- | --- | --- | --- |
149
+ | `rows[].dashboardCondition.id` | `string` | No | Auto-generated | Internal dashboard-condition id used for filtered-data cache keys and stable condition identity. | The editor generates ids like `condition-4fzzzxjy` and preserves existing ids once dashboard-condition authoring is enabled. It is not an author-facing shared-filter target. |
150
+ | `rows[].columns[].conditionalWidgets[].widget` | `string` | Yes in conditional mode | None | Visualization key for one candidate component in the column. | Must match a key in `visualizations`. Author order defines priority. |
151
+ | `rows[].columns[].conditionalWidgets[].dashboardCondition.id` | `string` | No | Auto-generated | Internal dashboard-condition id used for filtered-data cache keys and stable condition identity. | The editor generates ids like `condition-8fzzzbjm` for new conditions and keeps older saved ids unchanged. It is not an author-facing shared-filter target. Scope component conditions with the owning visualization key or row index instead. |
152
+ | `*.dashboardCondition.datasetKey` | `string` | Yes except for `filtersIncomplete` | None | Dataset used to evaluate data-backed dashboard conditions. | May differ from the visualization dataset. Not used by `filtersIncomplete`. |
153
+ | `*.dashboardCondition.operator` | `string` | Yes when a dashboard condition is enabled | None | Dashboard-condition comparison mode. | `hasData`, `hasNoData`, `columnHasAnyValue`, `filtersIncomplete` |
154
+ | `*.dashboardCondition.columnName` | `string` | Only for `columnHasAnyValue` | None | Dataset column inspected by the dashboard condition. | Must exist in the dashboard-condition dataset. |
155
+ | `*.dashboardCondition.values` | `string[]` | Only for `columnHasAnyValue` | `[]` | One or more acceptable values. | Runtime uses loose string coercion so numeric dataset values can match authored strings. |
156
+
157
+ | Behavior | Details |
158
+ | --- | --- |
159
+ | Shared filter application | Conditions apply unscoped filters plus filters targeted to the content they control. Row conditions inherit the row index target. Component conditions inherit the same target their component data would use: the row index when data is configured on the row, otherwise the owning visualization key. Filters whose `columnName` is missing from the condition dataset are ignored for data-backed conditions. |
160
+ | `filtersIncomplete` targeting | `filtersIncomplete` uses the same inherited row or widget target as other dashboard conditions and includes unscoped filters. It passes only when an applicable visible filter is at reset state, and ignores filters scoped to unrelated targets. Use it for static helper content, such as a markup include message. It replaces the default incomplete-filter message but does not make ordinary data-backed rows or widgets render while filters are incomplete. |
161
+ | Unresolved inputs | For data-backed operators, if the condition dataset is unavailable or an applicable filter is still at reset state, the condition resolves as hidden rather than behaving like `hasNoData`. `filtersIncomplete` resolves from filter reset state instead of dataset availability. |
162
+ | Conditional columns | `conditionalWidgets` lets one dashboard column hold multiple candidate components while still rendering as one slot. Runtime uses the first matching entry in author order. |
163
+ | Simple/conditional cleanup | The editor automatically collapses conditional mode back to simple mode when only one unconditioned entry remains after a completed save or delete action. |
164
+ | Row suppression | A false row condition hides the full row. A no-match conditional column hides only that widget slot while preserving grid width. |
165
+ | v1 limitations | Toggle rows and multi-viz rows do not expose condition editing in the editor, and runtime ignores any condition config found there. |
166
+
167
+ ### `APIFilter`
168
+
169
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
170
+ | --- | --- | --- | --- | --- | --- |
171
+ | `apiEndpoint` | `string` | Yes | None | Endpoint used to fetch filter options. | Must resolve to JSON data. |
172
+ | `valueSelector` | `string` | Yes | None | Field used as the stored filter value. | Required. |
173
+ | `textSelector` | `string` | No | `''` | Field used as the visible filter label. | When omitted or blank, runtime falls back to `valueSelector` for the displayed option text. |
174
+ | `subgroupValueSelector` | `string` | Yes for API-backed nested dropdowns | None | Nested subgroup value field for nested dropdowns. | Required when an API-backed filter uses nested subgrouping. |
175
+ | `subgroupTextSelector` | `string` | No | None | Nested subgroup label field for nested dropdowns. | Only used when nested subgrouping is enabled. |
176
+
177
+ ### `SubGrouping`
178
+
179
+ Dashboard nested-dropdown filters use the shared [`SubGrouping`](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/core/CONFIG.md#subgrouping) structure from core. Dashboard-specific behavior to remember: `subGrouping.defaultValue` can seed the active subgroup when no query parameter or existing active subgroup is available, and `subGrouping.valuesLookup` is persisted option metadata for data-backed nested dropdowns.
180
+
181
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
182
+ | --- | --- | --- | --- | --- | --- |
183
+ | `subGrouping.columnName` | `string` | Yes for nested data filters | None | Source column used to compute subgroup values. | Must exist in the dataset for data filters. |
184
+ | `subGrouping.setByQueryParameter` | `string` | No | None | Query-string parameter used to seed the active subgroup value. | Used by dashboard nested-dropdown filters for deep links and query-parameter initialization. |
185
+ | `subGrouping.valuesLookup` | `Record<string, { values: string[]; orderedValues?: string[] }>` | Yes for data nested dropdowns | None | Lookup of subgroup values by parent filter value. | Runtime derives nested options from this object. URL nested dropdowns can receive equivalent option state from API filter loading. |
186
+ | `subGrouping.defaultValue` | `string` | No | None | Default nested selection when no query parameter or active value applies. | Must match a value in the current subgroup. |
187
+
188
+ ## Table And Download Controls
189
+
190
+ `@cdc/dashboard` uses the shared `Table` structure from the core reference. In this package, the dashboard shell honors the shared table flags plus `table.downloadImageButton` for image downloads. When image downloads are enabled, `table.downloadImageButtonStyle` may be `button` or `link`; omitted values use legacy button styling. `table.downloadPdfButton` can render a PDF action, but the shared media handler currently reports PDF downloads as disabled.
191
+
192
+ The runtime defaults are the dashboard shell table settings from `packages/dashboard/src/data/initial-state.js`: `label: 'Data Table'`, `show: true`, `showDownloadUrl: false`, `downloadUrlLabel: ''`, `showDownloadLinkBelow: true`, and `showVertical: true`.
193
+
194
+ ## Multi-Dashboard Support
195
+
196
+ | Field | Type | Required | Default | Description | Allowed values / Notes |
197
+ | --- | --- | --- | --- | --- | --- |
198
+ | `multiDashboards` | `MultiDashboard[]` | No | None | Optional tabbed dashboard set. | Each entry contains its own `dashboard`, `rows`, `visualizations`, and `label`. |
199
+ | `multiDashboards[].label` | `string` | Yes | None | Label shown on the dashboard tab. | Required for each dashboard slot. |
200
+
201
+ ## Fields You Can Ignore
202
+
203
+ These fields often appear in saved configs, editor exports, or migration output, but consumers usually do not need to author them:
204
+
205
+ | Field or group | Why you can ignore it |
206
+ | --- | --- |
207
+ | `runtime.*` | Internal runtime state created during load and render. |
208
+ | Top-level `uuid`, `id`, `category`, `subType`, `orientation`, and `label` | Export/editor metadata that may appear around dashboard configs; these are not required for rendering. |
209
+ | `migrations.*` | Migration bookkeeping that records which update steps have run. |
210
+ | `visualizations.*.formattedData`, `visualizations.*.originalFormattedData`, `visualizations.*.runtime` | Generated data and runtime artifacts owned by the loader. |
211
+ | `visualizations.*.dashboardFilters` | Runtime helper snapshot of active dashboard shared filters used by markup/filter processing. Author `dashboard.sharedFilters` instead. |
212
+ | `visualizations.*.editing`, `visualizations.*.showEditorPanel`, `visualizations.*.newViz`, `visualizations.*.openModal` | Editor state, not consumer config. |
213
+ | `visualizations.*.uid` | Editor/runtime identifier that is injected or normalized internally. |
214
+ | `datasets.*.dataFileSize`, `datasets.*.dataFileName`, `datasets.*.dataFileFormat`, `datasets.*.dataFileSourceType`, `datasets.*.runtimeDataUrl` | Runtime or file metadata. |
215
+ | Top-level `dataFileName`, `dataFileSourceType`, and `formattedData` | Legacy single-dataset metadata/runtime output. Prefer named `datasets` for new configs. |
216
+ | `rows[].uuid`, `rows[].columns[].hide`, `rows[].columns[].equalHeight`, `rows[].originalMultiVizColumn` | Layout bookkeeping that may be injected or updated by the editor. |
217
+ | `dashboard.sharedFilters[].tier`, `dashboard.sharedFilters[].active`, `dashboard.sharedFilters[].queuedActive`, and `dashboard.sharedFilters[].subGrouping.active` | Runtime/cache filter state. These may be present in saved configs, but consumers usually only author stable filter definitions plus optional defaults. |
218
+ | `dashboard.filters` | Legacy migration field replaced by `dashboard.sharedFilters`. |
219
+ | `activeDashboard` | Runtime-managed active tab index for multi-dashboard sets. |
package/README.md CHANGED
@@ -2,35 +2,75 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@cdc/dashboard)](https://www.npmjs.com/package/@cdc/dashboard)
4
4
 
5
- `<CdcDashboard />` is a React component produced by the CDC for combining multiple visualizations into a single module. Some supported visualization types are CdcMap and CdcChart. This package is part of the larger [CDC Open Visualization](https://github.com/CDCgov/cdc-open-viz) project.
5
+ `<CdcDashboard />` combines multiple visualizations into a single dashboard shell.
6
+ The primary configuration reference is [CONFIG.md](./CONFIG.md).
6
7
 
7
- ### Installation and Usage
8
+ ## Installation
8
9
 
9
- 1. Install the package in your React project `npm install @cdc/dashboard`
10
- 2. Import the component and begin using in your code.
10
+ ```bash
11
+ npm install @cdc/dashboard
12
+ ```
11
13
 
12
- ```JSX
13
- import CdcChart from '@cdc/dashboard'
14
+ ## Quick Start
14
15
 
15
- function App() {
16
+ Use the package by passing a `config` object directly:
16
17
 
17
- return (
18
- <div className="App">
19
- <CdcDashboard config={configObj} />
20
- </div>
21
- );
18
+ <!-- README_EXAMPLE_CONFIG_START -->
19
+ ```jsx
20
+ import CdcDashboard from '@cdc/dashboard'
21
+
22
+ const config = {
23
+ type: 'dashboard',
24
+ version: '4.26.4',
25
+ dashboard: {
26
+ theme: 'theme-blue',
27
+ title: 'Dashboard Example',
28
+ titleStyle: 'small',
29
+ sharedFilters: []
30
+ },
31
+ data: [],
32
+ rows: [
33
+ {
34
+ columns: [
35
+ {
36
+ width: 12,
37
+ widget: 'markup-1'
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ visualizations: {
43
+ 'markup-1': {
44
+ type: 'markup-include',
45
+ theme: 'theme-blue',
46
+ contentEditor: {
47
+ inlineHTML: '<p>Minimal dashboard example</p>',
48
+ showHeader: true,
49
+ srcUrl: '',
50
+ title: 'Dashboard Example',
51
+ useInlineHTML: true
52
+ }
53
+ }
54
+ }
22
55
  }
23
56
 
24
- export default App;
57
+ function App() {
58
+ return <CdcDashboard config={config} />
59
+ }
60
+
61
+ export default App
25
62
  ```
63
+ <!-- README_EXAMPLE_CONFIG_END -->
64
+
65
+ ## Configuration
26
66
 
27
- Note, you must pass in a configuration object. Configuration objects can be created with the [Editor package](https://github.com/CDCgov/cdc-open-viz/tree/main/packages/editor).
67
+ The primary reference for authoring configs is [CONFIG.md](./CONFIG.md).
28
68
 
29
- Sample config data can be found in [packages/dashboard/examples](https://github.com/CDCgov/cdc-open-viz/tree/integration/packages/dashboard/examples).
69
+ If you are reading this in a context where relative Markdown links do not open correctly, use the [GitHub copy of the dashboard config reference](https://github.com/CDCgov/cdc-open-viz/blob/main/packages/dashboard/CONFIG.md).
30
70
 
31
- ### Properties
71
+ ## Properties
32
72
 
33
- | Property | Type | Description |
34
- | --------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
35
- | config | String | A JavaScript object with the configuration for the dashboard. Pass either this or the configUrl property to setup your dashboard. |
36
- | configUrl | String | Pass a URL to a .json file and it will be consumed and used as the configuration. |
73
+ | Property | Type | Description |
74
+ | --- | --- | --- |
75
+ | `config` | `object` | Dashboard configuration object. Pass this or `configUrl` to initialize the dashboard. |
76
+ | `configUrl` | `string` | URL to a JSON config file that will be fetched at runtime. |