@cdc/waffle-chart 4.26.1 → 4.26.3

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.
@@ -25,13 +25,14 @@ import { publish } from '@cdc/core/helpers/events'
25
25
  import chartReducer from './store/chart.reducer'
26
26
  import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
27
27
  import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
28
+ import { processMarkupVariables } from '@cdc/core/helpers/markupProcessor'
28
29
 
29
30
  import './scss/main.scss'
30
31
  import Title from '@cdc/core/components/ui/Title'
31
- import Layout from '@cdc/core/components/Layout'
32
+ import { VisualizationContainer, VisualizationContent } from '@cdc/core/components/Layout'
32
33
 
33
34
  // images
34
- import CalloutFlag from './images/callout-flag.svg?url'
35
+ import CalloutFlag from '@cdc/core/assets/callout-flag.svg?url'
35
36
 
36
37
  // TP5 Style Constants
37
38
  const TP5_NODE_WIDTH = 13
@@ -72,6 +73,59 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
72
73
  roundToPlace
73
74
  } = config
74
75
 
76
+ const processedTextFields = useMemo(() => {
77
+ if (!config.enableMarkupVariables || !config.markupVariables?.length) {
78
+ return {
79
+ title,
80
+ content,
81
+ subtext,
82
+ valueDescription: config.valueDescription
83
+ }
84
+ }
85
+
86
+ const markupOptions = {
87
+ isEditor,
88
+ showNoDataMessage: false,
89
+ allowHideSection: false,
90
+ filters: config.filters || [],
91
+ locale: config.locale,
92
+ dataMetadata: config.dataMetadata
93
+ }
94
+
95
+ return {
96
+ title: title
97
+ ? processMarkupVariables(title, config.data || [], config.markupVariables, markupOptions).processedContent
98
+ : title,
99
+ content: content
100
+ ? processMarkupVariables(content, config.data || [], config.markupVariables, markupOptions).processedContent
101
+ : content,
102
+ subtext: subtext
103
+ ? processMarkupVariables(subtext, config.data || [], config.markupVariables, markupOptions).processedContent
104
+ : subtext,
105
+ valueDescription: config.valueDescription
106
+ ? processMarkupVariables(config.valueDescription, config.data || [], config.markupVariables, markupOptions)
107
+ .processedContent
108
+ : config.valueDescription
109
+ }
110
+ }, [
111
+ config.enableMarkupVariables,
112
+ config.markupVariables,
113
+ config.data,
114
+ config.filters,
115
+ config.locale,
116
+ config.dataMetadata,
117
+ config.valueDescription,
118
+ title,
119
+ content,
120
+ subtext,
121
+ isEditor
122
+ ])
123
+
124
+ const processedTitle = processedTextFields.title
125
+ const processedContent = processedTextFields.content
126
+ const processedSubtext = processedTextFields.subtext
127
+ const processedValueDescription = processedTextFields.valueDescription
128
+
75
129
  const gaugeColor = config.visual.colors[config.theme]
76
130
  let dataFontSize = config.fontSize ? { fontSize: config.fontSize + 'px' } : null
77
131
 
@@ -351,7 +405,7 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
351
405
  return setRatio() + 2
352
406
  }, [nodeWidth, nodeSpacer, config.visualizationType])
353
407
 
354
- const { innerContainerClasses, contentClasses } = useDataVizClasses(config)
408
+ const { contentClasses } = useDataVizClasses(config)
355
409
 
