@cdc/core 4.26.2 → 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 (186) hide show
  1. package/LICENSE +201 -0
  2. package/_stories/Gallery.Charts.stories.tsx +1 -1
  3. package/_stories/Gallery.DataBite.stories.tsx +1 -1
  4. package/_stories/Gallery.Maps.stories.tsx +1 -1
  5. package/_stories/PageART.stories.tsx +1 -1
  6. package/_stories/PageBRFSS.stories.tsx +1 -1
  7. package/_stories/PageCancerRegistries.stories.tsx +1 -1
  8. package/_stories/PageEasternEquineEncephalitis.stories.tsx +3 -3
  9. package/_stories/PageExcessiveAlcoholUse.stories.tsx +1 -1
  10. package/_stories/PageMaternalMortality.stories.tsx +1 -1
  11. package/_stories/PageOralHealth.stories.tsx +1 -1
  12. package/_stories/PageRespiratory.stories.tsx +4 -4
  13. package/_stories/PageSmokingTobacco.stories.tsx +1 -1
  14. package/_stories/PageStateDiabetesProfiles.stories.tsx +1 -1
  15. package/_stories/PageWastewater.stories.tsx +4 -4
  16. package/_stories/VegaImport.stories.tsx +3 -3
  17. package/assets/callout-flag.svg +7 -0
  18. package/components/AdvancedEditor/EmbedEditor.tsx +1 -1
  19. package/components/Alert/components/Alert.styles.css +2 -2
  20. package/components/ComboBox/combobox.styles.css +48 -48
  21. package/components/CustomColorsEditor/CustomColorsEditor.css +53 -53
  22. package/components/DataTable/DataTable.tsx +46 -18
  23. package/components/DataTable/DataTableStandAlone.tsx +1 -0
  24. package/components/DataTable/components/ChartHeader.tsx +21 -12
  25. package/components/DataTable/components/MapHeader.tsx +34 -28
  26. package/components/DataTable/components/SortIcon/sort-icon.css +5 -5
  27. package/components/DataTable/data-table.css +50 -52
  28. package/components/DataTable/helpers/applyCustomOrder.ts +17 -0
  29. package/components/DataTable/helpers/getChartCellValue.ts +10 -7
  30. package/components/DataTable/helpers/getMapDataTableColumnKeys.ts +22 -0
  31. package/components/DataTable/helpers/mapCellMatrix.tsx +33 -23
  32. package/components/DataTable/helpers/tests/mapCellMatrix.test.ts +33 -0
  33. package/components/DownloadButton.tsx +14 -6
  34. package/components/EditorPanel/ColumnsEditor.tsx +38 -31
  35. package/components/EditorPanel/CustomSortOrder.tsx +94 -0
  36. package/components/EditorPanel/DataTableEditor.tsx +139 -23
  37. package/components/EditorPanel/EditorPanel.styles.css +71 -71
  38. package/components/EditorPanel/EditorPanel.tsx +3 -8
  39. package/components/EditorPanel/EditorPanelDispatch.tsx +4 -4
  40. package/components/EditorPanel/FootnotesEditor.tsx +2 -2
  41. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +7 -6
  42. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +12 -10
  43. package/components/EditorPanel/components/MarkupVariablesEditor.tsx +160 -106
  44. package/components/EditorPanel/components/PanelMarkup.tsx +5 -1
  45. package/{styles/v2/components → components/EditorPanel}/editor.scss +67 -13
  46. package/components/EditorPanel/sections/StyleTreatmentSection.tsx +99 -0
  47. package/components/EditorPanel/sections/VisualSection.tsx +11 -0
  48. package/components/EditorWrapper/editor-wrapper.style.css +1 -1
  49. package/components/Filters/Filters.tsx +3 -5
  50. package/components/Filters/components/Tabs.tsx +19 -7
  51. package/{styles → components/Filters}/filters.scss +3 -3
  52. package/components/Footnotes/FootnotesStandAlone.tsx +4 -2
  53. package/components/HeaderThemeSelector/HeaderThemeSelector.css +61 -5
  54. package/components/Layout/components/Responsive.tsx +14 -6
  55. package/components/Layout/components/Sidebar/components/Sidebar.tsx +1 -1
  56. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +12 -18
  57. package/components/Layout/components/Visualization/index.tsx +39 -38
  58. package/components/Layout/components/Visualization/visualizations.scss +232 -15
  59. package/components/Layout/components/VisualizationContainer.test.tsx +67 -0
  60. package/components/Layout/components/VisualizationContainer.tsx +37 -0
  61. package/components/Layout/components/VisualizationContent.test.tsx +182 -0
  62. package/components/Layout/components/VisualizationContent.tsx +75 -0
  63. package/components/Layout/index.tsx +5 -5
  64. package/components/Layout/styles/editor-utils.scss +3 -3
  65. package/components/Layout/styles/editor.scss +4 -4
  66. package/components/Legend/Legend.Gradient.tsx +7 -1
  67. package/components/Loader/loader.styles.css +2 -2
  68. package/components/Loading.jsx +1 -1
  69. package/components/MediaControls.tsx +10 -2
  70. package/components/MultiSelect/multiselect.styles.css +19 -19
  71. package/components/NestedDropdown/nesteddropdown.styles.css +15 -15
  72. package/components/PaletteSelector/PaletteSelector.css +15 -15
  73. package/components/RichTooltip/richTooltip.css +6 -6
  74. package/components/Table/table.styles.css +2 -2
  75. package/components/Waiting.tsx +1 -1
  76. package/components/_stories/Filters.stories.tsx +1 -1
  77. package/components/_stories/styles.scss +0 -1
  78. package/components/elements/Button.jsx +1 -1
  79. package/components/elements/Card.jsx +1 -1
  80. package/{styles/v2/components → components/elements}/button.scss +9 -8
  81. package/components/inputs/InputCheckbox.jsx +1 -1
  82. package/components/inputs/InputSelect.tsx +1 -1
  83. package/components/inputs/InputText.jsx +1 -1
  84. package/components/inputs/InputToggle.tsx +1 -1
  85. package/{styles/v2/components/input → components/inputs}/_input-check-radio.scss +2 -2
  86. package/{styles/v2/components/input → components/inputs}/_input-group.scss +3 -3
  87. package/{styles/v2/components/input → components/inputs}/_input-slider.scss +2 -2
  88. package/{styles/v2/components/input → components/inputs}/_input.scss +5 -5
  89. package/{styles/v2/components/input → components/inputs}/index.scss +2 -2
  90. package/{styles → components}/loading.scss +1 -1
  91. package/components/managers/DataDesigner.tsx +1 -1
  92. package/{styles/v2/components → components/managers}/data-designer.scss +6 -7
  93. package/components/ui/Accordion.jsx +1 -1
  94. package/components/ui/Icon.tsx +1 -1
  95. package/components/ui/LoadSpin.jsx +1 -1
  96. package/components/ui/Modal.jsx +1 -1
  97. package/components/ui/Overlay.jsx +1 -1
  98. package/components/ui/Title/index.test.tsx +34 -0
  99. package/components/ui/Title/index.tsx +24 -7
  100. package/components/ui/Title/title.styles.css +119 -25
  101. package/components/ui/Tooltip.tsx +1 -1
  102. package/components/ui/_stories/Title.stories.tsx +1 -1
  103. package/{styles/v2/components → components/ui}/accordion.scss +3 -3
  104. package/components/ui/accordion.styles.css +11 -11
  105. package/{styles/v2/components → components/ui}/modal.scss +2 -2
  106. package/{styles/v2/components → components/ui}/overlay.scss +6 -6
  107. package/{styles/v2/components → components}/ui/tooltip.scss +1 -1
  108. package/{styles → components}/waiting.scss +9 -3
  109. package/devTemplate/dev.js +50 -0
  110. package/dist/cove-main.css +528 -231
  111. package/dist/cove-main.css.map +1 -1
  112. package/generateViteConfig.js +2 -2
  113. package/helpers/backfillDefaults.ts +35 -0
  114. package/helpers/constants.ts +12 -0
  115. package/helpers/cove/date.ts +32 -3
  116. package/helpers/cove/number.ts +29 -15
  117. package/helpers/coveUpdateWorker.ts +12 -8
  118. package/helpers/displayDataAsText.ts +1 -1
  119. package/helpers/embed/embedHelper.js +13 -2
  120. package/helpers/embed/index.ts +0 -4
  121. package/helpers/extractDataAndMetadata.ts +20 -0
  122. package/helpers/fetchRemoteData.ts +14 -8
  123. package/helpers/labelHash.ts +9 -0
  124. package/helpers/markupProcessor.ts +56 -38
  125. package/helpers/prepareScreenshot.ts +6 -3
  126. package/helpers/testing.ts +1 -1
  127. package/helpers/tests/abbreviateNumber.test.ts +59 -0
  128. package/helpers/tests/backfillDefaults.test.ts +253 -0
  129. package/helpers/tests/date.test.ts +46 -0
  130. package/helpers/tests/extractDataAndMetadata.test.ts +93 -0
  131. package/helpers/tests/markupProcessor.test.ts +315 -124
  132. package/helpers/tests/number.test.ts +42 -0
  133. package/helpers/tests/prepareScreenshot.test.ts +28 -28
  134. package/helpers/tests/testStandaloneBuild.ts +36 -26
  135. package/helpers/tests/useDataVizClasses.test.ts +66 -0
  136. package/helpers/tests/visualizationWrapperUsage.test.ts +57 -0
  137. package/helpers/useDataVizClasses.ts +13 -7
  138. package/helpers/ver/4.24.4.ts +24 -0
  139. package/helpers/ver/4.26.3.ts +44 -0
  140. package/helpers/ver/4.26.4.ts +31 -0
  141. package/helpers/ver/tests/4.26.3.test.ts +168 -0
  142. package/helpers/ver/tests/4.26.4.test.ts +88 -0
  143. package/helpers/ver/tests/coveUpdateWorker.test.ts +57 -0
  144. package/package.json +2 -2
  145. package/styles/_global.scss +7 -7
  146. package/styles/_reset.scss +2 -2
  147. package/styles/{v2/base → base}/_file-selector.scss +4 -4
  148. package/styles/{v2/base → base}/_general.scss +2 -4
  149. package/styles/{v2/base → base}/index.scss +1 -1
  150. package/styles/base.scss +107 -165
  151. package/styles/cove-main.scss +3 -6
  152. package/styles/layout/_component.scss +110 -0
  153. package/styles/{v2/layout → layout}/_data-table.scss +7 -7
  154. package/styles/layout/_wrapper-padding.scss +27 -0
  155. package/styles/{v2/main.scss → main.scss} +3 -1
  156. package/styles/{v2/themes → themes}/_color-definitions.scss +46 -41
  157. package/styles/{_accessibility.scss → utils/_accessibility.scss} +1 -1
  158. package/styles/{_global-variables.scss → utils/_properties.scss} +133 -112
  159. package/styles/{v2/utils → utils}/index.scss +2 -1
  160. package/types/Axis.ts +2 -0
  161. package/types/ComponentStyles.ts +1 -0
  162. package/types/ConfigureData.ts +1 -0
  163. package/types/MarkupInclude.ts +1 -0
  164. package/types/MarkupVariable.ts +2 -1
  165. package/types/Palette.ts +1 -0
  166. package/types/Table.ts +9 -0
  167. package/types/Visualization.ts +1 -0
  168. package/styles/_common-components.css +0 -73
  169. package/styles/_variables.scss +0 -63
  170. package/styles/v2/layout/_component.scss +0 -21
  171. package/styles/v2/utils/_variables.scss +0 -9
  172. package/{styles/v2/components/card.scss → components/elements/card.css} +2 -2
  173. /package/{styles/v2/components → components/ui}/icon.scss +0 -0
  174. /package/{styles/v2/components → components/ui}/loadspin.scss +0 -0
  175. /package/styles/{v2/base → base}/_heading.scss +0 -0
  176. /package/styles/{v2/base → base}/_reset.scss +0 -0
  177. /package/styles/{v2/layout → layout}/_alert.scss +0 -0
  178. /package/styles/{v2/layout → layout}/_progression.scss +0 -0
  179. /package/styles/{v2/layout → layout}/_tooltip.scss +0 -0
  180. /package/styles/{v2/layout → layout}/index.scss +0 -0
  181. /package/styles/{v2/themes → themes}/index.scss +0 -0
  182. /package/styles/{v2/utils → utils}/_align.scss +0 -0
  183. /package/styles/{v2/utils → utils}/_animations.scss +0 -0
  184. /package/styles/{v2/utils → utils}/_breakpoints.scss +0 -0
  185. /package/styles/{v2/utils → utils}/_grid.scss +0 -0
  186. /package/styles/{v2/utils → utils}/_mixins.scss +0 -0
