@cdc/chart 4.26.2 → 4.26.4

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 (165) hide show
  1. package/CONFIG.md +169 -0
  2. package/README.md +42 -17
  3. package/dist/cdcchart.js +39419 -35180
  4. package/examples/__data__/data-with-metadata.json +10 -0
  5. package/examples/feature/bar/additional-column-tooltip.json +3 -3
  6. package/examples/feature/deviation/planet-deviation-config.json +2 -2
  7. package/examples/feature/paired-bar/paired-bar-example.json +2 -2
  8. package/examples/feature/pie/planet-pie-example-config.json +2 -1
  9. package/examples/feature/tests-case-rate/case-rate-example-config.json +2 -2
  10. package/examples/feature/tests-covid/covid-confidence-example-config.json +2 -2
  11. package/examples/feature/tests-covid/covid-example-config.json +2 -2
  12. package/examples/feature/tests-cutoff/cutoff-example-config.json +2 -2
  13. package/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json +2 -2
  14. package/examples/metadata-variables.json +58 -0
  15. package/examples/minimal-example.json +24 -0
  16. package/examples/private/test2.json +35012 -0
  17. package/package.json +4 -4
  18. package/src/CdcChart.tsx +8 -4
  19. package/src/CdcChartComponent.tsx +326 -290
  20. package/src/_stories/Chart.CustomColors.smoke.stories.tsx +97 -0
  21. package/src/_stories/Chart.Defaults.smoke.stories.tsx +95 -0
  22. package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
  23. package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
  24. package/src/_stories/{Chart.SmallMultiples.stories.tsx → Chart.SmallMultiples.smoke.stories.tsx} +17 -1
  25. package/src/_stories/Chart.SmallestLeftAxisMax.smoke.stories.tsx +64 -0
  26. package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +48 -2
  27. package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
  28. package/src/_stories/ChartBar.Editor.stories.tsx +177 -115
  29. package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
  30. package/src/_stories/ChartEditor.Editor.stories.tsx +24 -1
  31. package/src/_stories/{Chart.CustomColors.stories.tsx → ChartLine.DashedDates.smoke.stories.tsx} +4 -4
  32. package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
  33. package/src/_stories/_mock/paired-bar-abbr.json +421 -0
  34. package/src/_stories/_mock/paired-bar.json +1 -1
  35. package/src/_stories/_mock/pie_custom_colors.json +268 -0
  36. package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
  37. package/src/components/Annotations/components/AnnotationDraggable.styles.css +10 -10
  38. package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
  39. package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -1
  40. package/src/components/Annotations/components/AnnotationList.styles.css +11 -11
  41. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
  42. package/src/components/Axis/BottomAxis.tsx +10 -3
  43. package/src/components/Axis/LeftAxis.tsx +2 -4
  44. package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
  45. package/src/components/Axis/PairedBarAxis.tsx +10 -4
  46. package/src/components/BarChart/components/BarChart.Horizontal.tsx +21 -33
  47. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +21 -35
  48. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +21 -36
  49. package/src/components/BarChart/components/BarChart.Vertical.tsx +21 -34
  50. package/src/components/BarChart/components/BarChart.tsx +2 -6
  51. package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
  52. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
  53. package/src/components/BarChart/helpers/useBarChart.ts +4 -1
  54. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
  55. package/src/components/Brush/BrushSelector.tsx +2 -1
  56. package/src/components/Brush/MiniChartPreview.tsx +21 -26
  57. package/src/components/EditorPanel/EditorPanel.tsx +692 -954
  58. package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
  59. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +218 -167
  60. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
  61. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +39 -1
  62. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +169 -135
  63. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +154 -109
  64. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
  65. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +95 -28
  66. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +45 -42
  67. package/src/components/EditorPanel/editor-panel.scss +1 -1
  68. package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
  69. package/src/components/Forecasting/Forecasting.tsx +2 -2
  70. package/src/components/ForestPlot/ForestPlot.tsx +26 -22
  71. package/src/components/HorizonChart/HorizonChart.tsx +10 -2
  72. package/src/components/HoverLine/HoverLine.tsx +6 -8
  73. package/src/components/Legend/Legend.Component.tsx +4 -4
  74. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +9 -4
  75. package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
  76. package/src/components/Legend/helpers/createFormatLabels.tsx +3 -2
  77. package/src/components/Legend/helpers/index.ts +0 -2
  78. package/src/components/LineChart/LineChartProps.ts +1 -0
  79. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +3 -2
  80. package/src/components/LineChart/index.tsx +11 -4
  81. package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
  82. package/src/components/LinearChart/tests/LinearChart.test.tsx +224 -0
  83. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -0
  84. package/src/components/LinearChart.tsx +124 -47
  85. package/src/components/PairedBarChart.jsx +2 -2
  86. package/src/components/PieChart/PieChart.tsx +30 -13
  87. package/src/components/RadarChart/RadarChart.tsx +1 -1
  88. package/src/components/Regions/components/Regions.tsx +36 -26
  89. package/src/components/Sankey/components/Sankey.tsx +3 -3
  90. package/src/components/Sankey/sankey.scss +1 -1
  91. package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
  92. package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
  93. package/src/components/SmallMultiples/SmallMultiples.css +5 -5
  94. package/src/components/Sparkline/components/SparkLine.tsx +1 -1
  95. package/src/components/Sparkline/index.scss +4 -2
  96. package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
  97. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
  98. package/src/data/initial-state.js +24 -14
  99. package/src/data/legacy-defaults.ts +18 -0
  100. package/src/helpers/abbreviateNumber.ts +24 -17
  101. package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
  102. package/src/helpers/getChartPatternId.ts +17 -0
  103. package/src/helpers/getMinMax.ts +16 -2
  104. package/src/helpers/seriesColumnSettings.ts +114 -0
  105. package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
  106. package/src/helpers/tests/seriesColumnSettings.test.ts +84 -0
  107. package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
  108. package/src/helpers/tooltipHelpers.ts +176 -0
  109. package/src/hooks/useHighlightedBars.ts +9 -16
  110. package/src/hooks/useProgrammaticTooltip.ts +16 -2
  111. package/src/hooks/useRightAxis.ts +14 -0
  112. package/src/hooks/useScales.ts +92 -56
  113. package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
  114. package/src/hooks/useTooltip.tsx +186 -40
  115. package/src/scss/main.scss +152 -79
  116. package/src/test/CdcChart.test.jsx +26 -2
  117. package/src/types/ChartConfig.ts +5 -0
  118. package/tests/fixtures/chart-config-with-metadata.json +29 -0
  119. package/tests/fixtures/data-with-metadata.json +10 -0
  120. package/examples/chart-regression-2.json +0 -2360
  121. package/examples/feature/__data__/age-adjusted-rates.json +0 -1486
  122. package/examples/feature/__data__/city-temperature.json +0 -2198
  123. package/examples/feature/bar/Barchart_with_negative.json +0 -34
  124. package/examples/feature/boxplot/box-plot-data.json +0 -71
  125. package/examples/feature/boxplot/boxplot-data.json +0 -156
  126. package/examples/feature/combo/combochart-categories_are_numbers .json +0 -18
  127. package/examples/feature/forest-plot/log.json +0 -26
  128. package/examples/feature/tests-date-exclusions/date-exclusions-data.json +0 -162
  129. package/examples/region-issue.json +0 -2065
  130. package/examples/xaxis.json +0 -493
  131. /package/examples/feature/bar/{tall-data.json → __data__/tall-data.json} +0 -0
  132. /package/examples/feature/deviation/{planet-deviation-data.json → __data__/planet-deviation-data.json} +0 -0
  133. /package/examples/feature/paired-bar/{paired-bar-data.json → __data__/paired-bar-data.json} +0 -0
  134. /package/examples/feature/paired-bar/{paired-bar-formatted.json → __data__/paired-bar-formatted.json} +0 -0
  135. /package/examples/feature/tests-case-rate/{case-rate-example-data.json → __data__/case-rate-example-data.json} +0 -0
  136. /package/examples/feature/tests-covid/{covid-example-data-confidence.json → __data__/covid-example-data-confidence.json} +0 -0
  137. /package/examples/feature/tests-covid/{covid-example-data.json → __data__/covid-example-data.json} +0 -0
  138. /package/examples/feature/tests-cutoff/{cutoff-example-data.json → __data__/cutoff-example-data.json} +0 -0
  139. /package/examples/feature/tests-non-numerics/{planet-example-data-nonnumeric.json → __data__/planet-example-data-nonnumeric.json} +0 -0
  140. /package/src/_stories/{Chart.Anchors.stories.tsx → Chart.Anchors.smoke.stories.tsx} +0 -0
  141. /package/src/_stories/{Chart.BoxPlot.stories.tsx → Chart.BoxPlot.smoke.stories.tsx} +0 -0
  142. /package/src/_stories/{Chart.CI.stories.tsx → Chart.CI.smoke.stories.tsx} +0 -0
  143. /package/src/_stories/{Chart.Combo.stories.tsx → Chart.Combo.smoke.stories.tsx} +0 -0
  144. /package/src/_stories/{Chart.DynamicSeries.stories.tsx → Chart.DynamicSeries.smoke.stories.tsx} +0 -0
  145. /package/src/_stories/{Chart.Filters.stories.tsx → Chart.Filters.smoke.stories.tsx} +0 -0
  146. /package/src/_stories/{Chart.Forecast.stories.tsx → Chart.Forecast.smoke.stories.tsx} +0 -0
  147. /package/src/_stories/{Chart.Legend.Gradient.stories.tsx → Chart.Legend.Gradient.smoke.stories.tsx} +0 -0
  148. /package/src/_stories/{Chart.Patterns.stories.tsx → Chart.Patterns.smoke.stories.tsx} +0 -0
  149. /package/src/_stories/{Chart.PreserveDecimals.stories.tsx → Chart.PreserveDecimals.smoke.stories.tsx} +0 -0
  150. /package/src/_stories/{Chart.Regions.Categorical.stories.tsx → Chart.Regions.Categorical.smoke.stories.tsx} +0 -0
  151. /package/src/_stories/{Chart.Regions.DateScale.stories.tsx → Chart.Regions.DateScale.smoke.stories.tsx} +0 -0
  152. /package/src/_stories/{Chart.Regions.DateTimeScale.stories.tsx → Chart.Regions.DateTimeScale.smoke.stories.tsx} +0 -0
  153. /package/src/_stories/{Chart.ScatterPlot.stories.tsx → Chart.ScatterPlot.smoke.stories.tsx} +0 -0
  154. /package/src/_stories/{ChartAnnotation.stories.tsx → ChartAnnotation.smoke.stories.tsx} +0 -0
  155. /package/src/_stories/{ChartAxisLabels.stories.tsx → ChartAxisLabels.smoke.stories.tsx} +0 -0
  156. /package/src/_stories/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +0 -0
  157. /package/src/_stories/{ChartBrush.Matrix.Continuous.stories.tsx → ChartBrush.Matrix.Continuous.smoke.stories.tsx} +0 -0
  158. /package/src/_stories/{ChartBrush.Matrix.Date.stories.tsx → ChartBrush.Matrix.Date.smoke.stories.tsx} +0 -0
  159. /package/src/_stories/{ChartBrush.Matrix.DateTime.stories.tsx → ChartBrush.Matrix.DateTime.smoke.stories.tsx} +0 -0
  160. /package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +0 -0
  161. /package/src/_stories/{ChartLine.QuadrantAngles.stories.tsx → ChartLine.QuadrantAngles.smoke.stories.tsx} +0 -0
  162. /package/src/_stories/{ChartLine.Suppression.stories.tsx → ChartLine.Suppression.smoke.stories.tsx} +0 -0
  163. /package/src/_stories/{ChartLine.Symbols.stories.tsx → ChartLine.Symbols.smoke.stories.tsx} +0 -0
  164. /package/src/_stories/{ChartPrefixSuffix.stories.tsx → ChartPrefixSuffix.smoke.stories.tsx} +0 -0
  165. /package/src/_stories/{TechAdoptionWithLinks.stories.tsx → TechAdoptionWithLinks.smoke.stories.tsx} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { useContext, FC } from 'react'
