@carto/ps-react-ui 4.7.1 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/category-DwaeYjpX.js +656 -0
- package/dist/category-DwaeYjpX.js.map +1 -0
- package/dist/change-column-Cidl_M-4.js +1110 -0
- package/dist/change-column-Cidl_M-4.js.map +1 -0
- package/dist/data-zoom-layout-BH0LPwSy.js +28 -0
- package/dist/data-zoom-layout-BH0LPwSy.js.map +1 -0
- package/dist/echart-CU0KmClP.js +176 -0
- package/dist/echart-CU0KmClP.js.map +1 -0
- package/dist/exports-Cx-f6m6U.js +63 -0
- package/dist/exports-Cx-f6m6U.js.map +1 -0
- package/dist/formula-DuC0NQLH.js +79 -0
- package/dist/formula-DuC0NQLH.js.map +1 -0
- package/dist/markdown-BD1jcknS.js +8326 -0
- package/dist/markdown-BD1jcknS.js.map +1 -0
- package/dist/merge-options-DCkkHZIf.js +34 -0
- package/dist/merge-options-DCkkHZIf.js.map +1 -0
- package/dist/{styles-BYTyKQFP.js → option-builders-F-c9ELi1.js} +25 -45
- package/dist/option-builders-F-c9ELi1.js.map +1 -0
- package/dist/png-item-CS4z1iSH.js +45 -0
- package/dist/png-item-CS4z1iSH.js.map +1 -0
- package/dist/range-DsqTjSpg.js +186 -0
- package/dist/range-DsqTjSpg.js.map +1 -0
- package/dist/spread-CTuIXZSM.js +67 -0
- package/dist/spread-CTuIXZSM.js.map +1 -0
- package/dist/style-DVnT6HC1.js +131 -0
- package/dist/style-DVnT6HC1.js.map +1 -0
- package/dist/styles-cohnxh9F.js +23 -0
- package/dist/styles-cohnxh9F.js.map +1 -0
- package/dist/table-HIpXuq4G.js +390 -0
- package/dist/table-HIpXuq4G.js.map +1 -0
- package/dist/transforms-Cdx4fkU5.js +106 -0
- package/dist/transforms-Cdx4fkU5.js.map +1 -0
- package/dist/types/widgets/echart/utils.test.d.ts +1 -0
- package/dist/types/widgets/formula/config.test.d.ts +1 -0
- package/dist/types/widgets/stores/widget-store-branches.test.d.ts +1 -0
- package/dist/types/widgets/table/config.test.d.ts +1 -0
- package/dist/types/widgets-v2/actions/brush-toggle/brush-toggle.d.ts +56 -0
- package/dist/types/widgets-v2/actions/brush-toggle/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/brush-toggle/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/brush-toggle/style.d.ts +12 -0
- package/dist/types/widgets-v2/actions/brush-toggle/transforms.d.ts +11 -0
- package/dist/types/widgets-v2/actions/brush-toggle/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/actions/change-column/change-column-icon.d.ts +2 -0
- package/dist/types/widgets-v2/actions/change-column/change-column.d.ts +29 -0
- package/dist/types/widgets-v2/actions/change-column/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/change-column/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/change-column/sortable-column-item.d.ts +14 -0
- package/dist/types/widgets-v2/actions/change-column/style.d.ts +33 -0
- package/dist/types/widgets-v2/actions/change-column/types.d.ts +10 -0
- package/dist/types/widgets-v2/actions/download/download.d.ts +18 -0
- package/dist/types/widgets-v2/actions/download/exports.d.ts +37 -0
- package/dist/types/widgets-v2/actions/download/icons.d.ts +12 -0
- package/dist/types/widgets-v2/actions/download/index.d.ts +6 -0
- package/dist/types/widgets-v2/actions/download/labels.d.ts +11 -0
- package/dist/types/widgets-v2/actions/download/png-item.d.ts +24 -0
- package/dist/types/widgets-v2/actions/download/style.d.ts +1 -0
- package/dist/types/widgets-v2/actions/download/types.d.ts +35 -0
- package/dist/types/widgets-v2/actions/fullscreen/fullscreen.d.ts +59 -0
- package/dist/types/widgets-v2/actions/fullscreen/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/fullscreen/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/fullscreen/style.d.ts +48 -0
- package/dist/types/widgets-v2/actions/fullscreen/types.d.ts +14 -0
- package/dist/types/widgets-v2/actions/index.d.ts +9 -0
- package/dist/types/widgets-v2/actions/lock-selection/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/lock-selection/labels.d.ts +6 -0
- package/dist/types/widgets-v2/actions/lock-selection/lock-selection.d.ts +36 -0
- package/dist/types/widgets-v2/actions/lock-selection/style.d.ts +12 -0
- package/dist/types/widgets-v2/actions/lock-selection/transforms.d.ts +6 -0
- package/dist/types/widgets-v2/actions/relative-data/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/relative-data/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/relative-data/relative-data.d.ts +39 -0
- package/dist/types/widgets-v2/actions/relative-data/style.d.ts +12 -0
- package/dist/types/widgets-v2/actions/relative-data/transforms.d.ts +30 -0
- package/dist/types/widgets-v2/actions/relative-data/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/actions/searcher/filter.d.ts +6 -0
- package/dist/types/widgets-v2/actions/searcher/index.d.ts +4 -0
- package/dist/types/widgets-v2/actions/searcher/labels.d.ts +7 -0
- package/dist/types/widgets-v2/actions/searcher/searcher-toggle.d.ts +23 -0
- package/dist/types/widgets-v2/actions/searcher/searcher.d.ts +11 -0
- package/dist/types/widgets-v2/actions/searcher/style.d.ts +16 -0
- package/dist/types/widgets-v2/actions/stack-toggle/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/stack-toggle/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/stack-toggle/stack-toggle.d.ts +10 -0
- package/dist/types/widgets-v2/actions/stack-toggle/style.d.ts +12 -0
- package/dist/types/widgets-v2/actions/stack-toggle/transforms.d.ts +13 -0
- package/dist/types/widgets-v2/actions/stack-toggle/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/index.d.ts +3 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/style.d.ts +12 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/transforms.d.ts +51 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/actions/zoom-toggle/zoom-toggle.d.ts +35 -0
- package/dist/types/widgets-v2/bar/download.d.ts +24 -0
- package/dist/types/widgets-v2/bar/index.d.ts +4 -0
- package/dist/types/widgets-v2/bar/options.d.ts +43 -0
- package/dist/types/widgets-v2/bar/options.test.d.ts +1 -0
- package/dist/types/widgets-v2/bar/skeleton.d.ts +6 -0
- package/dist/types/widgets-v2/bar/types.d.ts +41 -0
- package/dist/types/widgets-v2/category/category-ui.d.ts +81 -0
- package/dist/types/widgets-v2/category/category.d.ts +48 -0
- package/dist/types/widgets-v2/category/components/category-bar-stacked.d.ts +28 -0
- package/dist/types/widgets-v2/category/components/category-bar.d.ts +23 -0
- package/dist/types/widgets-v2/category/components/category-legend.d.ts +18 -0
- package/dist/types/widgets-v2/category/components/category-row-multi.d.ts +31 -0
- package/dist/types/widgets-v2/category/components/category-row-other.d.ts +13 -0
- package/dist/types/widgets-v2/category/components/category-row-single.d.ts +28 -0
- package/dist/types/widgets-v2/category/components/category-row-stacked.d.ts +38 -0
- package/dist/types/widgets-v2/category/download.d.ts +16 -0
- package/dist/types/widgets-v2/category/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/category/index.d.ts +10 -0
- package/dist/types/widgets-v2/category/skeleton.d.ts +11 -0
- package/dist/types/widgets-v2/category/style.d.ts +166 -0
- package/dist/types/widgets-v2/category/types.d.ts +49 -0
- package/dist/types/widgets-v2/echart/echart-ui.d.ts +44 -0
- package/dist/types/widgets-v2/echart/echart.d.ts +75 -0
- package/dist/types/widgets-v2/echart/index.d.ts +4 -0
- package/dist/types/widgets-v2/echart/shared-resize-observer.d.ts +5 -0
- package/dist/types/widgets-v2/echart/shared-resize-observer.test.d.ts +1 -0
- package/dist/types/widgets-v2/echart/style.d.ts +6 -0
- package/dist/types/widgets-v2/echart/use-chart-selection.d.ts +51 -0
- package/dist/types/widgets-v2/formula/delta.d.ts +22 -0
- package/dist/types/widgets-v2/formula/download.d.ts +20 -0
- package/dist/types/widgets-v2/formula/formula-ui.d.ts +20 -0
- package/dist/types/widgets-v2/formula/formula.d.ts +8 -0
- package/dist/types/widgets-v2/formula/index.d.ts +11 -0
- package/dist/types/widgets-v2/formula/note.d.ts +11 -0
- package/dist/types/widgets-v2/formula/prefix.d.ts +12 -0
- package/dist/types/widgets-v2/formula/series.d.ts +16 -0
- package/dist/types/widgets-v2/formula/skeleton.d.ts +4 -0
- package/dist/types/widgets-v2/formula/style.d.ts +29 -0
- package/dist/types/widgets-v2/formula/suffix.d.ts +12 -0
- package/dist/types/widgets-v2/formula/types.d.ts +40 -0
- package/dist/types/widgets-v2/formula/value.d.ts +14 -0
- package/dist/types/widgets-v2/histogram/download.d.ts +17 -0
- package/dist/types/widgets-v2/histogram/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/histogram/index.d.ts +5 -0
- package/dist/types/widgets-v2/histogram/options.d.ts +42 -0
- package/dist/types/widgets-v2/histogram/options.test.d.ts +1 -0
- package/dist/types/widgets-v2/histogram/skeleton.d.ts +9 -0
- package/dist/types/widgets-v2/histogram/transforms.d.ts +17 -0
- package/dist/types/widgets-v2/histogram/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/histogram/types.d.ts +47 -0
- package/dist/types/widgets-v2/index.d.ts +107 -0
- package/dist/types/widgets-v2/markdown/download.d.ts +16 -0
- package/dist/types/widgets-v2/markdown/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/markdown/index.d.ts +6 -0
- package/dist/types/widgets-v2/markdown/markdown-content.d.ts +34 -0
- package/dist/types/widgets-v2/markdown/markdown-ui.d.ts +12 -0
- package/dist/types/widgets-v2/markdown/markdown.d.ts +6 -0
- package/dist/types/widgets-v2/markdown/skeleton.d.ts +4 -0
- package/dist/types/widgets-v2/markdown/style.d.ts +61 -0
- package/dist/types/widgets-v2/markdown/types.d.ts +4 -0
- package/dist/types/widgets-v2/note/labels.d.ts +5 -0
- package/dist/types/widgets-v2/note/style.d.ts +26 -0
- package/dist/types/widgets-v2/note/widget-note.d.ts +46 -0
- package/dist/types/widgets-v2/pie/download.d.ts +17 -0
- package/dist/types/widgets-v2/pie/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/pie/index.d.ts +4 -0
- package/dist/types/widgets-v2/pie/options.d.ts +35 -0
- package/dist/types/widgets-v2/pie/options.test.d.ts +1 -0
- package/dist/types/widgets-v2/pie/skeleton.d.ts +4 -0
- package/dist/types/widgets-v2/pie/types.d.ts +50 -0
- package/dist/types/widgets-v2/provider/widget-provider.d.ts +32 -0
- package/dist/types/widgets-v2/range/index.d.ts +4 -0
- package/dist/types/widgets-v2/range/range-ui.d.ts +19 -0
- package/dist/types/widgets-v2/range/range.d.ts +19 -0
- package/dist/types/widgets-v2/range/skeleton.d.ts +9 -0
- package/dist/types/widgets-v2/range/style.d.ts +40 -0
- package/dist/types/widgets-v2/range/types.d.ts +37 -0
- package/dist/types/widgets-v2/scatterplot/download.d.ts +16 -0
- package/dist/types/widgets-v2/scatterplot/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/scatterplot/index.d.ts +5 -0
- package/dist/types/widgets-v2/scatterplot/options.d.ts +42 -0
- package/dist/types/widgets-v2/scatterplot/options.test.d.ts +1 -0
- package/dist/types/widgets-v2/scatterplot/skeleton.d.ts +12 -0
- package/dist/types/widgets-v2/scatterplot/transforms.d.ts +17 -0
- package/dist/types/widgets-v2/scatterplot/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/scatterplot/types.d.ts +50 -0
- package/dist/types/widgets-v2/selection-summary/labels.d.ts +6 -0
- package/dist/types/widgets-v2/selection-summary/selection-summary.d.ts +22 -0
- package/dist/types/widgets-v2/selection-summary/style.d.ts +23 -0
- package/dist/types/widgets-v2/spread/download.d.ts +15 -0
- package/dist/types/widgets-v2/spread/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/spread/index.d.ts +6 -0
- package/dist/types/widgets-v2/spread/separator.d.ts +7 -0
- package/dist/types/widgets-v2/spread/skeleton.d.ts +9 -0
- package/dist/types/widgets-v2/spread/spread-ui.d.ts +18 -0
- package/dist/types/widgets-v2/spread/spread.d.ts +5 -0
- package/dist/types/widgets-v2/spread/types.d.ts +25 -0
- package/dist/types/widgets-v2/state/labels.d.ts +7 -0
- package/dist/types/widgets-v2/state/labels.test.d.ts +1 -0
- package/dist/types/widgets-v2/state/style.d.ts +19 -0
- package/dist/types/widgets-v2/state/widget-state.d.ts +19 -0
- package/dist/types/widgets-v2/stores/index.d.ts +8 -0
- package/dist/types/widgets-v2/stores/pipeline-middleware.d.ts +5 -0
- package/dist/types/widgets-v2/stores/pipeline-middleware.test.d.ts +1 -0
- package/dist/types/widgets-v2/stores/transforms.d.ts +4 -0
- package/dist/types/widgets-v2/stores/transforms.test.d.ts +1 -0
- package/dist/types/widgets-v2/stores/types.d.ts +55 -0
- package/dist/types/widgets-v2/stores/use-echart-instance.d.ts +15 -0
- package/dist/types/widgets-v2/stores/use-transform-enabled.d.ts +17 -0
- package/dist/types/widgets-v2/stores/use-transform.d.ts +12 -0
- package/dist/types/widgets-v2/stores/widget-context.d.ts +2 -0
- package/dist/types/widgets-v2/stores/widget-store-registry.d.ts +74 -0
- package/dist/types/widgets-v2/stores/widget-store-registry.test.d.ts +1 -0
- package/dist/types/widgets-v2/subheader/style.d.ts +10 -0
- package/dist/types/widgets-v2/subheader/subheader.d.ts +11 -0
- package/dist/types/widgets-v2/table/download.d.ts +18 -0
- package/dist/types/widgets-v2/table/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/table/helpers.d.ts +32 -0
- package/dist/types/widgets-v2/table/helpers.test.d.ts +1 -0
- package/dist/types/widgets-v2/table/index.d.ts +7 -0
- package/dist/types/widgets-v2/table/labels.d.ts +22 -0
- package/dist/types/widgets-v2/table/skeleton.d.ts +22 -0
- package/dist/types/widgets-v2/table/style.d.ts +44 -0
- package/dist/types/widgets-v2/table/table-ui.d.ts +38 -0
- package/dist/types/widgets-v2/table/table.d.ts +50 -0
- package/dist/types/widgets-v2/table/types.d.ts +37 -0
- package/dist/types/widgets-v2/test-utils.d.ts +52 -0
- package/dist/types/widgets-v2/timeseries/download.d.ts +17 -0
- package/dist/types/widgets-v2/timeseries/download.test.d.ts +1 -0
- package/dist/types/widgets-v2/timeseries/index.d.ts +4 -0
- package/dist/types/widgets-v2/timeseries/options.d.ts +39 -0
- package/dist/types/widgets-v2/timeseries/options.test.d.ts +1 -0
- package/dist/types/widgets-v2/timeseries/skeleton.d.ts +8 -0
- package/dist/types/widgets-v2/timeseries/types.d.ts +56 -0
- package/dist/types/widgets-v2/toolbox/labels.d.ts +5 -0
- package/dist/types/widgets-v2/toolbox/style.d.ts +30 -0
- package/dist/types/widgets-v2/toolbox/toolbox.d.ts +49 -0
- package/dist/types/widgets-v2/utils/data-zoom-layout.d.ts +11 -0
- package/dist/types/widgets-v2/utils/index.d.ts +2 -0
- package/dist/types/widgets-v2/utils/merge-options.d.ts +12 -0
- package/dist/types/widgets-v2/utils/merge-options.test.d.ts +1 -0
- package/dist/types/widgets-v2/wrapper/index.d.ts +4 -0
- package/dist/types/widgets-v2/wrapper/labels.d.ts +6 -0
- package/dist/types/widgets-v2/wrapper/style.d.ts +111 -0
- package/dist/types/widgets-v2/wrapper/widget-actions.d.ts +22 -0
- package/dist/types/widgets-v2/wrapper/widget-content.d.ts +12 -0
- package/dist/types/widgets-v2/wrapper/widget-wrapper.d.ts +51 -0
- package/dist/use-transform-DXPN3nY7.js +110 -0
- package/dist/use-transform-DXPN3nY7.js.map +1 -0
- package/dist/widget-context-DTGO0Yta.js +13 -0
- package/dist/widget-context-DTGO0Yta.js.map +1 -0
- package/dist/widget-store-registry-_W4Z4xp-.js +178 -0
- package/dist/widget-store-registry-_W4Z4xp-.js.map +1 -0
- package/dist/widgets/bar.js +14 -13
- package/dist/widgets/bar.js.map +1 -1
- package/dist/widgets/histogram.js +8 -7
- package/dist/widgets/histogram.js.map +1 -1
- package/dist/widgets/pie.js +19 -18
- package/dist/widgets/pie.js.map +1 -1
- package/dist/widgets/scatterplot.js +8 -7
- package/dist/widgets/scatterplot.js.map +1 -1
- package/dist/widgets/timeseries.js +11 -10
- package/dist/widgets/timeseries.js.map +1 -1
- package/dist/widgets/utils.js +8 -7
- package/dist/widgets/utils.js.map +1 -1
- package/dist/widgets-v2/actions.js +43 -0
- package/dist/widgets-v2/actions.js.map +1 -0
- package/dist/widgets-v2/bar.js +327 -0
- package/dist/widgets-v2/bar.js.map +1 -0
- package/dist/widgets-v2/category.js +104 -0
- package/dist/widgets-v2/category.js.map +1 -0
- package/dist/widgets-v2/echart.js +57 -0
- package/dist/widgets-v2/echart.js.map +1 -0
- package/dist/widgets-v2/formula.js +74 -0
- package/dist/widgets-v2/formula.js.map +1 -0
- package/dist/widgets-v2/histogram.js +350 -0
- package/dist/widgets-v2/histogram.js.map +1 -0
- package/dist/widgets-v2/markdown.js +68 -0
- package/dist/widgets-v2/markdown.js.map +1 -0
- package/dist/widgets-v2/pie.js +381 -0
- package/dist/widgets-v2/pie.js.map +1 -0
- package/dist/widgets-v2/range.js +52 -0
- package/dist/widgets-v2/range.js.map +1 -0
- package/dist/widgets-v2/scatterplot.js +405 -0
- package/dist/widgets-v2/scatterplot.js.map +1 -0
- package/dist/widgets-v2/spread.js +72 -0
- package/dist/widgets-v2/spread.js.map +1 -0
- package/dist/widgets-v2/stores.js +42 -0
- package/dist/widgets-v2/stores.js.map +1 -0
- package/dist/widgets-v2/table.js +78 -0
- package/dist/widgets-v2/table.js.map +1 -0
- package/dist/widgets-v2/timeseries.js +352 -0
- package/dist/widgets-v2/timeseries.js.map +1 -0
- package/dist/widgets-v2/utils.js +7 -0
- package/dist/widgets-v2/utils.js.map +1 -0
- package/dist/widgets-v2.js +953 -0
- package/dist/widgets-v2.js.map +1 -0
- package/package.json +73 -5
- package/src/components/lasso-tool/chip.test.tsx +176 -0
- package/src/components/lasso-tool/lasso-tool-inline.test.tsx +171 -0
- package/src/components/lasso-tool/lasso-tool.test.tsx +198 -0
- package/src/components/list-data/list-data.test.tsx +73 -0
- package/src/components/no-data-alert/no-data-alert.test.tsx +38 -0
- package/src/components/responsive-drawer/responsive-drawer.test.tsx +68 -0
- package/src/widgets/actions/brush-toggle/brush-overlay.test.tsx +465 -0
- package/src/widgets/actions/brush-toggle/brush-toggle.test.tsx +208 -0
- package/src/widgets/actions/change-column/change-column-dnd.test.tsx +193 -0
- package/src/widgets/actions/change-column/sortable-column-item.test.tsx +124 -0
- package/src/widgets/actions/zoom-toggle/zoom-toggle.test.tsx +322 -0
- package/src/widgets/category/components/category-rows.test.tsx +213 -0
- package/src/widgets/echart/utils.test.ts +277 -0
- package/src/widgets/formula/config.test.ts +37 -0
- package/src/widgets/range/components/range-item.test.tsx +243 -0
- package/src/widgets/stores/widget-store-branches.test.ts +275 -0
- package/src/widgets/table/config.test.ts +65 -0
- package/src/widgets/utils/chart-config/option-builders.test.ts +188 -0
- package/src/widgets-v2/PERFORMANCE.md +189 -0
- package/src/widgets-v2/actions/brush-toggle/brush-toggle.test.tsx +180 -0
- package/src/widgets-v2/actions/brush-toggle/brush-toggle.tsx +154 -0
- package/src/widgets-v2/actions/brush-toggle/index.ts +3 -0
- package/src/widgets-v2/actions/brush-toggle/labels.ts +9 -0
- package/src/widgets-v2/actions/brush-toggle/style.ts +11 -0
- package/src/widgets-v2/actions/brush-toggle/transforms.test.ts +47 -0
- package/src/widgets-v2/actions/brush-toggle/transforms.ts +31 -0
- package/src/widgets-v2/actions/change-column/change-column-icon.tsx +14 -0
- package/src/widgets-v2/actions/change-column/change-column.test.tsx +59 -0
- package/src/widgets-v2/actions/change-column/change-column.tsx +180 -0
- package/src/widgets-v2/actions/change-column/index.ts +7 -0
- package/src/widgets-v2/actions/change-column/labels.ts +9 -0
- package/src/widgets-v2/actions/change-column/sortable-column-item.tsx +56 -0
- package/src/widgets-v2/actions/change-column/style.ts +32 -0
- package/src/widgets-v2/actions/change-column/types.ts +11 -0
- package/src/widgets-v2/actions/download/download.test.tsx +327 -0
- package/src/widgets-v2/actions/download/download.tsx +144 -0
- package/src/widgets-v2/actions/download/exports.test.tsx +198 -0
- package/src/widgets-v2/actions/download/exports.ts +115 -0
- package/src/widgets-v2/actions/download/icons.tsx +26 -0
- package/src/widgets-v2/actions/download/index.ts +13 -0
- package/src/widgets-v2/actions/download/labels.ts +16 -0
- package/src/widgets-v2/actions/download/png-item.test.tsx +72 -0
- package/src/widgets-v2/actions/download/png-item.tsx +52 -0
- package/src/widgets-v2/actions/download/style.ts +3 -0
- package/src/widgets-v2/actions/download/types.ts +32 -0
- package/src/widgets-v2/actions/fullscreen/fullscreen.test.tsx +150 -0
- package/src/widgets-v2/actions/fullscreen/fullscreen.tsx +230 -0
- package/src/widgets-v2/actions/fullscreen/index.ts +7 -0
- package/src/widgets-v2/actions/fullscreen/labels.ts +9 -0
- package/src/widgets-v2/actions/fullscreen/style.ts +59 -0
- package/src/widgets-v2/actions/fullscreen/types.ts +15 -0
- package/src/widgets-v2/actions/index.ts +82 -0
- package/src/widgets-v2/actions/lock-selection/index.ts +10 -0
- package/src/widgets-v2/actions/lock-selection/labels.ts +11 -0
- package/src/widgets-v2/actions/lock-selection/lock-selection.test.tsx +187 -0
- package/src/widgets-v2/actions/lock-selection/lock-selection.tsx +130 -0
- package/src/widgets-v2/actions/lock-selection/style.ts +11 -0
- package/src/widgets-v2/actions/lock-selection/transforms.ts +27 -0
- package/src/widgets-v2/actions/relative-data/index.ts +3 -0
- package/src/widgets-v2/actions/relative-data/labels.ts +9 -0
- package/src/widgets-v2/actions/relative-data/relative-data.test.tsx +71 -0
- package/src/widgets-v2/actions/relative-data/relative-data.tsx +107 -0
- package/src/widgets-v2/actions/relative-data/style.ts +11 -0
- package/src/widgets-v2/actions/relative-data/transforms.test.ts +151 -0
- package/src/widgets-v2/actions/relative-data/transforms.ts +70 -0
- package/src/widgets-v2/actions/searcher/filter.ts +28 -0
- package/src/widgets-v2/actions/searcher/index.ts +8 -0
- package/src/widgets-v2/actions/searcher/labels.ts +13 -0
- package/src/widgets-v2/actions/searcher/searcher-toggle.tsx +91 -0
- package/src/widgets-v2/actions/searcher/searcher.test.tsx +92 -0
- package/src/widgets-v2/actions/searcher/searcher.tsx +112 -0
- package/src/widgets-v2/actions/searcher/style.ts +15 -0
- package/src/widgets-v2/actions/stack-toggle/index.ts +3 -0
- package/src/widgets-v2/actions/stack-toggle/labels.ts +9 -0
- package/src/widgets-v2/actions/stack-toggle/stack-toggle.test.tsx +61 -0
- package/src/widgets-v2/actions/stack-toggle/stack-toggle.tsx +54 -0
- package/src/widgets-v2/actions/stack-toggle/style.ts +11 -0
- package/src/widgets-v2/actions/stack-toggle/transforms.test.ts +43 -0
- package/src/widgets-v2/actions/stack-toggle/transforms.ts +25 -0
- package/src/widgets-v2/actions/zoom-toggle/index.ts +9 -0
- package/src/widgets-v2/actions/zoom-toggle/labels.ts +9 -0
- package/src/widgets-v2/actions/zoom-toggle/style.ts +11 -0
- package/src/widgets-v2/actions/zoom-toggle/transforms.test.ts +148 -0
- package/src/widgets-v2/actions/zoom-toggle/transforms.ts +171 -0
- package/src/widgets-v2/actions/zoom-toggle/zoom-toggle.test.tsx +107 -0
- package/src/widgets-v2/actions/zoom-toggle/zoom-toggle.tsx +106 -0
- package/src/widgets-v2/bar/download.test.tsx +91 -0
- package/src/widgets-v2/bar/download.tsx +66 -0
- package/src/widgets-v2/bar/index.ts +10 -0
- package/src/widgets-v2/bar/options.test.ts +317 -0
- package/src/widgets-v2/bar/options.ts +326 -0
- package/src/widgets-v2/bar/skeleton.test.tsx +19 -0
- package/src/widgets-v2/bar/skeleton.tsx +69 -0
- package/src/widgets-v2/bar/types.ts +46 -0
- package/src/widgets-v2/category/category-ui.test.tsx +746 -0
- package/src/widgets-v2/category/category-ui.tsx +389 -0
- package/src/widgets-v2/category/category.relative-data.test.tsx +107 -0
- package/src/widgets-v2/category/category.stack-toggle.test.tsx +85 -0
- package/src/widgets-v2/category/category.test.tsx +305 -0
- package/src/widgets-v2/category/category.tsx +121 -0
- package/src/widgets-v2/category/components/category-bar-stacked.test.tsx +121 -0
- package/src/widgets-v2/category/components/category-bar-stacked.tsx +73 -0
- package/src/widgets-v2/category/components/category-bar.test.tsx +64 -0
- package/src/widgets-v2/category/components/category-bar.tsx +49 -0
- package/src/widgets-v2/category/components/category-legend.test.tsx +51 -0
- package/src/widgets-v2/category/components/category-legend.tsx +39 -0
- package/src/widgets-v2/category/components/category-row-multi.tsx +86 -0
- package/src/widgets-v2/category/components/category-row-other.test.tsx +28 -0
- package/src/widgets-v2/category/components/category-row-other.tsx +33 -0
- package/src/widgets-v2/category/components/category-row-single.tsx +76 -0
- package/src/widgets-v2/category/components/category-row-stacked.test.tsx +244 -0
- package/src/widgets-v2/category/components/category-row-stacked.tsx +99 -0
- package/src/widgets-v2/category/download.test.ts +71 -0
- package/src/widgets-v2/category/download.ts +54 -0
- package/src/widgets-v2/category/index.ts +32 -0
- package/src/widgets-v2/category/skeleton.test.tsx +26 -0
- package/src/widgets-v2/category/skeleton.tsx +74 -0
- package/src/widgets-v2/category/style.ts +290 -0
- package/src/widgets-v2/category/types.ts +54 -0
- package/src/widgets-v2/echart/echart-ui.test.tsx +232 -0
- package/src/widgets-v2/echart/echart-ui.tsx +184 -0
- package/src/widgets-v2/echart/echart.test.tsx +229 -0
- package/src/widgets-v2/echart/echart.tsx +199 -0
- package/src/widgets-v2/echart/index.ts +22 -0
- package/src/widgets-v2/echart/shared-resize-observer.test.ts +91 -0
- package/src/widgets-v2/echart/shared-resize-observer.ts +56 -0
- package/src/widgets-v2/echart/style.ts +8 -0
- package/src/widgets-v2/echart/use-chart-selection.test.tsx +118 -0
- package/src/widgets-v2/echart/use-chart-selection.ts +115 -0
- package/src/widgets-v2/formula/delta.tsx +61 -0
- package/src/widgets-v2/formula/download.test.tsx +65 -0
- package/src/widgets-v2/formula/download.tsx +69 -0
- package/src/widgets-v2/formula/formula-ui.test.tsx +91 -0
- package/src/widgets-v2/formula/formula-ui.tsx +66 -0
- package/src/widgets-v2/formula/formula.test.tsx +50 -0
- package/src/widgets-v2/formula/formula.tsx +34 -0
- package/src/widgets-v2/formula/index.ts +17 -0
- package/src/widgets-v2/formula/note.tsx +25 -0
- package/src/widgets-v2/formula/prefix.tsx +25 -0
- package/src/widgets-v2/formula/series.tsx +67 -0
- package/src/widgets-v2/formula/skeleton.test.tsx +21 -0
- package/src/widgets-v2/formula/skeleton.tsx +27 -0
- package/src/widgets-v2/formula/style.ts +31 -0
- package/src/widgets-v2/formula/subcomponents.test.tsx +107 -0
- package/src/widgets-v2/formula/suffix.tsx +25 -0
- package/src/widgets-v2/formula/types.ts +44 -0
- package/src/widgets-v2/formula/value.tsx +31 -0
- package/src/widgets-v2/histogram/download.test.ts +94 -0
- package/src/widgets-v2/histogram/download.ts +60 -0
- package/src/widgets-v2/histogram/index.ts +10 -0
- package/src/widgets-v2/histogram/options.test.ts +304 -0
- package/src/widgets-v2/histogram/options.ts +337 -0
- package/src/widgets-v2/histogram/skeleton.test.tsx +16 -0
- package/src/widgets-v2/histogram/skeleton.tsx +70 -0
- package/src/widgets-v2/histogram/transforms.test.ts +46 -0
- package/src/widgets-v2/histogram/transforms.ts +30 -0
- package/src/widgets-v2/histogram/types.ts +51 -0
- package/src/widgets-v2/index.ts +201 -0
- package/src/widgets-v2/markdown/download.test.ts +66 -0
- package/src/widgets-v2/markdown/download.ts +53 -0
- package/src/widgets-v2/markdown/index.ts +6 -0
- package/src/widgets-v2/markdown/markdown-content.test.tsx +155 -0
- package/src/widgets-v2/markdown/markdown-content.tsx +72 -0
- package/src/widgets-v2/markdown/markdown-ui.test.tsx +75 -0
- package/src/widgets-v2/markdown/markdown-ui.tsx +55 -0
- package/src/widgets-v2/markdown/markdown.test.tsx +39 -0
- package/src/widgets-v2/markdown/markdown.tsx +17 -0
- package/src/widgets-v2/markdown/skeleton.test.tsx +15 -0
- package/src/widgets-v2/markdown/skeleton.tsx +32 -0
- package/src/widgets-v2/markdown/style.ts +53 -0
- package/src/widgets-v2/markdown/types.ts +4 -0
- package/src/widgets-v2/note/labels.ts +9 -0
- package/src/widgets-v2/note/style.ts +26 -0
- package/src/widgets-v2/note/widget-note.test.tsx +158 -0
- package/src/widgets-v2/note/widget-note.tsx +172 -0
- package/src/widgets-v2/pie/download.test.ts +78 -0
- package/src/widgets-v2/pie/download.ts +55 -0
- package/src/widgets-v2/pie/index.ts +10 -0
- package/src/widgets-v2/pie/options.test.ts +585 -0
- package/src/widgets-v2/pie/options.ts +509 -0
- package/src/widgets-v2/pie/skeleton.test.tsx +17 -0
- package/src/widgets-v2/pie/skeleton.tsx +32 -0
- package/src/widgets-v2/pie/types.ts +55 -0
- package/src/widgets-v2/provider/widget-provider.test.tsx +119 -0
- package/src/widgets-v2/provider/widget-provider.tsx +111 -0
- package/src/widgets-v2/range/index.ts +4 -0
- package/src/widgets-v2/range/range-ui.test.tsx +130 -0
- package/src/widgets-v2/range/range-ui.tsx +211 -0
- package/src/widgets-v2/range/range.test.tsx +68 -0
- package/src/widgets-v2/range/range.tsx +46 -0
- package/src/widgets-v2/range/skeleton.test.tsx +17 -0
- package/src/widgets-v2/range/skeleton.tsx +47 -0
- package/src/widgets-v2/range/style.ts +41 -0
- package/src/widgets-v2/range/types.ts +37 -0
- package/src/widgets-v2/scatterplot/download.test.ts +71 -0
- package/src/widgets-v2/scatterplot/download.ts +54 -0
- package/src/widgets-v2/scatterplot/index.ts +11 -0
- package/src/widgets-v2/scatterplot/options.test.ts +399 -0
- package/src/widgets-v2/scatterplot/options.ts +421 -0
- package/src/widgets-v2/scatterplot/skeleton.test.tsx +17 -0
- package/src/widgets-v2/scatterplot/skeleton.tsx +84 -0
- package/src/widgets-v2/scatterplot/transforms.test.ts +97 -0
- package/src/widgets-v2/scatterplot/transforms.ts +38 -0
- package/src/widgets-v2/scatterplot/types.ts +55 -0
- package/src/widgets-v2/selection-summary/labels.ts +11 -0
- package/src/widgets-v2/selection-summary/selection-summary.test.tsx +53 -0
- package/src/widgets-v2/selection-summary/selection-summary.tsx +62 -0
- package/src/widgets-v2/selection-summary/style.ts +23 -0
- package/src/widgets-v2/spread/download.test.ts +64 -0
- package/src/widgets-v2/spread/download.ts +59 -0
- package/src/widgets-v2/spread/index.ts +6 -0
- package/src/widgets-v2/spread/separator.tsx +11 -0
- package/src/widgets-v2/spread/skeleton.test.tsx +17 -0
- package/src/widgets-v2/spread/skeleton.tsx +38 -0
- package/src/widgets-v2/spread/spread-ui.test.tsx +108 -0
- package/src/widgets-v2/spread/spread-ui.tsx +52 -0
- package/src/widgets-v2/spread/spread.test.tsx +50 -0
- package/src/widgets-v2/spread/spread.tsx +31 -0
- package/src/widgets-v2/spread/types.ts +27 -0
- package/src/widgets-v2/state/labels.test.ts +33 -0
- package/src/widgets-v2/state/labels.ts +20 -0
- package/src/widgets-v2/state/style.ts +25 -0
- package/src/widgets-v2/state/widget-state.test.tsx +294 -0
- package/src/widgets-v2/state/widget-state.tsx +184 -0
- package/src/widgets-v2/stores/index.ts +49 -0
- package/src/widgets-v2/stores/pipeline-middleware.test.ts +187 -0
- package/src/widgets-v2/stores/pipeline-middleware.ts +91 -0
- package/src/widgets-v2/stores/transforms.test.ts +162 -0
- package/src/widgets-v2/stores/transforms.ts +70 -0
- package/src/widgets-v2/stores/types.ts +64 -0
- package/src/widgets-v2/stores/use-echart-instance.test.tsx +91 -0
- package/src/widgets-v2/stores/use-echart-instance.ts +29 -0
- package/src/widgets-v2/stores/use-transform-enabled.test.tsx +127 -0
- package/src/widgets-v2/stores/use-transform-enabled.ts +25 -0
- package/src/widgets-v2/stores/use-transform.test.tsx +262 -0
- package/src/widgets-v2/stores/use-transform.ts +158 -0
- package/src/widgets-v2/stores/widget-context.test.tsx +58 -0
- package/src/widgets-v2/stores/widget-context.ts +15 -0
- package/src/widgets-v2/stores/widget-store-registry.test.ts +292 -0
- package/src/widgets-v2/stores/widget-store-registry.ts +248 -0
- package/src/widgets-v2/subheader/style.ts +12 -0
- package/src/widgets-v2/subheader/subheader.test.tsx +30 -0
- package/src/widgets-v2/subheader/subheader.tsx +16 -0
- package/src/widgets-v2/table/download.test.ts +75 -0
- package/src/widgets-v2/table/download.ts +47 -0
- package/src/widgets-v2/table/helpers.test.ts +214 -0
- package/src/widgets-v2/table/helpers.ts +136 -0
- package/src/widgets-v2/table/index.ts +23 -0
- package/src/widgets-v2/table/labels.tsx +41 -0
- package/src/widgets-v2/table/skeleton.test.tsx +26 -0
- package/src/widgets-v2/table/skeleton.tsx +65 -0
- package/src/widgets-v2/table/style.ts +46 -0
- package/src/widgets-v2/table/table-ui.test.tsx +200 -0
- package/src/widgets-v2/table/table-ui.tsx +331 -0
- package/src/widgets-v2/table/table.test.tsx +119 -0
- package/src/widgets-v2/table/table.tsx +174 -0
- package/src/widgets-v2/table/types.ts +44 -0
- package/src/widgets-v2/test-utils.ts +107 -0
- package/src/widgets-v2/timeseries/download.test.ts +95 -0
- package/src/widgets-v2/timeseries/download.ts +86 -0
- package/src/widgets-v2/timeseries/index.ts +10 -0
- package/src/widgets-v2/timeseries/options.test.ts +379 -0
- package/src/widgets-v2/timeseries/options.ts +341 -0
- package/src/widgets-v2/timeseries/skeleton.test.tsx +13 -0
- package/src/widgets-v2/timeseries/skeleton.tsx +76 -0
- package/src/widgets-v2/timeseries/types.ts +61 -0
- package/src/widgets-v2/toolbox/labels.ts +9 -0
- package/src/widgets-v2/toolbox/style.ts +33 -0
- package/src/widgets-v2/toolbox/toolbox.test.tsx +200 -0
- package/src/widgets-v2/toolbox/toolbox.tsx +309 -0
- package/src/widgets-v2/utils/data-zoom-layout.ts +26 -0
- package/src/widgets-v2/utils/index.ts +2 -0
- package/src/widgets-v2/utils/merge-options.test.ts +52 -0
- package/src/widgets-v2/utils/merge-options.ts +50 -0
- package/src/widgets-v2/wrapper/index.ts +14 -0
- package/src/widgets-v2/wrapper/labels.ts +11 -0
- package/src/widgets-v2/wrapper/style.ts +134 -0
- package/src/widgets-v2/wrapper/widget-actions.test.tsx +52 -0
- package/src/widgets-v2/wrapper/widget-actions.tsx +43 -0
- package/src/widgets-v2/wrapper/widget-content.test.tsx +27 -0
- package/src/widgets-v2/wrapper/widget-content.tsx +29 -0
- package/src/widgets-v2/wrapper/widget-wrapper.test.tsx +159 -0
- package/src/widgets-v2/wrapper/widget-wrapper.tsx +178 -0
- package/dist/styles-BYTyKQFP.js.map +0 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { createTheme, type Theme } from '@mui/material'
|
|
3
|
+
import { addZoom, createAddZoom, ZOOM_LAYOUT } from './transforms'
|
|
4
|
+
|
|
5
|
+
const theme = createTheme() as unknown as Theme
|
|
6
|
+
|
|
7
|
+
describe('addZoom', () => {
|
|
8
|
+
it('appends an inside + slider dataZoom pair to the option', () => {
|
|
9
|
+
const out = addZoom({ xAxis: { type: 'value' } }) as {
|
|
10
|
+
xAxis: { type: string }
|
|
11
|
+
dataZoom: { type: string }[]
|
|
12
|
+
}
|
|
13
|
+
expect(out.xAxis).toEqual({ type: 'value' })
|
|
14
|
+
expect(out.dataZoom).toHaveLength(2)
|
|
15
|
+
expect(out.dataZoom[0]?.type).toBe('inside')
|
|
16
|
+
expect(out.dataZoom[1]?.type).toBe('slider')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('replaces an existing dataZoom array (no append/stack across runs)', () => {
|
|
20
|
+
const seeded = { dataZoom: [{ type: 'inside' }, { type: 'inside' }] }
|
|
21
|
+
const out = addZoom(seeded) as { dataZoom: { type: string }[] }
|
|
22
|
+
expect(out.dataZoom).toHaveLength(2)
|
|
23
|
+
expect(out.dataZoom.map((z) => z.type)).toEqual(['inside', 'slider'])
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('omits start/end so ECharts preserves the user-dragged range across re-runs', () => {
|
|
27
|
+
const out = addZoom({}) as {
|
|
28
|
+
dataZoom: { start?: number; end?: number }[]
|
|
29
|
+
}
|
|
30
|
+
for (const dz of out.dataZoom) {
|
|
31
|
+
expect(dz.start).toBeUndefined()
|
|
32
|
+
expect(dz.end).toBeUndefined()
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('returns the input unchanged when not an object', () => {
|
|
37
|
+
expect(addZoom(null)).toBe(null)
|
|
38
|
+
expect(addZoom(undefined)).toBe(undefined)
|
|
39
|
+
expect(addZoom('not an object')).toBe('not an object')
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('createAddZoom (theme-bound, v1-styled slider)', () => {
|
|
44
|
+
it('produces an inside zoom + a styled slider with the v1 chrome', () => {
|
|
45
|
+
const transform = createAddZoom(theme)
|
|
46
|
+
const out = transform({}) as {
|
|
47
|
+
dataZoom: {
|
|
48
|
+
type: string
|
|
49
|
+
height?: number
|
|
50
|
+
handleIcon?: string
|
|
51
|
+
fillerColor?: string
|
|
52
|
+
borderColor?: string
|
|
53
|
+
dataBackground?: { areaStyle?: { color?: string } }
|
|
54
|
+
textStyle?: { fontSize?: number }
|
|
55
|
+
}[]
|
|
56
|
+
}
|
|
57
|
+
expect(out.dataZoom).toHaveLength(2)
|
|
58
|
+
expect(out.dataZoom[0]?.type).toBe('inside')
|
|
59
|
+
const slider = out.dataZoom[1]!
|
|
60
|
+
expect(slider.type).toBe('slider')
|
|
61
|
+
// v1 hallmarks the new slider must carry.
|
|
62
|
+
expect(slider.height).toBe(ZOOM_LAYOUT.sliderHeight)
|
|
63
|
+
expect(slider.handleIcon).toMatch(/^image:\/\/data:image\/svg\+xml/)
|
|
64
|
+
expect(slider.fillerColor).toBeTruthy()
|
|
65
|
+
expect(slider.borderColor).toBeTruthy()
|
|
66
|
+
expect(slider.textStyle?.fontSize).toBeGreaterThan(0)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('omits start/end so the dragged range survives re-runs', () => {
|
|
70
|
+
const transform = createAddZoom(theme)
|
|
71
|
+
const out = transform({}) as {
|
|
72
|
+
dataZoom: { start?: number; end?: number }[]
|
|
73
|
+
}
|
|
74
|
+
for (const dz of out.dataZoom) {
|
|
75
|
+
expect(dz.start).toBeUndefined()
|
|
76
|
+
expect(dz.end).toBeUndefined()
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('returns non-object input unchanged', () => {
|
|
81
|
+
const transform = createAddZoom(theme)
|
|
82
|
+
expect(transform(null)).toBe(null)
|
|
83
|
+
expect(transform(undefined)).toBe(undefined)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('defaults to x-axis only (matches bar/histogram/timeseries semantics)', () => {
|
|
87
|
+
const transform = createAddZoom(theme)
|
|
88
|
+
const out = transform({}) as {
|
|
89
|
+
dataZoom: { type: string; xAxisIndex?: unknown; yAxisIndex?: unknown }[]
|
|
90
|
+
}
|
|
91
|
+
expect(out.dataZoom).toHaveLength(2)
|
|
92
|
+
for (const dz of out.dataZoom) {
|
|
93
|
+
expect(dz.xAxisIndex).toEqual([0])
|
|
94
|
+
expect(dz.yAxisIndex).toBeUndefined()
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('emits inside + slider per axis when axes=["x","y"] (2D zoom for scatter)', () => {
|
|
99
|
+
const transform = createAddZoom(theme, { axes: ['x', 'y'] })
|
|
100
|
+
const out = transform({}) as {
|
|
101
|
+
dataZoom: {
|
|
102
|
+
type: string
|
|
103
|
+
xAxisIndex?: unknown
|
|
104
|
+
yAxisIndex?: unknown
|
|
105
|
+
width?: number
|
|
106
|
+
right?: number
|
|
107
|
+
height?: number
|
|
108
|
+
bottom?: number
|
|
109
|
+
}[]
|
|
110
|
+
}
|
|
111
|
+
expect(out.dataZoom).toHaveLength(4)
|
|
112
|
+
const insides = out.dataZoom.filter((dz) => dz.type === 'inside')
|
|
113
|
+
const sliders = out.dataZoom.filter((dz) => dz.type === 'slider')
|
|
114
|
+
expect(insides).toHaveLength(2)
|
|
115
|
+
expect(sliders).toHaveLength(2)
|
|
116
|
+
// One inside per axis.
|
|
117
|
+
expect(insides.some((dz) => dz.xAxisIndex !== undefined)).toBe(true)
|
|
118
|
+
expect(insides.some((dz) => dz.yAxisIndex !== undefined)).toBe(true)
|
|
119
|
+
// X-slider: horizontal at the bottom (has height + bottom).
|
|
120
|
+
const xSlider = sliders.find((dz) => dz.xAxisIndex !== undefined)
|
|
121
|
+
expect(xSlider?.height).toBe(ZOOM_LAYOUT.sliderHeight)
|
|
122
|
+
expect(xSlider?.bottom).toBeDefined()
|
|
123
|
+
// Y-slider: vertical on the right (has width + right, no handleIcon).
|
|
124
|
+
const ySlider = sliders.find((dz) => dz.yAxisIndex !== undefined)
|
|
125
|
+
expect(ySlider?.width).toBe(ZOOM_LAYOUT.sliderHeight)
|
|
126
|
+
expect(ySlider?.right).toBeDefined()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('emits y-only when axes=["y"]', () => {
|
|
130
|
+
const transform = createAddZoom(theme, { axes: ['y'] })
|
|
131
|
+
const out = transform({}) as {
|
|
132
|
+
dataZoom: { type: string; xAxisIndex?: unknown; yAxisIndex?: unknown }[]
|
|
133
|
+
}
|
|
134
|
+
expect(out.dataZoom).toHaveLength(2)
|
|
135
|
+
for (const dz of out.dataZoom) {
|
|
136
|
+
expect(dz.yAxisIndex).toEqual([0])
|
|
137
|
+
expect(dz.xAxisIndex).toBeUndefined()
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
describe('ZOOM_LAYOUT', () => {
|
|
143
|
+
it('exposes the layout constants used by data-fusion mergers', () => {
|
|
144
|
+
expect(ZOOM_LAYOUT.sliderHeight).toBe(32)
|
|
145
|
+
expect(ZOOM_LAYOUT.sliderGap).toBe(8)
|
|
146
|
+
expect(ZOOM_LAYOUT.sliderBottomWithLegend).toBe(28)
|
|
147
|
+
})
|
|
148
|
+
})
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import type { Theme } from '@mui/material'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* v1's slider handle — 9×36 SVG with a white pill body, secondary-colored
|
|
5
|
+
* stroke, and three grip lines. Inlined as a data URL so the chart can
|
|
6
|
+
* render it without a network fetch.
|
|
7
|
+
*/
|
|
8
|
+
const SLIDER_HANDLE_ICON =
|
|
9
|
+
'image://data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOSIgaGVpZ2h0PSIzNiIgdmlld0JveD0iMCAwIDkgMzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHg9IjAuNSIgeT0iLTAuNSIgd2lkdGg9IjgiIGhlaWdodD0iMTgiIHJ4PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDI3KSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzM1OEJFNyIvPgo8cmVjdCB3aWR0aD0iMyIgaGVpZ2h0PSIyIiByeD0iMSIgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMyAyMykiIGZpbGw9IiMzNThCRTciLz4KPHJlY3Qgd2lkdGg9IjMiIGhlaWdodD0iMiIgcng9IjEiIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDMgMTkpIiBmaWxsPSIjMzU4QkU3Ii8+CjxyZWN0IHdpZHRoPSIzIiBoZWlnaHQ9IjIiIHJ4PSIxIiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAzIDE1KSIgZmlsbD0iIzM1OEJFNyIvPgo8L3N2Zz4='
|
|
10
|
+
|
|
11
|
+
const SLIDER_HEIGHT = 32
|
|
12
|
+
const SLIDER_BOTTOM = 0
|
|
13
|
+
|
|
14
|
+
/** Which chart axis (or axes) zoom applies to. */
|
|
15
|
+
export type ZoomAxis = 'x' | 'y'
|
|
16
|
+
|
|
17
|
+
export interface CreateAddZoomOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Axes to enable zoom on. Default `['x']` (matches bar / histogram /
|
|
20
|
+
* timeseries — horizontal pan/zoom on the category axis). Pass
|
|
21
|
+
* `['x', 'y']` for a scatterplot-style 2D zoom (mouse-wheel scales both
|
|
22
|
+
* axes; a horizontal slider sits at the bottom for x-range and a
|
|
23
|
+
* vertical slider sits on the right for y-range).
|
|
24
|
+
*/
|
|
25
|
+
axes?: readonly ZoomAxis[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Theme-bound zoom config transform: adds one inside `dataZoom`
|
|
30
|
+
* (mouse-wheel + drag) per axis plus a styled slider per axis with the
|
|
31
|
+
* v1 chrome (blue-tinted filler, secondary-color data preview, white
|
|
32
|
+
* pill handles, CARTO typography). The x-slider is horizontal at the
|
|
33
|
+
* bottom; the y-slider is vertical on the right.
|
|
34
|
+
*
|
|
35
|
+
* Returned function has stable identity for a given theme + axes
|
|
36
|
+
* combination; pair with `useMemo` at the call site.
|
|
37
|
+
*
|
|
38
|
+
* **No `start` / `end`** are emitted: ECharts defaults to `0–100` on the
|
|
39
|
+
* first `setOption` and then keeps the runtime slider state across
|
|
40
|
+
* subsequent merges (no `replaceMerge` for `dataZoom`). Re-running the
|
|
41
|
+
* transform on data/formatter/RelativeData updates therefore preserves the
|
|
42
|
+
* user's dragged range instead of snapping it back.
|
|
43
|
+
*/
|
|
44
|
+
export function createAddZoom(
|
|
45
|
+
theme: Theme,
|
|
46
|
+
options: CreateAddZoomOptions = {},
|
|
47
|
+
): (option: unknown) => unknown {
|
|
48
|
+
const axes = options.axes ?? ['x']
|
|
49
|
+
const includeX = axes.includes('x')
|
|
50
|
+
const includeY = axes.includes('y')
|
|
51
|
+
const sliderStyles = getZoomSliderStyles(theme)
|
|
52
|
+
const baseSliderProps = {
|
|
53
|
+
throttle: 0,
|
|
54
|
+
showDetail: false,
|
|
55
|
+
brushSelect: false,
|
|
56
|
+
moveHandleSize: 8,
|
|
57
|
+
handleSize: '100%',
|
|
58
|
+
...sliderStyles,
|
|
59
|
+
}
|
|
60
|
+
return (option: unknown): unknown => {
|
|
61
|
+
if (option == null || typeof option !== 'object') return option
|
|
62
|
+
const cfg = option as Record<string, unknown>
|
|
63
|
+
const dataZoom: object[] = []
|
|
64
|
+
if (includeX) {
|
|
65
|
+
dataZoom.push({ type: 'inside', xAxisIndex: [0], throttle: 0 })
|
|
66
|
+
}
|
|
67
|
+
if (includeY) {
|
|
68
|
+
dataZoom.push({ type: 'inside', yAxisIndex: [0], throttle: 0 })
|
|
69
|
+
}
|
|
70
|
+
if (includeX) {
|
|
71
|
+
dataZoom.push({
|
|
72
|
+
type: 'slider',
|
|
73
|
+
xAxisIndex: [0],
|
|
74
|
+
height: SLIDER_HEIGHT,
|
|
75
|
+
bottom: SLIDER_BOTTOM,
|
|
76
|
+
handleIcon: SLIDER_HANDLE_ICON,
|
|
77
|
+
...baseSliderProps,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
if (includeY) {
|
|
81
|
+
// Vertical slider — `width` is its thickness, `right` pins it to
|
|
82
|
+
// the right edge. We omit `handleIcon` so ECharts renders its
|
|
83
|
+
// default vertical handle (the inline SVG is shaped for a
|
|
84
|
+
// horizontal slider and looks wrong when rotated).
|
|
85
|
+
dataZoom.push({
|
|
86
|
+
type: 'slider',
|
|
87
|
+
yAxisIndex: [0],
|
|
88
|
+
width: SLIDER_HEIGHT,
|
|
89
|
+
right: SLIDER_BOTTOM,
|
|
90
|
+
...baseSliderProps,
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
return { ...cfg, dataZoom }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Back-compat untyped transform — produces the bare `dataZoom` config from
|
|
99
|
+
* the original v2 implementation. Use {@link createAddZoom} when a theme is
|
|
100
|
+
* available so the slider matches the v1 styling.
|
|
101
|
+
*
|
|
102
|
+
* `start` / `end` are intentionally omitted so ECharts preserves the user's
|
|
103
|
+
* runtime range across subsequent `setOption` merges (see {@link createAddZoom}).
|
|
104
|
+
*/
|
|
105
|
+
export const addZoom = (option: unknown): unknown => {
|
|
106
|
+
if (option == null || typeof option !== 'object') return option
|
|
107
|
+
const cfg = option as Record<string, unknown>
|
|
108
|
+
return {
|
|
109
|
+
...cfg,
|
|
110
|
+
dataZoom: [
|
|
111
|
+
{ type: 'inside' },
|
|
112
|
+
{
|
|
113
|
+
type: 'slider',
|
|
114
|
+
height: SLIDER_HEIGHT,
|
|
115
|
+
bottom: SLIDER_BOTTOM,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Style block matching v1's `getEChartZoomSliderStyles`. */
|
|
122
|
+
function getZoomSliderStyles(theme: Theme) {
|
|
123
|
+
const secondary = theme.palette.secondary?.main ?? '#358BE7'
|
|
124
|
+
return {
|
|
125
|
+
fillerColor: 'rgba(53, 139, 231, 0.25)',
|
|
126
|
+
borderColor: 'rgba(53, 139, 231, 0.3)',
|
|
127
|
+
borderWidth: 0.5,
|
|
128
|
+
backgroundColor: 'transparent',
|
|
129
|
+
borderRadius: 4,
|
|
130
|
+
dataBackground: {
|
|
131
|
+
lineStyle: { opacity: 0 },
|
|
132
|
+
areaStyle: { opacity: 1, color: secondary },
|
|
133
|
+
},
|
|
134
|
+
selectedDataBackground: {
|
|
135
|
+
lineStyle: { opacity: 0 },
|
|
136
|
+
areaStyle: { opacity: 1, color: secondary },
|
|
137
|
+
},
|
|
138
|
+
handleStyle: {
|
|
139
|
+
color: theme.palette.common?.white ?? '#fff',
|
|
140
|
+
borderColor: 'rgba(3, 111, 226, 0.08)',
|
|
141
|
+
borderWidth: 1,
|
|
142
|
+
shadowBlur: 3,
|
|
143
|
+
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
144
|
+
shadowOffsetX: 0,
|
|
145
|
+
shadowOffsetY: 1,
|
|
146
|
+
},
|
|
147
|
+
textStyle: {
|
|
148
|
+
color: theme.palette.black?.[60] ?? theme.palette.text?.primary,
|
|
149
|
+
fontSize: parseInt(
|
|
150
|
+
(theme.typography.overlineDelicate?.fontSize as string | undefined) ??
|
|
151
|
+
'11',
|
|
152
|
+
),
|
|
153
|
+
fontFamily:
|
|
154
|
+
theme.typography.overlineDelicate?.fontFamily ??
|
|
155
|
+
theme.typography.caption?.fontFamily,
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Visual layout constants used by the data-fusion mergers (bar, histogram,
|
|
162
|
+
* timeseries) when laying out the slider against the legend / grid.
|
|
163
|
+
*/
|
|
164
|
+
export const ZOOM_LAYOUT = {
|
|
165
|
+
/** Slider height in px (matches `createAddZoom` output). */
|
|
166
|
+
sliderHeight: SLIDER_HEIGHT,
|
|
167
|
+
/** Vertical gap between chart grid and the slider. */
|
|
168
|
+
sliderGap: 8,
|
|
169
|
+
/** Slider `bottom` when a legend is shown — sits above the legend row. */
|
|
170
|
+
sliderBottomWithLegend: 28,
|
|
171
|
+
} as const
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
+
import { fireEvent, render, screen } from '@testing-library/react'
|
|
3
|
+
import type { ECharts } from 'echarts'
|
|
4
|
+
import { ZoomToggle } from './zoom-toggle'
|
|
5
|
+
import { Provider } from '../../provider/widget-provider'
|
|
6
|
+
import {
|
|
7
|
+
applyTransforms,
|
|
8
|
+
clearAllWidgetStores,
|
|
9
|
+
getWidgetStore,
|
|
10
|
+
setEchartInstance,
|
|
11
|
+
} from '../../stores'
|
|
12
|
+
|
|
13
|
+
beforeEach(() => clearAllWidgetStores())
|
|
14
|
+
afterEach(() => clearAllWidgetStores())
|
|
15
|
+
|
|
16
|
+
describe('<ZoomToggle>', () => {
|
|
17
|
+
it('starts disabled by default', () => {
|
|
18
|
+
render(
|
|
19
|
+
<Provider id='zt-1' data={[]}>
|
|
20
|
+
<ZoomToggle />
|
|
21
|
+
</Provider>,
|
|
22
|
+
)
|
|
23
|
+
const trigger = screen.getByLabelText('Enable zoom')
|
|
24
|
+
expect(trigger.getAttribute('aria-pressed')).toBe('false')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('respects initialEnabled=true', () => {
|
|
28
|
+
render(
|
|
29
|
+
<Provider id='zt-2' data={[]}>
|
|
30
|
+
<ZoomToggle initialEnabled />
|
|
31
|
+
</Provider>,
|
|
32
|
+
)
|
|
33
|
+
expect(screen.getByLabelText('Disable zoom')).toBeTruthy()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('clicking enables the transform — dataZoom appears in the post-pipeline option', () => {
|
|
37
|
+
render(
|
|
38
|
+
<Provider id='zt-3' data={[1]}>
|
|
39
|
+
<ZoomToggle />
|
|
40
|
+
</Provider>,
|
|
41
|
+
)
|
|
42
|
+
fireEvent.click(screen.getByLabelText('Enable zoom'))
|
|
43
|
+
// configTransforms now apply inside <Widget.Echart>; replay the
|
|
44
|
+
// pipeline locally over a blank structural option.
|
|
45
|
+
const configTransforms = getWidgetStore('zt-3').getState().configTransforms
|
|
46
|
+
const opts = applyTransforms({}, configTransforms) as {
|
|
47
|
+
dataZoom?: { type: string }[]
|
|
48
|
+
}
|
|
49
|
+
expect(opts.dataZoom).toBeTruthy()
|
|
50
|
+
expect(opts.dataZoom).toHaveLength(2)
|
|
51
|
+
expect(opts.dataZoom?.[0]?.type).toBe('inside')
|
|
52
|
+
expect(opts.dataZoom?.[1]?.type).toBe('slider')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('clicking to disable issues a one-shot setOption({}, replaceMerge: ["dataZoom"]) on the live instance', () => {
|
|
56
|
+
const setOption = vi.fn()
|
|
57
|
+
const chart = { setOption } as unknown as ECharts
|
|
58
|
+
render(
|
|
59
|
+
<Provider id='zt-4' data={[1]}>
|
|
60
|
+
<ZoomToggle initialEnabled />
|
|
61
|
+
</Provider>,
|
|
62
|
+
)
|
|
63
|
+
setEchartInstance('zt-4', chart)
|
|
64
|
+
fireEvent.click(screen.getByLabelText('Disable zoom'))
|
|
65
|
+
expect(setOption).toHaveBeenCalledTimes(1)
|
|
66
|
+
expect(setOption).toHaveBeenCalledWith({}, { replaceMerge: ['dataZoom'] })
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('clicking to enable does NOT touch the live instance (no cleanup needed)', () => {
|
|
70
|
+
const setOption = vi.fn()
|
|
71
|
+
const chart = { setOption } as unknown as ECharts
|
|
72
|
+
render(
|
|
73
|
+
<Provider id='zt-5' data={[1]}>
|
|
74
|
+
<ZoomToggle />
|
|
75
|
+
</Provider>,
|
|
76
|
+
)
|
|
77
|
+
setEchartInstance('zt-5', chart)
|
|
78
|
+
fireEvent.click(screen.getByLabelText('Enable zoom'))
|
|
79
|
+
expect(setOption).not.toHaveBeenCalled()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('rehydrates enabled state from transformStates on remount', () => {
|
|
83
|
+
const { unmount } = render(
|
|
84
|
+
<Provider id='zt-6' data={[1]} keepAlive>
|
|
85
|
+
<ZoomToggle />
|
|
86
|
+
</Provider>,
|
|
87
|
+
)
|
|
88
|
+
fireEvent.click(screen.getByLabelText('Enable zoom'))
|
|
89
|
+
unmount()
|
|
90
|
+
render(
|
|
91
|
+
<Provider id='zt-6' data={[1]} keepAlive>
|
|
92
|
+
<ZoomToggle />
|
|
93
|
+
</Provider>,
|
|
94
|
+
)
|
|
95
|
+
// Re-mounted with keepAlive — enabled survived.
|
|
96
|
+
expect(screen.getByLabelText('Disable zoom')).toBeTruthy()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('honors custom labels', () => {
|
|
100
|
+
render(
|
|
101
|
+
<Provider id='zt-7' data={[]}>
|
|
102
|
+
<ZoomToggle labels={{ off: 'Pan & zoom', on: 'Stop pan & zoom' }} />
|
|
103
|
+
</Provider>,
|
|
104
|
+
)
|
|
105
|
+
expect(screen.getByLabelText('Pan & zoom')).toBeTruthy()
|
|
106
|
+
})
|
|
107
|
+
})
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useCallback, useMemo, type ComponentType } from 'react'
|
|
2
|
+
import { IconButton, useTheme, type SvgIconProps } from '@mui/material'
|
|
3
|
+
import ZoomInIcon from '@mui/icons-material/ZoomIn'
|
|
4
|
+
import { Tooltip } from '../../../components'
|
|
5
|
+
import {
|
|
6
|
+
getEchartInstance,
|
|
7
|
+
useSingleTransform,
|
|
8
|
+
useWidgetId,
|
|
9
|
+
} from '../../stores'
|
|
10
|
+
import { createAddZoom, type ZoomAxis } from './transforms'
|
|
11
|
+
import { DEFAULT_ZOOM_TOGGLE_LABELS, type ZoomToggleLabels } from './labels'
|
|
12
|
+
import { styles } from './style'
|
|
13
|
+
|
|
14
|
+
const ZOOM_DESCRIPTOR = {
|
|
15
|
+
id: 'zoom-toggle',
|
|
16
|
+
type: 'config' as const,
|
|
17
|
+
order: 20,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ZoomToggleProps {
|
|
21
|
+
initialEnabled?: boolean
|
|
22
|
+
labels?: Partial<ZoomToggleLabels>
|
|
23
|
+
icon?: ComponentType<SvgIconProps>
|
|
24
|
+
iconProps?: SvgIconProps
|
|
25
|
+
/**
|
|
26
|
+
* Which axes the zoom controls. Default `['x']` — matches bar /
|
|
27
|
+
* histogram / timeseries (horizontal pan on the category axis). Pass
|
|
28
|
+
* `['x', 'y']` for 2D zoom on a scatterplot-style chart (mouse-wheel
|
|
29
|
+
* scales both axes; horizontal slider at bottom + vertical slider on
|
|
30
|
+
* the right).
|
|
31
|
+
*/
|
|
32
|
+
axes?: readonly ZoomAxis[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Toggle a `dataZoom` slider + wheel-zoom on the chart. The transform is
|
|
37
|
+
* theme-bound so the slider gets v1's CARTO chrome (blue-tinted filler,
|
|
38
|
+
* secondary-color preview, white pill handles).
|
|
39
|
+
*
|
|
40
|
+
* `dataZoom` is intentionally NOT in `replaceMergeKeys` — ECharts merges
|
|
41
|
+
* subsequent `setOption` calls so the user's dragged range survives
|
|
42
|
+
* unrelated re-renders (data updates, formatter swaps, RelativeData toggles).
|
|
43
|
+
*
|
|
44
|
+
* On disable the transform is unregistered, but ECharts' merge semantics
|
|
45
|
+
* would otherwise *keep* the live `dataZoom` component visible. To remove
|
|
46
|
+
* the slider immediately we issue a one-shot
|
|
47
|
+
* `setOption({}, { replaceMerge: ['dataZoom'] })` against the live chart
|
|
48
|
+
* instance via {@link getEchartInstance} — this bypasses the pipeline so
|
|
49
|
+
* unrelated transforms aren't disturbed.
|
|
50
|
+
*/
|
|
51
|
+
export function ZoomToggle({
|
|
52
|
+
initialEnabled = false,
|
|
53
|
+
labels,
|
|
54
|
+
icon: Icon = ZoomInIcon,
|
|
55
|
+
iconProps,
|
|
56
|
+
axes,
|
|
57
|
+
}: ZoomToggleProps) {
|
|
58
|
+
const id = useWidgetId()
|
|
59
|
+
const theme = useTheme()
|
|
60
|
+
const _labels = { ...DEFAULT_ZOOM_TOGGLE_LABELS, ...labels }
|
|
61
|
+
// Reduce `axes` to two structural booleans before memoizing so the memo
|
|
62
|
+
// depends on stable primitive values, not an array reference (callers
|
|
63
|
+
// typically pass an inline `axes={['x', 'y']}` literal that changes
|
|
64
|
+
// identity each render). Default — no `axes` prop — is x-axis only,
|
|
65
|
+
// matching `createAddZoom`'s default.
|
|
66
|
+
const includeX = axes ? axes.includes('x') : true
|
|
67
|
+
const includeY = axes ? axes.includes('y') : false
|
|
68
|
+
const transform = useMemo(() => {
|
|
69
|
+
const resolved: ZoomAxis[] = []
|
|
70
|
+
if (includeX) resolved.push('x')
|
|
71
|
+
if (includeY) resolved.push('y')
|
|
72
|
+
return createAddZoom(theme, { axes: resolved })
|
|
73
|
+
}, [theme, includeX, includeY])
|
|
74
|
+
const { enabled, toggle } = useSingleTransform(
|
|
75
|
+
id,
|
|
76
|
+
ZOOM_DESCRIPTOR,
|
|
77
|
+
transform,
|
|
78
|
+
{ initialEnabled },
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
const handleToggle = useCallback(() => {
|
|
82
|
+
if (enabled) {
|
|
83
|
+
// About to disable — clear the dataZoom component on the live
|
|
84
|
+
// instance so the slider disappears immediately.
|
|
85
|
+
getEchartInstance(id)?.setOption({}, { replaceMerge: ['dataZoom'] })
|
|
86
|
+
}
|
|
87
|
+
toggle()
|
|
88
|
+
}, [enabled, toggle, id])
|
|
89
|
+
|
|
90
|
+
const tooltip = enabled ? _labels.on : _labels.off
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<Tooltip title={tooltip}>
|
|
94
|
+
<IconButton
|
|
95
|
+
size='small'
|
|
96
|
+
aria-label={tooltip}
|
|
97
|
+
aria-pressed={enabled}
|
|
98
|
+
onClick={handleToggle}
|
|
99
|
+
className={enabled ? 'active' : undefined}
|
|
100
|
+
sx={{ ...styles.toggle, ...(enabled && styles.toggleActive) }}
|
|
101
|
+
>
|
|
102
|
+
<Icon fontSize='small' {...iconProps} />
|
|
103
|
+
</IconButton>
|
|
104
|
+
</Tooltip>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
import { createBarDownloadConfig } from './download'
|
|
3
|
+
import type { BarWidgetData } from './types'
|
|
4
|
+
|
|
5
|
+
const sample: BarWidgetData = [[{ name: 'a', value: 1 }]]
|
|
6
|
+
const multi: BarWidgetData = [
|
|
7
|
+
[
|
|
8
|
+
{ name: 'a', value: 1 },
|
|
9
|
+
{ name: 'b', value: 2 },
|
|
10
|
+
],
|
|
11
|
+
[{ name: 'c', value: 3 }],
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
let revokeSpy: ReturnType<typeof vi.spyOn>
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
// jsdom/happy-dom often miss URL.* — stub deterministically.
|
|
18
|
+
vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock')
|
|
19
|
+
revokeSpy = vi
|
|
20
|
+
.spyOn(URL, 'revokeObjectURL')
|
|
21
|
+
.mockImplementation(() => undefined)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe('createBarDownloadConfig', () => {
|
|
25
|
+
it('returns CSV-only items when getCaptureEl is not provided', () => {
|
|
26
|
+
const items = createBarDownloadConfig({
|
|
27
|
+
filename: 'demo',
|
|
28
|
+
getData: () => sample,
|
|
29
|
+
})
|
|
30
|
+
expect(items.map((i) => i.id)).toEqual(['csv'])
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('prepends a PNG item when getCaptureEl is provided', () => {
|
|
34
|
+
const items = createBarDownloadConfig({
|
|
35
|
+
filename: 'demo',
|
|
36
|
+
getData: () => sample,
|
|
37
|
+
getCaptureEl: () => document.createElement('div'),
|
|
38
|
+
})
|
|
39
|
+
expect(items.map((i) => i.id)).toEqual(['png', 'csv'])
|
|
40
|
+
const pngItem = items[0]
|
|
41
|
+
expect(pngItem?.label).toBe('PNG')
|
|
42
|
+
expect(pngItem?.icon).toBeTruthy()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('the PNG item rejects when the captureEl getter returns null', async () => {
|
|
46
|
+
const items = createBarDownloadConfig({
|
|
47
|
+
filename: 'demo',
|
|
48
|
+
getData: () => sample,
|
|
49
|
+
getCaptureEl: () => null,
|
|
50
|
+
})
|
|
51
|
+
const png = items.find((i) => i.id === 'png')
|
|
52
|
+
expect(png).toBeTruthy()
|
|
53
|
+
await expect(png!.resolve()).rejects.toThrow(/No PNG capture element/)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('CSV resolve returns a download handle with the filename + revoke fn (single series)', async () => {
|
|
57
|
+
const items = createBarDownloadConfig({
|
|
58
|
+
filename: 'sales',
|
|
59
|
+
getData: () => sample,
|
|
60
|
+
})
|
|
61
|
+
const csv = items.find((i) => i.id === 'csv')!
|
|
62
|
+
const handle = await csv.resolve()
|
|
63
|
+
expect(handle.url).toBe('blob:mock')
|
|
64
|
+
expect(handle.filename).toBe('sales.csv')
|
|
65
|
+
expect(typeof handle.revoke).toBe('function')
|
|
66
|
+
handle.revoke?.()
|
|
67
|
+
expect(revokeSpy).toHaveBeenCalledWith('blob:mock')
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('CSV resolve emits empty-row separators between multiple series', async () => {
|
|
71
|
+
let csvText = ''
|
|
72
|
+
// Intercept the Blob payload so we can assert on the serialised CSV.
|
|
73
|
+
const RealBlob = global.Blob
|
|
74
|
+
vi.stubGlobal(
|
|
75
|
+
'Blob',
|
|
76
|
+
class extends RealBlob {
|
|
77
|
+
constructor(parts: BlobPart[], opts?: BlobPropertyBag) {
|
|
78
|
+
csvText = typeof parts[0] === 'string' ? parts[0] : ''
|
|
79
|
+
super(parts, opts)
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
const items = createBarDownloadConfig({
|
|
84
|
+
filename: 'multi',
|
|
85
|
+
getData: () => multi,
|
|
86
|
+
})
|
|
87
|
+
await items.find((i) => i.id === 'csv')!.resolve()
|
|
88
|
+
expect(csvText).toBe('name,value\na,1\nb,2\n\nname,value\nc,3')
|
|
89
|
+
vi.unstubAllGlobals()
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CSVIcon,
|
|
3
|
+
buildPngDownloadItem,
|
|
4
|
+
downloadToCSV,
|
|
5
|
+
type DownloadItem,
|
|
6
|
+
} from '../actions/download'
|
|
7
|
+
import type { BarWidgetData } from './types'
|
|
8
|
+
|
|
9
|
+
export interface BarDownloadConfigArgs {
|
|
10
|
+
filename: string
|
|
11
|
+
getData: () => BarWidgetData
|
|
12
|
+
/**
|
|
13
|
+
* Optional getter for the widget's capture element (registered by
|
|
14
|
+
* `Widget.State` on its success path). When provided, a PNG item is
|
|
15
|
+
* prepended to the returned list. Wire it to
|
|
16
|
+
* `() => getCaptureEl(id)`.
|
|
17
|
+
*/
|
|
18
|
+
getCaptureEl?: () => HTMLElement | null
|
|
19
|
+
/** PNG `pixelRatio` (default 2). */
|
|
20
|
+
pngPixelRatio?: number
|
|
21
|
+
/** PNG `backgroundColor` (default transparent). */
|
|
22
|
+
pngBackgroundColor?: string | null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds download items for the Bar widget. Always includes a CSV item
|
|
27
|
+
* with one `name,value` block per series, separated by an empty row when
|
|
28
|
+
* there are multiple. When `getCaptureEl` is supplied, also prepends a PNG
|
|
29
|
+
* item that rasterises the captured element via `html2canvas`.
|
|
30
|
+
*/
|
|
31
|
+
export function createBarDownloadConfig(
|
|
32
|
+
args: BarDownloadConfigArgs,
|
|
33
|
+
): DownloadItem[] {
|
|
34
|
+
const items: DownloadItem[] = []
|
|
35
|
+
if (args.getCaptureEl) {
|
|
36
|
+
items.push(
|
|
37
|
+
buildPngDownloadItem({
|
|
38
|
+
filename: args.filename,
|
|
39
|
+
getCaptureEl: args.getCaptureEl,
|
|
40
|
+
pixelRatio: args.pngPixelRatio,
|
|
41
|
+
backgroundColor: args.pngBackgroundColor,
|
|
42
|
+
}),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
items.push({
|
|
46
|
+
id: 'csv',
|
|
47
|
+
label: 'CSV',
|
|
48
|
+
icon: <CSVIcon fontSize='small' />,
|
|
49
|
+
resolve: () => {
|
|
50
|
+
const data = args.getData()
|
|
51
|
+
const rows: unknown[][] = []
|
|
52
|
+
for (const [i, series] of data.entries()) {
|
|
53
|
+
if (i > 0) rows.push([])
|
|
54
|
+
rows.push(['name', 'value'])
|
|
55
|
+
for (const d of series) rows.push([d.name, d.value])
|
|
56
|
+
}
|
|
57
|
+
const handle = downloadToCSV(rows)
|
|
58
|
+
return Promise.resolve({
|
|
59
|
+
url: handle.url,
|
|
60
|
+
filename: `${args.filename}.csv`,
|
|
61
|
+
revoke: handle.revoke,
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
return items
|
|
66
|
+
}
|