@@ -0,0 +1,182 @@
1
+ import React from 'react'
2
+ import { render, screen } from '@testing-library/react'
3
+ import { describe, expect, it } from 'vitest'
4
+ import VisualizationContent from './VisualizationContent'
5
+
6
+ describe('VisualizationContent', () => {
7
+ it('renders the standard inner, body, and body-wrap layers by default', () => {
8
+ const { container } = render(
9
+ <VisualizationContent innerClassName='inner-extra' bodyClassName='body-extra' bodyWrapClassName='wrap-extra'>
10
+ <div>Inner content</div>
11
+ </VisualizationContent>
12
+ )
13
+
14
+ const inner = container.querySelector('.cove-visualization__inner')
15
+ const body = container.querySelector('.cove-visualization__body')
16
+ const bodyWrap = container.querySelector('.cove-visualization__body-wrap')
17
+ const content = container.querySelector('.cove-visualization__content-section')
18
+
19
+ expect(inner).toHaveClass('inner-extra')
20
+ expect(body).toHaveClass('body-extra')
21
+ expect(bodyWrap).toHaveClass('wrap-extra')
22
+ expect(inner?.firstElementChild).toBe(body)
23
+ expect(body?.firstElementChild).toBe(bodyWrap)
24
+ expect(bodyWrap?.firstElementChild).toBe(content)
25
+ expect(screen.getByText('Inner content')).toBeInTheDocument()
26
+ })
27
+
28
+ it('renders header and footer outside the body wrapper', () => {
29
+ const { container } = render(
30
+ <VisualizationContent
31
+ header={<div data-testid='header'>Header</div>}
32
+ footer={<div data-testid='footer'>Footer</div>}
33
+ >
34
+ <div>Wrapped content</div>
35
+ </VisualizationContent>
36
+ )
37
+
38
+ expect(screen.getByTestId('header')).toBeInTheDocument()
39
+ expect(screen.getByTestId('footer')).toBeInTheDocument()
40
+ expect(container.querySelector('.cove-visualization__body-wrap')?.textContent).toContain('Wrapped content')
41
+ })
42
+
43
+ it('renders message content inside the body-wrap before the wrapped content', () => {
44
+ const { container } = render(
45
+ <VisualizationContent message={<div data-testid='message'>Message</div>}>
46
+ <div>Wrapped content</div>
47
+ </VisualizationContent>
48
+ )
49
+
50
+ const body = container.querySelector('.cove-visualization__body')
51
+ const messageLayer = container.querySelector('.cove-visualization__message')
52
+ const message = container.querySelector('.cove-visualization__message-section')
53
+ const bodyWrap = container.querySelector('.cove-visualization__body-wrap')
54
+ const content = container.querySelector('.cove-visualization__content-section')
55
+
56
+ expect(screen.getByTestId('message')).toBeInTheDocument()
57
+ expect(messageLayer).toBe(message)
58
+ expect(body?.firstElementChild).toBe(bodyWrap)
59
+ expect(bodyWrap?.firstElementChild).toBe(message)
60
+ expect(bodyWrap?.children[1]).toBe(content)
61
+ })
62
+
63
+ it('adds the shared no-subtext body state only when outer subtext is absent', () => {
64
+ const { container: withoutSubtext } = render(
65
+ <VisualizationContent header={<div>Header</div>} message={<div>Message</div>}>
66
+ <div>Wrapped content</div>
67
+ </VisualizationContent>
68
+ )
69
+ const { container: withSubtext } = render(
70
+ <VisualizationContent header={<div>Header</div>} subtext={<div>Subtext</div>}>
71
+ <div>Wrapped content</div>
72
+ </VisualizationContent>
73
+ )
74
+
75
+ expect(withoutSubtext.querySelector('.cove-visualization__body')).toHaveClass(
76
+ 'cove-visualization__body--no-subtext'
77
+ )
78
+ expect(withSubtext.querySelector('.cove-visualization__body')).not.toHaveClass(
79
+ 'cove-visualization__body--no-subtext'
80
+ )
81
+ })
82
+
83
+ it('applies custom classes to the message wrapper', () => {
84
+ const { container } = render(
85
+ <VisualizationContent message={<div data-testid='message'>Message</div>} messageClassName='introText mb-4'>
86
+ <div>Wrapped content</div>
87
+ </VisualizationContent>
88
+ )
89
+
90
+ const message = container.querySelector('.cove-visualization__message')
91
+
92
+ expect(message).toHaveClass('introText')
93
+ expect(message).toHaveClass('mb-4')
94
+ })
95
+
96
+ it('applies the introText wrapper class when requested', () => {
97
+ const { container } = render(
98
+ <VisualizationContent message={<div data-testid='message'>Message</div>} messageIsIntroText>
99
+ <div>Wrapped content</div>
100
+ </VisualizationContent>
101
+ )
102
+
103
+ const message = container.querySelector('.cove-visualization__message')
104
+
105
+ expect(message).toHaveClass('introText')
106
+ })
107
+
108
+ it('renders subtext content inside the body after the body-wrap', () => {
109
+ const { container } = render(
110
+ <VisualizationContent subtext={<div data-testid='subtext'>Subtext</div>}>
111
+ <div>Wrapped content</div>
112
+ </VisualizationContent>
113
+ )
114
+
115
+ const body = container.querySelector('.cove-visualization__body')
116
+ const bodyWrap = container.querySelector('.cove-visualization__body-wrap')
117
+ const subtext = container.querySelector('.cove-visualization__subtext-section')
118
+
119
+ expect(screen.getByTestId('subtext')).toBeInTheDocument()
120
+ expect(body?.firstElementChild).toBe(bodyWrap)
121
+ expect(body?.lastElementChild).toBe(subtext)
122
+ expect(subtext).not.toHaveClass('mt-4')
123
+ expect(subtext).not.toHaveClass('mb-4')
124
+ expect(subtext).not.toHaveAttribute('style')
125
+ })
126
+
127
+ it('renders body subtext content inside the body-wrap after the wrapped content', () => {
128
+ const { container } = render(
129
+ <VisualizationContent bodySubtext={<div data-testid='body-subtext'>Body Subtext</div>}>
130
+ <div>Wrapped content</div>
131
+ </VisualizationContent>
132
+ )
133
+
134
+ const bodyWrap = container.querySelector('.cove-visualization__body-wrap')
135
+ const content = container.querySelector('.cove-visualization__content-section')
136
+ const bodySubtext = container.querySelector('.cove-visualization__body-subtext-section')
137
+
138
+ expect(screen.getByTestId('body-subtext')).toBeInTheDocument()
139
+ expect(bodyWrap?.lastElementChild).toBe(bodySubtext)
140
+ expect(bodyWrap?.firstElementChild).toBe(content)
141
+ expect(bodySubtext).not.toHaveClass('mt-4')
142
+ expect(bodySubtext).not.toHaveClass('mb-4')
143
+ expect(bodySubtext).not.toHaveAttribute('style')
144
+ })
145
+
146
+ it('renders body footer content inside the body-wrap after body subtext', () => {
147
+ const { container } = render(
148
+ <VisualizationContent
149
+ bodySubtext={<div data-testid='body-subtext'>Body Subtext</div>}
150
+ bodyFooter={<div data-testid='body-footer'>Body Footer</div>}
151
+ >
152
+ <div>Wrapped content</div>
153
+ </VisualizationContent>
154
+ )
155
+
156
+ const bodyWrap = container.querySelector('.cove-visualization__body-wrap')
157
+ const content = container.querySelector('.cove-visualization__content-section')
158
+ const bodySubtext = container.querySelector('.cove-visualization__body-subtext-section')
159
+ const bodyFooter = container.querySelector('.cove-visualization__body-footer-section')
160
+
161
+ expect(screen.getByTestId('body-footer')).toBeInTheDocument()
162
+ expect(bodyWrap?.children[0]).toBe(content)
163
+ expect(bodyWrap?.children[1]).toBe(bodySubtext)
164
+ expect(bodyWrap?.lastElementChild).toBe(bodyFooter)
165
+ })
166
+
167
+ it('passes through non-class inner div props, including refs', () => {
168
+ const innerRef = React.createRef<HTMLDivElement>()
169
+
170
+ const { container } = render(
171
+ <VisualizationContent innerClassName='inner-extra' innerProps={{ 'aria-label': 'Visualization content', ref: innerRef }}>
172
+ <div>Inner content</div>
173
+ </VisualizationContent>
174
+ )
175
+
176
+ const inner = container.querySelector('.cove-visualization__inner')
177
+
178
+ expect(inner).toHaveAttribute('aria-label', 'Visualization content')
179
+ expect(inner).toHaveClass('inner-extra')
180
+ expect(innerRef.current).toBe(inner)
181
+ })
182
+ })
@@ -0,0 +1,75 @@
1
+ import React from 'react'
2
+
3
+ type VisualizationContentInnerProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>
4
+
5
+ type VisualizationContentProps = {
6
+ bodyFooter?: React.ReactNode
7
+ bodySubtext?: React.ReactNode
8
+ bodyClassName?: string
9
+ bodyWrapClassName?: string
10
+ children: React.ReactNode
11
+ filters?: React.ReactNode
12
+ footer?: React.ReactNode
13
+ header?: React.ReactNode
14
+ innerClassName?: string
15
+ innerProps?: VisualizationContentInnerProps
16
+ message?: React.ReactNode
17
+ messageClassName?: string
18
+ messageIsIntroText?: boolean
19
+ subtext?: React.ReactNode
20
+ }
21
+
22
+ const VisualizationContent = ({
23
+ bodyFooter,
24
+ bodySubtext,
25
+ bodyClassName,
26
+ bodyWrapClassName,
27
+ children,
28
+ filters,
29
+ footer,
30
+ header,
31
+ innerClassName,
32
+ innerProps,
33
+ message,
34
+ messageClassName,
35
+ messageIsIntroText,
36
+ subtext
37
+ }: VisualizationContentProps) => {
38
+ const resolvedInnerClasses = ['cove-visualization__inner', innerClassName].filter(Boolean).join(' ')
39
+ const bodyClasses = ['cove-visualization__body', !subtext && 'cove-visualization__body--no-subtext', bodyClassName].filter(Boolean).join(' ')
40
+ const bodyWrapClasses = ['cove-visualization__body-wrap', bodyWrapClassName].filter(Boolean).join(' ')
41
+
42
+ return (
43
+ <div {...innerProps} className={resolvedInnerClasses}>
44
+ {header}
45
+ <div className={bodyClasses}>
46
+ <div className={bodyWrapClasses}>
47
+ {message ? (
48
+ <section
49
+ className={[
50
+ 'cove-visualization__message',
51
+ 'cove-visualization__message-section',
52
+ messageIsIntroText && 'introText',
53
+ messageClassName
54
+ ]
55
+ .filter(Boolean)
56
+ .join(' ')}
57
+ >
58
+ {message}
59
+ </section>
60
+ ) : null}
61
+ {filters ? <section className='cove-visualization__filters-section'>{filters}</section> : null}
62
+ <section className='cove-visualization__content-section'>{children}</section>
63
+ {bodySubtext ? (
64
+ <section className='cove-visualization__body-subtext-section'>{bodySubtext}</section>
65
+ ) : null}
66
+ {bodyFooter ? <section className='cove-visualization__body-footer-section'>{bodyFooter}</section> : null}
67
+ </div>
68
+ {subtext ? <section className='cove-visualization__subtext-section'>{subtext}</section> : null}
69
+ </div>
70
+ {footer}
71
+ </div>
72
+ )
73
+ }
74
+
75
+ export default VisualizationContent
@@ -1,11 +1,11 @@
1
1
  import Responsive from './components/Responsive'
