@cdc/core 4.25.7 → 4.25.10

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 (128) hide show
  1. package/components/AdvancedEditor/AdvancedEditor.tsx +29 -8
  2. package/components/DataTable/DataTable.tsx +63 -11
  3. package/components/DataTable/DataTableStandAlone.tsx +4 -1
  4. package/components/DataTable/components/ChartHeader.tsx +58 -9
  5. package/components/DataTable/components/ExpandCollapse.tsx +21 -1
  6. package/components/DataTable/components/MapHeader.tsx +35 -7
  7. package/components/DataTable/data-table.css +6 -0
  8. package/components/DataTable/helpers/chartCellMatrix.tsx +11 -8
  9. package/components/DataTable/helpers/mapCellMatrix.tsx +19 -1
  10. package/components/DownloadButton.tsx +42 -13
  11. package/components/EditorPanel/DataTableEditor.tsx +10 -1
  12. package/components/EditorPanel/components/MarkupHighlightedTextField.tsx +227 -0
  13. package/components/EditorPanel/components/MarkupVariablesEditor.tsx +411 -0
  14. package/components/EditorPanel/components/PanelMarkup.tsx +59 -0
  15. package/components/ErrorBoundary.jsx +3 -1
  16. package/components/Filters/Filters.tsx +35 -11
  17. package/components/Filters/components/Tabs.tsx +1 -0
  18. package/components/Footnotes/FootnotesStandAlone.tsx +2 -1
  19. package/components/Legend/Legend.Gradient.tsx +3 -6
  20. package/components/LegendShape.tsx +121 -3
  21. package/components/{MediaControls.jsx → MediaControls.tsx} +80 -16
  22. package/components/PaletteConversionModal.tsx +87 -0
  23. package/components/PaletteSelector/DeveloperPaletteRollback.tsx +114 -0
  24. package/components/PaletteSelector/PaletteSelector.css +51 -0
  25. package/components/PaletteSelector/PaletteSelector.tsx +112 -0
  26. package/components/PaletteSelector/index.ts +2 -0
  27. package/components/RichTooltip/RichTooltip.tsx +1 -0
  28. package/components/Table/Table.tsx +3 -1
  29. package/components/_stories/BlurStrokeTest.stories.tsx +1 -1
  30. package/components/_stories/DataTable.stories.tsx +1 -1
  31. package/components/_stories/Filters.stories.tsx +1 -1
  32. package/components/_stories/Footnotes.stories.tsx +1 -1
  33. package/components/_stories/Inputs.stories.tsx +1 -1
  34. package/components/_stories/MultiSelect.stories.tsx +3 -3
  35. package/components/_stories/NestedDropdown.stories.tsx +1 -1
  36. package/components/_stories/Table.stories.tsx +1 -1
  37. package/components/elements/_stories/Button.stories.tsx +1 -1
  38. package/components/elements/_stories/Card.stories.tsx +1 -1
  39. package/components/inputs/InputToggle.tsx +2 -0
  40. package/components/managers/DataDesigner.tsx +10 -9
  41. package/components/managers/_stories/DataDesigner.stories.tsx +1 -1
  42. package/components/ui/Tooltip.tsx +2 -1
  43. package/components/ui/_stories/Accordion.stories.tsx +1 -1
  44. package/components/ui/_stories/ColorPaletteMigration.stories.mdx +275 -0
  45. package/components/ui/_stories/Colors.stories.tsx +330 -0
  46. package/components/ui/_stories/IconGallery.stories.tsx +316 -0
  47. package/components/ui/_stories/Title.stories.tsx +1 -1
  48. package/contexts/EditorContext.ts +18 -0
  49. package/contexts/editor.actions.ts +28 -0
  50. package/contexts/editor.reducer.ts +94 -0
  51. package/data/chartColorPalettes.ts +118 -0
  52. package/data/colorPalettes.ts +9 -0
  53. package/data/mapColorPalettes.ts +45 -0
  54. package/data/sharedPalettes.ts +50 -0
  55. package/dist/cove-main.css +14 -13
  56. package/dist/cove-main.css.map +1 -1
  57. package/generateViteConfig.js +80 -0
  58. package/helpers/addValuesToFilters.ts +2 -3
  59. package/helpers/cloneConfig.ts +31 -0
  60. package/helpers/configDataHelpers.ts +128 -0
  61. package/helpers/configHelpers.ts +27 -0
  62. package/helpers/constants.ts +5 -2
  63. package/helpers/cove/number.ts +6 -2
  64. package/helpers/coveUpdateWorker.ts +15 -3
  65. package/helpers/events.ts +32 -0
  66. package/helpers/filterColorPalettes.ts +152 -0
  67. package/helpers/generateColorsArray.ts +13 -0
  68. package/helpers/getColorPaletteVersion.ts +33 -0
  69. package/helpers/getPaletteAccessor.ts +18 -0
  70. package/helpers/markupProcessor.ts +205 -0
  71. package/helpers/metrics/helpers.ts +75 -0
  72. package/helpers/metrics/types.ts +82 -0
  73. package/helpers/metrics/utils.ts +34 -0
  74. package/helpers/palettes/colorDistributions.ts +56 -0
  75. package/helpers/palettes/migratePaletteName.ts +150 -0
  76. package/helpers/palettes/standardizePaletteNames.ts +77 -0
  77. package/helpers/palettes/utils.ts +267 -0
  78. package/helpers/queryStringUtils.ts +13 -0
  79. package/helpers/testing.ts +345 -0
  80. package/helpers/tests/addValuesToFilters.test.ts +1 -2
  81. package/helpers/tests/generateColorsArray.test.ts +24 -0
  82. package/helpers/tests/markupProcessor.test.ts +538 -0
  83. package/helpers/tests/testStandaloneBuild.ts +44 -0
  84. package/helpers/useMarkupVariables.ts +31 -0
  85. package/helpers/vegaConfig.ts +0 -1
  86. package/helpers/ver/4.24.10.ts +2 -1
  87. package/helpers/ver/4.24.11.ts +2 -1
  88. package/helpers/ver/4.24.3.ts +2 -1
  89. package/helpers/ver/4.24.4.ts +2 -1
  90. package/helpers/ver/4.24.5.ts +2 -1
  91. package/helpers/ver/4.24.7.ts +2 -1
  92. package/helpers/ver/4.24.9.ts +2 -1
  93. package/helpers/ver/4.25.1.ts +2 -1
  94. package/helpers/ver/4.25.10.ts +36 -0
  95. package/helpers/ver/4.25.3.ts +2 -1
  96. package/helpers/ver/4.25.4.ts +2 -1
  97. package/helpers/ver/4.25.6.ts +2 -1
  98. package/helpers/ver/4.25.7.ts +2 -1
  99. package/helpers/ver/4.25.8.ts +62 -0
  100. package/helpers/ver/4.25.9.ts +293 -0
  101. package/helpers/ver/tests/4.25.10.test.ts +204 -0
  102. package/helpers/ver/tests/4.25.8.test.ts +86 -0
  103. package/helpers/ver/tests/4.25.9.test.ts +51 -0
  104. package/helpers/viewports.ts +2 -0
  105. package/hooks/useColorPalette.ts +79 -0
  106. package/package.json +12 -4
  107. package/styles/_button-section.scss +0 -2
  108. package/styles/_global.scss +7 -5
  109. package/styles/base.scss +8 -5
  110. package/styles/v2/components/button.scss +4 -3
  111. package/styles/v2/components/editor.scss +2 -1
  112. package/styles/v2/layout/_data-table.scss +3 -2
  113. package/styles/v2/themes/_color-definitions.scss +18 -17
  114. package/testBuild.js +0 -0
  115. package/testing-setup.js +32 -0
  116. package/types/ForecastingSeriesKey.ts +0 -1
  117. package/types/MarkupInclude.ts +6 -1
  118. package/types/MarkupVariable.ts +19 -0
  119. package/types/Series.ts +4 -0
  120. package/types/Table.ts +1 -0
  121. package/types/VizFilter.ts +1 -0
  122. package/vitest.config.ts +16 -0
  123. package/components/ui/_stories/Colors.stories.mdx +0 -220
  124. package/components/ui/_stories/IconGallery.stories.mdx +0 -14
  125. package/data/colorPalettes.js +0 -171
  126. package/helpers/events.js +0 -14
  127. package/helpers/formatConfigBeforeSave.ts +0 -135
  128. package/helpers/tests/formatConfigBeforeSave.test.ts +0 -68
