@cdc/chart 4.22.10 → 4.22.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.
Files changed (72) hide show
  1. package/README.md +5 -5
  2. package/dist/cdcchart.js +4 -4
  3. package/examples/age-adjusted-rates.json +1486 -1218
  4. package/examples/case-rate-example-config.json +1 -1
  5. package/examples/covid-confidence-example-config.json +33 -33
  6. package/examples/covid-example-config.json +34 -34
  7. package/examples/covid-example-data-confidence.json +30 -30
  8. package/examples/covid-example-data.json +20 -20
  9. package/examples/cutoff-example-config.json +36 -36
  10. package/examples/cutoff-example-data.json +36 -36
  11. package/examples/date-exclusions-config.json +1 -1
  12. package/examples/dynamic-legends.json +124 -124
  13. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
  14. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
  15. package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
  16. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +136 -136
  17. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
  18. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
  19. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
  20. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +110 -110
  21. package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
  22. package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
  23. package/examples/horizontal-chart.json +35 -35
  24. package/examples/horizontal-stacked-bar-chart.json +34 -34
  25. package/examples/line-chart.json +75 -75
  26. package/examples/paired-bar-data.json +16 -14
  27. package/examples/paired-bar-example.json +48 -48
  28. package/examples/paired-bar-formatted.json +36 -36
  29. package/examples/planet-chart-horizontal-example-config.json +33 -33
  30. package/examples/planet-combo-example-config.json +34 -31
  31. package/examples/planet-example-config.json +35 -33
  32. package/examples/planet-example-data.json +56 -56
  33. package/examples/planet-pie-example-config.json +28 -28
  34. package/examples/private/filters.json +170 -0
  35. package/examples/private/line-test-data.json +21 -21
  36. package/examples/private/line-test-two.json +209 -215
  37. package/examples/private/line-test.json +101 -101
  38. package/examples/private/new.json +48800 -0
  39. package/examples/private/shawn.json +1105 -1295
  40. package/examples/private/test.json +10123 -10123
  41. package/examples/private/yaxis-test.json +4 -3
  42. package/examples/private/yaxis.json +26 -26
  43. package/examples/stacked-vertical-bar-example.json +1 -1
  44. package/examples/temp-example-config.json +61 -54
  45. package/examples/temp-example-data.json +1 -1
  46. package/package.json +2 -2
  47. package/src/CdcChart.tsx +339 -380
  48. package/src/components/BarChart.tsx +425 -469
  49. package/src/components/DataTable.tsx +164 -195
  50. package/src/components/EditorPanel.js +1009 -710
  51. package/src/components/Legend.js +279 -329
  52. package/src/components/LineChart.tsx +90 -79
  53. package/src/components/LinearChart.tsx +376 -434
  54. package/src/components/PairedBarChart.tsx +197 -213
  55. package/src/components/PieChart.tsx +95 -151
  56. package/src/components/SparkLine.js +179 -201
  57. package/src/components/useIntersectionObserver.tsx +17 -20
  58. package/src/context.tsx +3 -3
  59. package/src/data/initial-state.js +37 -16
  60. package/src/hooks/useActiveElement.js +13 -13
  61. package/src/hooks/useChartClasses.js +34 -28
  62. package/src/hooks/useColorPalette.ts +56 -63
  63. package/src/hooks/useLegendClasses.js +18 -10
  64. package/src/hooks/useReduceData.ts +62 -78
  65. package/src/hooks/useRightAxis.js +25 -0
  66. package/src/hooks/useTopAxis.js +6 -0
  67. package/src/index.html +45 -45
  68. package/src/index.tsx +13 -16
  69. package/src/scss/DataTable.scss +5 -4
  70. package/src/scss/editor-panel.scss +71 -69
  71. package/src/scss/main.scss +157 -114
  72. package/src/scss/variables.scss +1 -1
@@ -1,334 +1,284 @@
1
- import React, { useContext, useEffect } from 'react';
2
- import Context from '../context';
3
- import parse from 'html-react-parser';
4
- import { LegendOrdinal, LegendItem, LegendLabel } from '@visx/legend';
5
- import LegendCircle from '@cdc/core/components/LegendCircle';
6
-
7
- import useLegendClasses from './../hooks/useLegendClasses';
1
+ import React, { useContext, useEffect } from 'react'
2
+ import Context from '../context'
3
+ import parse from 'html-react-parser'
4
+ import { LegendOrdinal, LegendItem, LegendLabel } from '@visx/legend'
5
+ import LegendCircle from '@cdc/core/components/LegendCircle'
8
6
 
