@cdc/core 4.26.1 → 4.26.3

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 (249) hide show
  1. package/.claude/agents/qa-test-developer.md +126 -0
  2. package/CLAUDE.local.md +67 -0
  3. package/LICENSE +201 -0
  4. package/_stories/Gallery.Charts.stories.tsx +35 -42
  5. package/_stories/Gallery.DataBite.stories.tsx +15 -8
  6. package/_stories/Gallery.Maps.stories.tsx +37 -28
  7. package/_stories/Gallery.WaffleChart.stories.tsx +1 -1
  8. package/_stories/PageART.stories.tsx +5 -4
  9. package/_stories/PageBRFSS.stories.tsx +21 -16
  10. package/_stories/PageCancerRegistries.stories.tsx +15 -15
  11. package/_stories/PageEasternEquineEncephalitis.stories.tsx +33 -19
  12. package/_stories/PageExcessiveAlcoholUse.stories.tsx +148 -143
  13. package/_stories/PageMaternalMortality.stories.tsx +5 -4
  14. package/_stories/PageOralHealth.stories.tsx +15 -10
  15. package/_stories/PageRespiratory.stories.tsx +4 -4
  16. package/_stories/PageSmokingTobacco.stories.tsx +15 -10
  17. package/_stories/PageStateDiabetesProfiles.stories.tsx +15 -10
  18. package/_stories/PageWastewater.stories.tsx +44 -30
  19. package/_stories/VegaImport.stories.tsx +401 -0
  20. package/_stories/vega-fixtures/bars-with-line.json +444 -0
  21. package/_stories/vega-fixtures/bars.json +58 -0
  22. package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
  23. package/_stories/vega-fixtures/combo.json +68 -0
  24. package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
  25. package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
  26. package/_stories/vega-fixtures/horizontal-bar.json +427 -0
  27. package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
  28. package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
  29. package/_stories/vega-fixtures/lines.json +227 -0
  30. package/_stories/vega-fixtures/measles-bars.json +348 -0
  31. package/_stories/vega-fixtures/measles-map.json +11101 -0
  32. package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
  33. package/_stories/vega-fixtures/multi-dataset.json +255 -0
  34. package/_stories/vega-fixtures/no-data.json +14 -0
  35. package/_stories/vega-fixtures/pie-chart.json +94 -0
  36. package/_stories/vega-fixtures/repeat-spec.json +47 -0
  37. package/_stories/vega-fixtures/stacked-area.json +222 -0
  38. package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
  39. package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
  40. package/_stories/vega-fixtures/stacked-bars.json +212 -0
  41. package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
  42. package/_stories/vega-fixtures/warning-combo.json +59 -0
  43. package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
  44. package/assets/callout-flag.svg +7 -0
  45. package/assets/icon-chart-area.svg +1 -0
  46. package/assets/icon-chart-radar.svg +23 -0
  47. package/assets/logo2.svg +31 -0
  48. package/components/AdvancedEditor/EmbedEditor.tsx +270 -38
  49. package/components/Alert/components/Alert.styles.css +2 -2
  50. package/components/ComboBox/combobox.styles.css +48 -48
  51. package/components/CustomColorsEditor/CustomColorsEditor.css +53 -53
  52. package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
  53. package/components/DataTable/DataTable.tsx +46 -18
  54. package/components/DataTable/DataTableStandAlone.tsx +1 -0
  55. package/components/DataTable/components/ChartHeader.tsx +21 -12
  56. package/components/DataTable/components/MapHeader.tsx +34 -28
  57. package/components/DataTable/components/SortIcon/sort-icon.css +5 -5
  58. package/components/DataTable/data-table.css +50 -52
  59. package/components/DataTable/helpers/applyCustomOrder.ts +17 -0
  60. package/components/DataTable/helpers/getChartCellValue.ts +10 -7
  61. package/components/DataTable/helpers/getMapDataTableColumnKeys.ts +22 -0
  62. package/components/DataTable/helpers/getSeriesName.ts +6 -0
  63. package/components/DataTable/helpers/mapCellMatrix.tsx +33 -23
  64. package/components/DataTable/helpers/tests/mapCellMatrix.test.ts +33 -0
  65. package/components/DownloadButton.tsx +14 -6
  66. package/components/EditorPanel/ColumnsEditor.tsx +38 -31
  67. package/components/EditorPanel/CustomSortOrder.tsx +94 -0
  68. package/components/EditorPanel/DataTableEditor.tsx +139 -23
  69. package/components/EditorPanel/EditorPanel.styles.css +71 -71
  70. package/components/EditorPanel/EditorPanel.tsx +3 -8
  71. package/components/EditorPanel/EditorPanelDispatch.tsx +4 -4
  72. package/components/EditorPanel/FootnotesEditor.tsx +2 -2
  73. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +21 -12
  74. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +16 -10
  75. package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
  76. package/components/EditorPanel/components/MarkupVariablesEditor.tsx +160 -106
  77. package/components/EditorPanel/components/PanelMarkup.tsx +5 -1
  78. package/{styles/v2/components → components/EditorPanel}/editor.scss +76 -22
  79. package/components/EditorPanel/sections/StyleTreatmentSection.tsx +99 -0
  80. package/components/EditorPanel/sections/VisualSection.tsx +11 -0
  81. package/components/EditorWrapper/editor-wrapper.style.css +1 -1
  82. package/components/Filters/Filters.tsx +3 -5
  83. package/components/Filters/components/Tabs.tsx +19 -7
  84. package/{styles → components/Filters}/filters.scss +3 -3
  85. package/components/Footnotes/FootnotesStandAlone.tsx +4 -2
  86. package/components/HeaderThemeSelector/HeaderThemeSelector.css +61 -5
  87. package/components/Layout/components/Responsive.tsx +14 -6
  88. package/components/Layout/components/Sidebar/components/Sidebar.tsx +1 -1
  89. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +14 -20
  90. package/components/Layout/components/Visualization/index.tsx +50 -38
  91. package/components/Layout/components/Visualization/visualizations.scss +232 -15
  92. package/components/Layout/components/VisualizationContainer.test.tsx +67 -0
  93. package/components/Layout/components/VisualizationContainer.tsx +37 -0
  94. package/components/Layout/components/VisualizationContent.test.tsx +182 -0
  95. package/components/Layout/components/VisualizationContent.tsx +75 -0
  96. package/components/Layout/index.tsx +5 -5
  97. package/components/Layout/styles/editor-utils.scss +3 -3
  98. package/components/Layout/styles/editor.scss +4 -4
  99. package/components/Legend/Legend.Gradient.tsx +7 -1
  100. package/components/Loader/loader.styles.css +2 -2
  101. package/components/Loading.jsx +1 -1
  102. package/components/MediaControls.tsx +10 -3
  103. package/components/MultiSelect/multiselect.styles.css +19 -19
  104. package/components/NestedDropdown/nesteddropdown.styles.css +15 -15
  105. package/components/PaletteSelector/PaletteSelector.css +15 -15
  106. package/components/RichTooltip/richTooltip.css +6 -6
  107. package/components/Table/table.styles.css +2 -2
  108. package/components/Waiting.tsx +1 -1
  109. package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
  110. package/components/_stories/DataTable.stories.tsx +1 -0
  111. package/components/_stories/Filters.stories.tsx +1 -1
  112. package/components/_stories/styles.scss +0 -1
  113. package/components/elements/Button.jsx +1 -1
  114. package/components/elements/Card.jsx +1 -1
  115. package/{styles/v2/components → components/elements}/button.scss +9 -8
  116. package/components/inputs/InputCheckbox.jsx +1 -1
  117. package/components/inputs/InputSelect.tsx +1 -1
  118. package/components/inputs/InputText.jsx +1 -1
  119. package/components/inputs/InputToggle.tsx +1 -1
  120. package/{styles/v2/components/input → components/inputs}/_input-check-radio.scss +2 -2
  121. package/{styles/v2/components/input → components/inputs}/_input-group.scss +3 -3
  122. package/{styles/v2/components/input → components/inputs}/_input-slider.scss +2 -2
  123. package/{styles/v2/components/input → components/inputs}/_input.scss +5 -5
  124. package/{styles/v2/components/input → components/inputs}/index.scss +2 -2
  125. package/{styles → components}/loading.scss +1 -1
  126. package/components/managers/DataDesigner.tsx +1 -1
  127. package/{styles/v2/components → components/managers}/data-designer.scss +6 -7
  128. package/components/ui/Accordion.jsx +1 -1
  129. package/components/ui/Icon.tsx +1 -1
  130. package/components/ui/LoadSpin.jsx +1 -1
  131. package/components/ui/Modal.jsx +1 -1
  132. package/components/ui/Overlay.jsx +1 -1
  133. package/components/ui/Title/index.test.tsx +34 -0
  134. package/components/ui/Title/index.tsx +24 -7
  135. package/components/ui/Title/title.styles.css +119 -25
  136. package/components/ui/Tooltip.tsx +1 -1
  137. package/components/ui/_stories/Title.stories.tsx +1 -1
  138. package/{styles/v2/components → components/ui}/accordion.scss +3 -3
  139. package/components/ui/accordion.styles.css +11 -11
  140. package/{styles/v2/components → components/ui}/modal.scss +2 -2
  141. package/{styles/v2/components → components/ui}/overlay.scss +6 -6
  142. package/{styles/v2/components → components}/ui/tooltip.scss +1 -1
  143. package/{styles → components}/waiting.scss +9 -3
  144. package/data/colorPalettes.ts +18 -5
  145. package/data/mapColorPalettes.ts +10 -0
  146. package/devTemplate/dev.js +285 -0
  147. package/devTemplate/index.html +30 -0
  148. package/devTemplate/preview.html +1503 -0
  149. package/devTemplate/sidebar.css +151 -0
  150. package/dist/cove-main.css +2530 -3901
  151. package/dist/cove-main.css.map +1 -1
  152. package/generateViteConfig.js +111 -2
  153. package/helpers/DataTransform.ts +1 -5
  154. package/helpers/backfillDefaults.ts +35 -0
  155. package/helpers/constants.ts +12 -0
  156. package/helpers/cove/date.ts +64 -3
  157. package/helpers/cove/number.ts +29 -15
  158. package/helpers/cove/string.ts +29 -0
  159. package/helpers/coveUpdateWorker.ts +14 -8
  160. package/helpers/displayDataAsText.ts +1 -1
  161. package/helpers/embed/embedCodeGenerator.ts +80 -0
  162. package/helpers/embed/embedHelper.js +169 -0
  163. package/helpers/embed/filterUtils.ts +121 -0
  164. package/helpers/embed/index.ts +17 -0
  165. package/helpers/embed/urlValidation.ts +119 -0
  166. package/helpers/extractDataAndMetadata.ts +20 -0
  167. package/helpers/fetchRemoteData.ts +14 -8
  168. package/helpers/filterVizData.ts +6 -1
  169. package/helpers/getFileExtension.ts +0 -6
  170. package/helpers/labelHash.ts +9 -0
  171. package/helpers/markupProcessor.ts +56 -38
  172. package/helpers/metrics/types.ts +3 -0
  173. package/helpers/palettes/colorDistributions.ts +1 -1
  174. package/helpers/palettes/utils.ts +12 -12
  175. package/helpers/parseCsvWithQuotes.ts +15 -14
  176. package/helpers/prepareScreenshot.ts +33 -10
  177. package/helpers/testing.ts +44 -0
  178. package/helpers/tests/DataTransform.test.ts +125 -0
  179. package/helpers/tests/abbreviateNumber.test.ts +59 -0
  180. package/helpers/tests/backfillDefaults.test.ts +253 -0
  181. package/helpers/tests/date.test.ts +110 -0
  182. package/helpers/tests/extractDataAndMetadata.test.ts +93 -0
  183. package/helpers/tests/markupProcessor.test.ts +315 -124
  184. package/helpers/tests/number.test.ts +42 -0
  185. package/helpers/tests/prepareScreenshot.test.ts +28 -28
  186. package/helpers/tests/testStandaloneBuild.ts +36 -26
  187. package/helpers/tests/useDataVizClasses.test.ts +66 -0
  188. package/helpers/tests/visualizationWrapperUsage.test.ts +57 -0
  189. package/helpers/useDataVizClasses.ts +13 -7
  190. package/helpers/vegaConfig.ts +1 -1
  191. package/helpers/vegaConfigImport.ts +160 -0
  192. package/helpers/ver/4.24.4.ts +24 -0
  193. package/helpers/ver/4.26.1.ts +1 -1
  194. package/helpers/ver/4.26.2.ts +84 -0
  195. package/helpers/ver/4.26.3.ts +44 -0
  196. package/helpers/ver/4.26.4.ts +31 -0
  197. package/helpers/ver/tests/4.26.1.test.ts +105 -0
  198. package/helpers/ver/tests/4.26.2.test.ts +298 -0
  199. package/helpers/ver/tests/4.26.3.test.ts +168 -0
  200. package/helpers/ver/tests/4.26.4.test.ts +88 -0
  201. package/helpers/ver/tests/coveUpdateWorker.test.ts +57 -0
  202. package/helpers/viewports.ts +2 -0
  203. package/package.json +27 -32
  204. package/styles/_global.scss +7 -7
  205. package/styles/_reset.scss +2 -2
  206. package/styles/{v2/base → base}/_file-selector.scss +4 -4
  207. package/styles/{v2/base → base}/_general.scss +2 -4
  208. package/styles/{v2/base → base}/index.scss +1 -1
  209. package/styles/base.scss +107 -165
  210. package/styles/cove-main.scss +3 -6
  211. package/styles/layout/_component.scss +110 -0
  212. package/styles/{v2/layout → layout}/_data-table.scss +7 -7
  213. package/styles/layout/_wrapper-padding.scss +27 -0
  214. package/styles/{v2/main.scss → main.scss} +3 -1
  215. package/styles/{v2/themes → themes}/_color-definitions.scss +46 -41
  216. package/styles/{_accessibility.scss → utils/_accessibility.scss} +1 -1
  217. package/styles/{v2/utils → utils}/_grid.scss +8 -3
  218. package/styles/{_global-variables.scss → utils/_properties.scss} +133 -112
  219. package/styles/{v2/utils → utils}/index.scss +2 -1
  220. package/types/Annotation.ts +10 -11
  221. package/types/Axis.ts +2 -0
  222. package/types/ComponentStyles.ts +1 -0
  223. package/types/ConfigureData.ts +1 -0
  224. package/types/General.ts +2 -0
  225. package/types/MarkupInclude.ts +1 -0
  226. package/types/MarkupVariable.ts +2 -1
  227. package/types/Palette.ts +22 -0
  228. package/types/Table.ts +9 -0
  229. package/types/Visualization.ts +7 -0
  230. package/_stories/StoryRenderingTests.stories.tsx +0 -164
  231. package/helpers/embedCodeGenerator.ts +0 -109
  232. package/styles/_common-components.css +0 -73
  233. package/styles/_variables.scss +0 -63
  234. package/styles/v2/layout/_component.scss +0 -21
  235. package/styles/v2/utils/_variables.scss +0 -9
  236. package/{styles/v2/components/card.scss → components/elements/card.css} +2 -2
  237. /package/{styles/v2/components → components/ui}/icon.scss +0 -0
  238. /package/{styles/v2/components → components/ui}/loadspin.scss +0 -0
  239. /package/styles/{v2/base → base}/_heading.scss +0 -0
  240. /package/styles/{v2/base → base}/_reset.scss +0 -0
  241. /package/styles/{v2/layout → layout}/_alert.scss +0 -0
  242. /package/styles/{v2/layout → layout}/_progression.scss +0 -0
  243. /package/styles/{v2/layout → layout}/_tooltip.scss +0 -0
  244. /package/styles/{v2/layout → layout}/index.scss +0 -0
  245. /package/styles/{v2/themes → themes}/index.scss +0 -0
  246. /package/styles/{v2/utils → utils}/_align.scss +0 -0
  247. /package/styles/{v2/utils → utils}/_animations.scss +0 -0
  248. /package/styles/{v2/utils → utils}/_breakpoints.scss +0 -0
  249. /package/styles/{v2/utils → utils}/_mixins.scss +0 -0
