@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/data-bite",
3
- "version": "4.23.10-alpha",
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.10-alpha",
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": "47278535fb20bb4e6b3320f8075051bedc5bca8e"
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
- const CdcDataBite = props => {
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 [config, setConfig] = useState({ ...defaults })
34
- const [loading, setLoading] = useState(true)
35
-
36
- const {
37
- title,
38
- dataColumn,
39
- dataFunction,
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 { innerContainerClasses, contentClasses } = useDataVizClasses(config)
53
+ const [state, dispatch] = useReducer(dataBiteReducer, initialState)
51
54
 
52
- const transform = new DataTransform()
55
+ const { config, loading, currentViewport, coveLoadedHasRan, container } = state
53
56
 
54
- const [currentViewport, setCurrentViewport] = useState('lg')
57
+ const { title, dataColumn, dataFunction, imageData, biteBody, biteFontSize, dataFormat, biteStyle, filters, subtext } = config
55
58
 
56
- const [coveLoadedHasRan, setCoveLoadedHasRan] = useState(false)
59
+ const { innerContainerClasses, contentClasses } = useDataVizClasses(config)
57
60
 
58
- const [container, setContainer] = useState()
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
- setCurrentViewport(newViewport)
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
- setConfig(newConfig)
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
- setContainer(node)
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
- setCoveLoadedHasRan(true)
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 && <div className={`bite-header cove-component__header component__header ${config.theme}`}>{parse(title)}</div>}
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
@@ -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
+ }