7
+ import useLegendClasses from './../hooks/useLegendClasses'
9
8
 
10
9
  const Legend = () => {
11
-
12
- const {
13
- config,
14
- legend,
15
- colorScale,
16
- seriesHighlight,
17
- highlight,
18
- highlightReset,
19
- setSeriesHighlight,
20
- dynamicLegendItems,
21
- setDynamicLegendItems,
22
- transformedData: data,
23
- setFilteredData,
24
- colorPalettes,
25
- rawData,
26
- setConfig
27
- } = useContext(Context);
28
-
29
- const {innerClasses, containerClasses} = useLegendClasses(config)
30
-
31
- useEffect(() => {
32
- if(dynamicLegendItems.length === 0) return;
33
-
34
- let itemsToHighlight = dynamicLegendItems.map( item => item.text);
35
-
36
- setSeriesHighlight( itemsToHighlight )
37
-
38
- let colsToKeep = [...itemsToHighlight]
39
- let tmpLabels = [];
40
-
41
- rawData.map( dataItem => {
42
- let tmp = {}
43
- colsToKeep.map( col => {
44
- tmp[col] = isNaN(dataItem[col]) ? dataItem[col] : dataItem[col]
45
- })
46
- return tmp
47
- })
48
-
49
- colsToKeep.map( col => {
50
- tmpLabels[col] = col
51
- })
52
-
53
- if(dynamicLegendItems.length > 0) {
54
- setConfig({
55
- ...config,
56
- runtime: {
57
- ...config.runtime,
58
- seriesKeys: colsToKeep,
59
- seriesLabels: tmpLabels
60
- }
61
- })
62
- }
63
-
64
-
65
-
66
- }, [dynamicLegendItems]);
67
-
68
-
69
- useEffect(() => {
70
- if(dynamicLegendItems.length === 0 ) {
71
-
72
- // loop through all labels and add keys
73
- let resetSeriesNames = [...config.runtime.seriesLabelsAll]
74
- let tmpLabels = [];
75
- config.runtime.seriesLabelsAll.map( item => {
76
- resetSeriesNames.map( col => {
77
- tmpLabels[col] = col
78
- })
79
- })
80
-
81
- setConfig({
82
- ...config,
83
- runtime: {
84
- ...config.runtime,
85
- seriesKeys: config.runtime.seriesLabelsAll,
86
- seriesLabels: tmpLabels
87
- }
88
- })
89
-
90
- }
91
- }, [dynamicLegendItems]);
92
-
93
- const removeDynamicLegendItem = (label) => {
94
- let newLegendItems = dynamicLegendItems.filter((item) => item.text !== label.text);
95
- let newLegendItemsText = newLegendItems.map(item => item.text )
96
- setDynamicLegendItems( newLegendItems )
97
- setSeriesHighlight( newLegendItemsText)
98
- }
99
- const handleDynamicLegendChange = (e) => {
100
- setDynamicLegendItems([...dynamicLegendItems, JSON.parse(e.target.value)])
101
- }
102
-
103
- const createLegendLabels = (data,defaultLabels) => {
104
- const colorCode = config.legend?.colorCode;
105
- if( config.visualizationType !=='Bar' || config.visualizationSubType !=="regular" || !colorCode || config.series?.length > 1){
106
- return defaultLabels;
107
- };
108
- let palette = colorPalettes[config.palette];
109
-
110
- while(data.length > palette.length) {
111
- palette = palette.concat(palette);
112
- }
113
- palette = palette.slice(0, data.length);
114
- //store uniq values to Set by colorCode
115
- const set = new Set();
116
-
117
- data.forEach(d=>set.add(d[colorCode]));
118
-
119
- // create labels with uniq values
120
- const uniqeLabels = Array.from(set).map((val,i)=>{
121
- const newLabel = {
122
- datum :val,
123
- index:i,
124
- text:val,
125
- value:palette[i]
126
- };
127
- return newLabel;
128
- });
129
-
130
- return uniqeLabels;
131
- };
132
-
133
-
134
-
135
- if (!legend) return;
136
-
137
- if (!legend.dynamicLegend) return (
138
- <aside id="legend" className={containerClasses.join(' ')} role="region" aria-label="legend" tabIndex={0}>
139
- {legend.label && <h2>{parse(legend.label)}</h2>}
140
- {legend.description && <p>{parse(legend.description)}</p>}
141
- <LegendOrdinal
142
- scale={colorScale}
143
- itemDirection="row"
144
- labelMargin="0 20px 0 0"
145
- shapeMargin="0 10px 0"
146
- >
147
-
148
- {labels => (
149
- <div className={innerClasses.join(' ')}>
150
- {createLegendLabels(data,labels).map((label, i) => {
151
-
152
- let className = 'legend-item'
153
- let itemName = label.datum
154
-
155
- // Filter excluded data keys from legend
156
- if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
157
- return
158
- }
159
-
160
- if (config.runtime.seriesLabels) {
161
- let index = config.runtime.seriesLabelsAll.indexOf(itemName)
162
- itemName = config.runtime.seriesKeys[index]
163
- }
164
-
165
- if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
166
- className += ' inactive'
167
- }
168
-
169
-
170
- return (
171
- <LegendItem
172
- className={className}
173
- tabIndex={0}
174
- key={`legend-quantile-${i}`}
175
- onKeyPress={(e) => {
176
- if (e.key === 'Enter') {
177
- highlight(label);
178
- }
179
- }}
180
- onClick={() => {
181
- highlight(label);
182
- }}
183
- >
184
- <LegendCircle fill={label.value} />
185
- <LegendLabel align="left" margin="0 0 0 4px">
186
- {label.text}
187
- </LegendLabel>
188
- </LegendItem>
189
- )
190
- })}
191
- {seriesHighlight.length > 0 && <button className={`legend-reset ${config.theme}`} onClick={ (labels) => highlightReset(labels) } tabIndex={0}>Reset</button>}
192
- </div>
193
- )}
194
- </LegendOrdinal>
195
- </aside>
196
- )
197
-
198
- return (
199
- <aside id="legend" className={containerClasses.join(' ')} role="region" aria-label="legend" tabIndex={0}>
200
- {legend.label && <h2>{parse(legend.label)}</h2>}
201
- {legend.description && <p>{parse(legend.description)}</p>}
202
-
203
- <LegendOrdinal
204
- scale={colorScale}
205
- itemDirection="row"
206
- labelMargin="0 20px 0 0"
207
- shapeMargin="0 10px 0"
208
- >
209
-
210
- {labels => {
211
- if (
212
- (Number(config.legend.dynamicLegendItemLimit) > dynamicLegendItems.length) // legend items are less than limit
213
- && (dynamicLegendItems.length !== config.runtime.seriesLabelsAll.length) ) // legend items are equal to series length
214
- {
215
- return (
216
- <select
217
- className='dynamic-legend-dropdown'
218
- onChange={(e) => handleDynamicLegendChange(e) }
219
- >
220
- <option
221
- className={'all'}
222
- tabIndex={0}
223
- value={JSON.stringify({ text: config.legend.dynamicLegendDefaultText })}
224
-
225
- >
226
- {config.legend.dynamicLegendDefaultText}
227
- </option>
228
- {labels.map((label, i) => {
229
- let className = 'legend-item'
230
- let itemName = label.datum
231
- let inDynamicList = false;
232
-
233
- // Filter excluded data keys from legend
234
- if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
235
- return
236
- }
237
-
238
- if (config.runtime.seriesLabels) {
239
- let index = config.runtime.seriesLabelsAll.indexOf(itemName)
240
- itemName = config.runtime.seriesKeys[index]
241
- }
242
-
243
- if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
244
- className += ' inactive'
245
- }
246
-
247
- dynamicLegendItems.map(listItem => {
248
- if(listItem.text === label.text) {
249
- inDynamicList = true;
250
- }
251
- })
252
-
253
- if(inDynamicList) return true;
254
- let palette = colorPalettes[config.palette];
255
-
256
- label.value = palette[dynamicLegendItems.length]
257
-
258
- return (
259
- <option
260
- className={className}
261
- tabIndex={0}
262
- value={JSON.stringify(label)}
263
-
264
- >
265
- {label.text}
266
- </option>
267
- )
268
- })}
269
- </select>
270
- )
271
- } else {
272
- return config.legend.dynamicLegendItemLimitMessage
273
- }
274
- }}
275
- </LegendOrdinal>
276
-
277
-
278
- <div className="dynamic-legend-list">
279
- {dynamicLegendItems.map((label, i) => {
280
-
281
- let className = ['legend-item']
282
- let itemName = label.text
283
- let palette = colorPalettes[config.palette];
284
-
285
- // Filter excluded data keys from legend
286
- if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
287
- return
288
- }
289
-
290
- if (config.runtime.seriesLabels && !config.legend.dynamicLegend) {
291
- let index = config.runtime.seriesLabelsAll.indexOf(itemName)
292
- itemName = config.runtime.seriesKeys[index]
293
- }
294
-
295
- if (seriesHighlight.length > 0 && !seriesHighlight.includes(itemName)) {
296
- className.push('inactive')
297
- }
298
-
299
- if(seriesHighlight.length === 0 && config.legend.dynamicLegend) {
300
- className.push('inactive')
301
- }
302
-
303
- return (
304
- <>
305
- <LegendItem
306
- className={className.join(' ')}
307
- tabIndex={0}
308
- key={`dynamic-legend-item-${i}`}
309
- alignItems="center"
310
-
311
- >
312
- <button
313
- className="btn-wrapper"
314
- onClick={() => {
315
- highlight(label);
316
- }}
317
- >
318
- <LegendCircle fill={palette[i]} config={config} />
319
- <LegendLabel align="space-between" margin="4px 0 0 4px">
320
- {label.text}
321
- </LegendLabel>
322
- </button>
323
- <button onClick={() => removeDynamicLegendItem(label)}>x</button>
324
- </LegendItem>
325
- </>
326
- )
327
- })}
328
- </div>
329
- {seriesHighlight.length < dynamicLegendItems.length && <button className={`legend-reset legend-reset--dynamic ${config.theme}`} onClick={highlightReset} tabIndex={0}>Reset</button>}
330
- </aside>
331
- )
10
+ const { config, legend, colorScale, seriesHighlight, highlight, highlightReset, setSeriesHighlight, dynamicLegendItems, setDynamicLegendItems, transformedData: data, setFilteredData, colorPalettes, rawData, setConfig } = useContext(Context)
11
+
12
+ const { innerClasses, containerClasses } = useLegendClasses(config)
13
+
14
+ useEffect(() => {
15
+ if (dynamicLegendItems.length === 0) return
16
+
17
+ let itemsToHighlight = dynamicLegendItems.map(item => item.text)
18
+
19
+ setSeriesHighlight(itemsToHighlight)
20
+
21
+ let colsToKeep = [...itemsToHighlight]
22
+ let tmpLabels = []
23
+
24
+ rawData.map(dataItem => {
25
+ let tmp = {}
26
+ colsToKeep.map(col => {
27
+ tmp[col] = isNaN(dataItem[col]) ? dataItem[col] : dataItem[col]
28
+ })
29
+ return tmp
30
+ })
31
+
32
+ colsToKeep.map(col => {
33
+ tmpLabels[col] = col
34
+ })
35
+
36
+ if (dynamicLegendItems.length > 0) {
37
+ setConfig({
38
+ ...config,
39
+ runtime: {
40
+ ...config.runtime,
41
+ seriesKeys: colsToKeep,
42
+ seriesLabels: tmpLabels
43
+ }
44
+ })
45
+ }
46
+ }, [dynamicLegendItems])
47
+
48
+ useEffect(() => {
49
+ if (dynamicLegendItems.length === 0) {
50
+ // loop through all labels and add keys
51
+ let resetSeriesNames = [...config.runtime.seriesLabelsAll]
52
+ let tmpLabels = []
53
+ config.runtime.seriesLabelsAll.map(item => {
54
+ resetSeriesNames.map(col => {
55
+ tmpLabels[col] = col
56
+ })
57
+ })
58
+
59
+ setConfig({
60
+ ...config,
61
+ runtime: {
62
+ ...config.runtime,
63
+ seriesKeys: config.runtime.seriesLabelsAll,
64
+ seriesLabels: tmpLabels
65
+ }
66
+ })
67
+ }
68
+ }, [dynamicLegendItems])
69
+
70
+ const removeDynamicLegendItem = label => {
71
+ let newLegendItems = dynamicLegendItems.filter(item => item.text !== label.text)
72
+ let newLegendItemsText = newLegendItems.map(item => item.text)
73
+ setDynamicLegendItems(newLegendItems)
74
+ setSeriesHighlight(newLegendItemsText)
75
+ }
76
+ const handleDynamicLegendChange = e => {
77
+ setDynamicLegendItems([...dynamicLegendItems, JSON.parse(e.target.value)])
78
+ }
79
+
80
+ const createLegendLabels = (data, defaultLabels) => {
81
+ const colorCode = config.legend?.colorCode
82
+ if (config.visualizationType !== 'Bar' || config.visualizationSubType !== 'regular' || !colorCode || config.series?.length > 1) {
83
+ return defaultLabels
84
+ }
85
+ let palette = colorPalettes[config.palette]
86
+
87
+ while (data.length > palette.length) {
88
+ palette = palette.concat(palette)
89
+ }
90
+ palette = palette.slice(0, data.length)
91
+ //store uniq values to Set by colorCode
92
+ const set = new Set()
93
+
94
+ data.forEach(d => set.add(d[colorCode]))
95
+
96
+ // create labels with uniq values
97
+ const uniqeLabels = Array.from(set).map((val, i) => {
98
+ const newLabel = {
99
+ datum: val,
100
+ index: i,
101
+ text: val,
102
+ value: palette[i]
103
+ }
104
+ return newLabel
105
+ })
106
+
107
+ return uniqeLabels
108
+ }
109
+
110
+ if (!legend) return
111
+
112
+ if (!legend.dynamicLegend)
113
+ return (
114
+ <aside id='legend' className={containerClasses.join(' ')} role='region' aria-label='legend' tabIndex={0}>
115
+ {legend.label && <h2>{parse(legend.label)}</h2>}
116
+ {legend.description && <p>{parse(legend.description)}</p>}
117
+ <LegendOrdinal scale={colorScale} itemDirection='row' labelMargin='0 20px 0 0' shapeMargin='0 10px 0'>
118
+ {labels => (
119
+ <div className={innerClasses.join(' ')}>
120
+ {createLegendLabels(data, labels).map((label, i) => {
121
+ let className = 'legend-item'
122
+ let itemName = label.datum
123
+
124
+ // Filter excluded data keys from legend
125
+ if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
126
+ return
127
+ }
128
+
129
+ if (config.runtime.seriesLabels) {
130
+ let index = config.runtime.seriesLabelsAll.indexOf(itemName)
131
+ itemName = config.runtime.seriesKeys[index]
132
+ }
133
+
134
+ if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
135
+ className += ' inactive'
136
+ }
137
+
138
+ return (
139
+ <LegendItem
140
+ className={className}
141
+ tabIndex={0}
142
+ key={`legend-quantile-${i}`}
143
+ onKeyPress={e => {
144
+ if (e.key === 'Enter') {
145
+ highlight(label)
146
+ }
147
+ }}
148
+ onClick={() => {
149
+ highlight(label)
150
+ }}
151
+ >
152
+ <LegendCircle fill={label.value} />
153
+ <LegendLabel align='left' margin='0 0 0 4px'>
154
+ {label.text}
155
+ </LegendLabel>
156
+ </LegendItem>
157
+ )
158
+ })}
159
+ {seriesHighlight.length > 0 && (
160
+ <button className={`legend-reset ${config.theme}`} onClick={labels => highlightReset(labels)} tabIndex={0}>
161
+ Reset
162
+ </button>
163
+ )}
164
+ </div>
165
+ )}
166
+ </LegendOrdinal>
167
+ </aside>
168
+ )
169
+
170
+ return (
171
+ <aside id='legend' className={containerClasses.join(' ')} role='region' aria-label='legend' tabIndex={0}>
172
+ {legend.label && <h2>{parse(legend.label)}</h2>}
173
+ {legend.description && <p>{parse(legend.description)}</p>}
174
+
175
+ <LegendOrdinal scale={colorScale} itemDirection='row' labelMargin='0 20px 0 0' shapeMargin='0 10px 0'>
176
+ {labels => {
177
+ if (
178
+ Number(config.legend.dynamicLegendItemLimit) > dynamicLegendItems.length && // legend items are less than limit
179
+ dynamicLegendItems.length !== config.runtime.seriesLabelsAll.length
180
+ ) {
181
+ // legend items are equal to series length
182
+ return (
183
+ <select className='dynamic-legend-dropdown' onChange={e => handleDynamicLegendChange(e)}>
184
+ <option className={'all'} tabIndex={0} value={JSON.stringify({ text: config.legend.dynamicLegendDefaultText })}>
185
+ {config.legend.dynamicLegendDefaultText}
186
+ </option>
187
+ {labels.map((label, i) => {
188
+ let className = 'legend-item'
189
+ let itemName = label.datum
190
+ let inDynamicList = false
191
+
192
+ // Filter excluded data keys from legend
193
+ if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
194
+ return
195
+ }
196
+
197
+ if (config.runtime.seriesLabels) {
198
+ let index = config.runtime.seriesLabelsAll.indexOf(itemName)
199
+ itemName = config.runtime.seriesKeys[index]
200
+ }
201
+
202
+ if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
203
+ className += ' inactive'
204
+ }
205
+
206
+ dynamicLegendItems.map(listItem => {
207
+ if (listItem.text === label.text) {
208
+ inDynamicList = true
209
+ }
210
+ })
211
+
212
+ if (inDynamicList) return true
213
+ let palette = colorPalettes[config.palette]
214
+
215
+ label.value = palette[dynamicLegendItems.length]
216
+
217
+ return (
218
+ <option className={className} tabIndex={0} value={JSON.stringify(label)}>
219
+ {label.text}
220
+ </option>
221
+ )
222
+ })}
223
+ </select>
224
+ )
225
+ } else {
226
+ return config.legend.dynamicLegendItemLimitMessage
227
+ }
228
+ }}
229
+ </LegendOrdinal>
230
+
231
+ <div className='dynamic-legend-list'>
232
+ {dynamicLegendItems.map((label, i) => {
233
+ let className = ['legend-item']
234
+ let itemName = label.text
235
+ let palette = colorPalettes[config.palette]
236
+
237
+ // Filter excluded data keys from legend
238
+ if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
239
+ return
240
+ }
241
+
242
+ if (config.runtime.seriesLabels && !config.legend.dynamicLegend) {
243
+ let index = config.runtime.seriesLabelsAll.indexOf(itemName)
244
+ itemName = config.runtime.seriesKeys[index]
245
+ }
246
+
247
+ if (seriesHighlight.length > 0 && !seriesHighlight.includes(itemName)) {
248
+ className.push('inactive')
249
+ }
250
+
251
+ if (seriesHighlight.length === 0 && config.legend.dynamicLegend) {
252
+ className.push('inactive')
253
+ }
254
+
255
+ return (
256
+ <>
257
+ <LegendItem className={className.join(' ')} tabIndex={0} key={`dynamic-legend-item-${i}`} alignItems='center'>
258
+ <button
259
+ className='btn-wrapper'
260
+ onClick={() => {
261
+ highlight(label)
262
+ }}
263
+ >
264
+ <LegendCircle fill={palette[i]} config={config} />
265
+ <LegendLabel align='space-between' margin='4px 0 0 4px'>
266
+ {label.text}
267
+ </LegendLabel>
268
+ </button>
269
+ <button onClick={() => removeDynamicLegendItem(label)}>x</button>
270
+ </LegendItem>
271
+ </>
272
+ )
273
+ })}
274
+ </div>
275
+ {seriesHighlight.length < dynamicLegendItems.length && (
276
+ <button className={`legend-reset legend-reset--dynamic ${config.theme}`} onClick={highlightReset} tabIndex={0}>
277
+ Reset
278
+ </button>
279
+ )}
280
+ </aside>
281
+ )
332
282
  }
333
283
 
334
- export default Legend;
284
+ export default Legend