@@ -16,7 +16,8 @@ const meta: Meta = {
16
16
  layout: 'fullscreen',
17
17
  docs: {
18
18
  description: {
19
- component: 'Stories for visualizations from the CDC Behavioral Risk Factor Surveillance System (BRFSS) Prevalence Data & Data Analysis Tools page (https://www.cdc.gov/brfss/brfssprevalence/index.html)'
19
+ component:
20
+ 'Stories for visualizations from the CDC Behavioral Risk Factor Surveillance System (BRFSS) Prevalence Data & Data Analysis Tools page (https://www.cdc.gov/brfss/brfssprevalence/index.html)'
20
21
  }
21
22
  }
22
23
  },
@@ -93,12 +94,16 @@ const useConfigWithAbsoluteDataUrl = (configUrl: string) => {
93
94
 
94
95
  newDatasets[absoluteKey] = {
95
96
  ...dataset,
96
- dataFileName: (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
97
- ? `https://www.cdc.gov/${(dataset as any).dataFileName.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
98
- : (dataset as any).dataFileName,
99
- dataUrl: (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
100
- ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
101
- : (dataset as any).dataUrl
97
+ dataFileName:
98
+ (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
99
+ ? `https://www.cdc.gov/${(dataset as any).dataFileName
100
+ .replace(/^(\.\.\/)+/, '')
101
+ .replace(/^\//, '')}`
102
+ : (dataset as any).dataFileName,
103
+ dataUrl:
104
+ (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
105
+ ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
106
+ : (dataset as any).dataUrl
102
107
  }
103
108
  }
104
109
  })
@@ -140,7 +145,7 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
140
145
  const timeout = 30000 // Longer timeout for external data loading
141
146
 
142
147
  const checkDashboard = () => {
143
- const dashboardElement = canvasElement.querySelector('.cove-dashboard')
148
+ const dashboardElement = canvasElement.querySelector('.type-dashboard')
144
149
  const loadingDiv = canvasElement.querySelector('div')
145
150
 
146
151
  // Log current state for debugging
@@ -161,12 +166,12 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
161
166
  })
