@cdc/core 4.25.10 → 4.26.1

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 (134) hide show
  1. package/_stories/Gallery.Charts.stories.tsx +307 -0
  2. package/_stories/Gallery.DataBite.stories.tsx +72 -0
  3. package/_stories/Gallery.Maps.stories.tsx +230 -0
  4. package/_stories/Gallery.WaffleChart.stories.tsx +187 -0
  5. package/_stories/PageART.stories.tsx +192 -0
  6. package/_stories/PageBRFSS.stories.tsx +289 -0
  7. package/_stories/PageCancerRegistries.stories.tsx +199 -0
  8. package/_stories/PageEasternEquineEncephalitis.stories.tsx +202 -0
  9. package/_stories/PageExcessiveAlcoholUse.stories.tsx +196 -0
  10. package/_stories/PageMaternalMortality.stories.tsx +192 -0
  11. package/_stories/PageOralHealth.stories.tsx +196 -0
  12. package/_stories/PageRespiratory.stories.tsx +332 -0
  13. package/_stories/PageSmokingTobacco.stories.tsx +195 -0
  14. package/_stories/PageStateDiabetesProfiles.stories.tsx +196 -0
  15. package/_stories/PageWastewater.stories.tsx +463 -0
  16. package/_stories/StoryRenderingTests.stories.tsx +164 -0
  17. package/assets/icon-magnifying-glass.svg +5 -0
  18. package/assets/icon-warming-stripes.svg +13 -0
  19. package/components/AdvancedEditor/AdvancedEditor.tsx +7 -1
  20. package/components/AdvancedEditor/EmbedEditor.tsx +281 -0
  21. package/components/ComboBox/ComboBox.tsx +345 -0
  22. package/components/ComboBox/combobox.styles.css +185 -0
  23. package/components/ComboBox/index.ts +1 -0
  24. package/components/CustomColorsEditor/CustomColorsEditor.css +299 -0
  25. package/components/CustomColorsEditor/CustomColorsEditor.tsx +209 -0
  26. package/components/CustomColorsEditor/index.ts +1 -0
  27. package/components/DataTable/DataTable.tsx +132 -58
  28. package/components/DataTable/DataTableStandAlone.tsx +8 -3
  29. package/components/DataTable/components/DataTableEditorPanel.tsx +12 -2
  30. package/components/DataTable/data-table.css +217 -210
  31. package/components/DataTable/helpers/mapCellMatrix.tsx +28 -9
  32. package/components/DataTable/helpers/standardizeState.js +2 -2
  33. package/components/DataTable/helpers/tests/standardizeState.test.js +54 -0
  34. package/components/EditorPanel/ColumnsEditor.tsx +37 -19
  35. package/components/EditorPanel/DataTableEditor.tsx +54 -28
  36. package/components/EditorPanel/EditorPanel.styles.css +439 -0
  37. package/components/EditorPanel/EditorPanel.tsx +144 -0
  38. package/components/EditorPanel/EditorPanelDispatch.tsx +75 -0
  39. package/components/EditorPanel/FieldSetWrapper.tsx +66 -23
  40. package/components/EditorPanel/FootnotesEditor.tsx +44 -37
  41. package/components/EditorPanel/Inputs.tsx +44 -8
  42. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +35 -62
  43. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +246 -175
  44. package/components/EditorPanel/components/MarkupVariablesEditor.tsx +61 -22
  45. package/components/EditorPanel/sections/VisualSection.tsx +169 -0
  46. package/components/Filters/Filters.tsx +57 -10
  47. package/components/Filters/components/Dropdown.tsx +6 -1
  48. package/components/Filters/helpers/getNestedOptions.ts +2 -1
  49. package/components/Filters/helpers/handleSorting.ts +1 -1
  50. package/components/Footnotes/Footnotes.tsx +35 -25
  51. package/components/Footnotes/FootnotesStandAlone.tsx +42 -6
  52. package/components/HeaderThemeSelector/HeaderThemeSelector.css +43 -0
  53. package/components/HeaderThemeSelector/HeaderThemeSelector.stories.tsx +74 -0
  54. package/components/HeaderThemeSelector/HeaderThemeSelector.tsx +61 -0
  55. package/components/HeaderThemeSelector/index.ts +2 -0
  56. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +82 -0
  57. package/components/Layout/components/Visualization/index.tsx +16 -1
  58. package/components/Layout/components/Visualization/visualizations.scss +7 -0
  59. package/components/Layout/styles/editor.scss +2 -1
  60. package/components/Legend/Legend.Gradient.tsx +1 -1
  61. package/components/Loader/Loader.tsx +1 -1
  62. package/components/MediaControls.tsx +63 -34
  63. package/components/PaletteConversionModal.tsx +7 -4
  64. package/components/PaletteSelector/PaletteSelector.css +49 -6
  65. package/components/Table/components/Cell.tsx +23 -2
  66. package/components/Table/components/Row.tsx +5 -3
  67. package/components/_stories/Filters.stories.tsx +20 -1
  68. package/components/_stories/Footnotes.CSV.stories.tsx +247 -0
  69. package/components/_stories/Footnotes.stories.tsx +768 -3
  70. package/components/_stories/Inputs.stories.tsx +2 -2
  71. package/components/_stories/styles.scss +0 -1
  72. package/components/ui/Accordion.jsx +1 -1
  73. package/components/ui/Icon.tsx +3 -1
  74. package/components/ui/Title/index.tsx +30 -2
  75. package/components/ui/Title/title.styles.css +42 -0
  76. package/components/ui/accordion.styles.css +57 -0
  77. package/data/chartColorPalettes.ts +1 -1
  78. package/dist/cove-main.css +75 -6
  79. package/dist/cove-main.css.map +1 -1
  80. package/generateViteConfig.js +8 -1
  81. package/helpers/addValuesToFilters.ts +11 -1
  82. package/helpers/constants.ts +37 -0
  83. package/helpers/cove/number.ts +33 -12
  84. package/helpers/coveUpdateWorker.ts +20 -11
  85. package/helpers/embedCodeGenerator.ts +109 -0
  86. package/helpers/fetchRemoteData.ts +3 -15
  87. package/helpers/getUniqueValues.ts +19 -0
  88. package/helpers/hashObj.ts +25 -0
  89. package/helpers/isRightAlignedTableValue.js +5 -0
  90. package/helpers/markupProcessor.ts +27 -12
  91. package/helpers/mergeCustomOrderValues.ts +37 -0
  92. package/helpers/metrics/helpers.ts +1 -0
  93. package/helpers/parseCsvWithQuotes.ts +65 -0
  94. package/helpers/pivotData.ts +2 -2
  95. package/helpers/prepareScreenshot.ts +268 -0
  96. package/helpers/queryStringUtils.ts +29 -0
  97. package/helpers/testing.ts +17 -4
  98. package/helpers/tests/prepareScreenshot.test.ts +414 -0
  99. package/helpers/tests/queryStringUtils.test.ts +381 -0
  100. package/helpers/tests/testStandaloneBuild.ts +23 -5
  101. package/helpers/useDataVizClasses.ts +0 -1
  102. package/helpers/ver/4.25.11.ts +13 -0
  103. package/helpers/ver/4.26.1.ts +80 -0
  104. package/helpers/viewports.ts +2 -0
  105. package/hooks/useDataColumns.ts +63 -0
  106. package/hooks/useFilterManagement.ts +94 -0
  107. package/hooks/useLegendSeparators.ts +26 -0
  108. package/hooks/useListManagement.ts +192 -0
  109. package/package.json +6 -4
  110. package/styles/_button-section.scss +0 -3
  111. package/styles/_common-components.css +73 -0
  112. package/styles/_global.scss +25 -5
  113. package/styles/base.scss +0 -50
  114. package/styles/cove-main.scss +3 -1
  115. package/styles/filters.scss +10 -3
  116. package/styles/v2/base/index.scss +0 -1
  117. package/styles/v2/components/editor.scss +14 -6
  118. package/styles/v2/utils/_breakpoints.scss +1 -1
  119. package/styles/v2/utils/index.scss +0 -1
  120. package/styles/waiting.scss +1 -1
  121. package/types/Axis.ts +1 -0
  122. package/types/ForecastingSeriesKey.ts +1 -0
  123. package/types/MarkupInclude.ts +5 -3
  124. package/types/MarkupVariable.ts +1 -1
  125. package/types/Series.ts +3 -0
  126. package/types/Table.ts +1 -0
  127. package/types/Visualization.ts +1 -0
  128. package/types/VizFilter.ts +2 -0
  129. package/LICENSE +0 -201
  130. package/styles/_mixins.scss +0 -13
  131. package/styles/_typography.scss +0 -0
  132. package/styles/v2/base/_typography.scss +0 -0
  133. package/styles/v2/components/guidance-block.scss +0 -74
  134. package/styles/v2/utils/_functions.scss +0 -0
