@cdc/data-bite 1.1.4 → 4.22.10
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/cdcdatabite.js +8 -8
- package/examples/gallery/calculated-average.json +3167 -0
- package/examples/gallery/calculated-with-pic.json +3173 -0
- package/examples/gallery/max-value.json +3167 -0
- package/examples/gallery/sum-of-data.json +3161 -0
- package/examples/private/double.json +0 -0
- package/examples/private/totals.json +1 -0
- package/package.json +3 -3
- package/src/CdcDataBite.tsx +55 -100
- package/src/components/EditorPanel.js +549 -173
- package/src/index.html +11 -2
- package/src/scss/bite.scss +99 -37
- package/src/scss/editor-panel.scss +0 -1
- package/src/scss/main.scss +10 -2
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"dashboard":{"theme":"theme-blue","title":"Total Vaccine Doses Administered","description":"Total vaccine doses administered data are updated every Wednesday as soon as they are reviewed and verified.\n<br>\nInformation about the number of vials shipped is posted on <a href=\"https://aspr.hhs.gov/SNS/Pages/JYNNEOS-Distribution.aspx\">https://aspr.hhs.gov/SNS/Pages/JYNNEOS-Distribution.aspx</a>, and is updated every Monday, Wednesday, and Friday.\n"},"rows":[[{"width":12,"widget":"data-bite1661201913029"},{},{}]],"visualizations":{"data-bite1661201911110":{"type":"data-bite","data":[{"Vaccines Distributed":null,"Vaccines Administered":803596,"Doses Shipped Date":null,"AsOf":" Data as of September 27 2022 4:00 AM EDT"}],"dataBite":"","dataFunction":"Sum","dataColumn":"Vaccines Distributed","bitePosition":"Left","biteFontSize":24,"fontSize":"small","biteBody":"<br><span class=\"h5\">Vials Shipped to all U.S. Jurisdictions</span>","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"body","filters":[],"subtext":"","title":"","theme":"theme-blue","shadow":false,"newViz":true,"uid":"data-bite1661201911110","visualizationType":"data-bite"},"data-bite1661201913029":{"type":"data-bite","data":[{"Vaccines Distributed":null,"Vaccines Administered":803596,"Doses Shipped Date":null,"AsOf":" Data as of September 27 2022 4:00 AM EDT"}],"dataBite":"","dataFunction":"Sum","dataColumn":"Vaccines Administered","bitePosition":"Left","biteFontSize":24,"fontSize":"small","biteBody":"<br><span class=\"h5\">Doses Administered in the 54 U.S. Jurisdictions Reporting Data<span id=\"administered_date\"> as of October 4, 2022.","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"body","filters":[],"subtext":"","title":"","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"newViz":true,"uid":"data-bite1661201913029","visualizationType":"data-bite","editing":true}},"table":{"label":"Data Table","show":false},"data":[{"Vaccines Distributed":null,"Vaccines Administered":803596,"Doses Shipped Date":null,"AsOf":" Data as of September 27 2022 4:00 AM EDT"}],"dataFileName":"https://www.cdc.gov/wcms/vizdata/poxvirus/monkeypox/data/vaccines/mpx_vaccine_databites.csv","dataFileSourceType":"url","dataUrl":"https://www.cdc.gov/wcms/vizdata/poxvirus/monkeypox/data/vaccines/mpx_vaccine_databites.csv","type":"dashboard","orientation":null,"visualizationSubType":null,"runtime":{},"uuid":1661454522321}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/data-bite",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.22.10",
|
|
4
4
|
"description": "React component for displaying a single piece of data in a card module",
|
|
5
5
|
"main": "dist/cdcdatabite",
|
|
6
6
|
"scripts": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@cdc/core": "^
|
|
23
|
+
"@cdc/core": "^4.22.10",
|
|
24
24
|
"chroma": "0.0.1",
|
|
25
25
|
"chroma-js": "^2.1.0",
|
|
26
26
|
"html-react-parser": "1.4.9",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"resolutions": {
|
|
40
40
|
"@types/react": "17.x"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "a7eb551a98c7363d3be58cb81dfc8bbc00522804"
|
|
43
43
|
}
|
package/src/CdcDataBite.tsx
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import React, { useEffect, useState, useCallback,FC } from 'react';
|
|
1
|
+
import React, { useEffect, useState, useCallback,FC, memo } from 'react';
|
|
2
2
|
import EditorPanel from './components/EditorPanel';
|
|
3
3
|
import defaults from './data/initial-state';
|
|
4
4
|
import Loading from '@cdc/core/components/Loading';
|
|
5
5
|
import getViewport from '@cdc/core/helpers/getViewport';
|
|
6
6
|
import ResizeObserver from 'resize-observer-polyfill';
|
|
7
|
-
import Papa from 'papaparse';
|
|
8
7
|
import parse from 'html-react-parser';
|
|
9
8
|
|
|
10
9
|
import Context from './context';
|
|
11
|
-
|
|
12
|
-
import DataTransform from '@cdc/core/components/DataTransform';
|
|
10
|
+
import { DataTransform } from '@cdc/core/helpers/DataTransform';
|
|
13
11
|
import CircleCallout from './components/CircleCallout';
|
|
14
12
|
import './scss/main.scss';
|
|
15
13
|
import numberFromString from '@cdc/core/helpers/numberFromString';
|
|
14
|
+
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData';
|
|
16
15
|
import { Fragment } from 'react';
|
|
17
16
|
|
|
18
17
|
import { publish } from '@cdc/core/helpers/events'
|
|
18
|
+
import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses';
|
|
19
|
+
import cacheBustingString from '@cdc/core/helpers/cacheBustingString';
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
type DefaultsType = typeof defaults
|
|
@@ -25,10 +26,11 @@ interface Props{
|
|
|
25
26
|
isDashboard?: boolean
|
|
26
27
|
isEditor?: boolean
|
|
27
28
|
setConfig?:any
|
|
29
|
+
link?:any
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const CdcDataBite:FC<Props> = (props) => {
|
|
31
|
-
const { configUrl, config: configObj, isDashboard = false, isEditor = false, setConfig: setParentConfig } = props
|
|
33
|
+
const { configUrl, config: configObj, isDashboard = false, isEditor = false, setConfig: setParentConfig,link } = props
|
|
32
34
|
|
|
33
35
|
const [config, setConfig] = useState<DefaultsType>({...defaults});
|
|
34
36
|
const [loading, setLoading] = useState<Boolean>(true);
|
|
@@ -47,6 +49,7 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
47
49
|
general: { isCompactStyle }
|
|
48
50
|
} = config;
|
|
49
51
|
|
|
52
|
+
const { innerContainerClasses, contentClasses } = useDataVizClasses(config);
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
const transform = new DataTransform()
|
|
@@ -65,44 +68,6 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
65
68
|
}
|
|
66
69
|
});
|
|
67
70
|
|
|
68
|
-
const fetchRemoteData = async (url) => {
|
|
69
|
-
try {
|
|
70
|
-
const urlObj = new URL(url);
|
|
71
|
-
const regex = /(?:\.([^.]+))?$/
|
|
72
|
-
|
|
73
|
-
let data = []
|
|
74
|
-
|
|
75
|
-
const ext = (regex.exec(urlObj.pathname)[1])
|
|
76
|
-
if ('csv' === ext) {
|
|
77
|
-
data = await fetch(url)
|
|
78
|
-
.then(response => response.text())
|
|
79
|
-
.then(responseText => {
|
|
80
|
-
const parsedCsv = Papa.parse(responseText, {
|
|
81
|
-
header: true,
|
|
82
|
-
dynamicTyping: true,
|
|
83
|
-
skipEmptyLines: true
|
|
84
|
-
})
|
|
85
|
-
return parsedCsv.data
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if ('json' === ext) {
|
|
90
|
-
data = await fetch(url)
|
|
91
|
-
.then(response => response.json())
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return data;
|
|
95
|
-
} catch {
|
|
96
|
-
// If we can't parse it, still attempt to fetch it
|
|
97
|
-
try {
|
|
98
|
-
let response = await (await fetch(configUrl)).json()
|
|
99
|
-
return response
|
|
100
|
-
} catch {
|
|
101
|
-
console.error(`Cannot parse URL: ${url}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
71
|
const updateConfig = (newConfig) => {
|
|
107
72
|
// Deeper copy
|
|
108
73
|
Object.keys(defaults).forEach(key => {
|
|
@@ -123,15 +88,14 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
123
88
|
const loadConfig = async () => {
|
|
124
89
|
let response = configObj || await (await fetch(configUrl)).json();
|
|
125
90
|
|
|
126
|
-
|
|
127
|
-
const date = new Date();
|
|
128
|
-
let cacheBustingString = new Date(date.getTime() - (date.getTime() % round)).toISOString();
|
|
91
|
+
|
|
129
92
|
|
|
130
93
|
// If data is included through a URL, fetch that and store
|
|
131
94
|
let responseData = response.data ?? {}
|
|
132
95
|
|
|
133
96
|
if (response.dataUrl) {
|
|
134
|
-
|
|
97
|
+
|
|
98
|
+
response.dataUrl = `${response.dataUrl}?${cacheBustingString()}`;
|
|
135
99
|
let newData = await fetchRemoteData(response.dataUrl)
|
|
136
100
|
|
|
137
101
|
if (newData && response.dataDescription) {
|
|
@@ -151,11 +115,11 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
151
115
|
setLoading(false);
|
|
152
116
|
}
|
|
153
117
|
|
|
154
|
-
const calculateDataBite = ():string|number => {
|
|
155
|
-
|
|
118
|
+
const calculateDataBite = (includePrefixSuffix:boolean = true):string|number => {
|
|
119
|
+
|
|
156
120
|
//If either the column or function aren't set, do not calculate
|
|
157
121
|
if (!dataColumn || !dataFunction) {
|
|
158
|
-
return '';
|
|
122
|
+
return '';
|
|
159
123
|
}
|
|
160
124
|
|
|
161
125
|
|
|
@@ -164,8 +128,8 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
164
128
|
if(value === undefined || value===null){
|
|
165
129
|
console.error('Enter correct value to "applyPrecision()" function ')
|
|
166
130
|
return ;
|
|
167
|
-
}
|
|
168
|
-
// second validation
|
|
131
|
+
}
|
|
132
|
+
// second validation
|
|
169
133
|
if(Number.isNaN(value)){
|
|
170
134
|
console.error(' Argunment isNaN, "applyPrecision()" function ')
|
|
171
135
|
return;
|
|
@@ -200,6 +164,7 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
200
164
|
return;
|
|
201
165
|
}
|
|
202
166
|
// second validation
|
|
167
|
+
console.log('arr', arr)
|
|
203
168
|
if(arr.length === 0 || !Array.isArray(arr)){
|
|
204
169
|
console.error('Arguments are not valid getColumnSum function ')
|
|
205
170
|
return;
|
|
@@ -218,9 +183,13 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
218
183
|
// first validation
|
|
219
184
|
if(arr===undefined || arr===null ||!Array.isArray(arr)){
|
|
220
185
|
console.error('Enter valid parameter getColumnMean function')
|
|
221
|
-
return
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if(config.dataFormat.ignoreZeros) {
|
|
190
|
+
arr = arr.filter( num => num !== 0 )
|
|
222
191
|
}
|
|
223
|
-
|
|
192
|
+
|
|
224
193
|
let mean:number = 0
|
|
225
194
|
if(arr.length > 1){
|
|
226
195
|
/// first convert each element to number then add using reduce method to escape string concatination.
|
|
@@ -284,13 +253,9 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
284
253
|
}
|
|
285
254
|
return formattedValue
|
|
286
255
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
256
|
|
|
292
257
|
let dataBite:string|number = '';
|
|
293
|
-
|
|
258
|
+
|
|
294
259
|
//Optionally filter the data based on the user's filter
|
|
295
260
|
let filteredData = config.data;
|
|
296
261
|
|
|
@@ -304,18 +269,17 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
304
269
|
}
|
|
305
270
|
});
|
|
306
271
|
|
|
307
|
-
let numericalData:any[] = []
|
|
308
|
-
|
|
272
|
+
let numericalData:any[] = [];
|
|
273
|
+
// Get the column's data
|
|
274
|
+
if(filteredData.length){
|
|
275
|
+
filteredData.forEach(row => {
|
|
276
|
+
let value = numberFromString(row[dataColumn])
|
|
277
|
+
if(typeof value === 'number') numericalData.push(value)
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
numericalData = config.data.map( item => Number( item[config.dataColumn] ));
|
|
281
|
+
}
|
|
309
282
|
|
|
310
|
-
// Get the column's data
|
|
311
|
-
if(filteredData.length){
|
|
312
|
-
filteredData.forEach(row => {
|
|
313
|
-
let value = numberFromString(row[dataColumn])
|
|
314
|
-
if(typeof value === 'number') numericalData.push(value)
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
283
|
|
|
320
284
|
switch (dataFunction) {
|
|
321
285
|
case DATA_FUNCTION_COUNT:
|
|
@@ -348,7 +312,7 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
348
312
|
rangeMin = applyLocaleString(rangeMin)
|
|
349
313
|
rangeMax = applyLocaleString(rangeMax)
|
|
350
314
|
}
|
|
351
|
-
dataBite = config.dataFormat.prefix + rangeMin + config.dataFormat.suffix + ' - ' + config.dataFormat.prefix + rangeMax+config.dataFormat.suffix;
|
|
315
|
+
dataBite = config.dataFormat.prefix + rangeMin + config.dataFormat.suffix + ' - ' + config.dataFormat.prefix + rangeMax+config.dataFormat.suffix;
|
|
352
316
|
break;
|
|
353
317
|
default:
|
|
354
318
|
console.warn('Data bite function not recognized: ' + dataFunction);
|
|
@@ -357,37 +321,22 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
357
321
|
// If not the range, then round and format here
|
|
358
322
|
if (dataFunction !== DATA_FUNCTION_RANGE) {
|
|
359
323
|
dataBite = applyPrecision(dataBite);
|
|
360
|
-
|
|
324
|
+
|
|
361
325
|
if (config.dataFormat.commas) {
|
|
362
326
|
dataBite = applyLocaleString(dataBite)
|
|
363
327
|
}
|
|
364
|
-
// Optional
|
|
328
|
+
// Optional
|
|
365
329
|
// return config.dataFormat.prefix + dataBite + config.dataFormat.suffix;
|
|
366
330
|
|
|
367
|
-
return dataFormat.prefix + dataBite + dataFormat.suffix
|
|
331
|
+
return includePrefixSuffix ? (dataFormat.prefix + dataBite + dataFormat.suffix) : dataBite
|
|
368
332
|
} else {
|
|
369
333
|
//Rounding and formatting for ranges happens earlier.
|
|
370
334
|
|
|
371
|
-
return dataFormat.prefix + dataBite + dataFormat.suffix
|
|
335
|
+
return includePrefixSuffix ? (dataFormat.prefix + dataBite + dataFormat.suffix) : dataBite
|
|
372
336
|
}
|
|
373
337
|
}
|
|
374
338
|
|
|
375
|
-
let innerContainerClasses = ['cove-component__inner']
|
|
376
|
-
config.title && innerContainerClasses.push('component--has-title')
|
|
377
|
-
config.subtext && innerContainerClasses.push('component--has-subtext')
|
|
378
|
-
config.biteStyle && innerContainerClasses.push(`bite__style--${config.biteStyle}`)
|
|
379
|
-
config.general?.isCompactStyle && innerContainerClasses.push(`component--isCompactStyle`)
|
|
380
|
-
|
|
381
|
-
let contentClasses = ['cove-component__content'];
|
|
382
|
-
!config.visual?.border && contentClasses.push('no-borders');
|
|
383
|
-
config.visual?.borderColorTheme && contentClasses.push('component--has-borderColorTheme');
|
|
384
|
-
config.visual?.accent && contentClasses.push('component--has-accent');
|
|
385
|
-
config.visual?.background && contentClasses.push('component--has-background');
|
|
386
|
-
config.visual?.hideBackgroundColor && contentClasses.push('component--hideBackgroundColor');
|
|
387
339
|
|
|
388
|
-
// ! these two will be retired.
|
|
389
|
-
config.shadow && innerContainerClasses.push('shadow')
|
|
390
|
-
config?.visual?.roundedBorders && innerContainerClasses.push('bite--has-rounded-borders')
|
|
391
340
|
|
|
392
341
|
// Load data when component first mounts
|
|
393
342
|
const outerContainerRef = useCallback(node => {
|
|
@@ -411,7 +360,7 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
411
360
|
}
|
|
412
361
|
}, [config, container]);
|
|
413
362
|
|
|
414
|
-
if(configObj && config && configObj.data !== config.data){
|
|
363
|
+
if(configObj && config && JSON.stringify(configObj.data) !== JSON.stringify(config.data)){
|
|
415
364
|
loadConfig();
|
|
416
365
|
}
|
|
417
366
|
|
|
@@ -430,7 +379,7 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
430
379
|
let imageAlt = imageData.alt
|
|
431
380
|
|
|
432
381
|
if ('dynamic' === imageData.display && imageData.options && imageData.options?.length > 0) {
|
|
433
|
-
let targetVal = Number(calculateDataBite())
|
|
382
|
+
let targetVal = Number(calculateDataBite(false))
|
|
434
383
|
let argumentActive = false
|
|
435
384
|
|
|
436
385
|
imageData.options.forEach((option, index) => {
|
|
@@ -487,28 +436,30 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
487
436
|
break;
|
|
488
437
|
}
|
|
489
438
|
|
|
490
|
-
if(config.shadow) biteClasses.push('shadow')
|
|
491
|
-
|
|
492
439
|
const showBite = undefined !== dataColumn && undefined !== dataFunction;
|
|
493
440
|
|
|
494
441
|
body = (
|
|
495
442
|
<>
|
|
496
443
|
{isEditor && <EditorPanel />}
|
|
497
444
|
<div className={isEditor ? 'spacing-wrapper' : ''}>
|
|
498
|
-
<div className=
|
|
499
|
-
{title && <div className={`bite-header component__header ${config.theme}`}>{parse(title)}</div>}
|
|
500
|
-
<div className={`bite ${biteClasses.join(' ')}
|
|
501
|
-
<div className={`bite-content-container ${
|
|
445
|
+
<div className={innerContainerClasses.join(' ')}>
|
|
446
|
+
{title && <div className={`bite-header cove-component__header component__header ${config.theme}`}>{parse(title)}</div>}
|
|
447
|
+
<div className={`bite ${biteClasses.join(' ')}`}>
|
|
448
|
+
<div className={`bite-content-container ${contentClasses.join(' ')}` }>
|
|
502
449
|
{showBite && 'graphic' === biteStyle && isTop && <CircleCallout theme={config.theme} text={calculateDataBite()} biteFontSize={biteFontSize} dataFormat={dataFormat} /> }
|
|
503
450
|
{isTop && <DataImage />}
|
|
504
451
|
<div className={`bite-content`}>
|
|
505
|
-
{showBite && 'title' === biteStyle && <div className="bite-value
|
|
452
|
+
{showBite && 'title' === biteStyle && <div className="bite-value" style={{fontSize: biteFontSize + 'px'}}>{calculateDataBite()}</div>}
|
|
453
|
+
{showBite && 'split' === biteStyle && <div className="bite-value" style={{fontSize: biteFontSize + 'px'}}>{calculateDataBite()}</div>}
|
|
506
454
|
<Fragment>
|
|
455
|
+
<div className="bite-content__text-wrap">
|
|
507
456
|
<p className="bite-text">
|
|
508
457
|
{showBite && 'body' === biteStyle && <span className="bite-value data-bite-body" style={{fontSize: biteFontSize + 'px'}}>{calculateDataBite()}</span>}
|
|
509
458
|
{parse(biteBody)}
|
|
510
459
|
</p>
|
|
460
|
+
{showBite && 'end' === biteStyle && <span className="bite-value data-bite-body" style={{fontSize: biteFontSize + 'px'}}>{calculateDataBite()}</span>}
|
|
511
461
|
{subtext && !isCompactStyle && <p className="bite-subtext">{parse(subtext)}</p>}
|
|
462
|
+
</div>
|
|
512
463
|
</Fragment>
|
|
513
464
|
</div>
|
|
514
465
|
{isBottom && <DataImage />}
|
|
@@ -516,12 +467,14 @@ const { configUrl, config: configObj, isDashboard = false, isEditor = false, set
|
|
|
516
467
|
</div>
|
|
517
468
|
</div>
|
|
518
469
|
</div>
|
|
470
|
+
{link && link}
|
|
519
471
|
</div>
|
|
520
472
|
</>
|
|
521
473
|
)
|
|
522
474
|
}
|
|
523
475
|
|
|
524
476
|
let classNames = [
|
|
477
|
+
'cove',
|
|
525
478
|
'cdc-open-viz-module',
|
|
526
479
|
'type-data-bite',
|
|
527
480
|
currentViewport,
|
|
@@ -568,8 +521,10 @@ export const BITE_LOCATION_BODY = 'body';
|
|
|
568
521
|
export const BITE_LOCATION_GRAPHIC = 'graphic';
|
|
569
522
|
export const BITE_LOCATIONS = {
|
|
570
523
|
'graphic': 'Graphic',
|
|
524
|
+
'split': 'Split Graphic and Message',
|
|
571
525
|
'title': 'Value above Message',
|
|
572
|
-
'body': 'Value before Message'
|
|
526
|
+
'body': 'Value before Message',
|
|
527
|
+
'end': 'Value after Message'
|
|
573
528
|
};
|
|
574
529
|
|
|
575
530
|
export const IMAGE_POSITION_LEFT = 'Left';
|