@cdc/waffle-chart 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.
- package/LICENSE +201 -0
- package/dist/cdcwafflechart.js +7817 -7156
- package/package.json +3 -3
- package/src/CdcWaffleChart.tsx +218 -160
- package/src/_stories/WaffleChart.Editor.stories.tsx +8 -7
- package/src/components/EditorPanel.jsx +36 -2
- package/src/data/initial-state.js +3 -1
- package/src/scss/main.scss +3 -10
- package/src/scss/waffle-chart.scss +72 -31
- package/src/test/CdcWaffleChart.test.jsx +2 -2
- package/src/types/Config.ts +4 -0
- package/src/images/callout-flag.svg +0 -7
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/waffle-chart",
|
|
3
|
-
"version": "4.26.
|
|
3
|
+
"version": "4.26.3",
|
|
4
4
|
"description": "React component for displaying a single piece of data in a card module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "rshelnutt <qyu6@cdc.gov>",
|
|
7
7
|
"bugs": "https://github.com/CDCgov/cdc-open-viz/issues",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@cdc/core": "^4.26.
|
|
9
|
+
"@cdc/core": "^4.26.3",
|
|
10
10
|
"@visx/shape": "^3.12.0",
|
|
11
11
|
"@visx/text": "^3.12.0",
|
|
12
12
|
"html-react-parser": "^5.2.3",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"vite-plugin-css-injected-by-js": "^2.4.0",
|
|
21
21
|
"vite-plugin-svgr": "^4.2.0"
|
|
22
22
|
},
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "d50e45a074fbefa56cac904917e707d57f237737",
|
|
24
24
|
"homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
|
|
25
25
|
"main": "dist/cdcwafflechart",
|
|
26
26
|
"moduleName": "CdcWaffleChart",
|
package/src/CdcWaffleChart.tsx
CHANGED
|
@@ -25,13 +25,14 @@ import { publish } from '@cdc/core/helpers/events'
|
|
|
25
25
|
import chartReducer from './store/chart.reducer'
|
|
26
26
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
27
27
|
import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
|
|
28
|
+
import { processMarkupVariables } from '@cdc/core/helpers/markupProcessor'
|
|
28
29
|
|
|
29
30
|
import './scss/main.scss'
|
|
30
31
|
import Title from '@cdc/core/components/ui/Title'
|
|
31
|
-
import
|
|
32
|
+
import { VisualizationContainer, VisualizationContent } from '@cdc/core/components/Layout'
|
|
32
33
|
|
|
33
34
|
// images
|
|
34
|
-
import CalloutFlag from '
|
|
35
|
+
import CalloutFlag from '@cdc/core/assets/callout-flag.svg?url'
|
|
35
36
|
|
|
36
37
|
// TP5 Style Constants
|
|
37
38
|
const TP5_NODE_WIDTH = 13
|
|
@@ -72,6 +73,59 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
|
|
|
72
73
|
roundToPlace
|
|
73
74
|
} = config
|
|
74
75
|
|
|
76
|
+
const processedTextFields = useMemo(() => {
|
|
77
|
+
if (!config.enableMarkupVariables || !config.markupVariables?.length) {
|
|
78
|
+
return {
|
|
79
|
+
title,
|
|
80
|
+
content,
|
|
81
|
+
subtext,
|
|
82
|
+
valueDescription: config.valueDescription
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const markupOptions = {
|
|
87
|
+
isEditor,
|
|
88
|
+
showNoDataMessage: false,
|
|
89
|
+
allowHideSection: false,
|
|
90
|
+
filters: config.filters || [],
|
|
91
|
+
locale: config.locale,
|
|
92
|
+
dataMetadata: config.dataMetadata
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
title: title
|
|
97
|
+
? processMarkupVariables(title, config.data || [], config.markupVariables, markupOptions).processedContent
|
|
98
|
+
: title,
|
|
99
|
+
content: content
|
|
100
|
+
? processMarkupVariables(content, config.data || [], config.markupVariables, markupOptions).processedContent
|
|
101
|
+
: content,
|
|
102
|
+
subtext: subtext
|
|
103
|
+
? processMarkupVariables(subtext, config.data || [], config.markupVariables, markupOptions).processedContent
|
|
104
|
+
: subtext,
|
|
105
|
+
valueDescription: config.valueDescription
|
|
106
|
+
? processMarkupVariables(config.valueDescription, config.data || [], config.markupVariables, markupOptions)
|
|
107
|
+
.processedContent
|
|
108
|
+
: config.valueDescription
|
|
109
|
+
}
|
|
110
|
+
}, [
|
|
111
|
+
config.enableMarkupVariables,
|
|
112
|
+
config.markupVariables,
|
|
113
|
+
config.data,
|
|
114
|
+
config.filters,
|
|
115
|
+
config.locale,
|
|
116
|
+
config.dataMetadata,
|
|
117
|
+
config.valueDescription,
|
|
118
|
+
title,
|
|
119
|
+
content,
|
|
120
|
+
subtext,
|
|
121
|
+
isEditor
|
|
122
|
+
])
|
|
123
|
+
|
|
124
|
+
const processedTitle = processedTextFields.title
|
|
125
|
+
const processedContent = processedTextFields.content
|
|
126
|
+
const processedSubtext = processedTextFields.subtext
|
|
127
|
+
const processedValueDescription = processedTextFields.valueDescription
|
|
128
|
+
|
|
75
129
|
const gaugeColor = config.visual.colors[config.theme]
|
|
76
130
|
let dataFontSize = config.fontSize ? { fontSize: config.fontSize + 'px' } : null
|
|
77
131
|
|
|
@@ -351,7 +405,7 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
|
|
|
351
405
|
return setRatio() + 2
|
|
352
406
|
}, [nodeWidth, nodeSpacer, config.visualizationType])
|
|
353
407
|
|
|
354
|
-
const {
|
|
408
|
+
const { contentClasses } = useDataVizClasses(config)
|
|
355
409
|
|
|
356
410
|
const xScale = scaleLinear({
|
|
357
411
|
domain: [0, waffleDenominator],
|
|
@@ -397,141 +451,141 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
|
|
|
397
451
|
<Error updateConfig={updateConfig} config={config} />
|
|
398
452
|
)}
|
|
399
453
|
{config.newViz && showConfigConfirm && <Confirm updateConfig={updateConfig} config={config} />}
|
|
400
|
-
|
|
401
|
-
{
|
|
402
|
-
<div className=
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
>
|
|
411
|
-
<div className='cove-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
{config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
|
|
417
|
-
</div>
|
|
418
|
-
</div>
|
|
419
|
-
<div className='cove-gauge-chart__content flex-grow-1 d-flex flex-column min-w-0'>
|
|
420
|
-
{content ? (
|
|
421
|
-
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
422
|
-
) : (
|
|
423
|
-
<div className='cove-waffle-chart__data--text' aria-hidden='true'>
|
|
424
|
-
|
|
425
|
-
</div>
|
|
426
|
-
)}
|
|
454
|
+
{(config.visualizationType === 'Gauge' || config.visualizationType === 'TP5 Gauge') && (
|
|
455
|
+
<div className={`cove-gauge-chart${config.overallFontSize ? ' font-' + config.overallFontSize : ''}`}>
|
|
456
|
+
<div className='cove-gauge-chart__chart'>
|
|
457
|
+
{config.visualizationType === 'TP5 Gauge' ? (
|
|
458
|
+
<>
|
|
459
|
+
<div
|
|
460
|
+
className={`cove-gauge-chart__body d-flex flex-row align-items-start flex-grow-1${
|
|
461
|
+
!processedContent ? ' justify-content-center' : ''
|
|
462
|
+
}`}
|
|
463
|
+
>
|
|
464
|
+
<div className='cove-gauge-chart__value-section flex-shrink-0'>
|
|
465
|
+
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
466
|
+
{prefix ? prefix : ' '}
|
|
467
|
+
{config.showPercent ? dataPercentage : waffleNumerator}
|
|
468
|
+
{suffix ? suffix + ' ' : ' '} {processedValueDescription}{' '}
|
|
469
|
+
{config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
|
|
427
470
|
</div>
|
|
428
471
|
</div>
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
x={0}
|
|
438
|
-
y={0}
|
|
439
|
-
width={config.gauge.width}
|
|
440
|
-
height={config.gauge.height}
|
|
441
|
-
fill='#dff2f6'
|
|
442
|
-
stroke='#007A99'
|
|
443
|
-
strokeWidth={1}
|
|
444
|
-
rx={10}
|
|
445
|
-
ry={10}
|
|
446
|
-
/>
|
|
447
|
-
<Bar
|
|
448
|
-
x={0}
|
|
449
|
-
y={0}
|
|
450
|
-
width={xScale(waffleNumerator)}
|
|
451
|
-
height={config.gauge.height}
|
|
452
|
-
fill='#007A99'
|
|
453
|
-
rx={10}
|
|
454
|
-
ry={10}
|
|
455
|
-
/>
|
|
456
|
-
</Group>
|
|
457
|
-
</svg>
|
|
458
|
-
{subtext && (
|
|
459
|
-
<div className='cove-waffle-chart__subtext subtext fst-italic mt-2'>{parse(subtext)}</div>
|
|
460
|
-
)}
|
|
461
|
-
</>
|
|
462
|
-
) : (
|
|
463
|
-
<>
|
|
464
|
-
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
465
|
-
{prefix ? prefix : ' '}
|
|
466
|
-
{config.showPercent ? dataPercentage : waffleNumerator}
|
|
467
|
-
{suffix ? suffix + ' ' : ' '} {config.valueDescription}{' '}
|
|
468
|
-
{config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
|
|
469
|
-
</div>
|
|
470
|
-
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
471
|
-
<svg height={config.gauge.height} width={'100%'}>
|
|
472
|
-
<Group>
|
|
473
|
-
<Bar
|
|
474
|
-
x={0}
|
|
475
|
-
y={0}
|
|
476
|
-
width={config.gauge.width}
|
|
477
|
-
height={config.gauge.height}
|
|
478
|
-
fill='#e0e0e0'
|
|
479
|
-
stroke='#999'
|
|
480
|
-
strokeWidth={1}
|
|
481
|
-
rx={4}
|
|
482
|
-
ry={4}
|
|
483
|
-
/>
|
|
484
|
-
<Bar
|
|
485
|
-
x={0}
|
|
486
|
-
y={0}
|
|
487
|
-
width={xScale(waffleNumerator)}
|
|
488
|
-
height={config.gauge.height}
|
|
489
|
-
fill={gaugeColor}
|
|
490
|
-
rx={4}
|
|
491
|
-
ry={4}
|
|
492
|
-
/>
|
|
493
|
-
</Group>
|
|
494
|
-
</svg>
|
|
495
|
-
<div className={'cove-waffle-chart__subtext subtext'}>{parse(subtext)}</div>
|
|
496
|
-
</>
|
|
497
|
-
)}
|
|
498
|
-
</div>
|
|
499
|
-
</div>
|
|
500
|
-
)}
|
|
501
|
-
{config.visualizationType !== 'Gauge' && config.visualizationType !== 'TP5 Gauge' && (
|
|
502
|
-
<div
|
|
503
|
-
className={`cove-waffle-chart${orientation === 'vertical' ? ' cove-waffle-chart--verical' : ''}${
|
|
504
|
-
config.overallFontSize ? ' font-' + config.overallFontSize : ''
|
|
505
|
-
}`}
|
|
506
|
-
>
|
|
507
|
-
<div className='cove-waffle-chart__chart' style={{ width: setRatio() }}>
|
|
508
|
-
<svg width={setSvgSize()} height={setSvgSize()} style={{ display: 'block' }}>
|
|
509
|
-
<Group top={1} left={1}>
|
|
510
|
-
{buildWaffle()}
|
|
511
|
-
</Group>
|
|
512
|
-
</svg>
|
|
513
|
-
</div>
|
|
514
|
-
{(dataPercentage || content) && (
|
|
515
|
-
<div className='cove-waffle-chart__data'>
|
|
516
|
-
{dataPercentage && (
|
|
517
|
-
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
518
|
-
{prefix ? prefix : null}
|
|
519
|
-
{dataPercentage}
|
|
520
|
-
{suffix ? suffix : null}
|
|
472
|
+
<div className='cove-gauge-chart__content flex-grow-1 d-flex flex-column min-w-0'>
|
|
473
|
+
{processedContent ? (
|
|
474
|
+
<div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>
|
|
475
|
+
) : (
|
|
476
|
+
<div className='cove-waffle-chart__data--text' aria-hidden='true'>
|
|
477
|
+
|
|
478
|
+
</div>
|
|
479
|
+
)}
|
|
521
480
|
</div>
|
|
481
|
+
</div>
|
|
482
|
+
<svg
|
|
483
|
+
height={config.gauge.height + 2}
|
|
484
|
+
width={'100%'}
|
|
485
|
+
className='mt-2'
|
|
486
|
+
style={{ overflow: 'visible', padding: '1px' }}
|
|
487
|
+
>
|
|
488
|
+
<Group>
|
|
489
|
+
<Bar
|
|
490
|
+
x={0}
|
|
491
|
+
y={0}
|
|
492
|
+
width={config.gauge.width}
|
|
493
|
+
height={config.gauge.height}
|
|
494
|
+
fill='#dff2f6'
|
|
495
|
+
stroke='#007A99'
|
|
496
|
+
strokeWidth={1}
|
|
497
|
+
rx={10}
|
|
498
|
+
ry={10}
|
|
499
|
+
/>
|
|
500
|
+
<Bar
|
|
501
|
+
x={0}
|
|
502
|
+
y={0}
|
|
503
|
+
width={xScale(waffleNumerator)}
|
|
504
|
+
height={config.gauge.height}
|
|
505
|
+
fill='#007A99'
|
|
506
|
+
rx={10}
|
|
507
|
+
ry={10}
|
|
508
|
+
/>
|
|
509
|
+
</Group>
|
|
510
|
+
</svg>
|
|
511
|
+
{processedSubtext && (
|
|
512
|
+
<div className='cove-waffle-chart__subtext subtext fst-italic mt-2'>{parse(processedSubtext)}</div>
|
|
522
513
|
)}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
514
|
+
</>
|
|
515
|
+
) : (
|
|
516
|
+
<>
|
|
517
|
+
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
518
|
+
{prefix ? prefix : ' '}
|
|
519
|
+
{config.showPercent ? dataPercentage : waffleNumerator}
|
|
520
|
+
{suffix ? suffix + ' ' : ' '} {processedValueDescription}{' '}
|
|
521
|
+
{config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
|
|
522
|
+
</div>
|
|
523
|
+
<div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>
|
|
524
|
+
<svg height={config.gauge.height} width={'100%'}>
|
|
525
|
+
<Group>
|
|
526
|
+
<Bar
|
|
527
|
+
x={0}
|
|
528
|
+
y={0}
|
|
529
|
+
width={config.gauge.width}
|
|
530
|
+
height={config.gauge.height}
|
|
531
|
+
fill='#e0e0e0'
|
|
532
|
+
stroke='#999'
|
|
533
|
+
strokeWidth={1}
|
|
534
|
+
rx={4}
|
|
535
|
+
ry={4}
|
|
536
|
+
/>
|
|
537
|
+
<Bar
|
|
538
|
+
x={0}
|
|
539
|
+
y={0}
|
|
540
|
+
width={xScale(waffleNumerator)}
|
|
541
|
+
height={config.gauge.height}
|
|
542
|
+
fill={gaugeColor}
|
|
543
|
+
rx={4}
|
|
544
|
+
ry={4}
|
|
545
|
+
/>
|
|
546
|
+
</Group>
|
|
547
|
+
</svg>
|
|
548
|
+
<div className={'cove-waffle-chart__subtext subtext'}>{parse(processedSubtext)}</div>
|
|
549
|
+
</>
|
|
527
550
|
)}
|
|
528
551
|
</div>
|
|
529
|
-
|
|
530
|
-
|
|
552
|
+
</div>
|
|
553
|
+
)}
|
|
554
|
+
{config.visualizationType !== 'Gauge' && config.visualizationType !== 'TP5 Gauge' && (
|
|
555
|
+
<div
|
|
556
|
+
className={`cove-waffle-chart${orientation === 'vertical' ? ' cove-waffle-chart--verical' : ''}${
|
|
557
|
+
config.overallFontSize ? ' font-' + config.overallFontSize : ''
|
|
558
|
+
}`}
|
|
559
|
+
>
|
|
560
|
+
<div className='cove-waffle-chart__chart' style={{ width: setRatio() }}>
|
|
561
|
+
<svg width={setSvgSize()} height={setSvgSize()} style={{ display: 'block' }}>
|
|
562
|
+
<Group top={1} left={1}>
|
|
563
|
+
{buildWaffle()}
|
|
564
|
+
</Group>
|
|
565
|
+
</svg>
|
|
566
|
+
</div>
|
|
567
|
+
{(dataPercentage || processedContent) && (
|
|
568
|
+
<div className='cove-waffle-chart__data'>
|
|
569
|
+
{dataPercentage && (
|
|
570
|
+
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
571
|
+
{prefix ? prefix : null}
|
|
572
|
+
{dataPercentage}
|
|
573
|
+
{suffix ? suffix : null}
|
|
574
|
+
</div>
|
|
575
|
+
)}
|
|
576
|
+
{processedContent && <div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>}
|
|
577
|
+
|
|
578
|
+
{processedSubtext && (
|
|
579
|
+
<div className='cove-waffle-chart__subtext subtext fst-italic'>{parse(processedSubtext)}</div>
|
|
580
|
+
)}
|
|
581
|
+
</div>
|
|
582
|
+
)}
|
|
583
|
+
</div>
|
|
584
|
+
)}
|
|
531
585
|
</>
|
|
532
586
|
)
|
|
533
587
|
|
|
534
|
-
// TP5 Style: render with callout wrapper inside cove-
|
|
588
|
+
// TP5 Style: render with callout wrapper inside cove-visualization__body
|
|
535
589
|
if (config.visualizationType === 'TP5 Waffle' || config.visualizationType === 'TP5 Gauge') {
|
|
536
590
|
const calloutClasses = ['cdc-callout', 'd-flex', 'flex-column']
|
|
537
591
|
if (!config.visual?.whiteBackground) {
|
|
@@ -539,34 +593,40 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
|
|
|
539
593
|
}
|
|
540
594
|
|
|
541
595
|
return (
|
|
542
|
-
<
|
|
596
|
+
<VisualizationContent
|
|
597
|
+
bodyClassName={['no-borders', ...contentClasses].filter(Boolean).join(' ')}
|
|
598
|
+
footer={link && link}
|
|
599
|
+
>
|
|
543
600
|
<div className={calloutClasses.join(' ')}>
|
|
544
601
|
{!config.visual?.whiteBackground && (
|
|
545
602
|
<img src={CalloutFlag} alt='' className='cdc-callout__flag' aria-hidden='true' />
|
|
546
603
|
)}
|
|
547
|
-
{config.showTitle &&
|
|
548
|
-
<h3 className='cdc-callout__heading fw-bold flex-shrink-0'>{parse(
|
|
604
|
+
{config.showTitle && processedTitle && processedTitle.trim() && (
|
|
605
|
+
<h3 className='cdc-callout__heading fw-bold flex-shrink-0'>{parse(processedTitle)}</h3>
|
|
549
606
|
)}
|
|
550
607
|
<div className='w-100 mw-100 overflow-hidden'>{renderChartContent()}</div>
|
|
551
608
|
</div>
|
|
552
|
-
|
|
553
|
-
</div>
|
|
609
|
+
</VisualizationContent>
|
|
554
610
|
)
|
|
555
611
|
}
|
|
556
612
|
|
|
557
613
|
// Original Style: Regular title and content
|
|
558
614
|
return (
|
|
559
|
-
<
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
615
|
+
<VisualizationContent
|
|
616
|
+
bodyClassName={contentClasses.join(' ')}
|
|
617
|
+
header={
|
|
618
|
+
<Title
|
|
619
|
+
showTitle={config.showTitle}
|
|
620
|
+
title={processedTitle}
|
|
621
|
+
titleStyle='legacy'
|
|
622
|
+
config={config}
|
|
623
|
+
classes={['chart-title', `${config.theme}`, 'mb-0']}
|
|
624
|
+
/>
|
|
625
|
+
}
|
|
626
|
+
footer={link && link}
|
|
627
|
+
>
|
|
628
|
+
{renderChartContent()}
|
|
629
|
+
</VisualizationContent>
|
|
570
630
|
)
|
|
571
631
|
}
|
|
572
632
|
|
|
@@ -608,7 +668,9 @@ const CdcWaffleChart = ({
|
|
|
608
668
|
let responseData = response.data ?? {}
|
|
609
669
|
|
|
610
670
|
if (response.dataUrl) {
|
|
611
|
-
|
|
671
|
+
const { data, dataMetadata } = await fetchRemoteData(response.dataUrl)
|
|
672
|
+
responseData = data
|
|
673
|
+
response.dataMetadata = dataMetadata
|
|
612
674
|
}
|
|
613
675
|
|
|
614
676
|
response.data = responseData
|
|
@@ -658,17 +720,12 @@ const CdcWaffleChart = ({
|
|
|
658
720
|
|
|
659
721
|
if (loading === false) {
|
|
660
722
|
content = (
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
showConfigConfirm={showConfigConfirm}
|
|
668
|
-
updateConfig={updateConfig}
|
|
669
|
-
/>
|
|
670
|
-
</Layout.Responsive>
|
|
671
|
-
</>
|
|
723
|
+
<WaffleChart
|
|
724
|
+
config={config}
|
|
725
|
+
isEditor={isEditor}
|
|
726
|
+
showConfigConfirm={showConfigConfirm}
|
|
727
|
+
updateConfig={updateConfig}
|
|
728
|
+
/>
|
|
672
729
|
)
|
|
673
730
|
}
|
|
674
731
|
|
|
@@ -677,14 +734,15 @@ const CdcWaffleChart = ({
|
|
|
677
734
|
<ConfigContext.Provider
|
|
678
735
|
value={{ config, updateConfig, loading, data: config.data, setParentConfig, isDashboard, outerContainerRef }}
|
|
679
736
|
>
|
|
680
|
-
<
|
|
737
|
+
<VisualizationContainer
|
|
681
738
|
config={config}
|
|
682
739
|
isEditor={isEditor}
|
|
740
|
+
currentViewport={currentViewport}
|
|
683
741
|
ref={outerContainerRef}
|
|
684
|
-
|
|
742
|
+
editorPanel={<EditorPanel showConfigConfirm={showConfigConfirm} />}
|
|
685
743
|
>
|
|
686
744
|
{content}
|
|
687
|
-
</
|
|
745
|
+
</VisualizationContainer>
|
|
688
746
|
</ConfigContext.Provider>
|
|
689
747
|
</ErrorBoundary>
|
|
690
748
|
)
|
|
@@ -87,12 +87,12 @@ export const GeneralSectionTests: Story = {
|
|
|
87
87
|
// Poll for header text update
|
|
88
88
|
await performAndAssert(
|
|
89
89
|
'Title Update',
|
|
90
|
-
() => canvasElement.querySelector('.cove-
|
|
90
|
+
() => canvasElement.querySelector('.cove-visualization__header h2')?.textContent?.trim() || '',
|
|
91
91
|
async () => {}, // action already performed above
|
|
92
92
|
(before, after) => after === 'Updated Waffle Chart Title E2E'
|
|
93
93
|
)
|
|
94
94
|
|
|
95
|
-
const chartTitleHeader = canvasElement.querySelector('.cove-
|
|
95
|
+
const chartTitleHeader = canvasElement.querySelector('.cove-visualization__header h2')
|
|
96
96
|
expect(chartTitleHeader).toBeTruthy()
|
|
97
97
|
expect(chartTitleHeader.textContent.trim()).toBe('Updated Waffle Chart Title E2E')
|
|
98
98
|
|
|
@@ -120,7 +120,7 @@ export const GeneralSectionTests: Story = {
|
|
|
120
120
|
)
|
|
121
121
|
expect(showTitleCheckbox.checked).toBe(!wasChecked)
|
|
122
122
|
|
|
123
|
-
const chartTitleHeaderAfterToggle = canvasElement.querySelector('.cove-
|
|
123
|
+
const chartTitleHeaderAfterToggle = canvasElement.querySelector('.cove-visualization__header')
|
|
124
124
|
if (showTitleCheckbox.checked) {
|
|
125
125
|
expect(chartTitleHeaderAfterToggle).toBeTruthy()
|
|
126
126
|
expect(chartTitleHeaderAfterToggle).not.toHaveStyle('display: none')
|
|
@@ -435,7 +435,7 @@ export const VisualSectionTests: Story = {
|
|
|
435
435
|
await openAccordion(canvas, 'Chart Settings')
|
|
436
436
|
// Core helper functions used throughout the visual tests
|
|
437
437
|
const waffleRoot = () => canvasElement.querySelector('.cove-waffle-chart') as HTMLElement
|
|
438
|
-
const contentContainer = () => canvasElement.querySelector('.cove-
|
|
438
|
+
const contentContainer = () => canvasElement.querySelector('.cove-visualization__body') as HTMLElement
|
|
439
439
|
expect(waffleRoot()).toBeTruthy()
|
|
440
440
|
|
|
441
441
|
// ============================================================================
|
|
@@ -658,7 +658,7 @@ export const VisualSectionTests: Story = {
|
|
|
658
658
|
|
|
659
659
|
// ============================================================================
|
|
660
660
|
// TEST 9: Theme Border Color Toggle
|
|
661
|
-
// Expectation: Class 'component--has-
|
|
661
|
+
// Expectation: Class 'component--has-border-color-theme' toggles.
|
|
662
662
|
// ============================================================================
|
|
663
663
|
// Find border color theme checkbox by exact label text
|
|
664
664
|
const borderColorThemeCheckbox = canvas.getByLabelText('Use Border Color Theme') as HTMLInputElement
|
|
@@ -671,7 +671,8 @@ export const VisualSectionTests: Story = {
|
|
|
671
671
|
async () => {
|
|
672
672
|
await userEvent.click(borderColorThemeCheckbox)
|
|
673
673
|
},
|
|
674
|
-
(before, after) =>
|
|
674
|
+
(before, after) =>
|
|
675
|
+
before !== after && (after.includes('border-color-theme') || before.includes('border-color-theme'))
|
|
675
676
|
)
|
|
676
677
|
|
|
677
678
|
// ============================================================================
|
|
@@ -712,7 +713,7 @@ export const VisualSectionTests: Story = {
|
|
|
712
713
|
|
|
713
714
|
// ============================================================================
|
|
714
715
|
// TEST 12: Hide Background Color Toggle
|
|
715
|
-
// Expectation: Class 'component--
|
|
716
|
+
// Expectation: Class 'component--hide-background-color' toggles.
|
|
716
717
|
// ============================================================================
|
|
717
718
|
// Find hide background checkbox by exact label text
|
|
718
719
|
const hideBackgroundCheckbox = canvas.getByLabelText('Hide Background Color') as HTMLInputElement
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useEffect, memo, useContext } from 'react'
|
|
2
|
-
import _ from 'lodash'
|
|
3
2
|
|
|
4
3
|
import ConfigContext from '../ConfigContext'
|
|
5
4
|
|
|
@@ -14,8 +13,9 @@ import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
|
14
13
|
import { useFilterManagement } from '@cdc/core/hooks/useFilterManagement'
|
|
15
14
|
import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
|
|
16
15
|
import { VisualSection } from '@cdc/core/components/EditorPanel/sections/VisualSection'
|
|
16
|
+
import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
|
|
17
17
|
|
|
18
|
-
import '@cdc/core/
|
|
18
|
+
import '@cdc/core/components/EditorPanel/editor.scss'
|
|
19
19
|
import WarningImage from '../images/warning.svg'
|
|
20
20
|
|
|
21
21
|
import { DATA_OPERATORS, DATA_FUNCTIONS } from '../CdcWaffleChart'
|
|
@@ -120,6 +120,28 @@ const EditorPanel = memo(props => {
|
|
|
120
120
|
</Tooltip>
|
|
121
121
|
}
|
|
122
122
|
/>
|
|
123
|
+
<Select
|
|
124
|
+
value={config.locale}
|
|
125
|
+
fieldName='locale'
|
|
126
|
+
label='Language for dates and numbers'
|
|
127
|
+
updateField={updateField}
|
|
128
|
+
options={[
|
|
129
|
+
{ value: 'en-US', label: 'English (en-US)' },
|
|
130
|
+
{ value: 'es-MX', label: 'Spanish (es-MX)' }
|
|
131
|
+
]}
|
|
132
|
+
tooltip={
|
|
133
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
134
|
+
<Tooltip.Target>
|
|
135
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
136
|
+
</Tooltip.Target>
|
|
137
|
+
<Tooltip.Content>
|
|
138
|
+
<p>
|
|
139
|
+
Change the language (locale) for this visualization to alter the way dates and numbers are formatted.
|
|
140
|
+
</p>
|
|
141
|
+
</Tooltip.Content>
|
|
142
|
+
</Tooltip>
|
|
143
|
+
}
|
|
144
|
+
/>
|
|
123
145
|
</Accordion.Section>
|
|
124
146
|
|
|
125
147
|
<Accordion.Section
|
|
@@ -431,6 +453,18 @@ const EditorPanel = memo(props => {
|
|
|
431
453
|
/>
|
|
432
454
|
</Accordion.Section>
|
|
433
455
|
)}
|
|
456
|
+
<Accordion.Section title='Markup Variables'>
|
|
457
|
+
<PanelMarkup
|
|
458
|
+
name='Markup Variables'
|
|
459
|
+
markupVariables={config.markupVariables || []}
|
|
460
|
+
data={data}
|
|
461
|
+
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
462
|
+
onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
|
|
463
|
+
onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
|
|
464
|
+
withAccordion={false}
|
|
465
|
+
dataMetadata={config.dataMetadata}
|
|
466
|
+
/>
|
|
467
|
+
</Accordion.Section>
|
|
434
468
|
</Accordion>
|
|
435
469
|
)
|
|
436
470
|
|
package/src/scss/main.scss
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
@import '@cdc/core/styles/accessibility';
|
|
1
|
+
@import '@cdc/core/styles/utils/accessibility';
|
|
2
2
|
@import 'waffle-chart';
|
|
3
3
|
|
|
4
|
-
.
|
|
5
|
-
.cove-
|
|
4
|
+
.cove-visualization.type-waffle-chart {
|
|
5
|
+
.cove-visualization__body:not(.component--has-background, .component--hide-background-color) {
|
|
6
6
|
background-color: white;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
&.is-editor .cove-component {
|
|
10
|
-
padding-left: 350px;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
&.is-editor .cove-editor__content .cove-component {
|
|
14
|
-
padding-left: 0px;
|
|
15
|
-
}
|
|
16
9
|
}
|