2
2
  import Sidebar from './components/Sidebar'
3
+ import VisualizationContainer from './components/VisualizationContainer'
4
+ import VisualizationContent from './components/VisualizationContent'
3
5
  import VisualizationWrapper from './components/Visualization'
4
6
 
5
- const Layout = {
6
- Responsive,
7
- Sidebar,
8
- VisualizationWrapper
9
- }
7
+ export { Responsive, Sidebar, VisualizationContainer, VisualizationContent, VisualizationWrapper }
10
8
 
9
+ /** @deprecated Use named imports instead: `import { Responsive, Sidebar, VisualizationContainer, VisualizationContent } from '@cdc/core/components/Layout'` */
10
+ const Layout = { Responsive, Sidebar, VisualizationContainer, VisualizationContent, VisualizationWrapper }
11
11
  export default Layout
@@ -1,7 +1,7 @@
1
1
  $editorAnimationTimer: 400ms;
2
2
  $primary: #3e92d5;
3
3
 
4
- .cdc-open-viz-module .cove-editor-utils__hotkeys {
4
+ .cove-visualization .cove-editor-utils__hotkeys {
5
5
  display: inline-flex;
6
6
  flex-flow: row nowrap;
7
7
  position: fixed;
@@ -54,7 +54,7 @@ $primary: #3e92d5;
54
54
  }
55
55
  }
