@cdc/data-bite 4.25.10 → 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.
@@ -0,0 +1,542 @@
1
+ import { useContext } from 'react'
2
+
3
+ import { DATA_FUNCTIONS, DATA_OPERATORS } from '@cdc/core/helpers/constants'
4
+
5
+ // Context
6
+ import Context from '../../context'
7
+
8
+ // Components
9
+ import { EditorPanel as BaseEditorPanel } from '@cdc/core/components/EditorPanel/EditorPanel'
10
+ import '@cdc/core/styles/v2/components/editor.scss'
11
+ import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
12
+ import Tooltip from '@cdc/core/components/ui/Tooltip'
13
+ import Icon from '@cdc/core/components/ui/Icon'
14
+ import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
15
+ import { useFilterManagement } from '@cdc/core/hooks/useFilterManagement'
16
+ import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
17
+ import { useListManagement } from '@cdc/core/hooks/useListManagement'
18
+ import { BITE_LOCATIONS, IMAGE_POSITIONS } from '../../constants'
19
+ import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
20
+ import Button from '@cdc/core/components/elements/Button'
21
+ import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
22
+ import { VisualSection } from '@cdc/core/components/EditorPanel/sections/VisualSection'
23
+ import Accordion from '@cdc/core/components/ui/Accordion'
24
+
25
+ type DataBiteEditorPanelProps = {
26
+ // Add any props if needed
27
+ }
28
+
29
+ const EditorPanel: React.FC<DataBiteEditorPanelProps> = () => {
30
+ const { config, updateConfig, loading, data, setParentConfig, isDashboard } = useContext(Context)
31
+
32
+ const updateField = updateFieldFactory(config, updateConfig, true)
33
+
34
+ // Filters -----------------------------------------------
35
+ const { addNewFilter, removeFilter, updateFilterProp, getFilterColumnValues } = useFilterManagement(
36
+ config,
37
+ updateConfig,
38
+ data
39
+ )
40
+
41
+ // Extract column names from data with memoization (replaces getColumns)
42
+ const columns = useDataColumns(data)
43
+
44
+ // Dynamic Images ----------------------------------------
45
+ // Use standardized list management hook (Phase 2 improvement)
46
+ const images = useListManagement({
47
+ config,
48
+ updateConfig,
49
+ listPath: 'imageData.options',
50
+ createItem: () => ({
51
+ source: '',
52
+ arguments: [{ operator: '', threshold: '' }],
53
+ alt: '',
54
+ secondArgument: false
55
+ })
56
+ })
57
+
58
+ // Helper for removing second argument from dynamic image conditions
59
+ const removeDynamicArgument = (index: number) => {
60
+ const item = images.items[index]
61
+ if (item?.arguments?.length > 1) {
62
+ const updatedArguments = [...item.arguments]
63
+ updatedArguments.pop()
64
+ images.updateField(index, 'arguments', updatedArguments)
65
+ }
66
+ }
67
+
68
+ return (
69
+ <BaseEditorPanel
70
+ config={config}
71
+ updateConfig={updateConfig as (config: any) => void}
72
+ loading={loading}
73
+ setParentConfig={setParentConfig as ((config: any) => void) | undefined}
74
+ isDashboard={isDashboard}
75
+ title='Configure Data Bites'
76
+ >
77
+ {({ convertStateToConfig }) => (
78
+ <Accordion>
79
+ <Accordion.Section title='General'>
80
+ <Select
81
+ value={config.biteStyle}
82
+ fieldName='biteStyle'
83
+ label='Data Bite Style'
84
+ updateField={updateField}
85
+ options={Object.entries(BITE_LOCATIONS).map(([key, value]) => ({ value: key, label: value }))}
86
+ initial='Select'
87
+ />
88
+ <TextField
89
+ value={config.title}
90
+ fieldName='title'
91
+ label='Title'
92
+ placeholder='Data Bite Title'
93
+ updateField={updateField}
94
+ />
95
+ <CheckBox
96
+ value={config.visual?.showTitle}
97
+ section='visual'
98
+ checked={config.visual?.showTitle}
99
+ fieldName='showTitle'
100
+ label='Show Title'
101
+ updateField={updateField}
102
+ />
103
+
104
+ <TextField
105
+ type='textarea'
106
+ value={config.biteBody}
107
+ fieldName='biteBody'
108
+ label='Message'
109
+ updateField={updateField}
110
+ tooltip={
111
+ <Tooltip style={{ textTransform: 'none' }}>
112
+ <Tooltip.Target>
113
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
114
+ </Tooltip.Target>
115
+ <Tooltip.Content>
116
+ <p>
117
+ Enter the message text for the visualization. The following HTML tags are supported: strong, em,
118
+ sup, and sub.
119
+ </p>
120
+ </Tooltip.Content>
121
+ </Tooltip>
122
+ }
123
+ />
124
+ <TextField
125
+ value={config.subtext}
126
+ fieldName='subtext'
127
+ label='Subtext/Citation'
128
+ placeholder='Data Bite Subtext or Citation'
129
+ updateField={updateField}
130
+ tooltip={
131
+ <Tooltip style={{ textTransform: 'none' }}>
132
+ <Tooltip.Target>
133
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
134
+ </Tooltip.Target>
135
+ <Tooltip.Content>
136
+ <p>
137
+ Enter supporting text to display below the data visualization, if applicable. The following HTML
138
+ tags are supported: strong, em, sup, and sub. You can also use markup variables like{' '}
139
+ {'{{variable-name}}'} to display dynamic data.
140
+ </p>
141
+ </Tooltip.Content>
142
+ </Tooltip>
143
+ }
144
+ />
145
+ </Accordion.Section>
146
+
147
+ <Accordion.Section title='Data'>
148
+ <ul className='column-edit'>
149
+ <li className='two-col'>
150
+ <Select
151
+ value={config.dataColumn || ''}
152
+ fieldName='dataColumn'
153
+ label='Data Column'
154
+ updateField={updateField}
155
+ initial='Select'
156
+ required={true}
157
+ options={columns}
158
+ />
159
+ <Select
160
+ value={config.dataFunction || ''}
161
+ fieldName='dataFunction'
162
+ label='Data Function'
163
+ updateField={updateField}
164
+ initial='Select'
165
+ required={true}
166
+ options={
167
+ Array.isArray(DATA_FUNCTIONS) ? DATA_FUNCTIONS : DATA_FUNCTIONS ? Object.values(DATA_FUNCTIONS) : []
168
+ }
169
+ />
170
+ </li>
171
+ </ul>
172
+ <span className='divider-heading'>Number Formatting</span>
173
+ <ul className='column-edit'>
174
+ <li className='three-col'>
175
+ <TextField
176
+ value={config.dataFormat.prefix}
177
+ section='dataFormat'
178
+ fieldName='prefix'
179
+ label='Prefix'
180
+ updateField={updateField}
181
+ />
182
+ <TextField
183
+ value={config.dataFormat.suffix}
184
+ section='dataFormat'
185
+ fieldName='suffix'
186
+ label='Suffix'
187
+ updateField={updateField}
188
+ />
189
+ <TextField
190
+ type='number'
191
+ value={config.dataFormat.roundToPlace}
192
+ section='dataFormat'
193
+ fieldName='roundToPlace'
194
+ label='Round'
195
+ updateField={updateField}
196
+ min='0'
197
+ max='99'
198
+ />
199
+ </li>
200
+ </ul>
201
+ <CheckBox
202
+ value={config.dataFormat.commas}
203
+ section='dataFormat'
204
+ fieldName='commas'
205
+ label='Add commas'
206
+ updateField={updateField}
207
+ />
208
+ <CheckBox
209
+ value={config.dataFormat.ignoreZeros}
210
+ section='dataFormat'
211
+ fieldName='ignoreZeros'
212
+ label='Ignore Zeros'
213
+ updateField={updateField}
214
+ />
215
+ <hr className='accordion__divider' />
216
+
217
+ <label style={{ marginBottom: '1rem' }}>
218
+ <span className='edit-label'>
219
+ Data Point Filters
220
+ <Tooltip style={{ textTransform: 'none' }}>
221
+ <Tooltip.Target>
222
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
223
+ </Tooltip.Target>
224
+ <Tooltip.Content>
225
+ <p>
226
+ To refine the highlighted data point, specify one or more filters (e.g., "Male" and "Female" for a
227
+ column called "Sex").
228
+ </p>
229
+ </Tooltip.Content>
230
+ </Tooltip>
231
+ </span>
232
+ </label>
233
+ {config.filters && (
234
+ <ul className='filters-list'>
235
+ {config.filters.map((filter: any, index: number) => (
236
+ <fieldset className='edit-block' key={index}>
237
+ <button
238
+ type='button'
239
+ className='btn btn-danger'
240
+ onClick={() => {
241
+ removeFilter(index)
242
+ }}
243
+ >
244
+ Remove
245
+ </button>
246
+ <Select
247
+ value={filter.columnName ? filter.columnName : ''}
248
+ fieldName='columnName'
249
+ label={'Column Name'}
250
+ updateField={(section, subsection, fieldName, value) => updateFilterProp(fieldName, index, value)}
251
+ options={columns}
252
+ initial='- Select Option -'
253
+ />
254
+ <Select
255
+ value={filter.columnValue || ''}
256
+ fieldName='columnValue'
257
+ label='Column Value'
258
+ updateField={(section, subsection, fieldName, value) => updateFilterProp(fieldName, index, value)}
259
+ options={Array.isArray(getFilterColumnValues(index)) ? getFilterColumnValues(index) : []}
260
+ initial='- Select Option -'
261
+ />
262
+ </fieldset>
263
+ ))}
264
+ </ul>
265
+ )}
266
+ {(!config.filters || config.filters.length === 0) && (
267
+ <div>
268
+ <fieldset className='edit-block'>
269
+ <p style={{ textAlign: 'center' }}>There are currently no filters.</p>
270
+ </fieldset>
271
+ </div>
272
+ )}
273
+ <Button type='button' onClick={addNewFilter} className='btn btn-primary full-width mt-3'>
274
+ Add Filter
275
+ </Button>
276
+ </Accordion.Section>
277
+
278
+ {/* Visual section for TP5 style */}
279
+ {config.biteStyle === 'tp5' && (
280
+ <Accordion.Section title='Visual'>
281
+ <CheckBox
282
+ value={config.visual?.whiteBackground}
283
+ section='visual'
284
+ fieldName='whiteBackground'
285
+ label='Use White Background Style'
286
+ updateField={updateField}
287
+ />
288
+ {/* TODO: Uncomment when ready to release Display Border feature
289
+ <CheckBox
290
+ value={config.visual?.border}
291
+ section='visual'
292
+ fieldName='border'
293
+ label='Display Border'
294
+ updateField={updateField}
295
+ />
296
+ */}
297
+ </Accordion.Section>
298
+ )}
299
+
300
+ {/* Visual section for other bite styles */}
301
+ {config.biteStyle !== 'tp5' && (
302
+ <Accordion.Section title='Visual'>
303
+ <VisualSection
304
+ config={config}
305
+ updateField={updateField}
306
+ updateConfig={updateConfig}
307
+ themeSelectorPosition='after'
308
+ beforeCheckboxes={
309
+ <>
310
+ <TextField
311
+ type='number'
312
+ value={config.biteFontSize}
313
+ fieldName='biteFontSize'
314
+ label='Bite Font Size'
315
+ updateField={updateField}
316
+ min={17}
317
+ max={65}
318
+ />
319
+ <Select
320
+ value={config.fontSize}
321
+ fieldName='fontSize'
322
+ label='Overall Font Size'
323
+ updateField={updateField}
324
+ options={['small', 'medium', 'large']}
325
+ />
326
+ </>
327
+ }
328
+ />
329
+ </Accordion.Section>
330
+ )}
331
+
332
+ {['title', 'body', 'graphic'].includes(config.biteStyle) && (
333
+ <Accordion.Section title={`Image${['dynamic'].includes(config.imageData.display) ? 's' : ''}`}>
334
+ <Select
335
+ value={config.imageData.display || ''}
336
+ section='imageData'
337
+ fieldName='display'
338
+ label='Image Display Type'
339
+ updateField={updateField}
340
+ options={['none', 'static', 'dynamic']}
341
+ />
342
+ <Select
343
+ value={config.bitePosition || ''}
344
+ fieldName='bitePosition'
345
+ label='Image/Graphic Position'
346
+ updateField={updateField}
347
+ initial='Select'
348
+ options={IMAGE_POSITIONS}
349
+ />
350
+ {['static'].includes(config.imageData.display) && (
351
+ <>
352
+ <TextField
353
+ value={config.imageData.url}
354
+ section='imageData'
355
+ fieldName='url'
356
+ label='Image URL'
357
+ updateField={updateField}
358
+ />
359
+ <TextField
360
+ value={config.imageData.alt}
361
+ section='imageData'
362
+ fieldName='alt'
363
+ label='Alt Text'
364
+ updateField={updateField}
365
+ />
366
+ </>
367
+ )}
368
+
369
+ {['dynamic'].includes(config.imageData.display) && (
370
+ <>
371
+ <TextField
372
+ value={config.imageData.url || ''}
373
+ section='imageData'
374
+ fieldName='url'
375
+ label='Image URL (default)'
376
+ updateField={updateField}
377
+ />
378
+ <TextField
379
+ value={config.imageData.alt}
380
+ section='imageData'
381
+ fieldName='alt'
382
+ label='Alt Text (default)'
383
+ updateField={updateField}
384
+ />
385
+
386
+ <hr className='accordion__divider' />
387
+
388
+ {(!images.items || images.items.length === 0) && (
389
+ <p style={{ textAlign: 'center' }}>There are currently no dynamic images.</p>
390
+ )}
391
+ {images.items && images.items.length > 0 && (
392
+ <>
393
+ <ul>
394
+ {images.items.map((option: any, index: number) => (
395
+ <fieldset className='edit-block' key={index}>
396
+ <button
397
+ type='button'
398
+ className='remove-column'
399
+ onClick={() => {
400
+ images.remove(index)
401
+ }}
402
+ >
403
+ Remove
404
+ </button>
405
+ <label>
406
+ <span className='edit-label column-heading'>
407
+ <strong>{'Image #' + (index + 1)}</strong>
408
+ </span>
409
+
410
+ <div className='accordion__panel-row align-center'>
411
+ <div className='accordion__panel-col flex-auto'>If Value</div>
412
+ <div className='accordion__panel-col flex-auto'>
413
+ <Select
414
+ label=''
415
+ value={option.arguments[0]?.operator || ''}
416
+ options={DATA_OPERATORS}
417
+ onChange={e => {
418
+ images.updateNested(index, 'arguments', 0, 'operator', e.target.value)
419
+ }}
420
+ />
421
+ </div>
422
+ <div className='accordion__panel-col flex-grow flex-shrink'>
423
+ <input
424
+ type='number'
425
+ value={option.arguments[0]?.threshold || ''}
426
+ onChange={e => {
427
+ images.updateNested(index, 'arguments', 0, 'threshold', e.target.value)
428
+ }}
429
+ />
430
+ </div>
431
+ </div>
432
+
433
+ <div className='accordion__panel-row mb-2 align-center'>
434
+ <div className='accordion__panel-col flex-grow'>
435
+ <Select
436
+ label=''
437
+ value={option.secondArgument ? 'and' : 'then'}
438
+ options={[
439
+ { value: 'then', label: 'Then' },
440
+ { value: 'and', label: 'And' }
441
+ ]}
442
+ onChange={e => {
443
+ if ('then' === e.target.value) {
444
+ images.updateField(index, 'secondArgument', false)
445
+ removeDynamicArgument(index)
446
+ }
447
+ if ('and' === e.target.value) {
448
+ images.updateField(index, 'secondArgument', true)
449
+ }
450
+ }}
451
+ />
452
+ </div>
453
+ </div>
454
+
455
+ {option.secondArgument && true === option.secondArgument && (
456
+ <>
457
+ <div className='accordion__panel-row align-center'>
458
+ <div className='accordion__panel-col flex-auto'>If Value</div>
459
+ <div className='accordion__panel-col flex-auto'>
460
+ <Select
461
+ label=''
462
+ value={option.arguments[1]?.operator || ''}
463
+ options={DATA_OPERATORS}
464
+ onChange={e => {
465
+ images.updateNested(index, 'arguments', 1, 'operator', e.target.value)
466
+ }}
467
+ />
468
+ </div>
469
+ <div className='accordion__panel-col flex-grow flex-shrink'>
470
+ <input
471
+ type='number'
472
+ value={option.arguments[1]?.threshold || ''}
473
+ onChange={e => {
474
+ images.updateNested(index, 'arguments', 1, 'threshold', e.target.value)
475
+ }}
476
+ />
477
+ </div>
478
+ </div>
479
+ <div className='accordion__panel-row mb-2 align-center text-center text-capitalize'>
480
+ <div className='accordion__panel-col flex-grow'>Then</div>
481
+ </div>
482
+ </>
483
+ )}
484
+
485
+ <div className='accordion__panel-row mb-2 align-center'>
486
+ <div className='accordion__panel-col flex-auto'>Show</div>
487
+ <div className='accordion__panel-col flex-grow'>
488
+ <input
489
+ type='text'
490
+ value={option.source || ''}
491
+ onChange={e => {
492
+ images.updateField(index, 'source', e.target.value)
493
+ }}
494
+ />
495
+ </div>
496
+ </div>
497
+
498
+ <div className='accordion__panel-row mb-2 align-center'>
499
+ <div className='accordion__panel-col flex-auto'>Alt Text</div>
500
+ <div className='accordion__panel-col flex-grow'>
501
+ <input
502
+ type='text'
503
+ value={option.alt || ''}
504
+ onChange={e => {
505
+ images.updateField(index, 'alt', e.target.value)
506
+ }}
507
+ />
508
+ </div>
509
+ </div>
510
+ </label>
511
+ </fieldset>
512
+ ))}
513
+ </ul>
514
+ </>
515
+ )}
516
+ <button type='button' onClick={images.add} className='btn btn-primary full-width'>
517
+ Add Dynamic Image
518
+ </button>
519
+ </>
520
+ )}
521
+ </Accordion.Section>
522
+ )}
523
+
524
+ <Accordion.Section title='Markup Variables'>
525
+ <PanelMarkup
526
+ name='Markup Variables'
527
+ markupVariables={config.markupVariables || []}
528
+ data={data}
529
+ enableMarkupVariables={config.enableMarkupVariables || false}
530
+ onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
531
+ onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
532
+ withAccordion={false}
533
+ />
534
+ </Accordion.Section>
535
+ <AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
536
+ </Accordion>
537
+ )}
538
+ </BaseEditorPanel>
539
+ )
540
+ }
541
+
542
+ export default EditorPanel
@@ -0,0 +1,3 @@
1
+ import EditorPanel from './EditorPanel'
2
+
3
+ export default EditorPanel
package/src/constants.ts CHANGED
@@ -1,32 +1,11 @@
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',
26
4
  title: 'Value above Message',
27
5
  body: 'Value before Message',
28
6
  end: 'Value after Message',
29
- gradient: 'Gradient'
7
+ gradient: 'Gradient',
8
+ tp5: 'TP5 Style'
30
9
  }
31
10
 
32
11
  export const IMAGE_POSITION_LEFT = 'Left'
@@ -34,33 +13,3 @@ export const IMAGE_POSITION_RIGHT = 'Right'
34
13
  export const IMAGE_POSITION_TOP = 'Top'
35
14
  export const IMAGE_POSITION_BOTTOM = 'Bottom'
36
15
  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
- ]
@@ -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>
package/src/index.jsx CHANGED
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import ReactDOM from 'react-dom/client'
3
3
 
4
4
  import '@cdc/core/styles/cove-main.scss'
5
+ import '@cdc/core/components/EditorPanel/EditorPanel.styles.css'
5
6
 
6
7
  import CdcDataBite from './CdcDataBite'
7
8