@cdc/waffle-chart 4.25.11 → 4.26.1
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/cdcwafflechart.js +6603 -6234
- package/examples/tp5-style-white.json +72 -0
- package/examples/tp5-style.json +72 -0
- package/examples/tp5-waffle.json +123 -0
- package/index.html +3 -6
- package/package.json +6 -5
- package/src/CdcWaffleChart.tsx +156 -96
- package/src/_stories/WaffleChart.Editor.stories.tsx +17 -30
- package/src/_stories/WaffleChart.stories.tsx +28 -0
- package/src/components/EditorPanel.jsx +110 -199
- package/src/images/callout-flag.svg +7 -0
- package/src/scss/waffle-chart.scss +86 -4
- package/src/test/CdcWaffleChart.test.jsx +1 -1
- package/src/types/Config.ts +4 -2
- package/LICENSE +0 -201
|
@@ -420,8 +420,8 @@ export const DataSectionTests: Story = {
|
|
|
420
420
|
}
|
|
421
421
|
|
|
422
422
|
/**
|
|
423
|
-
* VISUAL SECTION TESTS
|
|
424
|
-
* Tests
|
|
423
|
+
* CHART SETTINGS AND VISUAL SECTION TESTS
|
|
424
|
+
* Tests functionality within the Chart Settings and Visual accordions
|
|
425
425
|
*/
|
|
426
426
|
export const VisualSectionTests: Story = {
|
|
427
427
|
args: {
|
|
@@ -431,7 +431,8 @@ export const VisualSectionTests: Story = {
|
|
|
431
431
|
play: async ({ canvasElement }) => {
|
|
432
432
|
const canvas = within(canvasElement)
|
|
433
433
|
await waitForEditor(canvas)
|
|
434
|
-
|
|
434
|
+
// Open Chart Settings accordion first for tests 1-5
|
|
435
|
+
await openAccordion(canvas, 'Chart Settings')
|
|
435
436
|
// Core helper functions used throughout the visual tests
|
|
436
437
|
const waffleRoot = () => canvasElement.querySelector('.cove-waffle-chart') as HTMLElement
|
|
437
438
|
const contentContainer = () => canvasElement.querySelector('.cove-component__content > div') as HTMLElement
|
|
@@ -569,6 +570,9 @@ export const VisualSectionTests: Story = {
|
|
|
569
570
|
// TEST 6: Overall Font Size Change
|
|
570
571
|
// Expectation: font-small|font-medium|font-large class changes on waffle root.
|
|
571
572
|
// ============================================================================
|
|
573
|
+
// Open Visual accordion for tests 6+
|
|
574
|
+
await openAccordion(canvas, 'Visual')
|
|
575
|
+
|
|
572
576
|
const overallFontClass = () => {
|
|
573
577
|
const root = waffleRoot()
|
|
574
578
|
if (!root) return ''
|
|
@@ -624,11 +628,8 @@ export const VisualSectionTests: Story = {
|
|
|
624
628
|
// ============================================================================
|
|
625
629
|
const contentClassSig = () => Array.from(contentContainer().classList).sort().join(' ')
|
|
626
630
|
|
|
627
|
-
// Find border checkbox by label text
|
|
628
|
-
const borderCheckbox =
|
|
629
|
-
const label = input.closest('label')
|
|
630
|
-
return label?.textContent?.includes('Display Border')
|
|
631
|
-
}) as HTMLInputElement
|
|
631
|
+
// Find border checkbox by exact label text
|
|
632
|
+
const borderCheckbox = canvas.getByLabelText('Display Border') as HTMLInputElement
|
|
632
633
|
expect(borderCheckbox).toBeTruthy()
|
|
633
634
|
const borderWrapper = borderCheckbox.closest('label.checkbox') as HTMLElement
|
|
634
635
|
expect(borderWrapper).toBeTruthy()
|
|
@@ -659,13 +660,8 @@ export const VisualSectionTests: Story = {
|
|
|
659
660
|
// TEST 9: Theme Border Color Toggle
|
|
660
661
|
// Expectation: Class 'component--has-borderColorTheme' toggles.
|
|
661
662
|
// ============================================================================
|
|
662
|
-
// Find border color theme checkbox by label text
|
|
663
|
-
const borderColorThemeCheckbox =
|
|
664
|
-
input => {
|
|
665
|
-
const label = input.closest('label')
|
|
666
|
-
return label?.textContent?.includes('Use theme border color')
|
|
667
|
-
}
|
|
668
|
-
) as HTMLInputElement
|
|
663
|
+
// Find border color theme checkbox by exact label text
|
|
664
|
+
const borderColorThemeCheckbox = canvas.getByLabelText('Use Border Color Theme') as HTMLInputElement
|
|
669
665
|
expect(borderColorThemeCheckbox).toBeTruthy()
|
|
670
666
|
const borderColorThemeWrapper = borderColorThemeCheckbox.closest('label.checkbox') as HTMLElement
|
|
671
667
|
expect(borderColorThemeWrapper).toBeTruthy()
|
|
@@ -682,11 +678,8 @@ export const VisualSectionTests: Story = {
|
|
|
682
678
|
// TEST 10: Accent Style Toggle
|
|
683
679
|
// Expectation: Class 'component--has-accent' toggles.
|
|
684
680
|
// ============================================================================
|
|
685
|
-
// Find accent checkbox by label text
|
|
686
|
-
const accentCheckbox =
|
|
687
|
-
const label = input.closest('label')
|
|
688
|
-
return label?.textContent?.includes('Use Accent Style')
|
|
689
|
-
}) as HTMLInputElement
|
|
681
|
+
// Find accent checkbox by exact label text
|
|
682
|
+
const accentCheckbox = canvas.getByLabelText('Use Accent Style') as HTMLInputElement
|
|
690
683
|
expect(accentCheckbox).toBeTruthy()
|
|
691
684
|
const accentWrapper = accentCheckbox.closest('label.checkbox') as HTMLElement
|
|
692
685
|
expect(accentWrapper).toBeTruthy()
|
|
@@ -703,11 +696,8 @@ export const VisualSectionTests: Story = {
|
|
|
703
696
|
// TEST 11: Theme Background Color Toggle
|
|
704
697
|
// Expectation: Class 'component--has-background' toggles.
|
|
705
698
|
// ============================================================================
|
|
706
|
-
// Find background checkbox by label text
|
|
707
|
-
const backgroundCheckbox =
|
|
708
|
-
const label = input.closest('label')
|
|
709
|
-
return label?.textContent?.includes('Use Theme Background Color')
|
|
710
|
-
}) as HTMLInputElement
|
|
699
|
+
// Find background checkbox by exact label text
|
|
700
|
+
const backgroundCheckbox = canvas.getByLabelText('Use Theme Background Color') as HTMLInputElement
|
|
711
701
|
expect(backgroundCheckbox).toBeTruthy()
|
|
712
702
|
const backgroundWrapper = backgroundCheckbox.closest('label.checkbox') as HTMLElement
|
|
713
703
|
expect(backgroundWrapper).toBeTruthy()
|
|
@@ -724,11 +714,8 @@ export const VisualSectionTests: Story = {
|
|
|
724
714
|
// TEST 12: Hide Background Color Toggle
|
|
725
715
|
// Expectation: Class 'component--hideBackgroundColor' toggles.
|
|
726
716
|
// ============================================================================
|
|
727
|
-
// Find hide background checkbox by label text
|
|
728
|
-
const hideBackgroundCheckbox =
|
|
729
|
-
const label = input.closest('label')
|
|
730
|
-
return label?.textContent?.includes('Hide Background Color')
|
|
731
|
-
}) as HTMLInputElement
|
|
717
|
+
// Find hide background checkbox by exact label text
|
|
718
|
+
const hideBackgroundCheckbox = canvas.getByLabelText('Hide Background Color') as HTMLInputElement
|
|
732
719
|
expect(hideBackgroundCheckbox).toBeTruthy()
|
|
733
720
|
const hideBackgroundWrapper = hideBackgroundCheckbox.closest('label.checkbox') as HTMLElement
|
|
734
721
|
expect(hideBackgroundWrapper).toBeTruthy()
|
|
@@ -189,4 +189,32 @@ export const Gauge: Story = {
|
|
|
189
189
|
)
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
export const Waffle_Chart_TP5_Style: Story = {
|
|
193
|
+
args: {
|
|
194
|
+
configUrl: '/packages/waffle-chart/examples/tp5-style.json'
|
|
195
|
+
},
|
|
196
|
+
parameters: {
|
|
197
|
+
docs: {
|
|
198
|
+
description: {
|
|
199
|
+
story:
|
|
200
|
+
'TP5 Style - A new layout style that displays the waffle chart in a callout component with a blue background and icon. The title appears inside the callout header. This style mimics the CDC Template Package 5.0 callout component design and includes an optional white background variant.'
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export const Waffle_Chart_TP5_Style_White_Background: Story = {
|
|
207
|
+
args: {
|
|
208
|
+
configUrl: '/packages/waffle-chart/examples/tp5-style-white.json'
|
|
209
|
+
},
|
|
210
|
+
parameters: {
|
|
211
|
+
docs: {
|
|
212
|
+
description: {
|
|
213
|
+
story:
|
|
214
|
+
'TP5 Style with White Background - The white background variant of the TP5 style features a white background with a teal border instead of the default blue background. The icon remains visible in this variant.'
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
192
220
|
export default meta
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
1
|
+
import React, { useEffect, memo, useContext } from 'react'
|
|
3
2
|
import _ from 'lodash'
|
|
4
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
5
3
|
|
|
6
4
|
import ConfigContext from '../ConfigContext'
|
|
7
5
|
|
|
6
|
+
import { EditorPanel as BaseEditorPanel } from '@cdc/core/components/EditorPanel/EditorPanel'
|
|
8
7
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
9
8
|
import Accordion from '@cdc/core/components/ui/Accordion'
|
|
10
9
|
import Button from '@cdc/core/components/elements/Button'
|
|
@@ -12,8 +11,9 @@ import Icon from '@cdc/core/components/ui/Icon'
|
|
|
12
11
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
13
12
|
import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
14
13
|
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
14
|
+
import { useFilterManagement } from '@cdc/core/hooks/useFilterManagement'
|
|
15
|
+
import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
|
|
16
|
+
import { VisualSection } from '@cdc/core/components/EditorPanel/sections/VisualSection'
|
|
17
17
|
|
|
18
18
|
import '@cdc/core/styles/v2/components/editor.scss'
|
|
19
19
|
import WarningImage from '../images/warning.svg'
|
|
@@ -23,27 +23,16 @@ import { DATA_OPERATORS, DATA_FUNCTIONS } from '../CdcWaffleChart'
|
|
|
23
23
|
const EditorPanel = memo(props => {
|
|
24
24
|
const { config, updateConfig, loading, data, setParentConfig, isDashboard } = useContext(ConfigContext)
|
|
25
25
|
const { showConfigConfirm } = props
|
|
26
|
-
const [displayPanel, setDisplayPanel] = useState(true)
|
|
27
26
|
const inputSelectStyle = condition => (condition ? { backgroundColor: '#ffd2d2', color: '#d8000c' } : {})
|
|
28
27
|
|
|
29
28
|
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
-
}, [config])
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (!showConfigConfirm) {
|
|
42
|
-
let newConfig = { ...config }
|
|
43
|
-
delete newConfig.newViz
|
|
44
|
-
updateConfig(newConfig)
|
|
45
|
-
}
|
|
46
|
-
}, [])
|
|
30
|
+
// Filters
|
|
31
|
+
const { addNewFilter, removeFilter, updateFilterProp, getFilterColumnValues } = useFilterManagement(
|
|
32
|
+
config,
|
|
33
|
+
updateConfig,
|
|
34
|
+
data
|
|
35
|
+
)
|
|
47
36
|
|
|
48
37
|
useEffect(() => {
|
|
49
38
|
//Verify comparate data type
|
|
@@ -61,70 +50,15 @@ const EditorPanel = memo(props => {
|
|
|
61
50
|
}
|
|
62
51
|
}, [config.dataConditionalOperator, config.dataConditionalComparate])
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
updateConfig({
|
|
67
|
-
...config,
|
|
68
|
-
showEditorPanel: !displayPanel
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
// if (isDashboard) {
|
|
72
|
-
// updateConfig({ ...config, editing: false })
|
|
73
|
-
// } else {
|
|
74
|
-
// setDisplayPanel(!displayPanel)
|
|
75
|
-
// }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const convertStateToConfig = () => {
|
|
79
|
-
let strippedState = cloneConfig(config)
|
|
80
|
-
delete strippedState.newViz
|
|
81
|
-
delete strippedState.runtime
|
|
82
|
-
|
|
83
|
-
return strippedState
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const addNewFilter = () => {
|
|
87
|
-
let filters = config.filters ? [...config.filters] : []
|
|
88
|
-
filters.push({ values: [] })
|
|
89
|
-
updateConfig({ ...config, filters })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const removeFilter = index => {
|
|
93
|
-
let filters = [...config.filters]
|
|
94
|
-
filters.splice(index, 1)
|
|
95
|
-
updateConfig({ ...config, filters })
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const updateFilterProp = (name, index, value) => {
|
|
99
|
-
let filters = [...config.filters]
|
|
100
|
-
filters[index][name] = value
|
|
101
|
-
updateConfig({ ...config, filters })
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const getColumns = (filter = true) => {
|
|
105
|
-
let columns = {}
|
|
106
|
-
|
|
107
|
-
data.map(row => Object.keys(row).forEach(columnName => (columns[columnName] = true)))
|
|
108
|
-
|
|
109
|
-
return Object.keys(columns)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const getFilterColumnValues = index => {
|
|
113
|
-
let filterDataOptions = []
|
|
114
|
-
const filterColumnName = config.filters[index].columnName
|
|
115
|
-
if (data && filterColumnName) {
|
|
116
|
-
data.forEach(function (row) {
|
|
117
|
-
if (undefined !== row[filterColumnName] && -1 === filterDataOptions.indexOf(row[filterColumnName])) {
|
|
118
|
-
filterDataOptions.push(row[filterColumnName])
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
filterDataOptions.sort()
|
|
122
|
-
}
|
|
123
|
-
return filterDataOptions
|
|
124
|
-
}
|
|
53
|
+
// Extract column names from data with memoization (replaces getColumns)
|
|
54
|
+
const columns = useDataColumns(data)
|
|
125
55
|
//visualizationType
|
|
126
56
|
|
|
127
|
-
const approvedWaffleChartOptions = [
|
|
57
|
+
const approvedWaffleChartOptions = [
|
|
58
|
+
{ value: 'Waffle', label: 'Waffle' },
|
|
59
|
+
{ value: 'TP5 Waffle', label: 'TP5 Style Waffle' },
|
|
60
|
+
{ value: 'Gauge', label: 'Gauge' }
|
|
61
|
+
]
|
|
128
62
|
|
|
129
63
|
const editorContent = (
|
|
130
64
|
<Accordion>
|
|
@@ -210,7 +144,7 @@ const EditorPanel = memo(props => {
|
|
|
210
144
|
label='Data Column'
|
|
211
145
|
updateField={updateField}
|
|
212
146
|
initial='Select'
|
|
213
|
-
options={
|
|
147
|
+
options={columns}
|
|
214
148
|
/>
|
|
215
149
|
</div>
|
|
216
150
|
|
|
@@ -237,7 +171,7 @@ const EditorPanel = memo(props => {
|
|
|
237
171
|
fieldName='dataConditionalColumn'
|
|
238
172
|
updateField={updateField}
|
|
239
173
|
initial='Select'
|
|
240
|
-
options={
|
|
174
|
+
options={columns}
|
|
241
175
|
/>
|
|
242
176
|
</div>
|
|
243
177
|
<div className='cove-accordion__panel-col'>
|
|
@@ -297,7 +231,7 @@ const EditorPanel = memo(props => {
|
|
|
297
231
|
label='Data Column'
|
|
298
232
|
updateField={updateField}
|
|
299
233
|
initial='Select'
|
|
300
|
-
options={
|
|
234
|
+
options={columns}
|
|
301
235
|
/>
|
|
302
236
|
<Select
|
|
303
237
|
value={config.dataDenomFunction || ''}
|
|
@@ -387,7 +321,7 @@ const EditorPanel = memo(props => {
|
|
|
387
321
|
<Select
|
|
388
322
|
label='Column'
|
|
389
323
|
value={filter.columnName || ''}
|
|
390
|
-
options={
|
|
324
|
+
options={columns}
|
|
391
325
|
initial='- Select Option -'
|
|
392
326
|
onChange={e => {
|
|
393
327
|
updateFilterProp('columnName', index, e.target.value)
|
|
@@ -410,7 +344,7 @@ const EditorPanel = memo(props => {
|
|
|
410
344
|
Add Filter
|
|
411
345
|
</Button>
|
|
412
346
|
</Accordion.Section>
|
|
413
|
-
<Accordion.Section title='
|
|
347
|
+
<Accordion.Section title='Chart Settings'>
|
|
414
348
|
{config.visualizationType !== 'Gauge' && (
|
|
415
349
|
<Select
|
|
416
350
|
value={config.shape}
|
|
@@ -420,133 +354,110 @@ const EditorPanel = memo(props => {
|
|
|
420
354
|
options={['circle', 'square', 'person']}
|
|
421
355
|
/>
|
|
422
356
|
)}
|
|
423
|
-
{config.visualizationType !== 'Gauge' && (
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
357
|
+
{config.visualizationType !== 'Gauge' && config.visualizationType !== 'TP5 Waffle' && (
|
|
358
|
+
<>
|
|
359
|
+
<div
|
|
360
|
+
className='cove-accordion__panel-row cove-accordion__small-inputs'
|
|
361
|
+
style={{ marginTop: '1rem', marginBottom: '1rem' }}
|
|
362
|
+
>
|
|
363
|
+
<div className='cove-accordion__panel-col'>
|
|
364
|
+
<TextField
|
|
365
|
+
type='number'
|
|
366
|
+
value={config.nodeWidth}
|
|
367
|
+
fieldName='nodeWidth'
|
|
368
|
+
label='Width'
|
|
369
|
+
updateField={updateField}
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
<div className='cove-accordion__panel-col'>
|
|
373
|
+
<TextField
|
|
374
|
+
type='number'
|
|
375
|
+
value={config.nodeSpacer}
|
|
376
|
+
fieldName='nodeSpacer'
|
|
377
|
+
label='Spacer'
|
|
378
|
+
updateField={updateField}
|
|
379
|
+
/>
|
|
380
|
+
</div>
|
|
436
381
|
</div>
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
value={config.
|
|
441
|
-
fieldName='
|
|
442
|
-
label='
|
|
382
|
+
|
|
383
|
+
<div className='cove-input-group'>
|
|
384
|
+
<Select
|
|
385
|
+
value={config.orientation}
|
|
386
|
+
fieldName='orientation'
|
|
387
|
+
label='Layout'
|
|
443
388
|
updateField={updateField}
|
|
389
|
+
options={['horizontal', 'vertical']}
|
|
444
390
|
/>
|
|
445
391
|
</div>
|
|
446
|
-
</div>
|
|
447
|
-
)}
|
|
448
392
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
<div className='cove-input-group'>
|
|
462
|
-
<label>
|
|
463
|
-
<span className='edit-label column-heading cove-input__label'>Data Point Font Size</span>
|
|
464
|
-
</label>
|
|
465
|
-
<div className='cove-accordion__panel-row cove-accordion__small-inputs align-center'>
|
|
466
|
-
<div className='cove-accordion__panel-col'>
|
|
467
|
-
<TextField type='number' value={config.fontSize} fieldName='fontSize' updateField={updateField} />
|
|
468
|
-
</div>
|
|
469
|
-
<div className='cove-accordion__panel-col' style={{ display: 'flex', alignItems: 'center' }}>
|
|
470
|
-
<label className='accordion__panel-label--muted'> default (50px)</label>
|
|
393
|
+
<div className='cove-input-group'>
|
|
394
|
+
<label>
|
|
395
|
+
<span className='edit-label column-heading cove-input__label'>Data Point Font Size</span>
|
|
396
|
+
</label>
|
|
397
|
+
<div className='cove-accordion__panel-row cove-accordion__small-inputs align-center'>
|
|
398
|
+
<div className='cove-accordion__panel-col'>
|
|
399
|
+
<TextField type='number' value={config.fontSize} fieldName='fontSize' updateField={updateField} />
|
|
400
|
+
</div>
|
|
401
|
+
<div className='cove-accordion__panel-col' style={{ display: 'flex', alignItems: 'center' }}>
|
|
402
|
+
<label className='accordion__panel-label--muted'> default (50px)</label>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
471
405
|
</div>
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
<Select
|
|
476
|
-
value={config.overallFontSize}
|
|
477
|
-
fieldName='overallFontSize'
|
|
478
|
-
label='Overall Font Size'
|
|
479
|
-
updateField={updateField}
|
|
480
|
-
options={['small', 'medium', 'large']}
|
|
481
|
-
/>
|
|
482
|
-
|
|
483
|
-
<HeaderThemeSelector
|
|
484
|
-
selectedTheme={config.theme}
|
|
485
|
-
onThemeSelect={theme => updateConfig({ ...config, theme })}
|
|
486
|
-
label='Theme'
|
|
487
|
-
/>
|
|
406
|
+
</>
|
|
407
|
+
)}
|
|
408
|
+
</Accordion.Section>
|
|
488
409
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
section='visual'
|
|
493
|
-
fieldName='border'
|
|
494
|
-
label='Display Border'
|
|
495
|
-
updateField={updateField}
|
|
496
|
-
/>
|
|
497
|
-
<CheckBox
|
|
498
|
-
value={config.visual.borderColorTheme}
|
|
499
|
-
section='visual'
|
|
500
|
-
fieldName='borderColorTheme'
|
|
501
|
-
label='Use theme border color'
|
|
502
|
-
updateField={updateField}
|
|
503
|
-
/>
|
|
504
|
-
<CheckBox
|
|
505
|
-
value={config.visual.accent}
|
|
506
|
-
section='visual'
|
|
507
|
-
fieldName='accent'
|
|
508
|
-
label='Use Accent Style'
|
|
509
|
-
updateField={updateField}
|
|
510
|
-
/>
|
|
410
|
+
{/* Visual section for TP5 style */}
|
|
411
|
+
{config.visualizationType === 'TP5 Waffle' && (
|
|
412
|
+
<Accordion.Section title='Visual'>
|
|
511
413
|
<CheckBox
|
|
512
|
-
value={config.visual
|
|
414
|
+
value={config.visual?.whiteBackground}
|
|
513
415
|
section='visual'
|
|
514
|
-
fieldName='
|
|
515
|
-
label='Use
|
|
416
|
+
fieldName='whiteBackground'
|
|
417
|
+
label='Use White Background Style'
|
|
516
418
|
updateField={updateField}
|
|
517
419
|
/>
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
420
|
+
</Accordion.Section>
|
|
421
|
+
)}
|
|
422
|
+
|
|
423
|
+
{/* Visual section for other styles */}
|
|
424
|
+
{config.visualizationType !== 'TP5 Waffle' && (
|
|
425
|
+
<Accordion.Section title='Visual'>
|
|
426
|
+
<VisualSection
|
|
427
|
+
config={config}
|
|
523
428
|
updateField={updateField}
|
|
429
|
+
updateConfig={updateConfig}
|
|
430
|
+
beforeCheckboxes={
|
|
431
|
+
<Select
|
|
432
|
+
value={config.overallFontSize}
|
|
433
|
+
fieldName='overallFontSize'
|
|
434
|
+
label='Overall Font Size'
|
|
435
|
+
updateField={updateField}
|
|
436
|
+
options={['small', 'medium', 'large']}
|
|
437
|
+
/>
|
|
438
|
+
}
|
|
524
439
|
/>
|
|
525
|
-
</
|
|
526
|
-
|
|
440
|
+
</Accordion.Section>
|
|
441
|
+
)}
|
|
527
442
|
</Accordion>
|
|
528
443
|
)
|
|
529
444
|
|
|
530
|
-
if (loading) return null
|
|
531
|
-
|
|
532
445
|
return (
|
|
533
|
-
<
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
</>
|
|
549
|
-
</ErrorBoundary>
|
|
446
|
+
<BaseEditorPanel
|
|
447
|
+
config={config}
|
|
448
|
+
updateConfig={updateConfig}
|
|
449
|
+
loading={loading}
|
|
450
|
+
setParentConfig={setParentConfig}
|
|
451
|
+
isDashboard={isDashboard}
|
|
452
|
+
title='Configure Waffle Chart'
|
|
453
|
+
>
|
|
454
|
+
{({ convertStateToConfig }) => (
|
|
455
|
+
<>
|
|
456
|
+
{editorContent}
|
|
457
|
+
<AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
|
|
458
|
+
</>
|
|
459
|
+
)}
|
|
460
|
+
</BaseEditorPanel>
|
|
550
461
|
)
|
|
551
462
|
})
|
|
552
463
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
3
|
+
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="481.000000pt" height="563.000000pt" viewBox="0 0 481.000000 563.000000" preserveAspectRatio="xMidYMid meet">
|
|
4
|
+
<g transform="translate(0.000000,563.000000) scale(0.100000,-0.100000)" fill="#2c7a99" stroke="none">
|
|
5
|
+
<path d="M890 5514 c-161 -43 -308 -201 -354 -381 -14 -55 -16 -314 -16 -2527 0 -2015 2 -2466 13 -2466 7 0 51 14 97 30 47 17 92 33 100 35 8 2 16 4 18 5 1 2 7 4 12 5 6 1 11 3 13 4 1 2 13 4 26 7 14 2 30 9 38 15 7 6 13 8 13 4 0 -4 7 -2 15 5 8 7 15 10 15 6 0 -3 17 1 38 10 49 21 856 293 905 305 21 5 45 13 55 19 9 5 40 16 67 24 28 8 162 52 299 99 l249 85 151 -53 c83 -29 253 -90 379 -134 264 -94 556 -198 974 -346 164 -58 308 -110 321 -115 13 -6 27 -10 33 -10 11 0 8 4951 -4 4994 -22 80 -84 183 -152 252 -75 76 -141 114 -233 133 -38 8 -477 11 -1535 10 -1268 0 -1490 -3 -1537 -15z m2687 -1570 c49 -31 82 -134 64 -201 -10 -37 -41 -64 -422 -369 -227 -181 -430 -341 -452 -356 -43 -30 -84 -35 -136 -17 -17 6 -156 107 -309 224 l-277 213 -40 -31 c-50 -39 -318 -259 -325 -267 -3 -3 -27 -24 -55 -45 -27 -22 -55 -44 -61 -50 -86 -77 -253 -202 -277 -207 -20 -4 -53 -1 -84 8 -69 19 -105 64 -111 140 -6 70 8 100 69 149 105 84 134 107 168 133 19 15 92 74 164 132 71 58 144 116 162 130 86 68 114 90 187 150 124 102 156 120 206 120 23 0 57 -7 75 -16 18 -9 145 -103 282 -209 283 -217 293 -224 303 -210 4 6 42 39 86 74 43 35 88 71 100 81 31 27 153 127 231 190 37 30 111 91 164 135 142 119 217 145 288 99z m-1431 -983 c60 -44 59 -29 62 -601 3 -596 4 -589 -70 -638 -76 -49 -171 -29 -228 50 l-30 41 0 526 c0 591 -3 569 75 623 35 25 48 28 100 25 44 -2 69 -9 91 -26z m1252 15 c37 -19 67 -55 81 -95 8 -25 10 -183 9 -555 -3 -579 -1 -555 -71 -603 -67 -45 -144 -35 -211 27 l-41 39 -3 543 -2 544 23 35 c46 68 149 99 215 65z m-610 -343 c71 -57 71 -57 71 -448 0 -322 -1 -353 -19 -392 -27 -60 -83 -95 -155 -95 -63 -1 -95 16 -132 72 -23 33 -23 36 -23 407 0 406 -1 401 57 455 34 32 54 38 116 34 35 -2 57 -11 85 -33z m-1313 -142 c54 -24 92 -71 100 -124 4 -23 5 -159 3 -302 -3 -293 -3 -293 -82 -343 -66 -41 -160 -30 -207 24 -34 40 -39 84 -39 361 0 303 3 322 61 366 53 39 105 45 164 18z"/>
|
|
6
|
+
</g>
|
|
7
|
+
</svg>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Remove custom theme mixin - use core styles instead
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
.type-dashboard .type-waffle-chart .cove-component__content {
|
|
5
4
|
padding-top: 0;
|
|
6
5
|
}
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
justify-items: center;
|
|
20
19
|
align-items: flex-start;
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
& > svg {
|
|
23
22
|
margin: 0.7em 0;
|
|
24
23
|
}
|
|
25
24
|
}
|
|
@@ -97,7 +96,6 @@
|
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
@at-root {
|
|
100
|
-
|
|
101
99
|
.cove-waffle-chart.font-small,
|
|
102
100
|
.cove-gauge-chart.font-small #{&} {
|
|
103
101
|
.cove-waffle-chart__data--primary {
|
|
@@ -130,4 +128,88 @@
|
|
|
130
128
|
font-size: 20px;
|
|
131
129
|
}
|
|
132
130
|
}
|
|
133
|
-
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// TP5 Style for Waffle Chart
|
|
134
|
+
.type-waffle-chart {
|
|
135
|
+
&.waffle__style--tp5 {
|
|
136
|
+
.cove-component__content {
|
|
137
|
+
background: none !important;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.cdc-callout {
|
|
141
|
+
box-shadow: 0 2px 4px rgb(159 159 159 / 10%);
|
|
142
|
+
margin: 0 !important;
|
|
143
|
+
padding: 1.5rem;
|
|
144
|
+
background-color: var(--colors-cyan-10, #eff9fa);
|
|
145
|
+
border: 1px solid var(--colors-cyan-15, #dff2f6);
|
|
146
|
+
position: relative;
|
|
147
|
+
border-radius: 0.25rem;
|
|
148
|
+
flex-wrap: wrap;
|
|
149
|
+
gap: 0.5rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.cdc-callout__icon {
|
|
153
|
+
position: absolute;
|
|
154
|
+
font-family: var(--icons-cdc);
|
|
155
|
+
top: -0.65rem;
|
|
156
|
+
right: 1rem;
|
|
157
|
+
font-size: 2rem;
|
|
158
|
+
color: var(--colors-cyan-60v);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.cdc-callout__flag {
|
|
162
|
+
position: absolute;
|
|
163
|
+
top: -0.25rem;
|
|
164
|
+
right: 1.08rem;
|
|
165
|
+
width: 1.85rem;
|
|
166
|
+
height: auto;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.cove-waffle-chart {
|
|
170
|
+
padding: 0;
|
|
171
|
+
row-gap: 1rem;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.cove-waffle-chart__chart {
|
|
175
|
+
margin-bottom: 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.cove-waffle-chart__data {
|
|
179
|
+
margin-bottom: 0;
|
|
180
|
+
align-content: flex-start;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.cdc-callout__heading {
|
|
184
|
+
font-family: var(--fonts-nunito) !important;
|
|
185
|
+
width: 100%;
|
|
186
|
+
font-size: 1.1rem;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.cove-waffle-chart__data--text {
|
|
190
|
+
margin-top: 0.5rem;
|
|
191
|
+
font-size: 1rem;
|
|
192
|
+
}
|
|
193
|
+
.cove-waffle-chart__subtext {
|
|
194
|
+
font-size: 1rem;
|
|
195
|
+
}
|
|
196
|
+
.cove-waffle-chart__data--primary {
|
|
197
|
+
font-size: 2rem;
|
|
198
|
+
color: var(--colors-cyan-60v);
|
|
199
|
+
font-weight: 400;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// White background variant (when "Use White Background Style" is checked)
|
|
203
|
+
&.white-background-style {
|
|
204
|
+
.cove-component__content {
|
|
205
|
+
background: white !important;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.cdc-callout {
|
|
209
|
+
background: transparent !important;
|
|
210
|
+
border: 1px solid #009ec1 !important;
|
|
211
|
+
box-shadow: 0 2px 4px rgb(159 159 159 / 10%);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|