@cdc/data-bite 4.25.8 → 4.25.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 +9723 -8357
- package/package.json +14 -5
- package/src/CdcDataBite.tsx +55 -16
- package/src/_stories/DataBite.Editor.stories.tsx +862 -0
- package/src/_stories/DataBite.stories.tsx +59 -35
- package/src/components/EditorPanel.jsx +53 -47
- package/src/constants.ts +0 -52
- package/src/data/initial-state.js +3 -1
- package/src/index.jsx +1 -1
- package/src/scss/editor-panel.scss +12 -484
- package/src/scss/main.scss +0 -33
- package/src/store/db.reducer.ts +1 -1
- package/src/test/CdcDataBite.test.jsx +8 -3
- package/src/types/Config.ts +4 -2
- package/tests/fixtures/example-data.json +833 -0
- package/tests/fixtures/test-config.json +26 -0
- package/vite.config.js +1 -1
- package/vitest.config.ts +16 -0
- package/src/coreStyles_databite.scss +0 -3
- package/src/scss/variables.scss +0 -1
|
@@ -1,35 +1,59 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
-
import DataBite from '../CdcDataBite'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import DataBite from '../CdcDataBite'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof DataBite> = {
|
|
5
|
+
title: 'Components/Templates/Data Bite',
|
|
6
|
+
component: DataBite,
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component:
|
|
11
|
+
'Data Bite component for displaying key statistics and metrics. For comprehensive editor testing, see the "Editor Tests" section below.'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default meta
|
|
18
|
+
type Story = StoryObj<typeof DataBite>
|
|
19
|
+
|
|
20
|
+
// Gallery stories for visual documentation
|
|
21
|
+
export const Data_Bite_Circle_Average: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Average.json'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const Data_Bite_Text_Max_Pic: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Max_Pic.json'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const Data_Bite_Circle_Sum: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Sum.json'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const Data_Bite_Text_Average_Pic: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Average_Pic.json'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Simple editor mode story for basic rendering
|
|
46
|
+
export const Editor_Mode_Basic: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
configUrl: '/tests/fixtures/test-config.json',
|
|
49
|
+
isEditor: true
|
|
50
|
+
},
|
|
51
|
+
parameters: {
|
|
52
|
+
docs: {
|
|
53
|
+
description: {
|
|
54
|
+
story:
|
|
55
|
+
'Basic editor mode rendering. For comprehensive editor testing with interactions, see "Data Bite/Editor Tests" stories.'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { memo, useContext, useEffect, useState } from 'react'
|
|
1
|
+
import React, { memo, useContext, useEffect, useState } from 'react'
|
|
2
|
+
import { DATA_FUNCTIONS, DATA_OPERATORS } from '@cdc/core/helpers/constants'
|
|
3
|
+
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
2
4
|
import _ from 'lodash'
|
|
3
5
|
import {
|
|
4
6
|
Accordion,
|
|
@@ -8,16 +10,21 @@ import {
|
|
|
8
10
|
AccordionItemPanel
|
|
9
11
|
} from 'react-accessible-accordion'
|
|
10
12
|
|
|
13
|
+
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
11
14
|
import Context from '../context'
|
|
12
15
|
import WarningImage from '@cdc/core/assets/icon-warning-circle.svg'
|
|
13
16
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
14
17
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
15
18
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
16
19
|
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
17
|
-
import { BITE_LOCATIONS,
|
|
20
|
+
import { BITE_LOCATIONS, IMAGE_POSITIONS } from './../constants'
|
|
18
21
|
import Layout from '@cdc/core/components/Layout'
|
|
19
22
|
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
20
23
|
import Button from '@cdc/core/components/elements/Button'
|
|
24
|
+
import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
|
|
25
|
+
import { HeaderThemeSelector } from '@cdc/core/components/HeaderThemeSelector'
|
|
26
|
+
|
|
27
|
+
import '@cdc/core/styles/v2/components/editor.scss'
|
|
21
28
|
|
|
22
29
|
const EditorPanel = memo(() => {
|
|
23
30
|
const { config, updateConfig, loading, data, setParentConfig, isDashboard, isEditor } = useContext(Context)
|
|
@@ -51,7 +58,7 @@ const EditorPanel = memo(() => {
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
const convertStateToConfig = () => {
|
|
54
|
-
let strippedState =
|
|
61
|
+
let strippedState = cloneConfig(config)
|
|
55
62
|
//if(false === missingRequiredSections()) {
|
|
56
63
|
//strippedState.newViz
|
|
57
64
|
//}
|
|
@@ -239,7 +246,8 @@ const EditorPanel = memo(() => {
|
|
|
239
246
|
<Tooltip.Content>
|
|
240
247
|
<p>
|
|
241
248
|
Enter supporting text to display below the data visualization, if applicable. The following
|
|
242
|
-
HTML tags are supported: strong, em, sup, and sub.
|
|
249
|
+
HTML tags are supported: strong, em, sup, and sub. You can also use markup variables like{' '}
|
|
250
|
+
{'{{variable-name}}'} to display dynamic data.
|
|
243
251
|
</p>
|
|
244
252
|
</Tooltip.Content>
|
|
245
253
|
</Tooltip>
|
|
@@ -282,8 +290,8 @@ const EditorPanel = memo(() => {
|
|
|
282
290
|
Array.isArray(DATA_FUNCTIONS)
|
|
283
291
|
? DATA_FUNCTIONS
|
|
284
292
|
: DATA_FUNCTIONS
|
|
285
|
-
|
|
286
|
-
|
|
293
|
+
? Object.values(DATA_FUNCTIONS)
|
|
294
|
+
: []
|
|
287
295
|
}
|
|
288
296
|
/>
|
|
289
297
|
</li>
|
|
@@ -405,7 +413,7 @@ const EditorPanel = memo(() => {
|
|
|
405
413
|
<AccordionItemHeading>
|
|
406
414
|
<AccordionItemButton>Visual</AccordionItemButton>
|
|
407
415
|
</AccordionItemHeading>
|
|
408
|
-
<AccordionItemPanel>
|
|
416
|
+
<AccordionItemPanel className='panel-visual accordion__panel accordion__panel--visual'>
|
|
409
417
|
<TextField
|
|
410
418
|
type='number'
|
|
411
419
|
value={config.biteFontSize}
|
|
@@ -459,22 +467,11 @@ const EditorPanel = memo(() => {
|
|
|
459
467
|
updateField={updateField}
|
|
460
468
|
/>
|
|
461
469
|
</div>
|
|
462
|
-
<
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
title={palette}
|
|
468
|
-
key={palette}
|
|
469
|
-
onClick={e => {
|
|
470
|
-
e.preventDefault()
|
|
471
|
-
updateConfig({ ...config, theme: palette })
|
|
472
|
-
}}
|
|
473
|
-
className={config.theme === palette ? 'selected ' + palette : palette}
|
|
474
|
-
/>
|
|
475
|
-
))}
|
|
476
|
-
</ul>
|
|
477
|
-
</label>
|
|
470
|
+
<HeaderThemeSelector
|
|
471
|
+
selectedTheme={config.theme}
|
|
472
|
+
onThemeSelect={theme => updateConfig({ ...config, theme })}
|
|
473
|
+
label='Theme'
|
|
474
|
+
/>
|
|
478
475
|
</AccordionItemPanel>
|
|
479
476
|
</AccordionItem>
|
|
480
477
|
|
|
@@ -568,19 +565,14 @@ const EditorPanel = memo(() => {
|
|
|
568
565
|
<div className='accordion__panel-row align-center'>
|
|
569
566
|
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
570
567
|
<div className='accordion__panel-col flex-auto'>
|
|
571
|
-
<
|
|
568
|
+
<Select
|
|
569
|
+
label=''
|
|
572
570
|
value={option.arguments[0]?.operator || ''}
|
|
571
|
+
options={DATA_OPERATORS}
|
|
573
572
|
onChange={e => {
|
|
574
573
|
updateDynamicImage('operator', index, 0, e.target.value)
|
|
575
574
|
}}
|
|
576
|
-
|
|
577
|
-
<option value='' disabled />
|
|
578
|
-
{DATA_OPERATORS.map((operator, index) => (
|
|
579
|
-
<option value={operator} key={index}>
|
|
580
|
-
{operator}
|
|
581
|
-
</option>
|
|
582
|
-
))}
|
|
583
|
-
</select>
|
|
575
|
+
/>
|
|
584
576
|
</div>
|
|
585
577
|
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
586
578
|
<input
|
|
@@ -595,9 +587,13 @@ const EditorPanel = memo(() => {
|
|
|
595
587
|
|
|
596
588
|
<div className='accordion__panel-row mb-2 align-center'>
|
|
597
589
|
<div className='accordion__panel-col flex-grow'>
|
|
598
|
-
<
|
|
599
|
-
|
|
590
|
+
<Select
|
|
591
|
+
label=''
|
|
600
592
|
value={option.secondArgument ? 'and' : 'then'}
|
|
593
|
+
options={[
|
|
594
|
+
{ value: 'then', label: 'Then' },
|
|
595
|
+
{ value: 'and', label: 'And' }
|
|
596
|
+
]}
|
|
601
597
|
onChange={e => {
|
|
602
598
|
if ('then' === e.target.value) {
|
|
603
599
|
updateDynamicImage('secondArgument', index, null, false)
|
|
@@ -607,10 +603,7 @@ const EditorPanel = memo(() => {
|
|
|
607
603
|
updateDynamicImage('secondArgument', index, null, true)
|
|
608
604
|
}
|
|
609
605
|
}}
|
|
610
|
-
|
|
611
|
-
<option value={'then'}>Then</option>
|
|
612
|
-
<option value={'and'}>And</option>
|
|
613
|
-
</select>
|
|
606
|
+
/>
|
|
614
607
|
</div>
|
|
615
608
|
</div>
|
|
616
609
|
|
|
@@ -619,19 +612,14 @@ const EditorPanel = memo(() => {
|
|
|
619
612
|
<div className='accordion__panel-row align-center'>
|
|
620
613
|
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
621
614
|
<div className='accordion__panel-col flex-auto'>
|
|
622
|
-
<
|
|
615
|
+
<Select
|
|
616
|
+
label=''
|
|
623
617
|
value={option.arguments[1]?.operator || ''}
|
|
618
|
+
options={DATA_OPERATORS}
|
|
624
619
|
onChange={e => {
|
|
625
620
|
setDynamicArgument(index, 'operator', e.target.value)
|
|
626
621
|
}}
|
|
627
|
-
|
|
628
|
-
<option value='' disabled />
|
|
629
|
-
{DATA_OPERATORS.map((operator, index) => (
|
|
630
|
-
<option value={operator} key={index}>
|
|
631
|
-
{operator}
|
|
632
|
-
</option>
|
|
633
|
-
))}
|
|
634
|
-
</select>
|
|
622
|
+
/>
|
|
635
623
|
</div>
|
|
636
624
|
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
637
625
|
<input
|
|
@@ -688,6 +676,24 @@ const EditorPanel = memo(() => {
|
|
|
688
676
|
</AccordionItemPanel>
|
|
689
677
|
</AccordionItem>
|
|
690
678
|
)}
|
|
679
|
+
|
|
680
|
+
<AccordionItem>
|
|
681
|
+
<AccordionItemHeading>
|
|
682
|
+
<AccordionItemButton>Markup Variables</AccordionItemButton>
|
|
683
|
+
</AccordionItemHeading>
|
|
684
|
+
<AccordionItemPanel>
|
|
685
|
+
<PanelMarkup
|
|
686
|
+
name='Markup Variables'
|
|
687
|
+
markupVariables={config.markupVariables || []}
|
|
688
|
+
data={data}
|
|
689
|
+
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
690
|
+
onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
|
|
691
|
+
onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
|
|
692
|
+
withAccordion={false}
|
|
693
|
+
/>
|
|
694
|
+
</AccordionItemPanel>
|
|
695
|
+
</AccordionItem>
|
|
696
|
+
<AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
|
|
691
697
|
</Accordion>
|
|
692
698
|
</form>
|
|
693
699
|
</section>
|
package/src/constants.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
export const DATA_FUNCTION_MAX = 'Max'
|
|
2
|
-
export const DATA_FUNCTION_COUNT = 'Count'
|
|
3
|
-
export const DATA_FUNCTION_MEAN = 'Mean (Average)'
|
|
4
|
-
export const DATA_FUNCTION_MEDIAN = 'Median'
|
|
5
|
-
export const DATA_FUNCTION_MIN = 'Min'
|
|
6
|
-
export const DATA_FUNCTION_MODE = 'Mode'
|
|
7
|
-
export const DATA_FUNCTION_RANGE = 'Range'
|
|
8
|
-
export const DATA_FUNCTION_SUM = 'Sum'
|
|
9
|
-
export const DATA_FUNCTIONS = [
|
|
10
|
-
DATA_FUNCTION_COUNT,
|
|
11
|
-
DATA_FUNCTION_MAX,
|
|
12
|
-
DATA_FUNCTION_MEAN,
|
|
13
|
-
DATA_FUNCTION_MEDIAN,
|
|
14
|
-
DATA_FUNCTION_MIN,
|
|
15
|
-
DATA_FUNCTION_MODE,
|
|
16
|
-
DATA_FUNCTION_RANGE,
|
|
17
|
-
DATA_FUNCTION_SUM
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
export const BITE_LOCATION_TITLE = 'title'
|
|
21
|
-
export const BITE_LOCATION_BODY = 'body'
|
|
22
|
-
export const BITE_LOCATION_GRAPHIC = 'graphic'
|
|
23
1
|
export const BITE_LOCATIONS = {
|
|
24
2
|
graphic: 'Graphic',
|
|
25
3
|
split: 'Split Graphic and Message',
|
|
@@ -34,33 +12,3 @@ export const IMAGE_POSITION_RIGHT = 'Right'
|
|
|
34
12
|
export const IMAGE_POSITION_TOP = 'Top'
|
|
35
13
|
export const IMAGE_POSITION_BOTTOM = 'Bottom'
|
|
36
14
|
export const IMAGE_POSITIONS = [IMAGE_POSITION_LEFT, IMAGE_POSITION_RIGHT, IMAGE_POSITION_TOP, IMAGE_POSITION_BOTTOM]
|
|
37
|
-
|
|
38
|
-
export const DATA_OPERATOR_LESS = '<'
|
|
39
|
-
export const DATA_OPERATOR_GREATER = '>'
|
|
40
|
-
export const DATA_OPERATOR_LESSEQUAL = '<='
|
|
41
|
-
export const DATA_OPERATOR_GREATEREQUAL = '>='
|
|
42
|
-
export const DATA_OPERATOR_EQUAL = '='
|
|
43
|
-
export const DATA_OPERATOR_NOTEQUAL = '≠'
|
|
44
|
-
|
|
45
|
-
export const DATA_OPERATORS = [
|
|
46
|
-
DATA_OPERATOR_LESS,
|
|
47
|
-
DATA_OPERATOR_GREATER,
|
|
48
|
-
DATA_OPERATOR_LESSEQUAL,
|
|
49
|
-
DATA_OPERATOR_GREATEREQUAL,
|
|
50
|
-
DATA_OPERATOR_EQUAL,
|
|
51
|
-
DATA_OPERATOR_NOTEQUAL
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
export const HEADER_COLORS = [
|
|
55
|
-
'theme-blue',
|
|
56
|
-
'theme-purple',
|
|
57
|
-
'theme-brown',
|
|
58
|
-
'theme-teal',
|
|
59
|
-
'theme-pink',
|
|
60
|
-
'theme-orange',
|
|
61
|
-
'theme-slate',
|
|
62
|
-
'theme-indigo',
|
|
63
|
-
'theme-cyan',
|
|
64
|
-
'theme-green',
|
|
65
|
-
'theme-amber'
|
|
66
|
-
]
|
package/src/index.jsx
CHANGED