2
+ import { Draggable } from '@hello-pangea/dnd'
2
3
  import {
3
4
  Accordion,
4
5
  AccordionItem,
@@ -6,6 +7,7 @@ import {
6
7
  AccordionItemPanel,
7
8
  AccordionItemButton
8
9
  } from 'react-accessible-accordion'
10
+ import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
9
11
  import Tooltip from '@cdc/core/components/ui/Tooltip'
10
12
  import Icon from '@cdc/core/components/ui/Icon'
11
13
  import Button from '@cdc/core/components/elements/Button'
@@ -16,7 +18,7 @@ import { ChartContext } from '../../../../types/ChartContext'
16
18
  import { PanelProps } from '../PanelProps'
17
19
  import { checkColorContrast, getColorContrast } from '@cdc/core/helpers/cove/accessibility'
18
20
  import { getColorScale } from '../../../../helpers/getColorScale'
19
- import _ from 'lodash'
21
+ import { sanitizeToSvgId } from '@cdc/core/helpers/cove/string'
20
22
 
21
23
  const PanelPatternSettings: FC<PanelProps> = props => {
22
24
  const { config, updateConfig, transformedData } = useContext<ChartContext>(ConfigContext)
@@ -69,19 +71,6 @@ const PanelPatternSettings: FC<PanelProps> = props => {
69
71
  }
70
72
  }
71
73
 
72
- // Get unique values from a specific data field for dropdown options
73
- const getDataValueOptions = (dataKey: string) => {
74
- if (!dataKey || !Array.isArray(transformedData) || transformedData.length === 0) {
75
- return []
76
- }
77
-
78
- const uniqueValues = Array.from(new Set(transformedData.map(row => row[dataKey])))
79
- .filter(val => val !== undefined && val !== null && val !== '')
80
- .sort()
81
-
82
- return uniqueValues.map(value => ({ value: String(value), label: String(value) }))
83
- }
84
-
85
74
  const getFieldOptions = () => {
86
75
  if (!Array.isArray(transformedData) || transformedData.length === 0) return []
87
76
 
@@ -166,6 +155,21 @@ const PanelPatternSettings: FC<PanelProps> = props => {
166
155
  const fieldOptions = getFieldOptions()
167
156
  const currentPatterns: Record<string, LegendPattern> = legendCfg.patterns || {}
168
157
 
158
+ const handlePatternReorder = (sourceIndex: number, destinationIndex: number) => {
159
+ const patternEntries = Object.entries(currentPatterns)
160
+ const [movedPattern] = patternEntries.splice(sourceIndex, 1)
161
+ patternEntries.splice(destinationIndex, 0, movedPattern)
162
+
163
+ const newPatterns = Object.fromEntries(patternEntries)
164
+ updateConfig({
165
+ ...config,
166
+ legend: {
167
+ ...config.legend,
168
+ patterns: newPatterns
169
+ }
170
+ })
171
+ }
172
+
169
173
  // Check if all patterns pass contrast requirements
170
174
  const checkPatternContrasts = () => {
171
175
  return Object.values(currentPatterns).every(pattern => pattern.contrastCheck !== false)
@@ -282,11 +286,6 @@ const PanelPatternSettings: FC<PanelProps> = props => {
282
286
  [field]: value
283
287
  }
284
288
 
285
- // Clear dataValue if dataKey is being cleared or set to 'Select'
286
- if (field === 'dataKey' && (value === 'Select' || value === '')) {
287
- updatedPattern.dataValue = ''
288
- }
289
-
290
289
  const newPatterns = {
291
290
  ...(legendCfg.patterns || {}),
292
291
  [patternKey]: updatedPattern
@@ -326,130 +325,165 @@ const PanelPatternSettings: FC<PanelProps> = props => {
326
325
  message='Pattern colors must comply with <a href="https://www.w3.org/TR/WCAG21/">WCAG 2.1</a> 3:1 contrast ratio.'
327
326
  showCloseButton={false}
328
327
  />
329
- <br />
330
328
  </>
331
329
  )}
332
330
 
333
- {/* Individual Pattern Configurations */}
334
- {Object.entries(currentPatterns).map(([patternKey, pattern], index) => {
335
- const p: LegendPattern = pattern || {}
336
- const dataValueOptions = p.dataKey ? getDataValueOptions(p.dataKey) : []
337
-
338
- return (
339
- <Accordion allowZeroExpanded key={`pattern-accordion-${index}`}>
340
- <AccordionItem>
341
- <AccordionItemHeading>
342
- <AccordionItemButton>
343
- {p.dataKey && p.dataValue ? `${p.dataKey}: ${p.dataValue}` : `Pattern ${index + 1}`}
344
- </AccordionItemButton>
345
- </AccordionItemHeading>
346
- <AccordionItemPanel>
347
- {p.contrastCheck ?? true ? (
348
- <Alert type='success' message='This pattern passes contrast checks' showCloseButton={false} />
349
- ) : (
350
- <Alert
351
- type='danger'
352
- message='Error: <a href="https://webaim.org/resources/contrastchecker/" target="_blank"> Review Color Contrast</a>'
353
- showCloseButton={false}
354
- />
355
- )}
356
-
357
- <Select
358
- label='Data Key:'
359
- value={p.dataKey || ''}
360
- options={fieldOptions}
361
- initial='Select Data Key'
362
- fieldName={`pattern-datakey-${patternKey}`}
363
- updateField={(section, subsection, fieldName, value) =>
364
- handlePatternUpdate(patternKey, 'dataKey', value)
365
- }
366
- />
367
-
368
- {p.dataKey && (
369
- <>
370
- <label htmlFor={`pattern-datavalue-${patternKey}`}>
371
- Data Value:
372
- <input
373
- type='text'
374
- id={`pattern-datavalue-${patternKey}`}
375
- value={p.dataValue || ''}
376
- onChange={e => handlePatternUpdate(patternKey, 'dataValue', e.target.value)}
377
- placeholder='Enter data value'
378
- />
379
- </label>
380
- </>
381
- )}
382
-
383
- <label htmlFor={`pattern-label-${patternKey}`}>
384
- Label (optional):
385
- <input
386
- type='text'
387
- id={`pattern-label-${patternKey}`}
388
- value={p.label || ''}
389
- onChange={e => handlePatternUpdate(patternKey, 'label', e.target.value)}
390
- />
391
- </label>
392
-
393
- <Select
394
- label='Pattern Type:'
395
- value={p.shape || 'circles'}
396
- options={patternTypes}
397
- fieldName={`pattern-type-${patternKey}`}
398
- updateField={(section, subsection, fieldName, value) =>
399
- handlePatternUpdate(patternKey, 'shape', value)
400
- }
401
- />
402
-
403
- <Select
404
- label='Pattern Size:'
405
- value={getPatternSizeText(p.patternSize || 8)}
406
- options={patternSizes}
407
- fieldName={`pattern-size-${patternKey}`}
408
- updateField={(section, subsection, fieldName, value) =>
409
- handlePatternUpdate(patternKey, 'patternSize', getPatternSizeNumeric(value))
410
- }
411
- />
412
-
413
- <div className='mt-3'>
414
- <label htmlFor={`pattern-color-${patternKey}`}>
415
- Pattern Color
416
- <Tooltip style={{ textTransform: 'none' }}>
417
- <Tooltip.Target>
418
- <Icon
419
- display='question'
420
- style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
331
+ <GroupedList
332
+ items={Object.entries(currentPatterns)}
333
+ label='Pattern'
334
+ droppableId='chart-patterns-order'
335
+ onDragEnd={({ source, destination }) => {
336
+ if (!destination || source.index === destination.index) return
337
+ handlePatternReorder(source.index, destination.index)
338
+ }}
339
+ renderItem={([patternKey, pattern], index) => {
340
+ const p: LegendPattern = pattern || {}
341
+ const domPatternKey = `${sanitizeToSvgId(patternKey)}-${index}`
342
+
343
+ return (
344
+ <Draggable
345
+ key={`pattern-${patternKey}-${index}`}
346
+ draggableId={`pattern-${patternKey}-${index}`}
347
+ index={index}
348
+ >
349
+ {(provided, snapshot) => (
350
+ <div
351
+ ref={provided.innerRef}
352
+ {...provided.draggableProps}
353
+ {...provided.dragHandleProps}
354
+ className={snapshot.isDragging ? 'currently-dragging' : ''}
355
+ style={provided.draggableProps.style}
356
+ >
357
+ <Accordion allowZeroExpanded preExpanded={['panel']}>
358
+ <AccordionItem uuid='panel' className='series-item series-item--chart'>
359
+ <AccordionItemHeading className='series-item__title'>
360
+ <AccordionItemButton className='accordion__button'>
361
+ <Icon display='move' size={15} style={{ cursor: 'default' }} />
362
+ {p.dataKey && p.dataValue
363
+ ? `${p.dataKey}: ${p.dataValue}`
364
+ : p.dataValue
365
+ ? `All Series: ${p.dataValue}`
366
+ : `Pattern ${index + 1}`}
367
+ </AccordionItemButton>
368
+ </AccordionItemHeading>
369
+ <AccordionItemPanel>
370
+ <div className='series-item__panel-actions'>
371
+ <Button
372
+ type='button'
373
+ variant='danger'
374
+ size='sm'
375
+ className='grouped-list__remove'
376
+ onClick={() => handleRemovePattern(patternKey)}
377
+ >
378
+ Remove Pattern
379
+ </Button>
380
+ </div>
381
+ {p.contrastCheck ?? true ? (
382
+ <Alert
383
+ type='success'
384
+ message='This pattern passes contrast checks'
385
+ showCloseButton={false}
386
+ />
387
+ ) : (
388
+ <Alert
389
+ type='danger'
390
+ message='Error: <a href="https://webaim.org/resources/contrastchecker/" target="_blank"> Review Color Contrast</a>'
391
+ showCloseButton={false}
392
+ />
393
+ )}
394
+
395
+ <Select
396
+ label='Data Key:'
397
+ value={p.dataKey || ''}
398
+ options={fieldOptions}
399
+ initial='Select Data Key'
400
+ fieldName={`pattern-datakey-${domPatternKey}`}
401
+ updateField={(section, subsection, fieldName, value) =>
402
+ handlePatternUpdate(patternKey, 'dataKey', value)
403
+ }
421
404
  />
422
- </Tooltip.Target>
423
- <Tooltip.Content>
424
- <p>
425
- If this setting is used, it is the responsibility of the visualization author to verify the
426
- visualization colors meet WCAG 3:1 contrast ratios.
427
- </p>
428
- </Tooltip.Content>
429
- </Tooltip>
430
- <input
431
- type='text'
432
- value={p.color || ''}
433
- id={`pattern-color-${patternKey}`}
434
- onChange={e => handlePatternUpdate(patternKey, 'color', e.target.value)}
435
- placeholder='#666666'
436
- />
437
- </label>
438
- </div>
439
405
 
440
- <Button onClick={() => handleRemovePattern(patternKey)} className='btn btn-danger'>
441
- Remove Pattern
442
- </Button>
443
- </AccordionItemPanel>
444
- </AccordionItem>
445
- </Accordion>
446
- )
447
- })}
406
+ <label htmlFor={`pattern-datavalue-${domPatternKey}`}>
407
+ Data Value:
408
+ <input
409
+ type='text'
410
+ id={`pattern-datavalue-${domPatternKey}`}
411
+ value={p.dataValue || ''}
412
+ onChange={e => handlePatternUpdate(patternKey, 'dataValue', e.target.value)}
413
+ placeholder='Enter data value'
414
+ />
415
+ </label>
416
+
417
+ <label htmlFor={`pattern-label-${domPatternKey}`}>
418
+ Label (optional):
419
+ <input
420
+ type='text'
421
+ id={`pattern-label-${domPatternKey}`}
422
+ value={p.label || ''}
423
+ onChange={e => handlePatternUpdate(patternKey, 'label', e.target.value)}
424
+ />
425
+ </label>
426
+
427
+ <Select
428
+ label='Pattern Type:'
429
+ value={p.shape || 'circles'}
430
+ options={patternTypes}
431
+ fieldName={`pattern-type-${domPatternKey}`}
432
+ updateField={(section, subsection, fieldName, value) =>
433
+ handlePatternUpdate(patternKey, 'shape', value)
434
+ }
435
+ />
436
+
437
+ <Select
438
+ label='Pattern Size:'
439
+ value={getPatternSizeText(p.patternSize || 8)}
440
+ options={patternSizes}
441
+ fieldName={`pattern-size-${domPatternKey}`}
442
+ updateField={(section, subsection, fieldName, value) =>
443
+ handlePatternUpdate(patternKey, 'patternSize', getPatternSizeNumeric(value))
444
+ }
445
+ />
446
+
447
+ <div className='mt-3'>
448
+ <label htmlFor={`pattern-color-${domPatternKey}`}>
449
+ Pattern Color
450
+ <Tooltip style={{ textTransform: 'none' }}>
451
+ <Tooltip.Target>
452
+ <Icon
453
+ display='question'
454
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
455
+ />
456
+ </Tooltip.Target>
457
+ <Tooltip.Content>
458
+ <p>
459
+ If this setting is used, it is the responsibility of the visualization author to
460
+ verify the visualization colors meet WCAG 3:1 contrast ratios.
461
+ </p>
462
+ </Tooltip.Content>
463
+ </Tooltip>
464
+ <input
465
+ type='text'
466
+ value={p.color || ''}
467
+ id={`pattern-color-${domPatternKey}`}
468
+ onChange={e => handlePatternUpdate(patternKey, 'color', e.target.value)}
469
+ placeholder='#666666'
470
+ />
471
+ </label>
472
+ </div>
473
+ </AccordionItemPanel>
474
+ </AccordionItem>
475
+ </Accordion>
476
+ </div>
477
+ )}
478
+ </Draggable>
479
+ )
480
+ }}
481
+ />
448
482
 
449
483
  {/* Add Pattern Button */}
450
- <button className='btn btn-primary full-width mt-2' onClick={handleAddPattern}>
484
+ <Button variant='editor-primary' onClick={handleAddPattern}>
451
485
  Add Pattern
452
- </button>
486
+ </Button>
453
487
 
454
488
  {Object.keys(currentPatterns).length === 0 && (
455
489
  <p style={{ color: '#666', fontStyle: 'italic' }}>