162
167
 
163
168
  await step('Verify dashboard wrapper is present', async () => {
164
- const dashboard = canvasElement.querySelector('.cove-dashboard')
169
+ const dashboard = canvasElement.querySelector('.type-dashboard')
165
170
  expect(dashboard).toBeInTheDocument()
166
171
  })
167
172
 
168
173
  await step('Verify at least one visualization rendered', async () => {
169
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
174
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
170
175
  expect(coveModules.length).toBeGreaterThan(0)
171
176
  })
172
177
 
@@ -224,15 +229,15 @@ export const All_BRFSS_Dashboards: StoryObj = {
224
229
  }
225
230
 
226
231
  return (
227
- <div className="container-fluid p-4">
228
- <h1 className="mb-4">BRFSS Prevalence Data - All Dashboards</h1>
232
+ <div className='container-fluid p-4'>
233
+ <h1 className='mb-4'>BRFSS Prevalence Data - All Dashboards</h1>
229
234
 
230
- <section className="mb-5">
235
+ <section className='mb-5'>
231
236
  <h2>Explore by Location</h2>
232
237
  <Dashboard config={locationConfig} />
233
238
  </section>
234
239
 
235
- <section className="mb-5">
240
+ <section className='mb-5'>
236
241
  <h2>Explore by Topic</h2>
237
242
  <Dashboard config={topicConfig} />
238
243
  </section>
@@ -266,7 +271,7 @@ export const All_BRFSS_Dashboards: StoryObj = {
266
271
  const timeout = 40000
267
272
 
268
273
  const checkDashboards = () => {
269
- const dashboards = canvasElement.querySelectorAll('.cove-dashboard')
274
+ const dashboards = canvasElement.querySelectorAll('.type-dashboard')
270
275
  if (dashboards.length >= 2) {
271
276
  resolve()
272
277
  } else if (Date.now() - startTime > timeout) {
@@ -280,7 +285,7 @@ export const All_BRFSS_Dashboards: StoryObj = {
280
285
  })
281
286
 
282
287
  await step('Verify both dashboards are present', async () => {
283
- const dashboards = canvasElement.querySelectorAll('.cove-dashboard')
288
+ const dashboards = canvasElement.querySelectorAll('.type-dashboard')
284
289
  expect(dashboards.length).toBe(2)
285
290
  })
286
291
 
@@ -16,7 +16,8 @@ const meta: Meta = {
16
16
  layout: 'fullscreen',
17
17
  docs: {
18
18
  description: {
19
- component: 'Stories for visualizations from the CDC National Program of Cancer Registries (NPCR) Contact page (https://www.cdc.gov/national-program-cancer-registries/contact/index.html)'
19
+ component:
20
+ 'Stories for visualizations from the CDC National Program of Cancer Registries (NPCR) Contact page (https://www.cdc.gov/national-program-cancer-registries/contact/index.html)'
20
21
  }
21
22
  }
22
23
  },
@@ -92,12 +93,16 @@ const useConfigWithAbsoluteDataUrl = (configUrl: string) => {
92
93
 
93
94
  newDatasets[absoluteKey] = {
94
95
  ...dataset,
95
- dataFileName: (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
96
- ? `https://www.cdc.gov/${(dataset as any).dataFileName.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
97
- : (dataset as any).dataFileName,
98
- dataUrl: (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
99
- ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
100
- : (dataset as any).dataUrl
96
+ dataFileName:
97
+ (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
98
+ ? `https://www.cdc.gov/${(dataset as any).dataFileName
99
+ .replace(/^(\.\.\/)+/, '')
100
+ .replace(/^\//, '')}`
101
+ : (dataset as any).dataFileName,
102
+ dataUrl:
103
+ (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
104
+ ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
105
+ : (dataset as any).dataUrl
101
106
  }
102
107
  }
103
108
  })
@@ -139,7 +144,7 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
139
144
  const timeout = 20000
140
145
 
141
146
  const checkDashboard = () => {
142
- const dashboardElement = canvasElement.querySelector('.cove-dashboard')
147
+ const dashboardElement = canvasElement.querySelector('.type-dashboard')
143
148
  const loadingDiv = canvasElement.querySelector('div')
144
149
 
145
150
  // Log current state for debugging
@@ -160,20 +165,15 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
160
165
  })
161
166
 
162
167
  await step('Verify dashboard wrapper is present', async () => {
163
- const dashboard = canvasElement.querySelector('.cove-dashboard')
168
+ const dashboard = canvasElement.querySelector('.type-dashboard')
164
169
  expect(dashboard).toBeInTheDocument()
165
170
  })
166
171
 
167
172
  await step('Verify at least one visualization rendered', async () => {
168
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
173
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
169
174
  expect(coveModules.length).toBeGreaterThan(0)
170
175
  })
171
176
 
172
- await step('Verify map visualization is present', async () => {
173
- const mapElement = canvasElement.querySelector('svg')
174
- expect(mapElement).toBeInTheDocument()
175
- })
176
-
177
177
  console.log(` ${storyName} dashboard rendered successfully`)
178
178
  }
179
179
 
@@ -37,22 +37,36 @@ const CONFIG_URLS = {
37
37
  type MapStory = StoryObj<typeof CdcMap>
38
38
  type DashboardStory = StoryObj<typeof Dashboard>
39
39
 
40
- // Helper function to test map rendering
40
+ // Helper function to test map rendering (supports both SVG and canvas-based maps)
41
41
  const testMapRendering = async (canvasElement: HTMLElement, storyName: string) => {
42
- const canvas = within(canvasElement)
43
-
44
42
  await step('Wait for map to render', async () => {
45
- const mapElement = await canvas.findByRole('img', { hidden: true }, { timeout: 10000 })
46
- expect(mapElement).toBeInTheDocument()
43
+ await new Promise<void>((resolve, reject) => {
44
+ const startTime = Date.now()
45
+ const timeout = 15000
46
+
47
+ const checkMap = () => {
48
+ const svgMap = canvasElement.querySelector('svg[role="img"]')
49
+ const canvasMap = canvasElement.querySelector('canvas')
50
+ if (svgMap || canvasMap) {
51
+ resolve()
52
+ } else if (Date.now() - startTime > timeout) {
53
+ reject(new Error(`Timeout: No map element (svg or canvas) found after ${timeout}ms`))
54
+ } else {
55
+ setTimeout(checkMap, 100)
56
+ }
57
+ }
58
+ checkMap()
59
+ })
47
60
  })
48
61
 
49
- await step('Verify SVG element is present', async () => {
50
- const svgElement = canvasElement.querySelector('svg')
51
- expect(svgElement).toBeInTheDocument()
62
+ await step('Verify map visualization is present', async () => {
63
+ const svgMap = canvasElement.querySelector('svg[role="img"]')
64
+ const canvasMap = canvasElement.querySelector('canvas')
65
+ expect(svgMap || canvasMap).toBeTruthy()
52
66
  })
53
67
 
54
68
  await step('Verify COVE module wrapper is present', async () => {
55
- const coveModule = canvasElement.querySelector('.cdc-open-viz-module')
69
+ const coveModule = canvasElement.querySelector('.cove-visualization')
56
70
  expect(coveModule).toBeInTheDocument()
57
71
  })
58
72
 
@@ -67,7 +81,7 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
67
81
  const timeout = 15000
68
82
 
69
83
  const checkDashboard = () => {
70
- const dashboardElement = canvasElement.querySelector('.cove-dashboard')
84
+ const dashboardElement = canvasElement.querySelector('.type-dashboard')
71
85
  if (dashboardElement) {
72
86
  resolve()
73
87
  } else if (Date.now() - startTime > timeout) {
@@ -81,7 +95,7 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
81
95
  })
82
96
 
83
97
  await step('Verify dashboard wrapper is present', async () => {
84
- const dashboard = canvasElement.querySelector('.cove-dashboard')
98
+ const dashboard = canvasElement.querySelector('.type-dashboard')
85
99
  expect(dashboard).toBeInTheDocument()
86
100
  })
87
101
 
@@ -144,25 +158,25 @@ export const Connecticut_2022: MapStory = {
144
158
  */
145
159
  export const All_EEE_Visualizations: StoryObj = {
146
160
  render: () => (
147
- <div className="container-fluid p-4">
148
- <h1 className="mb-4">Eastern Equine Encephalitis - Historic Data</h1>
161
+ <div className='container-fluid p-4'>
162
+ <h1 className='mb-4'>Eastern Equine Encephalitis - Historic Data</h1>
149
163
 
150
- <section className="mb-5">
164
+ <section className='mb-5'>
151
165
  <h2>Cumulative Data for 2003–2024</h2>
152
166
  <Dashboard configUrl={CONFIG_URLS.cumulativeData} />
153
167
  </section>
154
168
 
155
- <section className="mb-5">
169
+ <section className='mb-5'>
156
170
  <h2>Explore Human Data for 2003–2024</h2>
157
171
  <Dashboard configUrl={CONFIG_URLS.exploreHumanData} />
158
172
  </section>
159
173
 
160
- <section className="mb-5">
174
+ <section className='mb-5'>
161
175
  <h2>Explore County Level Data for 2003–2024</h2>
162
176
  <CdcMap configUrl={CONFIG_URLS.exploreCountyData} />
163
177
  </section>
164
178
 
165
- <section className="mb-5">
179
+ <section className='mb-5'>
166
180
  <h2>Connecticut 2022 Data</h2>
167
181
  <CdcMap configUrl={CONFIG_URLS.ct2022} />
168
182
  </section>
@@ -179,7 +193,7 @@ export const All_EEE_Visualizations: StoryObj = {
179
193
  const timeout = 30000
180
194
 
181
195
  const checkModules = () => {
182
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
196
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
183
197
  if (coveModules.length >= 4) {
184
198
  resolve()
185
199
  } else if (Date.now() - startTime > timeout) {
@@ -193,7 +207,7 @@ export const All_EEE_Visualizations: StoryObj = {
193
207
  })
194
208
 
195
209
  await step('Verify at least 4 visualizations are present', async () => {
196
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
210
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
197
211
  expect(coveModules.length).toBeGreaterThanOrEqual(4)
198
212
  })
199
213
 
@@ -5,171 +5,176 @@ import { useEffect, useState } from 'react'
5
5
 
6
6
  // Fallback step function for test descriptions
7
7
  const step = async (description: string, fn: () => Promise<void> | void) => {
8
- console.log(`▶ ${description}`)
9
- await fn()
10
- console.log(`✓ ${description}`)
8
+ console.log(`▶ ${description}`)
9
+ await fn()
10
+ console.log(`✓ ${description}`)
11
11
  }
12
12
 
13
13
  const meta: Meta = {
14
- title: 'Regression Tests/Pages/Excessive Alcohol Use',
15
- parameters: {
16
- layout: 'fullscreen',
17
- docs: {
18
- description: {
19
- component: 'Stories for visualizations from the CDC Excessive Alcohol Use page (https://www.cdc.gov/alcohol/fact-sheets/states/excessive-alcohol-use-united-states.html)'
20
- }
21
- }
22
- },
23
- tags: ['autodocs']
14
+ title: 'Regression Tests/Pages/Excessive Alcohol Use',
15
+ parameters: {
16
+ layout: 'fullscreen',
17
+ docs: {
18
+ description: {
19
+ component:
20
+ 'Stories for visualizations from the CDC Excessive Alcohol Use page (https://www.cdc.gov/alcohol/fact-sheets/states/excessive-alcohol-use-united-states.html)'
21
+ }
22
+ }
23
+ },
24
+ tags: ['autodocs']
24
25
  }
25
26
 
26
27
  export default meta
27
28
 
28
29
  // Config URL from the excessive alcohol use page
29
30
  const CONFIG_URLS = {
30
- excessiveAlcoholUse: 'https://www.cdc.gov/alcohol/fact-sheets/states/alcohol-data-for-50-states.json'
31
+ excessiveAlcoholUse: 'https://www.cdc.gov/alcohol/fact-sheets/states/alcohol-data-for-50-states.json'
31
32
  }
32
33
 
33
34
  // Helper to fetch config and update data URLs to use absolute cdc.gov paths
34
35
  const useConfigWithAbsoluteDataUrl = (configUrl: string) => {
35
- const [config, setConfig] = useState(null)
36
-
37
- useEffect(() => {
38
- fetch(configUrl)
39
- .then(res => res.json())
40
- .then(data => {
41
- // Convert relative data URLs to absolute cdc.gov URLs
42
- if (data.dataUrl) {
43
- // Handle different relative path formats (../../path or /path)
44
- const dataUrl = data.dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
45
- data.dataUrl = `https://www.cdc.gov/${dataUrl}`
46
- }
47
- if (data.dataFileName) {
48
- const dataFileName = data.dataFileName.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
49
- data.dataFileName = `https://www.cdc.gov/${dataFileName}`
50
- }
36
+ const [config, setConfig] = useState(null)
37
+
38
+ useEffect(() => {
39
+ fetch(configUrl)
40
+ .then(res => res.json())
41
+ .then(data => {
42
+ // Convert relative data URLs to absolute cdc.gov URLs
43
+ if (data.dataUrl) {
44
+ // Handle different relative path formats (../../path or /path)
45
+ const dataUrl = data.dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
46
+ data.dataUrl = `https://www.cdc.gov/${dataUrl}`
47
+ }
48
+ if (data.dataFileName) {
49
+ const dataFileName = data.dataFileName.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
50
+ data.dataFileName = `https://www.cdc.gov/${dataFileName}`
51
+ }
51
52
 
52
- // For dashboard configs with multiDashboards, convert dataKey references in visualizations
53
- if (data.multiDashboards) {
54
- data.multiDashboards.forEach((dashboard: any) => {
55
- if (dashboard.visualizations) {
56
- Object.values(dashboard.visualizations).forEach((viz: any) => {
57
- // Only convert dataKey if it's a URL path (starts with / or ../)
58
- if (viz.dataKey && (viz.dataKey.startsWith('/') || viz.dataKey.startsWith('../'))) {
59
- const dataKey = viz.dataKey.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
60
- viz.dataKey = `https://www.cdc.gov/${dataKey}`
61
- }
62
- })
63
- }
64
- })
53
+ // For dashboard configs with multiDashboards, convert dataKey references in visualizations
54
+ if (data.multiDashboards) {
55
+ data.multiDashboards.forEach((dashboard: any) => {
56
+ if (dashboard.visualizations) {
57
+ Object.values(dashboard.visualizations).forEach((viz: any) => {
58
+ // Only convert dataKey if it's a URL path (starts with / or ../)
59
+ if (viz.dataKey && (viz.dataKey.startsWith('/') || viz.dataKey.startsWith('../'))) {
60
+ const dataKey = viz.dataKey.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
61
+ viz.dataKey = `https://www.cdc.gov/${dataKey}`
65
62
  }
63
+ })
64
+ }
65
+ })
66
+ }
66
67
 
67
- // For dashboard configs, convert dataKey references in visualizations
68
- if (data.visualizations) {
69
- Object.values(data.visualizations).forEach((viz: any) => {
70
- // Only convert dataKey if it's a URL path (starts with / or ../)
71
- if (viz.dataKey && (viz.dataKey.startsWith('/') || viz.dataKey.startsWith('../'))) {
72
- const dataKey = viz.dataKey.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
73
- viz.dataKey = `https://www.cdc.gov/${dataKey}`
74
- }
75
- })
76
- }
68
+ // For dashboard configs, convert dataKey references in visualizations
69
+ if (data.visualizations) {
70
+ Object.values(data.visualizations).forEach((viz: any) => {
71
+ // Only convert dataKey if it's a URL path (starts with / or ../)
72
+ if (viz.dataKey && (viz.dataKey.startsWith('/') || viz.dataKey.startsWith('../'))) {
73
+ const dataKey = viz.dataKey.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
74
+ viz.dataKey = `https://www.cdc.gov/${dataKey}`
75
+ }
76
+ })
77
+ }
77
78
 
78
- // For dashboard configs, convert datasets only if they reference external files
79
- if (data.datasets) {
80
- const newDatasets = {}
81
- Object.entries(data.datasets).forEach(([key, dataset]: [string, any]) => {
82
- // Check if dataset has embedded data
83
- const hasEmbeddedData = (dataset as any).data && Array.isArray((dataset as any).data)
84
-
85
- // If data is embedded, keep the original key
86
- if (hasEmbeddedData) {
87
- newDatasets[key] = dataset
88
- } else {
89
- // Otherwise, convert paths to absolute URLs (but keep absolute URLs as-is)
90
- const newKey = key.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
91
- const absoluteKey = key.startsWith('http') ? key : `https://www.cdc.gov/${newKey}`
92
-
93
- newDatasets[absoluteKey] = {
94
- ...dataset,
95
- dataFileName: (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
96
- ? `https://www.cdc.gov/${(dataset as any).dataFileName.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
97
- : (dataset as any).dataFileName,
98
- dataUrl: (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
99
- ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
100
- : (dataset as any).dataUrl
101
- }
102
- }
103
- })
104
- data.datasets = newDatasets
105
- }
79
+ // For dashboard configs, convert datasets only if they reference external files
80
+ if (data.datasets) {
81
+ const newDatasets = {}
82
+ Object.entries(data.datasets).forEach(([key, dataset]: [string, any]) => {
83
+ // Check if dataset has embedded data
84
+ const hasEmbeddedData = (dataset as any).data && Array.isArray((dataset as any).data)
85
+
86
+ // If data is embedded, keep the original key
87
+ if (hasEmbeddedData) {
88
+ newDatasets[key] = dataset
89
+ } else {
90
+ // Otherwise, convert paths to absolute URLs (but keep absolute URLs as-is)
91
+ const newKey = key.replace(/^(\.\.\/)+/, '').replace(/^\//, '')
92
+ const absoluteKey = key.startsWith('http') ? key : `https://www.cdc.gov/${newKey}`
93
+
94
+ newDatasets[absoluteKey] = {
95
+ ...dataset,
96
+ dataFileName:
97
+ (dataset as any).dataFileName && !(dataset as any).dataFileName.startsWith('http')
98
+ ? `https://www.cdc.gov/${(dataset as any).dataFileName
99
+ .replace(/^(\.\.\/)+/, '')
100
+ .replace(/^\//, '')}`
101
+ : (dataset as any).dataFileName,
102
+ dataUrl:
103
+ (dataset as any).dataUrl && !(dataset as any).dataUrl.startsWith('http')
104
+ ? `https://www.cdc.gov/${(dataset as any).dataUrl.replace(/^(\.\.\/)+/, '').replace(/^\//, '')}`
105
+ : (dataset as any).dataUrl
106
+ }
107
+ }
108
+ })
109
+ data.datasets = newDatasets
110
+ }
106
111
 
107
- // Set activeDashboard to 0 if it's null and multiDashboards exist
108
- if (data.multiDashboards && data.multiDashboards.length > 0 && data.activeDashboard === null) {
109
- data.activeDashboard = 0
110
- }
112
+ // Set activeDashboard to 0 if it's null and multiDashboards exist
113
+ if (data.multiDashboards && data.multiDashboards.length > 0 && data.activeDashboard === null) {
114
+ data.activeDashboard = 0
115
+ }
116
+
117
+ // Log config info for debugging
118
+ console.log('✓ Config loaded:', {
119
+ type: data.type,
120
+ hasMultiDashboards: !!data.multiDashboards,
121
+ dashboardCount: data.multiDashboards?.length || 0,
122
+ activeDashboard: data.activeDashboard,
123
+ datasetCount: Object.keys(data.datasets || {}).length,
124
+ dashboardLabels: data.multiDashboards?.map((d: any) => d.label)
125
+ })
111
126
 
112
- // Log config info for debugging
113
- console.log('✓ Config loaded:', {
114
- type: data.type,
115
- hasMultiDashboards: !!data.multiDashboards,
116
- dashboardCount: data.multiDashboards?.length || 0,
117
- activeDashboard: data.activeDashboard,
118
- datasetCount: Object.keys(data.datasets || {}).length,
119
- dashboardLabels: data.multiDashboards?.map((d: any) => d.label)
120
- })
121
-
122
- setConfig(data)
123
- })
124
- .catch(err => {
125
- console.error('Failed to fetch config:', configUrl, err)
126
- })
127
- }, [configUrl])
128
-
129
- return config
127
+ setConfig(data)
128
+ })
129
+ .catch(err => {
130
+ console.error('Failed to fetch config:', configUrl, err)
131
+ })
132
+ }, [configUrl])
133
+
134
+ return config
130
135
  }
131
136
 
132
137
  type DashboardStory = StoryObj<typeof Dashboard>
133
138
 
134
139
  // Helper function to test dashboard rendering
135
140
  const testDashboardRendering = async (canvasElement: HTMLElement, storyName: string) => {
136
- await step('Wait for dashboard to render', async () => {
137
- await new Promise<void>((resolve, reject) => {
138
- const startTime = Date.now()
139
- const timeout = 30000 // Longer timeout for external data loading
140
-
141
- const checkDashboard = () => {
142
- const dashboardElement = canvasElement.querySelector('.cove-dashboard')
143
- const loadingDiv = canvasElement.querySelector('div')
144
-
145
- // Log current state for debugging
146
- if (!dashboardElement && loadingDiv?.textContent?.includes('Loading')) {
147
- console.log('Still loading config...')
148
- }
141
+ await step('Wait for dashboard to render', async () => {
142
+ await new Promise<void>((resolve, reject) => {
143
+ const startTime = Date.now()
144
+ const timeout = 30000 // Longer timeout for external data loading
145
+
146
+ const checkDashboard = () => {
147
+ const dashboardElement = canvasElement.querySelector('.type-dashboard')
148
+ const loadingDiv = canvasElement.querySelector('div')
149
+
150
+ // Log current state for debugging
151
+ if (!dashboardElement && loadingDiv?.textContent?.includes('Loading')) {
152
+ console.log('Still loading config...')
153
+ }
149
154
 
150
- if (dashboardElement) {
151
- resolve()
152
- } else if (Date.now() - startTime > timeout) {
153
- reject(new Error(`Timeout: Dashboard element not found after ${timeout}ms`))
154
- } else {
155
- setTimeout(checkDashboard, 100)
156
- }
157
- }
158
- checkDashboard()
159
- })
155
+ if (dashboardElement) {
156
+ resolve()
157
+ } else if (Date.now() - startTime > timeout) {
158
+ reject(new Error(`Timeout: Dashboard element not found after ${timeout}ms`))
159
+ } else {
160
+ setTimeout(checkDashboard, 100)
161
+ }
162
+ }
163
+ checkDashboard()
160
164
  })
165
+ })
161
166
 
162
- await step('Verify dashboard wrapper is present', async () => {
163
- const dashboard = canvasElement.querySelector('.cove-dashboard')
164
- expect(dashboard).toBeInTheDocument()
165
- })
167
+ await step('Verify dashboard wrapper is present', async () => {
168
+ const dashboard = canvasElement.querySelector('.type-dashboard')
169
+ expect(dashboard).toBeInTheDocument()
170
+ })
166
171
 
167
- await step('Verify at least one visualization rendered', async () => {
168
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
169
- expect(coveModules.length).toBeGreaterThan(0)
170
- })
172
+ await step('Verify at least one visualization rendered', async () => {
173
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
174
+ expect(coveModules.length).toBeGreaterThan(0)
175
+ })
171
176
 
172
- console.log(`✓ ${storyName} dashboard rendered successfully`)
177
+ console.log(`✓ ${storyName} dashboard rendered successfully`)
173
178
  }
174
179
 
175
180
  /**
@@ -185,12 +190,12 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
185
190
  * - State-specific alcohol consumption trends
186
191
  */
187
192
  export const Excessive_Alcohol_Use_Dashboard: DashboardStory = {
188
- render: () => {
189
- const config = useConfigWithAbsoluteDataUrl(CONFIG_URLS.excessiveAlcoholUse)
190
- if (!config) return <div>Loading...</div>
191
- return <Dashboard config={config} />
192
- },
193
- play: async ({ canvasElement }) => {
194
- await testDashboardRendering(canvasElement, 'Excessive Alcohol Use Dashboard')
195
- }
193
+ render: () => {
194
+ const config = useConfigWithAbsoluteDataUrl(CONFIG_URLS.excessiveAlcoholUse)
195
+ if (!config) return <div>Loading...</div>
196
+ return <Dashboard config={config} />
197
+ },
198
+ play: async ({ canvasElement }) => {
199
+ await testDashboardRendering(canvasElement, 'Excessive Alcohol Use Dashboard')
200
+ }
196
201
  }
@@ -16,7 +16,8 @@ const meta: Meta = {
16
16
  layout: 'fullscreen',
17
17
  docs: {
18
18
  description: {
19
- component: 'Stories for visualizations from the CDC Pregnancy Mortality Surveillance System (PMSS) page (https://www.cdc.gov/maternal-mortality/php/pregnancy-mortality-surveillance-data/index.html)'
19
+ component:
20
+ 'Stories for visualizations from the CDC Pregnancy Mortality Surveillance System (PMSS) page (https://www.cdc.gov/maternal-mortality/php/pregnancy-mortality-surveillance-data/index.html)'
20
21
  }
21
22
  }
22
23
  },
@@ -140,7 +141,7 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
140
141
  const timeout = 20000
141
142
 
142
143
  const checkDashboard = () => {
143
- const dashboardElement = canvasElement.querySelector('.cove-dashboard')
144
+ const dashboardElement = canvasElement.querySelector('.type-dashboard')
144
145
  const loadingDiv = canvasElement.querySelector('div')
145
146
 
146
147
  // Log current state for debugging
@@ -161,12 +162,12 @@ const testDashboardRendering = async (canvasElement: HTMLElement, storyName: str
161
162
  })
162
163
 
163
164
  await step('Verify dashboard wrapper is present', async () => {
164
- const dashboard = canvasElement.querySelector('.cove-dashboard')
165
+ const dashboard = canvasElement.querySelector('.type-dashboard')
165
166
  expect(dashboard).toBeInTheDocument()
166
167
  })
167
168
 
168
169
  await step('Verify at least one visualization rendered', async () => {
169
- const coveModules = canvasElement.querySelectorAll('.cdc-open-viz-module')
170
+ const coveModules = canvasElement.querySelectorAll('.cove-visualization')
170
171
  expect(coveModules.length).toBeGreaterThan(0)
171
172
  })
172
173