@@ -0,0 +1,316 @@
1
+ import type { Meta } from '@storybook/react'
2
+ import React from 'react'
3
+
4
+ // Import all icons
5
+ import AreaChartIcon from '../../../assets/icon-area-chart.svg'
6
+ import CaretDownIcon from '../../../assets/icon-caret-down.svg'
7
+ import CaretFilledDownIcon from '../../../assets/icon-caret-filled-down.svg'
8
+ import CaretFilledUpIcon from '../../../assets/icon-caret-filled-up.svg'
9
+ import CaretUpIcon from '../../../assets/icon-caret-up.svg'
10
+ import BarPairedIcon from '../../../assets/icon-chart-bar-paired.svg'
11
+ import BarStackedIcon from '../../../assets/icon-chart-bar-stacked.svg'
12
+ import BarChartIcon from '../../../assets/icon-chart-bar.svg'
13
+ import BoxWhiskerIcon from '../../../assets/icon-chart-box-whisker.svg'
14
+ import ForecastIcon from '../../../assets/icon-chart-forecast.svg'
15
+ import ForestPlotIcon from '../../../assets/icon-chart-forest-plot.svg'
16
+ import LineChartIcon from '../../../assets/icon-chart-line.svg'
17
+ import PieChartIcon from '../../../assets/icon-chart-pie.svg'
18
+ import ScatterplotIcon from '../../../assets/icon-chart-scatterplot.svg'
19
+ import StackedAreaIcon from '../../../assets/icon-chart-stacked-area.svg'
20
+ import CheckIcon from '../../../assets/icon-check.svg'
21
+ import CloseIcon from '../../../assets/icon-close.svg'
22
+ import CodeIcon from '../../../assets/icon-code.svg'
23
+ import ComboChartIcon from '../../../assets/icon-combo-chart.svg'
24
+ import CommandIcon from '../../../assets/icon-command.svg'
25
+ import DashboardIcon from '../../../assets/icon-dashboard.svg'
26
+ import DataBiteIcon from '../../../assets/icon-databite.svg'
27
+ import DeviationBarIcon from '../../../assets/icon-deviation-bar.svg'
28
+ import EditIcon from '../../../assets/icon-edit.svg'
29
+ import EpiChartIcon from '../../../assets/icon-epi-chart.svg'
30
+ import FileUploadIcon from '../../../assets/icon-file-upload.svg'
31
+ import FilterBarsIcon from '../../../assets/icon-filter-bars.svg'
32
+ import FilterDropdownsIcon from '../../../assets/icon-filter-dropdowns.svg'
33
+ import FilteredTextIcon from '../../../assets/icon-filtered-text.svg'
34
+ import GearIcon from '../../../assets/icon-gear.svg'
35
+ import GearMultiIcon from '../../../assets/icon-gear-multi.svg'
36
+ import GridIcon from '../../../assets/icon-grid.svg'
37
+ import InfoIcon from '../../../assets/icon-info.svg'
38
+ import LinearGaugeIcon from '../../../assets/icon-linear-gauge.svg'
39
+ import LinkIcon from '../../../assets/icon-link.svg'
40
+ import MapAlabamaIcon from '../../../assets/icon-map-alabama.svg'
41
+ import MapUSAIcon from '../../../assets/icon-map-usa.svg'
42
+ import MapWorldIcon from '../../../assets/icon-map-world.svg'
43
+ import MinusIcon from '../../../assets/icon-minus.svg'
44
+ import MoveIcon from '../../../assets/icon-move.svg'
45
+ import PlusIcon from '../../../assets/icon-plus.svg'
46
+ import QuestionCircleIcon from '../../../assets/icon-question-circle.svg'
47
+ import RotateLeftIcon from '../../../assets/icon-rotate-left.svg'
48
+ import SankeyIcon from '../../../assets/icon-sankey.svg'
49
+ import TableIcon from '../../../assets/icon-table.svg'
50
+ import ToolsIcon from '../../../assets/icon-tools.svg'
51
+ import UploadIcon from '../../../assets/icon-upload.svg'
52
+ import WarningCircleIcon from '../../../assets/icon-warning-circle.svg'
53
+ import WarningTriangleIcon from '../../../assets/icon-warning-triangle.svg'
54
+ import ExternalLinkIcon from '../../../assets/external-link.svg'
55
+ import MapFoldedIcon from '../../../assets/map-folded.svg'
56
+ import USARegionGraphicIcon from '../../../assets/usa-region-graphic.svg'
57
+
58
+ const iconList = [
59
+ { name: 'Area Chart', component: AreaChartIcon, category: 'Charts' },
60
+ { name: 'Bar Chart', component: BarChartIcon, category: 'Charts' },
61
+ { name: 'Bar Chart Paired', component: BarPairedIcon, category: 'Charts' },
62
+ { name: 'Bar Chart Stacked', component: BarStackedIcon, category: 'Charts' },
63
+ { name: 'Box & Whisker', component: BoxWhiskerIcon, category: 'Charts' },
64
+ { name: 'Combo Chart', component: ComboChartIcon, category: 'Charts' },
65
+ { name: 'Deviation Bar', component: DeviationBarIcon, category: 'Charts' },
66
+ { name: 'Epi Chart', component: EpiChartIcon, category: 'Charts' },
67
+ { name: 'Forecast', component: ForecastIcon, category: 'Charts' },
68
+ { name: 'Forest Plot', component: ForestPlotIcon, category: 'Charts' },
69
+ { name: 'Line Chart', component: LineChartIcon, category: 'Charts' },
70
+ { name: 'Linear Gauge', component: LinearGaugeIcon, category: 'Charts' },
71
+ { name: 'Pie Chart', component: PieChartIcon, category: 'Charts' },
72
+ { name: 'Sankey', component: SankeyIcon, category: 'Charts' },
73
+ { name: 'Scatterplot', component: ScatterplotIcon, category: 'Charts' },
74
+ { name: 'Stacked Area', component: StackedAreaIcon, category: 'Charts' },
75
+
76
+ { name: 'Map Alabama', component: MapAlabamaIcon, category: 'Maps' },
77
+ { name: 'Map USA', component: MapUSAIcon, category: 'Maps' },
78
+ { name: 'Map World', component: MapWorldIcon, category: 'Maps' },
79
+ { name: 'Map Folded', component: MapFoldedIcon, category: 'Maps' },
80
+ { name: 'USA Region Graphic', component: USARegionGraphicIcon, category: 'Maps' },
81
+
82
+ { name: 'Dashboard', component: DashboardIcon, category: 'Components' },
83
+ { name: 'Data Bite', component: DataBiteIcon, category: 'Components' },
84
+ { name: 'Filtered Text', component: FilteredTextIcon, category: 'Components' },
85
+ { name: 'Table', component: TableIcon, category: 'Components' },
86
+
87
+ { name: 'Filter Bars', component: FilterBarsIcon, category: 'Filters' },
88
+ { name: 'Filter Dropdowns', component: FilterDropdownsIcon, category: 'Filters' },
89
+
90
+ { name: 'Caret Down', component: CaretDownIcon, category: 'Navigation' },
91
+ { name: 'Caret Filled Down', component: CaretFilledDownIcon, category: 'Navigation' },
92
+ { name: 'Caret Filled Up', component: CaretFilledUpIcon, category: 'Navigation' },
93
+ { name: 'Caret Up', component: CaretUpIcon, category: 'Navigation' },
94
+
95
+ { name: 'Check', component: CheckIcon, category: 'Actions' },
96
+ { name: 'Close', component: CloseIcon, category: 'Actions' },
97
+ { name: 'Edit', component: EditIcon, category: 'Actions' },
98
+ { name: 'File Upload', component: FileUploadIcon, category: 'Actions' },
99
+ { name: 'Minus', component: MinusIcon, category: 'Actions' },
100
+ { name: 'Move', component: MoveIcon, category: 'Actions' },
101
+ { name: 'Plus', component: PlusIcon, category: 'Actions' },
102
+ { name: 'Rotate Left', component: RotateLeftIcon, category: 'Actions' },
103
+ { name: 'Upload', component: UploadIcon, category: 'Actions' },
104
+
105
+ { name: 'Code', component: CodeIcon, category: 'Interface' },
106
+ { name: 'Command', component: CommandIcon, category: 'Interface' },
107
+ { name: 'External Link', component: ExternalLinkIcon, category: 'Interface' },
108
+ { name: 'Gear', component: GearIcon, category: 'Interface' },
109
+ { name: 'Gear Multi', component: GearMultiIcon, category: 'Interface' },
110
+ { name: 'Grid', component: GridIcon, category: 'Interface' },
111
+ { name: 'Info', component: InfoIcon, category: 'Interface' },
112
+ { name: 'Link', component: LinkIcon, category: 'Interface' },
113
+ { name: 'Question Circle', component: QuestionCircleIcon, category: 'Interface' },
114
+ { name: 'Tools', component: ToolsIcon, category: 'Interface' },
115
+ { name: 'Warning Circle', component: WarningCircleIcon, category: 'Interface' },
116
+ { name: 'Warning Triangle', component: WarningTriangleIcon, category: 'Interface' },
117
+ ]
118
+
119
+ const categories = [...new Set(iconList.map(icon => icon.category))]
120
+
121
+ const meta: Meta = {
122
+ title: 'Components/Atoms/Icon Gallery',
123
+ parameters: {
124
+ docs: {
125
+ page: () => (
126
+ <div style={{ padding: '20px' }}>
127
+ <h1>Icon Gallery</h1>
128
+ <p>This gallery showcases all available icons in the CDC Open Viz system, organized by category.</p>
129
+
130
+ {categories.map(category => (
131
+ <div key={category} style={{ marginBottom: '40px' }}>
132
+ <h2>{category}</h2>
133
+ <div style={{
134
+ display: 'grid',
135
+ gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
136
+ gap: '20px',
137
+ marginBottom: '20px'
138
+ }}>
139
+ {iconList
140
+ .filter(icon => icon.category === category)
141
+ .map(icon => (
142
+ <div
143
+ key={icon.name}
144
+ style={{
145
+ display: 'flex',
146
+ flexDirection: 'column',
147
+ alignItems: 'center',
148
+ padding: '15px',
149
+ border: '1px solid #e0e0e0',
150
+ borderRadius: '8px',
151
+ backgroundColor: '#fafafa'
152
+ }}
153
+ >
154
+ <icon.component
155
+ width="48"
156
+ height="48"
157
+ style={{ marginBottom: '10px' }}
158
+ />
159
+ <span style={{
160
+ fontSize: '12px',
161
+ fontWeight: 'bold',
162
+ textAlign: 'center',
163
+ color: '#333'
164
+ }}>
165
+ {icon.name}
166
+ </span>
167
+ <code style={{
168
+ fontSize: '10px',
169
+ color: '#666',
170
+ marginTop: '5px',
171
+ textAlign: 'center',
172
+ wordBreak: 'break-all'
173
+ }}>
174
+ {icon.component.toString().includes('icon-')
175
+ ? icon.component.toString().match(/icon-[^.]+/)?.[0] || 'icon'
176
+ : icon.component.toString().match(/[^/]+(?=\.svg)/)?.[0] || 'icon'
177
+ }.svg
178
+ </code>
179
+ </div>
180
+ ))}
181
+ </div>
182
+ </div>
183
+ ))}
184
+
185
+ <h2>Usage</h2>
186
+ <p>Import and use icons as React components:</p>
187
+ <pre><code>{`import WarningIcon from '@cdc/core/assets/icon-warning-circle.svg'
188
+
189
+ // Basic usage
190
+ <WarningIcon width="24" height="24" />
191
+
192
+ // With styling
193
+ <WarningIcon
194
+ width="32"
195
+ height="32"
196
+ className="warning-icon"
197
+ style={{ color: '#ff6b6b' }}
198
+ />`}</code></pre>
199
+
200
+ <h2>Guidelines</h2>
201
+ <ul>
202
+ <li><strong>Consistent Sizing</strong>: Use standard sizes (16px, 24px, 32px, 48px) for consistency</li>
203
+ <li><strong>Accessibility</strong>: Always provide meaningful alt text or aria-labels when needed</li>
204
+ <li><strong>Color</strong>: Icons inherit the current text color by default, can be overridden with CSS</li>
205
+ <li><strong>Context</strong>: Choose icons that clearly represent their function or content</li>
206
+ <li><strong>Performance</strong>: SVG icons are optimized for fast loading and scalability</li>
207
+ </ul>
208
+
209
+ <h2>File Location</h2>
210
+ <p>All icons are located in <code>packages/core/assets/</code> and follow the naming convention:</p>
211
+ <ul>
212
+ <li><code>icon-[name].svg</code> for interface and action icons</li>
213
+ <li><code>[descriptive-name].svg</code> for specialized graphics</li>
214
+ </ul>
215
+ </div>
216
+ )
217
+ }
218
+ }
219
+ }
220
+
221
+ export default meta
222
+
223
+ export const Gallery = {
224
+ render: () => (
225
+ <div style={{ padding: '20px' }}>
226
+ <h1>Icon Gallery</h1>
227
+ <p>This gallery showcases all available icons in the CDC Open Viz system, organized by category.</p>
228
+
229
+ {categories.map(category => (
230
+ <div key={category} style={{ marginBottom: '40px' }}>
231
+ <h2>{category}</h2>
232
+ <div style={{
233
+ display: 'grid',
234
+ gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
235
+ gap: '20px',
236
+ marginBottom: '20px'
237
+ }}>
238
+ {iconList
239
+ .filter(icon => icon.category === category)
240
+ .map(icon => (
241
+ <div
242
+ key={icon.name}
243
+ style={{
244
+ display: 'flex',
245
+ flexDirection: 'column',
246
+ alignItems: 'center',
247
+ padding: '15px',
248
+ border: '1px solid #e0e0e0',
249
+ borderRadius: '8px',
250
+ backgroundColor: '#fafafa'
251
+ }}
252
+ >
253
+ <icon.component
254
+ width="48"
255
+ height="48"
256
+ style={{ marginBottom: '10px' }}
257
+ />
258
+ <span style={{
259
+ fontSize: '12px',
260
+ fontWeight: 'bold',
261
+ textAlign: 'center',
262
+ color: '#333'
263
+ }}>
264
+ {icon.name}
265
+ </span>
266
+ <code style={{
267
+ fontSize: '10px',
268
+ color: '#666',
269
+ marginTop: '5px',
270
+ textAlign: 'center',
271
+ wordBreak: 'break-all'
272
+ }}>
273
+ {icon.component.toString().includes('icon-')
274
+ ? icon.component.toString().match(/icon-[^.]+/)?.[0] || 'icon'
275
+ : icon.component.toString().match(/[^/]+(?=\.svg)/)?.[0] || 'icon'
276
+ }.svg
277
+ </code>
278
+ </div>
279
+ ))}
280
+ </div>
281
+ </div>
282
+ ))}
283
+
284
+ <h2>Usage</h2>
285
+ <p>Import and use icons as React components:</p>
286
+ <pre><code>{`import WarningIcon from '@cdc/core/assets/icon-warning-circle.svg'
287
+
288
+ // Basic usage
289
+ <WarningIcon width="24" height="24" />
290
+
291
+ // With styling
292
+ <WarningIcon
293
+ width="32"
294
+ height="32"
295
+ className="warning-icon"
296
+ style={{ color: '#ff6b6b' }}
297
+ />`}</code></pre>
298
+
299
+ <h2>Guidelines</h2>
300
+ <ul>
301
+ <li><strong>Consistent Sizing</strong>: Use standard sizes (16px, 24px, 32px, 48px) for consistency</li>
302
+ <li><strong>Accessibility</strong>: Always provide meaningful alt text or aria-labels when needed</li>
303
+ <li><strong>Color</strong>: Icons inherit the current text color by default, can be overridden with CSS</li>
304
+ <li><strong>Context</strong>: Choose icons that clearly represent their function or content</li>
305
+ <li><strong>Performance</strong>: SVG icons are optimized for fast loading and scalability</li>
306
+ </ul>
307
+
308
+ <h2>File Location</h2>
309
+ <p>All icons are located in <code>packages/core/assets/</code> and follow the naming convention:</p>
310
+ <ul>
311
+ <li><code>icon-[name].svg</code> for interface and action icons</li>
312
+ <li><code>[descriptive-name].svg</code> for specialized graphics</li>
313
+ </ul>
314
+ </div>
315
+ )
316
+ }
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react'
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
2
  import Title from '../Title'
