@cdc/core 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.
- package/.claude/agents/qa-test-developer.md +126 -0
- package/CLAUDE.local.md +67 -0
- package/LICENSE +201 -0
- package/_stories/Gallery.Charts.stories.tsx +35 -42
- package/_stories/Gallery.DataBite.stories.tsx +15 -8
- package/_stories/Gallery.Maps.stories.tsx +37 -28
- package/_stories/Gallery.WaffleChart.stories.tsx +1 -1
- package/_stories/PageART.stories.tsx +5 -4
- package/_stories/PageBRFSS.stories.tsx +21 -16
- package/_stories/PageCancerRegistries.stories.tsx +15 -15
- package/_stories/PageEasternEquineEncephalitis.stories.tsx +33 -19
- package/_stories/PageExcessiveAlcoholUse.stories.tsx +148 -143
- package/_stories/PageMaternalMortality.stories.tsx +5 -4
- package/_stories/PageOralHealth.stories.tsx +15 -10
- package/_stories/PageRespiratory.stories.tsx +4 -4
- package/_stories/PageSmokingTobacco.stories.tsx +15 -10
- package/_stories/PageStateDiabetesProfiles.stories.tsx +15 -10
- package/_stories/PageWastewater.stories.tsx +44 -30
- package/_stories/VegaImport.stories.tsx +401 -0
- package/_stories/vega-fixtures/bars-with-line.json +444 -0
- package/_stories/vega-fixtures/bars.json +58 -0
- package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
- package/_stories/vega-fixtures/combo.json +68 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
- package/_stories/vega-fixtures/horizontal-bar.json +427 -0
- package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
- package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
- package/_stories/vega-fixtures/lines.json +227 -0
- package/_stories/vega-fixtures/measles-bars.json +348 -0
- package/_stories/vega-fixtures/measles-map.json +11101 -0
- package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
- package/_stories/vega-fixtures/multi-dataset.json +255 -0
- package/_stories/vega-fixtures/no-data.json +14 -0
- package/_stories/vega-fixtures/pie-chart.json +94 -0
- package/_stories/vega-fixtures/repeat-spec.json +47 -0
- package/_stories/vega-fixtures/stacked-area.json +222 -0
- package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
- package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
- package/_stories/vega-fixtures/stacked-bars.json +212 -0
- package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
- package/_stories/vega-fixtures/warning-combo.json +59 -0
- package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
- package/assets/callout-flag.svg +7 -0
- package/assets/icon-chart-area.svg +1 -0
- package/assets/icon-chart-radar.svg +23 -0
- package/assets/logo2.svg +31 -0
- package/components/AdvancedEditor/EmbedEditor.tsx +270 -38
- package/components/Alert/components/Alert.styles.css +2 -2
- package/components/ComboBox/combobox.styles.css +48 -48
- package/components/CustomColorsEditor/CustomColorsEditor.css +53 -53
- package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
- package/components/DataTable/DataTable.tsx +46 -18
- package/components/DataTable/DataTableStandAlone.tsx +1 -0
- package/components/DataTable/components/ChartHeader.tsx +21 -12
- package/components/DataTable/components/MapHeader.tsx +34 -28
- package/components/DataTable/components/SortIcon/sort-icon.css +5 -5
- package/components/DataTable/data-table.css +50 -52
- package/components/DataTable/helpers/applyCustomOrder.ts +17 -0
- package/components/DataTable/helpers/getChartCellValue.ts +10 -7
- package/components/DataTable/helpers/getMapDataTableColumnKeys.ts +22 -0
- package/components/DataTable/helpers/getSeriesName.ts +6 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +33 -23
- package/components/DataTable/helpers/tests/mapCellMatrix.test.ts +33 -0
- package/components/DownloadButton.tsx +14 -6
- package/components/EditorPanel/ColumnsEditor.tsx +38 -31
- package/components/EditorPanel/CustomSortOrder.tsx +94 -0
- package/components/EditorPanel/DataTableEditor.tsx +139 -23
- package/components/EditorPanel/EditorPanel.styles.css +71 -71
- package/components/EditorPanel/EditorPanel.tsx +3 -8
- package/components/EditorPanel/EditorPanelDispatch.tsx +4 -4
- package/components/EditorPanel/FootnotesEditor.tsx +2 -2
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +21 -12
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +16 -10
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
- package/components/EditorPanel/components/MarkupVariablesEditor.tsx +160 -106
- package/components/EditorPanel/components/PanelMarkup.tsx +5 -1
- package/{styles/v2/components → components/EditorPanel}/editor.scss +76 -22
- package/components/EditorPanel/sections/StyleTreatmentSection.tsx +99 -0
- package/components/EditorPanel/sections/VisualSection.tsx +11 -0
- package/components/EditorWrapper/editor-wrapper.style.css +1 -1
- package/components/Filters/Filters.tsx +3 -5
- package/components/Filters/components/Tabs.tsx +19 -7
- package/{styles → components/Filters}/filters.scss +3 -3
- package/components/Footnotes/FootnotesStandAlone.tsx +4 -2
- package/components/HeaderThemeSelector/HeaderThemeSelector.css +61 -5
- package/components/Layout/components/Responsive.tsx +14 -6
- package/components/Layout/components/Sidebar/components/Sidebar.tsx +1 -1
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +14 -20
- package/components/Layout/components/Visualization/index.tsx +50 -38
- package/components/Layout/components/Visualization/visualizations.scss +232 -15
- package/components/Layout/components/VisualizationContainer.test.tsx +67 -0
- package/components/Layout/components/VisualizationContainer.tsx +37 -0
- package/components/Layout/components/VisualizationContent.test.tsx +182 -0
- package/components/Layout/components/VisualizationContent.tsx +75 -0
- package/components/Layout/index.tsx +5 -5
- package/components/Layout/styles/editor-utils.scss +3 -3
- package/components/Layout/styles/editor.scss +4 -4
- package/components/Legend/Legend.Gradient.tsx +7 -1
- package/components/Loader/loader.styles.css +2 -2
- package/components/Loading.jsx +1 -1
- package/components/MediaControls.tsx +10 -3
- package/components/MultiSelect/multiselect.styles.css +19 -19
- package/components/NestedDropdown/nesteddropdown.styles.css +15 -15
- package/components/PaletteSelector/PaletteSelector.css +15 -15
- package/components/RichTooltip/richTooltip.css +6 -6
- package/components/Table/table.styles.css +2 -2
- package/components/Waiting.tsx +1 -1
- package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
- package/components/_stories/DataTable.stories.tsx +1 -0
- package/components/_stories/Filters.stories.tsx +1 -1
- package/components/_stories/styles.scss +0 -1
- package/components/elements/Button.jsx +1 -1
- package/components/elements/Card.jsx +1 -1
- package/{styles/v2/components → components/elements}/button.scss +9 -8
- package/components/inputs/InputCheckbox.jsx +1 -1
- package/components/inputs/InputSelect.tsx +1 -1
- package/components/inputs/InputText.jsx +1 -1
- package/components/inputs/InputToggle.tsx +1 -1
- package/{styles/v2/components/input → components/inputs}/_input-check-radio.scss +2 -2
- package/{styles/v2/components/input → components/inputs}/_input-group.scss +3 -3
- package/{styles/v2/components/input → components/inputs}/_input-slider.scss +2 -2
- package/{styles/v2/components/input → components/inputs}/_input.scss +5 -5
- package/{styles/v2/components/input → components/inputs}/index.scss +2 -2
- package/{styles → components}/loading.scss +1 -1
- package/components/managers/DataDesigner.tsx +1 -1
- package/{styles/v2/components → components/managers}/data-designer.scss +6 -7
- package/components/ui/Accordion.jsx +1 -1
- package/components/ui/Icon.tsx +1 -1
- package/components/ui/LoadSpin.jsx +1 -1
- package/components/ui/Modal.jsx +1 -1
- package/components/ui/Overlay.jsx +1 -1
- package/components/ui/Title/index.test.tsx +34 -0
- package/components/ui/Title/index.tsx +24 -7
- package/components/ui/Title/title.styles.css +119 -25
- package/components/ui/Tooltip.tsx +1 -1
- package/components/ui/_stories/Title.stories.tsx +1 -1
- package/{styles/v2/components → components/ui}/accordion.scss +3 -3
- package/components/ui/accordion.styles.css +11 -11
- package/{styles/v2/components → components/ui}/modal.scss +2 -2
- package/{styles/v2/components → components/ui}/overlay.scss +6 -6
- package/{styles/v2/components → components}/ui/tooltip.scss +1 -1
- package/{styles → components}/waiting.scss +9 -3
- package/data/colorPalettes.ts +18 -5
- package/data/mapColorPalettes.ts +10 -0
- package/devTemplate/dev.js +285 -0
- package/devTemplate/index.html +30 -0
- package/devTemplate/preview.html +1503 -0
- package/devTemplate/sidebar.css +151 -0
- package/dist/cove-main.css +2530 -3901
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +111 -2
- package/helpers/DataTransform.ts +1 -5
- package/helpers/backfillDefaults.ts +35 -0
- package/helpers/constants.ts +12 -0
- package/helpers/cove/date.ts +64 -3
- package/helpers/cove/number.ts +29 -15
- package/helpers/cove/string.ts +29 -0
- package/helpers/coveUpdateWorker.ts +14 -8
- package/helpers/displayDataAsText.ts +1 -1
- package/helpers/embed/embedCodeGenerator.ts +80 -0
- package/helpers/embed/embedHelper.js +169 -0
- package/helpers/embed/filterUtils.ts +121 -0
- package/helpers/embed/index.ts +17 -0
- package/helpers/embed/urlValidation.ts +119 -0
- package/helpers/extractDataAndMetadata.ts +20 -0
- package/helpers/fetchRemoteData.ts +14 -8
- package/helpers/filterVizData.ts +6 -1
- package/helpers/getFileExtension.ts +0 -6
- package/helpers/labelHash.ts +9 -0
- package/helpers/markupProcessor.ts +56 -38
- package/helpers/metrics/types.ts +3 -0
- package/helpers/palettes/colorDistributions.ts +1 -1
- package/helpers/palettes/utils.ts +12 -12
- package/helpers/parseCsvWithQuotes.ts +15 -14
- package/helpers/prepareScreenshot.ts +33 -10
- package/helpers/testing.ts +44 -0
- package/helpers/tests/DataTransform.test.ts +125 -0
- package/helpers/tests/abbreviateNumber.test.ts +59 -0
- package/helpers/tests/backfillDefaults.test.ts +253 -0
- package/helpers/tests/date.test.ts +110 -0
- package/helpers/tests/extractDataAndMetadata.test.ts +93 -0
- package/helpers/tests/markupProcessor.test.ts +315 -124
- package/helpers/tests/number.test.ts +42 -0
- package/helpers/tests/prepareScreenshot.test.ts +28 -28
- package/helpers/tests/testStandaloneBuild.ts +36 -26
- package/helpers/tests/useDataVizClasses.test.ts +66 -0
- package/helpers/tests/visualizationWrapperUsage.test.ts +57 -0
- package/helpers/useDataVizClasses.ts +13 -7
- package/helpers/vegaConfig.ts +1 -1
- package/helpers/vegaConfigImport.ts +160 -0
- package/helpers/ver/4.24.4.ts +24 -0
- package/helpers/ver/4.26.1.ts +1 -1
- package/helpers/ver/4.26.2.ts +84 -0
- package/helpers/ver/4.26.3.ts +44 -0
- package/helpers/ver/4.26.4.ts +31 -0
- package/helpers/ver/tests/4.26.1.test.ts +105 -0
- package/helpers/ver/tests/4.26.2.test.ts +298 -0
- package/helpers/ver/tests/4.26.3.test.ts +168 -0
- package/helpers/ver/tests/4.26.4.test.ts +88 -0
- package/helpers/ver/tests/coveUpdateWorker.test.ts +57 -0
- package/helpers/viewports.ts +2 -0
- package/package.json +27 -32
- package/styles/_global.scss +7 -7
- package/styles/_reset.scss +2 -2
- package/styles/{v2/base → base}/_file-selector.scss +4 -4
- package/styles/{v2/base → base}/_general.scss +2 -4
- package/styles/{v2/base → base}/index.scss +1 -1
- package/styles/base.scss +107 -165
- package/styles/cove-main.scss +3 -6
- package/styles/layout/_component.scss +110 -0
- package/styles/{v2/layout → layout}/_data-table.scss +7 -7
- package/styles/layout/_wrapper-padding.scss +27 -0
- package/styles/{v2/main.scss → main.scss} +3 -1
- package/styles/{v2/themes → themes}/_color-definitions.scss +46 -41
- package/styles/{_accessibility.scss → utils/_accessibility.scss} +1 -1
- package/styles/{v2/utils → utils}/_grid.scss +8 -3
- package/styles/{_global-variables.scss → utils/_properties.scss} +133 -112
- package/styles/{v2/utils → utils}/index.scss +2 -1
- package/types/Annotation.ts +10 -11
- package/types/Axis.ts +2 -0
- package/types/ComponentStyles.ts +1 -0
- package/types/ConfigureData.ts +1 -0
- package/types/General.ts +2 -0
- package/types/MarkupInclude.ts +1 -0
- package/types/MarkupVariable.ts +2 -1
- package/types/Palette.ts +22 -0
- package/types/Table.ts +9 -0
- package/types/Visualization.ts +7 -0
- package/_stories/StoryRenderingTests.stories.tsx +0 -164
- package/helpers/embedCodeGenerator.ts +0 -109
- package/styles/_common-components.css +0 -73
- package/styles/_variables.scss +0 -63
- package/styles/v2/layout/_component.scss +0 -21
- package/styles/v2/utils/_variables.scss +0 -9
- package/{styles/v2/components/card.scss → components/elements/card.css} +2 -2
- /package/{styles/v2/components → components/ui}/icon.scss +0 -0
- /package/{styles/v2/components → components/ui}/loadspin.scss +0 -0
- /package/styles/{v2/base → base}/_heading.scss +0 -0
- /package/styles/{v2/base → base}/_reset.scss +0 -0
- /package/styles/{v2/layout → layout}/_alert.scss +0 -0
- /package/styles/{v2/layout → layout}/_progression.scss +0 -0
- /package/styles/{v2/layout → layout}/_tooltip.scss +0 -0
- /package/styles/{v2/layout → layout}/index.scss +0 -0
- /package/styles/{v2/themes → themes}/index.scss +0 -0
- /package/styles/{v2/utils → utils}/_align.scss +0 -0
- /package/styles/{v2/utils → utils}/_animations.scss +0 -0
- /package/styles/{v2/utils → utils}/_breakpoints.scss +0 -0
- /package/styles/{v2/utils → utils}/_mixins.scss +0 -0
|
@@ -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>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free v6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M64 64c0-17.7-14.3-32-32-32S0 46.3 0 64L0 400c0 44.2 35.8 80 80 80l400 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 416c-8.8 0-16-7.2-16-16L64 64zm96 288l288 0c17.7 0 32-14.3 32-32l0-68.2c0-7.6-2.7-15-7.7-20.8l-65.8-76.8c-12.1-14.2-33.7-15-46.9-1.8l-21 21c-10 10-26.4 9.2-35.4-1.6l-39.2-47c-12.6-15.1-35.7-15.4-48.7-.6L135.9 215c-5.1 5.8-7.9 13.3-7.9 21.1l0 84c0 17.7 14.3 32 32 32z"/></svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
|
|
2
|
+
<!-- Outer pentagon (grid) -->
|
|
3
|
+
<path d="M256 32l211.25 153.5L175 478.5H337l81.25-293L256 32zm0 0L44.75 185.5L175 478.5h162L175 478.5 44.75 185.5 256 32z" fill="none" stroke="currentColor" stroke-width="20" stroke-linejoin="round"/>
|
|
4
|
+
<!-- Middle pentagon (grid ring) -->
|
|
5
|
+
<path d="M256 112l126.75 92.1L207.5 375.3h97l48.75-171.2L256 112z" fill="none" stroke="currentColor" stroke-width="12" stroke-opacity="0.4" stroke-linejoin="round"/>
|
|
6
|
+
<path d="M256 112l-126.75 92.1L207.5 375.3h-97l-48.75-171.2L256 112z" fill="none" stroke="currentColor" stroke-width="12" stroke-opacity="0.4" stroke-linejoin="round"/>
|
|
7
|
+
<!-- Inner pentagon (grid ring) -->
|
|
8
|
+
<path d="M256 192l63.4 46L289 332.7h-66l-30-94.7L256 192z" fill="none" stroke="currentColor" stroke-width="8" stroke-opacity="0.3" stroke-linejoin="round"/>
|
|
9
|
+
<!-- Axis lines -->
|
|
10
|
+
<line x1="256" y1="256" x2="256" y2="32" stroke="currentColor" stroke-width="8" stroke-opacity="0.5"/>
|
|
11
|
+
<line x1="256" y1="256" x2="467.25" y2="185.5" stroke="currentColor" stroke-width="8" stroke-opacity="0.5"/>
|
|
12
|
+
<line x1="256" y1="256" x2="337" y2="478.5" stroke="currentColor" stroke-width="8" stroke-opacity="0.5"/>
|
|
13
|
+
<line x1="256" y1="256" x2="175" y2="478.5" stroke="currentColor" stroke-width="8" stroke-opacity="0.5"/>
|
|
14
|
+
<line x1="256" y1="256" x2="44.75" y2="185.5" stroke="currentColor" stroke-width="8" stroke-opacity="0.5"/>
|
|
15
|
+
<!-- Data polygon (filled) -->
|
|
16
|
+
<polygon points="256,80 400,200 350,420 162,420 112,200" fill="currentColor" fill-opacity="0.3" stroke="currentColor" stroke-width="16" stroke-linejoin="round"/>
|
|
17
|
+
<!-- Data points -->
|
|
18
|
+
<circle cx="256" cy="80" r="12" fill="currentColor"/>
|
|
19
|
+
<circle cx="400" cy="200" r="12" fill="currentColor"/>
|
|
20
|
+
<circle cx="350" cy="420" r="12" fill="currentColor"/>
|
|
21
|
+
<circle cx="162" cy="420" r="12" fill="currentColor"/>
|
|
22
|
+
<circle cx="112" cy="200" r="12" fill="currentColor"/>
|
|
23
|
+
</svg>
|
package/assets/logo2.svg
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="135 160 228 147" xml:space="preserve">
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
.st0{fill:#0055B8;}
|
|
7
|
+
.st1{fill:#FFFFFF;}
|
|
8
|
+
</style>
|
|
9
|
+
<g>
|
|
10
|
+
<path class="st0" d="M141.22,300.14H186h151.44c10.88,0,19.84-8.27,20.91-18.87c0.07-0.71,0.11-1.42,0.11-2.15V165.04H188.93
|
|
11
|
+
h-26.68c-7.26,0-13.65,3.68-17.43,9.27c-0.76,1.12-1.41,2.31-1.94,3.57c-1.06,2.52-1.65,5.28-1.65,8.18V300.14z"/>
|
|
12
|
+
<path class="st1" d="M162.25,160.83c-13.91,0-25.23,11.32-25.23,25.23v118.28h31.62h6.95h161.85c13.91,0,25.23-11.32,25.23-25.23
|
|
13
|
+
V160.83H162.25z M326.53,239.21c-0.2-0.23-0.56-0.25-0.78-0.05c-1.32,1.19-5.84,4.76-12.61,4.88c-8.53,0.14-17.17-6.93-17.17-19.2
|
|
14
|
+
c0-12.27,8.92-19.21,17.27-19.21c6.2,0,10.2,2.92,11.41,3.95c0.23,0.19,0.57,0.17,0.77-0.06l7.57-8.41c0.18-0.2,0.2-0.51,0.02-0.72
|
|
15
|
+
c-1.24-1.49-6.57-6.89-18.51-6.89c-1.11,0-2.25,0.06-3.41,0.17l45.61-28.63h1.76v62.45l-31.15,12.59L326.53,239.21z M243.33,242.49
|
|
16
|
+
h-6.37c-0.31,0-0.56-0.25-0.56-0.56v-34.78c0-0.31,0.25-0.56,0.56-0.56h7.31c11.28,0,18.77,5.56,18.77,17.43
|
|
17
|
+
C263.04,237.79,255.72,242.49,243.33,242.49z M240.95,194.29h-17.32c-0.31,0-0.56,0.25-0.56,0.56v59.4c0,0.08,0.02,0.15,0.04,0.22
|
|
18
|
+
l-65.24,45.68h-6.1l40.05-44.48c2.03,0.34,4.03,0.51,5.93,0.51c11.85,0,18.13-6.24,19.55-7.87c0.19-0.21,0.19-0.53,0-0.74
|
|
19
|
+
l-7.52-8.36c-0.2-0.23-0.56-0.25-0.78-0.05c-1.32,1.19-5.84,4.76-12.61,4.88c-8.53,0.14-17.17-6.93-17.17-19.2
|
|
20
|
+
c0-12.27,8.92-19.21,17.27-19.21c6.2,0,10.2,2.92,11.41,3.95c0.23,0.19,0.57,0.17,0.77-0.06l7.57-8.41c0.18-0.2,0.2-0.51,0.02-0.72
|
|
21
|
+
c-1.24-1.49-6.57-6.89-18.51-6.89c-5.92,0-12.69,1.53-18.48,5.1l12.88-33.56h76.66L240.95,194.29z M142.88,177.88
|
|
22
|
+
c0.53-1.26,1.18-2.45,1.94-3.57c3.78-5.59,10.18-9.27,17.43-9.27h26.35l-14.39,37.49c-5.11,4.98-8.62,12.23-8.62,22.3
|
|
23
|
+
c0,0.05,0,0.1,0,0.15l-24.37,63.49V186.06C141.22,183.16,141.81,180.39,142.88,177.88z M141.22,297.77l25.1-65.41
|
|
24
|
+
c2.66,12.93,12.13,19.81,21.77,22.47l-40.8,45.31h-6.07V297.77z M163.69,300.14l64.76-45.34h16.43c18.03,0,32.01-10.51,32.01-30.08
|
|
25
|
+
c0-21.2-13.14-29.7-31.38-30.37l27.92-29.3h77.01l-49.53,31.09c-9.9,4-18.58,12.87-18.58,28.7c0,14.08,6.93,22.65,15.44,27.19
|
|
26
|
+
l-119.11,48.12H163.69z M358.35,281.27c-1.08,10.6-10.03,18.87-20.91,18.87h-149.9l114.43-46.23c4.21,1.55,8.58,2.26,12.53,2.26
|
|
27
|
+
c11.85,0,18.13-6.24,19.55-7.87c0.19-0.21,0.19-0.53,0-0.74l-4.37-4.85l28.78-11.63v48.03
|
|
28
|
+
C358.46,279.84,358.43,280.56,358.35,281.27z"/>
|
|
29
|
+
</g>
|
|
30
|
+
|
|
31
|
+
</svg>
|
|
@@ -1,31 +1,55 @@
|
|
|
1
1
|
import React, { useState, useEffect, useMemo } from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
generateEmbedCode,
|
|
4
|
+
extractFilters,
|
|
5
|
+
initializeFilterState,
|
|
6
|
+
buildFilterUrlParams,
|
|
7
|
+
type FilterMetadata,
|
|
8
|
+
type FilterState
|
|
9
|
+
} from '../../helpers/embed'
|
|
10
|
+
import '../../helpers/embed/embedHelper.js' // Initialize embed helper for iframe resizing
|
|
3
11
|
|
|
4
12
|
type EmbedEditorProps = {
|
|
5
13
|
config?: any // Current visualization config
|
|
6
14
|
}
|
|
7
15
|
|
|
16
|
+
type TabId = 'preview' | 'code'
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* EmbedEditor - Provides "Share with Partners" functionality
|
|
10
20
|
* Generates embed codes for iframe embedding of visualizations
|
|
21
|
+
* Now includes filter customization, preview, and embed code generation
|
|
11
22
|
*/
|
|
12
23
|
export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
13
24
|
const [configUrl, setConfigUrl] = useState<string | null>(null)
|
|
14
25
|
const [showEmbedModal, setShowEmbedModal] = useState(false)
|
|
15
|
-
const [embedCode, setEmbedCode] = useState('')
|
|
16
|
-
const [embedCodeCopied, setEmbedCodeCopied] = useState(false)
|
|
17
26
|
const [isExpanded, setIsExpanded] = useState(false)
|
|
27
|
+
const [activeTab, setActiveTab] = useState<TabId>('preview')
|
|
28
|
+
const [embedCodeCopied, setEmbedCodeCopied] = useState(false)
|
|
29
|
+
|
|
30
|
+
// Extract filters from config
|
|
31
|
+
const filters = useMemo(() => extractFilters(config), [config])
|
|
32
|
+
|
|
33
|
+
// Initialize filter state
|
|
34
|
+
const [filterState, setFilterState] = useState<Record<string, FilterState>>({})
|
|
35
|
+
|
|
36
|
+
// Update filter state when filters change
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (filters.length > 0) {
|
|
39
|
+
setFilterState(initializeFilterState(filters))
|
|
40
|
+
}
|
|
41
|
+
}, [filters])
|
|
18
42
|
|
|
19
43
|
// Check if all filters have setByQueryParameter
|
|
20
44
|
const filtersAreValid = useMemo(() => {
|
|
21
45
|
if (!config) return true
|
|
22
46
|
|
|
23
47
|
// Check regular filters
|
|
24
|
-
const
|
|
48
|
+
const regularFilters = config.filters || []
|
|
25
49
|
// Check dashboard shared filters
|
|
26
50
|
const sharedFilters = config.dashboard?.sharedFilters || []
|
|
27
51
|
|
|
28
|
-
const allFilters = [...
|
|
52
|
+
const allFilters = [...regularFilters, ...sharedFilters]
|
|
29
53
|
|
|
30
54
|
// If no filters, valid
|
|
31
55
|
if (allFilters.length === 0) return true
|
|
@@ -34,6 +58,20 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
34
58
|
return allFilters.every((filter: any) => !!filter.setByQueryParameter)
|
|
35
59
|
}, [config])
|
|
36
60
|
|
|
61
|
+
// Determine if we have valid filters to show
|
|
62
|
+
const hasFilters = filters.length > 0 && filtersAreValid
|
|
63
|
+
|
|
64
|
+
// Generate embed code with current filter settings
|
|
65
|
+
const embedCode = useMemo(() => {
|
|
66
|
+
if (!configUrl) return ''
|
|
67
|
+
|
|
68
|
+
const urlParams = buildFilterUrlParams(filters, filterState)
|
|
69
|
+
return generateEmbedCode({
|
|
70
|
+
configUrl,
|
|
71
|
+
urlParams
|
|
72
|
+
})
|
|
73
|
+
}, [configUrl, filters, filterState])
|
|
74
|
+
|
|
37
75
|
// Detect configUrl from WCMS permalink or use dev fallback
|
|
38
76
|
useEffect(() => {
|
|
39
77
|
// Try to get config URL from WCMS permalink element
|
|
@@ -74,12 +112,33 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
74
112
|
return
|
|
75
113
|
}
|
|
76
114
|
|
|
77
|
-
|
|
78
|
-
setEmbedCode(code)
|
|
115
|
+
setActiveTab('preview')
|
|
79
116
|
setShowEmbedModal(true)
|
|
80
117
|
setEmbedCodeCopied(false)
|
|
81
118
|
}
|
|
82
119
|
|
|
120
|
+
// Handle filter value change
|
|
121
|
+
const handleFilterChange = (filterKey: string, value: string) => {
|
|
122
|
+
setFilterState(prev => ({
|
|
123
|
+
...prev,
|
|
124
|
+
[filterKey]: {
|
|
125
|
+
...prev[filterKey],
|
|
126
|
+
value
|
|
127
|
+
}
|
|
128
|
+
}))
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Handle filter hide toggle
|
|
132
|
+
const handleHideToggle = (filterKey: string, hide: boolean) => {
|
|
133
|
+
setFilterState(prev => ({
|
|
134
|
+
...prev,
|
|
135
|
+
[filterKey]: {
|
|
136
|
+
...prev[filterKey],
|
|
137
|
+
hide
|
|
138
|
+
}
|
|
139
|
+
}))
|
|
140
|
+
}
|
|
141
|
+
|
|
83
142
|
// Handle copying embed code from modal
|
|
84
143
|
const handleCopyFromModal = async () => {
|
|
85
144
|
try {
|
|
@@ -98,9 +157,6 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
98
157
|
setEmbedCodeCopied(false)
|
|
99
158
|
}
|
|
100
159
|
|
|
101
|
-
// Hide embed section until released
|
|
102
|
-
return null
|
|
103
|
-
|
|
104
160
|
return (
|
|
105
161
|
<>
|
|
106
162
|
{/* Collapsible Share with Partners Section */}
|
|
@@ -155,8 +211,7 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
155
211
|
) : (
|
|
156
212
|
<>
|
|
157
213
|
<p style={{ fontSize: '0.85em', marginBottom: '1em', color: '#666' }}>
|
|
158
|
-
Generate embed codes for partners to add this visualization to their
|
|
159
|
-
need to be published to Link (www.cdc.gov) before it can be embedded by a partner.
|
|
214
|
+
Generate embed codes for partners to add this visualization to their website.
|
|
160
215
|
</p>
|
|
161
216
|
|
|
162
217
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5em' }}>
|
|
@@ -174,7 +229,7 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
174
229
|
)}
|
|
175
230
|
</div>
|
|
176
231
|
|
|
177
|
-
{/* Embed Code Modal */}
|
|
232
|
+
{/* Embed Code Modal with Tabs */}
|
|
178
233
|
{showEmbedModal && (
|
|
179
234
|
<div
|
|
180
235
|
className='modal-overlay'
|
|
@@ -186,8 +241,9 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
186
241
|
bottom: 0,
|
|
187
242
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
188
243
|
display: 'flex',
|
|
189
|
-
alignItems: '
|
|
244
|
+
alignItems: 'flex-start',
|
|
190
245
|
justifyContent: 'center',
|
|
246
|
+
paddingTop: '5vh',
|
|
191
247
|
zIndex: 9999
|
|
192
248
|
}}
|
|
193
249
|
onClick={handleCloseModal}
|
|
@@ -198,12 +254,16 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
198
254
|
backgroundColor: 'white',
|
|
199
255
|
borderRadius: '8px',
|
|
200
256
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
|
201
|
-
maxWidth: '
|
|
257
|
+
maxWidth: '800px',
|
|
202
258
|
width: '90%',
|
|
203
|
-
|
|
259
|
+
maxHeight: '90vh',
|
|
260
|
+
margin: '20px',
|
|
261
|
+
display: 'flex',
|
|
262
|
+
flexDirection: 'column'
|
|
204
263
|
}}
|
|
205
264
|
onClick={e => e.stopPropagation()}
|
|
206
265
|
>
|
|
266
|
+
{/* Modal Header */}
|
|
207
267
|
<div
|
|
208
268
|
className='modal-header'
|
|
209
269
|
style={{
|
|
@@ -216,7 +276,7 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
216
276
|
borderRadius: '8px 8px 0 0'
|
|
217
277
|
}}
|
|
218
278
|
>
|
|
219
|
-
<h3 style={{ color: 'white', margin: 0 }}>
|
|
279
|
+
<h3 style={{ color: 'white', margin: 0 }}>Share with Partners</h3>
|
|
220
280
|
<button
|
|
221
281
|
onClick={handleCloseModal}
|
|
222
282
|
style={{
|
|
@@ -234,26 +294,196 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
234
294
|
</button>
|
|
235
295
|
</div>
|
|
236
296
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
297
|
+
{/* Tab Navigation */}
|
|
298
|
+
<div
|
|
299
|
+
style={{
|
|
300
|
+
display: 'flex',
|
|
301
|
+
borderBottom: '1px solid #e0e0e0',
|
|
302
|
+
backgroundColor: '#f5f5f5'
|
|
303
|
+
}}
|
|
304
|
+
>
|
|
305
|
+
{(['preview', 'code'] as TabId[]).map(tab => {
|
|
306
|
+
const tabLabels: Record<TabId, string> = {
|
|
307
|
+
preview: 'Preview Visualization',
|
|
308
|
+
code: 'Get Embed Code'
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<button
|
|
313
|
+
key={tab}
|
|
314
|
+
onClick={() => setActiveTab(tab)}
|
|
315
|
+
style={{
|
|
316
|
+
flex: 1,
|
|
317
|
+
padding: '12px 16px',
|
|
318
|
+
border: 'none',
|
|
319
|
+
backgroundColor: activeTab === tab ? 'white' : 'transparent',
|
|
320
|
+
borderBottom: activeTab === tab ? '2px solid #005eaa' : '2px solid transparent',
|
|
321
|
+
color: activeTab === tab ? '#005eaa' : '#666',
|
|
322
|
+
fontWeight: activeTab === tab ? 'bold' : 'normal',
|
|
323
|
+
cursor: 'pointer',
|
|
324
|
+
transition: 'all 0.2s'
|
|
325
|
+
}}
|
|
326
|
+
>
|
|
327
|
+
{tabLabels[tab]}
|
|
328
|
+
</button>
|
|
329
|
+
)
|
|
330
|
+
})}
|
|
255
331
|
</div>
|
|
256
332
|
|
|
333
|
+
{/* Tab Content */}
|
|
334
|
+
<div
|
|
335
|
+
className='modal-body'
|
|
336
|
+
style={{
|
|
337
|
+
padding: '20px',
|
|
338
|
+
flex: 1,
|
|
339
|
+
overflow: 'auto'
|
|
340
|
+
}}
|
|
341
|
+
>
|
|
342
|
+
{/* Preview Tab - Contains filter controls (if filters exist) and preview */}
|
|
343
|
+
{activeTab === 'preview' && (
|
|
344
|
+
<div>
|
|
345
|
+
{/* Filter Settings - only shown if there are valid filters */}
|
|
346
|
+
{hasFilters && (
|
|
347
|
+
<>
|
|
348
|
+
<h4 style={{ marginTop: 0, marginBottom: '1rem' }}>Filter Settings</h4>
|
|
349
|
+
<p style={{ marginBottom: '1rem', color: '#666' }}>
|
|
350
|
+
Set default values and visibility for filters in the partner's embedded visualization.
|
|
351
|
+
</p>
|
|
352
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', marginBottom: '2rem' }}>
|
|
353
|
+
{filters.map((filter, index) => {
|
|
354
|
+
const state = filterState[filter.key] || { value: '', hide: false }
|
|
355
|
+
const hasValues = filter.values && filter.values.length > 0
|
|
356
|
+
|
|
357
|
+
return (
|
|
358
|
+
<div
|
|
359
|
+
key={filter.key || index}
|
|
360
|
+
style={{
|
|
361
|
+
padding: '1rem',
|
|
362
|
+
background: 'white',
|
|
363
|
+
border: '1px solid #ddd',
|
|
364
|
+
borderRadius: '4px'
|
|
365
|
+
}}
|
|
366
|
+
>
|
|
367
|
+
<label
|
|
368
|
+
htmlFor={`filter-${index}`}
|
|
369
|
+
style={{
|
|
370
|
+
display: 'block',
|
|
371
|
+
marginBottom: '0.5rem',
|
|
372
|
+
fontWeight: 'bold'
|
|
373
|
+
}}
|
|
374
|
+
>
|
|
375
|
+
{filter.label}
|
|
376
|
+
</label>
|
|
377
|
+
|
|
378
|
+
{hasValues ? (
|
|
379
|
+
<select
|
|
380
|
+
id={`filter-${index}`}
|
|
381
|
+
value={state.value}
|
|
382
|
+
onChange={e => handleFilterChange(filter.key, e.target.value)}
|
|
383
|
+
style={{
|
|
384
|
+
width: '100%',
|
|
385
|
+
padding: '0.5rem',
|
|
386
|
+
fontSize: '0.9rem',
|
|
387
|
+
border: '2px solid #d1d5db',
|
|
388
|
+
borderRadius: '6px',
|
|
389
|
+
backgroundColor: '#f9fafb',
|
|
390
|
+
cursor: 'pointer'
|
|
391
|
+
}}
|
|
392
|
+
>
|
|
393
|
+
{filter.values?.map((value, valueIndex) => (
|
|
394
|
+
<option key={valueIndex} value={value}>
|
|
395
|
+
{value}
|
|
396
|
+
</option>
|
|
397
|
+
))}
|
|
398
|
+
</select>
|
|
399
|
+
) : (
|
|
400
|
+
<div style={{ color: '#999', fontStyle: 'italic' }}>No values available</div>
|
|
401
|
+
)}
|
|
402
|
+
|
|
403
|
+
<div style={{ marginTop: '0.75rem' }}>
|
|
404
|
+
<label
|
|
405
|
+
style={{
|
|
406
|
+
display: 'flex',
|
|
407
|
+
alignItems: 'center',
|
|
408
|
+
cursor: 'pointer',
|
|
409
|
+
fontWeight: 'normal'
|
|
410
|
+
}}
|
|
411
|
+
>
|
|
412
|
+
<input
|
|
413
|
+
type='checkbox'
|
|
414
|
+
checked={state.hide}
|
|
415
|
+
onChange={e => handleHideToggle(filter.key, e.target.checked)}
|
|
416
|
+
style={{ marginRight: '0.5rem' }}
|
|
417
|
+
/>
|
|
418
|
+
<span style={{ color: '#666' }}>Hide filter in embed</span>
|
|
419
|
+
</label>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
)
|
|
423
|
+
})}
|
|
424
|
+
</div>
|
|
425
|
+
</>
|
|
426
|
+
)}
|
|
427
|
+
|
|
428
|
+
{/* Preview Section - title only shown if there are filters */}
|
|
429
|
+
{hasFilters && <h4 style={{ marginBottom: '1rem' }}>Preview</h4>}
|
|
430
|
+
<p style={{ marginBottom: '1rem', color: '#666' }}>
|
|
431
|
+
This shows how the visualization will appear on the partner website
|
|
432
|
+
{hasFilters ? ' with your selected settings' : ''}. The partner will have control over the width of
|
|
433
|
+
the embedded visualization. If you do not see the latest version of the visualization, save it and
|
|
434
|
+
reopen this popup.
|
|
435
|
+
</p>
|
|
436
|
+
<div
|
|
437
|
+
style={{
|
|
438
|
+
border: '2px dashed #999',
|
|
439
|
+
borderRadius: '4px',
|
|
440
|
+
padding: '1rem'
|
|
441
|
+
}}
|
|
442
|
+
>
|
|
443
|
+
<div
|
|
444
|
+
key={`${configUrl}-${JSON.stringify(filterState)}`}
|
|
445
|
+
data-cove-embed
|
|
446
|
+
data-config-url={(() => {
|
|
447
|
+
const urlParams = buildFilterUrlParams(filters, filterState)
|
|
448
|
+
const params = new URLSearchParams()
|
|
449
|
+
Object.entries(urlParams).forEach(([key, value]) => {
|
|
450
|
+
if (value) params.set(key, value)
|
|
451
|
+
})
|
|
452
|
+
return params.toString() ? `${configUrl}?${params.toString()}` : configUrl || ''
|
|
453
|
+
})()}
|
|
454
|
+
/>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
)}
|
|
458
|
+
|
|
459
|
+
{/* Embed Code Tab */}
|
|
460
|
+
{activeTab === 'code' && (
|
|
461
|
+
<div>
|
|
462
|
+
<p style={{ marginBottom: '10px', color: '#666' }}>
|
|
463
|
+
Copy this code and send it to a partner so they can add it to their site. Your visualization will
|
|
464
|
+
need to be published to Link (www.cdc.gov) before it can be embedded by a partner.
|
|
465
|
+
</p>
|
|
466
|
+
<textarea
|
|
467
|
+
readOnly
|
|
468
|
+
value={embedCode}
|
|
469
|
+
style={{
|
|
470
|
+
width: '100%',
|
|
471
|
+
height: '200px',
|
|
472
|
+
fontFamily: 'monospace',
|
|
473
|
+
fontSize: '0.85em',
|
|
474
|
+
padding: '10px',
|
|
475
|
+
border: '1px solid #ddd',
|
|
476
|
+
borderRadius: '4px',
|
|
477
|
+
resize: 'vertical',
|
|
478
|
+
boxSizing: 'border-box'
|
|
479
|
+
}}
|
|
480
|
+
onFocus={e => e.target.select()}
|
|
481
|
+
/>
|
|
482
|
+
</div>
|
|
483
|
+
)}
|
|
484
|
+
</div>
|
|
485
|
+
|
|
486
|
+
{/* Modal Footer */}
|
|
257
487
|
<div
|
|
258
488
|
className='modal-footer'
|
|
259
489
|
style={{
|
|
@@ -267,9 +497,11 @@ export const EmbedEditor: React.FC<EmbedEditorProps> = ({ config }) => {
|
|
|
267
497
|
<button className='btn btn-secondary' onClick={handleCloseModal}>
|
|
268
498
|
Close
|
|
269
499
|
</button>
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
500
|
+
{activeTab === 'code' && (
|
|
501
|
+
<button className='btn btn-primary' onClick={handleCopyFromModal} style={{ minWidth: '120px' }}>
|
|
502
|
+
{embedCodeCopied ? '✓ Copied!' : 'Copy to Clipboard'}
|
|
503
|
+
</button>
|
|
504
|
+
)}
|
|
273
505
|
</div>
|
|
274
506
|
</div>
|
|
275
507
|
</div>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
.
|
|
1
|
+
.cove-visualization {
|
|
2
2
|
.accordion__panel > .alert {
|
|
3
3
|
margin-bottom: 15px;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.alert {
|
|
7
7
|
align-items: center;
|
|
8
|
-
justify-content: center;
|
|
9
8
|
display: inline-flex;
|
|
9
|
+
justify-content: center;
|
|
10
10
|
|
|
11
11
|
.cove-icon {
|
|
12
12
|
margin: 5px;
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
.
|
|
1
|
+
.cove-visualization {
|
|
2
2
|
.cove-combobox {
|
|
3
3
|
position: relative;
|
|
4
4
|
width: 100%;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.cove-combobox-wrapper {
|
|
8
|
-
position: relative;
|
|
9
|
-
display: flex;
|
|
10
8
|
align-items: center;
|
|
9
|
+
display: flex;
|
|
10
|
+
position: relative;
|
|
11
11
|
width: 100%;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
input.cove-combobox-input[role='combobox'] {
|
|
15
|
-
|
|
15
|
+
-webkit-appearance: none;
|
|
16
|
+
-moz-appearance: none;
|
|
17
|
+
appearance: none;
|
|
18
|
+
background-clip: padding-box;
|
|
19
|
+
background-color: white;
|
|
20
|
+
border: 1px solid var(--cool-gray-10) !important;
|
|
21
|
+
border-radius: 0.333rem;
|
|
22
|
+
color: var(--cool-gray-90);
|
|
23
|
+
cursor: text;
|
|
16
24
|
display: block;
|
|
17
|
-
padding: 0.5rem 3rem 0.5rem 0.5rem;
|
|
18
25
|
font-family: var(--app-font-secondary);
|
|
19
|
-
font-weight: 300;
|
|
20
26
|
font-size: 0.833rem;
|
|
27
|
+
font-weight: 300;
|
|
21
28
|
line-height: normal;
|
|
22
|
-
|
|
23
|
-
background-color: white;
|
|
24
|
-
background-clip: padding-box;
|
|
25
|
-
border: 1px solid var(--cool-gray-10) !important;
|
|
26
|
-
border-radius: 0.333rem;
|
|
29
|
+
padding: 0.5rem 3rem 0.5rem 0.5rem;
|
|
27
30
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
28
|
-
|
|
29
|
-
-webkit-appearance: none;
|
|
30
|
-
-moz-appearance: none;
|
|
31
|
-
cursor: text;
|
|
31
|
+
width: 100%;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
input.cove-combobox-input[role='combobox']:focus {
|
|
35
|
-
color: var(--cool-gray-90);
|
|
36
35
|
background-color: white;
|
|
37
36
|
border: 1px solid var(--cool-gray-10) !important;
|
|
38
37
|
box-shadow: none;
|
|
38
|
+
color: var(--cool-gray-90);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
input.cove-combobox-input[role='combobox']:focus-visible {
|
|
42
|
+
border-radius: 6px !important;
|
|
42
43
|
outline: dashed 2px rgb(0, 122, 153) !important;
|
|
43
44
|
outline-offset: 3px !important;
|
|
44
|
-
border-radius: 6px !important;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
input.cove-combobox-input[role='combobox']:disabled {
|
|
48
48
|
background-color: var(--lightestGray);
|
|
49
49
|
color: var(--cool-gray-90);
|
|
50
|
-
opacity: 1;
|
|
51
50
|
cursor: default;
|
|
51
|
+
opacity: 1;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
input.cove-combobox-input[role='combobox']:disabled::placeholder {
|
|
@@ -62,21 +62,21 @@
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
.cove-combobox-button {
|
|
65
|
-
position: absolute;
|
|
66
|
-
right: 0.5rem;
|
|
67
|
-
top: 50%;
|
|
68
|
-
transform: translateY(-50%);
|
|
69
|
-
display: flex;
|
|
70
65
|
align-items: center;
|
|
71
|
-
justify-content: center;
|
|
72
|
-
width: 1em;
|
|
73
|
-
height: 1em;
|
|
74
66
|
background: transparent;
|
|
75
67
|
border: none;
|
|
76
68
|
cursor: pointer;
|
|
69
|
+
display: flex;
|
|
70
|
+
height: 1em;
|
|
71
|
+
justify-content: center;
|
|
77
72
|
padding: 0;
|
|
78
|
-
z-index: 2;
|
|
79
73
|
pointer-events: none;
|
|
74
|
+
position: absolute;
|
|
75
|
+
right: 0.5rem;
|
|
76
|
+
top: 50%;
|
|
77
|
+
transform: translateY(-50%);
|
|
78
|
+
width: 1em;
|
|
79
|
+
z-index: 2;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
.cove-combobox-button:disabled {
|
|
@@ -94,21 +94,21 @@
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
.cove-combobox-listbox {
|
|
97
|
-
position: absolute;
|
|
98
|
-
top: calc(100% + 0.125rem);
|
|
99
|
-
left: 0;
|
|
100
|
-
right: auto;
|
|
101
|
-
width: 150%;
|
|
102
|
-
z-index: 1000;
|
|
103
|
-
max-height: 20rem;
|
|
104
|
-
margin: 0;
|
|
105
|
-
padding: 0;
|
|
106
|
-
overflow-y: auto;
|
|
107
|
-
list-style: none;
|
|
108
97
|
background-color: white;
|
|
109
98
|
border: 1px solid var(--cool-gray-10);
|
|
110
99
|
border-radius: 0.333rem;
|
|
111
100
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
|
101
|
+
left: 0;
|
|
102
|
+
list-style: none;
|
|
103
|
+
margin: 0;
|
|
104
|
+
max-height: 20rem;
|
|
105
|
+
overflow-y: auto;
|
|
106
|
+
padding: 0;
|
|
107
|
+
position: absolute;
|
|
108
|
+
right: auto;
|
|
109
|
+
top: calc(100% + 0.125rem);
|
|
110
|
+
width: 150%;
|
|
111
|
+
z-index: 1000;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
.cove-combobox-listbox:has(.no-results) {
|
|
@@ -116,14 +116,14 @@
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
.cove-combobox-option {
|
|
119
|
-
padding: 0.5rem 0.5rem;
|
|
120
|
-
font-family: var(--app-font-secondary);
|
|
121
|
-
font-weight: 300;
|
|
122
|
-
font-size: 0.778rem;
|
|
123
119
|
color: var(--cool-gray-90);
|
|
124
120
|
cursor: pointer;
|
|
125
|
-
|
|
121
|
+
font-family: var(--app-font-secondary);
|
|
122
|
+
font-size: 0.778rem;
|
|
123
|
+
font-weight: 300;
|
|
124
|
+
padding: 0.5rem 0.5rem;
|
|
126
125
|
transition: background-color 0.15s ease-in-out;
|
|
126
|
+
user-select: none;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
.cove-combobox-option .cove-combobox-option-highlight {
|
|
@@ -148,15 +148,15 @@
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
.sr-only {
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
border: 0;
|
|
152
|
+
clip: rect(0, 0, 0, 0);
|
|
153
153
|
height: 1px;
|
|
154
|
-
padding: 0;
|
|
155
154
|
margin: -1px;
|
|
156
155
|
overflow: hidden;
|
|
157
|
-
|
|
156
|
+
padding: 0;
|
|
157
|
+
position: absolute;
|
|
158
158
|
white-space: nowrap;
|
|
159
|
-
|
|
159
|
+
width: 1px;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
@media (prefers-reduced-motion: reduce) {
|