@cdc/data-bite 4.24.3 → 4.24.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.
- package/dist/cdcdatabite.js +9138 -5284
- package/index.html +9 -2
- package/package.json +3 -3
- package/src/CdcDataBite.tsx +75 -15
- package/src/components/EditorPanel.jsx +8 -40
- package/src/components/GradientBite.jsx +20 -16
- package/src/scss/bite.scss +16 -11
- package/src/scss/editor-panel.scss +1 -1
- package/src/scss/kpi.scss +44 -44
- package/src/scss/main.scss +1 -1
package/index.html
CHANGED
|
@@ -6,15 +6,22 @@
|
|
|
6
6
|
<style>
|
|
7
7
|
body {
|
|
8
8
|
margin: 0;
|
|
9
|
+
border-top: none !important;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.cdc-open-viz-module {
|
|
13
|
+
min-height: 100vh;
|
|
9
14
|
}
|
|
10
15
|
</style>
|
|
16
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/contrib/libs/bootstrap/latest/css/bootstrap.min.css?_=39423" />
|
|
17
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/4.0/assets/css/app.min.css?_=39423" />
|
|
11
18
|
</head>
|
|
12
19
|
<body>
|
|
13
20
|
<!-- Original -->
|
|
14
|
-
<div class="react-container" data-config="/examples/sankey-example-data.json"></div>
|
|
21
|
+
<!-- <div class="react-container" data-config="/examples/sankey-example-data.json"></div> -->
|
|
15
22
|
|
|
16
23
|
<!-- DATA PRESENTATION GALLERY: https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/data_bites.html#examples -->
|
|
17
|
-
|
|
24
|
+
<div class="react-container" data-config="/examples/gallery/calculated-average.json"></div>
|
|
18
25
|
<!-- <div class="react-container" data-config="/examples/gallery/calculated-with-pic.json"></div> -->
|
|
19
26
|
<div class="react-container" data-config="/examples/gallery/max-value.json"></div>
|
|
20
27
|
<!-- <div class="react-container" data-config="/examples/gallery/sum-of-data.json"></div> -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/data-bite",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.4",
|
|
4
4
|
"description": "React component for displaying a single piece of data in a card module",
|
|
5
5
|
"moduleName": "CdcDataBite",
|
|
6
6
|
"main": "dist/cdcdatabite",
|
|
@@ -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.4",
|
|
30
30
|
"chroma": "0.0.1",
|
|
31
31
|
"chroma-js": "^2.1.0",
|
|
32
32
|
"html-react-parser": "^3.0.8",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"react": "^18.2.0",
|
|
40
40
|
"react-dom": "^18.2.0"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "1843b4632140d582af6a87606374cbd4fe25ad5c"
|
|
43
43
|
}
|
package/src/CdcDataBite.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import Loading from '@cdc/core/components/Loading'
|
|
|
11
11
|
import Title from '@cdc/core/components/ui/Title'
|
|
12
12
|
import CircleCallout from './components/CircleCallout'
|
|
13
13
|
import GradientBite from './components/GradientBite'
|
|
14
|
+
import Layout from '@cdc/core/components/Layout'
|
|
14
15
|
|
|
15
16
|
// external
|
|
16
17
|
import ResizeObserver from 'resize-observer-polyfill'
|
|
@@ -448,13 +449,75 @@ const CdcDataBite = (props: CdcDataBiteProps) => {
|
|
|
448
449
|
break
|
|
449
450
|
}
|
|
450
451
|
|
|
451
|
-
const
|
|
452
|
+
const missingRequiredSections = () => {
|
|
453
|
+
//Whether to show error message if something is required to show a data-bite and isn't filled in
|
|
454
|
+
return false
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const Error = () => {
|
|
458
|
+
const styles = {
|
|
459
|
+
position: 'absolute',
|
|
460
|
+
background: 'white',
|
|
461
|
+
zIndex: '999',
|
|
462
|
+
height: '100vh',
|
|
463
|
+
width: '100%',
|
|
464
|
+
display: 'flex',
|
|
465
|
+
justifyContent: 'center',
|
|
466
|
+
alignItems: 'center',
|
|
467
|
+
gridArea: 'content'
|
|
468
|
+
}
|
|
469
|
+
return (
|
|
470
|
+
<section className='waiting' style={styles}>
|
|
471
|
+
<section className='waiting-container'>
|
|
472
|
+
<h3>Error With Configuration</h3>
|
|
473
|
+
<p>{config.runtime.editorErrorMessage}</p>
|
|
474
|
+
</section>
|
|
475
|
+
</section>
|
|
476
|
+
)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const Confirm = () => {
|
|
480
|
+
const styles = {
|
|
481
|
+
position: 'absolute',
|
|
482
|
+
background: 'white',
|
|
483
|
+
zIndex: '999',
|
|
484
|
+
height: '100vh',
|
|
485
|
+
width: '100%',
|
|
486
|
+
display: 'flex',
|
|
487
|
+
justifyContent: 'center',
|
|
488
|
+
alignItems: 'center',
|
|
489
|
+
gridArea: 'content'
|
|
490
|
+
}
|
|
452
491
|
|
|
492
|
+
return (
|
|
493
|
+
<section className='waiting' style={styles}>
|
|
494
|
+
<section className='waiting-container'>
|
|
495
|
+
<h3>Finish Configuring</h3>
|
|
496
|
+
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
497
|
+
<button
|
|
498
|
+
className='btn'
|
|
499
|
+
style={{ margin: '1em auto' }}
|
|
500
|
+
disabled={missingRequiredSections()}
|
|
501
|
+
onClick={e => {
|
|
502
|
+
e.preventDefault()
|
|
503
|
+
updateConfig({ ...config, newViz: false })
|
|
504
|
+
}}
|
|
505
|
+
>
|
|
506
|
+
I'm Done
|
|
507
|
+
</button>
|
|
508
|
+
</section>
|
|
509
|
+
</section>
|
|
510
|
+
)
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const showBite = undefined !== dataColumn && undefined !== dataFunction
|
|
453
514
|
body = (
|
|
454
515
|
<>
|
|
455
516
|
{isEditor && <EditorPanel />}
|
|
456
|
-
<
|
|
457
|
-
<div className={
|
|
517
|
+
<Layout.Responsive isEditor={isEditor}>
|
|
518
|
+
<div className={`${contentClasses.join(' ')}`}>
|
|
519
|
+
{!config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error />}
|
|
520
|
+
{(!config.dataColumn || !config.dataFunction) && <Confirm />}
|
|
458
521
|
<Title config={config} title={title} isDashboard={isDashboard} classes={['bite-header', `${config.theme}`]} />
|
|
459
522
|
<div className={`bite ${biteClasses.join(' ')}`}>
|
|
460
523
|
<div className={`bite-content-container ${contentClasses.join(' ')}`}>
|
|
@@ -496,30 +559,27 @@ const CdcDataBite = (props: CdcDataBiteProps) => {
|
|
|
496
559
|
</div>
|
|
497
560
|
</div>
|
|
498
561
|
{link && link}
|
|
499
|
-
</
|
|
562
|
+
</Layout.Responsive>
|
|
500
563
|
</>
|
|
501
564
|
)
|
|
502
565
|
}
|
|
503
566
|
|
|
504
|
-
let classNames = ['cove', 'cdc-open-viz-module', 'type-data-bite', currentViewport, config.theme, 'font-' + config.fontSize]
|
|
505
|
-
if (isEditor) {
|
|
506
|
-
classNames.push('is-editor')
|
|
507
|
-
}
|
|
508
|
-
|
|
509
567
|
return (
|
|
510
568
|
<Context.Provider value={{ config, updateConfig, loading, data: config.data, setParentConfig, isDashboard }}>
|
|
511
569
|
{biteStyle !== 'gradient' && (
|
|
512
|
-
<
|
|
570
|
+
<Layout.VisualizationWrapper ref={outerContainerRef} config={config} isEditor={isEditor} showEditorPanel={config?.showEditorPanel}>
|
|
513
571
|
{body}
|
|
514
|
-
</
|
|
572
|
+
</Layout.VisualizationWrapper>
|
|
515
573
|
)}
|
|
516
574
|
{'gradient' === biteStyle && (
|
|
517
|
-
<
|
|
575
|
+
<Layout.VisualizationWrapper ref={outerContainerRef} config={config} isEditor={isEditor} showEditorPanel={config?.showEditorPanel}>
|
|
518
576
|
{isEditor && <EditorPanel />}
|
|
519
|
-
<
|
|
577
|
+
<Layout.Responsive isEditor={isEditor}>
|
|
578
|
+
{!config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error />}
|
|
579
|
+
{(!config.dataColumn || !config.dataFunction) && <Confirm />}
|
|
520
580
|
<GradientBite label={config.title} value={calculateDataBite()} />
|
|
521
|
-
</
|
|
522
|
-
</
|
|
581
|
+
</Layout.Responsive>
|
|
582
|
+
</Layout.VisualizationWrapper>
|
|
523
583
|
)}
|
|
524
584
|
</Context.Provider>
|
|
525
585
|
)
|
|
@@ -10,6 +10,7 @@ import Icon from '@cdc/core/components/ui/Icon'
|
|
|
10
10
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
11
11
|
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
12
12
|
import { BITE_LOCATIONS, DATA_FUNCTIONS, IMAGE_POSITIONS, DATA_OPERATORS } from '../CdcDataBite'
|
|
13
|
+
import Layout from '@cdc/core/components/Layout'
|
|
13
14
|
|
|
14
15
|
const TextField = memo(({ label, section = null, subsection = null, fieldName, updateField, value: stateValue, tooltip, type = 'input', i = null, min = null, max = null, ...attributes }) => {
|
|
15
16
|
const [value, setValue] = useState(stateValue)
|
|
@@ -129,7 +130,7 @@ const Select = memo(({ label, value, options, fieldName, section = null, subsect
|
|
|
129
130
|
const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
|
|
130
131
|
|
|
131
132
|
const EditorPanel = memo(() => {
|
|
132
|
-
const { config, updateConfig, loading, data, setParentConfig, isDashboard } = useContext(Context)
|
|
133
|
+
const { config, updateConfig, loading, data, setParentConfig, isDashboard, isEditor } = useContext(Context)
|
|
133
134
|
|
|
134
135
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
135
136
|
|
|
@@ -153,39 +154,10 @@ const EditorPanel = memo(() => {
|
|
|
153
154
|
|
|
154
155
|
const onBackClick = () => {
|
|
155
156
|
setDisplayPanel(!displayPanel)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
<section className='waiting'>
|
|
161
|
-
<section className='waiting-container'>
|
|
162
|
-
<h3>Error With Configuration</h3>
|
|
163
|
-
<p>{config.runtime.editorErrorMessage}</p>
|
|
164
|
-
</section>
|
|
165
|
-
</section>
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const Confirm = () => {
|
|
170
|
-
return (
|
|
171
|
-
<section className='waiting'>
|
|
172
|
-
<section className='waiting-container'>
|
|
173
|
-
<h3>Finish Configuring</h3>
|
|
174
|
-
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
175
|
-
<button
|
|
176
|
-
className='btn'
|
|
177
|
-
style={{ margin: '1em auto' }}
|
|
178
|
-
disabled={missingRequiredSections()}
|
|
179
|
-
onClick={e => {
|
|
180
|
-
e.preventDefault()
|
|
181
|
-
updateConfig({ ...config, newViz: false })
|
|
182
|
-
}}
|
|
183
|
-
>
|
|
184
|
-
I'm Done
|
|
185
|
-
</button>
|
|
186
|
-
</section>
|
|
187
|
-
</section>
|
|
188
|
-
)
|
|
157
|
+
updateConfig({
|
|
158
|
+
...config,
|
|
159
|
+
showEditorPanel: !displayPanel
|
|
160
|
+
})
|
|
189
161
|
}
|
|
190
162
|
|
|
191
163
|
const convertStateToConfig = () => {
|
|
@@ -302,11 +274,7 @@ const EditorPanel = memo(() => {
|
|
|
302
274
|
|
|
303
275
|
return (
|
|
304
276
|
<ErrorBoundary component='EditorPanel'>
|
|
305
|
-
|
|
306
|
-
{(!config.dataColumn || !config.dataFunction) && <Confirm />}
|
|
307
|
-
<button className={displayPanel ? `editor-toggle` : `editor-toggle collapsed`} title={displayPanel ? `Collapse Editor` : `Expand Editor`} onClick={onBackClick} />
|
|
308
|
-
<section className={displayPanel ? 'editor-panel cove' : 'hidden editor-panel cove'}>
|
|
309
|
-
<div className='heading-2'>Configure Data Bite</div>
|
|
277
|
+
<Layout.Sidebar isEditor={true} config={config} title='Configure Data Bites' onBackClick={onBackClick} displayPanel={displayPanel}>
|
|
310
278
|
<section className='form-container'>
|
|
311
279
|
<form>
|
|
312
280
|
<Accordion allowZeroExpanded={true}>
|
|
@@ -664,7 +632,7 @@ const EditorPanel = memo(() => {
|
|
|
664
632
|
</Accordion>
|
|
665
633
|
</form>
|
|
666
634
|
</section>
|
|
667
|
-
</
|
|
635
|
+
</Layout.Sidebar>
|
|
668
636
|
</ErrorBoundary>
|
|
669
637
|
)
|
|
670
638
|
})
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import '../scss/kpi.scss'
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import '../scss/kpi.scss'
|
|
3
3
|
|
|
4
|
-
export const KPIComponent = ({label, value}) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<span className="value"><strong>{value}</strong></span>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
4
|
+
export const KPIComponent = ({ label, value }) => {
|
|
5
|
+
return (
|
|
6
|
+
<div className='cove-component__content kpi-container'>
|
|
7
|
+
<div className='kpi-content'>
|
|
8
|
+
<div className='label-container'>
|
|
9
|
+
<span className='label'>
|
|
10
|
+
<strong>{label}</strong>
|
|
11
|
+
</span>
|
|
15
12
|
</div>
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
<div className='value-container'>
|
|
14
|
+
<span className='value'>
|
|
15
|
+
<strong>{value}</strong>
|
|
16
|
+
</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
18
22
|
|
|
19
|
-
export default KPIComponent
|
|
23
|
+
export default KPIComponent
|
package/src/scss/bite.scss
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
@import '../../../core/styles/variables';
|
|
2
2
|
|
|
3
|
-
&.is-editor {
|
|
4
|
-
position: relative;
|
|
5
|
-
.cove-component__inner {
|
|
6
|
-
margin: 3em auto 0;
|
|
7
|
-
max-width: 35em;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
3
|
&.theme-blue {
|
|
11
4
|
.bite-value {
|
|
12
5
|
color: $primary;
|
|
@@ -76,14 +69,27 @@
|
|
|
76
69
|
// TODO after v2 refactor remove header reference colors
|
|
77
70
|
// Use .font-color/.bg-color, etc. in color definitions or something similar
|
|
78
71
|
// Remove box shadows if we're no longer using them
|
|
79
|
-
.cove-
|
|
72
|
+
.sidebar + .cove-component__content .bite-content-container:not(.component--hide-background-color) {
|
|
73
|
+
margin: 3em auto 0;
|
|
74
|
+
max-width: 35em;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.sidebar + .cove-component__content .bite-content-container:not(.component--hide-background-color) {
|
|
78
|
+
background-color: white;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.cove-component__content {
|
|
80
82
|
// Visual: Shadow
|
|
81
83
|
&.shadow {
|
|
82
84
|
box-shadow: rgba(0, 0, 0, 0.2) 0 3px 10px;
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
.cove-component__inner {
|
|
88
|
+
padding: 1rem !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
// General: Bite Style > Graphic
|
|
86
|
-
|
|
92
|
+
&.bite__style--graphic {
|
|
87
93
|
.bite-content {
|
|
88
94
|
flex: 1;
|
|
89
95
|
}
|
|
@@ -135,7 +141,6 @@
|
|
|
135
141
|
border-top-left-radius: 3px;
|
|
136
142
|
border-top-right-radius: 3px;
|
|
137
143
|
}
|
|
138
|
-
|
|
139
144
|
.bite-content-container.component--hideBackgroundColor {
|
|
140
145
|
background: transparent;
|
|
141
146
|
}
|
|
@@ -231,7 +236,7 @@
|
|
|
231
236
|
|
|
232
237
|
.cove-component__content {
|
|
233
238
|
display: flex;
|
|
234
|
-
padding: 1em;
|
|
239
|
+
padding: 1em !important;
|
|
235
240
|
justify-content: space-between;
|
|
236
241
|
|
|
237
242
|
.bite-content {
|
package/src/scss/kpi.scss
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
.kpi-container {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
border-radius: 10px;
|
|
3
|
+
border: 1px solid rgba(0, 0, 0, 0.25) !important;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
|
|
6
|
+
display: flex;
|
|
7
|
+
padding: 5px !important;
|
|
8
|
+
height: 70px;
|
|
9
|
+
width: 100%;
|
|
10
|
+
position: relative;
|
|
11
|
+
display: flex;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
.kpi-content {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
background: linear-gradient(90deg, rgba(8, 132, 136, 1) 19%, rgba(255, 255, 255, 1) 74%);
|
|
16
|
+
border-radius: 10px;
|
|
17
|
+
display: flex;
|
|
18
|
+
flex: 1;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
.label-container,
|
|
20
22
|
.value-container {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
display: flex;
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: 100%;
|
|
26
|
+
align-items: center;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
.label-container {
|
|
28
|
-
|
|
29
|
+
.label-container {
|
|
30
|
+
padding-left: 30px !important;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
.value-container {
|
|
32
|
-
|
|
34
|
+
justify-content: center;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
.label {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
color: white;
|
|
39
|
+
font-size: 18px;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
42
|
.value {
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
color: brown;
|
|
44
|
+
font-size: 24px;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
|
|
47
47
|
//small
|
|
48
|
-
@media only screen and (min-width:768px) and (max-width:991px){
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
@media only screen and (min-width: 768px) and (max-width: 991px) {
|
|
49
|
+
.label {
|
|
50
|
+
font-size: 14px;
|
|
51
|
+
}
|
|
52
|
+
.value {
|
|
53
|
+
font-size: 20px;
|
|
54
|
+
}
|
|
55
55
|
}
|
|
56
56
|
//xs
|
|
57
|
-
@media only screen and (max-width:767px){
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
57
|
+
@media only screen and (max-width: 767px) {
|
|
58
|
+
.label-container {
|
|
59
|
+
justify-content: flex-start;
|
|
60
|
+
padding-left: 10px !important;
|
|
61
|
+
}
|
|
62
|
+
.label {
|
|
63
|
+
font-size: 10px;
|
|
64
|
+
}
|
|
65
|
+
.value {
|
|
66
|
+
font-size: 14px;
|
|
67
|
+
}
|
|
68
|
+
}
|