56
56
 
57
- .cdc-open-viz-module .cove-editor-utils__breakpoints {
57
+ .cove-visualization .cove-editor-utils__breakpoints {
58
58
  position: fixed;
59
59
  bottom: 5rem;
60
60
  right: 4rem;
@@ -97,7 +97,7 @@ $primary: #3e92d5;
97
97
  list-style: none;
98
98
  }
99
99
 
100
- .cdc-open-viz-module .cove-editor-utils__breakpoints-item {
100
+ .cove-visualization .cove-editor-utils__breakpoints-item {
101
101
  display: block;
102
102
  position: relative;
103
103
  margin-right: 1rem;
@@ -1,4 +1,4 @@
1
- @import '../../../styles/v2/utils/variables';
1
+ @import '../../../styles/utils/properties';
2
2
 
3
3
  $editorAnimationTimer: 400ms;
4
4
  $mediumGray: #e6e6e6;
@@ -81,7 +81,7 @@ $mediumGray: #e6e6e6;
81
81
 
82
82
  @at-root {
83
83
  .cove-editor {
84
- width: $editorWidth;
84
+ width: var(--editorWidth);
85
85
  }
86
86
  }
87
87
  }
@@ -127,8 +127,8 @@ $mediumGray: #e6e6e6;
127
127
  background-color: #e6e6e6;
128
128
  transition: background-color 400ms cubic-bezier(0.16, 1, 0.3, 1);
129
129
  overflow: hidden auto;
130
- width: calc(100% - $editorWidth);
131
- left: $editorWidth;
130
+ width: calc(100% - var(--editorWidth));
131
+ left: var(--editorWidth);
132
132
  @at-root {
133
133
  .cove-editor.panel-shown #{&} {
134
134
  background-color: #e7e7e7;
@@ -99,7 +99,13 @@ const LegendGradient = ({
99
99
  if (style === 'gradient') {
100
100
  return (
101
101
  // TODO: figure out why bootstrap 'overflow: visible' is not working consistently
102
- <svg className={'w-100 overflow-visible'} height={newHeight} style={{ overflow: 'visible' }} width={width}>
102
+ <svg
103
+ className={'w-100 overflow-visible'}
104
+ height={newHeight}
105
+ style={{ display: 'block', maxWidth: '100%', overflow: 'visible' }}
106
+ viewBox={`0 0 ${width} ${newHeight}`}
107
+ width='100%'
108
+ >
103
109
  {/* background border*/}
104
110
  <rect x={0} y={0} width={legendWidth + MARGIN * 2} height={boxHeight + MARGIN * 2} fill={BORDER_COLOR} />
105
111
  {/* Define the gradient */}
@@ -1,10 +1,10 @@
1
1
  .cove-loader {
2
2
  &.fullscreen {
3
3
  background: rgba(255, 255, 255, 0.8);
4
- position: absolute;
5
- width: 100%;
6
4
  display: flex;
7
5
  justify-content: center;
6
+ position: absolute;
7
+ width: 100%;
8
8
  z-index: 100;
9
9
  & > * {
10
10
  margin-top: 40vh;
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import '../styles/loading.scss'
2
+ import './loading.scss'
3
3
 
4
4
  export default function Loading({ viewport = 'lg' }) {
5
5
  return (
@@ -161,6 +161,13 @@ const Button = ({
161
161
  }) => {
162
162
  const buttonClasses = ['btn', 'btn-primary']
163
163
 
164
+ const label =
165
+ type === 'csv'
166
+ ? state?.table?.downloadDataLabel || buttonText[type]
167
+ : type === 'image'
168
+ ? state?.table?.downloadImageLabel || buttonText[type]
169
+ : buttonText[type]
170
+
164
171
  return (
165
172
  <button
166
173
  className={buttonClasses.join(' ')}
@@ -168,7 +175,7 @@ const Button = ({
168
175
  onClick={() => generateMedia(state, type, elementToCapture, interactionLabel, includeContextInDownload)}
169
176
  style={{ lineHeight: '1.4em' }}
170
177
  >
171
- {buttonText[type]}
178
+ {label}
172
179
  </button>
173
180
  )
174
181
  }
@@ -184,7 +191,8 @@ const DownloadLink = ({
184
191
  }) => {
185
192
  const vizType = state?.type === 'map' ? 'Map' : 'Chart'
186
193
  const format = type === 'pdf' ? 'PDF' : 'PNG'
187
- const linkText = `Download ${vizType} (${format})`
194
+ const defaultLinkText = `Download ${vizType} (${format})`
195
+ const linkText = type === 'image' ? state?.table?.downloadImageLabel || defaultLinkText : defaultLinkText
188
196
 
189
197
  return (
190
198
  <a
@@ -3,45 +3,45 @@
3
3
  display: block;
4
4
  }
5
5
  .wrapper {
6
- display: inline-flex;
7
6
  align-items: center;
7
+ display: inline-flex;
8
8
  width: 100%;
9
9
  .selected {
10
10
  &[aria-disabled='true'] {
11
11
  background: var(--lightestGray);
12
12
  }
13
13
  border: 1px solid var(--lightGray);
14
- padding: 7px;
14
+ border-radius: 5px;
15
+ display: inline-block;
15
16
  min-width: 200px;
17
+ padding: 7px;
16
18
  width: 100%;
17
- display: inline-block;
18
19
  :is(button) {
19
- border: none;
20
20
  background: none;
21
+ border: none;
21
22
  }
22
23
  :is(div) {
23
- display: inline-block;
24
- padding: 0 0 0 5px;
25
- margin-right: 5px;
26
- margin-bottom: 2px;
27
24
  background: var(--lightGray);
28
25
  border-radius: 5px;
26
+ display: inline-block;
27
+ margin-bottom: 2px;
28
+ margin-right: 5px;
29
+ padding: 0 0 0 5px;
29
30
  }
30
31
  .expand {
31
- padding: 2px 0px;
32
- margin-right: -6px;
32
+ color: var(--mediumGray);
33
33
  float: right;
34
34
  margin-bottom: -3px;
35
- color: var(--mediumGray);
35
+ margin-right: -6px;
36
+ padding: 2px 0px;
36
37
  &:focus {
37
38
  outline: none;
38
39
  }
39
40
  }
40
- border-radius: 5px;
41
41
  }
42
42
  .cove-tooltip__content {
43
- position: absolute;
44
43
  min-width: 120px;
44
+ position: absolute;
45
45
  :is(p) {
46
46
  margin-bottom: 0;
47
47
  }
@@ -52,15 +52,15 @@
52
52
  }
53
53
  .dropdown {
54
54
  background: white;
55
- position: absolute;
56
- top: var(--select-height);
57
- margin-top: 0px;
58
55
  border: 1px solid var(--lightGray);
59
- padding-left: 0;
60
- min-height: 40px;
56
+ margin-top: 0px;
61
57
  max-height: 200px;
62
- overflow-y: scroll;
58
+ min-height: 40px;
63
59
  min-width: 200px;
60
+ overflow-y: scroll;
61
+ padding-left: 0;
62
+ position: absolute;
63
+ top: var(--select-height);
64
64
  z-index: 4;
65
65
 
66
66
  :is(li) {
@@ -1,4 +1,4 @@
1
- .cdc-dashboard-inner-container.cove-component__content.cove-dashboard-filters-container:has(
1
+ .cdc-dashboard-inner-container.cove-visualization__body.cove-dashboard-filters-container:has(
2
2
  > .nested-dropdown.open-filter
3
3
  )
4
4
  :has(> .nested-dropdown-container) {
@@ -16,14 +16,14 @@
16
16
  }
17
17
 
18
18
  .search-input {
19
- color: var(--cool-gray-90);
20
- font-weight: 300;
21
19
 
22
20
  border: none;
23
- position: relative;
21
+ color: var(--cool-gray-90);
24
22
  display: inline-block;
25
- width: 100%;
23
+ font-weight: 300;
26
24
  padding: 0;
25
+ position: relative;
26
+ width: 100%;
27
27
  &::placeholder {
28
28
  color: var(--cool-gray-90);
29
29
  }
@@ -36,21 +36,21 @@
36
36
  [class^='main-nested-dropdown-container-'],
37
37
  .nested-dropdown-input-container {
38
38
  border: 1px solid var(--cool-gray-10);
39
+ font-size: 1em;
39
40
  min-width: 200px;
40
41
  padding: 0.4rem 0.75rem;
41
- font-size: 1em;
42
42
  }
43
43
 
44
44
  [class^='selectable-item-'] {
45
+ font-weight: normal;
45
46
  list-style: none;
46
47
  padding-left: 20px;
47
48
  position: relative;
48
- font-weight: normal;
49
49
  white-space: nowrap;
50
50
 
51
51
  & .check-mark {
52
- position: absolute;
53
52
  left: 0px;
53
+ position: absolute;
54
54
  }
55
55
 
56
56
  &:hover {
@@ -59,16 +59,16 @@
59
59
  }
60
60
 
61
61
  .nested-dropdown-input-container {
62
- display: block;
63
- width: calc(100% + 7px);
64
62
  border-radius: 0.25rem;
63
+ display: block;
65
64
  position: relative;
65
+ width: calc(100% + 7px);
66
66
  & > span.list-arrow {
67
- position: absolute;
68
- top: 9px;
69
- right: 9px;
70
67
  float: right;
71
68
  pointer-events: none;
69
+ position: absolute;
70
+ right: 9px;
71
+ top: 9px;
72
72
  }
73
73
 
74
74
  &.disabled {
@@ -80,12 +80,12 @@
80
80
  }
81
81
 
82
82
  & [class^='main-nested-dropdown-container-'] {
83
+ background: white;
83
84
  max-height: 375px;
85
+ min-width: 200px;
84
86
  overflow-y: auto;
85
87
  position: absolute;
86
88
  z-index: 3;
87
- min-width: 200px;
88
- background: white;
89
89
  }
90
90
 
91
91
  .hide {
@@ -7,12 +7,12 @@
7
7
 
8
8
  /* List item-based palette selector (used by maps) */
9
9
  .color-palette li {
10
- width: 1.5em;
11
- height: 1.5em;
10
+ border: rgba(0, 0, 0, 0.3) 3px solid;
11
+ cursor: pointer;
12
12
  display: inline-block;
13
+ height: 1.5em;
13
14
  margin-right: 0.5em;
14
- cursor: pointer;
15
- border: rgba(0, 0, 0, 0.3) 3px solid;
15
+ width: 1.5em;
16
16
  }
17
17
 
18
18
  .color-palette li.active {
@@ -33,25 +33,25 @@
33
33
  }
34
34
 
35
35
  .color-palette a {
36
- display: inline-block;
37
36
  border-bottom: 1px solid rgba(0, 0, 0, 0.8);
37
+ display: inline-block;
38
38
  }
39
39
 
40
40
  /* Series list variant */
41
41
  .color-palette.series-list {
42
+ border: none;
42
43
  flex-direction: column;
43
44
  padding: 0;
44
- border: none;
45
45
  }
46
46
 
47
47
  .color-palette.series-list li {
48
- padding: 0.3em 0.5em;
49
- display: flex;
50
48
  align-items: center;
49
+ border: 0;
50
+ display: flex;
51
+ height: auto;
51
52
  justify-content: space-between;
53
+ padding: 0.3em 0.5em;
52
54
  width: auto;
53
- height: auto;
54
- border: 0;
55
55
  }
56
56
 
57
57
  .color-palette.series-list li:not(:last-child) {
@@ -60,18 +60,18 @@
60
60
 
61
61
  /* Header variant */
62
62
  .header .color-palette li {
63
- width: 1.5em;
64
- height: 1.5em;
65
63
  display: inline-block;
64
+ height: 1.5em;
65
+ width: 1.5em;
66
66
  }
67
67
 
68
68
  /* Developer rollback component styles */
69
69
  .developer-palette-rollback {
70
- margin: 8px 0;
71
- padding: 8px;
70
+ background-color: #fffbf0;
72
71
  border: 1px dashed #ffc107;
73
72
  border-radius: 4px;
74
- background-color: #fffbf0;
73
+ margin: 8px 0;
74
+ padding: 8px;
75
75
  }
76
76
 
77
77
  .developer-palette-rollback .rollback-info {
@@ -1,16 +1,16 @@
1
1
  .tooltip-link {
2
+ color: var(--cool-gray-90);
3
+ cursor: pointer;
4
+ font-family: var(--app-font-main);
5
+ font-size: 0.833rem !important;
6
+ position: relative;
2
7
  text-decoration: underline;
3
8
  text-decoration-color: var(--cool-gray-90);
4
9
  text-decoration-style: dotted;
5
10
  text-decoration-thickness: 2px;
6
11
  text-underline-offset: 0.25rem;
7
- position: relative;
8
- cursor: pointer;
9
- color: var(--cool-gray-90);
10
- font-family: var(--app-font-main);
11
- font-size: 0.833rem !important;
12
12
  }
13
13
  .tooltip-link:hover {
14
- text-decoration-color: #009ec1;
15
14
  color: var(--cool-gray-90);
15
+ text-decoration-color: #009ec1;
16
16
  }
@@ -2,9 +2,9 @@
2
2
  clip: rect(0 0 0 0);
3
3
  clip-path: inset(50%);
4
4
  height: 1px;
5
+ left: -10000px;
5
6
  overflow: hidden;
7
+ position: fixed;
6
8
  white-space: nowrap;
7
9
  width: 1px;
8
- position: fixed;
9
- left: -10000px;
10
10
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import '../styles/waiting.scss'
2
+ import './waiting.scss'
3
3
 
4
4
  const styles = {
5
5
  position: 'relative',