@cdc/data-bite 4.23.10-alpha → 4.23.11
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 +4577 -4554
- package/package.json +3 -3
- package/src/{CdcDataBite.jsx → CdcDataBite.tsx} +33 -31
- package/src/_stories/DataBite.stories.tsx +35 -0
- package/src/scss/bite.scss +0 -79
- package/src/store/db.actions.ts +19 -0
- package/src/store/db.reducer.ts +32 -0
- package/src/types/Config.ts +39 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/data-bite",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.11",
|
|
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.23.
|
|
29
|
+
"@cdc/core": "^4.23.11",
|
|
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": "ecad213667a3cb96c921eaddba43a31c84caaa08"
|
|
43
43
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState, useCallback } from 'react'
|
|
1
|
+
import React, { useEffect, useState, useCallback, useReducer } from 'react'
|
|
2
2
|
import { Fragment } from 'react'
|
|
3
3
|
|
|
4
4
|
// contexts & initial state
|
|
@@ -8,6 +8,7 @@ import Context from './context'
|
|
|
8
8
|
// internal components
|
|
9
9
|
import EditorPanel from './components/EditorPanel'
|
|
10
10
|
import Loading from '@cdc/core/components/Loading'
|
|
11
|
+
import Title from '@cdc/core/components/ui/Title'
|
|
11
12
|
import CircleCallout from './components/CircleCallout'
|
|
12
13
|
|
|
13
14
|
// external
|
|
@@ -23,45 +24,47 @@ import { publish } from '@cdc/core/helpers/events'
|
|
|
23
24
|
import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
|
|
24
25
|
import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
|
|
25
26
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
27
|
+
import { Config } from './types/Config'
|
|
28
|
+
import dataBiteReducer from './store/db.reducer'
|
|
26
29
|
|
|
27
30
|
// styles
|
|
28
31
|
import './scss/main.scss'
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
type CdcDataBiteProps = {
|
|
34
|
+
config: Config
|
|
35
|
+
configUrl: string
|
|
36
|
+
isDashboard: boolean
|
|
37
|
+
isEditor: boolean
|
|
38
|
+
setConfig: () => {}
|
|
39
|
+
link: any
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const CdcDataBite = (props: CdcDataBiteProps) => {
|
|
31
43
|
const { configUrl, config: configObj, isDashboard = false, isEditor = false, setConfig: setParentConfig, link } = props
|
|
32
44
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
imageData,
|
|
41
|
-
biteBody,
|
|
42
|
-
biteFontSize,
|
|
43
|
-
dataFormat,
|
|
44
|
-
biteStyle,
|
|
45
|
-
filters,
|
|
46
|
-
subtext,
|
|
47
|
-
general: { isCompactStyle }
|
|
48
|
-
} = config
|
|
45
|
+
const initialState = {
|
|
46
|
+
config: configObj ?? defaults,
|
|
47
|
+
loading: true,
|
|
48
|
+
currentViewport: 'lg',
|
|
49
|
+
coveLoadedHasRan: false,
|
|
50
|
+
container: null
|
|
51
|
+
}
|
|
49
52
|
|
|
50
|
-
const
|
|
53
|
+
const [state, dispatch] = useReducer(dataBiteReducer, initialState)
|
|
51
54
|
|
|
52
|
-
const
|
|
55
|
+
const { config, loading, currentViewport, coveLoadedHasRan, container } = state
|
|
53
56
|
|
|
54
|
-
const
|
|
57
|
+
const { title, dataColumn, dataFunction, imageData, biteBody, biteFontSize, dataFormat, biteStyle, filters, subtext } = config
|
|
55
58
|
|
|
56
|
-
const
|
|
59
|
+
const { innerContainerClasses, contentClasses } = useDataVizClasses(config)
|
|
57
60
|
|
|
58
|
-
const
|
|
61
|
+
const transform = new DataTransform()
|
|
59
62
|
|
|
60
63
|
//Observes changes to outermost container and changes viewport size in state
|
|
61
64
|
const resizeObserver = new ResizeObserver(entries => {
|
|
62
65
|
for (let entry of entries) {
|
|
63
66
|
let newViewport = getViewport(entry.contentRect.width * 2) // Data bite is usually presented as small, so we scale it up for responsive calculations
|
|
64
|
-
|
|
67
|
+
dispatch({ type: 'SET_CURRENT_VIEWPORT', payload: newViewport })
|
|
65
68
|
}
|
|
66
69
|
})
|
|
67
70
|
|
|
@@ -79,7 +82,7 @@ const CdcDataBite = props => {
|
|
|
79
82
|
|
|
80
83
|
//Check things that are needed and set error messages if needed
|
|
81
84
|
newConfig.runtime.editorErrorMessage = ''
|
|
82
|
-
|
|
85
|
+
dispatch({ type: 'SET_CONFIG', payload: newConfig })
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
//@ts-ignore
|
|
@@ -108,8 +111,7 @@ const CdcDataBite = props => {
|
|
|
108
111
|
const processedConfig = { ...(await coveUpdateWorker(response)) }
|
|
109
112
|
|
|
110
113
|
updateConfig({ ...defaults, ...processedConfig })
|
|
111
|
-
|
|
112
|
-
setLoading(false)
|
|
114
|
+
dispatch({ type: 'SET_LOADING', payload: false })
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
const calculateDataBite = (includePrefixSuffix = true) => {
|
|
@@ -337,7 +339,7 @@ const CdcDataBite = props => {
|
|
|
337
339
|
if (node !== null) {
|
|
338
340
|
resizeObserver.observe(node)
|
|
339
341
|
}
|
|
340
|
-
|
|
342
|
+
dispatch({ type: 'SET_CONTAINER', payload: node })
|
|
341
343
|
}, [])
|
|
342
344
|
|
|
343
345
|
// Initial load
|
|
@@ -349,7 +351,7 @@ const CdcDataBite = props => {
|
|
|
349
351
|
useEffect(() => {
|
|
350
352
|
if (config && !coveLoadedHasRan && container) {
|
|
351
353
|
publish('cove_loaded', { config: config })
|
|
352
|
-
|
|
354
|
+
dispatch({ type: 'SET_COVE_LOADED_HAS_RAN', payload: true })
|
|
353
355
|
}
|
|
354
356
|
}, [config, container])
|
|
355
357
|
|
|
@@ -452,7 +454,7 @@ const CdcDataBite = props => {
|
|
|
452
454
|
{isEditor && <EditorPanel />}
|
|
453
455
|
<div className={isEditor ? 'spacing-wrapper' : ''}>
|
|
454
456
|
<div className={innerContainerClasses.join(' ')}>
|
|
455
|
-
{title
|
|
457
|
+
<Title config={config} title={title} isDashboard={isDashboard} classes={['bite-header', `${config.theme}`]} />
|
|
456
458
|
<div className={`bite ${biteClasses.join(' ')}`}>
|
|
457
459
|
<div className={`bite-content-container ${contentClasses.join(' ')}`}>
|
|
458
460
|
{showBite && 'graphic' === biteStyle && isTop && <CircleCallout theme={config.theme} text={calculateDataBite()} biteFontSize={biteFontSize} dataFormat={dataFormat} />}
|
|
@@ -483,7 +485,7 @@ const CdcDataBite = props => {
|
|
|
483
485
|
{calculateDataBite()}
|
|
484
486
|
</span>
|
|
485
487
|
)}
|
|
486
|
-
{subtext && !isCompactStyle && <p className='bite-subtext'>{parse(subtext)}</p>}
|
|
488
|
+
{subtext && !config.general.isCompactStyle && <p className='bite-subtext'>{parse(subtext)}</p>}
|
|
487
489
|
</div>
|
|
488
490
|
</Fragment>
|
|
489
491
|
</div>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import DataBite from '../CdcDataBite'
|
|
3
|
+
import { Config } from '../types/Config'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof DataBite> = {
|
|
6
|
+
title: 'Components/Templates/Data Bite',
|
|
7
|
+
component: DataBite
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj<typeof DataBite>
|
|
11
|
+
|
|
12
|
+
export const Data_Bite_Circle_Average: Story = {
|
|
13
|
+
args: {
|
|
14
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Average.json'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Data_Bite_Text_Max_Pic: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Max_Pic.json'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const Data_Bite_Circle_Sum: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Sum.json'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export const Data_Bite_Text_Average_Pic: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Average_Pic.json'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default meta
|
package/src/scss/bite.scss
CHANGED
|
@@ -11,111 +11,66 @@
|
|
|
11
11
|
.bite-value {
|
|
12
12
|
color: $primary;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
.cove-component__header {
|
|
16
|
-
background-color: $primary;
|
|
17
|
-
}
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
&.theme-purple {
|
|
21
17
|
.bite-value {
|
|
22
18
|
color: $purple-primary;
|
|
23
19
|
}
|
|
24
|
-
.cove-component__header {
|
|
25
|
-
background-color: $purple-primary;
|
|
26
|
-
}
|
|
27
20
|
}
|
|
28
21
|
|
|
29
22
|
&.theme-amber {
|
|
30
23
|
.bite-value {
|
|
31
24
|
color: $amber-primary;
|
|
32
25
|
}
|
|
33
|
-
.cove-component__header {
|
|
34
|
-
background-color: $amber-primary;
|
|
35
|
-
}
|
|
36
26
|
}
|
|
37
27
|
|
|
38
28
|
&.theme-orange {
|
|
39
29
|
.bite-value {
|
|
40
30
|
color: $orange-primary;
|
|
41
31
|
}
|
|
42
|
-
.cove-component__header {
|
|
43
|
-
background-color: $orange-primary;
|
|
44
|
-
}
|
|
45
32
|
}
|
|
46
33
|
|
|
47
34
|
&.theme-brown {
|
|
48
35
|
.bite-value {
|
|
49
36
|
color: $brown-primary;
|
|
50
37
|
}
|
|
51
|
-
.cove-component__header {
|
|
52
|
-
background-color: $brown-primary;
|
|
53
|
-
}
|
|
54
38
|
}
|
|
55
39
|
|
|
56
40
|
&.theme-teal {
|
|
57
41
|
.bite-value {
|
|
58
42
|
color: $teal-primary;
|
|
59
43
|
}
|
|
60
|
-
.cove-component__header {
|
|
61
|
-
background-color: $teal-primary;
|
|
62
|
-
}
|
|
63
44
|
}
|
|
64
45
|
|
|
65
46
|
&.theme-pink {
|
|
66
47
|
.bite-value {
|
|
67
48
|
color: $pink-primary;
|
|
68
49
|
}
|
|
69
|
-
.cove-component__header {
|
|
70
|
-
background-color: $pink-primary;
|
|
71
|
-
}
|
|
72
50
|
}
|
|
73
51
|
|
|
74
52
|
&.theme-slate {
|
|
75
53
|
.bite-value {
|
|
76
54
|
color: $slate-primary;
|
|
77
55
|
}
|
|
78
|
-
.cove-component__header {
|
|
79
|
-
background-color: $slate-primary;
|
|
80
|
-
}
|
|
81
56
|
}
|
|
82
57
|
|
|
83
58
|
&.theme-indigo {
|
|
84
59
|
.bite-value {
|
|
85
60
|
color: $indigo-primary;
|
|
86
61
|
}
|
|
87
|
-
.cove-component__header {
|
|
88
|
-
background-color: $indigo-primary;
|
|
89
|
-
}
|
|
90
62
|
}
|
|
91
63
|
|
|
92
64
|
&.theme-cyan {
|
|
93
65
|
.bite-value {
|
|
94
66
|
color: $cyan-primary;
|
|
95
67
|
}
|
|
96
|
-
.cove-component__header {
|
|
97
|
-
background-color: $cyan-primary;
|
|
98
|
-
}
|
|
99
68
|
}
|
|
100
69
|
|
|
101
70
|
&.theme-green {
|
|
102
71
|
.bite-value {
|
|
103
72
|
color: $green-primary;
|
|
104
73
|
}
|
|
105
|
-
.cove-component__header {
|
|
106
|
-
background-color: $green-primary;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
.cove-component__header {
|
|
110
|
-
padding: 0 1em;
|
|
111
|
-
left: 0;
|
|
112
|
-
top: 0;
|
|
113
|
-
padding: 0.6rem 0.8rem;
|
|
114
|
-
color: white;
|
|
115
|
-
font-size: 1.1em;
|
|
116
|
-
&:empty {
|
|
117
|
-
min-height: 5px;
|
|
118
|
-
}
|
|
119
74
|
}
|
|
120
75
|
|
|
121
76
|
// TODO after v2 refactor remove header reference colors
|
|
@@ -200,100 +155,66 @@
|
|
|
200
155
|
.bite-value {
|
|
201
156
|
color: $primary;
|
|
202
157
|
}
|
|
203
|
-
|
|
204
|
-
.cove-component__header {
|
|
205
|
-
background-color: $primary;
|
|
206
|
-
}
|
|
207
158
|
}
|
|
208
159
|
|
|
209
160
|
&.theme-purple {
|
|
210
161
|
.bite-value {
|
|
211
162
|
color: $purple-primary;
|
|
212
163
|
}
|
|
213
|
-
.cove-component__header {
|
|
214
|
-
background-color: $purple-primary;
|
|
215
|
-
}
|
|
216
164
|
}
|
|
217
165
|
|
|
218
166
|
&.theme-amber {
|
|
219
167
|
.bite-value {
|
|
220
168
|
color: $amber-primary;
|
|
221
169
|
}
|
|
222
|
-
.cove-component__header {
|
|
223
|
-
background-color: $amber-primary;
|
|
224
|
-
}
|
|
225
170
|
}
|
|
226
171
|
|
|
227
172
|
&.theme-orange {
|
|
228
173
|
.bite-value {
|
|
229
174
|
color: $orange-primary;
|
|
230
175
|
}
|
|
231
|
-
.cove-component__header {
|
|
232
|
-
background-color: $orange-primary;
|
|
233
|
-
}
|
|
234
176
|
}
|
|
235
177
|
|
|
236
178
|
&.theme-brown {
|
|
237
179
|
.bite-value {
|
|
238
180
|
color: $brown-primary;
|
|
239
181
|
}
|
|
240
|
-
.cove-component__header {
|
|
241
|
-
background-color: $brown-primary;
|
|
242
|
-
}
|
|
243
182
|
}
|
|
244
183
|
|
|
245
184
|
&.theme-teal {
|
|
246
185
|
.bite-value {
|
|
247
186
|
color: $teal-primary;
|
|
248
187
|
}
|
|
249
|
-
.cove-component__header {
|
|
250
|
-
background-color: $teal-primary;
|
|
251
|
-
}
|
|
252
188
|
}
|
|
253
189
|
|
|
254
190
|
&.theme-pink {
|
|
255
191
|
.bite-value {
|
|
256
192
|
color: $pink-primary;
|
|
257
193
|
}
|
|
258
|
-
.cove-component__header {
|
|
259
|
-
background-color: $pink-primary;
|
|
260
|
-
}
|
|
261
194
|
}
|
|
262
195
|
|
|
263
196
|
&.theme-slate {
|
|
264
197
|
.bite-value {
|
|
265
198
|
color: $slate-primary;
|
|
266
199
|
}
|
|
267
|
-
.cove-component__header {
|
|
268
|
-
background-color: $slate-primary;
|
|
269
|
-
}
|
|
270
200
|
}
|
|
271
201
|
|
|
272
202
|
&.theme-indigo {
|
|
273
203
|
.bite-value {
|
|
274
204
|
color: $indigo-primary;
|
|
275
205
|
}
|
|
276
|
-
.cove-component__header {
|
|
277
|
-
background-color: $indigo-primary;
|
|
278
|
-
}
|
|
279
206
|
}
|
|
280
207
|
|
|
281
208
|
&.theme-cyan {
|
|
282
209
|
.bite-value {
|
|
283
210
|
color: $cyan-primary;
|
|
284
211
|
}
|
|
285
|
-
.cove-component__header {
|
|
286
|
-
background-color: $cyan-primary;
|
|
287
|
-
}
|
|
288
212
|
}
|
|
289
213
|
|
|
290
214
|
&.theme-green {
|
|
291
215
|
.bite-value {
|
|
292
216
|
color: $green-primary;
|
|
293
217
|
}
|
|
294
|
-
.cove-component__header {
|
|
295
|
-
background-color: $green-primary;
|
|
296
|
-
}
|
|
297
218
|
}
|
|
298
219
|
|
|
299
220
|
h3 {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config } from '../types/Config'
|
|
2
|
+
|
|
3
|
+
type Action<T, P> = { type: T; payload: P }
|
|
4
|
+
|
|
5
|
+
type SET_CONFIG = Action<'SET_CONFIG', Config>
|
|
6
|
+
type SET_LOADING = Action<'SET_LOADING', boolean>
|
|
7
|
+
type SET_CURRENT_VIEWPORT = Action<'SET_CURRENT_VIEWPORT', string>
|
|
8
|
+
type SET_COVE_LOADED_HAS_RAN = Action<'SET_COVE_LOADED_HAS_RAN', boolean>
|
|
9
|
+
type SET_CONTAINER = Action<'SET_CONTAINER', any>
|
|
10
|
+
|
|
11
|
+
// prettier-ignore
|
|
12
|
+
type DataBiteActions =
|
|
13
|
+
| SET_CONFIG
|
|
14
|
+
| SET_LOADING
|
|
15
|
+
| SET_CURRENT_VIEWPORT
|
|
16
|
+
| SET_COVE_LOADED_HAS_RAN
|
|
17
|
+
| SET_CONTAINER
|
|
18
|
+
|
|
19
|
+
export default DataBiteActions
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Config } from '../types/Config'
|
|
2
|
+
import DataBiteActions from './db.actions'
|
|
3
|
+
|
|
4
|
+
export type DataBiteState = {
|
|
5
|
+
config?: Config
|
|
6
|
+
loading: boolean
|
|
7
|
+
currentViewport: string
|
|
8
|
+
coveLoadedHasRan: boolean
|
|
9
|
+
container: any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const reducer = (state: DataBiteState, action: DataBiteActions): DataBiteState => {
|
|
13
|
+
switch (action.type) {
|
|
14
|
+
case 'SET_CONFIG': {
|
|
15
|
+
return { ...state, config: action.payload }
|
|
16
|
+
}
|
|
17
|
+
case 'SET_LOADING': {
|
|
18
|
+
return { ...state, loading: action.payload }
|
|
19
|
+
}
|
|
20
|
+
case 'SET_CURRENT_VIEWPORT': {
|
|
21
|
+
return { ...state, currentViewport: action.payload }
|
|
22
|
+
}
|
|
23
|
+
case 'SET_COVE_LOADED_HAS_RAN': {
|
|
24
|
+
return { ...state, coveLoadedHasRan: action.payload }
|
|
25
|
+
}
|
|
26
|
+
case 'SET_CONTAINER': {
|
|
27
|
+
return { ...state, container: action.payload }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default reducer
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type Config = {
|
|
2
|
+
type: string
|
|
3
|
+
data: Object[]
|
|
4
|
+
dataBite: string
|
|
5
|
+
dataFunction: string
|
|
6
|
+
dataColumn: string
|
|
7
|
+
bitePosition: string
|
|
8
|
+
biteFontSize: number
|
|
9
|
+
fontSize: string
|
|
10
|
+
biteBody: string
|
|
11
|
+
imageData: {
|
|
12
|
+
display: string
|
|
13
|
+
url: string
|
|
14
|
+
alt: string
|
|
15
|
+
options: Object[]
|
|
16
|
+
}
|
|
17
|
+
dataFormat: {
|
|
18
|
+
roundToPlace: number
|
|
19
|
+
commas: boolean
|
|
20
|
+
prefix: string
|
|
21
|
+
suffix: string
|
|
22
|
+
}
|
|
23
|
+
biteStyle: string
|
|
24
|
+
filters: Object[]
|
|
25
|
+
subtext: string
|
|
26
|
+
title: string
|
|
27
|
+
theme: string
|
|
28
|
+
shadow: boolean
|
|
29
|
+
visual: {
|
|
30
|
+
border: boolean
|
|
31
|
+
accent: boolean
|
|
32
|
+
background: boolean
|
|
33
|
+
hideBackgroundColor: boolean
|
|
34
|
+
borderColorTheme: boolean
|
|
35
|
+
}
|
|
36
|
+
general: {
|
|
37
|
+
isCompactStyle: boolean
|
|
38
|
+
}
|
|
39
|
+
}
|