@@ -1,278 +1,285 @@
1
- .table {
2
- width: unset;
3
- min-width: 100%;
4
- }
5
-
6
- .bs4 .table.table-width-unset {
7
- width: unset;
8
- }
9
-
10
- .collapsed+.table-container {
11
- border-bottom: none;
12
- }
13
-
14
- .table-container {
15
- overflow-x: auto;
16
- border-right: 1px solid var(--lightGray);
17
- border-left: 1px solid var(--lightGray);
18
- border-bottom: 1px solid var(--lightGray);
19
- }
20
-
21
- .cdc-open-viz-module div.data-table-heading {
22
- position: relative;
23
- border: var(--cool-gray-10) 1px solid;
24
- border-radius: 6px;
25
-
26
- svg {
27
- position: absolute;
28
- height: 100%;
29
- width: 15px;
30
- top: 0;
31
- right: 1em;
1
+ .cove,
2
+ .cdc-open-viz-module {
3
+ .table {
4
+ width: unset;
5
+ min-width: 100%;
32
6
  }
33
7
 
34
- &:focus {
35
- z-index: 2;
36
- position: relative;
8
+ .bs4 .table.table-width-unset {
9
+ width: unset;
37
10
  }
38
- }
39
11
 
40
- table.horizontal {
41
-
42
- th,
43
- td {
44
- min-width: 200px;
45
- }
46
- }
47
-
48
- table.data-table {
49
- margin-bottom: 0;
50
- background: #fff;
51
- position: relative;
52
- border: none;
53
- border-collapse: collapse;
54
- appearance: none;
55
- table-layout: fixed;
56
-
57
- * {
58
- box-sizing: border-box;
12
+ .collapsed+.table-container {
13
+ border-bottom: none;
59
14
  }
60
15
 
61
- thead {
62
- user-select: none;
63
- -moz-user-select: none;
64
- user-select: none;
65
-
66
- button {
67
- background: none;
68
- font-size: initial;
69
- color: #fff;
70
- border: 0;
71
- }
72
-
73
- tr {
74
- background: none;
75
- }
16
+ .table-container {
17
+ overflow-x: auto;
18
+ border-right: 1px solid var(--lightGray);
19
+ border-left: 1px solid var(--lightGray);
20
+ border-bottom: 1px solid var(--lightGray);
76
21
  }
77
22
 
78
- thead {
79
- color: #fff;
23
+ div.data-table-heading {
24
+ position: relative;
25
+ border: var(--cool-gray-10) 1px solid;
26
+ border-radius: 6px;
80
27
 
81
- .resizer {
82
- cursor: e-resize;
83
- width: 10px;
28
+ svg {
84
29
  position: absolute;
30
+ height: 100%;
31
+ width: 15px;
85
32
  top: 0;
86
- bottom: 0;
87
- right: 0;
88
- touch-action: none;
33
+ right: 1em;
89
34
  }
90
35
 
91
- tr {
92
- text-align: left;
36
+ &:focus {
37
+ z-index: 2;
38
+ position: relative;
93
39
  }
40
+ }
41
+
42
+ table.horizontal {
94
43
 
95
44
  th,
96
45
  td {
97
- padding: 0.5em 0.7em;
98
- line-height: normal;
99
- position: relative;
100
- text-align: left;
101
- border-right: 1px solid var(--lightGray) !important;
46
+ min-width: 200px;
102
47
  }
48
+ }
103
49
 
104
- th {
105
- background-color: var(--primary);
106
- background-repeat: no-repeat;
107
- background-position: right 0.5em center;
108
- background-size: 10px 5px;
109
- }
50
+ table.data-table {
51
+ margin-bottom: 0;
52
+ background: #fff;
53
+ position: relative;
54
+ border: none;
55
+ border-collapse: collapse;
56
+ appearance: none;
57
+ table-layout: fixed;
110
58
 
111
- th:last-child,
112
- td:last-child {
113
- border-right: 0;
59
+ * {
60
+ box-sizing: border-box;
114
61
  }
115
- }
116
62
 
117
- tr {
118
- &.row-group {
119
- background-color: var(--tertiary) !important;
120
- font-weight: bold;
121
- }
63
+ thead {
64
+ user-select: none;
65
+ -moz-user-select: none;
66
+ user-select: none;
122
67
 
123
- border-bottom: solid 1px #e5e5e5;
124
- min-width: 100%;
68
+ button {
69
+ background: none;
70
+ font-size: initial;
71
+ color: #fff !important;
72
+ border: 0;
73
+ }
125
74
 
126
- /* Needed to fill content up*/
127
- &:last-child {
128
- border-bottom: 0;
75
+ tr {
76
+ background: none;
77
+ }
129
78
  }
130
- }
131
79
 
132
- th,
133
- td {
134
- padding: 0.3em 0.7em;
135
- border-right: 1px solid rgba(0, 0, 0, 0.1);
136
- white-space: nowrap;
80
+ thead {
81
+ color: #fff !important;
82
+
83
+ .resizer {
84
+ cursor: e-resize;
85
+ width: 10px;
86
+ position: absolute;
87
+ top: 0;
88
+ bottom: 0;
89
+ right: 0;
90
+ touch-action: none;
91
+ }
92
+
93
+ tr {
94
+ text-align: left;
95
+ }
96
+
97
+ th,
98
+ td {
99
+ padding: 0.5em 0.7em;
100
+ line-height: normal;
101
+ position: relative;
102
+ text-align: left;
103
+ border-right: 1px solid var(--lightGray) !important;
104
+ }
105
+
106
+ th {
107
+ background-color: var(--primary);
108
+ background-repeat: no-repeat;
109
+ background-position: right 0.5em center;
110
+ background-size: 10px 5px;
111
+ color: #fff !important
112
+ }
137
113
 
138
- &:last-child {
139
- border-right: 0 !important;
114
+ th:last-child,
115
+ td:last-child {
116
+ border-right: 0;
117
+ }
140
118
  }
141
- }
142
119
 
143
- td {
144
- position: relative;
120
+ tr {
121
+ &.row-group {
122
+ background-color: var(--tertiary) !important;
123
+ font-weight: bold;
124
+ }
145
125
 
146
- svg {
147
- margin-left: 1rem;
126
+ border-bottom: solid 1px #e5e5e5;
127
+ min-width: 100%;
148
128
 
149
- &.legend-shape-svg {
150
- display: flex;
151
- margin-left: 0 !important;
129
+ /* Needed to fill content up*/
130
+ &:last-child {
131
+ border-bottom: 0;
152
132
  }
153
133
  }
154
134
 
155
- }
135
+ th,
136
+ td {
137
+ padding: 0.3em 0.7em;
138
+ border-right: 1px solid rgba(0, 0, 0, 0.1);
139
+ white-space: nowrap;
156
140
 
157
- td a {
158
- padding: 0.3em 0.7em;
159
- position: absolute;
160
- top: 0;
161
- bottom: 0;
162
- right: 0;
163
- left: 0;
164
- display: block;
165
- color: inherit;
166
- text-decoration: none;
167
- }
141
+ &:last-child {
142
+ border-right: 0 !important;
143
+ }
144
+ }
168
145
 
169
- td span.table-link {
170
- text-decoration: underline;
171
- cursor: pointer;
172
- color: #075290;
146
+ td {
147
+ position: relative;
148
+
149
+ svg {
150
+ margin-left: 1rem;
151
+
152
+ &.legend-shape-svg {
153
+ display: flex;
154
+ margin-left: 0 !important;
155
+ }
156
+ }
173
157
 
174
- svg {
175
- max-width: 13px;
176
- vertical-align: baseline;
177
- margin-left: 5px;
178
158
  }
179
- }
180
159
 
181
- .boxplot-td {
182
- table-layout: fixed;
183
- width: 200;
184
- }
185
- }
186
-
187
- .no-data {
188
- position: relative;
189
-
190
- .no-data-message {
191
- background: rgba(255, 255, 255, 0.5);
192
- top: 0;
193
- left: 0;
194
- right: 0;
195
- bottom: 0;
196
- position: absolute;
197
- text-align: center;
198
- display: flex;
199
- align-items: center;
200
- justify-content: center;
201
- z-index: 7;
160
+ td a {
161
+ padding: 0.3em 0.7em;
162
+ position: absolute;
163
+ top: 0;
164
+ bottom: 0;
165
+ right: 0;
166
+ left: 0;
167
+ display: block;
168
+ color: inherit;
169
+ text-decoration: none;
170
+ }
202
171
 
203
- :is(h3) {
204
- font-size: 1.3rem;
205
- font-weight: 600;
206
- margin-bottom: 0.3rem;
172
+ td div a {
173
+ position: relative;
174
+ padding: 0;
175
+ display: inline;
207
176
  }
208
- }
209
177
 
210
- tr:hover {
211
- background: #fff;
212
- }
178
+ td span.table-link {
179
+ text-decoration: underline;
180
+ cursor: pointer;
181
+ color: #075290;
213
182
 
214
- th,
215
- td {
216
- width: 50%;
183
+ svg {
184
+ max-width: 13px;
185
+ vertical-align: baseline;
186
+ margin-left: 5px;
187
+ }
188
+ }
217
189
 
218
- &::before {
219
- content: '\00a0';
190
+ .boxplot-td {
191
+ table-layout: fixed;
192
+ width: 200;
220
193
  }
221
194
  }
222
- }
223
195
 
224
- .data-table-pagination {
225
- margin: 1rem 0;
226
- display: flex;
227
- align-items: center;
196
+ .no-data {
197
+ position: relative;
228
198
 
229
- ul {
230
- list-style: none;
231
- margin: 0 1rem 0 0;
232
- display: flex;
199
+ .no-data-message {
200
+ background: rgba(255, 255, 255, 0.5);
201
+ top: 0;
202
+ left: 0;
203
+ right: 0;
204
+ bottom: 0;
205
+ position: absolute;
206
+ text-align: center;
207
+ display: flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ z-index: 7;
211
+
212
+ :is(h3) {
213
+ font-size: 1.3rem;
214
+ font-weight: 600;
215
+ margin-bottom: 0.3rem;
216
+ }
217
+ }
233
218
 
234
- li+li {
235
- margin-left: 0.3rem;
219
+ tr:hover {
220
+ background: #fff;
236
221
  }
237
222
 
238
- button {
239
- background: var(--mediumGray);
223
+ th,
224
+ td {
225
+ width: 50%;
240
226
 
241
- &:hover {
242
- background: lighten(var(--mediumGray), 5%);
227
+ &::before {
228
+ content: '\00a0';
243
229
  }
244
230
  }
231
+ }
245
232
 
246
- button.btn svg {
247
- margin: 0px 0 3px 0;
248
- }
233
+ .data-table-pagination {
234
+ margin: 1rem 0;
235
+ display: flex;
236
+ align-items: center;
237
+
238
+ ul {
239
+ list-style: none;
240
+ margin: 0 1rem 0 0;
241
+ display: flex;
242
+
243
+ li+li {
244
+ margin-left: 0.3rem;
245
+ }
249
246
 
250
- button[disabled] {
251
- background: var(--mediumGray);
252
- opacity: 0.3;
253
- cursor: default;
247
+ button {
248
+ background: var(--mediumGray);
249
+
250
+ &:hover {
251
+ background: lighten(var(--mediumGray), 5%);
252
+ }
253
+ }
254
254
 
255
- &:hover {
255
+ button.btn svg {
256
+ margin: 0px 0 3px 0;
257
+ }
258
+
259
+ button[disabled] {
256
260
  background: var(--mediumGray);
261
+ opacity: 0.3;
262
+ cursor: default;
263
+
264
+ &:hover {
265
+ background: var(--mediumGray);
266
+ }
257
267
  }
258
268
  }
259
269
  }
260
- }
261
-
262
- .btn-download {
263
- color: #fff;
264
- float: right;
265
- text-decoration: none;
266
- transition: 0.3s all;
267
- margin: 1em 0;
268
270
 
269
- &:hover {
271
+ .btn-download {
272
+ color: #fff;
273
+ float: right;
274
+ text-decoration: none;
270
275
  transition: 0.3s all;
276
+ margin: 1em 0;
277
+
278
+ &:hover {
279
+ transition: 0.3s all;
280
+ }
271
281
  }
272
- }
273
282
 
274
- .cove,
275
- .cdc-open-viz-module {
276
283
  .download-links a:not(:last-child) {
277
284
  margin-right: 10px;
278
285
  display: inline-block;
@@ -4,19 +4,36 @@ import { DataTableProps } from '../DataTable'
4
4
  import { ReactNode } from 'react'
5
5
  import { displayDataAsText } from '@cdc/core/helpers/displayDataAsText'
6
6
  import _ from 'lodash'
7
- import { applyLegendToRow } from '@cdc/map/src/helpers/applyLegendToRow'
8
- import { hashObj } from '@cdc/map/src/helpers'
9
- import { getPatternForRow } from '@cdc/map/src/helpers/getPatternForRow'
7
+ import { hashObj } from '../../../helpers/hashObj'
10
8
 
11
9
  type MapRowsProps = DataTableProps & {
12
10
  rows: string[]
11
+ applyLegendToRow: (
12
+ rowObj: any,
13
+ config: any,
14
+ runtimeLegend: any,
15
+ legendMemo: any,
16
+ legendSpecialClassLastMemo: any
17
+ ) => string[]
18
+ getPatternForRow: (rowObj: any, config: any) => any
13
19
  }
14
20
 
15
- const getGeoLabel = (config, row, formatLegendLocation, displayGeoName) => {
21
+ const getGeoLabel = (config, row, formatLegendLocation, displayGeoName, runtimeData = null) => {
16
22
  const { geoType, type } = config.general
23
+
17
24
  let labelValue
18
25
  if (!['single-state', 'us-county'].includes(geoType) || type === 'us-geocode') {
26
+ // Use the row (UID) for lookup - this allows "US-AL" to become "Alabama"
19
27
  labelValue = displayGeoName(row)
28
+
29
+ // If displayGeoName returned the same value (not found in lookups), use the raw imported data
30
+ if (labelValue === row && runtimeData && config.columns?.geo?.name) {
31
+ const rawGeoValue = runtimeData[row]?.[config.columns.geo.name]
32
+ if (rawGeoValue && rawGeoValue !== row) {
33
+ labelValue = rawGeoValue
34
+ }
35
+ }
36
+
20
37
  labelValue = String(labelValue).startsWith('region') ? _.capitalize(labelValue) : labelValue
21
38
  } else {
22
39
  labelValue = formatLegendLocation(row)
@@ -58,7 +75,7 @@ export const getMapRowData = (
58
75
  ].map(column => {
59
76
  const label = columns[column]?.label || columns[column]?.name || column
60
77
  if (column === 'geo') {
61
- dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
78
+ dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
62
79
  } else if (filterColumns.includes(column)) {
63
80
  dataRow[label] = runtimeData[row][column]
64
81
  } else {
@@ -81,7 +98,9 @@ const mapCellArray = ({
81
98
  setFilteredCountryCode,
82
99
  legendMemo,
83
100
  legendSpecialClassLastMemo,
84
- runtimeLegend
101
+ runtimeLegend,
102
+ applyLegendToRow,
103
+ getPatternForRow
85
104
  }: MapRowsProps): ReactNode[][] => {
86
105
  const { allowMapZoom, geoType, type } = config.general
87
106
  return rows.map(row =>
@@ -100,16 +119,16 @@ const mapCellArray = ({
100
119
  if (!legendColor) {
101
120
  console.error('No legend color found') // eslint-disable-line no-console
102
121
  }
103
- const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
122
+ const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
104
123
  const mapZoomHandler =
105
124
  type === 'bubble' && allowMapZoom && geoType === 'world' ? () => setFilteredCountryCode(row) : undefined
106
125
 
107
126
  const validColor = legendColor && legendColor.length > 0 && !noColor
108
-
127
+
109
128
  // Check for pattern information
110
129
  const patternInfo = getPatternForRow(rowObj, config)
111
130
  const mapId = config.runtime?.uniqueId || 'map'
112
-
131
+
113
132
  return (
114
133
  <div className='col-12'>
115
134
  {validColor ? (
@@ -8,8 +8,8 @@ const states = {
8
8
  CO: 'Colorado',
9
9
  CT: 'Connecticut',
10
10
  DE: 'Delaware',
11
- DC: 'District Of Columbia',
12
- FM: 'Federated States Of Micronesia',
11
+ DC: 'District of Columbia',
12
+ FM: 'Federated States of Micronesia',
13
13
  FL: 'Florida',
14
14
  GA: 'Georgia',
15
15
  GU: 'Guam',
@@ -0,0 +1,54 @@
1
+ import { standardizeStateName } from '../standardizeState'
2
+
3
+ describe('standardizeStateName', () => {
4
+ it('should return non-string values unchanged', () => {
5
+ expect(standardizeStateName(123)).toBe(123)
6
+ expect(standardizeStateName(null)).toBe(null)
7
+ expect(standardizeStateName(undefined)).toBe(undefined)
8
+ expect(standardizeStateName(true)).toBe(true)
9
+ })
10
+
11
+ it('should return numeric strings unchanged', () => {
12
+ expect(standardizeStateName('123')).toBe('123')
13
+ expect(standardizeStateName('456.78')).toBe('456.78')
14
+ })
15
+
16
+ it('should convert state abbreviations to full names', () => {
17
+ expect(standardizeStateName('DC')).toBe('District of Columbia')
18
+ expect(standardizeStateName('dc')).toBe('District of Columbia')
19
+ expect(standardizeStateName('CA')).toBe('California')
20
+ expect(standardizeStateName('ca')).toBe('California')
21
+ expect(standardizeStateName('FM')).toBe('Federated States of Micronesia')
22
+ expect(standardizeStateName('fm')).toBe('Federated States of Micronesia')
23
+ })
24
+
25
+ it('should handle Virgin Islands variations', () => {
26
+ expect(standardizeStateName('VI')).toBe('U.S. VIRGIN ISLANDS')
27
+ expect(standardizeStateName('vi')).toBe('U.S. VIRGIN ISLANDS')
28
+ expect(standardizeStateName('Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
29
+ expect(standardizeStateName('VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
30
+ expect(standardizeStateName('U.S. Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
31
+ expect(standardizeStateName('US VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
32
+ })
33
+
34
+ it('should verify "of" is lowercase in state names', () => {
35
+ const dcName = standardizeStateName('DC')
36
+ expect(dcName).toContain('of')
37
+ expect(dcName).not.toContain('Of')
38
+
39
+ const fmName = standardizeStateName('FM')
40
+ expect(fmName).toContain('of')
41
+ expect(fmName).not.toContain('Of')
42
+ })
43
+
44
+ it('should return original value for unknown state codes', () => {
45
+ expect(standardizeStateName('ZZ')).toBe('ZZ')
46
+ expect(standardizeStateName('Unknown State')).toBe('Unknown State')
47
+ })
48
+
49
+ it('should handle mixed case state names', () => {
50
+ expect(standardizeStateName('California')).toBe('California')
51
+ expect(standardizeStateName('CALIFORNIA')).toBe('CALIFORNIA')
52
+ expect(standardizeStateName('cAlIfOrNiA')).toBe('cAlIfOrNiA')
53
+ })
54
+ })