@cdc/waffle-chart 4.24.3 → 4.24.5
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/dist/cdcwafflechart.js +8732 -4881
- package/index.html +7 -0
- package/package.json +3 -3
- package/src/CdcWaffleChart.tsx +94 -79
- package/src/components/EditorPanel.jsx +12 -48
- package/src/scss/main.scss +14 -2
- package/src/scss/waffle-chart.scss +4 -0
package/index.html
CHANGED
|
@@ -4,18 +4,25 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
6
6
|
<style>
|
|
7
|
+
.type-waffle-chart {
|
|
8
|
+
min-height: 100vh;
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
body {
|
|
8
12
|
/* max-width: 1000px; */
|
|
9
13
|
margin: 0 auto !important;
|
|
10
14
|
display: flex;
|
|
11
15
|
flex-direction: column;
|
|
12
16
|
justify-content: center;
|
|
17
|
+
border-top: none !important;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
.react-container + .react-container {
|
|
16
21
|
margin-top: 3rem;
|
|
17
22
|
}
|
|
18
23
|
</style>
|
|
24
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/contrib/libs/bootstrap/latest/css/bootstrap.min.css?_=39423" />
|
|
25
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/4.0/assets/css/app.min.css?_=39423" />
|
|
19
26
|
</head>
|
|
20
27
|
<body>
|
|
21
28
|
<!-- Original -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/waffle-chart",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.5",
|
|
4
4
|
"description": "React component for displaying a single piece of data in a card module",
|
|
5
5
|
"moduleName": "CdcWaffleChart",
|
|
6
6
|
"main": "dist/cdcwafflechart",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@cdc/core": "^4.24.
|
|
29
|
+
"@cdc/core": "^4.24.5",
|
|
30
30
|
"@visx/group": "^3.0.0",
|
|
31
31
|
"@visx/scale": "^3.0.0",
|
|
32
32
|
"@visx/shape": "^3.0.0",
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"react": "^18.2.0",
|
|
42
42
|
"react-dom": "^18.2.0"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "def85aaf4cd9dc1983e80f2900199f35de82af95"
|
|
45
45
|
}
|
package/src/CdcWaffleChart.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useReducer } from 'react'
|
|
1
|
+
import React, { useCallback, useEffect, useReducer, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
// visx
|
|
4
4
|
import { Circle, Bar } from '@visx/shape'
|
|
@@ -27,6 +27,7 @@ import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
|
|
|
27
27
|
|
|
28
28
|
import './scss/main.scss'
|
|
29
29
|
import Title from '@cdc/core/components/ui/Title'
|
|
30
|
+
import Layout from '@cdc/core/components/Layout'
|
|
30
31
|
|
|
31
32
|
type CdcWaffleChartProps = {
|
|
32
33
|
configUrl?: string
|
|
@@ -37,24 +38,9 @@ type CdcWaffleChartProps = {
|
|
|
37
38
|
setConfig?: () => void
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
const WaffleChart = ({ config, isEditor, link = '' }) => {
|
|
41
|
+
const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateConfig }) => {
|
|
41
42
|
const { title, theme, shape, nodeWidth, nodeSpacer, prefix, suffix, subtext, content, orientation, filters, dataColumn, dataFunction, dataConditionalColumn, dataConditionalOperator, dataConditionalComparate, customDenom, dataDenom, dataDenomColumn, dataDenomFunction, roundToPlace } = config
|
|
42
43
|
|
|
43
|
-
const handleWaffleChartAriaLabel = (state, testing = false): string => {
|
|
44
|
-
// eslint-disable-next-line no-console
|
|
45
|
-
if (testing) console.log(`handleWaffleChartAriaLabels Testing On:`, state)
|
|
46
|
-
try {
|
|
47
|
-
let ariaLabel = 'Waffle chart'
|
|
48
|
-
if (state.title) {
|
|
49
|
-
ariaLabel += ` with the title: ${state.title}`
|
|
50
|
-
}
|
|
51
|
-
return ariaLabel
|
|
52
|
-
} catch (e) {
|
|
53
|
-
// eslint-disable-next-line no-console
|
|
54
|
-
console.error(e.message)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
44
|
const gaugeColor = config.visual.colors[config.theme]
|
|
59
45
|
let dataFontSize = config.fontSize ? { fontSize: config.fontSize + 'px' } : null
|
|
60
46
|
|
|
@@ -279,58 +265,90 @@ const WaffleChart = ({ config, isEditor, link = '' }) => {
|
|
|
279
265
|
range: [0, config.gauge.width]
|
|
280
266
|
})
|
|
281
267
|
|
|
268
|
+
const Error = ({ config, updateConfig }) => {
|
|
269
|
+
return (
|
|
270
|
+
<section className='waiting'>
|
|
271
|
+
<section className='waiting-container'>
|
|
272
|
+
<h3>Error With Configuration</h3>
|
|
273
|
+
<p>{config.runtime.editorErrorMessage}</p>
|
|
274
|
+
</section>
|
|
275
|
+
</section>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const Confirm = ({ updateConfig, config }) => {
|
|
280
|
+
const confirmDone = e => {
|
|
281
|
+
e.preventDefault()
|
|
282
|
+
let newConfig = { ...config }
|
|
283
|
+
delete newConfig.newViz
|
|
284
|
+
updateConfig(newConfig)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<section className='waiting'>
|
|
289
|
+
<section className='waiting-container'>
|
|
290
|
+
<h3>Finish Configuring</h3>
|
|
291
|
+
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
292
|
+
<button className='btn' style={{ margin: '1em auto' }} onClick={confirmDone}>
|
|
293
|
+
I'm Done
|
|
294
|
+
</button>
|
|
295
|
+
</section>
|
|
296
|
+
</section>
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
|
|
282
300
|
return (
|
|
283
|
-
<div className=
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
<
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
297
|
-
<svg height={config.gauge.height} width={'100%'}>
|
|
298
|
-
<Group>
|
|
299
|
-
<foreignObject style={{ border: '1px solid black' }} x={0} y={0} width={config.gauge.width} height={config.gauge.height} fill='#fff' />
|
|
300
|
-
<Bar x={0} y={0} width={xScale(waffleNumerator)} height={config.gauge.height} fill={gaugeColor} />
|
|
301
|
-
</Group>
|
|
302
|
-
</svg>
|
|
303
|
-
<div className={'cove-waffle-chart__subtext subtext'}>{parse(subtext)}</div>
|
|
301
|
+
<div className='cove-component__content'>
|
|
302
|
+
<Title title={title} config={config} classes={['chart-title', `${config.theme}`, 'mb-0']} />
|
|
303
|
+
<div className={contentClasses.join(' ')}>
|
|
304
|
+
{!config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error updateConfig={updateConfig} config={config} />}
|
|
305
|
+
{config.newViz && showConfigConfirm && <Confirm updateConfig={updateConfig} config={config} />}
|
|
306
|
+
<div className='cove-component__content-wrap'>
|
|
307
|
+
{config.visualizationType === 'Gauge' && (
|
|
308
|
+
<div className={`cove-gauge-chart${config.overallFontSize ? ' font-' + config.overallFontSize : ''}`}>
|
|
309
|
+
<div className='cove-gauge-chart__chart'>
|
|
310
|
+
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
311
|
+
{prefix ? prefix : ' '}
|
|
312
|
+
{config.showPercent ? dataPercentage : waffleNumerator}
|
|
313
|
+
{suffix ? suffix + ' ' : ' '} {config.valueDescription} {config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
|
|
304
314
|
</div>
|
|
315
|
+
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
316
|
+
<svg height={config.gauge.height} width={'100%'}>
|
|
317
|
+
<Group>
|
|
318
|
+
<foreignObject style={{ border: '1px solid black' }} x={0} y={0} width={config.gauge.width} height={config.gauge.height} fill='#fff' />
|
|
319
|
+
<Bar x={0} y={0} width={xScale(waffleNumerator)} height={config.gauge.height} fill={gaugeColor} />
|
|
320
|
+
</Group>
|
|
321
|
+
</svg>
|
|
322
|
+
<div className={'cove-waffle-chart__subtext subtext'}>{parse(subtext)}</div>
|
|
305
323
|
</div>
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
</
|
|
313
|
-
</
|
|
314
|
-
{(dataPercentage || content) && (
|
|
315
|
-
<div className='cove-waffle-chart__data'>
|
|
316
|
-
{dataPercentage && (
|
|
317
|
-
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
318
|
-
{prefix ? prefix : null}
|
|
319
|
-
{dataPercentage}
|
|
320
|
-
{suffix ? suffix : null}
|
|
321
|
-
</div>
|
|
322
|
-
)}
|
|
323
|
-
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
324
|
-
|
|
325
|
-
{subtext && <div className='cove-waffle-chart__subtext subtext'>{parse(subtext)}</div>}
|
|
326
|
-
</div>
|
|
327
|
-
)}
|
|
324
|
+
</div>
|
|
325
|
+
)}
|
|
326
|
+
{config.visualizationType !== 'Gauge' && (
|
|
327
|
+
<div className={`cove-waffle-chart${orientation === 'vertical' ? ' cove-waffle-chart--verical' : ''}${config.overallFontSize ? ' font-' + config.overallFontSize : ''}`}>
|
|
328
|
+
<div className='cove-waffle-chart__chart' style={{ width: setRatio() }}>
|
|
329
|
+
<svg width={setRatio()} height={setRatio()}>
|
|
330
|
+
<Group>{buildWaffle()}</Group>
|
|
331
|
+
</svg>
|
|
328
332
|
</div>
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
{(dataPercentage || content) && (
|
|
334
|
+
<div className='cove-waffle-chart__data'>
|
|
335
|
+
{dataPercentage && (
|
|
336
|
+
<div className='cove-waffle-chart__data--primary' style={dataFontSize}>
|
|
337
|
+
{prefix ? prefix : null}
|
|
338
|
+
{dataPercentage}
|
|
339
|
+
{suffix ? suffix : null}
|
|
340
|
+
</div>
|
|
341
|
+
)}
|
|
342
|
+
<div className='cove-waffle-chart__data--text'>{parse(content)}</div>
|
|
343
|
+
|
|
344
|
+
{subtext && <div className='cove-waffle-chart__subtext subtext'>{parse(subtext)}</div>}
|
|
345
|
+
</div>
|
|
346
|
+
)}
|
|
347
|
+
</div>
|
|
348
|
+
)}
|
|
331
349
|
</div>
|
|
332
|
-
|
|
333
|
-
|
|
350
|
+
</div>
|
|
351
|
+
{link && link}
|
|
334
352
|
</div>
|
|
335
353
|
)
|
|
336
354
|
}
|
|
@@ -339,6 +357,7 @@ const CdcWaffleChart = ({ configUrl, config: configObj, isDashboard = false, isE
|
|
|
339
357
|
// Default States
|
|
340
358
|
const [state, dispatch] = useReducer(chartReducer, { config: configObj ?? defaults, loading: true, preview: false, viewport: 'lg', coveLoadedHasRan: false, container: null })
|
|
341
359
|
const { loading, config, viewport: currentViewport, coveLoadedHasRan, container } = state
|
|
360
|
+
const [showConfigConfirm, setShowConfigConfirm] = useState(false)
|
|
342
361
|
|
|
343
362
|
// Default Functions
|
|
344
363
|
const updateConfig = newConfig => {
|
|
@@ -417,31 +436,27 @@ const CdcWaffleChart = ({ configUrl, config: configObj, isDashboard = false, isE
|
|
|
417
436
|
let content = <Loading />
|
|
418
437
|
|
|
419
438
|
if (loading === false) {
|
|
420
|
-
let classNames = ['cove', 'cdc-open-viz-module', 'type-waffle-chart', currentViewport, config.theme, 'font-' + config.overallFontSize]
|
|
421
|
-
|
|
422
|
-
if (isEditor) {
|
|
423
|
-
classNames.push('is-editor')
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
let bodyClasses = ['cove-component', 'waffle-chart']
|
|
427
|
-
|
|
428
439
|
let body = (
|
|
429
|
-
<
|
|
430
|
-
<WaffleChart config={config} isEditor={isEditor} />
|
|
431
|
-
</
|
|
440
|
+
<Layout.Responsive isEditor={isEditor}>
|
|
441
|
+
<WaffleChart config={config} isEditor={isEditor} showConfigConfirm={showConfigConfirm} updateConfig={updateConfig} />
|
|
442
|
+
</Layout.Responsive>
|
|
432
443
|
)
|
|
433
444
|
|
|
434
445
|
content = (
|
|
435
|
-
|
|
436
|
-
{isEditor && <EditorPanel>{body}</EditorPanel>}
|
|
446
|
+
<>
|
|
447
|
+
{isEditor && <EditorPanel showConfigConfirm={showConfigConfirm}>{body}</EditorPanel>}
|
|
437
448
|
{!isEditor && body}
|
|
438
|
-
|
|
449
|
+
</>
|
|
439
450
|
)
|
|
440
451
|
}
|
|
441
452
|
|
|
442
453
|
return (
|
|
443
454
|
<ErrorBoundary component='WaffleChart'>
|
|
444
|
-
<ConfigContext.Provider value={{ config, updateConfig, loading, data: config.data, setParentConfig, isDashboard, outerContainerRef }}>
|
|
455
|
+
<ConfigContext.Provider value={{ config, updateConfig, loading, data: config.data, setParentConfig, isDashboard, outerContainerRef }}>
|
|
456
|
+
<Layout.VisualizationWrapper config={config} isEditor={isEditor} ref={outerContainerRef} showEditorPanel={config?.showEditorPanel}>
|
|
457
|
+
{content}
|
|
458
|
+
</Layout.VisualizationWrapper>
|
|
459
|
+
</ConfigContext.Provider>
|
|
445
460
|
</ErrorBoundary>
|
|
446
461
|
)
|
|
447
462
|
}
|
|
@@ -12,6 +12,7 @@ import InputText from '@cdc/core/components/inputs/InputText'
|
|
|
12
12
|
import InputSelect from '@cdc/core/components/inputs/InputSelect'
|
|
13
13
|
import InputCheckbox from '@cdc/core/components/inputs/InputCheckbox'
|
|
14
14
|
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
15
|
+
import Layout from '@cdc/core/components/Layout'
|
|
15
16
|
|
|
16
17
|
import '@cdc/core/styles/v2/components/editor.scss'
|
|
17
18
|
import WarningImage from '../images/warning.svg'
|
|
@@ -38,9 +39,8 @@ const CheckBox = memo(({ label, value, fieldName, section = null, subsection = n
|
|
|
38
39
|
|
|
39
40
|
const EditorPanel = memo(props => {
|
|
40
41
|
const { config, updateConfig, loading, data, setParentConfig, isDashboard } = useContext(ConfigContext)
|
|
41
|
-
|
|
42
|
+
const { showConfigConfirm } = props
|
|
42
43
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
43
|
-
const [showConfigConfirm, setShowConfigConfirm] = useState(false)
|
|
44
44
|
const inputSelectStyle = condition => (condition ? { backgroundColor: '#ffd2d2', color: '#d8000c' } : {})
|
|
45
45
|
|
|
46
46
|
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
@@ -80,6 +80,10 @@ const EditorPanel = memo(props => {
|
|
|
80
80
|
|
|
81
81
|
const onBackClick = () => {
|
|
82
82
|
setDisplayPanel(!displayPanel)
|
|
83
|
+
updateConfig({
|
|
84
|
+
...config,
|
|
85
|
+
showEditorPanel: !displayPanel
|
|
86
|
+
})
|
|
83
87
|
|
|
84
88
|
// if (isDashboard) {
|
|
85
89
|
// updateConfig({ ...config, editing: false })
|
|
@@ -88,38 +92,6 @@ const EditorPanel = memo(props => {
|
|
|
88
92
|
// }
|
|
89
93
|
}
|
|
90
94
|
|
|
91
|
-
const Error = () => {
|
|
92
|
-
return (
|
|
93
|
-
<section className='waiting'>
|
|
94
|
-
<section className='waiting-container'>
|
|
95
|
-
<h3>Error With Configuration</h3>
|
|
96
|
-
<p>{config.runtime.editorErrorMessage}</p>
|
|
97
|
-
</section>
|
|
98
|
-
</section>
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const Confirm = () => {
|
|
103
|
-
const confirmDone = e => {
|
|
104
|
-
e.preventDefault()
|
|
105
|
-
let newConfig = { ...config }
|
|
106
|
-
delete newConfig.newViz
|
|
107
|
-
updateConfig(newConfig)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<section className='waiting'>
|
|
112
|
-
<section className='waiting-container'>
|
|
113
|
-
<h3>Finish Configuring</h3>
|
|
114
|
-
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
115
|
-
<button className='btn' style={{ margin: '1em auto' }} onClick={confirmDone}>
|
|
116
|
-
I'm Done
|
|
117
|
-
</button>
|
|
118
|
-
</section>
|
|
119
|
-
</section>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
95
|
const convertStateToConfig = () => {
|
|
124
96
|
let strippedState = JSON.parse(JSON.stringify(config))
|
|
125
97
|
delete strippedState.newViz
|
|
@@ -427,20 +399,12 @@ const EditorPanel = memo(props => {
|
|
|
427
399
|
|
|
428
400
|
return (
|
|
429
401
|
<ErrorBoundary component='EditorPanel'>
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
<h2 className='cove-editor__heading'>Configure Chart</h2>
|
|
437
|
-
<section className='cove-editor__content'>{editorContent}</section>
|
|
438
|
-
</div>
|
|
439
|
-
</section>
|
|
440
|
-
<div className='cove-editor__content'>
|
|
441
|
-
<div className='cove-editor__content-wrap'>{props.children}</div>
|
|
442
|
-
</div>
|
|
443
|
-
</div>
|
|
402
|
+
<>
|
|
403
|
+
<Layout.Sidebar displayPanel={displayPanel} onBackClick={onBackClick} isDashboard={isDashboard} title='Configure Waffle Chart' showEditorPanel={displayPanel}>
|
|
404
|
+
{editorContent}
|
|
405
|
+
</Layout.Sidebar>
|
|
406
|
+
{props.children}
|
|
407
|
+
</>
|
|
444
408
|
</ErrorBoundary>
|
|
445
409
|
)
|
|
446
410
|
})
|
package/src/scss/main.scss
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
@import '@cdc/core/styles/v2/components/input';
|
|
2
|
-
@import '@cdc/core/styles/v2/main';
|
|
3
1
|
@import '@cdc/core/styles/base';
|
|
2
|
+
@import '@cdc/core/styles/heading-colors';
|
|
3
|
+
@import '@cdc/core/styles/v2/themes/color-definitions';
|
|
4
4
|
@import 'waffle-chart';
|
|
5
5
|
|
|
6
6
|
.cdc-open-viz-module.type-waffle-chart {
|
|
@@ -14,4 +14,16 @@
|
|
|
14
14
|
content: '\21BB';
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
.cove-component__content:not(.component--has-background, .component--hideBackgroundColor) {
|
|
19
|
+
background-color: white;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.is-editor .cove-component {
|
|
23
|
+
padding-left: 350px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.is-editor .cove-editor__content .cove-component {
|
|
27
|
+
padding-left: 0px;
|
|
28
|
+
}
|
|
17
29
|
}
|