3
3
 
4
4
  const meta: Meta = {
@@ -0,0 +1,18 @@
1
+ import { WCMSProps } from '@cdc/core/types/WCMSProps'
2
+ import { Dispatch, createContext } from 'react'
3
+ import EditorActions from './editor.actions'
4
+ import { EditorState } from '@cdc/core/contexts/editor.reducer'
5
+
6
+ export type EditorCTX = WCMSProps &
7
+ EditorState & {
8
+ displayName?: string
9
+ setTempConfig: Function
10
+ }
11
+
12
+ const ConfigContext = createContext<EditorCTX>({
13
+ displayName: 'ConfigContext',
14
+ setTempConfig: () => {}
15
+ } as unknown as EditorCTX)
16
+
17
+ export default ConfigContext
18
+ export const EditorDispatchContext = createContext<Dispatch<EditorActions>>(() => {})
@@ -0,0 +1,28 @@
1
+ import { type Action } from '@cdc/core/types/Action'
2
+ import { type ViewPort } from '@cdc/core/types/ViewPort'
3
+ import { type Visualization } from '@cdc/core/types/Visualization'
4
+ import { type DataSet } from '@cdc/core/types/DataSet'
5
+
6
+ type EDITOR_SAVE = Action<'EDITOR_SAVE', Visualization>
7
+ type EDITOR_SET_CONFIG = Action<'EDITOR_SET_CONFIG', Visualization>
8
+ type EDITOR_TEMP_SAVE = Action<'EDITOR_TEMP_SAVE', Visualization>
9
+ type EDITOR_SET_ERRORS = Action<'EDITOR_SET_ERRORS', string[]>
10
+ type EDITOR_SET_VIEWPORT = Action<'EDITOR_SET_VIEWPORT', ViewPort>
11
+ type EDITOR_SET_GLOBALACTIVE = Action<'EDITOR_SET_GLOBALACTIVE', number>
12
+ type SET_DASHBOARD_DATASET = Action<
13
+ 'SET_DASHBOARD_DATASET',
14
+ { datasetKey: string; oldDatasetKey?: string; dataset: DataSet }
15
+ >
16
+ type DELETE_DATASET = Action<'DELETE_DASHBOARD_DATASET', { datasetKey: string }>
17
+
18
+ type actions =
19
+ | EDITOR_SAVE
20
+ | EDITOR_TEMP_SAVE
21
+ | EDITOR_SET_ERRORS
22
+ | EDITOR_SET_VIEWPORT
23
+ | EDITOR_SET_GLOBALACTIVE
24
+ | EDITOR_SET_CONFIG
25
+ | DELETE_DATASET
26
+ | SET_DASHBOARD_DATASET
27
+
28
+ export default actions
@@ -0,0 +1,94 @@
1
+ import _ from 'lodash'
2
+ import EditorActions from './editor.actions'
3
+ import { Visualization } from '@cdc/core/types/Visualization'
4
+ import { devToolsWrapper } from '@cdc/core/helpers/withDevTools'
5
+ import { cloneConfig } from '@cdc/core/helpers/cloneConfig'
6
+
7
+ export type EditorState = {
8
+ config?: Visualization
9
+ tempConfig?: Visualization | null
10
+ errors: string[]
11
+ currentViewport: string
12
+ globalActive: number
13
+ newViz?: boolean
14
+ }
15
+ const reducer = (state: EditorState, action: EditorActions): EditorState => {
16
+ switch (action.type) {
17
+ case 'EDITOR_SAVE': {
18
+ return { ...state, config: action.payload, tempConfig: null }
19
+ }
20
+ case 'EDITOR_SET_CONFIG': {
21
+ return { ...state, config: action.payload }
22
+ }
23
+ case 'SET_DASHBOARD_DATASET': {
24
+ const { dataset, datasetKey, oldDatasetKey } = action.payload
25
+ const oldDataset = oldDatasetKey ? state.config?.datasets[oldDatasetKey] : {}
26
+ const config = cloneConfig(state.config)
27
+ if (oldDatasetKey) {
28
+ const changeDatasets = _config => {
29
+ _config.rows?.forEach(row => {
30
+ if (row.dataKey === oldDatasetKey) {
31
+ row.dataKey = datasetKey
32
+ }
33
+ })
34
+ Object.values(_config.visualizations || {}).forEach((viz: any) => {
35
+ if (viz.dataKey === oldDatasetKey) {
36
+ viz.dataKey = datasetKey
37
+ }
38
+ })
39
+ }
40
+ applyMultiDashboards(config, changeDatasets)
41
+ delete config.datasets[oldDatasetKey]
42
+ }
43
+ Object.values(config.datasets).forEach(dataset => {
44
+ dataset.preview = false
45
+ })
46
+ config.datasets[datasetKey] = { ...oldDataset, ...dataset }
47
+ return { ...state, config }
48
+ }
49
+ case 'DELETE_DASHBOARD_DATASET': {
50
+ const { datasetKey } = action.payload
51
+ const deleteDatasetKeys = _config => {
52
+ _config.rows?.forEach(row => {
53
+ if (row.dataKey === datasetKey) {
54
+ delete row.dataKey
55
+ }
56
+ })
57
+ Object.values(_config.visualizations || {}).forEach((viz: any) => {
58
+ if (viz.dataKey === datasetKey) {
59
+ delete viz.dataKey
60
+ }
61
+ })
62
+ }
63
+ const config = cloneConfig(state.config)
64
+ applyMultiDashboards(config, deleteDatasetKeys)
65
+ delete config.datasets[datasetKey]
66
+ return { ...state, config }
67
+ }
68
+ case 'EDITOR_TEMP_SAVE': {
69
+ return { ...state, tempConfig: action.payload }
70
+ }
71
+ case 'EDITOR_SET_ERRORS': {
72
+ return { ...state, errors: action.payload }
73
+ }
74
+ case 'EDITOR_SET_VIEWPORT': {
75
+ return { ...state, currentViewport: action.payload }
76
+ }
77
+ case 'EDITOR_SET_GLOBALACTIVE': {
78
+ return { ...state, globalActive: action.payload }
79
+ }
80
+ default:
81
+ return state
82
+ }
83
+ }
84
+
85
+ const applyMultiDashboards = (config: Record<string, any>, mutationFunc: Function) => {
86
+ if (config.multiDashboards) {
87
+ config.multiDashboards.forEach(dashboard => {
88
+ mutationFunc(dashboard)
89
+ })
90
+ }
91
+ mutationFunc(config)
92
+ }
93
+
94
+ export default devToolsWrapper<EditorState, EditorActions>(reducer)
@@ -0,0 +1,118 @@
1
+ import { updatePaletteNames } from '../helpers/updatePaletteNames'
2
+ import { sharedPalettes } from './sharedPalettes'
3
+
4
+ // Chart-specific color palettes with versioned structure
5
+
6
+ const chartColorPalettesData = {
7
+ v1: {
8
+ 'qualitative_bold': [
9
+ '#377eb8',
10
+ '#ff7f00',
11
+ '#4daf4a',
12
+ '#984ea3',
13
+ '#e41a1c',
14
+ '#ffff33',
15
+ '#a65628',
16
+ '#f781bf',
17
+ '#3399CC'
18
+ ],
19
+
20
+ 'qualitative_soft': [
21
+ '#a6cee3',
22
+ '#1f78b4',
23
+ '#b2df8a',
24
+ '#33a02c',
25
+ '#fb9a99',
26
+ '#e31a1c',
27
+ '#fdbf6f',
28
+ '#ff7f00',
29
+ '#aca9eb'
30
+ ],
31
+ qualitative1: sharedPalettes.qualitative1,
32
+
33
+ qualitative2: sharedPalettes.qualitative2,
34
+
35
+ qualitative3: sharedPalettes.qualitative3,
36
+
37
+ qualitative4: sharedPalettes.qualitative4,
38
+
39
+ 'sequential_blue': ['#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
40
+ 'sequential_blue_extended': ['#d5f6f9', '#99e2ed', '#5fb6d1', '#3189b0', '#116091', '#0a3e72'],
41
+ 'sequential_orange_extended': ['#ffefcf', '#ffd49c', '#f7a866', '#eb7723', '#b95117', '#862b0b'],
42
+ 'sequential_green': ['#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'],
43
+
44
+ colorblindsafe: sharedPalettes.colorblindsafe
45
+ },
46
+ v2: {
47
+ // New standardized v2 palettes per migration guide (underscore naming convention)
48
+ 'sequential_orange': ['#FFE4D5', '#FED0B6', '#F7B99A', '#ED9E7C', '#E58061', '#DB6B49', '#C95936', '#A8462C', '#702B1D'],
49
+ 'sequential_purple': ['#E2D3DF', '#CDB2C8', '#B78FAF', '#A6739B', '#935586', '#823A73', '#722161', '#5F2359', '#47264F'],
50
+ 'sequential_blue': ['#DBE8F7', '#BED5ED', '#99BCE1', '#73A1D5', '#4E88C7', '#1E6BC0', '#0057B7', '#01418D', '#032659'],
51
+ 'sequential_green': ['#D5F9F6', '#AEECE7', '#85DED7', '#63D2CA', '#3BBCAF', '#14A594', '#0A937F', '#0F7A68', '#105B4D'],
52
+ 'qualitative_standard': ['#0057B7', '#722161', '#00B1CE', '#D94E5F', '#5A8E3F', '#FFB24D', '#FB7E38', '#032659', '#975722'],
53
+
54
+ // New v2-only palettes (no migration needed)
55
+ 'sequential_teal': ['#e5fafc', '#b3e3ed', '#80cddf', '#4db8d1', '#00b1ce', '#03a2bd', '#0690a6', '#0d6e81', '#125261'],
56
+ 'divergent_blue_cyan': ['#032659', '#014697', '#1D6ABF', '#6197D2', '#C1D2DB', '#5CCBDE', '#01ACC9', '#097F95', '#125261'],
57
+ 'divergent_blue_purple': ['#032659', '#014697', '#1D6ABF', '#6197D2', '#C4CDE1', '#AF8CAA', '#935586', '#7C256B', '#47264F'],
58
+ 'divergent_green_orange': ['#105B4D', '#16806E', '#3EA394', '#5EBFB3', '#FABF61', '#EE956C', '#E27447', '#AC4726', '#702B1D'],
59
+ 'divergent_blue_orange': ['#032659', '#0057B7', '#0092C6', '#55B1A3', '#FFB24D', '#EA803B', '#DD622F', '#AF3423', '#660F14']
60
+ }
61
+ }
62
+
63
+ export const twoColorPaletteData = {
64
+ v1: {
65
+ 'monochrome-1': ['#a6cee3', '#15017a'],
66
+ 'monochrome-2': ['#c2c0fc', '#15017a'],
67
+ 'monochrome-3': ['#cab2d6', '#6a3d9a'],
68
+ 'monochrome-4': ['#c2c0fc', '#6a3d9a'],
69
+ 'monochrome-5': ['#fedab8', '#bf5b17'],
70
+ 'cool-1': ['#b2df8a', '#1f78b4'],
71
+ 'cool-2': ['#a6cee3', '#72d66b'],
72
+ 'cool-3': ['#c2c0fc', '#386cb0'],
73
+ 'cool-4': ['#72d66b', '#6a3d9a'],
74
+ 'cool-5': ['#a6cee3', '#6a3d9a'],
75
+ 'warm-1': ['#e31a1c', '#fedab8'],
76
+ 'complementary-1': ['#1f78b4', '#e6ab02'],
77
+ 'complementary-2': ['#1f78b4', '#ff7f00'],
78
+ 'complementary-3': ['#6a3d9a', '#ff7f00'],
79
+ 'complementary-4': ['#6a3d9a', '#e6ab02'],
80
+ 'complementary-5': ['#df168c', '#1eb386']
81
+ },
82
+ v2: {
83
+ // All palettes using indexes [2,6] from their respective divergent palettes
84
+ 'divergent_blue_purple': ['#1D6ABF', '#935586'],
85
+
86
+ 'divergent_green_orange': ['#3EA394', '#E27447'],
87
+
88
+ 'divergent_blue_cyan': ['#1D6ABF', '#01ACC9'],
89
+
90
+ 'divergent_blue_orange': ['#0092C6', '#DD622F']
91
+ }
92
+ }
93
+
94
+ // Forecasting Palettes should be refactored to use versioned palettes
95
+ const sequentialColors = {
96
+ 'Sequential Blue': ['#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
97
+ 'Sequential Blue Two': ['#d5f6f9', '#99e2ed', '#5fb6d1', '#3189b0', '#116091', '#0a3e72'],
98
+ 'Sequential Blue Three': sharedPalettes.sequentialBlueNine,
99
+ 'Sequential Orange': ['#ffefcf', '#ffd49c', '#f7a866', '#eb7723', '#b95117', '#862b0b'],
100
+ 'Sequential Orange Two': sharedPalettes.sequentialOrangeNine,
101
+ 'Sequential Green': ['#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32']
102
+ }
103
+
104
+ // Process and export chart color palettes with versioned structure
105
+ export const chartColorPalettes = {
106
+ v1: updatePaletteNames(chartColorPalettesData.v1),
107
+ v2: updatePaletteNames(chartColorPalettesData.v2)
108
+ }
109
+
110
+ export const twoColorPalette = {
111
+ v1: updatePaletteNames(twoColorPaletteData.v1),
112
+ v2: updatePaletteNames(twoColorPaletteData.v2) // No changes for v2, but structured for consistency
113
+ }
114
+
115
+ export const sequentialPalettes = sequentialColors
116
+ export const colorPalettesChart = chartColorPalettes
117
+ export const colorPalettesChartV1 = chartColorPalettes.v1
118
+ export const colorPalettesChartV2 = chartColorPalettes.v2
@@ -0,0 +1,9 @@
1
+ import { mapColorPalettes, mapColorPalettesV1, mapColorPalettesV2 } from './mapColorPalettes'
2
+ import { chartColorPalettes, sequentialPalettes, colorPalettesChart, colorPalettesChartV1, colorPalettesChartV2, twoColorPalette } from './chartColorPalettes'
3
+
4
+
5
+ // Re-export map palettes (already processed in mapColorPalettes.ts)
6
+ export { mapColorPalettes, mapColorPalettesV1, mapColorPalettesV2 }
7
+
8
+ // Re-export chart palettes (already processed in chartColorPalettes.ts)
9
+ export { chartColorPalettes, sequentialPalettes, colorPalettesChart, colorPalettesChartV1, colorPalettesChartV2, twoColorPalette }
@@ -0,0 +1,45 @@
1
+ import { updatePaletteNames } from '../helpers/updatePaletteNames'
2
+ import { sharedPalettes } from './sharedPalettes'
3
+
4
+ // Map-specific color palettes extracted from main colorPalettes.ts
5
+
6
+ const mapColorPalettesData = {
7
+ v1: {
8
+ sequential_yellow_orange_red: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],
9
+ sequential_yellow_orange_brown: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'],
10
+ sequential_pink_purple: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'],
11
+ sequential_blue_green: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'],
12
+ sequential_orange_red: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],
13
+ sequential_red: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'],
14
+ sequential_green_blue: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#267ba6', '#0868ac', '#084081'],
15
+ divergent_yellow_purple: ['#fff0b0', '#f5cc76', '#edae4b', '#e3683c', '#bf2a48', '#6d2059', '#8f0c4b', '#310958', '#0e0943'],
16
+ qualitative1: sharedPalettes.qualitative1,
17
+ qualitative2: sharedPalettes.qualitative2,
18
+ qualitative3: sharedPalettes.qualitative3,
19
+ qualitative4: sharedPalettes.qualitative4,
20
+ sequential_blue_extended: sharedPalettes.sequentialBlueNine,
21
+ sequential_orange_extended: sharedPalettes.sequentialOrangeNine,
22
+ colorblindsafe: sharedPalettes.colorblindsafe
23
+ },
24
+ v2: {
25
+ sequential_blue: ["#dbe8f7", "#bed5ed", "#99bce1", "#73a1d5", "#4e88c7", "#1e6bc0", "#0057b7", "#01418d", "#032659"],
26
+ sequential_teal: ["#e5fafc", "#b3e3ed", "#80cddf", "#4db8d1", "#00b1ce", "#03a2bd", "#0690a6", "#0d6e81", "#125261"],
27
+ sequential_purple: ["#e2d3df", "#cdb2c8", "#b78faf", "#a6739b", "#935586", "#823a73", "#722161", "#5f2359", "#47264f"],
28
+ sequential_orange: ["#ffe4d5", "#fed0b6", "#f7b99a", "#ed9e7c", "#e58061", "#db6b49", "#c95936", "#a8462c", "#702b1d"],
29
+ sequential_green: ["#d5f9f6", "#aeece7", "#85ded7", "#63d2ca", "#3bbcaf", "#14a594", "#0a937f", "#0f7a68", "#105b4d"],
30
+ divergent_blue_cyan: ["#032659", "#014697", "#1d6abf", "#6197d2", "#c1d2db", "#5ccbde", "#01acc9", "#097f95", "#125261"],
31
+ divergent_blue_purple: ["#032659", "#014697", "#1d6abf", "#6197d2", "#c4cde1", "#af8caa", "#935586", "#7c256b", "#47264f"],
32
+ divergent_green_orange: ["#105b4d", "#16806e", "#3ea394", "#5ebfb3", "#fabf61", "#ee956c", "#e27447", "#ac4726", "#702b1d"],
33
+ divergent_blue_orange: ["#032659", "#0057b7", "#0092c6", "#55b1a3", "#ffb24d", "#ea803b", "#dd622f", "#af3423", "#660f14"],
34
+ qualitative_standard: ["#0057b7", "#722161", "#00b1ce", "#d94e5f", "#5a8e3f", "#ffb24d", "#fb7e38", "#032659", "#975722"],
35
+ }
36
+ }
37
+
38
+ // Process and export map color palettes
39
+ export const mapColorPalettes = {
40
+ v1: updatePaletteNames(mapColorPalettesData.v1),
41
+ v2: updatePaletteNames(mapColorPalettesData.v2)
42
+ }
43
+
44
+ export const mapColorPalettesV1 = mapColorPalettes.v1
45
+ export const mapColorPalettesV2 = mapColorPalettes.v2