356
410
  const xScale = scaleLinear({
357
411
  domain: [0, waffleDenominator],
@@ -397,103 +451,182 @@ const WaffleChart = ({ config, isEditor, link = '', showConfigConfirm, updateCon
397
451
  <Error updateConfig={updateConfig} config={config} />
398
452
  )}
399
453
  {config.newViz && showConfigConfirm && <Confirm updateConfig={updateConfig} config={config} />}
400
- <div className='cove-component__content-wrap p-0'>
401
- {config.visualizationType === 'Gauge' && (
402
- <div className={`cove-gauge-chart${config.overallFontSize ? ' font-' + config.overallFontSize : ''}`}>
403
- <div className='cove-gauge-chart__chart'>
404
- <div className='cove-waffle-chart__data--primary' style={dataFontSize}>
405
- {prefix ? prefix : ' '}
406
- {config.showPercent ? dataPercentage : waffleNumerator}
407
- {suffix ? suffix + ' ' : ' '} {config.valueDescription}{' '}
408
- {config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
409
- </div>
410
- <div className='cove-waffle-chart__data--text'>{parse(content)}</div>
411
- <svg height={config.gauge.height + 4} width={'100%'} style={{ overflow: 'visible' }}>
412
- <Group top={2} left={2}>
413
- <foreignObject
414
- style={{ border: '1px solid black' }}
415
- x={0}
416
- y={0}
417
- width={config.gauge.width}
418
- height={config.gauge.height}
419
- fill='#fff'
420
- />
421
- <Bar x={0} y={0} width={xScale(waffleNumerator)} height={config.gauge.height} fill={gaugeColor} />
422
- </Group>
423
- </svg>
424
- <div className={'cove-waffle-chart__subtext subtext'}>{parse(subtext)}</div>
425
- </div>
426
- </div>
427
- )}
428
- {config.visualizationType !== 'Gauge' && (
429
- <div
430
- className={`cove-waffle-chart${orientation === 'vertical' ? ' cove-waffle-chart--verical' : ''}${
431
- config.overallFontSize ? ' font-' + config.overallFontSize : ''
432
- }`}
433
- >
434
- <div className='cove-waffle-chart__chart' style={{ width: setRatio() }}>
435
- <svg width={setSvgSize()} height={setSvgSize()} style={{ display: 'block' }}>
436
- <Group top={1} left={1}>
437
- {buildWaffle()}
438
- </Group>
439
- </svg>
440
- </div>
441
- {(dataPercentage || content) && (
442
- <div className='cove-waffle-chart__data'>
443
- {dataPercentage && (
444
- <div className='cove-waffle-chart__data--primary' style={dataFontSize}>
445
- {prefix ? prefix : null}
446
- {dataPercentage}
447
- {suffix ? suffix : null}
454
+ {(config.visualizationType === 'Gauge' || config.visualizationType === 'TP5 Gauge') && (
455
+ <div className={`cove-gauge-chart${config.overallFontSize ? ' font-' + config.overallFontSize : ''}`}>
456
+ <div className='cove-gauge-chart__chart'>
457
+ {config.visualizationType === 'TP5 Gauge' ? (
458
+ <>
459
+ <div
460
+ className={`cove-gauge-chart__body d-flex flex-row align-items-start flex-grow-1${
461
+ !processedContent ? ' justify-content-center' : ''
462
+ }`}
463
+ >
464
+ <div className='cove-gauge-chart__value-section flex-shrink-0'>
465
+ <div className='cove-waffle-chart__data--primary' style={dataFontSize}>
466
+ {prefix ? prefix : ' '}
467
+ {config.showPercent ? dataPercentage : waffleNumerator}
468
+ {suffix ? suffix + ' ' : ' '} {processedValueDescription}{' '}
469
+ {config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
470
+ </div>
471
+ </div>
472
+ <div className='cove-gauge-chart__content flex-grow-1 d-flex flex-column min-w-0'>
473
+ {processedContent ? (
474
+ <div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>
475
+ ) : (
476
+ <div className='cove-waffle-chart__data--text' aria-hidden='true'>
477
+ &nbsp;
478
+ </div>
479
+ )}
448
480
  </div>
481
+ </div>
482
+ <svg
483
+ height={config.gauge.height + 2}
484
+ width={'100%'}
485
+ className='mt-2'
486
+ style={{ overflow: 'visible', padding: '1px' }}
487
+ >
488
+ <Group>
489
+ <Bar
490
+ x={0}
491
+ y={0}
492
+ width={config.gauge.width}
493
+ height={config.gauge.height}
494
+ fill='#dff2f6'
495
+ stroke='#007A99'
496
+ strokeWidth={1}
497
+ rx={10}
498
+ ry={10}
499
+ />
500
+ <Bar
501
+ x={0}
502
+ y={0}
503
+ width={xScale(waffleNumerator)}
504
+ height={config.gauge.height}
505
+ fill='#007A99'
506
+ rx={10}
507
+ ry={10}
508
+ />
509
+ </Group>
510
+ </svg>
511
+ {processedSubtext && (
512
+ <div className='cove-waffle-chart__subtext subtext fst-italic mt-2'>{parse(processedSubtext)}</div>
449
513
  )}
450
- <div className='cove-waffle-chart__data--text'>{parse(content)}</div>
451
-
452
- {subtext && <div className='cove-waffle-chart__subtext subtext fst-italic'>{parse(subtext)}</div>}
453
- </div>
514
+ </>
515
+ ) : (
516
+ <>
517
+ <div className='cove-waffle-chart__data--primary' style={dataFontSize}>
518
+ {prefix ? prefix : ' '}
519
+ {config.showPercent ? dataPercentage : waffleNumerator}
520
+ {suffix ? suffix + ' ' : ' '} {processedValueDescription}{' '}
521
+ {config.showDenominator && waffleDenominator ? waffleDenominator : ' '}
522
+ </div>
523
+ <div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>
524
+ <svg height={config.gauge.height} width={'100%'}>
525
+ <Group>
526
+ <Bar
527
+ x={0}
528
+ y={0}
529
+ width={config.gauge.width}
530
+ height={config.gauge.height}
531
+ fill='#e0e0e0'
532
+ stroke='#999'
533
+ strokeWidth={1}
534
+ rx={4}
535
+ ry={4}
536
+ />
537
+ <Bar
538
+ x={0}
539
+ y={0}
540
+ width={xScale(waffleNumerator)}
541
+ height={config.gauge.height}
542
+ fill={gaugeColor}
543
+ rx={4}
544
+ ry={4}
545
+ />
546
+ </Group>
547
+ </svg>
548
+ <div className={'cove-waffle-chart__subtext subtext'}>{parse(processedSubtext)}</div>
549
+ </>
454
550
  )}
455
551
  </div>
456
- )}
457
- </div>
552
+ </div>
553
+ )}
554
+ {config.visualizationType !== 'Gauge' && config.visualizationType !== 'TP5 Gauge' && (
555
+ <div
556
+ className={`cove-waffle-chart${orientation === 'vertical' ? ' cove-waffle-chart--verical' : ''}${
557
+ config.overallFontSize ? ' font-' + config.overallFontSize : ''
558
+ }`}
559
+ >
560
+ <div className='cove-waffle-chart__chart' style={{ width: setRatio() }}>
561
+ <svg width={setSvgSize()} height={setSvgSize()} style={{ display: 'block' }}>
562
+ <Group top={1} left={1}>
563
+ {buildWaffle()}
564
+ </Group>
565
+ </svg>
566
+ </div>
567
+ {(dataPercentage || processedContent) && (
568
+ <div className='cove-waffle-chart__data'>
569
+ {dataPercentage && (
570
+ <div className='cove-waffle-chart__data--primary' style={dataFontSize}>
571
+ {prefix ? prefix : null}
572
+ {dataPercentage}
573
+ {suffix ? suffix : null}
574
+ </div>
575
+ )}
576
+ {processedContent && <div className='cove-waffle-chart__data--text'>{parse(processedContent)}</div>}
577
+
578
+ {processedSubtext && (
579
+ <div className='cove-waffle-chart__subtext subtext fst-italic'>{parse(processedSubtext)}</div>
580
+ )}
581
+ </div>
582
+ )}
583
+ </div>
584
+ )}
458
585
  </>
459
586
  )
460
587
 
461
- // TP5 Style: render with callout wrapper inside cove-component__content
462
- if (config.visualizationType === 'TP5 Waffle') {
588
+ // TP5 Style: render with callout wrapper inside cove-visualization__body
589
+ if (config.visualizationType === 'TP5 Waffle' || config.visualizationType === 'TP5 Gauge') {
463
590
  const calloutClasses = ['cdc-callout', 'd-flex', 'flex-column']
464
591
  if (!config.visual?.whiteBackground) {
465
592
  calloutClasses.push('dfe-block', 'cdc-callout--data')
466
593
  }
467
594
 
468
595
  return (
469
- <div className='cove-component__content p-0 border-0'>
596
+ <VisualizationContent
597
+ bodyClassName={['no-borders', ...contentClasses].filter(Boolean).join(' ')}
598
+ footer={link && link}
599
+ >
470
600
  <div className={calloutClasses.join(' ')}>
471
601
  {!config.visual?.whiteBackground && (
472
602
  <img src={CalloutFlag} alt='' className='cdc-callout__flag' aria-hidden='true' />
473
603
  )}
474
- {config.showTitle && title && title.trim() && (
475
- <h3 className='cdc-callout__heading fw-bold flex-shrink-0'>{parse(title)}</h3>
604
+ {config.showTitle && processedTitle && processedTitle.trim() && (
605
+ <h3 className='cdc-callout__heading fw-bold flex-shrink-0'>{parse(processedTitle)}</h3>
476
606
  )}
477
607
  <div className='w-100 mw-100 overflow-hidden'>{renderChartContent()}</div>
478
608
  </div>
479
- {link && link}
480
- </div>
609
+ </VisualizationContent>
481
610
  )
482
611
  }
483
612
 
484
613
  // Original Style: Regular title and content
485
614
  return (
486
- <div className='cove-component__content'>
487
- <Title
488
- showTitle={config.showTitle}
489
- title={title}
490
- titleStyle='legacy'
491
- config={config}
492
- classes={['chart-title', `${config.theme}`, 'mb-0']}
493
- />
494
- <div className={contentClasses.join(' ')}>{renderChartContent()}</div>
495
- {link && link}
496
- </div>
615
+ <VisualizationContent
616
+ bodyClassName={contentClasses.join(' ')}
617
+ header={
618
+ <Title
619
+ showTitle={config.showTitle}
620
+ title={processedTitle}
621
+ titleStyle='legacy'
622
+ config={config}
623
+ classes={['chart-title', `${config.theme}`, 'mb-0']}
624
+ />
625
+ }
626
+ footer={link && link}
627
+ >
628
+ {renderChartContent()}
629
+ </VisualizationContent>
497
630
  )
498
631
  }
499
632
 
@@ -535,7 +668,9 @@ const CdcWaffleChart = ({
535
668
  let responseData = response.data ?? {}
536
669
 
537
670
  if (response.dataUrl) {
538
- responseData = await fetchRemoteData(response.dataUrl)
671
+ const { data, dataMetadata } = await fetchRemoteData(response.dataUrl)
672
+ responseData = data
673
+ response.dataMetadata = dataMetadata
539
674
  }
540
675
 
541
676
  response.data = responseData
@@ -564,8 +699,7 @@ const CdcWaffleChart = ({
564
699
 
565
700
  //Load initial config
566
701
  useEffect(() => {
567
- // eslint-disable-next-line no-console
568
- loadConfig().catch(err => console.log(err))
702
+ loadConfig().catch(err => console.warn(err))
569
703
  }, [])
570
704
 
571
705
  useEffect(() => {
@@ -586,17 +720,12 @@ const CdcWaffleChart = ({
586
720
 
587
721
  if (loading === false) {
588
722
  content = (
589
- <>
590
- {isEditor && <EditorPanel showConfigConfirm={showConfigConfirm} />}
591
- <Layout.Responsive isEditor={isEditor}>
592
- <WaffleChart
593
- config={config}
594
- isEditor={isEditor}
595
- showConfigConfirm={showConfigConfirm}
596
- updateConfig={updateConfig}
597
- />
598
- </Layout.Responsive>
599
- </>
723
+ <WaffleChart
724
+ config={config}
725
+ isEditor={isEditor}
726
+ showConfigConfirm={showConfigConfirm}
727
+ updateConfig={updateConfig}
728
+ />
600
729
  )
601
730
  }
602
731
 
@@ -605,14 +734,15 @@ const CdcWaffleChart = ({
605
734
  <ConfigContext.Provider
606
735
  value={{ config, updateConfig, loading, data: config.data, setParentConfig, isDashboard, outerContainerRef }}
607
736
  >
608
- <Layout.VisualizationWrapper
737
+ <VisualizationContainer
609
738
  config={config}
610
739
  isEditor={isEditor}
740
+ currentViewport={currentViewport}
611
741
  ref={outerContainerRef}
612
- showEditorPanel={config?.showEditorPanel}
742
+ editorPanel={<EditorPanel showConfigConfirm={showConfigConfirm} />}
613
743
  >
614
744
  {content}
615
- </Layout.VisualizationWrapper>
745
+ </VisualizationContainer>
616
746
  </ConfigContext.Provider>
617
747
  </ErrorBoundary>
618
748
  )