From 28db9ad7fcc7dbbaeefa959564be329c5ed0f5af Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Sat, 31 May 2025 15:40:05 -0700 Subject: [PATCH] chore: moving reusable components from `src/components` to `packages/superset-ui-core/src/components` (#33593) --- .github/workflows/superset-frontend.yml | 18 -- superset-frontend/.eslintrc.js | 15 +- superset-frontend/jest.config.js | 4 +- superset-frontend/package-lock.json | 64 ++++-- superset-frontend/package.json | 20 +- .../superset-ui-chart-controls/package.json | 1 - .../components/CertifiedIconWithTooltip.tsx | 2 +- .../src/components/ColumnOption.tsx | 11 +- .../src/components/ControlHeader.tsx | 7 +- .../components/ControlSubSectionHeader.tsx | 1 - .../src/components/Dropdown.tsx | 2 +- .../src/components/Menu.tsx | 2 +- .../src/components/MetricOption.tsx | 16 +- .../src/components/SQLPopover.tsx | 3 +- .../src/components/Select.tsx | 6 +- .../src/components/Tooltip.tsx | 58 ----- .../superset-ui-chart-controls/src/index.ts | 7 +- .../components/RadioButtonControl.tsx | 2 +- .../superset-ui-chart-controls/src/types.ts | 2 +- .../test/components/ColumnOption.test.tsx | 31 +-- .../test/components/ColumnTypeLabel.test.tsx | 2 +- .../InfoTooltipWithTrigger.test.tsx | 10 +- .../test/components/MetricOption.test.tsx | 34 +-- .../test/components/labelUtils.test.tsx | 2 +- .../packages/superset-ui-core/.eslintrc | 68 ++++++ .../__mocks__/mockExportObject.js | 19 ++ .../__mocks__/mockExportString.js | 19 ++ .../superset-ui-core/__mocks__/svgrMock.tsx | 29 +++ .../packages/superset-ui-core/package.json | 39 ++++ .../src/components/Alert/Alert.stories.tsx | 0 .../src/components/Alert/index.tsx | 0 .../src/components/Alert/types.ts | 0 .../components/AntdThemeProvider/index.tsx | 0 .../AsyncAceEditor/AsyncAceEditor.stories.tsx | 0 .../AsyncAceEditor/AsyncAceEditor.test.tsx | 2 +- .../AsyncAceEditor/Tooltip.test.tsx | 0 .../src/components/AsyncAceEditor/Tooltip.tsx | 0 .../src/components/AsyncAceEditor/index.tsx | 158 ++++++++++++-- .../src/components/AsyncAceEditor/types.ts | 0 .../AsyncEsmComponent.stories.tsx | 0 .../AsyncEsmComponent.test.tsx | 2 +- .../components/AsyncEsmComponent/index.tsx | 0 .../src/components/AsyncEsmComponent/types.ts | 0 .../AutoComplete/AutoComplete.stories.tsx | 0 .../AutoComplete/AutoComplete.test.tsx | 19 +- .../src/components/AutoComplete/index.tsx | 0 .../src/components/AutoComplete/types.ts | 0 .../src/components/Avatar/Avatar.stories.tsx | 0 .../src/components/Avatar/Avatar.test.tsx | 2 +- .../src/components/Avatar/index.tsx | 0 .../src/components/Avatar/types.ts | 0 .../src/components/Badge/Badge.stories.tsx | 0 .../src/components/Badge/Badge.test.tsx | 2 +- .../src/components/Badge/index.tsx | 0 .../src/components/Badge/types.ts | 0 .../Breadcrumb/Breadcrumb.stories.tsx | 0 .../components/Breadcrumb/Breadcrumb.test.tsx | 4 +- .../src/components/Breadcrumb/index.tsx | 0 .../src/components/Breadcrumb/types.ts | 0 .../src/components/Button/Button.stories.tsx | 0 .../src/components/Button/Button.test.tsx | 2 +- .../src/components/Button/index.tsx | 0 .../src/components/Button/types.ts | 2 +- .../ButtonGroup/ButtonGroup.stories.tsx | 0 .../ButtonGroup/ButtonGroup.test.tsx | 2 +- .../src/components/ButtonGroup/index.tsx | 0 .../src/components/ButtonGroup/types.ts | 0 .../CachedLabel/CachedLabel.test.tsx | 2 +- .../CachedLabel/TooltipContent.test.tsx | 4 +- .../components/CachedLabel/TooltipContent.tsx | 2 +- .../src/components/CachedLabel/index.tsx | 2 +- .../src/components/CachedLabel/types.ts | 0 .../src/components/Card/Card.stories.tsx | 0 .../src/components/Card/Card.test.tsx | 2 +- .../src/components/Card/index.tsx | 0 .../src/components/Card/types.ts | 0 .../CertifiedBadge/CertifiedBadge.stories.tsx | 0 .../CertifiedBadge/CertifiedBadge.test.tsx | 13 +- .../src/components/CertifiedBadge/index.tsx | 2 +- .../src/components/CertifiedBadge/types.ts | 2 +- .../components/Checkbox/Checkbox.stories.tsx | 0 .../src/components/Checkbox/Checkbox.test.tsx | 27 +-- .../src/components/Checkbox/CheckboxIcons.tsx | 0 .../src/components/Checkbox/index.tsx | 0 .../src/components/Checkbox/types.ts | 0 .../components/Collapse/Collapse.stories.tsx | 0 .../src/components/Collapse/Collapse.test.tsx | 11 +- .../src/components/Collapse/Collapse.tsx | 0 .../Collapse/CollapseLabelInModal.tsx | 4 +- .../src/components/Collapse/index.tsx | 0 .../src/components/Collapse/types.ts | 0 .../ConfirmStatusChange.stories.tsx | 2 +- .../ConfirmStatusChange.test.jsx | 2 +- .../components/ConfirmStatusChange/index.tsx | 0 .../components/ConfirmStatusChange/types.ts | 0 .../CronPicker/CronPicker.stories.tsx | 0 .../components/CronPicker/CronPicker.test.tsx | 2 +- .../src/components/CronPicker/index.tsx | 3 + .../src/components/CronPicker/types.ts | 0 .../DatePicker/DatePicker.stories.tsx | 0 .../components/DatePicker/DatePicker.test.tsx | 2 +- .../src/components/DatePicker/index.tsx | 0 .../src/components/DatePicker/types.ts | 0 .../DeleteModal/DeleteModal.test.tsx | 16 +- .../src/components/DeleteModal/index.tsx | 0 .../src/components/DeleteModal/types.ts | 0 .../src/components/DesignSystem.stories.tsx | 0 .../components/Divider/Divider.stories.tsx | 0 .../src/components/Divider/Divider.test.tsx | 2 +- .../src/components/Divider/index.tsx | 0 .../src/components/Divider/types.ts | 0 .../components/Dropdown/Dropdown.stories.tsx | 2 +- .../src/components/Dropdown/Dropdown.test.tsx | 2 +- .../src/components/Dropdown/index.tsx | 2 +- .../src/components/Dropdown/types.ts | 0 .../DropdownButton/DropdownButton.stories.tsx | 2 +- .../src/components/DropdownButton/index.tsx | 0 .../src/components/DropdownButton/types.ts | 0 .../DropdownContainer.stories.tsx | 0 .../DropdownContainer.test.tsx | 180 ++++++++++++++++ .../DropdownContainer/Overview.stories.tsx | 0 .../components/DropdownContainer/index.tsx | 6 +- .../src/components/DropdownContainer/types.ts | 0 .../DynamicEditableTitle.test.tsx | 16 +- .../components/DynamicEditableTitle/index.tsx | 0 .../components/DynamicEditableTitle/types.ts | 0 .../EditableTitle/EditableTitle.stories.tsx | 0 .../EditableTitle/EditableTitle.test.tsx | 12 +- .../src/components/EditableTitle/index.tsx | 31 +-- .../src/components/EditableTitle/types.ts | 2 +- .../src/components/EmptyState/Empty.test.tsx | 2 +- .../src/components/EmptyState/Empty.tsx | 0 .../EmptyState/EmptyState.stories.tsx | 2 +- .../src/components/EmptyState/index.tsx | 31 ++- .../components/EmptyState/svgs}/document.svg | 0 .../EmptyState/svgs}/empty-charts.svg | 0 .../EmptyState/svgs}/empty-dashboard.svg | 0 .../EmptyState/svgs}/empty-dataset.svg | 0 .../EmptyState/svgs}/empty-query.svg | 0 .../EmptyState/svgs}/empty-table.svg | 0 .../src/components/EmptyState/svgs}/empty.svg | 0 .../EmptyState/svgs}/empty_sql_chart.svg | 0 .../EmptyState/svgs}/filter-results.svg | 0 .../components/EmptyState/svgs}/filter.svg | 0 .../EmptyState/svgs}/star-circle.svg | 0 .../src/components/EmptyState/svgs}/union.svg | 0 .../components/EmptyState/svgs}/vector.svg | 0 .../src/components/EmptyState/types.ts | 0 .../components/FaveStar/FaveStar.stories.tsx | 0 .../src/components/FaveStar/FaveStar.test.tsx | 8 +- .../src/components/FaveStar/index.tsx | 2 +- .../src/components/FaveStar/types.ts | 0 .../src/components/Flex/Flex.stories.tsx | 0 .../src/components/Flex/Flex.test.tsx | 2 +- .../src/components/Flex/index.tsx | 0 .../src/components/Flex/types.ts | 0 .../src/components/Form/Form.tsx | 0 .../src/components/Form/FormItem.tsx | 0 .../src/components/Form/FormLabel.tsx | 0 .../Form/LabeledErrorBoundInput.stories.tsx | 0 .../Form/LabeledErrorBoundInput.test.jsx | 2 +- .../Form/LabeledErrorBoundInput.tsx | 11 +- .../src/components/Form/index.tsx | 0 .../src/components/Form/types.ts | 0 .../src/components/Grid/Grid.stories.tsx | 2 +- .../src/components/Grid/Grid.test.tsx | 2 +- .../src/components/Grid/index.tsx | 0 .../src/components/Grid/types.ts | 0 .../IconButton/IconButton.stories.tsx | 0 .../components/IconButton/IconButton.test.tsx | 2 +- .../src/components/IconButton/index.tsx | 0 .../IconTooltip/IconTooltip.stories.tsx | 2 +- .../IconTooltip/IconTooltip.test.jsx | 4 +- .../src/components/IconTooltip/index.tsx | 0 .../src/components/IconTooltip/types.ts | 0 .../src/components/Icons/AntdEnhanced.tsx | 2 + .../src/components/Icons/AsyncIcon.tsx | 2 +- .../src/components/Icons/BaseIcon.tsx | 2 +- .../src/components/Icons/Icons.stories.tsx | 0 .../src/components/Icons/index.tsx | 2 + .../components/Icons/svgs}/transparent.svg | 0 .../src/components/Icons/types.ts | 0 .../src/components/Image/index.tsx | 0 .../InfoTooltip/InfoTooltip.stories.tsx | 3 +- .../src/components/InfoTooltip/index.tsx} | 9 +- .../src/components/Input/Input.stories.tsx | 0 .../src/components/Input/Input.test.tsx | 2 +- .../src/components/Input/index.tsx | 0 .../src/components/Input/types.ts | 0 .../src/components/Label/Label.stories.tsx | 0 .../src/components/Label/Label.test.tsx | 2 +- .../src/components/Label/index.tsx | 2 +- .../Label/reusable/DatasetTypeLabel.tsx | 2 +- .../Label/reusable/PublishedLabel.tsx | 2 +- .../src/components/Label/types.ts | 0 .../LastUpdated/LastUpdated.test.tsx | 2 +- .../src/components/LastUpdated/index.tsx | 4 +- .../src/components/LastUpdated/types.ts | 0 .../src/components/Layout/Layout.stories.tsx | 2 +- .../src/components/Layout/Layout.test.tsx | 12 +- .../src/components/Layout/index.tsx | 0 .../src/components/Layout/types.ts | 0 .../src/components/List/List.stories.tsx | 0 .../src/components/List/List.test.tsx | 2 +- .../src/components/List/index.ts | 2 +- .../src/components/List/types.ts | 0 .../ListViewCard/ImageLoader.test.tsx | 2 +- .../components/ListViewCard/ImageLoader.tsx | 0 .../ListViewCard/ListViewCard.stories.tsx | 2 +- .../ListViewCard/ListViewCard.test.tsx | 2 +- .../src/components/ListViewCard/index.tsx | 0 .../src/components/ListViewCard/types.ts | 0 .../components/Loading/Loading.stories.tsx | 0 .../src/components/Loading/Loading.test.tsx | 2 +- .../src/components/Loading/index.tsx | 2 +- .../src/components/Loading/types.ts | 0 .../src/components/Menu/Menu.stories.tsx | 0 .../src/components/Menu/index.tsx | 0 .../src/components/Metadata/index.tsx | 0 .../components/MetadataBar/ContentConfig.tsx | 2 +- .../src/components/MetadataBar/ContentType.ts | 0 .../MetadataBar/MetadataBar.stories.tsx | 0 .../MetadataBar/MetadataBar.test.tsx | 33 ++- .../components/MetadataBar/MetadataBar.tsx | 0 .../MetadataBarOverview.stories.tsx | 0 .../src/components/MetadataBar/constants.ts | 0 .../src/components/MetadataBar/index.tsx | 0 .../src/components/Modal/FormModal.test.tsx | 15 +- .../src/components/Modal/FormModal.tsx | 0 .../src/components/Modal/Modal.stories.tsx | 0 .../src/components/Modal/Modal.tsx | 0 .../src/components/Modal/index.ts | 0 .../src/components/Modal/types.ts | 0 .../ModalTrigger/ModalTrigger.stories.tsx | 2 +- .../ModalTrigger/ModalTrigger.test.tsx | 17 +- .../src/components/ModalTrigger/index.tsx | 4 +- .../PageHeaderWithActions.test.tsx | 4 +- .../PageHeaderWithActions/index.tsx | 2 +- .../components/Pagination/Ellipsis.test.tsx | 10 +- .../src/components/Pagination/Ellipsis.tsx | 0 .../src/components/Pagination/Item.test.tsx | 10 +- .../src/components/Pagination/Item.tsx | 0 .../src/components/Pagination/Next.test.tsx | 10 +- .../src/components/Pagination/Next.tsx | 0 .../src/components/Pagination/Prev.test.tsx | 10 +- .../src/components/Pagination/Prev.tsx | 0 .../components/Pagination/Wrapper.test.tsx | 2 +- .../src/components/Pagination/Wrapper.tsx | 0 .../src/components/Pagination/index.tsx | 2 +- .../src/components/Pagination/types.ts | 0 .../components/Popover/Popover.stories.tsx | 2 +- .../src/components/Popover/Popover.test.tsx | 14 +- .../src/components/Popover/index.tsx | 4 +- .../PopoverDropdown.stories.tsx | 0 .../PopoverDropdown/PopoverDropdown.test.tsx | 12 +- .../src/components/PopoverDropdown/index.tsx | 4 +- .../PopoverSection/PopoverSection.stories.tsx | 0 .../PopoverSection/PopoverSection.test.tsx | 8 +- .../src/components/PopoverSection/index.tsx | 2 +- .../ProgressBar/ProgressBar.stories.tsx | 0 .../ProgressBar/ProgressBar.test.tsx | 2 +- .../src/components/ProgressBar/index.tsx | 0 .../src/components/Radio/Radio.stories.tsx | 2 +- .../src/components/Radio/Radio.test.tsx | 4 +- .../src/components/Radio/index.tsx | 0 .../RefreshLabel/RefreshLabel.stories.tsx | 0 .../RefreshLabel/RefreshLabel.test.tsx | 10 +- .../src/components/RefreshLabel/index.tsx | 4 +- .../{ => SafeMarkdown}/SafeMarkdown.tsx | 6 +- .../components/Select/AsyncSelect.stories.tsx | 0 .../components/Select/AsyncSelect.test.tsx | 62 +++--- .../src/components/Select/AsyncSelect.tsx | 9 +- .../src/components/Select/Select.stories.tsx | 17 -- .../src/components/Select/Select.test.tsx | 86 ++++---- .../src/components/Select/Select.tsx | 12 +- .../src/components/Select/constants.ts | 2 +- .../src/components/Select/index.ts | 31 +++ .../src/components/Select/styles.tsx | 2 +- .../src/components/Select/types.ts | 0 .../src/components/Select/utils.tsx | 2 +- .../components/Skeleton/Skeleton.stories.tsx | 0 .../src/components/Skeleton/Skeleton.test.tsx | 8 +- .../src/components/Skeleton/index.tsx | 0 .../src/components/Slider/Slider.stories.tsx | 0 .../src/components/Slider/Slider.test.tsx | 2 +- .../src/components/Slider/index.tsx | 0 .../src/components/Space/Space.stories.tsx | 0 .../src/components/Space/Space.test.tsx | 4 +- .../src/components/Space/index.tsx | 0 .../src/components/Spin/Spin.test.tsx | 2 +- .../src/components/Spin/index.tsx | 0 .../src/components/Steps/Steps.stories.tsx | 0 .../src/components/Steps/Steps.test.tsx | 2 +- .../src/components/Steps/index.tsx | 0 .../src/components/Switch/Switch.stories.tsx | 0 .../src/components/Switch/Switch.test.tsx | 2 +- .../src/components/Switch/index.tsx | 0 .../src/components/Table/Table.stories.tsx | 0 .../src/components/Table/Table.test.tsx | 2 +- .../Table/TableOverview.stories.tsx | 4 +- .../src/components/Table/VirtualTable.tsx | 0 .../ActionCell/ActionCell.overview.tsx | 0 .../ActionCell/ActionCell.stories.tsx | 0 .../ActionCell/ActionCell.test.tsx | 8 +- .../cell-renderers/ActionCell/fixtures.ts | 0 .../Table/cell-renderers/ActionCell/index.tsx | 0 .../BooleanCell/BooleanCell.stories.tsx | 0 .../BooleanCell/BooleanCell.test.tsx | 10 +- .../cell-renderers/BooleanCell/index.tsx | 8 +- .../ButtonCell/ButtonCell.stories.tsx | 0 .../ButtonCell/ButtonCell.test.tsx | 2 +- .../Table/cell-renderers/ButtonCell/index.tsx | 0 .../NullCell/NullCell.stories.tsx | 0 .../cell-renderers/NullCell/NullCell.test.tsx | 10 +- .../Table/cell-renderers/NullCell/index.tsx | 6 +- .../NumericCell/NumericCell.stories.tsx | 0 .../NumericCell/NumericCell.test.tsx | 2 +- .../cell-renderers/NumericCell/index.tsx | 0 .../TimeCell/TimeCell.stories.tsx | 0 .../cell-renderers/TimeCell/TimeCell.test.tsx | 2 +- .../Table/cell-renderers/TimeCell/index.tsx | 0 .../Table/cell-renderers/fixtures.ts | 0 .../header-renderers/HeaderWithRadioGroup.tsx | 6 +- .../src/components/Table/index.tsx | 2 +- .../src/components/Table/sorters.test.ts | 0 .../src/components/Table/sorters.ts | 0 .../Table/utils/InteractiveTableUtils.ts | 2 +- .../src/components/Table/utils/utils.test.ts | 2 +- .../src/components/Table/utils/utils.ts | 0 .../TableCollection/TableCollection.test.tsx | 2 +- .../src/components/TableCollection/index.tsx | 6 +- .../src/components/TableCollection/utils.tsx | 36 +++- .../TableView/TableView.stories.tsx | 2 +- .../components/TableView/TableView.test.tsx | 16 +- .../src/components/TableView/TableView.tsx | 14 +- .../src/components/TableView/index.ts | 1 - .../src/components/TableView/types.ts | 0 .../src/components/Tabs/Tabs.stories.tsx | 0 .../src/components/Tabs/Tabs.tsx | 2 +- .../src/components/Tabs/index.ts | 0 .../src/components/Tag/index.tsx | 19 ++ .../TelemetryPixel/TelemetryPixel.test.tsx | 2 +- .../src/components/TelemetryPixel/index.tsx | 0 .../src/components/ThemeEditor/index.tsx | 4 +- .../src/components/Timer/Timer.stories.tsx | 4 +- .../src/components/Timer/Timer.test.tsx | 12 +- .../src/components/Timer/index.tsx | 11 +- ...mezoneSelector.DaylightSavingTime.test.tsx | 9 +- .../TimezoneSelector.stories.tsx | 0 .../TimezoneSelector.test.tsx | 17 +- .../src/components/TimezoneSelector/index.tsx | 4 +- .../components/Tooltip/Tooltip.stories.tsx | 0 .../src/components/Tooltip/Tooltip.test.tsx | 10 +- .../src/components/Tooltip/index.tsx | 6 +- .../src/components/Tooltip/types.ts | 6 +- .../TooltipParagraph.stories.tsx | 0 .../TooltipParagraph.test.tsx | 11 +- .../src/components/TooltipParagraph/index.tsx | 6 +- .../src/components/Tree/Tree.stories.tsx | 2 +- .../src/components/Tree/Tree.test.tsx | 4 +- .../src/components/Tree/index.tsx | 0 .../TreeSelect/TreeSelect.stories.tsx | 0 .../components/TreeSelect/TreeSelect.test.tsx | 2 +- .../src/components/TreeSelect/index.tsx | 0 .../src/components/TruncatedList/index.tsx | 2 +- .../Typography/Typography.stories.tsx | 0 .../components/Typography/Typography.test.tsx | 16 +- .../src/components/Typography/index.tsx | 0 .../src/components/Upload/Upload.stories.tsx | 0 .../src/components/Upload/Upload.test.tsx | 11 +- .../src/components/Upload/index.tsx | 0 .../WarningIconWithTooltip.stories.tsx | 0 .../WarningIconWithTooltip/index.tsx | 6 +- .../assets/images/.!80135!loading.gif | 0 .../assets/images/.!80342!loading.gif | 0 .../assets/images/.!80520!loading.gif | 0 .../assets/images/.!80903!loading.gif | 0 .../src/components/assets/images/index.ts} | 8 +- .../src/components/assets/images/loading.gif | Bin 0 -> 79023 bytes .../src/components/assets/index.ts | 20 ++ .../src/components/assets/svgs}/chart.svg | 0 .../src/components/assets/svgs}/error.svg | 0 .../src/components/assets/svgs/index.ts | 22 ++ .../src/components/atomic-design.png | Bin .../src/components/constants.ts | 16 +- .../superset-ui-core/src/components/index.ts | 149 ++++++++++++- .../packages/superset-ui-core/src/index.ts | 1 - .../src/query/api/v1/types.ts | 2 +- .../superset-ui-core/src/spec/index.tsx | 46 ++++ .../superset-ui-core}/src/utils/dates.test.ts | 2 +- .../superset-ui-core}/src/utils/dates.ts | 0 .../superset-ui-core/src/utils/html.test.tsx | 48 ++--- .../src/utils/rankedSearchCompare.test.ts | 0 .../src/utils/rankedSearchCompare.ts | 0 .../chart-composition/ChartFrame.test.tsx | 12 +- .../test/components/SafeMarkdown.test.ts | 2 +- .../currency-format/CurrencyFormatter.test.ts | 10 +- .../test/utils/featureFlag.test.ts | 12 +- .../packages/superset-ui-core/tsconfig.json | 14 +- .../superset-ui-core}/types/ace-builds.d.ts | 0 .../superset-ui-core/types/assets.d.ts | 21 ++ .../superset-ui-core/types/brace.d.ts | 29 +++ .../types/react-table-config.d.ts | 0 .../packages/superset-ui-demo/package.json | 1 - .../shared/components/VerifyCORS.tsx | 2 +- .../storybook/stories/ExampleApp.stories.jsx | 13 +- .../tsconfig.json | 26 +-- .../legacy-plugin-chart-chord/tsconfig.json | 26 +-- .../tsconfig.json | 26 +-- .../legacy-plugin-chart-horizon/tsconfig.json | 26 +-- .../legacy-plugin-chart-map-box/tsconfig.json | 26 +-- .../tsconfig.json | 26 +-- .../package.json | 2 +- .../src/ParallelCoordinates.js | 2 +- .../tsconfig.json | 34 ++- .../types/d3-parcoords.d.ts | 22 ++ .../types/d3.d.ts | 22 ++ .../src/OptionDescription.tsx | 8 +- .../test/OptionDescription.test.jsx | 2 +- .../tsconfig.json | 31 ++- .../legacy-plugin-chart-rose/tsconfig.json | 26 +-- .../tsconfig.json | 26 +-- .../legacy-preset-chart-deckgl/tsconfig.json | 27 +-- .../legacy-preset-chart-nvd3/tsconfig.json | 26 +-- .../plugin-chart-cartodiagram/tsconfig.json | 26 +-- .../src/Timeseries/Step/index.ts | 5 +- .../MixedTimeseries/transformProps.test.ts | 2 +- .../test/Timeseries/transformers.test.ts | 2 +- .../test/utils/transformers.test.ts | 2 +- .../plugin-chart-echarts/tsconfig.json | 26 +-- .../Handlebars/HandlebarsViewer.tsx | 3 +- .../plugin-chart-handlebars/src/consts.ts | 5 +- .../src/plugin/controls/handlebarTemplate.tsx | 6 +- .../src/plugin/controls/style.tsx | 4 +- .../plugin-chart-handlebars/tsconfig.json | 31 ++- .../plugin-chart-pivot-table/tsconfig.json | 26 +-- .../plugins/plugin-chart-table/package.json | 1 - .../src/DataTable/DataTable.tsx | 2 +- .../src/DataTable/components/GlobalFilter.tsx | 2 +- .../components/SearchSelectDropdown.tsx | 4 +- .../DataTable/components/SelectPageSize.tsx | 8 +- .../plugin-chart-table/src/TableChart.tsx | 10 +- .../plugin-chart-table/src/buildQuery.ts | 11 +- .../test/TableChart.test.tsx | 2 +- .../plugins/plugin-chart-table/tsconfig.json | 24 +-- .../src/chart/WordCloud.tsx | 61 +++--- .../plugin-chart-word-cloud/tsconfig.json | 26 +-- superset-frontend/spec/helpers/shim.tsx | 2 +- .../src/SqlLab/actions/sqlLab.js | 2 +- .../AceEditorWrapper.test.tsx | 11 +- .../components/AceEditorWrapper/index.tsx | 2 +- .../AceEditorWrapper/useKeywords.ts | 2 +- .../SqlLab/components/ColumnElement/index.tsx | 2 +- .../EstimateQueryCostButton.test.tsx | 4 +- .../EstimateQueryCostButton/index.tsx | 12 +- .../ExploreCtasResultsButton/index.tsx | 4 +- .../ExploreResultsButton.test.tsx | 2 +- .../components/ExploreResultsButton/index.tsx | 6 +- .../components/HighlightedSql/index.tsx | 2 +- .../KeyboardShortcutButton/index.tsx | 2 +- .../QueryAutoRefresh.test.tsx | 177 ++++++++------- .../SqlLab/components/QueryHistory/index.tsx | 2 +- .../QueryLimitSelect.test.tsx | 4 +- .../components/QueryLimitSelect/index.tsx | 6 +- .../QueryStateLabel/QueryStateLabel.test.tsx | 2 +- .../components/QueryStateLabel/index.tsx | 2 +- .../SqlLab/components/QueryTable/index.tsx | 17 +- .../SqlLab/components/QueryTable/styles.ts | 2 +- .../src/SqlLab/components/ResultSet/index.tsx | 12 +- .../RunQueryActionButton.test.tsx | 4 +- .../components/RunQueryActionButton/index.tsx | 4 +- .../SaveDatasetActionButton.test.tsx | 2 +- .../SaveDatasetActionButton/index.tsx | 4 +- .../components/SaveDatasetModal/index.tsx | 4 +- .../src/SqlLab/components/SaveQuery/index.tsx | 12 +- .../components/ScheduleQueryButton/index.tsx | 14 +- .../components/ShareSqlLabQuery/index.tsx | 5 +- .../src/SqlLab/components/ShowSQL/index.tsx | 5 +- .../SqlLab/components/SouthPane/Results.tsx | 2 +- .../src/SqlLab/components/SouthPane/index.tsx | 6 +- .../components/SqlEditor/SqlEditor.test.tsx | 4 +- .../src/SqlLab/components/SqlEditor/index.tsx | 16 +- .../components/SqlEditorLeftBar/index.tsx | 3 +- .../SqlEditorTabHeader.test.tsx | 4 +- .../components/SqlEditorTabHeader/index.tsx | 8 +- .../components/TabbedSqlEditors/index.tsx | 6 +- .../TableElement/TableElement.test.tsx | 4 +- .../SqlLab/components/TableElement/index.tsx | 10 +- .../TablePreview/TablePreview.test.tsx | 2 +- .../SqlLab/components/TablePreview/index.tsx | 17 +- .../TemplateParamsEditor.test.tsx | 6 +- .../components/TemplateParamsEditor/index.tsx | 16 +- superset-frontend/src/SqlLab/constants.ts | 2 +- .../src/SqlLab/reducers/sqlLab.js | 2 +- superset-frontend/src/SqlLab/types.ts | 5 +- ....!4592!superset-logo-horiz-apache-dark.png | 0 ....!4862!superset-logo-horiz-apache-dark.png | 0 ....!4993!superset-logo-horiz-apache-dark.png | 0 .../src/components/AlteredSliceTag/index.tsx | 12 +- .../AuditInfo/ModifiedInfo.test.tsx | 4 +- .../src/components/AuditInfo/index.tsx | 2 +- .../src/components/Chart/Chart.tsx | 3 +- .../ChartContextMenu/ChartContextMenu.tsx | 4 +- .../Chart/ChartErrorMessage.test.tsx | 2 +- .../src/components/Chart/ChartRenderer.jsx | 2 +- .../Chart/DisabledMenuItemTooltip.tsx | 4 +- .../Chart/DrillBy/DrillByMenuItems.test.tsx | 2 +- .../Chart/DrillBy/DrillByMenuItems.tsx | 9 +- .../components/Chart/DrillBy/DrillByModal.tsx | 2 +- .../Chart/DrillBy/useDisplayModeToggle.tsx | 2 +- .../Chart/DrillBy/useResultsTableView.tsx | 2 +- .../DrillDetail/DrillDetailMenuItems.test.tsx | 2 +- .../DrillDetail/DrillDetailMenuItems.tsx | 2 +- .../Chart/DrillDetail/DrillDetailModal.tsx | 2 +- .../Chart/DrillDetail/DrillDetailPane.tsx | 15 +- .../DrillDetail/DrillDetailTableControls.tsx | 2 +- .../Chart/MenuItemWithTruncation.tsx | 4 +- .../src/components/Chart/chartAction.js | 2 +- .../src/components/Chart/chartReducer.ts | 2 +- .../CopyToClipboard.stories.tsx | 4 +- .../src/components/CopyToClipboard/index.tsx | 2 +- .../DatabaseSelector.test.tsx | 24 +-- .../src/components/DatabaseSelector/index.tsx | 15 +- .../Datasource/ChangeDatasourceModal.tsx | 26 ++- .../components/Datasource/CollectionTable.tsx | 20 +- .../Datasource/DatasourceEditor.jsx | 40 ++-- .../Datasource/DatasourceEditor.test.jsx | 49 +++-- .../DatasourceEditorCurrency.test.jsx | 2 +- .../Datasource/DatasourceEditorRTL.test.jsx | 23 +- .../components/Datasource/DatasourceModal.tsx | 14 +- .../src/components/Datasource/Field.test.tsx | 2 +- .../src/components/Datasource/Field.tsx | 9 +- .../src/components/Datasource/Fieldset.tsx | 4 +- .../DropdownContainer.test.tsx | 157 -------------- .../ErrorMessage/BasicErrorAlert.test.tsx | 2 +- .../ErrorMessage/BasicErrorAlert.tsx | 2 +- .../DatabaseErrorMessage.test.tsx | 2 +- .../DatasetNotFoundErrorMessage.test.tsx | 2 +- .../ErrorMessage/ErrorAlert.stories.tsx | 4 +- .../ErrorMessage/ErrorAlert.test.tsx | 3 +- .../components/ErrorMessage/ErrorAlert.tsx | 12 +- .../ErrorMessageWithStackTrace.test.tsx | 2 +- .../ErrorMessageWithStackTrace.tsx | 2 +- .../FrontendNetworkErrorMessage.test.tsx | 2 +- .../src/components/ErrorMessage/IssueCode.tsx | 2 +- .../ErrorMessage/MarshmallowErrorMessage.tsx | 4 +- .../ParameterErrorMessage.test.tsx | 2 +- .../ErrorMessage/ParameterErrorMessage.tsx | 2 +- .../ErrorMessage/TimeoutErrorMessage.test.tsx | 2 +- .../src/components/FacePile/index.tsx | 2 +- .../src/components/FilterableTable/index.tsx | 6 +- .../src/components/GridTable/Header.test.tsx | 6 +- .../src/components/GridTable/Header.tsx | 2 +- .../components/GridTable/HeaderMenu.test.tsx | 14 +- .../src/components/GridTable/HeaderMenu.tsx | 10 +- .../src/components/GridTable/index.tsx | 5 +- .../src/components/ImportModal/ErrorAlert.tsx | 2 +- .../ImportModal/ImportErrorAlert.tsx | 2 +- .../src/components/ImportModal/index.tsx | 10 +- .../src/components/InfoTooltip/index.tsx | 86 -------- .../src/components/JsonModal/index.tsx | 3 +- .../src/components/ListView/ActionsBar.tsx | 9 +- .../components/ListView/CardSortSelect.tsx | 3 +- .../ListView/CrossLinksTooltip.test.tsx | 8 +- .../components/ListView/CrossLinksTooltip.tsx | 2 +- .../components/ListView/Filters/DateRange.tsx | 12 +- .../ListView/Filters/NumericalRange.tsx | 4 +- .../components/ListView/Filters/Search.tsx | 14 +- .../components/ListView/Filters/Select.tsx | 3 +- .../src/components/ListView/ListView.tsx | 18 +- .../src/components/MessageToasts/Toast.tsx | 2 +- .../TableSelector/TableSelector.test.tsx | 14 +- .../src/components/TableSelector/index.tsx | 12 +- .../{InfoTooltip/types.ts => Tag/TagType.ts} | 43 ++-- .../src/components/Tag/index.tsx | 5 +- .../components/TagsList/TagsList.stories.tsx | 2 +- .../src/components/TagsList/TagsList.test.tsx | 2 +- .../src/components/TagsList/index.tsx | 4 +- superset-frontend/src/components/index.ts | 204 ++---------------- superset-frontend/src/constants.ts | 24 +-- .../components/AddSliceCard/AddSliceCard.tsx | 8 +- .../components/BuilderComponentPane/index.tsx | 2 +- .../components/CssEditor/CssEditor.test.tsx | 4 +- .../dashboard/components/CssEditor/index.tsx | 10 +- .../src/dashboard/components/Dashboard.jsx | 3 +- .../DashboardBuilder.test.tsx | 6 +- .../DashboardBuilder/DashboardBuilder.tsx | 10 +- .../DashboardBuilder/DashboardContainer.tsx | 2 +- .../DashboardBuilder/DashboardWrapper.tsx | 8 +- .../dashboard/components/DashboardGrid.jsx | 4 +- .../components/DeleteComponentButton.tsx | 2 +- .../components/EmbeddedModal/index.tsx | 15 +- .../FiltersBadge/DetailsPanel/index.tsx | 2 +- .../FiltersBadge/FilterIndicator/index.tsx | 2 +- .../components/FiltersBadge/index.tsx | 4 +- .../src/dashboard/components/Header/index.jsx | 8 +- .../Header/useDashboardMetadataBar.tsx | 4 +- .../Header/useHeaderActionsDropdownMenu.tsx | 2 +- .../OverwriteConfirmModal.tsx | 4 +- .../components/OverwriteConfirm/index.tsx | 2 +- .../PropertiesModal/PropertiesModal.test.jsx | 2 +- .../components/PropertiesModal/index.tsx | 6 +- .../components/PublishedStatus/index.tsx | 2 +- .../components/RefreshIntervalModal.test.tsx | 2 +- .../components/RefreshIntervalModal.tsx | 15 +- .../src/dashboard/components/SaveModal.tsx | 16 +- .../src/dashboard/components/SliceAdder.tsx | 14 +- .../components/SliceHeader/index.tsx | 33 ++- .../ViewResultsModalTrigger.tsx | 3 +- .../components/SliceHeaderControls/index.tsx | 14 +- .../components/URLShortLinkButton/index.tsx | 11 +- .../dashboard/components/dnd/DragHandle.tsx | 2 +- .../filterscope/FilterFieldItem.jsx | 2 +- .../filterscope/FilterScopeModal.tsx | 5 +- .../filterscope/FilterScopeSelector.jsx | 2 +- .../renderFilterScopeTreeNodes.jsx | 2 +- .../components/filterscope/treeIcons.jsx | 2 +- .../components/gridComponents/Column.jsx | 2 +- .../components/gridComponents/Header.jsx | 4 +- .../components/gridComponents/Markdown.jsx | 4 +- .../components/gridComponents/Row.jsx | 5 +- .../components/gridComponents/Tab.jsx | 2 +- .../components/gridComponents/Tab.test.tsx | 4 +- .../components/gridComponents/Tabs.jsx | 6 +- .../components/gridComponents/Tabs.test.jsx | 2 +- .../gridComponents/new/NewColumn.jsx | 2 +- .../gridComponents/new/NewDivider.jsx | 2 +- .../gridComponents/new/NewHeader.jsx | 2 +- .../gridComponents/new/NewMarkdown.jsx | 2 +- .../components/gridComponents/new/NewRow.jsx | 2 +- .../components/gridComponents/new/NewTabs.jsx | 2 +- .../menu/BackgroundStyleDropdown.tsx | 2 +- .../DownloadAsImage.test.tsx | 2 +- .../DownloadMenuItems/DownloadAsImage.tsx | 2 +- .../DownloadMenuItems/DownloadAsPdf.test.tsx | 2 +- .../menu/DownloadMenuItems/DownloadAsPdf.tsx | 2 +- .../DownloadMenuItems.test.tsx | 2 +- .../DownloadScreenshot.test.tsx | 2 +- .../DownloadMenuItems/DownloadScreenshot.tsx | 2 +- .../menu/DownloadMenuItems/index.tsx | 2 +- .../components/menu/MarkdownModeDropdown.tsx | 2 +- .../ShareMenuItems/ShareMenuItems.test.tsx | 2 +- .../components/menu/ShareMenuItems/index.tsx | 2 +- .../FilterBar/ActionButtons/index.tsx | 2 +- .../FilterBar/CrossFilters/CrossFilterTag.tsx | 2 +- .../CrossFilters/CrossFilterTitle.tsx | 4 +- .../ScopingModal/ChartsScopingListPanel.tsx | 6 +- .../ScopingModal/ScopingModal.tsx | 2 +- .../ScopingModal/ScopingTreePanel.tsx | 6 +- .../CrossFilters/VerticalCollapse.tsx | 2 +- .../FilterBarSettings.test.tsx | 3 +- .../FilterBar/FilterBarSettings/index.tsx | 8 +- .../FilterControls/FilterControl.tsx | 2 +- .../FilterControls/FilterControls.tsx | 4 +- .../FilterControls/FilterDivider.tsx | 4 +- .../FilterBar/FilterControls/FilterValue.tsx | 10 +- .../FilterBar/FilterControls/utils.ts | 6 +- .../FiltersOutOfScopeCollapsible/index.tsx | 2 +- .../nativeFilters/FilterBar/Header/index.tsx | 4 +- .../nativeFilters/FilterBar/Horizontal.tsx | 2 +- .../nativeFilters/FilterBar/Vertical.tsx | 4 +- .../nativeFilters/FilterBar/index.tsx | 4 +- .../FilterCard/DependenciesRow.tsx | 4 +- .../nativeFilters/FilterCard/NameRow.tsx | 2 +- .../nativeFilters/FilterCard/ScopeRow.tsx | 2 +- .../FilterCard/TooltipWithTruncation.tsx | 3 +- .../nativeFilters/FilterCard/index.tsx | 2 +- .../FiltersConfigModal/DividerConfigForm.tsx | 2 +- .../FiltersConfigModal/DraggableFilter.tsx | 4 +- .../FilterTitleContainer.tsx | 4 +- .../FiltersConfigModal/FilterTitlePane.tsx | 4 +- .../CollapsibleControl.test.tsx | 9 +- .../FiltersConfigForm/CollapsibleControl.tsx | 7 +- .../FiltersConfigForm/ColumnSelect.tsx | 2 +- .../FiltersConfigForm/DatasetSelect.tsx | 2 +- .../FiltersConfigForm/DefaultValue.tsx | 2 +- .../FiltersConfigForm/DependencyList.tsx | 4 +- .../FilterScope/FilterScope.tsx | 2 +- .../FilterScope/ScopingTree.tsx | 6 +- .../__tests__/TreeInitialization.test.tsx | 2 +- .../__tests__/TreeSelection.test.tsx | 2 +- .../FilterScope/__tests__/utils.tsx | 2 +- .../FiltersConfigForm/FiltersConfigForm.tsx | 26 +-- .../FiltersConfigForm/RemovedFilter.tsx | 2 +- .../getControlItemsMap.test.tsx | 2 +- .../FiltersConfigForm/getControlItemsMap.tsx | 15 +- .../FiltersConfigForm/state.ts | 2 +- .../FiltersConfigForm/utils.ts | 2 +- .../FiltersConfigModal/FiltersConfigModal.tsx | 12 +- .../Footer/CancelConfirmationAlert.tsx | 6 +- .../FiltersConfigModal/Footer/Footer.tsx | 2 +- .../nativeFilters/FiltersConfigModal/utils.ts | 2 +- .../dashboard/containers/DashboardPage.tsx | 2 +- superset-frontend/src/embedded/index.tsx | 3 +- .../src/explore/components/ChartPills.tsx | 9 +- .../src/explore/components/ControlHeader.tsx | 7 +- .../components/ControlPanelsContainer.tsx | 8 +- .../components/DataTableControl/index.tsx | 34 +-- .../DataTableControl/useTableColumns.test.ts | 6 +- .../DataTablesPane/DataTablesPane.tsx | 4 +- .../components/DataTableControls.tsx | 1 + .../components/ResultsPaneOnDashboard.tsx | 2 +- .../DataTablesPane/components/SamplesPane.tsx | 10 +- .../components/SingleQueryResultPane.tsx | 7 +- .../components/useResultsPane.tsx | 2 +- .../DatasourcePanelDragOption/index.tsx | 2 +- .../DatasourcePanel/DatasourcePanelItem.tsx | 17 +- .../components/DatasourcePanel/index.tsx | 5 +- .../explore/components/EmbedCodeContent.jsx | 5 +- .../src/explore/components/ExploreAlert.tsx | 3 +- .../components/ExploreChartHeader/index.jsx | 7 +- .../useExploreMetadataBar.tsx | 4 +- .../components/ExploreChartPanel/index.jsx | 3 +- .../components/ExploreViewContainer/index.jsx | 5 +- .../components/ExportToCSVDropdown/index.tsx | 6 +- .../components/PropertiesModal/index.tsx | 8 +- .../components/RowCountLabel/index.tsx | 2 +- .../components/RunQueryButton/index.tsx | 4 +- .../src/explore/components/SaveModal.test.jsx | 4 +- .../src/explore/components/SaveModal.tsx | 26 +-- .../AnnotationLayer.jsx | 4 +- .../controls/AnnotationLayerControl/index.tsx | 11 +- .../components/controls/BoundsControl.tsx | 2 +- .../components/controls/CheckboxControl.jsx | 2 +- .../CollectionControl.test.tsx | 6 +- .../controls/CollectionControl/index.jsx | 8 +- .../controls/ColorPickerControl.jsx | 2 +- .../ColorSchemeControl/ColorSchemeLabel.tsx | 2 +- .../controls/ColorSchemeControl/index.tsx | 10 +- .../ColumnConfigControl.tsx | 2 +- .../ColumnConfigControl/ColumnConfigItem.tsx | 4 +- .../ColumnConfigPopover.tsx | 2 +- .../ControlForm/controls.ts | 4 +- .../ColumnConfigControl/ControlForm/index.tsx | 12 +- .../ColumnConfigControl/constants.tsx | 2 +- .../controls/ComparisonRangeLabel.tsx | 2 +- .../ConditionalFormattingControl.tsx | 2 +- .../FormattingPopover.tsx | 2 +- .../FormattingPopoverContent.tsx | 10 +- .../ConditionalFormattingControl/types.ts | 2 +- .../ContourControl/ContourPopoverControl.tsx | 4 +- .../ControlPopover/ControlPopover.tsx | 7 +- .../CurrencyControl/CurrencyControl.tsx | 2 +- .../controls/CustomListItem/index.tsx | 2 +- .../controls/DatasourceControl/index.jsx | 10 +- .../DateFilterControl/DateFilterLabel.tsx | 14 +- .../components/AdvancedFrame.tsx | 7 +- .../components/CalendarFrame.tsx | 2 +- .../components/CommonFrame.tsx | 2 +- .../components/CurrentCalendarFrame.tsx | 2 +- .../components/CustomFrame.tsx | 10 +- .../components/DateFunctionTooltip.tsx | 2 +- .../components/DateLabel.tsx | 2 +- .../DateFilterControl/utils/constants.ts | 4 +- .../DateFilterControl/utils/dateParser.ts | 2 +- .../ColumnSelectPopover.tsx | 4 +- .../DndColumnSelectPopoverTitle.jsx | 4 +- .../DndFilterSelect.test.tsx | 12 +- .../DndFilterSelect.tsx | 2 +- .../DndColumnSelectControl/DndSelectLabel.tsx | 2 +- .../DndColumnSelectControl/Option.tsx | 7 +- .../DndColumnSelectControl/OptionWrapper.tsx | 2 +- .../useResizeButton.tsx | 2 +- .../AdhocFilterControl/index.jsx | 4 +- .../AdhocFilterEditPopover/index.jsx | 5 +- .../index.tsx | 2 +- ...hocFilterEditPopoverSqlTabContent.test.tsx | 2 +- .../index.tsx | 2 +- .../FixedOrMetricControl.test.tsx | 2 +- .../controls/FixedOrMetricControl/index.jsx | 4 +- .../components/controls/HiddenControl.tsx | 2 +- .../LayerConfigsControl/FlatLayerTree.tsx | 6 +- .../LayerConfigsControl.tsx | 2 +- .../LayerConfigsPopoverContent.tsx | 6 +- .../LayerConfigsControl/LayerTreeItem.tsx | 5 +- .../LayerConfigsControl/dragDropUtil.tsx | 2 +- .../controls/LayerConfigsControl/types.ts | 2 +- .../MapViewControl/MapViewControl.tsx | 3 +- .../MapViewControl/MapViewPopoverContent.tsx | 2 +- .../AdhocMetricEditPopover/index.jsx | 4 +- .../AdhocMetricEditPopoverTitle.tsx | 4 +- .../controls/MetricControl/MetricsControl.jsx | 2 +- .../controls/NumberControl/index.tsx | 2 +- .../controls/OptionControls/index.tsx | 8 +- .../SelectAsyncControl.test.tsx | 2 +- .../controls/SelectAsyncControl/index.tsx | 2 +- .../components/controls/SelectControl.jsx | 2 +- .../components/controls/SliderControl.tsx | 2 +- .../components/controls/SpatialControl.jsx | 11 +- .../components/controls/TextAreaControl.jsx | 8 +- .../components/controls/TextControl/index.tsx | 5 +- .../controls/TimeOffsetControl.test.tsx | 2 +- .../components/controls/TimeOffsetControl.tsx | 7 +- .../TimeSeriesColumnControl/index.jsx | 15 +- .../explore/components/controls/ViewQuery.tsx | 3 +- .../components/controls/ViewQueryModal.tsx | 2 +- .../controls/ViewQueryModalFooter.tsx | 2 +- .../components/controls/ViewportControl.jsx | 3 +- .../VizTypeControl/FastVizSwitcher.tsx | 2 +- .../controls/VizTypeControl/VizTile.tsx | 6 +- .../VizTypeControl/VizTypeControl.test.tsx | 6 +- .../VizTypeControl/VizTypeGallery.tsx | 11 +- .../controls/VizTypeControl/constants.tsx | 2 +- .../controls/VizTypeControl/index.tsx | 3 +- .../ZoomConfigControl/ZoomConfigControl.tsx | 3 +- .../DashboardsSubMenu.test.tsx | 2 +- .../DashboardsSubMenu.tsx | 6 +- .../useExploreAdditionalActionsMenu/index.jsx | 6 +- .../controlUtils/getColumnKeywords.tsx | 2 +- .../controlUtils/standardizedFormData.test.ts | 5 +- .../src/features/alerts/AlertReportModal.tsx | 28 ++- .../alerts/buildErrorTooltipMessage.tsx | 2 +- .../components/AlertReportCronScheduler.tsx | 7 +- .../alerts/components/AlertStatusIcon.tsx | 4 +- .../alerts/components/NotificationMethod.tsx | 6 +- .../alerts/components/NumberInput.tsx | 2 +- .../alerts/components/RecipientIcon.tsx | 4 +- .../features/allEntities/AllEntitiesTable.tsx | 18 +- .../AnnotationLayerModal.test.jsx | 2 +- .../annotationLayers/AnnotationLayerModal.tsx | 6 +- .../annotations/AnnotationModal.test.jsx | 2 +- .../features/annotations/AnnotationModal.tsx | 11 +- .../src/features/charts/ChartCard.tsx | 8 +- .../cssTemplates/CssTemplateModal.test.jsx | 2 +- .../cssTemplates/CssTemplateModal.tsx | 6 +- .../src/features/dashboards/DashboardCard.tsx | 8 +- .../CommonParameters.tsx | 5 +- .../DatabaseConnectionForm/EncryptedField.tsx | 4 +- .../OAuth2ClientField.tsx | 2 +- .../DatabaseConnectionForm/TableCatalog.tsx | 6 +- .../ValidatedInputField.tsx | 2 +- .../DatabaseConnectionForm/index.tsx | 2 +- .../databases/DatabaseModal/ExtraOptions.tsx | 2 +- .../databases/DatabaseModal/ModalHeader.tsx | 4 +- .../databases/DatabaseModal/SSHTunnelForm.tsx | 13 +- .../DatabaseModal/SSHTunnelSwitch.test.tsx | 2 +- .../DatabaseModal/SSHTunnelSwitch.tsx | 5 +- .../DatabaseModal/SqlAlchemyForm.tsx | 2 +- .../databases/DatabaseModal/index.test.tsx | 31 +-- .../databases/DatabaseModal/index.tsx | 18 +- .../databases/DatabaseModal/styles.ts | 2 +- .../UploadDataModel/ColumnsPreview.tsx | 5 +- .../UploadDataModel/StyledFormItemWithTip.tsx | 2 +- .../UploadDataModel/UploadDataModal.test.tsx | 2 +- .../databases/UploadDataModel/index.tsx | 6 +- .../databases/UploadDataModel/styles.ts | 2 +- .../src/features/databases/types.ts | 2 +- .../DatasetPanel/DatasetPanel.test.tsx | 2 +- .../AddDataset/DatasetPanel/DatasetPanel.tsx | 9 +- .../DatasetPanel/MessageContent.tsx | 2 +- .../AddDataset/EditDataset/UsageTab/index.tsx | 15 +- .../datasets/AddDataset/EditDataset/index.tsx | 4 +- .../datasets/AddDataset/Footer/index.tsx | 2 +- .../datasets/AddDataset/Header/index.tsx | 10 +- .../datasets/AddDataset/LeftPanel/index.tsx | 5 +- .../datasets/DatasetSelectLabel/index.tsx | 2 +- .../datasets/DuplicateDatasetModal.tsx | 2 +- .../metadataBar/useDatasetMetadataBar.tsx | 6 +- .../src/features/home/ActivityTable.tsx | 6 +- .../src/features/home/ChartTable.tsx | 5 +- .../src/features/home/DashboardTable.tsx | 4 +- .../src/features/home/EmptyState.tsx | 5 +- .../features/home/LanguagePicker.stories.tsx | 2 +- .../src/features/home/LanguagePicker.test.tsx | 2 +- .../src/features/home/LanguagePicker.tsx | 6 +- superset-frontend/src/features/home/Menu.tsx | 9 +- .../src/features/home/RightMenu.tsx | 12 +- .../src/features/home/SavedQueries.tsx | 11 +- .../src/features/home/SubMenu.tsx | 15 +- .../features/queries/QueryPreviewModal.tsx | 2 +- .../queries/SavedQueryPreviewModal.test.jsx | 2 +- .../queries/SavedQueryPreviewModal.tsx | 2 +- .../queries/SyntaxHighlighterCopy.tsx | 4 +- .../HeaderReportDropdown/index.test.tsx | 2 +- .../HeaderReportDropdown/index.tsx | 8 +- .../features/reports/ReportModal/index.tsx | 10 +- .../features/reports/ReportModal/styles.tsx | 4 +- .../features/rls/RowLevelSecurityModal.tsx | 6 +- .../src/features/roles/RoleFormItems.tsx | 2 +- .../src/features/roles/RoleListAddModal.tsx | 2 +- .../features/roles/RoleListDuplicateModal.tsx | 2 +- .../src/features/roles/RoleListEditModal.tsx | 9 +- .../src/features/tags/BulkTagModal.tsx | 7 +- .../src/features/tags/TagCard.tsx | 6 +- .../src/features/tags/TagModal.tsx | 2 +- superset-frontend/src/features/tags/tags.ts | 8 +- .../src/features/users/UserListModal.tsx | 2 +- .../components/Range/RangeFilterPlugin.tsx | 4 +- .../components/Select/SelectFilterPlugin.tsx | 16 +- .../TimeColumn/TimeColumnFilterPlugin.tsx | 6 +- .../filters/components/TimeColumn/types.ts | 2 +- .../TimeGrain/TimeGrainFilterPlugin.tsx | 6 +- .../src/filters/components/TimeGrain/types.ts | 2 +- .../src/hooks/useDebounceValue.ts | 4 +- .../src/pages/AlertReportList/index.tsx | 12 +- .../src/pages/AllEntities/index.tsx | 6 +- .../src/pages/AnnotationLayerList/index.tsx | 7 +- .../AnnotationList/AnnotationList.test.jsx | 3 +- .../src/pages/AnnotationList/index.tsx | 7 +- superset-frontend/src/pages/Chart/index.tsx | 2 +- .../src/pages/ChartCreation/index.tsx | 4 +- .../src/pages/ChartList/index.tsx | 22 +- .../src/pages/CssTemplateList/index.tsx | 5 +- .../src/pages/DashboardList/index.tsx | 27 +-- .../pages/DatabaseList/DatabaseList.test.jsx | 3 +- .../src/pages/DatabaseList/index.tsx | 10 +- .../pages/DatasetList/DatasetList.test.tsx | 3 +- .../src/pages/DatasetList/index.tsx | 17 +- .../src/pages/ExecutionLogList/index.tsx | 5 +- superset-frontend/src/pages/Home/index.tsx | 4 +- superset-frontend/src/pages/Login/index.tsx | 2 +- .../src/pages/QueryHistoryList/index.tsx | 8 +- .../src/pages/Register/index.tsx | 2 +- .../src/pages/RolesList/index.tsx | 5 +- .../src/pages/RowLevelSecurityList/index.tsx | 5 +- .../src/pages/SavedQueryList/index.tsx | 22 +- superset-frontend/src/pages/SqlLab/index.tsx | 2 +- superset-frontend/src/pages/Tags/index.tsx | 6 +- .../src/pages/UsersList/index.tsx | 5 +- superset-frontend/src/theme.ts | 3 - superset-frontend/src/types/Chart.ts | 4 +- superset-frontend/src/types/TaggedObject.ts | 4 +- superset-frontend/src/views/App.tsx | 3 +- .../src/views/RootContextProviders.tsx | 4 +- .../TimeTable/SparklineCell.tsx | 2 +- .../visualizations/TimeTable/TimeTable.jsx | 14 +- superset-frontend/tsconfig.base.json | 43 ++++ superset-frontend/tsconfig.json | 46 +--- 928 files changed, 3421 insertions(+), 3013 deletions(-) delete mode 100644 superset-frontend/packages/superset-ui-chart-controls/src/components/Tooltip.tsx create mode 100644 superset-frontend/packages/superset-ui-core/.eslintrc create mode 100644 superset-frontend/packages/superset-ui-core/__mocks__/mockExportObject.js create mode 100644 superset-frontend/packages/superset-ui-core/__mocks__/mockExportString.js create mode 100644 superset-frontend/packages/superset-ui-core/__mocks__/svgrMock.tsx rename superset-frontend/{ => packages/superset-ui-core}/src/components/Alert/Alert.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Alert/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Alert/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AntdThemeProvider/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/AsyncAceEditor.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/Tooltip.test.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/Tooltip.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/index.tsx (59%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncAceEditor/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncEsmComponent/AsyncEsmComponent.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncEsmComponent/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AsyncEsmComponent/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AutoComplete/AutoComplete.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AutoComplete/AutoComplete.test.tsx (85%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AutoComplete/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/AutoComplete/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Avatar/Avatar.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Avatar/Avatar.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Avatar/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Avatar/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Badge/Badge.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Badge/Badge.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Badge/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Badge/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Breadcrumb/Breadcrumb.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Breadcrumb/Breadcrumb.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Breadcrumb/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Breadcrumb/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Button/Button.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Button/Button.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Button/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Button/types.ts (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ButtonGroup/ButtonGroup.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ButtonGroup/ButtonGroup.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ButtonGroup/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ButtonGroup/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CachedLabel/CachedLabel.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CachedLabel/TooltipContent.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CachedLabel/TooltipContent.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CachedLabel/index.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CachedLabel/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Card/Card.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Card/Card.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Card/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Card/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CertifiedBadge/CertifiedBadge.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CertifiedBadge/CertifiedBadge.test.tsx (88%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CertifiedBadge/index.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CertifiedBadge/types.ts (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Checkbox/Checkbox.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Checkbox/Checkbox.test.tsx (80%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Checkbox/CheckboxIcons.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Checkbox/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Checkbox/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/Collapse.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/Collapse.test.tsx (90%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/Collapse.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/CollapseLabelInModal.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Collapse/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ConfirmStatusChange/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ConfirmStatusChange/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CronPicker/CronPicker.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CronPicker/CronPicker.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CronPicker/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/CronPicker/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DatePicker/DatePicker.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DatePicker/DatePicker.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DatePicker/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DatePicker/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DeleteModal/DeleteModal.test.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DeleteModal/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DeleteModal/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DesignSystem.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Divider/Divider.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Divider/Divider.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Divider/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Divider/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Dropdown/Dropdown.stories.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Dropdown/Dropdown.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Dropdown/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Dropdown/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownButton/DropdownButton.stories.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownButton/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownButton/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownContainer/DropdownContainer.stories.tsx (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.test.tsx rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownContainer/Overview.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownContainer/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DropdownContainer/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx (83%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DynamicEditableTitle/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/DynamicEditableTitle/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EditableTitle/EditableTitle.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EditableTitle/EditableTitle.test.tsx (91%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EditableTitle/index.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EditableTitle/types.ts (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EmptyState/Empty.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EmptyState/Empty.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EmptyState/EmptyState.stories.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EmptyState/index.tsx (83%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/document.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty-charts.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty-dashboard.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty-dataset.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty-query.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty-table.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/empty_sql_chart.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/filter-results.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/filter.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/star-circle.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/union.svg (100%) rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/EmptyState/svgs}/vector.svg (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/EmptyState/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/FaveStar/FaveStar.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/FaveStar/FaveStar.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/FaveStar/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/FaveStar/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Flex/Flex.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Flex/Flex.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Flex/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Flex/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/Form.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/FormItem.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/FormLabel.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/LabeledErrorBoundInput.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/LabeledErrorBoundInput.test.jsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/LabeledErrorBoundInput.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Form/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Grid/Grid.stories.tsx (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Grid/Grid.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Grid/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Grid/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconButton/IconButton.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconButton/IconButton.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconButton/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconTooltip/IconTooltip.stories.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconTooltip/IconTooltip.test.jsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconTooltip/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/IconTooltip/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/AntdEnhanced.tsx (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/AsyncIcon.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/BaseIcon.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/Icons.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/index.tsx (98%) rename superset-frontend/{src/assets/images/icons => packages/superset-ui-core/src/components/Icons/svgs}/transparent.svg (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Icons/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Image/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/InfoTooltip/InfoTooltip.stories.tsx (95%) rename superset-frontend/packages/{superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx => superset-ui-core/src/components/InfoTooltip/index.tsx} (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Input/Input.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Input/Input.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Input/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Input/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/Label.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/Label.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/reusable/DatasetTypeLabel.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/reusable/PublishedLabel.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Label/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/LastUpdated/LastUpdated.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/LastUpdated/index.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/LastUpdated/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Layout/Layout.stories.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Layout/Layout.test.tsx (89%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Layout/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Layout/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/List/List.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/List/List.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/List/index.ts (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/List/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/ImageLoader.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/ImageLoader.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/ListViewCard.stories.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/ListViewCard.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ListViewCard/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Loading/Loading.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Loading/Loading.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Loading/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Loading/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Menu/Menu.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Menu/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Metadata/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/ContentConfig.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/ContentType.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/MetadataBar.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/MetadataBar.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/MetadataBar.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/MetadataBarOverview.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/constants.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/MetadataBar/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/FormModal.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/FormModal.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/Modal.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/Modal.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/index.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Modal/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ModalTrigger/ModalTrigger.stories.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ModalTrigger/ModalTrigger.test.tsx (88%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ModalTrigger/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PageHeaderWithActions/PageHeaderWithActions.test.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PageHeaderWithActions/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Ellipsis.test.tsx (79%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Ellipsis.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Item.test.tsx (82%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Item.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Next.test.tsx (79%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Next.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Prev.test.tsx (79%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Prev.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Wrapper.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/Wrapper.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/index.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Pagination/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Popover/Popover.stories.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Popover/Popover.test.tsx (90%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Popover/index.tsx (91%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverDropdown/PopoverDropdown.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverDropdown/PopoverDropdown.test.tsx (88%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverDropdown/index.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverSection/PopoverSection.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverSection/PopoverSection.test.tsx (88%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/PopoverSection/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ProgressBar/ProgressBar.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ProgressBar/ProgressBar.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ProgressBar/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Radio/Radio.stories.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Radio/Radio.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Radio/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/RefreshLabel/RefreshLabel.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/RefreshLabel/RefreshLabel.test.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/RefreshLabel/index.tsx (92%) rename superset-frontend/packages/superset-ui-core/src/components/{ => SafeMarkdown}/SafeMarkdown.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/AsyncSelect.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/AsyncSelect.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/AsyncSelect.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/Select.stories.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/Select.test.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/Select.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/constants.ts (96%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/Select/index.ts rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/styles.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Select/utils.tsx (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Skeleton/Skeleton.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Skeleton/Skeleton.test.tsx (86%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Skeleton/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Slider/Slider.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Slider/Slider.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Slider/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Space/Space.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Space/Space.test.tsx (91%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Space/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Spin/Spin.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Spin/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Steps/Steps.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Steps/Steps.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Steps/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Switch/Switch.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Switch/Switch.test.tsx (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Switch/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/Table.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/Table.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/TableOverview.stories.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/VirtualTable.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ActionCell/ActionCell.overview.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ActionCell/ActionCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ActionCell/fixtures.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ActionCell/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/BooleanCell/BooleanCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx (75%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/BooleanCell/index.tsx (84%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ButtonCell/ButtonCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/ButtonCell/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NullCell/NullCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx (79%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NullCell/index.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NumericCell/NumericCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/NumericCell/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/TimeCell/TimeCell.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/TimeCell/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/cell-renderers/fixtures.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/index.tsx (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/sorters.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/sorters.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/utils/InteractiveTableUtils.ts (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/utils/utils.test.ts (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Table/utils/utils.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableCollection/TableCollection.test.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableCollection/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableCollection/utils.tsx (76%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableView/TableView.stories.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableView/TableView.test.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableView/TableView.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableView/index.ts (95%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TableView/types.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tabs/Tabs.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tabs/Tabs.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tabs/index.ts (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/Tag/index.tsx rename superset-frontend/{ => packages/superset-ui-core}/src/components/TelemetryPixel/TelemetryPixel.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TelemetryPixel/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/ThemeEditor/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Timer/Timer.stories.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Timer/Timer.test.tsx (91%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Timer/index.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TimezoneSelector/TimezoneSelector.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TimezoneSelector/TimezoneSelector.test.tsx (94%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TimezoneSelector/index.tsx (97%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tooltip/Tooltip.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tooltip/Tooltip.test.tsx (84%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tooltip/index.tsx (90%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tooltip/types.ts (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TooltipParagraph/TooltipParagraph.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TooltipParagraph/TooltipParagraph.test.tsx (92%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TooltipParagraph/index.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tree/Tree.stories.tsx (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tree/Tree.test.tsx (93%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Tree/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TreeSelect/TreeSelect.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TreeSelect/TreeSelect.test.tsx (96%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TreeSelect/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/TruncatedList/index.tsx (98%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Typography/Typography.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Typography/Typography.test.tsx (86%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Typography/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Upload/Upload.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Upload/Upload.test.tsx (87%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/Upload/index.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/WarningIconWithTooltip/WarningIconWithTooltip.stories.tsx (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/components/WarningIconWithTooltip/index.tsx (87%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80135!loading.gif create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80342!loading.gif create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80520!loading.gif create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80903!loading.gif rename superset-frontend/{src/components/Select/index.tsx => packages/superset-ui-core/src/components/assets/images/index.ts} (81%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/images/loading.gif create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/index.ts rename superset-frontend/{src/assets/images => packages/superset-ui-core/src/components/assets/svgs}/chart.svg (100%) rename superset-frontend/{src/assets/images/icons => packages/superset-ui-core/src/components/assets/svgs}/error.svg (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/components/assets/svgs/index.ts rename superset-frontend/{ => packages/superset-ui-core}/src/components/atomic-design.png (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/spec/index.tsx rename superset-frontend/{ => packages/superset-ui-core}/src/utils/dates.test.ts (99%) rename superset-frontend/{ => packages/superset-ui-core}/src/utils/dates.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/utils/rankedSearchCompare.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/utils/rankedSearchCompare.ts (100%) rename superset-frontend/{src => packages/superset-ui-core}/types/ace-builds.d.ts (100%) create mode 100644 superset-frontend/packages/superset-ui-core/types/assets.d.ts create mode 100644 superset-frontend/packages/superset-ui-core/types/brace.d.ts rename superset-frontend/{src => packages/superset-ui-core}/types/react-table-config.d.ts (100%) create mode 100644 superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3-parcoords.d.ts create mode 100644 superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3.d.ts create mode 100644 superset-frontend/src/assets/branding/.!4592!superset-logo-horiz-apache-dark.png create mode 100644 superset-frontend/src/assets/branding/.!4862!superset-logo-horiz-apache-dark.png create mode 100644 superset-frontend/src/assets/branding/.!4993!superset-logo-horiz-apache-dark.png delete mode 100644 superset-frontend/src/components/DropdownContainer/DropdownContainer.test.tsx delete mode 100644 superset-frontend/src/components/InfoTooltip/index.tsx rename superset-frontend/src/components/{InfoTooltip/types.ts => Tag/TagType.ts} (57%) create mode 100644 superset-frontend/tsconfig.base.json diff --git a/.github/workflows/superset-frontend.yml b/.github/workflows/superset-frontend.yml index ac7c01d98e2..3665c6f0591 100644 --- a/.github/workflows/superset-frontend.yml +++ b/.github/workflows/superset-frontend.yml @@ -121,24 +121,6 @@ jobs: files: merged-output/coverage-summary.json slug: apache/superset - core-cover: - needs: frontend-build - if: needs.frontend-build.outputs.should-run == 'true' - runs-on: ubuntu-24.04 - steps: - - name: Download Docker Image Artifact - uses: actions/download-artifact@v4 - with: - name: docker-image - - - name: Load Docker Image - run: docker load < docker-image.tar.gz - - - name: superset-ui/core coverage - run: | - docker run --rm $TAG bash -c \ - "npm run core:cover" - lint-frontend: needs: frontend-build if: needs.frontend-build.outputs.should-run == 'true' diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index d4f4648a35a..59f003c2936 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -52,7 +52,7 @@ const restrictedImportsRules = { message: 'Lodash Memoize is unsafe! Please use memoize-one instead', }, 'no-testing-library-react': { - name: '@testing-library/react', + name: '@superset-ui/core/spec', message: 'Please use spec/helpers/testing-library instead', }, 'no-testing-library-react-dom-utils': { @@ -97,6 +97,15 @@ module.exports = { // resolve modules from `/superset_frontend/node_modules` and `/superset_frontend` moduleDirectory: ['node_modules', '.'], }, + typescript: { + alwaysTryTypes: true, + project: [ + './tsconfig.json', + './packages/superset-ui-core/tsconfig.json', + './packages/superset-ui-chart-controls/', + './plugins/*/tsconfig.json', + ], + }, }, // only allow import from top level of module 'import/core-modules': importCoreModules, @@ -326,7 +335,9 @@ module.exports = { rules: { 'import/no-extraneous-dependencies': [ 'error', - { devDependencies: true }, + { + devDependencies: true, + }, ], 'no-only-tests/no-only-tests': 'error', 'max-classes-per-file': 0, diff --git a/superset-frontend/jest.config.js b/superset-frontend/jest.config.js index 6c9dd85cd51..517c91767fd 100644 --- a/superset-frontend/jest.config.js +++ b/superset-frontend/jest.config.js @@ -28,7 +28,9 @@ module.exports = { '^src/(.*)$': '/src/$1', '^spec/(.*)$': '/spec/$1', // mapping plugins of superset-ui to source code - '@superset-ui/(.*)$': '/node_modules/@superset-ui/$1/src', + '^@superset-ui/([^/]+)/(.*)$': + '/node_modules/@superset-ui/$1/src/$2', + '^@superset-ui/([^/]+)$': '/node_modules/@superset-ui/$1/src', }, testEnvironment: 'jsdom', modulePathIgnorePatterns: ['/packages/generator-superset'], diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 5ebf2e1f37a..3ff13ccdb79 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -14,7 +14,6 @@ "src/setup/*" ], "dependencies": { - "@ant-design/icons": "^5.2.6", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.3.0", @@ -54,20 +53,16 @@ "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.5.1", "abortcontroller-polyfill": "^1.7.8", - "ace-builds": "^1.41.0", "ag-grid-community": "33.1.1", "ag-grid-react": "33.1.1", "antd": "^5.24.6", - "brace": "^0.11.1", "chrono-node": "^2.7.8", "classnames": "^2.2.5", - "core-js": "^3.38.1", "d3-color": "^3.1.0", "d3-scale": "^2.1.2", "dayjs": "^1.11.13", "dom-to-image-more": "^3.2.0", "dom-to-pdf": "^0.3.2", - "dompurify": "^3.2.4", "echarts": "^5.6.0", "emotion-rgba": "0.0.12", "eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings", @@ -106,18 +101,15 @@ "rc-trigger": "^5.3.4", "re-resizable": "^6.10.1", "react": "^17.0.2", - "react-ace": "^10.1.0", "react-checkbox-tree": "^1.8.0", "react-color": "^2.13.8", "react-diff-viewer-continued": "^3.4.0", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", "react-dom": "^17.0.2", - "react-draggable": "^4.4.6", "react-google-recaptcha": "^3.1.0", "react-hot-loader": "^4.13.1", "react-intersection-observer": "^9.16.0", - "react-js-cron": "^2.1.2", "react-json-tree": "^0.17.0", "react-lines-ellipsis": "^0.15.4", "react-loadable": "^5.5.0", @@ -131,14 +123,12 @@ "react-syntax-highlighter": "^15.4.5", "react-table": "^7.8.0", "react-transition-group": "^4.4.5", - "react-ultimate-pagination": "^1.3.2", "react-virtualized-auto-sizer": "^1.0.25", "react-window": "^1.8.10", "redux": "^4.2.1", "redux-localstorage": "^0.4.1", "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", - "regenerator-runtime": "^0.14.1", "rimraf": "^6.0.1", "rison": "^0.1.1", "scroll-into-view-if-needed": "^3.1.0", @@ -197,7 +187,6 @@ "@types/enzyme": "^3.10.18", "@types/fetch-mock": "^7.3.2", "@types/jest": "^29.5.14", - "@types/jquery": "^3.5.8", "@types/js-levenshtein": "^1.1.3", "@types/json-bigint": "^1.0.4", "@types/math-expression-evaluator": "^1.3.3", @@ -212,7 +201,6 @@ "@types/react-resizable": "^3.0.8", "@types/react-router-dom": "^5.3.3", "@types/react-syntax-highlighter": "^15.5.13", - "@types/react-table": "^7.7.20", "@types/react-transition-group": "^4.4.12", "@types/react-ultimate-pagination": "^1.2.4", "@types/react-virtualized-auto-sizer": "^1.0.4", @@ -245,6 +233,7 @@ "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^7.2.0", + "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-cypress": "^3.6.0", "eslint-plugin-file-progress": "^1.5.0", @@ -307,6 +296,12 @@ "engines": { "node": "^20.16.0", "npm": "^10.8.1" + }, + "peerDependencies": { + "ace-builds": "^1.41.0", + "core-js": "^3.38.1", + "react-ace": "^10.1.0", + "regenerator-runtime": "^0.14.1" } }, "eslint-rules/eslint-i18n-strings": { @@ -12696,7 +12691,6 @@ "version": "1.8.8", "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/react": "*" @@ -19562,6 +19556,13 @@ "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", "license": "BSD-3-Clause" }, + "node_modules/d3v3": { + "name": "d3", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", + "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==", + "license": "BSD-3-Clause" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -22078,6 +22079,19 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-import-resolver-alias": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", + "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + }, + "peerDependencies": { + "eslint-plugin-import": ">=1.4.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -52292,7 +52306,6 @@ "@testing-library/react-hooks": "*", "@testing-library/user-event": "*", "ace-builds": "^1.4.14", - "antd": "^5.24.6", "brace": "^0.11.1", "memoize-one": "^5.1.1", "react": "^17.0.2", @@ -52305,24 +52318,38 @@ "version": "0.20.4", "license": "Apache-2.0", "dependencies": { + "@ant-design/icons": "^5.2.6", "@babel/runtime": "^7.25.6", "@fontsource/fira-code": "^5.0.18", "@fontsource/inter": "^5.0.20", "@types/json-bigint": "^1.0.4", "@visx/responsive": "^3.12.0", + "ace-builds": "^1.41.0", + "brace": "^0.11.1", + "classnames": "^2.2.5", + "core-js": "^3.38.1", "csstype": "^3.1.3", "d3-format": "^1.3.2", "d3-interpolate": "^3.0.1", "d3-scale": "^3.0.0", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", + "dayjs": "^1.11.13", + "dompurify": "^3.2.4", "fetch-retry": "^6.0.0", "jed": "^1.1.1", "lodash": "^4.17.21", "math-expression-evaluator": "^2.0.6", "pretty-ms": "^9.2.0", + "re-resizable": "^6.10.1", + "react-ace": "^10.1.0", + "react-draggable": "^4.4.6", "react-error-boundary": "^5.0.0", + "react-js-cron": "^2.1.2", "react-markdown": "^8.0.7", + "react-resize-detector": "^7.1.2", + "react-ultimate-pagination": "^1.3.2", + "regenerator-runtime": "^0.14.1", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^3.0.1", @@ -52341,10 +52368,12 @@ "@types/d3-time-format": "^4.0.3", "@types/enzyme": "^3.10.18", "@types/fetch-mock": "^7.3.8", + "@types/jquery": "^3.5.8", "@types/lodash": "^4.17.16", "@types/math-expression-evaluator": "^1.3.3", "@types/node": "^22.10.3", "@types/prop-types": "^15.7.2", + "@types/react-table": "^7.7.20", "@types/rison": "0.1.0", "@types/seedrandom": "^3.0.8", "fetch-mock": "^11.1.4", @@ -52363,6 +52392,7 @@ "@testing-library/user-event": "*", "@types/react": "*", "@types/react-loadable": "*", + "@types/react-window": "^1.8.8", "@types/tinycolor2": "*", "antd": "^5.24.6", "nanoid": "^5.0.9", @@ -53319,8 +53349,7 @@ "@superset-ui/legacy-preset-chart-nvd3": "*", "@superset-ui/plugin-chart-echarts": "*", "@superset-ui/plugin-chart-table": "*", - "@superset-ui/plugin-chart-word-cloud": "*", - "antd": "^5.24.6" + "@superset-ui/plugin-chart-word-cloud": "*" } }, "packages/superset-ui-demo/node_modules/@storybook/builder-webpack5": { @@ -54020,7 +54049,7 @@ "version": "0.20.3", "license": "Apache-2.0", "dependencies": { - "d3": "^3.5.17", + "d3v3": "npm:d3@3.5.17", "prop-types": "^15.8.1" }, "peerDependencies": { @@ -54362,7 +54391,6 @@ "@testing-library/user-event": "*", "@types/classnames": "*", "@types/react": "*", - "antd": "^5.24.6", "match-sorter": "^6.3.3", "react": "^17.0.2", "react-dom": "^17.0.2" diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 85758ea2358..75b4add8452 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -70,6 +70,7 @@ "storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006", "tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --watch", "test": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80% --silent", + "test-loud": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80%", "type": "tsc --noEmit", "update-maps": "jupyter nbconvert --to notebook --execute --inplace 'plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb' -Xfrozen_modules=off", "validate-release": "../RELEASING/validate_this_release.sh" @@ -81,7 +82,6 @@ "last 3 edge versions" ], "dependencies": { - "@ant-design/icons": "^5.2.6", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.3.0", @@ -121,20 +121,16 @@ "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.5.1", "abortcontroller-polyfill": "^1.7.8", - "ace-builds": "^1.41.0", "ag-grid-community": "33.1.1", "ag-grid-react": "33.1.1", "antd": "^5.24.6", - "brace": "^0.11.1", "chrono-node": "^2.7.8", "classnames": "^2.2.5", - "core-js": "^3.38.1", "d3-color": "^3.1.0", "d3-scale": "^2.1.2", "dayjs": "^1.11.13", "dom-to-image-more": "^3.2.0", "dom-to-pdf": "^0.3.2", - "dompurify": "^3.2.4", "echarts": "^5.6.0", "emotion-rgba": "0.0.12", "eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings", @@ -173,18 +169,15 @@ "rc-trigger": "^5.3.4", "re-resizable": "^6.10.1", "react": "^17.0.2", - "react-ace": "^10.1.0", "react-checkbox-tree": "^1.8.0", "react-color": "^2.13.8", "react-diff-viewer-continued": "^3.4.0", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", "react-dom": "^17.0.2", - "react-draggable": "^4.4.6", "react-google-recaptcha": "^3.1.0", "react-hot-loader": "^4.13.1", "react-intersection-observer": "^9.16.0", - "react-js-cron": "^2.1.2", "react-json-tree": "^0.17.0", "react-lines-ellipsis": "^0.15.4", "react-loadable": "^5.5.0", @@ -198,14 +191,12 @@ "react-syntax-highlighter": "^15.4.5", "react-table": "^7.8.0", "react-transition-group": "^4.4.5", - "react-ultimate-pagination": "^1.3.2", "react-virtualized-auto-sizer": "^1.0.25", "react-window": "^1.8.10", "redux": "^4.2.1", "redux-localstorage": "^0.4.1", "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", - "regenerator-runtime": "^0.14.1", "rimraf": "^6.0.1", "rison": "^0.1.1", "scroll-into-view-if-needed": "^3.1.0", @@ -264,7 +255,6 @@ "@types/enzyme": "^3.10.18", "@types/fetch-mock": "^7.3.2", "@types/jest": "^29.5.14", - "@types/jquery": "^3.5.8", "@types/js-levenshtein": "^1.1.3", "@types/json-bigint": "^1.0.4", "@types/math-expression-evaluator": "^1.3.3", @@ -279,7 +269,6 @@ "@types/react-resizable": "^3.0.8", "@types/react-router-dom": "^5.3.3", "@types/react-syntax-highlighter": "^15.5.13", - "@types/react-table": "^7.7.20", "@types/react-transition-group": "^4.4.12", "@types/react-ultimate-pagination": "^1.2.4", "@types/react-virtualized-auto-sizer": "^1.0.4", @@ -312,6 +301,7 @@ "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^7.2.0", + "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-cypress": "^3.6.0", "eslint-plugin-file-progress": "^1.5.0", @@ -371,6 +361,12 @@ "webpack-sources": "^3.2.3", "webpack-visualizer-plugin2": "^1.1.0" }, + "peerDependencies": { + "ace-builds": "^1.41.0", + "core-js": "^3.38.1", + "react-ace": "^10.1.0", + "regenerator-runtime": "^0.14.1" + }, "engines": { "node": "^20.16.0", "npm": "^10.8.1" diff --git a/superset-frontend/packages/superset-ui-chart-controls/package.json b/superset-frontend/packages/superset-ui-chart-controls/package.json index ea9353f7e33..060ba39b5d0 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/package.json +++ b/superset-frontend/packages/superset-ui-chart-controls/package.json @@ -40,7 +40,6 @@ "@testing-library/react-hooks": "*", "@testing-library/user-event": "*", "ace-builds": "^1.4.14", - "antd": "^5.24.6", "brace": "^0.11.1", "memoize-one": "^5.1.1", "react": "^17.0.2", diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx index 6124834c573..18cedfbca9a 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx @@ -18,7 +18,7 @@ */ import { kebabCase } from 'lodash'; import { t, useTheme, styled } from '@superset-ui/core'; -import Tooltip from './Tooltip'; +import { Tooltip } from '@superset-ui/core/components'; interface CertifiedIconWithTooltipProps { certifiedBy?: string | null; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx index 801363e51c7..763bf0a7d11 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx @@ -17,8 +17,12 @@ * under the License. */ import { useState, ReactNode, useLayoutEffect, RefObject } from 'react'; -import { css, SafeMarkdown, styled, SupersetTheme } from '@superset-ui/core'; -import { Tooltip } from './Tooltip'; +import { css, styled, SupersetTheme } from '@superset-ui/core'; +import { + SafeMarkdown, + Tooltip, + InfoTooltip, +} from '@superset-ui/core/components'; import { ColumnTypeLabel } from './ColumnTypeLabel/ColumnTypeLabel'; import CertifiedIconWithTooltip from './CertifiedIconWithTooltip'; import { ColumnMeta } from '../types'; @@ -28,7 +32,6 @@ import { getColumnTypeTooltipNode, } from './labelUtils'; import { SQLPopover } from './SQLPopover'; -import { InfoTooltipWithTrigger } from './InfoTooltipWithTrigger'; export type ColumnOptionProps = { column: ColumnMeta; @@ -98,7 +101,7 @@ export function ColumnOption({ /> )} {warningMarkdown && ( - } label={`warn-${column.column_name}`} diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ControlHeader.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/ControlHeader.tsx index 944591bb111..472c83b156f 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/ControlHeader.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ControlHeader.tsx @@ -19,8 +19,7 @@ import { ReactNode } from 'react'; import { t, css } from '@superset-ui/core'; import { InfoCircleOutlined } from '@ant-design/icons'; -import { InfoTooltipWithTrigger } from './InfoTooltipWithTrigger'; -import { Tooltip } from './Tooltip'; +import { InfoTooltip, Tooltip } from '@superset-ui/core/components'; type ValidationError = string; @@ -61,7 +60,7 @@ export function ControlHeader({ {description && ( - - )} {warningMarkdown && ( - } label={`warn-${metric.metric_name}`} diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/SQLPopover.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/SQLPopover.tsx index 89b9626e75e..af0ff77db9e 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/SQLPopover.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/SQLPopover.tsx @@ -17,9 +17,8 @@ * under the License. */ import { useEffect, useState } from 'react'; -import { Popover } from 'antd'; +import { Popover, type PopoverProps } from '@superset-ui/core/components'; import type ReactAce from 'react-ace'; -import type { PopoverProps } from 'antd/es/popover'; import { CalculatorOutlined } from '@ant-design/icons'; import { css, styled, useTheme, t } from '@superset-ui/core'; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/Select.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/Select.tsx index 421f97887c4..4831dcba107 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/Select.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/Select.tsx @@ -18,9 +18,9 @@ */ import { useState, ReactNode } from 'react'; import { - Select as AntdSelect, - type SelectProps as AntdSelectProps, -} from 'antd'; + RawAntdSelect as AntdSelect, + type RawAntdSelectProps as AntdSelectProps, +} from '@superset-ui/core/components'; export const { Option }: any = AntdSelect; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/Tooltip.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/Tooltip.tsx deleted file mode 100644 index 52865a5e407..00000000000 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/Tooltip.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { useTheme } from '@superset-ui/core'; -import { Tooltip as BaseTooltip } from 'antd'; -import { - TooltipProps as BaseTooltipProps, - TooltipPlacement as BaseTooltipPlacement, -} from 'antd/es/tooltip'; - -export type TooltipProps = BaseTooltipProps; -export type TooltipPlacement = BaseTooltipPlacement; - -export const Tooltip = ({ - overlayStyle = {}, - color, - ...props -}: BaseTooltipProps) => { - const theme = useTheme(); - const defaultColor = `${theme.colors.grayscale.dark2}e6`; - return ( - - ); -}; - -export default Tooltip; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts index e58bc940385..dc1d89e476c 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts @@ -18,6 +18,11 @@ */ import * as sectionsModule from './sections'; +export { + Tooltip, + TooltipPlacement, + TooltipProps, +} from '@superset-ui/core/components'; export * from './utils'; export * from './constants'; export * from './operators'; @@ -25,14 +30,12 @@ export * from './operators'; // can't do `export * as sections from './sections'`, babel-transformer will fail export const sections = sectionsModule; -export * from './components/InfoTooltipWithTrigger'; export * from './components/ColumnOption'; export * from './components/ColumnTypeLabel/ColumnTypeLabel'; export * from './components/ControlSubSectionHeader'; export * from './components/Dropdown'; export * from './components/Menu'; export * from './components/MetricOption'; -export * from './components/Tooltip'; export * from './components/ControlHeader'; export * from './shared-controls'; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/RadioButtonControl.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/RadioButtonControl.tsx index c3dbda75c7a..edf67179655 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/RadioButtonControl.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/RadioButtonControl.tsx @@ -18,7 +18,7 @@ */ import { ReactNode } from 'react'; import { JsonValue } from '@superset-ui/core'; -import { Radio } from 'antd'; +import { Radio } from '@superset-ui/core/components'; import { ControlHeader } from '../../components/ControlHeader'; // [value, label] diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts index 71517884daa..3fbd234c1d4 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts @@ -300,7 +300,7 @@ export interface FilterOption { data: T; } -// Ref: superset-frontend/src/components/Select/SupersetStyledSelect.tsx +// Ref: superset-frontend/@superset-ui/core/components/Select/SupersetStyledSelect.tsx export interface SelectControlConfig< O extends SelectOption = SelectOption, T extends SelectControlType = SelectControlType, diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnOption.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnOption.test.tsx index 68c6f626330..e0b3f8f30dd 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnOption.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnOption.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import '@testing-library/jest-dom'; -import { render } from '@testing-library/react'; +import { render } from '@superset-ui/core/spec'; import { ThemeProvider, supersetTheme, @@ -26,19 +26,20 @@ import { import { ColumnOption, ColumnOptionProps } from '../../src'; -jest.mock('../../src/components/SQLPopover', () => ({ +jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({ SQLPopover: () =>
, })); -jest.mock('../../src/components/ColumnTypeLabel/ColumnTypeLabel', () => ({ - ColumnTypeLabel: ({ type }: { type: string }) => ( -
{type}
- ), -})); +jest.mock( + '@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel', + () => ({ + ColumnTypeLabel: ({ type }: { type: string }) => ( +
{type}
+ ), + }), +); -jest.mock('../../src/components/InfoTooltipWithTrigger', () => ({ - InfoTooltipWithTrigger: () => ( -
- ), +jest.mock('@superset-ui/core/components/InfoTooltip', () => ({ + InfoTooltip: () =>
, })); const defaultProps: ColumnOptionProps = { @@ -117,11 +118,11 @@ test('dttm column has correct column label if showType is true', () => { String(GenericDataType.Temporal), ); }); -test('doesnt show InfoTooltipWithTrigger when no warning', () => { +test('doesnt show InfoTooltip when no warning', () => { const { queryByText } = setup(); - expect(queryByText('mock-info-tooltip-with-trigger')).not.toBeInTheDocument(); + expect(queryByText('mock-tooltip')).not.toBeInTheDocument(); }); -test('shows a warning with InfoTooltipWithTrigger when it contains warning', () => { +test('shows a warning with InfoTooltip when it contains warning', () => { const { getByTestId } = setup({ ...defaultProps, column: { @@ -129,5 +130,5 @@ test('shows a warning with InfoTooltipWithTrigger when it contains warning', () warning_text: 'This is a warning', }, }); - expect(getByTestId('mock-info-tooltip-with-trigger')).toBeInTheDocument(); + expect(getByTestId('mock-tooltip')).toBeInTheDocument(); }); diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx index 603ac9172eb..350820207eb 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { isValidElement } from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { GenericDataType } from '@superset-ui/core'; diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/InfoTooltipWithTrigger.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/InfoTooltipWithTrigger.test.tsx index d243b1fd9f8..f195813861a 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/InfoTooltipWithTrigger.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/InfoTooltipWithTrigger.test.tsx @@ -17,11 +17,11 @@ * under the License. */ import '@testing-library/jest-dom'; -import { fireEvent, render } from '@testing-library/react'; +import { fireEvent, render } from '@superset-ui/core/spec'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; -import { InfoTooltipWithTrigger, InfoTooltipWithTriggerProps } from '../../src'; +import { InfoTooltip, InfoTooltipProps } from '@superset-ui/core/components'; -jest.mock('../../src/components/Tooltip', () => ({ +jest.mock('@superset-ui/core/components/Tooltip', () => ({ Tooltip: ({ children }: { children: React.ReactNode }) => (
{children}
), @@ -29,10 +29,10 @@ jest.mock('../../src/components/Tooltip', () => ({ const defaultProps = {}; -const setup = (props: Partial = {}) => +const setup = (props: Partial = {}) => render( - + , ); diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/MetricOption.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/MetricOption.test.tsx index 03da5df2ffc..8782de01a4a 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/MetricOption.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/MetricOption.test.tsx @@ -17,27 +17,31 @@ * under the License. */ import '@testing-library/jest-dom'; -import { render } from '@testing-library/react'; +import { render } from '@superset-ui/core/spec'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; -import { MetricOption, MetricOptionProps } from '../../src'; +import { + MetricOption, + MetricOptionProps, +} from '../../src/components/MetricOption'; -jest.mock('../../src/components/InfoTooltipWithTrigger', () => ({ - InfoTooltipWithTrigger: () => ( -
- ), +jest.mock('@superset-ui/core/components/InfoTooltip', () => ({ + InfoTooltip: () =>
, })); -jest.mock('../../src/components/ColumnTypeLabel/ColumnTypeLabel', () => ({ - ColumnTypeLabel: () =>
, -})); jest.mock( - '../../src/components/Tooltip', + '@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel', + () => ({ + ColumnTypeLabel: () =>
, + }), +); +jest.mock( + '@superset-ui/core/components/Tooltip', () => ({ children }: { children: React.ReactNode }) => (
{children}
), ); -jest.mock('../../src/components/SQLPopover', () => ({ +jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({ SQLPopover: () =>
, })); @@ -68,9 +72,9 @@ test('shows a label with verbose_name', () => { expect(lbl).toHaveLength(1); expect(`${lbl[0].textContent}`).toEqual(defaultProps.metric.verbose_name); }); -test('shows a InfoTooltipWithTrigger', () => { +test('shows a InfoTooltip', () => { const { getByTestId } = setup(); - expect(getByTestId('mock-info-tooltip-with-trigger')).toBeInTheDocument(); + expect(getByTestId('mock-tooltip')).toBeInTheDocument(); }); test('shows SQL Popover trigger', () => { const { getByTestId } = setup(); @@ -85,14 +89,14 @@ test('shows a label with metric_name when no verbose_name', () => { }); expect(getByText(defaultProps.metric.metric_name)).toBeInTheDocument(); }); -test('doesnt show InfoTooltipWithTrigger when no warning', () => { +test('doesnt show InfoTooltip when no warning', () => { const { queryByText } = setup({ metric: { ...defaultProps.metric, warning_text: '', }, }); - expect(queryByText('mock-info-tooltip-with-trigger')).not.toBeInTheDocument(); + expect(queryByText('mock-tooltip')).not.toBeInTheDocument(); }); test('sets target="_blank" when openInNewWindow is true', () => { const { getByRole } = setup({ diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx index 9b5b760f791..c90b65fb674 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { ReactElement } from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; import { diff --git a/superset-frontend/packages/superset-ui-core/.eslintrc b/superset-frontend/packages/superset-ui-core/.eslintrc new file mode 100644 index 00000000000..e0ff7c67bb8 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/.eslintrc @@ -0,0 +1,68 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +{ + "plugins": ["jest", "jest-dom", "no-only-tests", "testing-library"], + "env": { + "jest/globals": true + }, + "settings": { + "jest": { + "version": "detect" + } + }, + "extends": [ + "plugin:jest/recommended", + "plugin:jest-dom/recommended", + "plugin:testing-library/react" + ], + "overrides": [ + { + "files": [ + "**/*.stories.*", + "**/*.overview.*", + "**/fixtures.*" + ], + "rules": { + "import/no-extraneous-dependencies": "off" + } + } + ], + "rules": { + "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], + "jest/consistent-test-it": "error", + "no-only-tests/no-only-tests": "error", + "prefer-promise-reject-errors": 0, + + "testing-library/no-node-access": "off", + "testing-library/prefer-screen-queries": "off", + "testing-library/no-container": "off", + "testing-library/await-async-queries": "off", + "testing-library/await-async-utils": "off", + "testing-library/no-await-sync-events": "off", + "testing-library/no-render-in-lifecycle": "off", + "testing-library/no-unnecessary-act": "off", + "testing-library/no-wait-for-multiple-assertions": "off", + "testing-library/await-async-events": "off", + "testing-library/no-wait-for-side-effects": "off", + "testing-library/prefer-presence-queries": "off", + "testing-library/render-result-naming-convention": "off", + "testing-library/prefer-find-by": "off", + "testing-library/no-manual-cleanup": "off" + } +} diff --git a/superset-frontend/packages/superset-ui-core/__mocks__/mockExportObject.js b/superset-frontend/packages/superset-ui-core/__mocks__/mockExportObject.js new file mode 100644 index 00000000000..ab22d88b5b2 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/__mocks__/mockExportObject.js @@ -0,0 +1,19 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +module.exports = {}; diff --git a/superset-frontend/packages/superset-ui-core/__mocks__/mockExportString.js b/superset-frontend/packages/superset-ui-core/__mocks__/mockExportString.js new file mode 100644 index 00000000000..5b7f1d6da96 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/__mocks__/mockExportString.js @@ -0,0 +1,19 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +module.exports = 'test-file-stub'; diff --git a/superset-frontend/packages/superset-ui-core/__mocks__/svgrMock.tsx b/superset-frontend/packages/superset-ui-core/__mocks__/svgrMock.tsx new file mode 100644 index 00000000000..4f1178bee8d --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/__mocks__/svgrMock.tsx @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SVGProps, forwardRef } from 'react'; + +const SvgrMock = forwardRef>( + (props, ref) => , +); + +SvgrMock.displayName = 'SvgrMock'; + +export const ReactComponent = SvgrMock; +export default SvgrMock; diff --git a/superset-frontend/packages/superset-ui-core/package.json b/superset-frontend/packages/superset-ui-core/package.json index 26bd3494599..2b760997b56 100644 --- a/superset-frontend/packages/superset-ui-core/package.json +++ b/superset-frontend/packages/superset-ui-core/package.json @@ -24,23 +24,37 @@ "lib" ], "dependencies": { + "@ant-design/icons": "^5.2.6", "@babel/runtime": "^7.25.6", "@fontsource/fira-code": "^5.0.18", "@fontsource/inter": "^5.0.20", "@types/json-bigint": "^1.0.4", + "ace-builds": "^1.41.0", + "brace": "^0.11.1", + "classnames": "^2.2.5", "csstype": "^3.1.3", + "core-js": "^3.38.1", "d3-format": "^1.3.2", + "dayjs": "^1.11.13", "d3-interpolate": "^3.0.1", "d3-scale": "^3.0.0", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", + "dompurify": "^3.2.4", "fetch-retry": "^6.0.0", "jed": "^1.1.1", "lodash": "^4.17.21", "math-expression-evaluator": "^2.0.6", "pretty-ms": "^9.2.0", + "re-resizable": "^6.10.1", + "react-ace": "^10.1.0", + "react-js-cron": "^2.1.2", + "react-draggable": "^4.4.6", + "react-resize-detector": "^7.1.2", + "react-ultimate-pagination": "^1.3.2", "react-error-boundary": "^5.0.0", "react-markdown": "^8.0.7", + "regenerator-runtime": "^0.14.1", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^3.0.1", @@ -58,8 +72,10 @@ "@types/d3-scale": "^2.1.1", "@types/d3-time": "^3.0.4", "@types/d3-time-format": "^4.0.3", + "@types/react-table": "^7.7.20", "@types/enzyme": "^3.10.18", "@types/fetch-mock": "^7.3.8", + "@types/jquery": "^3.5.8", "@types/lodash": "^4.17.16", "@types/math-expression-evaluator": "^1.3.3", "@types/node": "^22.10.3", @@ -83,6 +99,7 @@ "@testing-library/user-event": "*", "@types/react": "*", "@types/react-loadable": "*", + "@types/react-window": "^1.8.8", "@types/tinycolor2": "*", "nanoid": "^5.0.9", "react": "^17.0.2", @@ -91,5 +108,27 @@ }, "publishConfig": { "access": "public" + }, + "exports": { + ".": { + "import": "./esm/index.js", + "require": "./lib/index.js", + "types": "./lib/index.d.ts" + }, + "./components/*": { + "import": "./esm/components/*/index.js", + "require": "./lib/components/*/index.js", + "types": "./lib/components/*/index.d.ts" + }, + "./components": { + "import": "./esm/components/index.js", + "require": "./lib/components/index.js", + "types": "./lib/components/index.d.ts" + }, + "./utils/*": { + "import": "./esm/utils/*.js", + "require": "./lib/utils/*.js", + "types": "./lib/utils/*.d.ts" + } } } diff --git a/superset-frontend/src/components/Alert/Alert.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Alert/Alert.stories.tsx similarity index 100% rename from superset-frontend/src/components/Alert/Alert.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Alert/Alert.stories.tsx diff --git a/superset-frontend/src/components/Alert/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Alert/index.tsx similarity index 100% rename from superset-frontend/src/components/Alert/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Alert/index.tsx diff --git a/superset-frontend/src/components/Alert/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Alert/types.ts similarity index 100% rename from superset-frontend/src/components/Alert/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Alert/types.ts diff --git a/superset-frontend/src/components/AntdThemeProvider/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/AntdThemeProvider/index.tsx similarity index 100% rename from superset-frontend/src/components/AntdThemeProvider/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AntdThemeProvider/index.tsx diff --git a/superset-frontend/src/components/AsyncAceEditor/AsyncAceEditor.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.stories.tsx similarity index 100% rename from superset-frontend/src/components/AsyncAceEditor/AsyncAceEditor.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.stories.tsx diff --git a/superset-frontend/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx similarity index 97% rename from superset-frontend/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx index b0170a36e7c..151b1db1a93 100644 --- a/superset-frontend/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, waitFor } from 'spec/helpers/testing-library'; +import { render, screen, waitFor } from '@superset-ui/core/spec'; import { AsyncAceEditor, SQLEditor, diff --git a/superset-frontend/src/components/AsyncAceEditor/Tooltip.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/Tooltip.test.tsx similarity index 100% rename from superset-frontend/src/components/AsyncAceEditor/Tooltip.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/Tooltip.test.tsx diff --git a/superset-frontend/src/components/AsyncAceEditor/Tooltip.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/Tooltip.tsx similarity index 100% rename from superset-frontend/src/components/AsyncAceEditor/Tooltip.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/Tooltip.tsx diff --git a/superset-frontend/src/components/AsyncAceEditor/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/index.tsx similarity index 59% rename from superset-frontend/src/components/AsyncAceEditor/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/index.tsx index cb75630a067..e4292b25b5b 100644 --- a/superset-frontend/src/components/AsyncAceEditor/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/index.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { forwardRef, useEffect, ComponentType } from 'react'; +import { forwardRef, useEffect, useCallback, ComponentType } from 'react'; import type { Editor as OrigEditor, @@ -30,8 +30,7 @@ import type { IAceEditorProps } from 'react-ace'; import { AsyncEsmComponent, PlaceholderProps, -} from 'src/components/AsyncEsmComponent'; -import useEffectEvent from 'src/hooks/useEffectEvent'; +} from '@superset-ui/core/components/AsyncEsmComponent'; import { useTheme, css } from '@superset-ui/core'; import { Global } from '@emotion/react'; @@ -156,9 +155,10 @@ export function AsyncAceEditor( }, ref, ) { - const supersetTheme = useTheme(); + const token = useTheme(); const langTools = acequire('ace/ext/language_tools'); - const setCompleters = useEffectEvent( + + const setCompleters = useCallback( (keywords: AceCompleterKeyword[]) => { const completer = { getCompletions: ( @@ -181,7 +181,9 @@ export function AsyncAceEditor( }; langTools.setCompleters([completer]); }, + [langTools, mode], ); + useEffect(() => { if (keywords) { setCompleters(keywords); @@ -193,36 +195,148 @@ export function AsyncAceEditor( .ant-tag { + margin-right: 0px; + } + } + } + + /* Adjust the searchbox to match theme */ + .ace_search { + background-color: ${token.colorBgContainer} !important; + color: ${token.colorText} !important; + border: 1px solid ${token.colorBorder} !important; + } + + .ace_search_field { + background-color: ${token.colorBgContainer} !important; + color: ${token.colorText} !important; + border: 1px solid ${token.colorBorder} !important; + } + + .ace_button { + background-color: ${token.colorBgElevated} !important; + color: ${token.colorText} !important; + border: 1px solid ${token.colorBorder} !important; + } + + .ace_button:hover { + background-color: ${token.colorPrimaryBg} !important; } `} /> diff --git a/superset-frontend/src/components/AsyncAceEditor/types.ts b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/types.ts similarity index 100% rename from superset-frontend/src/components/AsyncAceEditor/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/types.ts diff --git a/superset-frontend/src/components/AsyncEsmComponent/AsyncEsmComponent.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/AsyncEsmComponent.stories.tsx similarity index 100% rename from superset-frontend/src/components/AsyncEsmComponent/AsyncEsmComponent.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/AsyncEsmComponent.stories.tsx diff --git a/superset-frontend/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx similarity index 97% rename from superset-frontend/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx index 8c16c800ecc..82a88a322f9 100644 --- a/superset-frontend/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/AsyncEsmComponent.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { AsyncEsmComponent } from '.'; const Placeholder = () => Loading...; diff --git a/superset-frontend/src/components/AsyncEsmComponent/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/index.tsx similarity index 100% rename from superset-frontend/src/components/AsyncEsmComponent/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/index.tsx diff --git a/superset-frontend/src/components/AsyncEsmComponent/types.ts b/superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/types.ts similarity index 100% rename from superset-frontend/src/components/AsyncEsmComponent/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/AsyncEsmComponent/types.ts diff --git a/superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/AutoComplete/AutoComplete.stories.tsx similarity index 100% rename from superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AutoComplete/AutoComplete.stories.tsx diff --git a/superset-frontend/src/components/AutoComplete/AutoComplete.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/AutoComplete/AutoComplete.test.tsx similarity index 85% rename from superset-frontend/src/components/AutoComplete/AutoComplete.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AutoComplete/AutoComplete.test.tsx index 93bdb3c6285..a69e2924cf2 100644 --- a/superset-frontend/src/components/AutoComplete/AutoComplete.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/AutoComplete/AutoComplete.test.tsx @@ -17,12 +17,7 @@ * under the License. */ import { useState } from 'react'; -import { - render, - screen, - userEvent, - waitFor, -} from 'spec/helpers/testing-library'; +import { render, screen, userEvent, waitFor } from '@superset-ui/core/spec'; import { Input } from '../Input'; import { AutoComplete } from '.'; @@ -49,17 +44,17 @@ const AutoCompleteTest = () => { }; describe('AutoComplete Component', () => { - test('renders input field', () => { + it('renders input field', () => { render(); expect( screen.getByPlaceholderText('Type to search...'), ).toBeInTheDocument(); }); - test('shows options when user types', async () => { + it('shows options when user types', async () => { render(); const input = screen.getByPlaceholderText('Type to search...'); - userEvent.type(input, 'test'); + await userEvent.type(input, 'test'); await waitFor(() => { expect(screen.getByText('test result 0')).toBeInTheDocument(); @@ -68,16 +63,16 @@ describe('AutoComplete Component', () => { }); }); - test('selecting an option updates input value', async () => { + it('selecting an option updates input value', async () => { render(); const input = screen.getByPlaceholderText('Type to search...'); - userEvent.type(input, 'test'); + await userEvent.type(input, 'test'); await waitFor(() => { expect(screen.getByText('test result 0')).toBeInTheDocument(); }); - userEvent.click(screen.getByText('test result 0')); + await userEvent.click(screen.getByText('test result 0')); expect(input).toHaveValue('test0'); }); }); diff --git a/superset-frontend/src/components/AutoComplete/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/AutoComplete/index.tsx similarity index 100% rename from superset-frontend/src/components/AutoComplete/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/AutoComplete/index.tsx diff --git a/superset-frontend/src/components/AutoComplete/types.ts b/superset-frontend/packages/superset-ui-core/src/components/AutoComplete/types.ts similarity index 100% rename from superset-frontend/src/components/AutoComplete/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/AutoComplete/types.ts diff --git a/superset-frontend/src/components/Avatar/Avatar.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Avatar/Avatar.stories.tsx similarity index 100% rename from superset-frontend/src/components/Avatar/Avatar.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Avatar/Avatar.stories.tsx diff --git a/superset-frontend/src/components/Avatar/Avatar.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Avatar/Avatar.test.tsx similarity index 94% rename from superset-frontend/src/components/Avatar/Avatar.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Avatar/Avatar.test.tsx index 91fbe60d947..41b3d494925 100644 --- a/superset-frontend/src/components/Avatar/Avatar.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Avatar/Avatar.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Avatar } from '.'; test('renders with default props', async () => { diff --git a/superset-frontend/src/components/Avatar/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Avatar/index.tsx similarity index 100% rename from superset-frontend/src/components/Avatar/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Avatar/index.tsx diff --git a/superset-frontend/src/components/Avatar/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Avatar/types.ts similarity index 100% rename from superset-frontend/src/components/Avatar/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Avatar/types.ts diff --git a/superset-frontend/src/components/Badge/Badge.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Badge/Badge.stories.tsx similarity index 100% rename from superset-frontend/src/components/Badge/Badge.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Badge/Badge.stories.tsx diff --git a/superset-frontend/src/components/Badge/Badge.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Badge/Badge.test.tsx similarity index 95% rename from superset-frontend/src/components/Badge/Badge.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Badge/Badge.test.tsx index 8f666349c7c..98fa396bfb6 100644 --- a/superset-frontend/src/components/Badge/Badge.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Badge/Badge.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { Badge } from '.'; const mockedProps = { diff --git a/superset-frontend/src/components/Badge/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Badge/index.tsx similarity index 100% rename from superset-frontend/src/components/Badge/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Badge/index.tsx diff --git a/superset-frontend/src/components/Badge/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Badge/types.ts similarity index 100% rename from superset-frontend/src/components/Badge/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Badge/types.ts diff --git a/superset-frontend/src/components/Breadcrumb/Breadcrumb.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/Breadcrumb.stories.tsx similarity index 100% rename from superset-frontend/src/components/Breadcrumb/Breadcrumb.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/Breadcrumb.stories.tsx diff --git a/superset-frontend/src/components/Breadcrumb/Breadcrumb.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/Breadcrumb.test.tsx similarity index 92% rename from superset-frontend/src/components/Breadcrumb/Breadcrumb.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/Breadcrumb.test.tsx index 5edcf805f02..bd45b713059 100644 --- a/superset-frontend/src/components/Breadcrumb/Breadcrumb.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/Breadcrumb.test.tsx @@ -16,12 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { Breadcrumb } from '.'; describe('Breadcrumb Component', () => { - test('renders breadcrumb items correctly', () => { + it('renders breadcrumb items correctly', () => { render( Home diff --git a/superset-frontend/src/components/Breadcrumb/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/index.tsx similarity index 100% rename from superset-frontend/src/components/Breadcrumb/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/index.tsx diff --git a/superset-frontend/src/components/Breadcrumb/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/types.ts similarity index 100% rename from superset-frontend/src/components/Breadcrumb/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Breadcrumb/types.ts diff --git a/superset-frontend/src/components/Button/Button.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Button/Button.stories.tsx similarity index 100% rename from superset-frontend/src/components/Button/Button.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Button/Button.stories.tsx diff --git a/superset-frontend/src/components/Button/Button.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Button/Button.test.tsx similarity index 96% rename from superset-frontend/src/components/Button/Button.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Button/Button.test.tsx index 25c41faf2d8..2f2c16db27b 100644 --- a/superset-frontend/src/components/Button/Button.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Button/Button.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { fireEvent, render } from 'spec/helpers/testing-library'; +import { fireEvent, render } from '@superset-ui/core/spec'; import { Button } from '.'; import { ButtonGallery, diff --git a/superset-frontend/src/components/Button/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Button/index.tsx similarity index 100% rename from superset-frontend/src/components/Button/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Button/index.tsx diff --git a/superset-frontend/src/components/Button/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Button/types.ts similarity index 95% rename from superset-frontend/src/components/Button/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Button/types.ts index 2a8b102be75..92e29eaeed3 100644 --- a/superset-frontend/src/components/Button/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/Button/types.ts @@ -24,7 +24,7 @@ import type { ButtonVariantType, ButtonColorType, } from 'antd/es/button'; -import { IconType } from 'src/components/Icons/types'; +import { IconType } from '@superset-ui/core/components/Icons/types'; import type { TooltipPlacement } from '../Tooltip/types'; export type { AntdButtonProps, ButtonType, ButtonVariantType, ButtonColorType }; diff --git a/superset-frontend/src/components/ButtonGroup/ButtonGroup.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/ButtonGroup.stories.tsx similarity index 100% rename from superset-frontend/src/components/ButtonGroup/ButtonGroup.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/ButtonGroup.stories.tsx diff --git a/superset-frontend/src/components/ButtonGroup/ButtonGroup.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/ButtonGroup.test.tsx similarity index 96% rename from superset-frontend/src/components/ButtonGroup/ButtonGroup.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/ButtonGroup.test.tsx index 62362eb970d..986027a9628 100644 --- a/superset-frontend/src/components/ButtonGroup/ButtonGroup.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/ButtonGroup.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { Button } from '../Button'; import { ButtonGroup } from '.'; diff --git a/superset-frontend/src/components/ButtonGroup/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/index.tsx similarity index 100% rename from superset-frontend/src/components/ButtonGroup/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/index.tsx diff --git a/superset-frontend/src/components/ButtonGroup/types.ts b/superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/types.ts similarity index 100% rename from superset-frontend/src/components/ButtonGroup/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/ButtonGroup/types.ts diff --git a/superset-frontend/src/components/CachedLabel/CachedLabel.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/CachedLabel.test.tsx similarity index 95% rename from superset-frontend/src/components/CachedLabel/CachedLabel.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CachedLabel/CachedLabel.test.tsx index 2e25ed99823..59d9d63088c 100644 --- a/superset-frontend/src/components/CachedLabel/CachedLabel.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/CachedLabel.test.tsx @@ -18,7 +18,7 @@ */ import { isValidElement } from 'react'; -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { CachedLabel } from '.'; import type { CacheLabelProps } from './types'; diff --git a/superset-frontend/src/components/CachedLabel/TooltipContent.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.test.tsx similarity index 92% rename from superset-frontend/src/components/CachedLabel/TooltipContent.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.test.tsx index a9ba7babc04..72629c868b2 100644 --- a/superset-frontend/src/components/CachedLabel/TooltipContent.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.test.tsx @@ -17,8 +17,8 @@ * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; -import { extendedDayjs } from 'src/utils/dates'; +import { render, screen } from '@superset-ui/core/spec'; +import { extendedDayjs } from '../../utils/dates'; import { TooltipContent } from './TooltipContent'; test('Rendering TooltipContent correctly - no timestep', () => { diff --git a/superset-frontend/src/components/CachedLabel/TooltipContent.tsx b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.tsx similarity index 96% rename from superset-frontend/src/components/CachedLabel/TooltipContent.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.tsx index fc0b5914f6b..470e2aa4a50 100644 --- a/superset-frontend/src/components/CachedLabel/TooltipContent.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/TooltipContent.tsx @@ -18,8 +18,8 @@ */ import { FC } from 'react'; -import { extendedDayjs } from 'src/utils/dates'; import { t } from '@superset-ui/core'; +import { extendedDayjs } from '../../utils/dates'; interface Props { cachedTimestamp?: string; diff --git a/superset-frontend/src/components/CachedLabel/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/index.tsx similarity index 96% rename from superset-frontend/src/components/CachedLabel/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CachedLabel/index.tsx index bf1f55fdee4..3a535377622 100644 --- a/superset-frontend/src/components/CachedLabel/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/index.tsx @@ -19,7 +19,7 @@ import { useState, FC } from 'react'; import { t } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Label } from '../Label'; import { Tooltip } from '../Tooltip'; import { TooltipContent } from './TooltipContent'; diff --git a/superset-frontend/src/components/CachedLabel/types.ts b/superset-frontend/packages/superset-ui-core/src/components/CachedLabel/types.ts similarity index 100% rename from superset-frontend/src/components/CachedLabel/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/CachedLabel/types.ts diff --git a/superset-frontend/src/components/Card/Card.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Card/Card.stories.tsx similarity index 100% rename from superset-frontend/src/components/Card/Card.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Card/Card.stories.tsx diff --git a/superset-frontend/src/components/Card/Card.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Card/Card.test.tsx similarity index 94% rename from superset-frontend/src/components/Card/Card.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Card/Card.test.tsx index 2254b4d3c17..5f4028cda2f 100644 --- a/superset-frontend/src/components/Card/Card.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Card/Card.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, waitFor } from 'spec/helpers/testing-library'; +import { render, waitFor } from '@superset-ui/core/spec'; import { Card } from '.'; afterEach(async () => { diff --git a/superset-frontend/src/components/Card/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Card/index.tsx similarity index 100% rename from superset-frontend/src/components/Card/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Card/index.tsx diff --git a/superset-frontend/src/components/Card/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Card/types.ts similarity index 100% rename from superset-frontend/src/components/Card/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Card/types.ts diff --git a/superset-frontend/src/components/CertifiedBadge/CertifiedBadge.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/CertifiedBadge.stories.tsx similarity index 100% rename from superset-frontend/src/components/CertifiedBadge/CertifiedBadge.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/CertifiedBadge.stories.tsx diff --git a/superset-frontend/src/components/CertifiedBadge/CertifiedBadge.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/CertifiedBadge.test.tsx similarity index 88% rename from superset-frontend/src/components/CertifiedBadge/CertifiedBadge.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/CertifiedBadge.test.tsx index b67c0eca446..000f04ac666 100644 --- a/superset-frontend/src/components/CertifiedBadge/CertifiedBadge.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/CertifiedBadge.test.tsx @@ -16,12 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - render, - screen, - userEvent, - waitFor, -} from 'spec/helpers/testing-library'; +import { render, screen, userEvent, waitFor } from '@superset-ui/core/spec'; import { CertifiedBadge } from '.'; import type { CertifiedBadgeProps } from './types'; @@ -35,20 +30,20 @@ test('renders with default props', async () => { test('renders a tooltip when hovered', async () => { await asyncRender(); - userEvent.hover(screen.getByRole('img')); + await userEvent.hover(screen.getByRole('img')); expect(await screen.findByRole('tooltip')).toBeInTheDocument(); }); test('renders with certified by', async () => { const certifiedBy = 'Trusted Authority'; await asyncRender({ certifiedBy }); - userEvent.hover(screen.getByRole('img')); + await userEvent.hover(screen.getByRole('img')); expect(await screen.findByRole('tooltip')).toHaveTextContent(certifiedBy); }); test('renders with details', async () => { const details = 'All requirements have been met.'; await asyncRender({ details }); - userEvent.hover(screen.getByRole('img')); + await userEvent.hover(screen.getByRole('img')); expect(await screen.findByRole('tooltip')).toHaveTextContent(details); }); diff --git a/superset-frontend/src/components/CertifiedBadge/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/index.tsx similarity index 96% rename from superset-frontend/src/components/CertifiedBadge/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/index.tsx index 144f924bd78..4eff6bf4d50 100644 --- a/superset-frontend/src/components/CertifiedBadge/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/index.tsx @@ -17,7 +17,7 @@ * under the License. */ import { t, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Tooltip } from '../Tooltip'; import type { CertifiedBadgeProps } from './types'; diff --git a/superset-frontend/src/components/CertifiedBadge/types.ts b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/types.ts similarity index 92% rename from superset-frontend/src/components/CertifiedBadge/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/types.ts index 947ec0082f9..71f8b4c909f 100644 --- a/superset-frontend/src/components/CertifiedBadge/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/CertifiedBadge/types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import type { IconType } from 'src/components/Icons/types'; +import type { IconType } from '@superset-ui/core/components/Icons/types'; export interface CertifiedBadgeProps { certifiedBy?: string; diff --git a/superset-frontend/src/components/Checkbox/Checkbox.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/Checkbox.stories.tsx similarity index 100% rename from superset-frontend/src/components/Checkbox/Checkbox.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Checkbox/Checkbox.stories.tsx diff --git a/superset-frontend/src/components/Checkbox/Checkbox.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/Checkbox.test.tsx similarity index 80% rename from superset-frontend/src/components/Checkbox/Checkbox.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Checkbox/Checkbox.test.tsx index b53e6da30a6..0b88e0297ab 100644 --- a/superset-frontend/src/components/Checkbox/Checkbox.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/Checkbox.test.tsx @@ -16,12 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - render, - screen, - userEvent, - waitFor, -} from 'spec/helpers/testing-library'; +import { render, screen, userEvent, waitFor } from '@superset-ui/core/spec'; import { Checkbox } from '.'; import type { CheckboxProps } from './types'; @@ -44,37 +39,37 @@ describe('Checkbox Component', () => { }); describe('Rendering', () => { - test('should render correctly', async () => { + it('should render correctly', async () => { const { container } = await asyncRender(); expect(container).toBeInTheDocument(); }); - test('should render the label', async () => { + it('should render the label', async () => { await asyncRender(); expect(screen.getByText('Checkbox Label')).toBeInTheDocument(); }); - test('should render the checkbox', async () => { + it('should render the checkbox', async () => { await asyncRender(); expect(screen.getByRole('checkbox')).toBeInTheDocument(); }); }); describe('States', () => { - test('should render as unchecked when checked is false', async () => { + it('should render as unchecked when checked is false', async () => { await asyncRender(); const checkbox = screen.getByRole('checkbox'); expect(checkbox).not.toBeChecked(); }); - test('should render as checked when checked is true', async () => { + it('should render as checked when checked is true', async () => { const checkedProps = { ...mockedProps, checked: true }; await asyncRender(checkedProps); const checkbox = screen.getByRole('checkbox'); expect(checkbox).toBeChecked(); }); - test('should render as indeterminate when indeterminate is true', async () => { + it('should render as indeterminate when indeterminate is true', async () => { const indeterminateProps = { ...mockedProps, indeterminate: true }; await asyncRender(indeterminateProps); const checkbox = screen.getByRole('checkbox'); @@ -82,7 +77,7 @@ describe('Checkbox Component', () => { expect((checkbox as HTMLInputElement).indeterminate).toBe(true); }); - test('should render as disabled when disabled prop is true', async () => { + it('should render as disabled when disabled prop is true', async () => { const disabledProps = { ...mockedProps, disabled: true }; await asyncRender(disabledProps); expect(screen.getByRole('checkbox')).toBeDisabled(); @@ -90,14 +85,14 @@ describe('Checkbox Component', () => { }); describe('Interactions', () => { - test('should call the onChange handler when clicked', async () => { + it('should call the onChange handler when clicked', async () => { await asyncRender(); const checkbox = screen.getByRole('checkbox'); await userEvent.click(checkbox); expect(mockedProps.onChange).toHaveBeenCalledTimes(1); }); - test('should not call the onChange handler when disabled and clicked', async () => { + it('should not call the onChange handler when disabled and clicked', async () => { const mockOnChange = jest.fn(); const disabledProps = { ...mockedProps, @@ -113,7 +108,7 @@ describe('Checkbox Component', () => { expect(mockOnChange).not.toHaveBeenCalled(); }); - test('calls onChange handler successfully', async () => { + it('calls onChange handler successfully', async () => { const mockAction = jest.fn(); render(); const checkboxInput = screen.getByRole('checkbox'); diff --git a/superset-frontend/src/components/Checkbox/CheckboxIcons.tsx b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/CheckboxIcons.tsx similarity index 100% rename from superset-frontend/src/components/Checkbox/CheckboxIcons.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Checkbox/CheckboxIcons.tsx diff --git a/superset-frontend/src/components/Checkbox/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/index.tsx similarity index 100% rename from superset-frontend/src/components/Checkbox/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Checkbox/index.tsx diff --git a/superset-frontend/src/components/Checkbox/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Checkbox/types.ts similarity index 100% rename from superset-frontend/src/components/Checkbox/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Checkbox/types.ts diff --git a/superset-frontend/src/components/Collapse/Collapse.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.stories.tsx similarity index 100% rename from superset-frontend/src/components/Collapse/Collapse.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.stories.tsx diff --git a/superset-frontend/src/components/Collapse/Collapse.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.test.tsx similarity index 90% rename from superset-frontend/src/components/Collapse/Collapse.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.test.tsx index 4e9f74fe0cd..664215d88ad 100644 --- a/superset-frontend/src/components/Collapse/Collapse.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.test.tsx @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; -import userEvent from '@testing-library/user-event'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import { Collapse } from '.'; import type { CollapseProps } from './types'; @@ -63,25 +62,25 @@ test('renders with one item expanded by default', () => { expect(screen.queryByText('Content 2')).not.toBeInTheDocument(); }); -test('expands on click', () => { +test('expands on click', async () => { renderCollapse(); expect(screen.queryByText('Content 1')).not.toBeInTheDocument(); expect(screen.queryByText('Content 2')).not.toBeInTheDocument(); - userEvent.click(screen.getAllByRole('button')[0]); + await userEvent.click(screen.getAllByRole('button')[0]); expect(screen.getByText('Content 1')).toBeInTheDocument(); expect(screen.queryByText('Content 2')).not.toBeInTheDocument(); }); -test('collapses on click', () => { +test('collapses on click', async () => { renderCollapse({ defaultActiveKey: ['1'] }); expect(screen.getByText('Content 1')).toBeInTheDocument(); expect(screen.queryByText('Content 2')).not.toBeInTheDocument(); - userEvent.click(screen.getAllByRole('button')[0]); + await userEvent.click(screen.getAllByRole('button')[0]); expect(screen.getByText('Content 1').parentNode).toHaveClass( 'ant-collapse-content-hidden', diff --git a/superset-frontend/src/components/Collapse/Collapse.tsx b/superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.tsx similarity index 100% rename from superset-frontend/src/components/Collapse/Collapse.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/Collapse.tsx diff --git a/superset-frontend/src/components/Collapse/CollapseLabelInModal.tsx b/superset-frontend/packages/superset-ui-core/src/components/Collapse/CollapseLabelInModal.tsx similarity index 94% rename from superset-frontend/src/components/Collapse/CollapseLabelInModal.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/CollapseLabelInModal.tsx index 24935810c77..611ad304623 100644 --- a/superset-frontend/src/components/Collapse/CollapseLabelInModal.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Collapse/CollapseLabelInModal.tsx @@ -16,8 +16,8 @@ * under the License. */ import { useTheme } from '@superset-ui/core'; -import { Typography } from 'src/components/Typography'; -import { Icons } from 'src/components'; +import { Typography } from '@superset-ui/core/components/Typography'; +import { Icons } from '@superset-ui/core/components'; interface CollapseLabelInModalProps { title: React.ReactNode; diff --git a/superset-frontend/src/components/Collapse/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Collapse/index.tsx similarity index 100% rename from superset-frontend/src/components/Collapse/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/index.tsx diff --git a/superset-frontend/src/components/Collapse/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Collapse/types.ts similarity index 100% rename from superset-frontend/src/components/Collapse/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Collapse/types.ts diff --git a/superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx similarity index 96% rename from superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx index 132cea64c88..e61157329dc 100644 --- a/superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.stories.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Button } from 'src/components'; +import { Button } from '@superset-ui/core/components'; import { ConfirmStatusChange } from '.'; import type { ConfirmStatusChangeProps, Callback } from './types'; diff --git a/superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx similarity index 96% rename from superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx rename to superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx index 2138a61d84f..bd84ca1a285 100644 --- a/superset-frontend/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/ConfirmStatusChange.test.jsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { fireEvent, render, waitFor } from 'spec/helpers/testing-library'; +import { fireEvent, render, waitFor } from '@superset-ui/core/spec'; import { Button } from '../Button'; import { ConfirmStatusChange } from '.'; diff --git a/superset-frontend/src/components/ConfirmStatusChange/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/index.tsx similarity index 100% rename from superset-frontend/src/components/ConfirmStatusChange/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/index.tsx diff --git a/superset-frontend/src/components/ConfirmStatusChange/types.ts b/superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/types.ts similarity index 100% rename from superset-frontend/src/components/ConfirmStatusChange/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/ConfirmStatusChange/types.ts diff --git a/superset-frontend/src/components/CronPicker/CronPicker.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.stories.tsx similarity index 100% rename from superset-frontend/src/components/CronPicker/CronPicker.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.stories.tsx diff --git a/superset-frontend/src/components/CronPicker/CronPicker.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx similarity index 96% rename from superset-frontend/src/components/CronPicker/CronPicker.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx index cbe8ae37dd1..3a95f27e556 100644 --- a/superset-frontend/src/components/CronPicker/CronPicker.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import * as ReactCronPicker from 'react-js-cron'; import { CronPicker } from '.'; diff --git a/superset-frontend/src/components/CronPicker/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/index.tsx similarity index 98% rename from superset-frontend/src/components/CronPicker/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/CronPicker/index.tsx index 54afd218e83..71f4545eba8 100644 --- a/superset-frontend/src/components/CronPicker/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/index.tsx @@ -20,6 +20,9 @@ import { styled, t } from '@superset-ui/core'; import ReactCronPicker from 'react-js-cron'; import type { Locale, CronProps } from './types'; +// Styles for the crontab-related lib +import 'react-js-cron/dist/styles.css'; + export const LOCALE: Locale = { everyText: t('every'), emptyMonths: t('every month'), diff --git a/superset-frontend/src/components/CronPicker/types.ts b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/types.ts similarity index 100% rename from superset-frontend/src/components/CronPicker/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/CronPicker/types.ts diff --git a/superset-frontend/src/components/DatePicker/DatePicker.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/DatePicker/DatePicker.stories.tsx similarity index 100% rename from superset-frontend/src/components/DatePicker/DatePicker.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DatePicker/DatePicker.stories.tsx diff --git a/superset-frontend/src/components/DatePicker/DatePicker.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/DatePicker/DatePicker.test.tsx similarity index 95% rename from superset-frontend/src/components/DatePicker/DatePicker.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DatePicker/DatePicker.test.tsx index 463c3ace578..eac06ac80cf 100644 --- a/superset-frontend/src/components/DatePicker/DatePicker.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DatePicker/DatePicker.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { DatePicker, RangePicker } from '.'; test('should render date picker', () => { diff --git a/superset-frontend/src/components/DatePicker/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DatePicker/index.tsx similarity index 100% rename from superset-frontend/src/components/DatePicker/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DatePicker/index.tsx diff --git a/superset-frontend/src/components/DatePicker/types.ts b/superset-frontend/packages/superset-ui-core/src/components/DatePicker/types.ts similarity index 100% rename from superset-frontend/src/components/DatePicker/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/DatePicker/types.ts diff --git a/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/DeleteModal/DeleteModal.test.tsx similarity index 87% rename from superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DeleteModal/DeleteModal.test.tsx index 2f579e2e721..c04362cda0e 100644 --- a/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DeleteModal/DeleteModal.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, userEvent, screen } from '@superset-ui/core/spec'; import { DeleteModal } from '.'; test('Must display title and content', () => { @@ -34,7 +34,7 @@ test('Must display title and content', () => { expect(screen.getByTestId('test-description')).toBeInTheDocument(); }); -test('Calling "onHide"', () => { +test('Calling "onHide"', async () => { const props = { title:
Title
, description:
Description
, @@ -48,12 +48,12 @@ test('Calling "onHide"', () => { expect(props.onConfirm).toHaveBeenCalledTimes(0); // type "del" in the input - userEvent.type(screen.getByTestId('delete-modal-input'), 'del'); + await userEvent.type(screen.getByTestId('delete-modal-input'), 'del'); expect(screen.getByTestId('delete-modal-input')).toHaveValue('del'); // close the modal expect(screen.getByText('×')).toBeInTheDocument(); - userEvent.click(screen.getByText('×')); + await userEvent.click(screen.getByText('×')); expect(props.onHide).toHaveBeenCalledTimes(1); expect(props.onConfirm).toHaveBeenCalledTimes(0); @@ -61,7 +61,7 @@ test('Calling "onHide"', () => { expect(screen.getByTestId('delete-modal-input')).toHaveValue(''); }); -test('Calling "onConfirm" only after typing "delete" in the input', () => { +test('Calling "onConfirm" only after typing "delete" in the input', async () => { const props = { title:
Title
, description:
Description
, @@ -76,12 +76,12 @@ test('Calling "onConfirm" only after typing "delete" in the input', () => { expect(props.onConfirm).toHaveBeenCalledTimes(0); // do not execute "onConfirm" if you have not typed "delete" - userEvent.click(screen.getByText('Delete')); + await userEvent.click(screen.getByText('Delete')); expect(props.onConfirm).toHaveBeenCalledTimes(0); // execute "onConfirm" if you have typed "delete" - userEvent.type(screen.getByTestId('delete-modal-input'), 'delete'); - userEvent.click(screen.getByText('Delete')); + await userEvent.type(screen.getByTestId('delete-modal-input'), 'delete'); + await userEvent.click(screen.getByText('Delete')); expect(props.onConfirm).toHaveBeenCalledTimes(1); // confirm input has been cleared diff --git a/superset-frontend/src/components/DeleteModal/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DeleteModal/index.tsx similarity index 100% rename from superset-frontend/src/components/DeleteModal/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DeleteModal/index.tsx diff --git a/superset-frontend/src/components/DeleteModal/types.ts b/superset-frontend/packages/superset-ui-core/src/components/DeleteModal/types.ts similarity index 100% rename from superset-frontend/src/components/DeleteModal/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/DeleteModal/types.ts diff --git a/superset-frontend/src/components/DesignSystem.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/DesignSystem.stories.tsx similarity index 100% rename from superset-frontend/src/components/DesignSystem.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DesignSystem.stories.tsx diff --git a/superset-frontend/src/components/Divider/Divider.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Divider/Divider.stories.tsx similarity index 100% rename from superset-frontend/src/components/Divider/Divider.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Divider/Divider.stories.tsx diff --git a/superset-frontend/src/components/Divider/Divider.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Divider/Divider.test.tsx similarity index 94% rename from superset-frontend/src/components/Divider/Divider.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Divider/Divider.test.tsx index 8148754c0e0..8767adde014 100644 --- a/superset-frontend/src/components/Divider/Divider.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Divider/Divider.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Divider } from '.'; test('should render', () => { diff --git a/superset-frontend/src/components/Divider/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Divider/index.tsx similarity index 100% rename from superset-frontend/src/components/Divider/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Divider/index.tsx diff --git a/superset-frontend/src/components/Divider/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Divider/types.ts similarity index 100% rename from superset-frontend/src/components/Divider/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Divider/types.ts diff --git a/superset-frontend/src/components/Dropdown/Dropdown.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.stories.tsx similarity index 96% rename from superset-frontend/src/components/Dropdown/Dropdown.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.stories.tsx index 5f0f9717caf..29d8998806c 100644 --- a/superset-frontend/src/components/Dropdown/Dropdown.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.stories.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { MenuDotsDropdown } from '.'; import type { MenuDotsDropdownProps } from './types'; diff --git a/superset-frontend/src/components/Dropdown/Dropdown.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.test.tsx similarity index 96% rename from superset-frontend/src/components/Dropdown/Dropdown.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.test.tsx index 65ae7208c60..9baaef9adbf 100644 --- a/superset-frontend/src/components/Dropdown/Dropdown.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/Dropdown.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render, fireEvent, screen } from 'spec/helpers/testing-library'; +import { render, fireEvent, screen } from '@superset-ui/core/spec'; import { NoAnimationDropdown } from '.'; const props = { diff --git a/superset-frontend/src/components/Dropdown/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx similarity index 98% rename from superset-frontend/src/components/Dropdown/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx index b3ffde7341a..4b1e0c449b5 100644 --- a/superset-frontend/src/components/Dropdown/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx @@ -20,7 +20,7 @@ import { ReactElement, cloneElement } from 'react'; import { Dropdown as AntdDropdown, DropdownProps } from 'antd'; import { styled } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { IconOrientation, type NoAnimationDropdownProps, diff --git a/superset-frontend/src/components/Dropdown/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/types.ts similarity index 100% rename from superset-frontend/src/components/Dropdown/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Dropdown/types.ts diff --git a/superset-frontend/src/components/DropdownButton/DropdownButton.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownButton/DropdownButton.stories.tsx similarity index 96% rename from superset-frontend/src/components/DropdownButton/DropdownButton.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DropdownButton/DropdownButton.stories.tsx index 851d0abcc46..b406d9b4da5 100644 --- a/superset-frontend/src/components/DropdownButton/DropdownButton.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DropdownButton/DropdownButton.stories.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { DropdownButton } from '.'; import type { DropdownButtonProps } from './types'; diff --git a/superset-frontend/src/components/DropdownButton/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownButton/index.tsx similarity index 100% rename from superset-frontend/src/components/DropdownButton/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DropdownButton/index.tsx diff --git a/superset-frontend/src/components/DropdownButton/types.ts b/superset-frontend/packages/superset-ui-core/src/components/DropdownButton/types.ts similarity index 100% rename from superset-frontend/src/components/DropdownButton/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/DropdownButton/types.ts diff --git a/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.stories.tsx similarity index 100% rename from superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.stories.tsx diff --git a/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.test.tsx new file mode 100644 index 00000000000..f46b151c7a3 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/DropdownContainer.test.tsx @@ -0,0 +1,180 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { screen, render } from '@superset-ui/core/spec'; +import { Button, DropdownContainer, Icons } from '..'; + +const generateItems = (n: number) => + Array.from({ length: n }).map((_, i) => ({ + id: `el-${i + 1}`, + element: , + })); + +const ITEMS = generateItems(10); + +beforeEach(() => { + // Reset any mocks + jest.restoreAllMocks(); + + // Mock ResizeObserver globally + global.ResizeObserver = jest.fn().mockImplementation(() => ({ + observe: jest.fn(), + unobserve: jest.fn(), + disconnect: jest.fn(), + })); +}); + +test('renders children', () => { + render(); + expect(screen.getByText('Element 1')).toBeInTheDocument(); + expect(screen.getByText('Element 2')).toBeInTheDocument(); + expect(screen.getByText('Element 3')).toBeInTheDocument(); +}); + +test('renders children with custom horizontal spacing', () => { + render(); + expect(screen.getByTestId('container')).toHaveStyle('gap: 20px'); +}); + +test('does not render a dropdown button when not overflowing', () => { + render(); + expect(screen.queryByText('More')).not.toBeInTheDocument(); +}); + +test('renders component with dropdown trigger icon prop without error', () => { + render( + } + />, + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with dropdown trigger text prop without error', () => { + const customText = 'Custom text'; + render( + , + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with dropdown trigger count prop without error', () => { + const customCount = 99; + render( + , + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with dropdown style prop without error', () => { + render( + , + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with onOverflowingStateChange prop without error', () => { + const onOverflowingStateChange = jest.fn(); + render( + , + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with custom dropdown content prop without error', () => { + const customDropdownContent =
Custom content
; + render( + customDropdownContent} + />, + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +test('renders component with dropdown trigger tooltip prop without error', () => { + render( + , + ); + // Component should render without error + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); + +// Tests that can work without complex overflow mocking +test('container has correct test id', () => { + render(); + expect(screen.getByTestId('container')).toBeInTheDocument(); +}); + +test('renders all provided items when not overflowing', () => { + const items = generateItems(3); + render(); + + items.forEach((item, index) => { + expect(screen.getByText(`Element ${index + 1}`)).toBeInTheDocument(); + }); +}); + +test('accepts custom style props', () => { + const customStyle = { backgroundColor: 'red', padding: '10px' }; + render(); + + const container = screen.getByTestId('container'); + expect(container).toHaveStyle('background-color: red'); + expect(container).toHaveStyle('padding: 10px'); +}); + +// Integration test that doesn't rely on specific overflow behavior +test('component renders and functions without throwing errors', () => { + const onOverflowingStateChange = jest.fn(); + + expect(() => { + render( + , + ); + }).not.toThrow(); + + // Basic functionality test + expect(screen.getByText('Element 1')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/DropdownContainer/Overview.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/Overview.stories.tsx similarity index 100% rename from superset-frontend/src/components/DropdownContainer/Overview.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/Overview.stories.tsx diff --git a/superset-frontend/src/components/DropdownContainer/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/index.tsx similarity index 98% rename from superset-frontend/src/components/DropdownContainer/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/index.tsx index 15ed6355334..b9835e3e132 100644 --- a/superset-frontend/src/components/DropdownContainer/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/index.tsx @@ -31,11 +31,7 @@ import { import { Global } from '@emotion/react'; import { css, t, useTheme, usePrevious } from '@superset-ui/core'; import { useResizeDetector } from 'react-resize-detector'; -import { Icons } from 'src/components/Icons'; -import { Badge } from '../Badge'; -import { Button } from '../Button'; -import { Tooltip } from '../Tooltip'; -import Popover from '../Popover'; +import { Badge, Icons, Button, Tooltip, Popover } from '..'; import type { DropdownContainerProps, DropdownItem, diff --git a/superset-frontend/src/components/DropdownContainer/types.ts b/superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/types.ts similarity index 100% rename from superset-frontend/src/components/DropdownContainer/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/DropdownContainer/types.ts diff --git a/superset-frontend/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx similarity index 83% rename from superset-frontend/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx index 544f408b179..c8e0ba13314 100644 --- a/superset-frontend/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/DynamicEditableTitle.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import { DynamicEditableTitle } from '.'; const createProps = (overrides: Record = {}) => ({ @@ -43,26 +43,26 @@ describe('Chart editable title', () => { expect(screen.getByText('Add the name of the chart')).toBeVisible(); }); - it('click, edit and save title', () => { + it('click, edit and save title', async () => { const props = createProps(); render(); const textboxElement = screen.getByRole('textbox'); - userEvent.click(textboxElement); - userEvent.type(textboxElement, ' edited'); + await userEvent.click(textboxElement); + await userEvent.type(textboxElement, ' edited'); expect(screen.getByText('Chart title edited')).toBeVisible(); - userEvent.type(textboxElement, '{enter}'); + await userEvent.type(textboxElement, '{enter}'); expect(props.onSave).toHaveBeenCalled(); }); - it('renders in non-editable mode', () => { + it('renders in non-editable mode', async () => { const props = createProps({ canEdit: false }); render(); const titleElement = screen.getByLabelText('Chart title'); const inputElement = screen.getByRole('textbox'); expect(inputElement).toBeDisabled(); expect(titleElement).toBeVisible(); - userEvent.click(titleElement); - userEvent.type(titleElement, ' edited{enter}'); + await userEvent.click(titleElement); + await userEvent.type(titleElement, ' edited{enter}'); expect(props.onSave).not.toHaveBeenCalled(); }); }); diff --git a/superset-frontend/src/components/DynamicEditableTitle/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx similarity index 100% rename from superset-frontend/src/components/DynamicEditableTitle/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx diff --git a/superset-frontend/src/components/DynamicEditableTitle/types.ts b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/types.ts similarity index 100% rename from superset-frontend/src/components/DynamicEditableTitle/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/types.ts diff --git a/superset-frontend/src/components/EditableTitle/EditableTitle.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/EditableTitle.stories.tsx similarity index 100% rename from superset-frontend/src/components/EditableTitle/EditableTitle.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EditableTitle/EditableTitle.stories.tsx diff --git a/superset-frontend/src/components/EditableTitle/EditableTitle.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/EditableTitle.test.tsx similarity index 91% rename from superset-frontend/src/components/EditableTitle/EditableTitle.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EditableTitle/EditableTitle.test.tsx index 82955594f3b..4440c116e24 100644 --- a/superset-frontend/src/components/EditableTitle/EditableTitle.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/EditableTitle.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { fireEvent, render } from 'spec/helpers/testing-library'; +import { fireEvent, render } from '@superset-ui/core/spec'; import { EditableTitle } from '.'; const mockEvent = { @@ -48,7 +48,7 @@ test('should not render an input if it is not editable', () => { }); describe('should handle click', () => { - test('should enable editing mode on click', () => { + it('should enable editing mode on click', () => { const { getByTestId, container } = render(); fireEvent.click(getByTestId('textarea-editable-title-input')); @@ -59,7 +59,7 @@ describe('should handle click', () => { }); describe('should handle change', () => { - test('should change title', () => { + it('should change title', () => { const { getByTestId } = render(); const textarea = getByTestId('textarea-editable-title-input'); fireEvent.change(textarea, mockEvent); @@ -74,7 +74,7 @@ describe('should handle blur', () => { return selectors; }; - test('should trigger callback', () => { + it('should trigger callback', () => { const callback = jest.fn(); const { getByTestId } = setup({ onSaveTitle: callback }); fireEvent.change(getByTestId('textarea-editable-title-input'), mockEvent); @@ -83,7 +83,7 @@ describe('should handle blur', () => { expect(callback).toHaveBeenCalledWith('new title'); }); - test('should not trigger callback', () => { + it('should not trigger callback', () => { const callback = jest.fn(); const { getByTestId } = setup({ onSaveTitle: callback }); fireEvent.blur(getByTestId('textarea-editable-title-input')); @@ -91,7 +91,7 @@ describe('should handle blur', () => { expect(callback).not.toHaveBeenCalled(); }); - test('should not save empty title', () => { + it('should not save empty title', () => { const callback = jest.fn(); const { getByTestId } = setup({ onSaveTitle: callback }); const textarea = getByTestId('textarea-editable-title-input'); diff --git a/superset-frontend/src/components/EditableTitle/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/index.tsx similarity index 92% rename from superset-frontend/src/components/EditableTitle/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EditableTitle/index.tsx index 9e2afdcecda..3be6fd3f29e 100644 --- a/superset-frontend/src/components/EditableTitle/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/index.tsx @@ -17,9 +17,8 @@ * under the License. */ -import { css, styled, SupersetTheme, t } from '@superset-ui/core'; +import { css, styled, t } from '@superset-ui/core'; import { useEffect, useState, useRef } from 'react'; -import { Link } from 'react-router-dom'; import cx from 'classnames'; import { Tooltip } from '../Tooltip'; import { CertifiedBadge } from '../CertifiedBadge'; @@ -82,7 +81,7 @@ export function EditableTitle({ placeholder = '', certifiedBy, certificationDetails, - url, + renderLink, maxWidth, autoSize = true, ...rest @@ -199,7 +198,7 @@ export function EditableTitle({ value = defaultTitle || title; } - let titleComponent = ( + let titleComponent: React.ReactNode = ( css` - color: ${theme.colorText}; - text-decoration: none; - :hover { - text-decoration: underline; - } - display: inline-block; - `} - > - {value} - - ) : ( - {value} - ); + if (renderLink) { + // New approach: let caller provide the link component + titleComponent = renderLink(value || ''); + } else { + titleComponent = {value}; + } } return ( diff --git a/superset-frontend/src/components/EditableTitle/types.ts b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/types.ts similarity index 96% rename from superset-frontend/src/components/EditableTitle/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/EditableTitle/types.ts index 5370a8cd336..dc615dac644 100644 --- a/superset-frontend/src/components/EditableTitle/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/EditableTitle/types.ts @@ -30,7 +30,7 @@ export interface EditableTitleProps { placeholder?: string; certifiedBy?: string; certificationDetails?: string; - url?: string; + renderLink?: (title: string) => React.ReactNode; maxWidth?: number; autoSize?: boolean; } diff --git a/superset-frontend/src/components/EmptyState/Empty.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/Empty.test.tsx similarity index 94% rename from superset-frontend/src/components/EmptyState/Empty.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/Empty.test.tsx index 7c9ace0fc81..da5dad601e0 100644 --- a/superset-frontend/src/components/EmptyState/Empty.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/Empty.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Empty } from './Empty'; test('should render', () => { diff --git a/superset-frontend/src/components/EmptyState/Empty.tsx b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/Empty.tsx similarity index 100% rename from superset-frontend/src/components/EmptyState/Empty.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/Empty.tsx diff --git a/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/EmptyState.stories.tsx similarity index 97% rename from superset-frontend/src/components/EmptyState/EmptyState.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/EmptyState.stories.tsx index 949548583fe..2c58d7ca459 100644 --- a/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/EmptyState.stories.tsx @@ -18,7 +18,7 @@ * under the License. */ import { Meta, StoryFn } from '@storybook/react'; -import { Row, Col } from 'src/components'; +import { Row, Col } from '@superset-ui/core/components'; import { EmptyState, imageMap } from '.'; const emptyStates = [ diff --git a/superset-frontend/src/components/EmptyState/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx similarity index 83% rename from superset-frontend/src/components/EmptyState/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx index 7b33d469f92..570119ff2fc 100644 --- a/superset-frontend/src/components/EmptyState/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx @@ -20,22 +20,21 @@ import { ReactNode, SyntheticEvent } from 'react'; import { styled, css, SupersetTheme, t } from '@superset-ui/core'; // Importing svg images -import FilterResultsImage from 'src/assets/images/filter-results.svg'; -import ChartImage from 'src/assets/images/chart.svg'; -import FilterImage from 'src/assets/images/filter.svg'; -import EmptyChartsImage from 'src/assets/images/empty-charts.svg'; -import EmptyDashboardImage from 'src/assets/images/empty-dashboard.svg'; -import UnionImage from 'src/assets/images/union.svg'; -import StarCircleImage from 'src/assets/images/star-circle.svg'; -import VectorImage from 'src/assets/images/vector.svg'; -import DocumentImage from 'src/assets/images/document.svg'; -import DatasetImage from 'src/assets/images/empty-dataset.svg'; -import EmptySqlChartImage from 'src/assets/images/empty_sql_chart.svg'; -import EmptyQueryImage from 'src/assets/images/empty-query.svg'; -import EmptyTableImage from 'src/assets/images/empty-table.svg'; -import EmptyImage from 'src/assets/images/empty.svg'; -import { Button } from '../Button'; -import { Empty } from './Empty'; +import FilterResultsImage from './svgs/filter-results.svg'; +import ChartImage from '../assets/svgs/chart.svg'; +import FilterImage from './svgs/filter.svg'; +import EmptyChartsImage from './svgs/empty-charts.svg'; +import EmptyDashboardImage from './svgs/empty-dashboard.svg'; +import UnionImage from './svgs/union.svg'; +import StarCircleImage from './svgs/star-circle.svg'; +import VectorImage from './svgs/vector.svg'; +import DocumentImage from './svgs/document.svg'; +import DatasetImage from './svgs/empty-dataset.svg'; +import EmptySqlChartImage from './svgs/empty_sql_chart.svg'; +import EmptyQueryImage from './svgs/empty-query.svg'; +import EmptyTableImage from './svgs/empty-table.svg'; +import EmptyImage from './svgs/empty.svg'; +import { Button, Empty } from '..'; import type { EmptyStateProps, EmptyStateSize } from './types'; export const imageMap = { diff --git a/superset-frontend/src/assets/images/document.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/document.svg similarity index 100% rename from superset-frontend/src/assets/images/document.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/document.svg diff --git a/superset-frontend/src/assets/images/empty-charts.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-charts.svg similarity index 100% rename from superset-frontend/src/assets/images/empty-charts.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-charts.svg diff --git a/superset-frontend/src/assets/images/empty-dashboard.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-dashboard.svg similarity index 100% rename from superset-frontend/src/assets/images/empty-dashboard.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-dashboard.svg diff --git a/superset-frontend/src/assets/images/empty-dataset.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-dataset.svg similarity index 100% rename from superset-frontend/src/assets/images/empty-dataset.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-dataset.svg diff --git a/superset-frontend/src/assets/images/empty-query.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-query.svg similarity index 100% rename from superset-frontend/src/assets/images/empty-query.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-query.svg diff --git a/superset-frontend/src/assets/images/empty-table.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-table.svg similarity index 100% rename from superset-frontend/src/assets/images/empty-table.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty-table.svg diff --git a/superset-frontend/src/assets/images/empty.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty.svg similarity index 100% rename from superset-frontend/src/assets/images/empty.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty.svg diff --git a/superset-frontend/src/assets/images/empty_sql_chart.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty_sql_chart.svg similarity index 100% rename from superset-frontend/src/assets/images/empty_sql_chart.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/empty_sql_chart.svg diff --git a/superset-frontend/src/assets/images/filter-results.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/filter-results.svg similarity index 100% rename from superset-frontend/src/assets/images/filter-results.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/filter-results.svg diff --git a/superset-frontend/src/assets/images/filter.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/filter.svg similarity index 100% rename from superset-frontend/src/assets/images/filter.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/filter.svg diff --git a/superset-frontend/src/assets/images/star-circle.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/star-circle.svg similarity index 100% rename from superset-frontend/src/assets/images/star-circle.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/star-circle.svg diff --git a/superset-frontend/src/assets/images/union.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/union.svg similarity index 100% rename from superset-frontend/src/assets/images/union.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/union.svg diff --git a/superset-frontend/src/assets/images/vector.svg b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/vector.svg similarity index 100% rename from superset-frontend/src/assets/images/vector.svg rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/svgs/vector.svg diff --git a/superset-frontend/src/components/EmptyState/types.ts b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/types.ts similarity index 100% rename from superset-frontend/src/components/EmptyState/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/EmptyState/types.ts diff --git a/superset-frontend/src/components/FaveStar/FaveStar.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/FaveStar.stories.tsx similarity index 100% rename from superset-frontend/src/components/FaveStar/FaveStar.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/FaveStar/FaveStar.stories.tsx diff --git a/superset-frontend/src/components/FaveStar/FaveStar.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/FaveStar.test.tsx similarity index 92% rename from superset-frontend/src/components/FaveStar/FaveStar.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/FaveStar/FaveStar.test.tsx index 89a51085768..05cbab43a6b 100644 --- a/superset-frontend/src/components/FaveStar/FaveStar.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/FaveStar.test.tsx @@ -17,10 +17,10 @@ * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import { FaveStar } from '.'; -jest.mock('src/components/Tooltip', () => ({ +jest.mock('@superset-ui/core/components/Tooltip', () => ({ Tooltip: (props: any) =>
, })); @@ -35,7 +35,7 @@ test('render right content', async () => { expect(screen.getByRole('img', { name: 'starred' })).toBeInTheDocument(); expect(props.saveFaveStar).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(props.saveFaveStar).toHaveBeenCalledTimes(1); expect(props.saveFaveStar).toHaveBeenCalledWith(props.itemId, true); @@ -43,7 +43,7 @@ test('render right content', async () => { expect(await findByRole('img', { name: 'unstarred' })).toBeInTheDocument(); expect(props.saveFaveStar).toHaveBeenCalledTimes(1); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(props.saveFaveStar).toHaveBeenCalledTimes(2); expect(props.saveFaveStar).toHaveBeenCalledWith(props.itemId, false); }); diff --git a/superset-frontend/src/components/FaveStar/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/index.tsx similarity index 97% rename from superset-frontend/src/components/FaveStar/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/FaveStar/index.tsx index eabacfe832d..bd51fa2a2ca 100644 --- a/superset-frontend/src/components/FaveStar/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/index.tsx @@ -20,7 +20,7 @@ import { useCallback, useEffect, MouseEvent } from 'react'; import { css, t, styled, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Tooltip } from '../Tooltip'; import type { FaveStarProps } from './types'; diff --git a/superset-frontend/src/components/FaveStar/types.ts b/superset-frontend/packages/superset-ui-core/src/components/FaveStar/types.ts similarity index 100% rename from superset-frontend/src/components/FaveStar/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/FaveStar/types.ts diff --git a/superset-frontend/src/components/Flex/Flex.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Flex/Flex.stories.tsx similarity index 100% rename from superset-frontend/src/components/Flex/Flex.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Flex/Flex.stories.tsx diff --git a/superset-frontend/src/components/Flex/Flex.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Flex/Flex.test.tsx similarity index 94% rename from superset-frontend/src/components/Flex/Flex.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Flex/Flex.test.tsx index dbbca7983e0..3353b96e612 100644 --- a/superset-frontend/src/components/Flex/Flex.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Flex/Flex.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Flex } from '.'; test('should render', () => { diff --git a/superset-frontend/src/components/Flex/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Flex/index.tsx similarity index 100% rename from superset-frontend/src/components/Flex/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Flex/index.tsx diff --git a/superset-frontend/src/components/Flex/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Flex/types.ts similarity index 100% rename from superset-frontend/src/components/Flex/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Flex/types.ts diff --git a/superset-frontend/src/components/Form/Form.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/Form.tsx similarity index 100% rename from superset-frontend/src/components/Form/Form.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/Form.tsx diff --git a/superset-frontend/src/components/Form/FormItem.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/FormItem.tsx similarity index 100% rename from superset-frontend/src/components/Form/FormItem.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/FormItem.tsx diff --git a/superset-frontend/src/components/Form/FormLabel.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/FormLabel.tsx similarity index 100% rename from superset-frontend/src/components/Form/FormLabel.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/FormLabel.tsx diff --git a/superset-frontend/src/components/Form/LabeledErrorBoundInput.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.stories.tsx similarity index 100% rename from superset-frontend/src/components/Form/LabeledErrorBoundInput.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.stories.tsx diff --git a/superset-frontend/src/components/Form/LabeledErrorBoundInput.test.jsx b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.test.jsx similarity index 97% rename from superset-frontend/src/components/Form/LabeledErrorBoundInput.test.jsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.test.jsx index 03cfdf15ea5..2b66127e237 100644 --- a/superset-frontend/src/components/Form/LabeledErrorBoundInput.test.jsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.test.jsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, fireEvent, screen } from 'spec/helpers/testing-library'; +import { render, fireEvent, screen } from '@superset-ui/core/spec'; import { LabeledErrorBoundInput } from './LabeledErrorBoundInput'; const defaultProps = { diff --git a/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx similarity index 93% rename from superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx index 995b004a3d2..77d5a1c5550 100644 --- a/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx @@ -16,15 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import { styled, css, SupersetTheme, t } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import errorIcon from 'src/assets/images/icons/error.svg'; -import { Button } from '../Button'; -import { InfoTooltip } from '../InfoTooltip'; +import { styled, css, SupersetTheme, t } from '../..'; +import { error as errorIcon } from '../assets/svgs'; +import { Button, Icons, InfoTooltip, Tooltip } from '..'; import { Input } from '../Input'; -import { Tooltip } from '../Tooltip'; -import { FormItem } from './FormItem'; import { FormLabel } from './FormLabel'; +import { FormItem } from './FormItem'; import type { LabeledErrorBoundInputProps } from './types'; const StyledInput = styled(Input)` diff --git a/superset-frontend/src/components/Form/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Form/index.tsx similarity index 100% rename from superset-frontend/src/components/Form/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Form/index.tsx diff --git a/superset-frontend/src/components/Form/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Form/types.ts similarity index 100% rename from superset-frontend/src/components/Form/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Form/types.ts diff --git a/superset-frontend/src/components/Grid/Grid.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.stories.tsx similarity index 99% rename from superset-frontend/src/components/Grid/Grid.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.stories.tsx index 30137208660..0a09f703ddb 100644 --- a/superset-frontend/src/components/Grid/Grid.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.stories.tsx @@ -17,7 +17,7 @@ * under the License. */ import { Meta, StoryObj } from '@storybook/react'; -import Slider from 'src/components/Slider/index'; +import Slider from '@superset-ui/core/components/Slider/index'; import { useState } from 'react'; import { Row, Col } from '.'; import type { ColProps, RowProps } from './types'; diff --git a/superset-frontend/src/components/Grid/Grid.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.test.tsx similarity index 95% rename from superset-frontend/src/components/Grid/Grid.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.test.tsx index 36174906e09..884ce75ed3b 100644 --- a/superset-frontend/src/components/Grid/Grid.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Grid/Grid.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { Col, Row } from '.'; diff --git a/superset-frontend/src/components/Grid/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Grid/index.tsx similarity index 100% rename from superset-frontend/src/components/Grid/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Grid/index.tsx diff --git a/superset-frontend/src/components/Grid/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Grid/types.ts similarity index 100% rename from superset-frontend/src/components/Grid/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Grid/types.ts diff --git a/superset-frontend/src/components/IconButton/IconButton.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.stories.tsx similarity index 100% rename from superset-frontend/src/components/IconButton/IconButton.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.stories.tsx diff --git a/superset-frontend/src/components/IconButton/IconButton.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.test.tsx similarity index 97% rename from superset-frontend/src/components/IconButton/IconButton.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.test.tsx index 4ee67d030f1..16448a92467 100644 --- a/superset-frontend/src/components/IconButton/IconButton.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, fireEvent } from 'spec/helpers/testing-library'; +import { render, screen, fireEvent } from '@superset-ui/core/spec'; import { IconButton } from '.'; const defaultProps = { diff --git a/superset-frontend/src/components/IconButton/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/IconButton/index.tsx similarity index 100% rename from superset-frontend/src/components/IconButton/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/IconButton/index.tsx diff --git a/superset-frontend/src/components/IconTooltip/IconTooltip.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.stories.tsx similarity index 96% rename from superset-frontend/src/components/IconTooltip/IconTooltip.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.stories.tsx index ca955071f40..b350c8c24ae 100644 --- a/superset-frontend/src/components/IconTooltip/IconTooltip.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.stories.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { css, useTheme } from '@superset-ui/core'; import { IconTooltip } from '.'; import type { IconTooltipProps } from './types'; diff --git a/superset-frontend/src/components/IconTooltip/IconTooltip.test.jsx b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.test.jsx similarity index 93% rename from superset-frontend/src/components/IconTooltip/IconTooltip.test.jsx rename to superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.test.jsx index c7467491c90..befe566eb71 100644 --- a/superset-frontend/src/components/IconTooltip/IconTooltip.test.jsx +++ b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/IconTooltip.test.jsx @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { IconTooltip } from '.'; -jest.mock('src/components/Tooltip', () => ({ +jest.mock('@superset-ui/core/components/Tooltip', () => ({ Tooltip: () =>
, })); diff --git a/superset-frontend/src/components/IconTooltip/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/index.tsx similarity index 100% rename from superset-frontend/src/components/IconTooltip/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/IconTooltip/index.tsx diff --git a/superset-frontend/src/components/IconTooltip/types.ts b/superset-frontend/packages/superset-ui-core/src/components/IconTooltip/types.ts similarity index 100% rename from superset-frontend/src/components/IconTooltip/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/IconTooltip/types.ts diff --git a/superset-frontend/src/components/Icons/AntdEnhanced.tsx b/superset-frontend/packages/superset-ui-core/src/components/Icons/AntdEnhanced.tsx similarity index 99% rename from superset-frontend/src/components/Icons/AntdEnhanced.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Icons/AntdEnhanced.tsx index 9a37cd6f14a..d01b5efdb55 100644 --- a/superset-frontend/src/components/Icons/AntdEnhanced.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Icons/AntdEnhanced.tsx @@ -34,6 +34,7 @@ import { BookOutlined, BugOutlined, BulbOutlined, + CalculatorOutlined, CaretUpOutlined, CaretDownOutlined, CaretLeftOutlined, @@ -157,6 +158,7 @@ const AntdIcons = { BookOutlined, BugOutlined, BulbOutlined, + CalculatorOutlined, CaretUpOutlined, CaretDownOutlined, CaretLeftOutlined, diff --git a/superset-frontend/src/components/Icons/AsyncIcon.tsx b/superset-frontend/packages/superset-ui-core/src/components/Icons/AsyncIcon.tsx similarity index 95% rename from superset-frontend/src/components/Icons/AsyncIcon.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Icons/AsyncIcon.tsx index 1ce39c25bd6..48f3521bfd3 100644 --- a/superset-frontend/src/components/Icons/AsyncIcon.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Icons/AsyncIcon.tsx @@ -18,7 +18,7 @@ */ import { FC, SVGProps, useEffect, useRef, useState } from 'react'; -import TransparentIcon from 'src/assets/images/icons/transparent.svg'; +import TransparentIcon from './svgs/transparent.svg'; import { IconType } from './types'; import { BaseIconComponent } from './BaseIcon'; diff --git a/superset-frontend/src/components/Icons/BaseIcon.tsx b/superset-frontend/packages/superset-ui-core/src/components/Icons/BaseIcon.tsx similarity index 97% rename from superset-frontend/src/components/Icons/BaseIcon.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Icons/BaseIcon.tsx index cc2c58af3c3..46c4c68905d 100644 --- a/superset-frontend/src/components/Icons/BaseIcon.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Icons/BaseIcon.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { css, useTheme, themeObject } from '@superset-ui/core'; +import { css, useTheme, themeObject } from '../..'; import { AntdIconType, BaseIconProps, CustomIconType, IconType } from './types'; const genAriaLabel = (fileName: string) => { diff --git a/superset-frontend/src/components/Icons/Icons.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Icons/Icons.stories.tsx similarity index 100% rename from superset-frontend/src/components/Icons/Icons.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Icons/Icons.stories.tsx diff --git a/superset-frontend/src/components/Icons/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Icons/index.tsx similarity index 98% rename from superset-frontend/src/components/Icons/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Icons/index.tsx index b43ae6ca182..acb7588993a 100644 --- a/superset-frontend/src/components/Icons/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Icons/index.tsx @@ -20,6 +20,7 @@ import { FC } from 'react'; import { antdEnhancedIcons } from './AntdEnhanced'; import AsyncIcon from './AsyncIcon'; + import type { IconType } from './types'; /** @@ -76,3 +77,4 @@ export const Icons: IconComponentType = { ...antdEnhancedIcons, ...iconOverrides, }; +export type { IconType }; diff --git a/superset-frontend/src/assets/images/icons/transparent.svg b/superset-frontend/packages/superset-ui-core/src/components/Icons/svgs/transparent.svg similarity index 100% rename from superset-frontend/src/assets/images/icons/transparent.svg rename to superset-frontend/packages/superset-ui-core/src/components/Icons/svgs/transparent.svg diff --git a/superset-frontend/src/components/Icons/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Icons/types.ts similarity index 100% rename from superset-frontend/src/components/Icons/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Icons/types.ts diff --git a/superset-frontend/src/components/Image/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Image/index.tsx similarity index 100% rename from superset-frontend/src/components/Image/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Image/index.tsx diff --git a/superset-frontend/src/components/InfoTooltip/InfoTooltip.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/InfoTooltip.stories.tsx similarity index 95% rename from superset-frontend/src/components/InfoTooltip/InfoTooltip.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/InfoTooltip.stories.tsx index 0a0f35a41d3..2339592addc 100644 --- a/superset-frontend/src/components/InfoTooltip/InfoTooltip.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/InfoTooltip.stories.tsx @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import type { InfoTooltipProps } from './types'; -import { InfoTooltip } from '.'; +import { InfoTooltip, InfoTooltipProps } from '.'; export default { title: 'Components/InfoTooltip', diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx b/superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/index.tsx similarity index 94% rename from superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx rename to superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/index.tsx index bd502f64c3a..e5ddfba57aa 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/InfoTooltip/index.tsx @@ -28,9 +28,9 @@ import { QuestionCircleOutlined, } from '@ant-design/icons'; import { Button } from 'antd'; -import { Tooltip, TooltipProps, TooltipPlacement } from './Tooltip'; +import { Tooltip, TooltipProps, TooltipPlacement } from '../Tooltip'; -export interface InfoTooltipWithTriggerProps { +export interface InfoTooltipProps { label?: string; tooltip?: TooltipProps['title']; onClick?: () => void; @@ -41,7 +41,7 @@ export interface InfoTooltipWithTriggerProps { iconSize?: 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl'; } -export const InfoTooltipWithTrigger = ({ +export const InfoTooltip = ({ type = 'info', iconSize = 's', label, @@ -50,7 +50,7 @@ export const InfoTooltipWithTrigger = ({ className = 'text-muted', placement = 'right', iconStyle, -}: InfoTooltipWithTriggerProps) => { +}: InfoTooltipProps) => { const theme = useTheme(); const infoTooltipWithTriggerVariants = useMemo( @@ -81,6 +81,7 @@ export const InfoTooltipWithTrigger = ({ , ); - userEvent.hover(screen.getByRole('button')); + await userEvent.hover(screen.getByRole('button')); await waitFor(() => expect(onOpenChange).toHaveBeenCalledTimes(1)); }); diff --git a/superset-frontend/src/components/Popover/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Popover/index.tsx similarity index 91% rename from superset-frontend/src/components/Popover/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Popover/index.tsx index 8446840722f..f7e41b5be62 100644 --- a/superset-frontend/src/components/Popover/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Popover/index.tsx @@ -23,6 +23,4 @@ export interface PopoverProps extends AntdPopoverProps { forceRender?: boolean; } -const Popover = (props: PopoverProps) => ; - -export default Popover; +export const Popover = (props: PopoverProps) => ; diff --git a/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/PopoverDropdown.stories.tsx similarity index 100% rename from superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/PopoverDropdown.stories.tsx diff --git a/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/PopoverDropdown.test.tsx similarity index 88% rename from superset-frontend/src/components/PopoverDropdown/PopoverDropdown.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/PopoverDropdown.test.tsx index 863ef046efa..9a4f669a5b9 100644 --- a/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/PopoverDropdown.test.tsx @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import PopoverDropdown, { PopoverDropdownProps, OptionProps, -} from 'src/components/PopoverDropdown'; +} from '@superset-ui/core/components/PopoverDropdown'; const defaultProps: PopoverDropdownProps = { id: 'popover-dropdown', @@ -42,7 +42,7 @@ test('renders with default props', async () => { test('renders the menu on click', async () => { render(); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(await screen.findByRole('menu')).toBeInTheDocument(); }); @@ -71,14 +71,14 @@ test('renders with custom option', async () => { )} />, ); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(await screen.findByText('Custom Option 1')).toBeInTheDocument(); }); test('triggers onChange', async () => { render(); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(await screen.findByText('Option 2')).toBeInTheDocument(); - userEvent.click(screen.getByText('Option 2')); + await userEvent.click(screen.getByText('Option 2')); expect(defaultProps.onChange).toHaveBeenCalled(); }); diff --git a/superset-frontend/src/components/PopoverDropdown/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/index.tsx similarity index 96% rename from superset-frontend/src/components/PopoverDropdown/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/index.tsx index a45b2b93a35..5b0532afa46 100644 --- a/superset-frontend/src/components/PopoverDropdown/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/PopoverDropdown/index.tsx @@ -19,8 +19,8 @@ import { Key } from 'react'; import cx from 'classnames'; import { styled, useTheme } from '@superset-ui/core'; -import { Menu } from 'src/components/Menu'; -import { Icons } from 'src/components/Icons'; +import { Menu } from '@superset-ui/core/components/Menu'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Dropdown } from '../Dropdown'; export interface OptionProps { diff --git a/superset-frontend/src/components/PopoverSection/PopoverSection.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverSection/PopoverSection.stories.tsx similarity index 100% rename from superset-frontend/src/components/PopoverSection/PopoverSection.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverSection/PopoverSection.stories.tsx diff --git a/superset-frontend/src/components/PopoverSection/PopoverSection.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverSection/PopoverSection.test.tsx similarity index 88% rename from superset-frontend/src/components/PopoverSection/PopoverSection.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverSection/PopoverSection.test.tsx index 29978aba637..09bbb44be38 100644 --- a/superset-frontend/src/components/PopoverSection/PopoverSection.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/PopoverSection/PopoverSection.test.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; -import PopoverSection from 'src/components/PopoverSection'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; +import PopoverSection from '.'; test('renders with default props', async () => { render( @@ -44,7 +44,7 @@ test('renders a tooltip when hovered', async () => {
, ); - userEvent.hover(screen.getAllByRole('img')[0]); + await userEvent.hover(screen.getAllByRole('img')[0]); expect(await screen.findByRole('tooltip')).toBeInTheDocument(); }); @@ -55,6 +55,6 @@ test('calls onSelect when clicked', async () => {
, ); - userEvent.click(await screen.findByRole('img')); + await userEvent.click(await screen.findByRole('img')); expect(onSelect).toHaveBeenCalled(); }); diff --git a/superset-frontend/src/components/PopoverSection/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/PopoverSection/index.tsx similarity index 97% rename from superset-frontend/src/components/PopoverSection/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/PopoverSection/index.tsx index be201a24b09..2e395e8a427 100644 --- a/superset-frontend/src/components/PopoverSection/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/PopoverSection/index.tsx @@ -18,7 +18,7 @@ */ import { MouseEventHandler, ReactNode } from 'react'; import { css, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Tooltip } from '../Tooltip'; export interface PopoverSectionProps { diff --git a/superset-frontend/src/components/ProgressBar/ProgressBar.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/ProgressBar/ProgressBar.stories.tsx similarity index 100% rename from superset-frontend/src/components/ProgressBar/ProgressBar.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ProgressBar/ProgressBar.stories.tsx diff --git a/superset-frontend/src/components/ProgressBar/ProgressBar.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/ProgressBar/ProgressBar.test.tsx similarity index 97% rename from superset-frontend/src/components/ProgressBar/ProgressBar.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ProgressBar/ProgressBar.test.tsx index cb419b51b5d..db606c0ff64 100644 --- a/superset-frontend/src/components/ProgressBar/ProgressBar.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ProgressBar/ProgressBar.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import ProgressBar, { ProgressBarProps } from '.'; const mockedProps: ProgressBarProps = { diff --git a/superset-frontend/src/components/ProgressBar/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ProgressBar/index.tsx similarity index 100% rename from superset-frontend/src/components/ProgressBar/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ProgressBar/index.tsx diff --git a/superset-frontend/src/components/Radio/Radio.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.stories.tsx similarity index 98% rename from superset-frontend/src/components/Radio/Radio.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.stories.tsx index d7fb4056dad..65ba411f1c2 100644 --- a/superset-frontend/src/components/Radio/Radio.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.stories.tsx @@ -17,7 +17,7 @@ * under the License. */ import { css } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Space } from '../Space'; import { Radio, type RadioProps, type RadioGroupWrapperProps } from '.'; diff --git a/superset-frontend/src/components/Radio/Radio.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.test.tsx similarity index 92% rename from superset-frontend/src/components/Radio/Radio.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.test.tsx index c9ea42ed709..2601ba95f15 100644 --- a/superset-frontend/src/components/Radio/Radio.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Radio/Radio.test.tsx @@ -16,12 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { Radio } from '.'; describe('Radio Component', () => { - test('renders radio button and allows selection', () => { + it('renders radio button and allows selection', () => { render( Option 1 diff --git a/superset-frontend/src/components/Radio/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Radio/index.tsx similarity index 100% rename from superset-frontend/src/components/Radio/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Radio/index.tsx diff --git a/superset-frontend/src/components/RefreshLabel/RefreshLabel.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/RefreshLabel.stories.tsx similarity index 100% rename from superset-frontend/src/components/RefreshLabel/RefreshLabel.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/RefreshLabel.stories.tsx diff --git a/superset-frontend/src/components/RefreshLabel/RefreshLabel.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/RefreshLabel.test.tsx similarity index 87% rename from superset-frontend/src/components/RefreshLabel/RefreshLabel.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/RefreshLabel.test.tsx index f90c503164a..c44b207e1dc 100644 --- a/superset-frontend/src/components/RefreshLabel/RefreshLabel.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/RefreshLabel.test.tsx @@ -16,21 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; -import RefreshLabel from 'src/components/RefreshLabel'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; +import RefreshLabel from '@superset-ui/core/components/RefreshLabel'; test('renders with default props', async () => { render(); const refresh = await screen.findByRole('button'); expect(refresh).toBeInTheDocument(); - userEvent.hover(refresh); + await userEvent.hover(refresh); }); test('renders tooltip on hover', async () => { const tooltipText = 'Tooltip'; render(); const refresh = screen.getByRole('button'); - userEvent.hover(refresh); + await userEvent.hover(refresh); const tooltip = await screen.findByRole('tooltip'); expect(tooltip).toBeInTheDocument(); expect(tooltip).toHaveTextContent(tooltipText); @@ -40,6 +40,6 @@ test('triggers on click event', async () => { const onClick = jest.fn(); render(); const refresh = await screen.findByRole('button'); - userEvent.click(refresh); + await userEvent.click(refresh); expect(onClick).toHaveBeenCalled(); }); diff --git a/superset-frontend/src/components/RefreshLabel/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/index.tsx similarity index 92% rename from superset-frontend/src/components/RefreshLabel/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/index.tsx index 61857f2cca9..88b680ab1ec 100644 --- a/superset-frontend/src/components/RefreshLabel/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/RefreshLabel/index.tsx @@ -18,8 +18,8 @@ */ import { MouseEventHandler, forwardRef } from 'react'; import { SupersetTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import type { IconType } from 'src/components/Icons/types'; +import { Icons } from '@superset-ui/core/components/Icons'; +import type { IconType } from '@superset-ui/core/components/Icons/types'; import { Tooltip } from '../Tooltip'; export interface RefreshLabelProps { diff --git a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx similarity index 96% rename from superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx rename to superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx index d35c2160e97..ed0a1cc4bfa 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx @@ -20,7 +20,7 @@ import { useEffect, useMemo, useState } from 'react'; import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'; import remarkGfm from 'remark-gfm'; import { mergeWith } from 'lodash'; -import { FeatureFlag, isFeatureEnabled } from '../utils'; +import { FeatureFlag, isFeatureEnabled } from '../../utils'; interface SafeMarkdownProps { source: string; @@ -37,7 +37,7 @@ export function getOverrideHtmlSchema( ); } -function SafeMarkdown({ +export function SafeMarkdown({ source, htmlSanitization = true, htmlSchemaOverrides = {}, @@ -85,5 +85,3 @@ function SafeMarkdown({ ); } - -export default SafeMarkdown; diff --git a/superset-frontend/src/components/Select/AsyncSelect.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.stories.tsx similarity index 100% rename from superset-frontend/src/components/Select/AsyncSelect.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.stories.tsx diff --git a/superset-frontend/src/components/Select/AsyncSelect.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.test.tsx similarity index 95% rename from superset-frontend/src/components/Select/AsyncSelect.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.test.tsx index 06e8e61470e..b1b97d63301 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.test.tsx @@ -20,11 +20,11 @@ import { createEvent, fireEvent, render, - screen, userEvent, + screen, waitFor, within, -} from 'spec/helpers/testing-library'; +} from '@superset-ui/core/spec'; import { AsyncSelect } from '.'; const ARIA_LABEL = 'Test'; @@ -137,9 +137,9 @@ const matchOrder = async (expectedLabels: string[]) => { return true; }; -const type = (text: string) => { +const type = async (text: string) => { const select = getSelect(); - userEvent.clear(select); + await userEvent.clear(select); return userEvent.type(select, text, { delay: 10 }); }; @@ -200,7 +200,7 @@ test('does not add a new option if the value is already in the options', async ( test('inverts the selection', async () => { render(); await open(); - userEvent.click(await findSelectOption(OPTIONS[0].label)); + await userEvent.click(await findSelectOption(OPTIONS[0].label)); expect(await screen.findByLabelText('stop')).toBeInTheDocument(); }); @@ -236,7 +236,7 @@ test('should sort selected to top when in single mode', async () => { render(); const originalLabels = OPTIONS.map(option => option.label); await open(); - userEvent.click(await findSelectOption(originalLabels[1])); + await userEvent.click(await findSelectOption(originalLabels[1])); // after selection, keep the original order expect(await matchOrder(originalLabels)).toBe(true); @@ -249,7 +249,7 @@ test('should sort selected to top when in single mode', async () => { // keep clicking other items, the updated order should still based on // original order - userEvent.click(await findSelectOption(originalLabels[5])); + await userEvent.click(await findSelectOption(originalLabels[5])); await matchOrder(labels); await type('{esc}'); await open(); @@ -258,7 +258,7 @@ test('should sort selected to top when in single mode', async () => { expect(await matchOrder(labels)).toBe(true); // should revert to original order - clearAll(); + await clearAll(); await type('{esc}'); await open(); expect(await matchOrder(originalLabels)).toBe(true); @@ -270,7 +270,7 @@ test('should sort selected to the top when in multi mode', async () => { let labels = originalLabels.slice(); await open(); - userEvent.click(await findSelectOption(labels[1])); + await userEvent.click(await findSelectOption(labels[1])); expect(await matchOrder(labels)).toBe(true); await type('{esc}'); @@ -279,14 +279,14 @@ test('should sort selected to the top when in multi mode', async () => { expect(await matchOrder(labels)).toBe(true); await open(); - userEvent.click(await findSelectOption(labels[5])); + await userEvent.click(await findSelectOption(labels[5])); await type('{esc}'); await open(); labels = [labels.splice(0, 1)[0], labels.splice(4, 1)[0]].concat(labels); expect(await matchOrder(labels)).toBe(true); // should revert to original order - clearAll(); + await clearAll(); await type('{esc}'); await open(); expect(await matchOrder(originalLabels)).toBe(true); @@ -449,7 +449,7 @@ test('clear all the values', async () => { onClear={onClear} />, ); - clearAll(); + await clearAll(); expect(onClear).toHaveBeenCalled(); const values = await findAllSelectValues(); expect(values.length).toBe(0); @@ -471,7 +471,7 @@ test('adds the null option when selected in single mode', async () => { })); render(); await open(); - userEvent.click(await findSelectOption(NULL_OPTION.label)); + await userEvent.click(await findSelectOption(NULL_OPTION.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(NULL_OPTION.label); }); @@ -485,8 +485,8 @@ test('adds the null option when selected in multiple mode', async () => { , ); await open(); - userEvent.click(await findSelectOption(OPTIONS[0].label)); - userEvent.click(await findSelectOption(NULL_OPTION.label)); + await userEvent.click(await findSelectOption(OPTIONS[0].label)); + await userEvent.click(await findSelectOption(NULL_OPTION.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(OPTIONS[0].label); expect(values[1]).toHaveTextContent(NULL_OPTION.label); @@ -512,8 +512,8 @@ test('opens the select without any data', async () => { test('displays the loading indicator when opening', async () => { render(); - await waitFor(() => { - userEvent.click(getSelect()); + await waitFor(async () => { + await userEvent.click(getSelect()); expect(screen.getByText(LOADING)).toBeInTheDocument(); }); expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); @@ -523,7 +523,7 @@ test('makes a selection in single mode', async () => { render(); const optionText = 'Emma'; await open(); - userEvent.click(await findSelectOption(optionText)); + await userEvent.click(await findSelectOption(optionText)); expect(await findSelectValue()).toHaveTextContent(optionText); }); @@ -531,8 +531,8 @@ test('multiple selections in multiple mode', async () => { render(); await open(); const [firstOption, secondOption] = OPTIONS; - userEvent.click(await findSelectOption(firstOption.label)); - userEvent.click(await findSelectOption(secondOption.label)); + await userEvent.click(await findSelectOption(firstOption.label)); + await userEvent.click(await findSelectOption(secondOption.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(firstOption.label); expect(values[1]).toHaveTextContent(secondOption.label); @@ -543,7 +543,7 @@ test('changes the selected item in single mode', async () => { render(); await open(); const [firstOption, secondOption] = OPTIONS; - userEvent.click(await findSelectOption(firstOption.label)); + await userEvent.click(await findSelectOption(firstOption.label)); expect(onChange).toHaveBeenCalledWith( expect.objectContaining({ label: firstOption.label, @@ -552,7 +552,7 @@ test('changes the selected item in single mode', async () => { expect.objectContaining(firstOption), ); expect(await findSelectValue()).toHaveTextContent(firstOption.label); - userEvent.click(await findSelectOption(secondOption.label)); + await userEvent.click(await findSelectOption(secondOption.label)); expect(onChange).toHaveBeenCalledWith( expect.objectContaining({ label: secondOption.label, @@ -568,8 +568,8 @@ test('deselects an item in multiple mode', async () => { await open(); const option3 = OPTIONS[2]; const option8 = OPTIONS[7]; - userEvent.click(await findSelectOption(option8.label)); - userEvent.click(await findSelectOption(option3.label)); + await userEvent.click(await findSelectOption(option8.label)); + await userEvent.click(await findSelectOption(option3.label)); let options = await findAllSelectOptions(); expect(options).toHaveLength(Math.min(defaultProps.pageSize, OPTIONS.length)); @@ -591,7 +591,7 @@ test('deselects an item in multiple mode', async () => { expect(values[0]).toHaveTextContent(option8.label); expect(values[1]).toHaveTextContent(option3.label); - userEvent.click(await findSelectOption(option3.label)); + await userEvent.click(await findSelectOption(option3.label)); values = await findAllSelectValues(); expect(values.length).toBe(1); expect(values[0]).toHaveTextContent(option8.label); @@ -848,8 +848,8 @@ test('does not fire onChange when searching but no selection', async () => { ); await open(); await type('Joh'); - userEvent.click(await findSelectOption('John')); - userEvent.click(screen.getByRole('main')); + await userEvent.click(await findSelectOption('John')); + await userEvent.click(screen.getByRole('main')); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -863,7 +863,7 @@ test('fires onChange when clearing the selection in single mode', async () => { value={OPTIONS[0]} />, ); - clearAll(); + await clearAll(); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -877,7 +877,7 @@ test('fires onChange when clearing the selection in multiple mode', async () => value={OPTIONS[0]} />, ); - clearAll(); + await clearAll(); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -1006,9 +1006,9 @@ test('does not fire onChange if the same value is selected in single mode', asyn const optionText = 'Emma'; await open(); expect(onChange).toHaveBeenCalledTimes(0); - userEvent.click(await findSelectOption(optionText)); + await userEvent.click(await findSelectOption(optionText)); expect(onChange).toHaveBeenCalledTimes(1); - userEvent.click(await findSelectOption(optionText)); + await userEvent.click(await findSelectOption(optionText)); expect(onChange).toHaveBeenCalledTimes(1); }); diff --git a/superset-frontend/src/components/Select/AsyncSelect.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx similarity index 98% rename from superset-frontend/src/components/Select/AsyncSelect.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx index 111da65cef5..9a915657347 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx @@ -42,8 +42,7 @@ import { RefSelectProps, } from 'antd/es/select'; import { debounce, isEqual, uniq } from 'lodash'; -import { Icons } from 'src/components/Icons'; -import { FAST_DEBOUNCE, SLOW_DEBOUNCE } from 'src/constants'; +import { Constants, Icons } from '@superset-ui/core/components'; import { Space } from '../Space'; import { getValue, @@ -106,7 +105,7 @@ const getQueryCacheKey = (value: string, page: number, pageSize: number) => * The Static type accepts a static array of options. * The Async type accepts a promise that will return the options. * Each of the categories come with different abilities. For a comprehensive guide please refer to - * the storybook in src/components/Select/Select.stories.tsx. + * the storybook in @superset-ui/core/components/Select/Select.stories.tsx. */ const AsyncSelect = forwardRef( ( @@ -363,7 +362,7 @@ const AsyncSelect = forwardRef( ); const debouncedFetchPage = useMemo( - () => debounce(fetchPage, SLOW_DEBOUNCE), + () => debounce(fetchPage, Constants.SLOW_DEBOUNCE), [fetchPage], ); @@ -395,7 +394,7 @@ const AsyncSelect = forwardRef( } setInputValue(search); onSearch?.(searchValue); - }, FAST_DEBOUNCE); + }, Constants.FAST_DEBOUNCE); useEffect(() => () => handleOnSearch.cancel(), [handleOnSearch]); diff --git a/superset-frontend/src/components/Select/Select.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.stories.tsx similarity index 95% rename from superset-frontend/src/components/Select/Select.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/Select.stories.tsx index c174de5477f..dc64db080a9 100644 --- a/superset-frontend/src/components/Select/Select.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.stories.tsx @@ -17,7 +17,6 @@ * under the License. */ import { StoryObj } from '@storybook/react'; -import ControlHeader from 'src/explore/components/ControlHeader'; import { SelectOptionsType, SelectProps } from './types'; import { Select } from '.'; @@ -72,21 +71,6 @@ const selectPositions = [ }, ]; -const mountHeader = (type: String) => { - let header; - if (type === 'text') { - header = 'Text header'; - } else if (type === 'control') { - header = ( - - ); - } - return header; -}; - const generateOptions = (opts: SelectOptionsType, count: number) => { let generated = opts.slice(); let iteration = 0; @@ -122,7 +106,6 @@ export const InteractiveSelect: StoryObj = { ? generateOptions(options, optionsCount) : options } - header={mountHeader(header)} mode="multiple" />
diff --git a/superset-frontend/src/components/Select/Select.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.test.tsx similarity index 93% rename from superset-frontend/src/components/Select/Select.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/Select.test.tsx index 72e4029228b..588620f47bd 100644 --- a/superset-frontend/src/components/Select/Select.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.test.tsx @@ -24,7 +24,7 @@ import { userEvent, waitFor, within, -} from 'spec/helpers/testing-library'; +} from '@superset-ui/core/spec'; import { Select } from '.'; type Option = { @@ -123,17 +123,17 @@ const matchOrder = async (expectedLabels: string[]) => { return true; }; -const type = (text: string, delay?: number, clear = true) => { +const type = async (text: string, delay?: number, clear = true) => { const select = getSelect(); if (clear) { - userEvent.clear(select); + await userEvent.clear(select); } return userEvent.type(select, text, { delay: delay ?? 10 }); }; -const clearTypedText = () => { +const clearTypedText = async () => { const select = getSelect(); - userEvent.clear(select); + await userEvent.clear(select); }; const open = () => waitFor(() => userEvent.click(getSelect())); @@ -201,7 +201,7 @@ test('does not add new options when the value is in a nested/grouped option', as test('inverts the selection', async () => { render(); const originalLabels = OPTIONS.map(option => option.label); await open(); - userEvent.click(await findSelectOption(originalLabels[1])); + await userEvent.click(await findSelectOption(originalLabels[1])); // after selection, keep the original order expect(await matchOrder(originalLabels)).toBe(true); @@ -231,7 +231,7 @@ test('should sort selected to top when in single mode', async () => { // keep clicking other items, the updated order should still based on // original order - userEvent.click(await findSelectOption(originalLabels[5])); + await userEvent.click(await findSelectOption(originalLabels[5])); await matchOrder(labels); await reopen(); labels = originalLabels.slice(); @@ -239,7 +239,7 @@ test('should sort selected to top when in single mode', async () => { expect(await matchOrder(labels)).toBe(true); // should revert to original order - clearAll(); + await clearAll(); await reopen(); expect(await matchOrder(originalLabels)).toBe(true); }); @@ -250,7 +250,7 @@ test('should sort selected to the top when in multi mode', async () => { let labels = originalLabels.slice(); await open(); - userEvent.click(await findSelectOption(labels[2])); + await userEvent.click(await findSelectOption(labels[2])); expect(await matchOrder(labels)).toBe(true); await reopen(); @@ -258,13 +258,13 @@ test('should sort selected to the top when in multi mode', async () => { expect(await matchOrder(labels)).toBe(true); await open(); - userEvent.click(await findSelectOption(labels[5])); + await userEvent.click(await findSelectOption(labels[5])); await reopen(); labels = [labels.splice(0, 1)[0], labels.splice(4, 1)[0]].concat(labels); expect(await matchOrder(labels)).toBe(true); // should revert to original order - clearAll(); + await clearAll(); await reopen(); expect(await matchOrder(originalLabels)).toBe(true); }); @@ -273,8 +273,8 @@ test('order of selected values is preserved until dropdown is closed', async () render(); await open(); - userEvent.click(await findSelectOption(NULL_OPTION.label)); + await userEvent.click(await findSelectOption(NULL_OPTION.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(NULL_OPTION.label); }); @@ -452,8 +452,8 @@ test('adds the null option when selected in multiple mode', async () => { />, ); await open(); - userEvent.click(await findSelectOption(OPTIONS[0].label)); - userEvent.click(await findSelectOption(NULL_OPTION.label)); + await userEvent.click(await findSelectOption(OPTIONS[0].label)); + await userEvent.click(await findSelectOption(NULL_OPTION.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(OPTIONS[0].label); expect(values[1]).toHaveTextContent(NULL_OPTION.label); @@ -476,7 +476,7 @@ test('makes a selection in single mode', async () => { render(); await open(); const [firstOption, secondOption] = OPTIONS; - userEvent.click(await findSelectOption(firstOption.label)); - userEvent.click(await findSelectOption(secondOption.label)); + await userEvent.click(await findSelectOption(firstOption.label)); + await userEvent.click(await findSelectOption(secondOption.label)); const values = await findAllSelectValues(); expect(values[0]).toHaveTextContent(firstOption.label); expect(values[1]).toHaveTextContent(secondOption.label); @@ -496,7 +496,7 @@ test('changes the selected item in single mode', async () => { render(); await open(); const [firstOption, secondOption] = OPTIONS; - userEvent.click(await findSelectOption(firstOption.label)); - userEvent.click(await findSelectOption(secondOption.label)); + await userEvent.click(await findSelectOption(firstOption.label)); + await userEvent.click(await findSelectOption(secondOption.label)); let values = await findAllSelectValues(); expect(values.length).toBe(2); expect(values[0]).toHaveTextContent(firstOption.label); expect(values[1]).toHaveTextContent(secondOption.label); - userEvent.click(await findSelectOption(firstOption.label)); + await userEvent.click(await findSelectOption(firstOption.label)); values = await findAllSelectValues(); expect(values.length).toBe(1); expect(values[0]).toHaveTextContent(secondOption.label); @@ -681,7 +681,9 @@ test('selects all values', async () => { />, ); await open(); - userEvent.click(await screen.findByText(selectAllButtonText(OPTIONS.length))); + await userEvent.click( + await screen.findByText(selectAllButtonText(OPTIONS.length)), + ); const values = await findAllSelectValues(); expect(values.length).toBe(1); expect(values[0]).toHaveTextContent(`+ ${OPTIONS.length} ...`); @@ -697,11 +699,13 @@ test('unselects all values', async () => { />, ); await open(); - userEvent.click(await screen.findByText(selectAllButtonText(OPTIONS.length))); + await userEvent.click( + await screen.findByText(selectAllButtonText(OPTIONS.length)), + ); let values = await findAllSelectValues(); expect(values.length).toBe(1); expect(values[0]).toHaveTextContent(`+ ${OPTIONS.length} ...`); - userEvent.click( + await userEvent.click( await screen.findByText(deselectAllButtonText(OPTIONS.length)), ); values = await findAllSelectValues(); @@ -722,7 +726,7 @@ test('deselecting a new value also removes it from the options', async () => { expect(await findSelectOption(NEW_OPTION)).toBeInTheDocument(); await type('{enter}'); clearTypedText(); - userEvent.click(await findSelectOption(NEW_OPTION)); + await userEvent.click(await findSelectOption(NEW_OPTION)); expect(await querySelectOption(NEW_OPTION)).not.toBeInTheDocument(); }); @@ -825,7 +829,7 @@ test('do not count unselected disabled options in "Select all"', async () => { test('"Deselect all" counts all selected options', async () => { render(); await open(); await type(NEW_OPTION); - userEvent.click(await findSelectOption(NEW_OPTION)); + await userEvent.click(await findSelectOption(NEW_OPTION)); clearTypedText(); await open(); - userEvent.click(await findSelectOption('Ava')); + await userEvent.click(await findSelectOption('Ava')); expect(await screen.findByText(deselectAllButtonText(2))).toBeInTheDocument(); }); @@ -868,12 +872,12 @@ test('"Select all" does not affect disabled options', async () => { // Checking Select all shouldn't affect the disabled options const selectAll = selectAllButtonText(OPTIONS.length - 1); - userEvent.click(await screen.findByText(selectAll)); + await userEvent.click(await screen.findByText(selectAll)); expect(await findSelectValue()).toHaveTextContent(options[0].label); expect(await findSelectValue()).not.toHaveTextContent(options[1].label); // Unchecking Select all shouldn't affect the disabled options - userEvent.click(await screen.findByText(selectAll)); + await userEvent.click(await screen.findByText(selectAll)); expect(await findSelectValue()).toHaveTextContent(options[0].label); expect(await findSelectValue()).not.toHaveTextContent(options[1].label); }); @@ -892,8 +896,8 @@ test('does not fire onChange when searching but no selection', async () => { ); await open(); await type('Joh'); - userEvent.click(await findSelectOption('John')); - userEvent.click(screen.getByRole('main')); + await userEvent.click(await findSelectOption('John')); + await userEvent.click(screen.getByRole('main')); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -907,7 +911,7 @@ test('fires onChange when clearing the selection in single mode', async () => { value={OPTIONS[0]} />, ); - clearAll(); + await clearAll(); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -921,7 +925,7 @@ test('fires onChange when clearing the selection in multiple mode', async () => value={OPTIONS[0]} />, ); - clearAll(); + await clearAll(); expect(onChange).toHaveBeenCalledTimes(1); }); @@ -1013,9 +1017,9 @@ test('does not fire onChange if the same value is selected in single mode', asyn const optionText = 'Emma'; await open(); expect(onChange).toHaveBeenCalledTimes(0); - userEvent.click(await findSelectOption(optionText)); + await userEvent.click(await findSelectOption(optionText)); expect(onChange).toHaveBeenCalledTimes(1); - userEvent.click(await findSelectOption(optionText)); + await userEvent.click(await findSelectOption(optionText)); expect(onChange).toHaveBeenCalledTimes(1); }); diff --git a/superset-frontend/src/components/Select/Select.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx similarity index 98% rename from superset-frontend/src/components/Select/Select.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx index 8471a5c96f4..38d254c5821 100644 --- a/superset-frontend/src/components/Select/Select.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx @@ -29,12 +29,8 @@ import { ReactElement, } from 'react'; -import { - ensureIsArray, - FAST_DEBOUNCE, - t, - usePrevious, -} from '@superset-ui/core'; +import { ensureIsArray, t, usePrevious } from '@superset-ui/core'; +import { Constants } from '@superset-ui/core/components'; import { LabeledValue as AntdLabeledValue, RefSelectProps, @@ -84,7 +80,7 @@ import { Button } from '../Button'; * The Static type accepts a static array of options. * The Async type accepts a promise that will return the options. * Each of the categories come with different abilities. For a comprehensive guide please refer to - * the storybook in src/components/Select/Select.stories.tsx. + * the storybook in @superset-ui/core/components/Select/Select.stories.tsx. */ const Select = forwardRef( ( @@ -384,7 +380,7 @@ const Select = forwardRef( setVisibleOptions(filteredOptions); setInputValue(searchValue); onSearch?.(searchValue); - }, FAST_DEBOUNCE); + }, Constants.FAST_DEBOUNCE); useEffect(() => () => handleOnSearch.cancel(), [handleOnSearch]); diff --git a/superset-frontend/src/components/Select/constants.ts b/superset-frontend/packages/superset-ui-core/src/components/Select/constants.ts similarity index 96% rename from superset-frontend/src/components/Select/constants.ts rename to superset-frontend/packages/superset-ui-core/src/components/Select/constants.ts index 84f5f01e4b0..dd2797b4a58 100644 --- a/superset-frontend/src/components/Select/constants.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/constants.ts @@ -17,8 +17,8 @@ * under the License. */ import { LabeledValue as AntdLabeledValue } from 'antd/es/select'; -import { rankedSearchCompare } from 'src/utils/rankedSearchCompare'; import { t } from '@superset-ui/core'; +import { rankedSearchCompare } from '../../utils/rankedSearchCompare'; import { RawValue } from './types'; export const MAX_TAG_COUNT = 4; diff --git a/superset-frontend/packages/superset-ui-core/src/components/Select/index.ts b/superset-frontend/packages/superset-ui-core/src/components/Select/index.ts new file mode 100644 index 00000000000..0b02349df8f --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/index.ts @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import Select from './Select'; +import AsyncSelect from './AsyncSelect'; + +export { Select, AsyncSelect }; +export * from './types'; +export * from './styles'; +export * from './constants'; + +// TODO hack to provide vanilla antd Select and SelectProps as +// we mutated the interface quite a bit here, and some internal packages +// are still using the vanilla antd Select +export { Select as RawAntdSelect } from 'antd'; +export { type SelectProps as RawAntdSelectProps } from 'antd/es/select'; diff --git a/superset-frontend/src/components/Select/styles.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/styles.tsx similarity index 98% rename from superset-frontend/src/components/Select/styles.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/styles.tsx index e777d67f74c..05743d60d7c 100644 --- a/superset-frontend/src/components/Select/styles.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/styles.tsx @@ -18,7 +18,7 @@ */ import { styled } from '@superset-ui/core'; import { Select } from 'antd'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { Spin } from '../Spin'; import { Flex } from '../Flex'; diff --git a/superset-frontend/src/components/Select/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Select/types.ts similarity index 100% rename from superset-frontend/src/components/Select/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Select/types.ts diff --git a/superset-frontend/src/components/Select/utils.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx similarity index 99% rename from superset-frontend/src/components/Select/utils.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx index e74a1f9ddcb..6bdd2724b02 100644 --- a/superset-frontend/src/components/Select/utils.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx @@ -18,7 +18,7 @@ */ import { ensureIsArray, t } from '@superset-ui/core'; import { ReactElement, RefObject } from 'react'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { LabeledValue as AntdLabeledValue, SELECT_ALL_VALUE } from '.'; import { StyledHelperText, StyledLoadingText, StyledSpin } from './styles'; import { CustomLabeledValue, RawValue, SelectOptionsType, V } from './types'; diff --git a/superset-frontend/src/components/Skeleton/Skeleton.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Skeleton/Skeleton.stories.tsx similarity index 100% rename from superset-frontend/src/components/Skeleton/Skeleton.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Skeleton/Skeleton.stories.tsx diff --git a/superset-frontend/src/components/Skeleton/Skeleton.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Skeleton/Skeleton.test.tsx similarity index 86% rename from superset-frontend/src/components/Skeleton/Skeleton.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Skeleton/Skeleton.test.tsx index fff2acd854e..f36778c1085 100644 --- a/superset-frontend/src/components/Skeleton/Skeleton.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Skeleton/Skeleton.test.tsx @@ -16,25 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { Skeleton } from '.'; describe('Skeleton Component', () => { - test('renders skeleton', () => { + it('renders skeleton', () => { render(); expect(screen.getByRole('list')).toHaveClass('ant-skeleton-paragraph'); }); - test('renders skeleton with correct number of paragraph rows', () => { + it('renders skeleton with correct number of paragraph rows', () => { render(); const paragraph = screen.getByRole('list'); expect(paragraph.children.length).toBe(3); }); - test('does not render skeleton when loading is false', () => { + it('does not render skeleton when loading is false', () => { render(

Loaded Content

diff --git a/superset-frontend/src/components/Skeleton/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Skeleton/index.tsx similarity index 100% rename from superset-frontend/src/components/Skeleton/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Skeleton/index.tsx diff --git a/superset-frontend/src/components/Slider/Slider.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Slider/Slider.stories.tsx similarity index 100% rename from superset-frontend/src/components/Slider/Slider.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Slider/Slider.stories.tsx diff --git a/superset-frontend/src/components/Slider/Slider.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Slider/Slider.test.tsx similarity index 95% rename from superset-frontend/src/components/Slider/Slider.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Slider/Slider.test.tsx index 8413e0ebc67..f4fa3157909 100644 --- a/superset-frontend/src/components/Slider/Slider.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Slider/Slider.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import Slider from '.'; const mockedProps = { diff --git a/superset-frontend/src/components/Slider/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Slider/index.tsx similarity index 100% rename from superset-frontend/src/components/Slider/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Slider/index.tsx diff --git a/superset-frontend/src/components/Space/Space.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Space/Space.stories.tsx similarity index 100% rename from superset-frontend/src/components/Space/Space.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Space/Space.stories.tsx diff --git a/superset-frontend/src/components/Space/Space.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Space/Space.test.tsx similarity index 91% rename from superset-frontend/src/components/Space/Space.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Space/Space.test.tsx index 8d73af21988..2097cecb3a8 100644 --- a/superset-frontend/src/components/Space/Space.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Space/Space.test.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - -import { render } from 'spec/helpers/testing-library'; +import '@testing-library/jest-dom'; +import { render } from '@superset-ui/core/spec'; import { Space } from '.'; test('should render', () => { diff --git a/superset-frontend/src/components/Space/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Space/index.tsx similarity index 100% rename from superset-frontend/src/components/Space/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Space/index.tsx diff --git a/superset-frontend/src/components/Spin/Spin.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Spin/Spin.test.tsx similarity index 94% rename from superset-frontend/src/components/Spin/Spin.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Spin/Spin.test.tsx index f76616110e6..a0214651a44 100644 --- a/superset-frontend/src/components/Spin/Spin.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Spin/Spin.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Spin } from '.'; test('renders spin with default props', () => { diff --git a/superset-frontend/src/components/Spin/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Spin/index.tsx similarity index 100% rename from superset-frontend/src/components/Spin/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Spin/index.tsx diff --git a/superset-frontend/src/components/Steps/Steps.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Steps/Steps.stories.tsx similarity index 100% rename from superset-frontend/src/components/Steps/Steps.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Steps/Steps.stories.tsx diff --git a/superset-frontend/src/components/Steps/Steps.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Steps/Steps.test.tsx similarity index 94% rename from superset-frontend/src/components/Steps/Steps.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Steps/Steps.test.tsx index 53418e2f147..5c8996ac220 100644 --- a/superset-frontend/src/components/Steps/Steps.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Steps/Steps.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import { Steps } from '.'; test('should render with default props', () => { diff --git a/superset-frontend/src/components/Steps/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Steps/index.tsx similarity index 100% rename from superset-frontend/src/components/Steps/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Steps/index.tsx diff --git a/superset-frontend/src/components/Switch/Switch.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Switch/Switch.stories.tsx similarity index 100% rename from superset-frontend/src/components/Switch/Switch.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Switch/Switch.stories.tsx diff --git a/superset-frontend/src/components/Switch/Switch.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Switch/Switch.test.tsx similarity index 95% rename from superset-frontend/src/components/Switch/Switch.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Switch/Switch.test.tsx index 0e8e762d041..03a4983115a 100644 --- a/superset-frontend/src/components/Switch/Switch.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Switch/Switch.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { Switch } from '.'; const mockedProps = { diff --git a/superset-frontend/src/components/Switch/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Switch/index.tsx similarity index 100% rename from superset-frontend/src/components/Switch/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Switch/index.tsx diff --git a/superset-frontend/src/components/Table/Table.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/Table.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/Table.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/Table.stories.tsx diff --git a/superset-frontend/src/components/Table/Table.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/Table.test.tsx similarity index 96% rename from superset-frontend/src/components/Table/Table.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/Table.test.tsx index 9e6b716704e..48fe7327bbd 100644 --- a/superset-frontend/src/components/Table/Table.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/Table.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, waitFor } from 'spec/helpers/testing-library'; +import { render, screen, waitFor } from '@superset-ui/core/spec'; import type { ColumnsType } from 'antd/es/table'; import { Table, TableSize } from './index'; diff --git a/superset-frontend/src/components/Table/TableOverview.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/TableOverview.stories.tsx similarity index 98% rename from superset-frontend/src/components/Table/TableOverview.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/TableOverview.stories.tsx index 88e411e8c1e..acbb24fffbf 100644 --- a/superset-frontend/src/components/Table/TableOverview.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/TableOverview.stories.tsx @@ -127,7 +127,7 @@ of the data object for that row, as the first argument of the sorter function. The alphabeticalSort is for columns that display a string of text. \`\`\` -import { alphabeticalSort } from 'src/components/Table/sorters'; +import { alphabeticalSort } from '@superset-ui/core/components/Table/sorters'; const basicColumns = [ { @@ -359,7 +359,7 @@ you can register \`onDragOver\` and \`onDragDrop\` event handlers on the destina as the getData key as shown below. \`\`\` -import { SUPERSET_TABLE_COLUMN } from 'src/components/table'; +import { SUPERSET_TABLE_COLUMN } from '@superset-ui/core/components/table'; const handleDrop = (ev:Event) => { const json = ev.dataTransfer?.getData?.(SUPERSET_TABLE_COLUMN); diff --git a/superset-frontend/src/components/Table/VirtualTable.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx similarity index 100% rename from superset-frontend/src/components/Table/VirtualTable.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.overview.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.overview.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.overview.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.overview.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx similarity index 87% rename from superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx index c17ac0196b5..0da17300839 100644 --- a/superset-frontend/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/ActionCell.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import ActionCell, { appendDataToMenu } from './index'; import { exampleMenuOptions, exampleRow } from './fixtures'; @@ -25,13 +25,13 @@ test('renders with default props', async () => { exampleMenuOptions[0].onClick = clickHandler; render(); // Open the menu - userEvent.click(await screen.findByTestId('dropdown-trigger')); + await userEvent.click(await screen.findByTestId('dropdown-trigger')); // verify all of the menu items are being displayed - exampleMenuOptions.forEach((item, index) => { + exampleMenuOptions.forEach(async (item, index) => { expect(screen.getByText(item.label)).toBeInTheDocument(); if (index === 0) { // verify the menu items' onClick gets invoked - userEvent.click(screen.getByText(item.label)); + await userEvent.click(screen.getByText(item.label)); } }); expect(clickHandler).toHaveBeenCalled(); diff --git a/superset-frontend/src/components/Table/cell-renderers/ActionCell/fixtures.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/fixtures.ts similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ActionCell/fixtures.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/fixtures.ts diff --git a/superset-frontend/src/components/Table/cell-renderers/ActionCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/index.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ActionCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ActionCell/index.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/BooleanCell/BooleanCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/BooleanCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/BooleanCell/BooleanCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/BooleanCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx similarity index 75% rename from superset-frontend/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx index 7853e6a892b..6060b5cfe4e 100644 --- a/superset-frontend/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/BooleanCell.test.tsx @@ -16,21 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; -import { BOOL_FALSE_DISPLAY, BOOL_TRUE_DISPLAY } from 'src/constants'; +import { render, screen } from '@superset-ui/core/spec'; +import { Constants } from '@superset-ui/core/components'; import BooleanCell from '.'; test('renders true value', async () => { render(); - expect(screen.getByText(BOOL_TRUE_DISPLAY)).toBeInTheDocument(); + expect(screen.getByText(Constants.BOOL_TRUE_DISPLAY)).toBeInTheDocument(); }); test('renders false value', async () => { render(); - expect(screen.getByText(BOOL_FALSE_DISPLAY)).toBeInTheDocument(); + expect(screen.getByText(Constants.BOOL_FALSE_DISPLAY)).toBeInTheDocument(); }); test('renders falsy value', async () => { render(); - expect(screen.getByText(BOOL_FALSE_DISPLAY)).toBeInTheDocument(); + expect(screen.getByText(Constants.BOOL_FALSE_DISPLAY)).toBeInTheDocument(); }); diff --git a/superset-frontend/src/components/Table/cell-renderers/BooleanCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/index.tsx similarity index 84% rename from superset-frontend/src/components/Table/cell-renderers/BooleanCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/index.tsx index e12060737ed..353e7461f3d 100644 --- a/superset-frontend/src/components/Table/cell-renderers/BooleanCell/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/BooleanCell/index.tsx @@ -16,14 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -import { BOOL_FALSE_DISPLAY, BOOL_TRUE_DISPLAY } from 'src/constants'; +import { Constants } from '@superset-ui/core/components'; export interface BooleanCellProps { value?: boolean; } function BooleanCell({ value }: BooleanCellProps) { - return {value ? BOOL_TRUE_DISPLAY : BOOL_FALSE_DISPLAY}; + return ( + + {value ? Constants.BOOL_TRUE_DISPLAY : Constants.BOOL_FALSE_DISPLAY} + + ); } export default BooleanCell; diff --git a/superset-frontend/src/components/Table/cell-renderers/ButtonCell/ButtonCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/ButtonCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ButtonCell/ButtonCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/ButtonCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx similarity index 94% rename from superset-frontend/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx index e7162f954ab..e9a8f8c97e5 100644 --- a/superset-frontend/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/ButtonCell.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; import ButtonCell from './index'; import { exampleRow } from '../fixtures'; diff --git a/superset-frontend/src/components/Table/cell-renderers/ButtonCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/index.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/ButtonCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/ButtonCell/index.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/NullCell/NullCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/NullCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/NullCell/NullCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/NullCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx similarity index 79% rename from superset-frontend/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx index f2a2bcbf83c..b4dfdc23a11 100644 --- a/superset-frontend/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/NullCell.test.tsx @@ -16,19 +16,19 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; -import { supersetTheme } from '@superset-ui/core'; -import { NULL_DISPLAY } from 'src/constants'; +import { render, screen } from '@superset-ui/core/spec'; +import { supersetTheme } from '../../../..'; +import { Constants } from '../../..'; import NullCell from '.'; test('renders null value', async () => { render(); - expect(screen.getByText(NULL_DISPLAY)).toBeInTheDocument(); + expect(screen.getByText(Constants.NULL_DISPLAY)).toBeInTheDocument(); }); test('renders with gray font', async () => { render(); - expect(screen.getByText(NULL_DISPLAY)).toHaveStyle( + expect(screen.getByText(Constants.NULL_DISPLAY)).toHaveStyle( `color: ${supersetTheme.colors.grayscale.light1}`, ); }); diff --git a/superset-frontend/src/components/Table/cell-renderers/NullCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/index.tsx similarity index 87% rename from superset-frontend/src/components/Table/cell-renderers/NullCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/index.tsx index 52fe59af9f1..e01b7c672ec 100644 --- a/superset-frontend/src/components/Table/cell-renderers/NullCell/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NullCell/index.tsx @@ -16,15 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -import { styled } from '@superset-ui/core'; -import { NULL_DISPLAY } from 'src/constants'; +import { styled } from '../../../..'; +import { Constants } from '../../..'; const GrayCell = styled.span` color: ${({ theme }) => theme.colors.grayscale.light1}; `; function NullCell() { - return {NULL_DISPLAY}; + return {Constants.NULL_DISPLAY}; } export default NullCell; diff --git a/superset-frontend/src/components/Table/cell-renderers/NumericCell/NumericCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/NumericCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/NumericCell/NumericCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/NumericCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx similarity index 96% rename from superset-frontend/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx index 7319942b69b..dbda8e91ed8 100644 --- a/superset-frontend/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/NumericCell.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import NumericCell, { CurrencyCode, LocaleCode, Style } from './index'; test('renders with French locale and Euro currency format', () => { diff --git a/superset-frontend/src/components/Table/cell-renderers/NumericCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/index.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/NumericCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/NumericCell/index.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/TimeCell/TimeCell.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/TimeCell.stories.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/TimeCell/TimeCell.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/TimeCell.stories.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx similarity index 96% rename from superset-frontend/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx index 30b8f2f67b2..811a7b7d2fb 100644 --- a/superset-frontend/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/TimeCell.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { TimeFormats } from '@superset-ui/core'; -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import TimeCell from '.'; const DATE = Date.parse('2022-01-01'); diff --git a/superset-frontend/src/components/Table/cell-renderers/TimeCell/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/index.tsx similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/TimeCell/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/TimeCell/index.tsx diff --git a/superset-frontend/src/components/Table/cell-renderers/fixtures.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/fixtures.ts similarity index 100% rename from superset-frontend/src/components/Table/cell-renderers/fixtures.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/cell-renderers/fixtures.ts diff --git a/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx similarity index 93% rename from superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx index 5e81b9fbcec..cd54635b064 100644 --- a/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx @@ -17,10 +17,8 @@ * under the License. */ import { useState } from 'react'; -import { css, useTheme } from '@superset-ui/core'; -import { Radio } from 'src/components/Radio'; -import { Icons } from 'src/components/Icons'; -import Popover from 'src/components/Popover'; +import { css, useTheme } from '../../..'; +import { Icons, Radio, Popover } from '../..'; export interface HeaderWithRadioGroupProps { headerTitle: string; diff --git a/superset-frontend/src/components/Table/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Table/index.tsx similarity index 99% rename from superset-frontend/src/components/Table/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Table/index.tsx index adc0d139c4b..945183d7bd7 100644 --- a/superset-frontend/src/components/Table/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/index.tsx @@ -22,7 +22,7 @@ import { Table as AntTable } from 'antd'; import { ColumnsType, TableProps as AntTableProps } from 'antd/es/table'; import { PaginationProps } from 'antd/es/pagination'; import { t, useTheme, logging, styled } from '@superset-ui/core'; -import { Loading } from 'src/components'; +import { Loading } from '@superset-ui/core/components'; import { RowSelectionType } from 'antd/es/table/interface'; import InteractiveTableUtils from './utils/InteractiveTableUtils'; import VirtualTable, { VirtualTableProps } from './VirtualTable'; diff --git a/superset-frontend/src/components/Table/sorters.test.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/sorters.test.ts similarity index 100% rename from superset-frontend/src/components/Table/sorters.test.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/sorters.test.ts diff --git a/superset-frontend/src/components/Table/sorters.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/sorters.ts similarity index 100% rename from superset-frontend/src/components/Table/sorters.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/sorters.ts diff --git a/superset-frontend/src/components/Table/utils/InteractiveTableUtils.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.ts similarity index 99% rename from superset-frontend/src/components/Table/utils/InteractiveTableUtils.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.ts index 94977413e2c..021ef81ff30 100644 --- a/superset-frontend/src/components/Table/utils/InteractiveTableUtils.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.ts @@ -17,7 +17,7 @@ * under the License. */ import type { ColumnsType } from 'antd/es/table'; -import { SUPERSET_TABLE_COLUMN } from 'src/components/Table'; +import { SUPERSET_TABLE_COLUMN } from '..'; import { withinRange } from './utils'; interface IInteractiveColumn extends HTMLElement { diff --git a/superset-frontend/src/components/Table/utils/utils.test.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/utils/utils.test.ts similarity index 97% rename from superset-frontend/src/components/Table/utils/utils.test.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/utils/utils.test.ts index 267817d3f7e..fc60729dc98 100644 --- a/superset-frontend/src/components/Table/utils/utils.test.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/Table/utils/utils.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { cleanup } from 'spec/helpers/testing-library'; +import { cleanup } from '@superset-ui/core/spec'; import { withinRange } from './utils'; // Add cleanup after each test diff --git a/superset-frontend/src/components/Table/utils/utils.ts b/superset-frontend/packages/superset-ui-core/src/components/Table/utils/utils.ts similarity index 100% rename from superset-frontend/src/components/Table/utils/utils.ts rename to superset-frontend/packages/superset-ui-core/src/components/Table/utils/utils.ts diff --git a/superset-frontend/src/components/TableCollection/TableCollection.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/TableCollection.test.tsx similarity index 97% rename from superset-frontend/src/components/TableCollection/TableCollection.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableCollection/TableCollection.test.tsx index 43880a65f11..52461fff66a 100644 --- a/superset-frontend/src/components/TableCollection/TableCollection.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/TableCollection.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import { renderHook } from '@testing-library/react-hooks'; import { TableInstance, useTable } from 'react-table'; import TableCollection from '.'; diff --git a/superset-frontend/src/components/TableCollection/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx similarity index 97% rename from superset-frontend/src/components/TableCollection/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx index 3e0fbe223ae..7ffae7ac207 100644 --- a/superset-frontend/src/components/TableCollection/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx @@ -26,7 +26,7 @@ import { TablePropGetter, } from 'react-table'; import { styled } from '@superset-ui/core'; -import { Table, TableSize } from 'src/components/Table'; +import { Table, TableSize } from '@superset-ui/core/components/Table'; import { TableRowSelection, SorterResult } from 'antd/es/table/interface'; import { mapColumns, mapRows } from './utils'; @@ -46,6 +46,7 @@ interface TableCollectionProps { toggleRowSelected?: (rowId: string, value: boolean) => void; toggleAllRowsSelected?: (value?: boolean) => void; sticky?: boolean; + size?: TableSize; } const StyledTable = styled(Table)` @@ -104,6 +105,7 @@ function TableCollection({ toggleAllRowsSelected, prepareRow, sticky, + size = TableSize.Middle, }: TableCollectionProps) { const mappedColumns = mapColumns( columns, @@ -141,7 +143,7 @@ function TableCollection({ sticky={sticky ?? false} columns={mappedColumns} data={mappedRows} - size={TableSize.Middle} + size={size} data-test="listview-table" pagination={false} tableLayout="auto" diff --git a/superset-frontend/src/components/TableCollection/utils.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/utils.tsx similarity index 76% rename from superset-frontend/src/components/TableCollection/utils.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableCollection/utils.tsx index 7859d30e197..165c5e0186a 100644 --- a/superset-frontend/src/components/TableCollection/utils.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/utils.tsx @@ -19,11 +19,21 @@ /** * This file contains utility functions for mapping columns and rows. - * These functions act as a compatibility layer between Ant Design Table and react-table. + * These functions act as a compatibility layer between Ant Design Table and react-table. */ import { ReactNode } from 'react'; -import { ColumnInstance, HeaderGroup, Row, CellValue } from 'react-table'; +import { + CellValue, + Row, + ColumnInstance as RTColumnInstance, + HeaderGroup as RTHeaderGroup, + UseSortByColumnOptions, + UseSortByColumnProps, + UseResizeColumnsColumnOptions, + UseResizeColumnsColumnProps, +} from 'react-table'; + import { SortOrder } from '../Table'; type TableSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; @@ -39,8 +49,22 @@ const COLUMN_SIZE_MAP: Record = { xxl: 200, }; +type EnhancedColumnInstance = RTColumnInstance & + Partial> & + Partial> & + Partial> & + Partial> & { + hidden?: boolean; + size?: keyof typeof COLUMN_SIZE_MAP; + }; + +type EnhancedHeaderGroup = RTHeaderGroup & { + isSorted?: boolean; + isSortedDesc?: boolean; +}; + function getSortingInfo( - headerGroups: HeaderGroup[], + headerGroups: EnhancedHeaderGroup[], headerId: string, ): { isSorted: boolean; @@ -59,8 +83,8 @@ function getSortingInfo( } export function mapColumns( - columns: ColumnInstance[], - headerGroups: HeaderGroup[], + columns: EnhancedColumnInstance[], + headerGroups: EnhancedHeaderGroup[], columnsForWrapText?: string[], ) { return columns.map(column => { @@ -87,7 +111,7 @@ export function mapColumns( }: { value: CellValue; row: { original: Row; id: string }; - column: ColumnInstance; + column: RTColumnInstance; }) => ReactNode; return cellRenderer({ diff --git a/superset-frontend/src/components/TableView/TableView.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.stories.tsx similarity index 97% rename from superset-frontend/src/components/TableView/TableView.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.stories.tsx index fb5cf5fbf3a..08c131060e1 100644 --- a/superset-frontend/src/components/TableView/TableView.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.stories.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import TableView, { TableViewProps, EmptyWrapperType } from '.'; +import { TableView, TableViewProps, EmptyWrapperType } from '.'; export default { title: 'Components/TableView', diff --git a/superset-frontend/src/components/TableView/TableView.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.test.tsx similarity index 93% rename from superset-frontend/src/components/TableView/TableView.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.test.tsx index f51edc5de87..228ba4dbe34 100644 --- a/superset-frontend/src/components/TableView/TableView.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.test.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; -import TableView, { TableViewProps } from '.'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; +import { TableView, TableViewProps } from '.'; const mockedProps: TableViewProps = { columns: [ @@ -116,19 +116,19 @@ test('should NOT render the pagination when fewer rows than page size', () => { expect(screen.queryByRole('navigation')).not.toBeInTheDocument(); }); -test('should change page when « and » buttons are clicked', () => { +test('should change page when « and » buttons are clicked', async () => { render(); const nextBtn = screen.getByText('»'); const prevBtn = screen.getByText('«'); - userEvent.click(nextBtn); + await userEvent.click(nextBtn); expect(screen.getAllByRole('cell')).toHaveLength(3); expect(screen.getByText('321')).toBeInTheDocument(); expect(screen.getByText('10')).toBeInTheDocument(); expect(screen.getByText('Kate')).toBeInTheDocument(); expect(screen.queryByText('Emily')).not.toBeInTheDocument(); - userEvent.click(prevBtn); + await userEvent.click(prevBtn); expect(screen.getAllByRole('cell')).toHaveLength(3); expect(screen.getByText('123')).toBeInTheDocument(); expect(screen.getByText('27')).toBeInTheDocument(); @@ -136,12 +136,12 @@ test('should change page when « and » buttons are clicked', () => { expect(screen.queryByText('Kate')).not.toBeInTheDocument(); }); -test('should sort by age', () => { +test('should sort by age', async () => { render(); - userEvent.click(screen.getAllByTestId('sort-header')[1]); + await userEvent.click(screen.getAllByTestId('sort-header')[1]); expect(screen.getAllByTestId('table-row-cell')[1]).toHaveTextContent('10'); - userEvent.click(screen.getAllByTestId('sort-header')[1]); + await userEvent.click(screen.getAllByTestId('sort-header')[1]); expect(screen.getAllByTestId('table-row-cell')[1]).toHaveTextContent('27'); }); diff --git a/superset-frontend/src/components/TableView/TableView.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.tsx similarity index 94% rename from superset-frontend/src/components/TableView/TableView.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.tsx index c9ffbb93eb4..ce99de46492 100644 --- a/superset-frontend/src/components/TableView/TableView.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableView/TableView.tsx @@ -20,9 +20,10 @@ import { memo, useEffect, useRef } from 'react'; import { isEqual } from 'lodash'; import { styled, t } from '@superset-ui/core'; import { useFilters, usePagination, useSortBy, useTable } from 'react-table'; -import { Empty } from 'src/components'; -import Pagination from 'src/components/Pagination'; -import TableCollection from 'src/components/TableCollection'; +import { Empty } from '@superset-ui/core/components'; +import Pagination from '@superset-ui/core/components/Pagination'; +import TableCollection from '@superset-ui/core/components/TableCollection'; +import { TableSize } from '@superset-ui/core/components/Table'; import { SortByType, ServerPagination } from './types'; const DEFAULT_PAGE_SIZE = 10; @@ -52,6 +53,7 @@ export interface TableViewProps { scrollTopOnPagination?: boolean; small?: boolean; columnsForWrapText?: string[]; + size?: TableSize; } const EmptyWrapper = styled.div` @@ -117,7 +119,7 @@ const PaginationStyles = styled.div<{ } `; -const TableView = ({ +const RawTableView = ({ columns, data, pageSize: initialPageSize, @@ -133,6 +135,7 @@ const TableView = ({ columnsForWrapText, onServerPagination = () => {}, scrollTopOnPagination = false, + size = TableSize.Middle, ...props }: TableViewProps) => { const initialState = { @@ -219,6 +222,7 @@ const TableView = ({ columns={columns} loading={loading} setSortBy={setSortBy} + size={size} columnsForWrapText={columnsForWrapText} /> {isEmpty && ( @@ -262,4 +266,4 @@ const TableView = ({ ); }; -export default memo(TableView); +export const TableView = memo(RawTableView); diff --git a/superset-frontend/src/components/TableView/index.ts b/superset-frontend/packages/superset-ui-core/src/components/TableView/index.ts similarity index 95% rename from superset-frontend/src/components/TableView/index.ts rename to superset-frontend/packages/superset-ui-core/src/components/TableView/index.ts index c1746ed7773..0ff8aafc024 100644 --- a/superset-frontend/src/components/TableView/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/TableView/index.ts @@ -17,4 +17,3 @@ * under the License. */ export * from './TableView'; -export { default } from './TableView'; diff --git a/superset-frontend/src/components/TableView/types.ts b/superset-frontend/packages/superset-ui-core/src/components/TableView/types.ts similarity index 100% rename from superset-frontend/src/components/TableView/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/TableView/types.ts diff --git a/superset-frontend/src/components/Tabs/Tabs.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tabs/Tabs.stories.tsx similarity index 100% rename from superset-frontend/src/components/Tabs/Tabs.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tabs/Tabs.stories.tsx diff --git a/superset-frontend/src/components/Tabs/Tabs.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tabs/Tabs.tsx similarity index 98% rename from superset-frontend/src/components/Tabs/Tabs.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tabs/Tabs.tsx index b5fd652e091..2688e0b5ed7 100644 --- a/superset-frontend/src/components/Tabs/Tabs.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Tabs/Tabs.tsx @@ -20,7 +20,7 @@ import { css, styled, useTheme } from '@superset-ui/core'; // eslint-disable-next-line no-restricted-imports import { Tabs as AntdTabs, TabsProps as AntdTabsProps } from 'antd'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; export interface TabsProps extends AntdTabsProps { allowOverflow?: boolean; diff --git a/superset-frontend/src/components/Tabs/index.ts b/superset-frontend/packages/superset-ui-core/src/components/Tabs/index.ts similarity index 100% rename from superset-frontend/src/components/Tabs/index.ts rename to superset-frontend/packages/superset-ui-core/src/components/Tabs/index.ts diff --git a/superset-frontend/packages/superset-ui-core/src/components/Tag/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tag/index.tsx new file mode 100644 index 00000000000..f9b7884464a --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/components/Tag/index.tsx @@ -0,0 +1,19 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export { Tag } from 'antd'; diff --git a/superset-frontend/src/components/TelemetryPixel/TelemetryPixel.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TelemetryPixel/TelemetryPixel.test.tsx similarity index 96% rename from superset-frontend/src/components/TelemetryPixel/TelemetryPixel.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TelemetryPixel/TelemetryPixel.test.tsx index 089c09140e8..7d12a612d7c 100644 --- a/superset-frontend/src/components/TelemetryPixel/TelemetryPixel.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TelemetryPixel/TelemetryPixel.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render } from 'spec/helpers/testing-library'; +import { render } from '@superset-ui/core/spec'; import TelemetryPixel from '.'; const OLD_ENV = process.env; diff --git a/superset-frontend/src/components/TelemetryPixel/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TelemetryPixel/index.tsx similarity index 100% rename from superset-frontend/src/components/TelemetryPixel/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TelemetryPixel/index.tsx diff --git a/superset-frontend/src/components/ThemeEditor/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx similarity index 97% rename from superset-frontend/src/components/ThemeEditor/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx index e14cb25fa94..344da2d765e 100644 --- a/superset-frontend/src/components/ThemeEditor/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx @@ -17,7 +17,7 @@ * under the License. */ import { Modal, Tooltip, Flex, Select } from 'antd'; -import { Button, JsonEditor } from 'src/components'; +import { Button, JsonEditor } from '@superset-ui/core/components'; import { themeObject, exampleThemes, @@ -25,7 +25,7 @@ import { SupersetTheme, } from '@superset-ui/core'; import { useState } from 'react'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; interface ThemeEditorProps { initialTheme?: SupersetTheme; diff --git a/superset-frontend/src/components/Timer/Timer.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.stories.tsx similarity index 94% rename from superset-frontend/src/components/Timer/Timer.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.stories.tsx index 3dd230944fb..e64567a100b 100644 --- a/superset-frontend/src/components/Timer/Timer.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.stories.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { extendedDayjs } from 'src/utils/dates'; -import Timer, { TimerProps } from './index'; +import { extendedDayjs } from '../../utils/dates'; +import { Timer, TimerProps } from '.'; export default { title: 'Components/Timer', diff --git a/superset-frontend/src/components/Timer/Timer.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.test.tsx similarity index 91% rename from superset-frontend/src/components/Timer/Timer.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.test.tsx index 3e396558514..61d6a5458d5 100644 --- a/superset-frontend/src/components/Timer/Timer.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Timer/Timer.test.tsx @@ -19,9 +19,15 @@ * specific language governing permissions and limitations * under the License. */ -import { render, sleep, waitFor } from 'spec/helpers/testing-library'; -import Timer, { TimerProps } from 'src/components/Timer'; -import { now } from 'src/utils/dates'; +import { render, waitFor } from '@superset-ui/core/spec'; +import { Timer, TimerProps } from '.'; +import { now } from '../../utils/dates'; + +function sleep(time: number) { + return new Promise(resolve => { + setTimeout(resolve, time); + }); +} function parseTime(text?: string | null) { return !!text && Number(text.replace(/:/g, '')); diff --git a/superset-frontend/src/components/Timer/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Timer/index.tsx similarity index 87% rename from superset-frontend/src/components/Timer/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Timer/index.tsx index b58f5ebd7e9..0eaa8e456b6 100644 --- a/superset-frontend/src/components/Timer/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Timer/index.tsx @@ -17,12 +17,9 @@ * under the License. */ import { useEffect, useRef, useState } from 'react'; -import { useTheme } from '@superset-ui/core'; -import type { LabelType } from 'src/components/Label/types'; -import { Label } from 'src/components'; -import { Icons } from 'src/components/Icons'; - -import { now, fDuration } from 'src/utils/dates'; +import { now, fDuration } from '../../utils/dates'; +import { useTheme } from '../..'; +import { Label, Icons, type LabelType } from '..'; export interface TimerProps { endTime?: number; @@ -31,7 +28,7 @@ export interface TimerProps { status?: LabelType; } -export default function Timer({ +export function Timer({ endTime, isRunning, startTime, diff --git a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx similarity index 94% rename from superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx index 98d823188ad..21fa1fc9abf 100644 --- a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx @@ -18,12 +18,7 @@ */ import { FC } from 'react'; -import { - render, - waitFor, - screen, - userEvent, -} from 'spec/helpers/testing-library'; +import { render, waitFor, screen, userEvent } from '@superset-ui/core/spec'; import type { TimezoneSelectorProps } from './index'; const loadComponent = (mockCurrentTime?: string) => { @@ -52,7 +47,7 @@ test('render timezones in correct order for daylight saving time', async () => { ); const searchInput = screen.getByRole('combobox'); - userEvent.click(searchInput); + await userEvent.click(searchInput); const options = await waitFor(() => document.querySelectorAll('.ant-select-item-option-content'), diff --git a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.stories.tsx similarity index 100% rename from superset-frontend/src/components/TimezoneSelector/TimezoneSelector.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.stories.tsx diff --git a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.test.tsx similarity index 94% rename from superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.test.tsx index 35c3448f9d1..25df21eef2c 100644 --- a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/TimezoneSelector.test.tsx @@ -17,13 +17,8 @@ * under the License. */ import { FC } from 'react'; -import { extendedDayjs } from 'src/utils/dates'; -import { - render, - screen, - userEvent, - waitFor, -} from 'spec/helpers/testing-library'; +import { render, screen, userEvent, waitFor } from '@superset-ui/core/spec'; +import { extendedDayjs } from '../../utils/dates'; import type { TimezoneSelectorProps } from './index'; const loadComponent = (mockCurrentTime?: string) => { @@ -40,9 +35,9 @@ const loadComponent = (mockCurrentTime?: string) => { const getSelectOptions = () => waitFor(() => document.querySelectorAll('.ant-select-item-option-content')); -const openSelectMenu = () => { +const openSelectMenu = async () => { const searchInput = screen.getByRole('combobox'); - userEvent.click(searchInput); + await userEvent.click(searchInput); }; jest.spyOn(extendedDayjs.tz, 'guess').mockReturnValue('America/New_York'); @@ -111,10 +106,10 @@ test('can select a timezone values and returns canonical timezone name', async ( const searchInput = screen.getByRole('combobox'); // search for mountain time - userEvent.type(searchInput, 'mou'); + await userEvent.type(searchInput, 'mou'); const findTitle = 'GMT -07:00 (Mountain Standard Time)'; const selectOption = await screen.findByTitle(findTitle); - userEvent.click(selectOption); + await userEvent.click(selectOption); expect(onTimezoneChange).toHaveBeenCalledTimes(1); expect(onTimezoneChange).toHaveBeenLastCalledWith('America/Boise'); }); diff --git a/superset-frontend/src/components/TimezoneSelector/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/index.tsx similarity index 97% rename from superset-frontend/src/components/TimezoneSelector/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/index.tsx index 9d6ea4479c1..3dd0ede01c2 100644 --- a/superset-frontend/src/components/TimezoneSelector/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TimezoneSelector/index.tsx @@ -19,8 +19,8 @@ import { useEffect, useMemo } from 'react'; import { t } from '@superset-ui/core'; -import { Select } from 'src/components'; -import { isDST, extendedDayjs } from 'src/utils/dates'; +import { Select } from '@superset-ui/core/components'; +import { isDST, extendedDayjs } from '../../utils/dates'; const DEFAULT_TIMEZONE = { name: 'GMT Standard Time', diff --git a/superset-frontend/src/components/Tooltip/Tooltip.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/Tooltip.stories.tsx similarity index 100% rename from superset-frontend/src/components/Tooltip/Tooltip.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tooltip/Tooltip.stories.tsx diff --git a/superset-frontend/src/components/Tooltip/Tooltip.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/Tooltip.test.tsx similarity index 84% rename from superset-frontend/src/components/Tooltip/Tooltip.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tooltip/Tooltip.test.tsx index 1d46066f3dc..6e0c5f9a6fd 100644 --- a/superset-frontend/src/components/Tooltip/Tooltip.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/Tooltip.test.tsx @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, userEvent } from 'spec/helpers/testing-library'; -import { Button } from 'src/components'; -import { Icons } from 'src/components/Icons'; -import { Tooltip } from '.'; +import { render, screen, userEvent } from '@superset-ui/core/spec'; +import { Button, Icons, Tooltip } from '..'; test('starts hidden with default props', () => { render( @@ -36,7 +34,7 @@ test('renders on hover', async () => { , ); - userEvent.hover(screen.getByRole('button')); + await userEvent.hover(screen.getByRole('button')); expect(await screen.findByRole('tooltip')).toBeInTheDocument(); }); @@ -46,6 +44,6 @@ test('renders with icon child', async () => { Hover me , ); - userEvent.hover(screen.getByRole('img')); + await userEvent.hover(screen.getByRole('img')); expect(await screen.findByRole('tooltip')).toBeInTheDocument(); }); diff --git a/superset-frontend/src/components/Tooltip/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/index.tsx similarity index 90% rename from superset-frontend/src/components/Tooltip/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tooltip/index.tsx index 6d2e8d71eda..ee8844a540e 100644 --- a/superset-frontend/src/components/Tooltip/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/index.tsx @@ -17,7 +17,8 @@ * under the License. */ import { Tooltip as AntdTooltip } from 'antd'; -import type { TooltipProps } from './types'; + +import type { TooltipProps, TooltipPlacement } from './types'; export const Tooltip = ({ overlayStyle, ...props }: TooltipProps) => ( ( {...props} /> ); - -export type { TooltipProps }; +export type { TooltipProps, TooltipPlacement }; diff --git a/superset-frontend/src/components/Tooltip/types.ts b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/types.ts similarity index 87% rename from superset-frontend/src/components/Tooltip/types.ts rename to superset-frontend/packages/superset-ui-core/src/components/Tooltip/types.ts index dbb0f2264c7..ab0f4875f21 100644 --- a/superset-frontend/src/components/Tooltip/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/Tooltip/types.ts @@ -16,7 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -export type { TooltipProps } from 'antd/es/tooltip'; +import { Tooltip } from 'antd'; + +export type TooltipProps = React.ComponentProps & { + overlayStyle?: React.CSSProperties; +}; export type TooltipPlacement = | 'top' diff --git a/superset-frontend/src/components/TooltipParagraph/TooltipParagraph.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/TooltipParagraph.stories.tsx similarity index 100% rename from superset-frontend/src/components/TooltipParagraph/TooltipParagraph.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/TooltipParagraph.stories.tsx diff --git a/superset-frontend/src/components/TooltipParagraph/TooltipParagraph.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/TooltipParagraph.test.tsx similarity index 92% rename from superset-frontend/src/components/TooltipParagraph/TooltipParagraph.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/TooltipParagraph.test.tsx index 4d3b08c11db..e42bab3d7b9 100644 --- a/superset-frontend/src/components/TooltipParagraph/TooltipParagraph.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/TooltipParagraph.test.tsx @@ -16,12 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - render, - screen, - userEvent, - waitFor, -} from 'spec/helpers/testing-library'; +import { render, screen, userEvent, waitFor } from '@superset-ui/core/spec'; import TooltipParagraph from '.'; test('starts hidden with default props', () => { @@ -38,7 +33,7 @@ test('not render on hover when not truncated', async () => {
, ); - userEvent.hover(screen.getByTestId('test-text')); + await userEvent.hover(screen.getByTestId('test-text')); // Wait a moment for any potential tooltip to appear await new Promise(resolve => setTimeout(resolve, 100)); @@ -63,7 +58,7 @@ test('render on hover when truncated', async () => { expect(ellipsisElement).toBeInTheDocument(); // Hover over the text - userEvent.hover(screen.getByTestId('test-text')); + await userEvent.hover(screen.getByTestId('test-text')); // In Ant Design v5, we can check if the aria-describedby attribute is present // which indicates the tooltip functionality is active diff --git a/superset-frontend/src/components/TooltipParagraph/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/index.tsx similarity index 93% rename from superset-frontend/src/components/TooltipParagraph/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/index.tsx index 5e767695459..3355ae22d8a 100644 --- a/superset-frontend/src/components/TooltipParagraph/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TooltipParagraph/index.tsx @@ -17,7 +17,11 @@ * under the License. */ import { useState, FC } from 'react'; -import { ParagraphProps, Typography, Tooltip } from 'src/components'; +import { + ParagraphProps, + Typography, + Tooltip, +} from '@superset-ui/core/components'; const TooltipParagraph: FC = ({ children, diff --git a/superset-frontend/src/components/Tree/Tree.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.stories.tsx similarity index 99% rename from superset-frontend/src/components/Tree/Tree.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.stories.tsx index e1190f089bd..84aa0d614db 100644 --- a/superset-frontend/src/components/Tree/Tree.stories.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.stories.tsx @@ -17,7 +17,7 @@ * under the License. */ import { Meta, StoryObj } from '@storybook/react'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import Tree, { TreeProps, type TreeDataNode } from './index'; const meta = { diff --git a/superset-frontend/src/components/Tree/Tree.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.test.tsx similarity index 93% rename from superset-frontend/src/components/Tree/Tree.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.test.tsx index ab61b5bd8df..1075bb53b65 100644 --- a/superset-frontend/src/components/Tree/Tree.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Tree/Tree.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import Tree from './index'; @@ -32,7 +32,7 @@ const treeData = [ ]; describe('Tree Component', () => { - test('expands and collapses parent node', async () => { + it('expands and collapses parent node', async () => { render(); expect(screen.queryByText('Child 1')).not.toBeInTheDocument(); diff --git a/superset-frontend/src/components/Tree/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Tree/index.tsx similarity index 100% rename from superset-frontend/src/components/Tree/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Tree/index.tsx diff --git a/superset-frontend/src/components/TreeSelect/TreeSelect.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/TreeSelect/TreeSelect.stories.tsx similarity index 100% rename from superset-frontend/src/components/TreeSelect/TreeSelect.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TreeSelect/TreeSelect.stories.tsx diff --git a/superset-frontend/src/components/TreeSelect/TreeSelect.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/TreeSelect/TreeSelect.test.tsx similarity index 96% rename from superset-frontend/src/components/TreeSelect/TreeSelect.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TreeSelect/TreeSelect.test.tsx index ce01d0affef..86077691abe 100644 --- a/superset-frontend/src/components/TreeSelect/TreeSelect.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TreeSelect/TreeSelect.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { render, fireEvent, screen } from '@testing-library/react'; +import { render, fireEvent, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { TreeSelect } from '.'; diff --git a/superset-frontend/src/components/TreeSelect/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TreeSelect/index.tsx similarity index 100% rename from superset-frontend/src/components/TreeSelect/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TreeSelect/index.tsx diff --git a/superset-frontend/src/components/TruncatedList/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TruncatedList/index.tsx similarity index 98% rename from superset-frontend/src/components/TruncatedList/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/TruncatedList/index.tsx index fecaca4a783..0348d064ccd 100644 --- a/superset-frontend/src/components/TruncatedList/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TruncatedList/index.tsx @@ -20,7 +20,7 @@ import { ReactNode, Key, useMemo } from 'react'; import { styled, t, useTruncation } from '@superset-ui/core'; -import { Tooltip } from 'src/components'; +import { Tooltip } from '@superset-ui/core/components'; export type TruncatedListProps = { /** diff --git a/superset-frontend/src/components/Typography/Typography.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Typography/Typography.stories.tsx similarity index 100% rename from superset-frontend/src/components/Typography/Typography.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Typography/Typography.stories.tsx diff --git a/superset-frontend/src/components/Typography/Typography.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Typography/Typography.test.tsx similarity index 86% rename from superset-frontend/src/components/Typography/Typography.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Typography/Typography.test.tsx index 8aaac2987ad..5382c87bdc9 100644 --- a/superset-frontend/src/components/Typography/Typography.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Typography/Typography.test.tsx @@ -16,28 +16,28 @@ * specific language governing permissions and limitations * under the License. */ -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen } from '@superset-ui/core/spec'; import '@testing-library/jest-dom'; import { Typography } from '.'; describe('Typography Component', () => { - test('renders Text component', () => { + it('renders Text component', () => { render(Text Content); expect(screen.getByText('Text Content')).toBeInTheDocument(); }); - test('renders Title component', () => { + it('renders Title component', () => { render(Title Content); expect(screen.getByText('Title Content')).toBeInTheDocument(); expect(screen.getByRole('heading', { level: 2 })).toBeInTheDocument(); }); - test('renders Paragraph component', () => { + it('renders Paragraph component', () => { render(Paragraph Content); expect(screen.getByText('Paragraph Content')).toBeInTheDocument(); }); - test('renders Link component', () => { + it('renders Link component', () => { render( Link Content @@ -48,19 +48,19 @@ describe('Typography Component', () => { expect(link).toHaveAttribute('href', 'https://example.com'); }); - test('renders strong text', () => { + it('renders strong text', () => { render(Strong Text); expect(screen.getByText('Strong Text')).toHaveStyle('font-weight: 600'); }); - test('renders underlined text', () => { + it('renders underlined text', () => { render(Underlined Text); expect(screen.getByText('Underlined Text')).toHaveStyle( 'text-decoration: underline', ); }); - test('renders disabled text', () => { + it('renders disabled text', () => { render(Disabled Text); expect(screen.getByText('Disabled Text')).toHaveClass( 'ant-typography-disabled', diff --git a/superset-frontend/src/components/Typography/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Typography/index.tsx similarity index 100% rename from superset-frontend/src/components/Typography/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Typography/index.tsx diff --git a/superset-frontend/src/components/Upload/Upload.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/Upload/Upload.stories.tsx similarity index 100% rename from superset-frontend/src/components/Upload/Upload.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Upload/Upload.stories.tsx diff --git a/superset-frontend/src/components/Upload/Upload.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Upload/Upload.test.tsx similarity index 87% rename from superset-frontend/src/components/Upload/Upload.test.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Upload/Upload.test.tsx index 9964c7901d8..fb0f08ed666 100644 --- a/superset-frontend/src/components/Upload/Upload.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Upload/Upload.test.tsx @@ -16,16 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { - render, - screen, - fireEvent, - waitFor, -} from 'spec/helpers/testing-library'; -import { Button, Upload } from 'src/components'; +import { render, screen, fireEvent, waitFor } from '@superset-ui/core/spec'; +import { Button, Upload } from '..'; describe('Upload Component', () => { - test('renders upload button and triggers file upload', async () => { + it('renders upload button and triggers file upload', async () => { const handleChange = jest.fn(); render( diff --git a/superset-frontend/src/components/Upload/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Upload/index.tsx similarity index 100% rename from superset-frontend/src/components/Upload/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/Upload/index.tsx diff --git a/superset-frontend/src/components/WarningIconWithTooltip/WarningIconWithTooltip.stories.tsx b/superset-frontend/packages/superset-ui-core/src/components/WarningIconWithTooltip/WarningIconWithTooltip.stories.tsx similarity index 100% rename from superset-frontend/src/components/WarningIconWithTooltip/WarningIconWithTooltip.stories.tsx rename to superset-frontend/packages/superset-ui-core/src/components/WarningIconWithTooltip/WarningIconWithTooltip.stories.tsx diff --git a/superset-frontend/src/components/WarningIconWithTooltip/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/WarningIconWithTooltip/index.tsx similarity index 87% rename from superset-frontend/src/components/WarningIconWithTooltip/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/WarningIconWithTooltip/index.tsx index 5732db72aaf..607eed6f7c0 100644 --- a/superset-frontend/src/components/WarningIconWithTooltip/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/WarningIconWithTooltip/index.tsx @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { useTheme, SafeMarkdown } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import type { IconType } from 'src/components/Icons/types'; -import { Tooltip } from '../Tooltip'; +import { useTheme } from '@superset-ui/core'; +import { Icons, type IconType, SafeMarkdown, Tooltip } from '..'; export interface WarningIconWithTooltipProps { warningMarkdown: string; diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80135!loading.gif b/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80135!loading.gif new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80342!loading.gif b/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80342!loading.gif new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80520!loading.gif b/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80520!loading.gif new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80903!loading.gif b/superset-frontend/packages/superset-ui-core/src/components/assets/images/.!80903!loading.gif new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/src/components/Select/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/assets/images/index.ts similarity index 81% rename from superset-frontend/src/components/Select/index.tsx rename to superset-frontend/packages/superset-ui-core/src/components/assets/images/index.ts index 004c22e7f24..c272c1186cd 100644 --- a/superset-frontend/src/components/Select/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/assets/images/index.ts @@ -16,10 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import Select from './Select'; -import AsyncSelect from './AsyncSelect'; +import Loading from './loading.gif'; -export { Select, AsyncSelect }; -export * from './types'; -export * from './styles'; -export * from './constants'; +export { Loading }; diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/images/loading.gif b/superset-frontend/packages/superset-ui-core/src/components/assets/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..d82fc5d9244e2b00a16c186bcee0503d71661683 GIT binary patch literal 79023 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 z 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 literal 0 HcmV?d00001 diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/index.ts b/superset-frontend/packages/superset-ui-core/src/components/assets/index.ts new file mode 100644 index 00000000000..c59dc1dc385 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/components/assets/index.ts @@ -0,0 +1,20 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export * from './svgs'; +export * from './images'; diff --git a/superset-frontend/src/assets/images/chart.svg b/superset-frontend/packages/superset-ui-core/src/components/assets/svgs/chart.svg similarity index 100% rename from superset-frontend/src/assets/images/chart.svg rename to superset-frontend/packages/superset-ui-core/src/components/assets/svgs/chart.svg diff --git a/superset-frontend/src/assets/images/icons/error.svg b/superset-frontend/packages/superset-ui-core/src/components/assets/svgs/error.svg similarity index 100% rename from superset-frontend/src/assets/images/icons/error.svg rename to superset-frontend/packages/superset-ui-core/src/components/assets/svgs/error.svg diff --git a/superset-frontend/packages/superset-ui-core/src/components/assets/svgs/index.ts b/superset-frontend/packages/superset-ui-core/src/components/assets/svgs/index.ts new file mode 100644 index 00000000000..e33811776f8 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/components/assets/svgs/index.ts @@ -0,0 +1,22 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import chart from './chart.svg'; +import error from './error.svg'; + +export { chart, error }; diff --git a/superset-frontend/src/components/atomic-design.png b/superset-frontend/packages/superset-ui-core/src/components/atomic-design.png similarity index 100% rename from superset-frontend/src/components/atomic-design.png rename to superset-frontend/packages/superset-ui-core/src/components/atomic-design.png diff --git a/superset-frontend/packages/superset-ui-core/src/components/constants.ts b/superset-frontend/packages/superset-ui-core/src/components/constants.ts index f252d725dd2..05b681c28f4 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/constants.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/constants.ts @@ -17,12 +17,12 @@ * under the License. */ -/** - * Faster debounce delay for inputs without expensive operation. - */ -export const FAST_DEBOUNCE = 250; +import { t } from '..'; -/** - * Slower debounce delay for inputs with expensive API calls. - */ -export const SLOW_DEBOUNCE = 500; +export const Constants = { + FAST_DEBOUNCE: 250, + SLOW_DEBOUNCE: 500, + NULL_DISPLAY: t('N/A'), + BOOL_TRUE_DISPLAY: t('True'), + BOOL_FALSE_DISPLAY: t('False'), +}; diff --git a/superset-frontend/packages/superset-ui-core/src/components/index.ts b/superset-frontend/packages/superset-ui-core/src/components/index.ts index 6fe666c0372..25e56804fe1 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/components/index.ts @@ -1,4 +1,4 @@ -/* +/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,5 +17,150 @@ * under the License. */ +/* + * Re-exporting of components in @superset-ui/core/components to facilitate + * their imports by other components. + * E.g. import { Select } from '@superset-ui/core/components', probably in the future from '@superset-ui/components' + */ +export * from './Input'; +export { AntdThemeProvider } from './AntdThemeProvider'; +export { + ConfirmStatusChange, + type ConfirmStatusChangeProps, +} from './ConfirmStatusChange'; +export { Alert, type AlertProps } from './Alert'; +export { CertifiedBadge } from './CertifiedBadge'; +export * from './Icons'; +export * from './Timer'; +export { + AsyncEsmComponent, + type PlaceholderProps as AsyncEsmPlaceholderProps, +} from './AsyncEsmComponent'; +export { + AsyncAceEditor, + CssEditor, + JsonEditor, + SQLEditor, + FullSQLEditor, + MarkdownEditor, + TextAreaEditor, + ConfigEditor, + type AsyncAceEditorProps, + type Editor, +} from './AsyncAceEditor'; +export { AutoComplete, type AutoCompleteProps } from './AutoComplete'; +export { + Avatar, + AvatarGroup, + type AvatarProps, + type AvatarGroupProps, +} from './Avatar'; +export { Badge, type BadgeProps } from './Badge'; +export { Button, type ButtonProps, type OnClickHandler } from './Button'; +export { ButtonGroup, type ButtonGroupProps } from './ButtonGroup'; +export { Breadcrumb, type BreadcrumbProps } from './Breadcrumb'; +export { CachedLabel, type CacheLabelProps } from './CachedLabel'; +export { Card } from './Card'; +export { + Checkbox, + type CheckboxProps, + type CheckboxChangeEvent, +} from './Checkbox'; +export { + Collapse, + type CollapseProps, + CollapseLabelInModal, + type CollapseLabelInModalProps, +} from './Collapse'; +export { CronPicker, type CronError } from './CronPicker'; +export * from './DatePicker'; +export { DeleteModal, type DeleteModalProps } from './DeleteModal'; +export { Divider, type DividerProps } from './Divider'; +export { + Dropdown, + MenuDotsDropdown, + NoAnimationDropdown, + type DropdownProps, + type NoAnimationDropdownProps, + type MenuDotsDropdownProps, +} from './Dropdown'; +export { DropdownButton, type DropdownButtonProps } from './DropdownButton'; +export { + DropdownContainer, + type DropdownItem, + type DropdownRef, +} from './DropdownContainer'; +export { + DynamicEditableTitle, + type DynamicEditableTitleProps, +} from './DynamicEditableTitle'; +export { EditableTitle, type EditableTitleProps } from './EditableTitle'; +export { EmptyState, type EmptyStateProps } from './EmptyState'; +export { Empty, type EmptyProps } from './EmptyState/Empty'; +export { FaveStar, type FaveStarProps } from './FaveStar'; +export { + Modal, + FormModal, + StyledModal, + type ModalProps, + type FormModalProps, +} from './Modal'; +export * from './ModalTrigger'; +export { Flex, type FlexProps } from './Flex'; +export { + Form, + FormItem, + FormLabel, + LabeledErrorBoundInput, + type FormInstance, + type FormProps, + type FormItemProps, +} from './Form'; +export { Grid, Row, Col, type RowProps, type ColProps } from './Grid'; +export { IconButton, type IconButtonProps } from './IconButton'; +export * from './Tooltip'; +export { Tooltip as RawAntdTooltip } from 'antd'; +export { IconTooltip, type IconTooltipProps } from './IconTooltip'; +export { InfoTooltip, type InfoTooltipProps } from './InfoTooltip'; +export { + Label, + DatasetTypeLabel, + PublishedLabel, + type LabelType, +} from './Label'; +export { LastUpdated, type LastUpdatedProps } from './LastUpdated'; +export { Layout, type LayoutProps, type SiderProps } from './Layout'; +export { List, type ListProps, type ListItemProps } from './List'; +export { + ListViewCard, + ImageLoader, + type ListViewCardProps, +} from './ListViewCard'; +export { Loading, type LoadingProps } from './Loading'; + +export { Skeleton, type SkeletonProps } from './Skeleton'; + +export { Switch, type SwitchProps } from './Switch'; + +export { TreeSelect, type TreeSelectProps } from './TreeSelect'; + +export { + Typography, + type TypographyProps, + type ParagraphProps, +} from './Typography'; + +export { Image, type ImageProps } from './Image'; +export { Upload, type UploadFile, type UploadChangeParam } from './Upload'; +// Add these to your index.ts +export * from './Menu'; +export * from './Popover'; +export * from './Radio'; +export * from './SafeMarkdown/SafeMarkdown'; +export * from './Select'; +export * from './Space'; +export * from './Steps'; +export * from './Table'; +export * from './TableView'; +export * from './Tag'; export * from './constants'; -export { default as SafeMarkdown } from './SafeMarkdown'; diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts index 99e9b518433..ceb5d08c90e 100644 --- a/superset-frontend/packages/superset-ui-core/src/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/index.ts @@ -32,7 +32,6 @@ export * from './theme'; export * from './validator'; export * from './chart'; export * from './chart-composition'; -export * from './components'; export * from './math-expression'; export * from './ui-overrides'; export * from './hooks'; diff --git a/superset-frontend/packages/superset-ui-core/src/query/api/v1/types.ts b/superset-frontend/packages/superset-ui-core/src/query/api/v1/types.ts index 06d1419e747..984eb52e5e6 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/api/v1/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/api/v1/types.ts @@ -43,7 +43,7 @@ export interface SupersetApiRequestOptions { * Superset API error types. * Ref: https://github.com/apache/incubator-superset/blob/318e5347bc6f88119725775baa4ab9a398a6f0b0/superset/errors.py#L24 * - * TODO: migrate superset-frontend/src/components/ErrorMessage/types.ts over + * TODO: migrate superset-frontend/@superset-ui/core/components/ErrorMessage/types.ts over */ export enum SupersetApiErrorType { // Generic unknown error diff --git a/superset-frontend/packages/superset-ui-core/src/spec/index.tsx b/superset-frontend/packages/superset-ui-core/src/spec/index.tsx new file mode 100644 index 00000000000..da7632b6954 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/spec/index.tsx @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import userEvent from '@testing-library/user-event'; +import { ReactElement } from 'react'; +import { render, RenderOptions } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { themeObject } from '@superset-ui/core'; + +// Define the wrapper component outside +const AllTheProviders = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +// Follow the exact pattern from RTL docs +const customRender = ( + ui: ReactElement, + options?: Omit, +) => render(ui, { wrapper: AllTheProviders, ...options }); + +export { + createEvent, + fireEvent, + screen, + waitFor, + cleanup, + within, +} from '@testing-library/react'; +export { customRender as render, userEvent }; diff --git a/superset-frontend/src/utils/dates.test.ts b/superset-frontend/packages/superset-ui-core/src/utils/dates.test.ts similarity index 99% rename from superset-frontend/src/utils/dates.test.ts rename to superset-frontend/packages/superset-ui-core/src/utils/dates.test.ts index 53d4cef846e..7395bcb5884 100644 --- a/superset-frontend/src/utils/dates.test.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/dates.test.ts @@ -23,7 +23,7 @@ import { epochTimeXDaysAgo, epochTimeXYearsAgo, extendedDayjs, -} from 'src/utils/dates'; +} from './dates'; describe('extendedDayjs', () => { it('returns dayjs object with extended methods', () => { diff --git a/superset-frontend/src/utils/dates.ts b/superset-frontend/packages/superset-ui-core/src/utils/dates.ts similarity index 100% rename from superset-frontend/src/utils/dates.ts rename to superset-frontend/packages/superset-ui-core/src/utils/dates.ts diff --git a/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx b/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx index 3f38e8c9c16..12a0a4f9f5a 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx +++ b/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx @@ -27,7 +27,7 @@ import { } from './html'; describe('sanitizeHtml', () => { - test('should sanitize the HTML string', () => { + it('should sanitize the HTML string', () => { const htmlString = ''; const sanitizedString = sanitizeHtml(htmlString); expect(sanitizedString).not.toContain('script'); @@ -35,13 +35,13 @@ describe('sanitizeHtml', () => { }); describe('isProbablyHTML', () => { - test('should return true if the text contains HTML tags', () => { + it('should return true if the text contains HTML tags', () => { const htmlText = '
Some HTML content
'; const isHTML = isProbablyHTML(htmlText); expect(isHTML).toBe(true); }); - test('should return false if the text does not contain HTML tags', () => { + it('should return false if the text does not contain HTML tags', () => { const plainText = 'Just a plain text'; const isHTML = isProbablyHTML(plainText); expect(isHTML).toBe(false); @@ -52,13 +52,13 @@ describe('isProbablyHTML', () => { }); describe('sanitizeHtmlIfNeeded', () => { - test('should sanitize the HTML string if it contains HTML tags', () => { + it('should sanitize the HTML string if it contains HTML tags', () => { const htmlString = '
Some HTML content
'; const sanitizedString = sanitizeHtmlIfNeeded(htmlString); expect(sanitizedString).toEqual(htmlString); }); - test('should return the string as is if it does not contain HTML tags', () => { + it('should return the string as is if it does not contain HTML tags', () => { const plainText = 'Just a plain text'; const sanitizedString = sanitizeHtmlIfNeeded(plainText); expect(sanitizedString).toEqual(plainText); @@ -66,7 +66,7 @@ describe('sanitizeHtmlIfNeeded', () => { }); describe('safeHtmlSpan', () => { - test('should return a safe HTML span when the input is HTML', () => { + it('should return a safe HTML span when the input is HTML', () => { const htmlString = '
Some HTML content
'; const safeSpan = safeHtmlSpan(htmlString); expect(safeSpan).toEqual( @@ -77,7 +77,7 @@ describe('safeHtmlSpan', () => { ); }); - test('should return the input string as is when it is not HTML', () => { + it('should return the input string as is when it is not HTML', () => { const plainText = 'Just a plain text'; const result = safeHtmlSpan(plainText); expect(result).toEqual(plainText); @@ -85,31 +85,31 @@ describe('safeHtmlSpan', () => { }); describe('removeHTMLTags', () => { - test('should remove HTML tags from the string', () => { + it('should remove HTML tags from the string', () => { const input = '

Hello, World!

'; const output = removeHTMLTags(input); expect(output).toBe('Hello, World!'); }); - test('should return the same string when no HTML tags are present', () => { + it('should return the same string when no HTML tags are present', () => { const input = 'This is a plain text.'; const output = removeHTMLTags(input); expect(output).toBe('This is a plain text.'); }); - test('should remove nested HTML tags and return combined text content', () => { + it('should remove nested HTML tags and return combined text content', () => { const input = '

Title

Content

'; const output = removeHTMLTags(input); expect(output).toBe('TitleContent'); }); - test('should handle self-closing tags and return an empty string', () => { + it('should handle self-closing tags and return an empty string', () => { const input = 'Image'; const output = removeHTMLTags(input); expect(output).toBe(''); }); - test('should handle malformed HTML tags and remove only well-formed tags', () => { + it('should handle malformed HTML tags and remove only well-formed tags', () => { const input = '

Unclosed tag'; const output = removeHTMLTags(input); expect(output).toBe('Unclosed tag'); @@ -117,44 +117,44 @@ describe('removeHTMLTags', () => { }); describe('isJsonString', () => { - test('valid JSON object', () => { + it('valid JSON object', () => { const jsonString = '{"name": "John", "age": 30, "city": "New York"}'; expect(isJsonString(jsonString)).toBe(true); }); - test('valid JSON array', () => { + it('valid JSON array', () => { const jsonString = '[1, 2, 3, 4, 5]'; expect(isJsonString(jsonString)).toBe(true); }); - test('valid JSON string', () => { + it('valid JSON string', () => { const jsonString = '"Hello, world!"'; expect(isJsonString(jsonString)).toBe(true); }); - test('invalid JSON with syntax error', () => { + it('invalid JSON with syntax error', () => { const jsonString = '{"name": "John", "age": 30, "city": "New York"'; expect(isJsonString(jsonString)).toBe(false); }); - test('empty string', () => { + it('empty string', () => { const jsonString = ''; expect(isJsonString(jsonString)).toBe(false); }); - test('non-JSON string', () => { + it('non-JSON string', () => { const jsonString = '

Hello, World!

'; expect(isJsonString(jsonString)).toBe(false); }); - test('non-JSON formatted number', () => { + it('non-JSON formatted number', () => { const jsonString = '12345abc'; expect(isJsonString(jsonString)).toBe(false); }); }); describe('getParagraphContents', () => { - test('should return an object with keys for each paragraph tag', () => { + it('should return an object with keys for each paragraph tag', () => { const htmlString = '

First paragraph.

Second paragraph.

'; const result = getParagraphContents(htmlString); @@ -164,23 +164,23 @@ describe('getParagraphContents', () => { }); }); - test('should return null if the string is not HTML', () => { + it('should return null if the string is not HTML', () => { const nonHtmlString = 'Just a plain text string.'; expect(getParagraphContents(nonHtmlString)).toBeNull(); }); - test('should return null if there are no

tags in the HTML string', () => { + it('should return null if there are no

tags in the HTML string', () => { const htmlStringWithoutP = '

No paragraph here.
'; expect(getParagraphContents(htmlStringWithoutP)).toBeNull(); }); - test('should return an object with empty string for empty

tag', () => { + it('should return an object with empty string for empty

tag', () => { const htmlStringWithEmptyP = '

'; const result = getParagraphContents(htmlStringWithEmptyP); expect(result).toEqual({ p1: '' }); }); - test('should handle HTML strings with nested

tags correctly', () => { + it('should handle HTML strings with nested

tags correctly', () => { const htmlStringWithNestedP = '

First paragraph with nested content.

'; const result = getParagraphContents(htmlStringWithNestedP); diff --git a/superset-frontend/src/utils/rankedSearchCompare.test.ts b/superset-frontend/packages/superset-ui-core/src/utils/rankedSearchCompare.test.ts similarity index 100% rename from superset-frontend/src/utils/rankedSearchCompare.test.ts rename to superset-frontend/packages/superset-ui-core/src/utils/rankedSearchCompare.test.ts diff --git a/superset-frontend/src/utils/rankedSearchCompare.ts b/superset-frontend/packages/superset-ui-core/src/utils/rankedSearchCompare.ts similarity index 100% rename from superset-frontend/src/utils/rankedSearchCompare.ts rename to superset-frontend/packages/superset-ui-core/src/utils/rankedSearchCompare.ts diff --git a/superset-frontend/packages/superset-ui-core/test/chart-composition/ChartFrame.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart-composition/ChartFrame.test.tsx index 4125bc0161e..bb4ccd12ee4 100644 --- a/superset-frontend/packages/superset-ui-core/test/chart-composition/ChartFrame.test.tsx +++ b/superset-frontend/packages/superset-ui-core/test/chart-composition/ChartFrame.test.tsx @@ -37,7 +37,7 @@ type Props = { const renderChartFrame = (props: Props) => render(); -it('renders content that requires smaller space than frame', () => { +test('renders content that requires smaller space than frame', () => { const { getByText } = renderChartFrame({ width: 400, height: 400, @@ -52,7 +52,7 @@ it('renders content that requires smaller space than frame', () => { expect(getByText('400/400')).toBeInTheDocument(); }); -it('renders content without specifying content size', () => { +test('renders content without specifying content size', () => { const { getByText } = renderChartFrame({ width: 400, height: 400, @@ -65,7 +65,7 @@ it('renders content without specifying content size', () => { expect(getByText('400/400')).toBeInTheDocument(); }); -it('renders content that requires equivalent size to frame', () => { +test('renders content that requires equivalent size to frame', () => { const { getByText } = renderChartFrame({ width: 400, height: 400, @@ -80,7 +80,7 @@ it('renders content that requires equivalent size to frame', () => { expect(getByText('400/400')).toBeInTheDocument(); }); -it('renders content that requires space larger than frame', () => { +test('renders content that requires space larger than frame', () => { const { getByText, container } = renderChartFrame({ width: 400, height: 400, @@ -97,7 +97,7 @@ it('renders content that requires space larger than frame', () => { expect(containerDiv).toHaveStyle({ overflowX: 'auto', overflowY: 'auto' }); }); -it('renders content when width is larger than frame', () => { +test('renders content when width is larger than frame', () => { const { getByText, container } = renderChartFrame({ width: 400, height: 400, @@ -113,7 +113,7 @@ it('renders content when width is larger than frame', () => { expect(containerDiv).toHaveStyle({ overflowX: 'auto', overflowY: 'hidden' }); }); -it('renders content when height is larger than frame', () => { +test('renders content when height is larger than frame', () => { const { getByText, container } = renderChartFrame({ width: 400, height: 400, diff --git a/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts b/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts index 4b4c826923b..93d3e4a2ecc 100644 --- a/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { getOverrideHtmlSchema } from '../../src/components/SafeMarkdown'; +import { getOverrideHtmlSchema } from '../../src/components/SafeMarkdown/SafeMarkdown'; describe('getOverrideHtmlSchema', () => { it('should append the override items', () => { diff --git a/superset-frontend/packages/superset-ui-core/test/currency-format/CurrencyFormatter.test.ts b/superset-frontend/packages/superset-ui-core/test/currency-format/CurrencyFormatter.test.ts index 5172e3b0ed3..b731b1ba498 100644 --- a/superset-frontend/packages/superset-ui-core/test/currency-format/CurrencyFormatter.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/currency-format/CurrencyFormatter.test.ts @@ -23,7 +23,7 @@ import { NumberFormats, } from '@superset-ui/core'; -it('getCurrencySymbol', () => { +test('getCurrencySymbol', () => { expect( getCurrencySymbol({ symbol: 'PLN', symbolPosition: 'prefix' }), ).toEqual('PLN'); @@ -36,7 +36,7 @@ it('getCurrencySymbol', () => { ).toThrow(RangeError); }); -it('CurrencyFormatter object fields', () => { +test('CurrencyFormatter object fields', () => { const defaultCurrencyFormatter = new CurrencyFormatter({ currency: { symbol: 'USD', symbolPosition: 'prefix' }, }); @@ -60,7 +60,7 @@ it('CurrencyFormatter object fields', () => { }); }); -it('CurrencyFormatter:hasValidCurrency', () => { +test('CurrencyFormatter:hasValidCurrency', () => { const currencyFormatter = new CurrencyFormatter({ currency: { symbol: 'USD', symbolPosition: 'prefix' }, }); @@ -83,7 +83,7 @@ it('CurrencyFormatter:hasValidCurrency', () => { expect(currencyFormatterWithoutCurrency.hasValidCurrency()).toBe(false); }); -it('CurrencyFormatter:getNormalizedD3Format', () => { +test('CurrencyFormatter:getNormalizedD3Format', () => { const currencyFormatter = new CurrencyFormatter({ currency: { symbol: 'USD', symbolPosition: 'prefix' }, }); @@ -112,7 +112,7 @@ it('CurrencyFormatter:getNormalizedD3Format', () => { expect(currencyFormatter4.getNormalizedD3Format()).toEqual(',.1'); }); -it('CurrencyFormatter:format', () => { +test('CurrencyFormatter:format', () => { const VALUE = 56100057; const currencyFormatterWithPrefix = new CurrencyFormatter({ currency: { symbol: 'USD', symbolPosition: 'prefix' }, diff --git a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts index 12a644c062a..b3c68f7e71d 100644 --- a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts @@ -18,7 +18,7 @@ */ import * as uiCore from '@superset-ui/core'; -it('initializes feature flags', () => { +test('initializes feature flags', () => { Object.defineProperty(window, 'featureFlags', { value: undefined, }); @@ -26,7 +26,7 @@ it('initializes feature flags', () => { expect(window.featureFlags).toEqual({}); }); -it('initializes feature flags with predefined values', () => { +test('initializes feature flags with predefined values', () => { Object.defineProperty(window, 'featureFlags', { value: undefined, }); @@ -37,7 +37,7 @@ it('initializes feature flags with predefined values', () => { expect(window.featureFlags).toEqual(featureFlags); }); -it('does nothing if feature flags are already initialized', () => { +test('does nothing if feature flags are already initialized', () => { const featureFlags = { DRILL_BY: false }; Object.defineProperty(window, 'featureFlags', { value: featureFlags, @@ -46,7 +46,7 @@ it('does nothing if feature flags are already initialized', () => { expect(window.featureFlags).toEqual(featureFlags); }); -it('returns false and raises console error if feature flags have not been initialized', () => { +test('returns false and raises console error if feature flags have not been initialized', () => { const logging = jest.spyOn(uiCore.logging, 'error'); Object.defineProperty(window, 'featureFlags', { value: undefined, @@ -56,14 +56,14 @@ it('returns false and raises console error if feature flags have not been initia expect(logging).toHaveBeenCalledWith('Failed to query feature flag DRILL_BY'); }); -it('returns false for unset feature flag', () => { +test('returns false for unset feature flag', () => { Object.defineProperty(window, 'featureFlags', { value: {}, }); expect(uiCore.isFeatureEnabled(uiCore.FeatureFlag.DrillBy)).toEqual(false); }); -it('returns true for set feature flag', () => { +test('returns true for set feature flag', () => { Object.defineProperty(window, 'featureFlags', { value: { DRILL_BY: true, diff --git a/superset-frontend/packages/superset-ui-core/tsconfig.json b/superset-frontend/packages/superset-ui-core/tsconfig.json index d345ae88fc0..4e39d068d5f 100644 --- a/superset-frontend/packages/superset-ui-core/tsconfig.json +++ b/superset-frontend/packages/superset-ui-core/tsconfig.json @@ -1,18 +1,24 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { "declarationDir": "lib", "outDir": "lib", - "rootDir": "src" + "rootDir": "src", + "baseUrl": ".", + "paths": { + "src/*": ["./src/*"], + "@superset-ui/core": ["src"], + "@superset-ui/core/*": ["src/*"] + } }, "exclude": [ "lib", "test" ], - "extends": "../../tsconfig.json", "include": [ "src/**/*", - "types/**/*", - "../../types/**/*" + "spec/**/*", + "types/**/*" ], "references": [] } diff --git a/superset-frontend/src/types/ace-builds.d.ts b/superset-frontend/packages/superset-ui-core/types/ace-builds.d.ts similarity index 100% rename from superset-frontend/src/types/ace-builds.d.ts rename to superset-frontend/packages/superset-ui-core/types/ace-builds.d.ts diff --git a/superset-frontend/packages/superset-ui-core/types/assets.d.ts b/superset-frontend/packages/superset-ui-core/types/assets.d.ts new file mode 100644 index 00000000000..76f6dc1a771 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/types/assets.d.ts @@ -0,0 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +declare module '*.gif'; +declare module '*.svg'; +declare module '*.png'; diff --git a/superset-frontend/packages/superset-ui-core/types/brace.d.ts b/superset-frontend/packages/superset-ui-core/types/brace.d.ts new file mode 100644 index 00000000000..0b3770eebed --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/types/brace.d.ts @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +declare module 'brace/mode/sql'; +declare module 'brace/mode/markdown'; +declare module 'brace/mode/json'; +declare module 'brace/mode/css'; +declare module 'brace/mode/html'; +declare module 'brace/mode/yaml'; +declare module 'brace/mode/javascript'; +declare module 'brace/theme/textmate'; +declare module 'brace/theme/github'; +declare module 'brace/ext/language_tools'; +declare module 'brace/ext/searchbox'; diff --git a/superset-frontend/src/types/react-table-config.d.ts b/superset-frontend/packages/superset-ui-core/types/react-table-config.d.ts similarity index 100% rename from superset-frontend/src/types/react-table-config.d.ts rename to superset-frontend/packages/superset-ui-core/types/react-table-config.d.ts diff --git a/superset-frontend/packages/superset-ui-demo/package.json b/superset-frontend/packages/superset-ui-demo/package.json index 898ef2d900e..c099af9b7e5 100644 --- a/superset-frontend/packages/superset-ui-demo/package.json +++ b/superset-frontend/packages/superset-ui-demo/package.json @@ -63,7 +63,6 @@ "typescript": "^5.7.2" }, "peerDependencies": { - "antd": "^5.24.6", "@encodable/color": "=1.1.1", "@superset-ui/core": "*", "@superset-ui/legacy-plugin-chart-calendar": "*", diff --git a/superset-frontend/packages/superset-ui-demo/storybook/shared/components/VerifyCORS.tsx b/superset-frontend/packages/superset-ui-demo/storybook/shared/components/VerifyCORS.tsx index e3706afa78a..ca3b580730a 100644 --- a/superset-frontend/packages/superset-ui-demo/storybook/shared/components/VerifyCORS.tsx +++ b/superset-frontend/packages/superset-ui-demo/storybook/shared/components/VerifyCORS.tsx @@ -25,7 +25,7 @@ import { SupersetApiError, t, } from '@superset-ui/core'; -import { Button } from 'antd'; +import { Button } from '@superset-ui/core/components'; import ErrorMessage from './ErrorMessage'; export type Props = { diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/ExampleApp.stories.jsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/ExampleApp.stories.jsx index dc72528c554..85bdbbf9619 100644 --- a/superset-frontend/packages/superset-ui-demo/storybook/stories/ExampleApp.stories.jsx +++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/ExampleApp.stories.jsx @@ -16,9 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -import { Layout, Menu, Button, Card, Alert, Input, Table, Space } from 'antd'; +import { + Layout, + Menu, + Button, + Card, + Alert, + Input, + Table, + Space, +} from '@superset-ui/core/components'; // eslint-disable-next-line import/no-extraneous-dependencies -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; const { Header, Content, Sider } = Layout; diff --git a/superset-frontend/plugins/legacy-plugin-chart-calendar/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-calendar/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-calendar/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-calendar/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-chord/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-chord/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-chord/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-chord/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-country-map/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-country-map/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-country-map/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-country-map/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-horizon/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-horizon/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-horizon/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-horizon/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-map-box/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-map-box/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-map-box/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-map-box/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/package.json b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/package.json index e9b5f45eb99..4101769139d 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/package.json +++ b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/package.json @@ -29,7 +29,7 @@ "access": "public" }, "dependencies": { - "d3": "^3.5.17", + "d3v3": "npm:d3@3.5.17", "prop-types": "^15.8.1" }, "peerDependencies": { diff --git a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/src/ParallelCoordinates.js b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/src/ParallelCoordinates.js index 0529c86aff1..c2970979eb7 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/src/ParallelCoordinates.js +++ b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/src/ParallelCoordinates.js @@ -17,7 +17,7 @@ * under the License. */ /* eslint-disable react/sort-prop-types */ -import d3 from 'd3'; +import * as d3 from 'd3v3'; import PropTypes from 'prop-types'; import { getSequentialSchemeRegistry } from '@superset-ui/core'; diff --git a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/tsconfig.json index 7e74154150e..e7088b6c760 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/tsconfig.json @@ -1,26 +1,20 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", - "outDir": "lib", + "composite": true, "rootDir": "src", - "allowJs": false - }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" + "outDir": "lib", + "baseUrl": ".", + "paths": { + "d3v3": ["./types/d3v3"] } + + + }, + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], + "references": [ + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3-parcoords.d.ts b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3-parcoords.d.ts new file mode 100644 index 00000000000..e8026f2e2ac --- /dev/null +++ b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3-parcoords.d.ts @@ -0,0 +1,22 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +declare module 'src/vendor/parcoords/d3.parcoords' { + const parcoords: any; + export default parcoords; +} diff --git a/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3.d.ts b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3.d.ts new file mode 100644 index 00000000000..34a150e873e --- /dev/null +++ b/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/types/d3.d.ts @@ -0,0 +1,22 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +declare module 'd3' { + const d3: any; + export = d3; +} diff --git a/superset-frontend/plugins/legacy-plugin-chart-partition/src/OptionDescription.tsx b/superset-frontend/plugins/legacy-plugin-chart-partition/src/OptionDescription.tsx index e349e61132a..4b5a68c3028 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-partition/src/OptionDescription.tsx +++ b/superset-frontend/plugins/legacy-plugin-chart-partition/src/OptionDescription.tsx @@ -19,10 +19,8 @@ import PropTypes from 'prop-types'; -import { - ColumnMeta, - InfoTooltipWithTrigger, -} from '@superset-ui/chart-controls'; +import { ColumnMeta } from '@superset-ui/chart-controls'; +import { InfoTooltip } from '@superset-ui/core/components'; const propTypes = { option: PropTypes.object.isRequired, @@ -38,7 +36,7 @@ export default function OptionDescription({ option }: { option: ColumnMeta }) { {option.label} {option.description && ( - { ); }); - it('renders an InfoTooltipWithTrigger', () => { + it('renders an InfoTooltip', () => { const tooltipTrigger = screen.getByLabelText('Show info tooltip'); expect(tooltipTrigger).toBeInTheDocument(); diff --git a/superset-frontend/plugins/legacy-plugin-chart-partition/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-partition/tsconfig.json index b6bfaa2d984..b5b28fc6189 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-partition/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-partition/tsconfig.json @@ -1,25 +1,18 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" - }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" + "baseUrl": ".", + "paths": { + "@superset-ui/core/components": ["../../packages/superset-ui-core/src/components"] } + }, + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], + "references": [ + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-rose/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-rose/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-rose/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-rose/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-plugin-chart-world-map/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-world-map/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-world-map/tsconfig.json +++ b/superset-frontend/plugins/legacy-plugin-chart-world-map/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/tsconfig.json b/superset-frontend/plugins/legacy-preset-chart-deckgl/tsconfig.json index 3e1b196c648..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-preset-chart-deckgl/tsconfig.json +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/tsconfig.json @@ -1,26 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "test/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/legacy-preset-chart-nvd3/tsconfig.json b/superset-frontend/plugins/legacy-preset-chart-nvd3/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/legacy-preset-chart-nvd3/tsconfig.json +++ b/superset-frontend/plugins/legacy-preset-chart-nvd3/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json b/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json index 019b367ef9e..b3af9a1d193 100644 --- a/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - }, + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts index fcdbc52468b..99d2c57101a 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts @@ -17,10 +17,7 @@ * under the License. */ import { AnnotationType, Behavior, t } from '@superset-ui/core'; -import { - EchartsTimeseriesChartProps, - EchartsTimeseriesFormData, -} from '@superset-ui/plugin-chart-echarts'; +import { EchartsTimeseriesChartProps, EchartsTimeseriesFormData } from '../..'; import buildQuery from '../buildQuery'; import controlPanel from './controlPanel'; import transformProps from '../transformProps'; diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/transformProps.test.ts index c3a476bce0d..9a24c990c9a 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/transformProps.test.ts @@ -21,7 +21,7 @@ import { LegendOrientation, LegendType, EchartsTimeseriesSeriesType, -} from '@superset-ui/plugin-chart-echarts'; +} from '../../src'; import transformProps from '../../src/MixedTimeseries/transformProps'; import { EchartsMixedTimeseriesFormData, diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts index d138ed0c5dc..a0b3d5ad7d2 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts @@ -17,7 +17,7 @@ * under the License. */ import { CategoricalColorScale } from '@superset-ui/core'; -import { EchartsTimeseriesSeriesType } from '@superset-ui/plugin-chart-echarts'; +import { EchartsTimeseriesSeriesType } from '../../src'; import { transformSeries } from '../../src/Timeseries/transformers'; // Mock the colorScale function diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/transformers.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/transformers.test.ts index 113b416f9c5..277911e3b83 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/transformers.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/transformers.test.ts @@ -31,7 +31,7 @@ import { TimeseriesAnnotationLayer, TimeseriesDataRecord, } from '@superset-ui/core'; -import { OrientationType } from '@superset-ui/plugin-chart-echarts'; +import { OrientationType } from '../../src'; import { transformEventAnnotation, transformFormulaAnnotation, diff --git a/superset-frontend/plugins/plugin-chart-echarts/tsconfig.json b/superset-frontend/plugins/plugin-chart-echarts/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-echarts/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx index 8e1a1aab9d4..701d8949b67 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx @@ -16,7 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { SafeMarkdown, styled, t } from '@superset-ui/core'; +import { styled, t } from '@superset-ui/core'; +import { SafeMarkdown } from '@superset-ui/core/components'; import Handlebars from 'handlebars'; import dayjs from 'dayjs'; import { useMemo, useState } from 'react'; diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts b/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts index e566fd66b27..f474eb67b34 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/consts.ts @@ -18,7 +18,8 @@ */ import { debounce } from 'lodash'; import { formatSelectOptions } from '@superset-ui/chart-controls'; -import { SLOW_DEBOUNCE, t } from '@superset-ui/core'; +import { Constants } from '@superset-ui/core/components'; +import { t } from '@superset-ui/core'; export const PAGE_SIZE_OPTIONS = formatSelectOptions([ [0, t('page_size.all')], @@ -36,5 +37,5 @@ export const PAGE_SIZE_OPTIONS = formatSelectOptions([ export const debounceFunc = debounce( (func: (val: string) => void, source: string) => func(source), - SLOW_DEBOUNCE, + Constants.SLOW_DEBOUNCE, ); diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx index a15b8936231..e09f7f5aba9 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx @@ -20,9 +20,9 @@ import { ControlSetItem, CustomControlConfig, sharedControls, - InfoTooltipWithTrigger, } from '@superset-ui/chart-controls'; -import { t, validateNonEmpty, useTheme, SafeMarkdown } from '@superset-ui/core'; +import { t, validateNonEmpty, useTheme } from '@superset-ui/core'; +import { InfoTooltip, SafeMarkdown } from '@superset-ui/core/components'; import { CodeEditor } from '../../components/CodeEditor/CodeEditor'; import { ControlHeader } from '../../components/ControlHeader/controlHeader'; import { debounceFunc } from '../../consts'; @@ -70,7 +70,7 @@ ${helperDescriptions
{props.label} - } /> diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx index 09aee379db5..b69b2ea0424 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/style.tsx @@ -20,9 +20,9 @@ import { ControlSetItem, CustomControlConfig, sharedControls, - InfoTooltipWithTrigger, } from '@superset-ui/chart-controls'; import { t, useTheme } from '@superset-ui/core'; +import { InfoTooltip } from '@superset-ui/core/components'; import { CodeEditor } from '../../components/CodeEditor/CodeEditor'; import { ControlHeader } from '../../components/ControlHeader/controlHeader'; import { debounceFunc } from '../../consts'; @@ -47,7 +47,7 @@ const StyleControl = (props: CustomControlConfig) => {
{props.label} - diff --git a/superset-frontend/plugins/plugin-chart-handlebars/tsconfig.json b/superset-frontend/plugins/plugin-chart-handlebars/tsconfig.json index b6bfaa2d984..b5b28fc6189 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-handlebars/tsconfig.json @@ -1,25 +1,18 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" - }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" + "baseUrl": ".", + "paths": { + "@superset-ui/core/components": ["../../packages/superset-ui-core/src/components"] } + }, + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], + "references": [ + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/tsconfig.json b/superset-frontend/plugins/plugin-chart-pivot-table/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/plugin-chart-pivot-table/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-pivot-table/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-table/package.json b/superset-frontend/plugins/plugin-chart-table/package.json index fac61d3205c..4abf7dacfe7 100644 --- a/superset-frontend/plugins/plugin-chart-table/package.json +++ b/superset-frontend/plugins/plugin-chart-table/package.json @@ -37,7 +37,6 @@ }, "peerDependencies": { "@ant-design/icons": "^5.2.6", - "antd": "^5.24.6", "@superset-ui/chart-controls": "*", "@superset-ui/core": "*", "@testing-library/dom": "^8.20.1", diff --git a/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx b/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx index d03bba53124..ee7b07174c0 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx @@ -42,7 +42,7 @@ import { } from 'react-table'; import { matchSorter, rankings } from 'match-sorter'; import { isEqual } from 'lodash'; -import { Space } from 'antd'; +import { Space } from '@superset-ui/core/components'; import GlobalFilter, { GlobalFilterProps } from './components/GlobalFilter'; import SelectPageSize, { SelectPageSizeProps, diff --git a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/GlobalFilter.tsx b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/GlobalFilter.tsx index b1ff46eee73..ef9b8fc8bd8 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/GlobalFilter.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/GlobalFilter.tsx @@ -25,7 +25,7 @@ import { Ref, } from 'react'; import { Row, FilterValue } from 'react-table'; -import { Input, type InputRef, Space } from 'antd'; +import { Input, type InputRef, Space } from '@superset-ui/core/components'; import useAsyncState from '../utils/useAsyncState'; export interface SearchInputProps { diff --git a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SearchSelectDropdown.tsx b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SearchSelectDropdown.tsx index 5a1cc6b6e16..d4cc33e6181 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SearchSelectDropdown.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SearchSelectDropdown.tsx @@ -18,10 +18,10 @@ */ /* eslint-disable import/no-extraneous-dependencies */ import { styled } from '@superset-ui/core'; -import { Select } from 'antd'; +import { RawAntdSelect } from '@superset-ui/core/components'; import { SearchOption } from '../../types'; -const StyledSelect = styled(Select)` +const StyledSelect = styled(RawAntdSelect)` width: 120px; margin-right: 8px; `; diff --git a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx index f62caefae68..a3323c2e205 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx @@ -19,7 +19,7 @@ import { memo } from 'react'; import { css, t } from '@superset-ui/core'; import { formatSelectOptions } from '@superset-ui/chart-controls'; -import { Select } from 'antd'; +import { RawAntdSelect } from '@superset-ui/core/components'; export type SizeOption = [number, string]; @@ -34,12 +34,12 @@ function DefaultSelectRenderer({ options, onChange, }: SelectPageSizeRendererProps) { - const { Option } = Select; + const { Option } = RawAntdSelect; return ( {t('Show')}{' '} - + value={current} onChange={value => onChange(value)} size="small" @@ -62,7 +62,7 @@ function DefaultSelectRenderer({ ); })} - {' '} + {' '} {t('entries')} ); diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx index b06d51d7e0f..76b331c93c6 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx @@ -54,7 +54,14 @@ import { useTheme, SupersetTheme, } from '@superset-ui/core'; -import { Dropdown, Menu, Tooltip } from '@superset-ui/chart-controls'; +import { + Input, + Space, + RawAntdSelect as Select, + Dropdown, + Menu, + Tooltip, +} from '@superset-ui/core/components'; import { CheckOutlined, InfoCircleOutlined, @@ -64,7 +71,6 @@ import { TableOutlined, } from '@ant-design/icons'; import { isEmpty, debounce, isEqual } from 'lodash'; -import { Input, Space, Select } from 'antd'; import { ColorSchemeEnum, DataColumnMeta, diff --git a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts index 439df369f5a..0e892567f42 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts +++ b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts @@ -18,17 +18,18 @@ */ import { AdhocColumn, + BuildQuery, + PostProcessingRule, + QueryFormOrderBy, + QueryMode, + QueryObject, buildQueryContext, ensureIsArray, getMetricLabel, isPhysicalColumn, - QueryFormOrderBy, - QueryMode, - QueryObject, removeDuplicates, } from '@superset-ui/core'; -import { PostProcessingRule } from '@superset-ui/core/src/query/types/PostProcessing'; -import { BuildQuery } from '@superset-ui/core/src/chart/registries/ChartBuildQueryRegistrySingleton'; + import { isTimeComparison, timeCompareOperator, diff --git a/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx b/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx index 6cc791aff40..bfb3ca4df90 100644 --- a/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx +++ b/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import '@testing-library/jest-dom'; -import { render, screen } from '@testing-library/react'; +import { render, screen } from '@superset-ui/core/spec'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; import TableChart from '../src/TableChart'; import transformProps from '../src/transformProps'; diff --git a/superset-frontend/plugins/plugin-chart-table/tsconfig.json b/superset-frontend/plugins/plugin-chart-table/tsconfig.json index f60297e2489..b5b28fc6189 100644 --- a/superset-frontend/plugins/plugin-chart-table/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-table/tsconfig.json @@ -1,18 +1,18 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" - }, - "exclude": ["lib", "test"], - "extends": "../../tsconfig.json", - "include": ["src/**/*", "types/**/*", "../../types/**/*"], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" + "baseUrl": ".", + "paths": { + "@superset-ui/core/components": ["../../packages/superset-ui-core/src/components"] } + }, + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], + "references": [ + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx b/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx index 7dc5d4604b0..d634e06a594 100644 --- a/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx +++ b/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx @@ -16,9 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - import { PureComponent } from 'react'; -import cloudLayout, { Word } from 'd3-cloud'; +import cloudLayout from 'd3-cloud'; import { PlainObject, createEncoderFactory, @@ -34,9 +33,20 @@ import { import { isEqual } from 'lodash'; const seedRandom = seed('superset-ui'); + +// Polyfill Word type since it's not exported from 'd3-cloud' +export type Word = { + text: string; + size: number; + x?: number; + y?: number; + rotate?: number; + font?: string; + weight?: string | number; +}; + export const ROTATION = { flat: () => 0, - // this calculates a random rotation between -90 and 90 degrees. random: () => Math.floor(seedRandom() * 6 - 3) * 30, square: () => Math.floor(seedRandom() * 2) * 90, }; @@ -53,9 +63,6 @@ type WordCloudEncodingConfig = { text: ['Text', string]; }; -/** - * These props should be stored when saving the chart. - */ export interface WordCloudVisualProps { encoding?: Partial; rotation?: RotationType; @@ -84,15 +91,10 @@ type FullWordCloudProps = WordCloudProps & const SCALE_FACTOR_STEP = 0.5; const MAX_SCALE_FACTOR = 3; -// Percentage of top results that will always be displayed. -// Needed to avoid clutter when shrinking a chart with many records. const TOP_RESULTS_PERCENTAGE = 0.1; - class WordCloud extends PureComponent { static defaultProps = defaultProps; - // Cannot name it isMounted because of conflict - // with React's component function name isComponentMounted = false; wordCloudEncoderFactory = createEncoderFactory({ @@ -112,11 +114,15 @@ class WordCloud extends PureComponent { }, }); - createEncoder = (encoding?: Partial) => { - const selector = this.wordCloudEncoderFactory.createSelector(); + createEncoder = ( + encoding?: Partial, + ): Encoder => { + const selector: ( + e: Partial, + ) => Encoder = + this.wordCloudEncoderFactory.createSelector(); - // @ts-ignore - return selector(encoding as any); + return selector(encoding ?? {}); }; constructor(props: FullWordCloudProps) { @@ -135,7 +141,6 @@ class WordCloud extends PureComponent { componentDidUpdate(prevProps: WordCloudProps) { const { data, encoding, width, height, rotation } = this.props; - if ( !isEqual(prevProps.data, data) || !isEqual(prevProps.encoding, encoding) || @@ -160,8 +165,7 @@ class WordCloud extends PureComponent { update() { const { data, encoding } = this.props; - const encoder: Encoder = - this.createEncoder(encoding); + const encoder = this.createEncoder(encoding); encoder.setDomainFromDataset(data); const sortedData = [...data].sort( @@ -175,7 +179,6 @@ class WordCloud extends PureComponent { ); const topResults = sortedData.slice(0, topResultsCount); - // Ensure top results are always included in the final word cloud by scaling chart down if needed this.generateCloud(encoder, 1, (words: Word[]) => topResults.every((d: PlainObject) => words.find( @@ -194,7 +197,6 @@ class WordCloud extends PureComponent { cloudLayout() .size([width * scaleFactor, height * scaleFactor]) - // clone the data because cloudLayout mutates input .words(data.map((d: Word) => ({ ...d }))) .padding(5) .rotate(ROTATION[rotation] || ROTATION.flat) @@ -208,9 +210,7 @@ class WordCloud extends PureComponent { .fontSize((d: PlainObject) => encoder.channels.fontSize.encodeDatum(d, 0)) .on('end', (words: Word[]) => { if (isValid(words) || scaleFactor > MAX_SCALE_FACTOR) { - if (this.isComponentMounted) { - this.setState({ words, scaleFactor }); - } + this.setWords(words); } else { this.generateCloud(encoder, scaleFactor + SCALE_FACTOR_STEP, isValid); } @@ -219,17 +219,13 @@ class WordCloud extends PureComponent { } render() { - const { scaleFactor } = this.state; + const { scaleFactor, words } = this.state; const { width, height, encoding, sliceId, colorScheme } = this.props; - const { words } = this.state; - // @ts-ignore const encoder = this.createEncoder(encoding); encoder.channels.color.setDomainFromDataset(words); - const { getValueFromDatum } = encoder.channels.color; const colorFn = CategoricalColorNamespace.getScale(colorScheme); - const viewBoxWidth = width * scaleFactor; const viewBoxHeight = height * scaleFactor; @@ -237,9 +233,7 @@ class WordCloud extends PureComponent { {words.map(w => ( @@ -248,7 +242,10 @@ class WordCloud extends PureComponent { fontSize={`${w.size}px`} fontWeight={w.weight} fontFamily={w.font} - fill={colorFn(getValueFromDatum(w) as string, sliceId)} + fill={colorFn( + encoder.channels.color.getValueFromDatum(w) as string, + sliceId, + )} textAnchor="middle" transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`} > diff --git a/superset-frontend/plugins/plugin-chart-word-cloud/tsconfig.json b/superset-frontend/plugins/plugin-chart-word-cloud/tsconfig.json index b6bfaa2d984..b3af9a1d193 100644 --- a/superset-frontend/plugins/plugin-chart-word-cloud/tsconfig.json +++ b/superset-frontend/plugins/plugin-chart-word-cloud/tsconfig.json @@ -1,25 +1,15 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "declarationDir": "lib", + "composite": true, + "rootDir": "src", "outDir": "lib", - "rootDir": "src" + "baseUrl": "." }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], + "include": ["src/**/*", "types/**/*"], + "exclude": ["lib", "test"], "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + { "path": "../../packages/superset-ui-core" }, + { "path": "../../packages/superset-ui-chart-controls" } ] } diff --git a/superset-frontend/spec/helpers/shim.tsx b/superset-frontend/spec/helpers/shim.tsx index af5ea846815..5de51ec841a 100644 --- a/superset-frontend/spec/helpers/shim.tsx +++ b/superset-frontend/spec/helpers/shim.tsx @@ -92,7 +92,7 @@ jest.mock('rehype-raw', () => () => jest.fn()); // Mocks the Icon component due to its async nature // Tests should override this when needed -jest.mock('src/components/Icons/AsyncIcon', () => ({ +jest.mock('@superset-ui/core/components/Icons/AsyncIcon', () => ({ __esModule: true, default: ({ fileName, diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index 8b54319a568..70269c37ec7 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -28,7 +28,7 @@ import { } from '@superset-ui/core'; import { invert, mapKeys } from 'lodash'; -import { now } from 'src/utils/dates'; +import { now } from '@superset-ui/core/utils/dates'; import { addDangerToast as addDangerToastAction, addInfoToast as addInfoToastAction, diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx index c2f2ac083a8..a46f60c5d4e 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx @@ -22,7 +22,10 @@ import { QueryEditor } from 'src/SqlLab/types'; import { Store } from 'redux'; import { initialState, defaultQueryEditor } from 'src/SqlLab/fixtures'; import AceEditorWrapper from 'src/SqlLab/components/AceEditorWrapper'; -import { FullSQLEditor, type AsyncAceEditorProps } from 'src/components'; +import { + FullSQLEditor, + type AsyncAceEditorProps, +} from '@superset-ui/core/components'; import { queryEditorSetCursorPosition, queryEditorSetDb, @@ -33,14 +36,14 @@ fetchMock.get('glob:*/api/v1/database/*/function_names/', { function_names: [], }); -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); -jest.mock('src/components/AsyncAceEditor', () => ({ +jest.mock('@superset-ui/core/components/AsyncAceEditor', () => ({ FullSQLEditor: jest .fn() .mockImplementation((props: AsyncAceEditorProps) => ( diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx index 799e42a94f5..bfa615765b6 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx @@ -24,7 +24,7 @@ import { Global } from '@emotion/react'; import { SQL_EDITOR_LEFTBAR_WIDTH } from 'src/SqlLab/constants'; import { queryEditorSetSelectedText } from 'src/SqlLab/actions/sqlLab'; -import { FullSQLEditor as AceEditor } from 'src/components'; +import { FullSQLEditor as AceEditor } from '@superset-ui/core/components'; import type { KeyboardShortcut } from 'src/SqlLab/components/KeyboardShortcutButton'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; import { SqlLabRootState, type CursorPosition } from 'src/SqlLab/types'; diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useKeywords.ts b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useKeywords.ts index d17884dd7da..99e99125133 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useKeywords.ts +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useKeywords.ts @@ -20,7 +20,7 @@ import { useEffect, useMemo, useRef } from 'react'; import { useSelector, useDispatch, shallowEqual, useStore } from 'react-redux'; import { getExtensionsRegistry, t } from '@superset-ui/core'; -import type { Editor } from 'src/components'; +import type { Editor } from '@superset-ui/core/components'; import sqlKeywords from 'src/SqlLab/utils/sqlKeywords'; import { addTable, addDangerToast } from 'src/SqlLab/actions/sqlLab'; import { diff --git a/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx b/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx index d2555b25dda..6150c6e3a79 100644 --- a/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx +++ b/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx @@ -19,7 +19,7 @@ import { ReactNode } from 'react'; import { ClassNames } from '@emotion/react'; import { styled, useTheme, t } from '@superset-ui/core'; -import { Flex, Tooltip } from 'src/components'; +import { Flex, Tooltip } from '@superset-ui/core/components'; const StyledTooltip = (props: any) => { const theme = useTheme(); diff --git a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx index 7668020cd35..a989d02f702 100644 --- a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx @@ -33,10 +33,10 @@ import EstimateQueryCostButton, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/index.tsx b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/index.tsx index 6dd2fd2374c..88fca28e97a 100644 --- a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/index.tsx @@ -20,10 +20,14 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { css, styled, t } from '@superset-ui/core'; -import { Alert, Button, Loading } from 'src/components'; -import TableView from 'src/components/TableView'; -import ModalTrigger from 'src/components/ModalTrigger'; -import { EmptyWrapperType } from 'src/components/TableView/TableView'; +import { + Alert, + Button, + Loading, + ModalTrigger, + TableView, + EmptyWrapperType, +} from '@superset-ui/core/components'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; import { SqlLabRootState, QueryCostEstimate } from 'src/SqlLab/types'; diff --git a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton/index.tsx b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton/index.tsx index 62a9e6b0d5a..8d8bc7b1cb4 100644 --- a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton/index.tsx @@ -23,8 +23,8 @@ import { addInfoToast, addDangerToast, } from 'src/SqlLab/actions/sqlLab'; -import { Button, IconTooltip } from 'src/components'; -import { Icons } from 'src/components/Icons'; +import { Button, IconTooltip } from '@superset-ui/core/components'; +import { Icons } from '@superset-ui/core/components/Icons'; import { exploreChart } from 'src/explore/exploreUtils'; import { SqlLabRootState } from 'src/SqlLab/types'; diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton/ExploreResultsButton.test.tsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton/ExploreResultsButton.test.tsx index 79a26966ac2..0b119946138 100644 --- a/superset-frontend/src/SqlLab/components/ExploreResultsButton/ExploreResultsButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton/ExploreResultsButton.test.tsx @@ -21,7 +21,7 @@ import { render, screen } from 'spec/helpers/testing-library'; import ExploreResultsButton, { ExploreResultsButtonProps, } from 'src/SqlLab/components/ExploreResultsButton'; -import type { OnClickHandler } from 'src/components'; +import type { OnClickHandler } from '@superset-ui/core/components'; const setup = ( onClickFn: OnClickHandler, diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.tsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.tsx index 1bdba6783ac..53f9cdc2b0f 100644 --- a/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.tsx @@ -17,7 +17,11 @@ * under the License. */ import { t } from '@superset-ui/core'; -import { Button, type OnClickHandler, Icons } from 'src/components'; +import { + Button, + type OnClickHandler, + Icons, +} from '@superset-ui/core/components'; export interface ExploreResultsButtonProps { database?: { diff --git a/superset-frontend/src/SqlLab/components/HighlightedSql/index.tsx b/superset-frontend/src/SqlLab/components/HighlightedSql/index.tsx index f3cf8dc8578..2733b4ae81e 100644 --- a/superset-frontend/src/SqlLab/components/HighlightedSql/index.tsx +++ b/superset-frontend/src/SqlLab/components/HighlightedSql/index.tsx @@ -21,7 +21,7 @@ import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; import atomOneDark from 'react-syntax-highlighter/dist/cjs/styles/hljs/atom-one-dark'; import { t, themeObject } from '@superset-ui/core'; -import ModalTrigger from 'src/components/ModalTrigger'; +import { ModalTrigger } from '@superset-ui/core/components'; SyntaxHighlighterBase.registerLanguage('sql', sql); diff --git a/superset-frontend/src/SqlLab/components/KeyboardShortcutButton/index.tsx b/superset-frontend/src/SqlLab/components/KeyboardShortcutButton/index.tsx index bc043589a4c..e9749a56187 100644 --- a/superset-frontend/src/SqlLab/components/KeyboardShortcutButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/KeyboardShortcutButton/index.tsx @@ -18,7 +18,7 @@ */ import { FC } from 'react'; import { styled, t, css } from '@superset-ui/core'; -import ModalTrigger from 'src/components/ModalTrigger'; +import { ModalTrigger } from '@superset-ui/core/components'; import { detectOS } from 'src/utils/common'; const userOS = detectOS(); diff --git a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx index 7a35adccc40..2e26087296e 100644 --- a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx +++ b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx @@ -16,11 +16,13 @@ * specific language governing permissions and limitations * under the License. */ +import { act } from 'react-dom/test-utils'; import { QueryState } from '@superset-ui/core'; import fetchMock from 'fetch-mock'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { render, waitFor } from 'spec/helpers/testing-library'; +import { cleanup } from '@testing-library/react'; import { LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY } from 'src/logger/LogUtils'; import { CLEAR_INACTIVE_QUERIES, @@ -41,46 +43,42 @@ const mockState = { databases: mockDatabases, }; -// NOTE: The uses of @ts-ignore in this file is to enable testing of bad inputs to verify the -// function / component handles bad data elegantly describe('QueryAutoRefresh', () => { - const runningQueries: QueryDictionary = {}; - runningQueries[runningQuery.id] = runningQuery; - - const successfulQueries: QueryDictionary = {}; - successfulQueries[successfulQuery.id] = successfulQuery; - + const runningQueries: QueryDictionary = { [runningQuery.id]: runningQuery }; + const successfulQueries: QueryDictionary = { + [successfulQuery.id]: successfulQuery, + }; const queriesLastUpdate = Date.now(); - const refreshApi = 'glob:*/api/v1/query/updated_since?*'; + beforeEach(() => { + jest.useFakeTimers(); + }); + afterEach(() => { fetchMock.reset(); + cleanup(); + jest.runOnlyPendingTimers(); + jest.useRealTimers(); }); it('isQueryRunning returns true for valid running query', () => { - const running = isQueryRunning(runningQuery); - expect(running).toBe(true); + expect(isQueryRunning(runningQuery)).toBe(true); }); it('isQueryRunning returns false for valid not-running query', () => { - const running = isQueryRunning(successfulQuery); - expect(running).toBe(false); + expect(isQueryRunning(successfulQuery)).toBe(false); }); it('isQueryRunning returns false for invalid query', () => { // @ts-ignore - let running = isQueryRunning(null); - expect(running).toBe(false); + expect(isQueryRunning(null)).toBe(false); // @ts-ignore - running = isQueryRunning(undefined); - expect(running).toBe(false); + expect(isQueryRunning(undefined)).toBe(false); // @ts-ignore - running = isQueryRunning('I Should Be An Object'); - expect(running).toBe(false); + expect(isQueryRunning('I Should Be An Object')).toBe(false); // @ts-ignore - running = isQueryRunning({ state: { badFormat: true } }); - expect(running).toBe(false); + expect(isQueryRunning({ state: { badFormat: true } })).toBe(false); }); it('shouldCheckForQueries is true for valid running query', () => { @@ -112,16 +110,10 @@ describe('QueryAutoRefresh', () => { }); it('Attempts to refresh when given pending query', async () => { - const store = mockStore({ - sqlLab: { ...mockState }, - }); + const store = mockStore({ sqlLab: { ...mockState } }); + fetchMock.get(refreshApi, { - result: [ - { - id: runningQuery.id, - status: 'success', - }, - ], + result: [{ id: runningQuery.id, status: 'success' }], }); render( @@ -131,22 +123,22 @@ describe('QueryAutoRefresh', () => { />, { useRedux: true, store }, ); - await waitFor( - () => - expect(store.getActions()).toContainEqual( - expect.objectContaining({ - type: REFRESH_QUERIES, - }), - ), - { timeout: QUERY_UPDATE_FREQ + 100 }, + + await act(async () => { + jest.advanceTimersByTime(QUERY_UPDATE_FREQ + 100); + }); + + await waitFor(() => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ type: REFRESH_QUERIES }), + ), ); }); it('Attempts to clear inactive queries when updated queries are empty', async () => { const store = mockStore({ sqlLab: { ...mockState } }); - fetchMock.get(refreshApi, { - result: [], - }); + + fetchMock.get(refreshApi, { result: [] }); render( { />, { useRedux: true, store }, ); - await waitFor( - () => - expect(store.getActions()).toContainEqual( - expect.objectContaining({ - type: CLEAR_INACTIVE_QUERIES, - }), - ), - { timeout: QUERY_UPDATE_FREQ + 100 }, + + await act(async () => { + jest.advanceTimersByTime(QUERY_UPDATE_FREQ + 100); + }); + + await waitFor(() => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ type: CLEAR_INACTIVE_QUERIES }), + ), ); + expect( store.getActions().filter(({ type }) => type === REFRESH_QUERIES), ).toHaveLength(0); expect(fetchMock.calls(refreshApi)).toHaveLength(1); }); - it('Does not fail and attempts to refresh when given pending query and invalid query', async () => { + it('Does not fail and attempts to refresh with mixed valid/invalid queries', async () => { const store = mockStore({ sqlLab: { ...mockState } }); + fetchMock.get(refreshApi, { - result: [ - { - id: runningQuery.id, - status: 'success', - }, - ], + result: [{ id: runningQuery.id, status: 'success' }], }); render( @@ -189,27 +179,25 @@ describe('QueryAutoRefresh', () => { />, { useRedux: true, store }, ); - await waitFor( - () => - expect(store.getActions()).toContainEqual( - expect.objectContaining({ - type: REFRESH_QUERIES, - }), - ), - { timeout: QUERY_UPDATE_FREQ + 100 }, + + await act(async () => { + jest.advanceTimersByTime(QUERY_UPDATE_FREQ + 100); + }); + + await waitFor(() => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ type: REFRESH_QUERIES }), + ), ); }); it('Does NOT Attempt to refresh when given only completed queries', async () => { const store = mockStore({ sqlLab: { ...mockState } }); + fetchMock.get(refreshApi, { - result: [ - { - id: runningQuery.id, - status: 'success', - }, - ], + result: [{ id: runningQuery.id, status: 'success' }], }); + render( { />, { useRedux: true, store }, ); - await waitFor( - () => - expect(store.getActions()).toContainEqual( - expect.objectContaining({ - type: CLEAR_INACTIVE_QUERIES, - }), - ), - { timeout: QUERY_UPDATE_FREQ + 100 }, + + await act(async () => { + jest.advanceTimersByTime(QUERY_UPDATE_FREQ + 100); + }); + + await waitFor(() => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ type: CLEAR_INACTIVE_QUERIES }), + ), ); + expect(fetchMock.calls(refreshApi)).toHaveLength(0); }); it('logs the failed error for async queries', async () => { const store = mockStore({ sqlLab: { ...mockState } }); + fetchMock.get(refreshApi, { result: [ { @@ -257,6 +248,7 @@ describe('QueryAutoRefresh', () => { }, ], }); + render( { />, { useRedux: true, store }, ); - await waitFor( - () => - expect(store.getActions()).toContainEqual( - expect.objectContaining({ - payload: expect.objectContaining({ - eventName: LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY, - eventData: expect.objectContaining({ - error_type: 'TEST_ERROR', - error_details: 'Syntax invalid', - issue_codes: [102], - }), + + await act(async () => { + jest.advanceTimersByTime(QUERY_UPDATE_FREQ + 100); + }); + + await waitFor(() => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ + payload: expect.objectContaining({ + eventName: LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY, + eventData: expect.objectContaining({ + error_type: 'TEST_ERROR', + error_details: 'Syntax invalid', + issue_codes: [102], }), }), - ), - { timeout: QUERY_UPDATE_FREQ + 100 }, + }), + ), ); }); }); diff --git a/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx b/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx index 4f578df507d..85cf33ade30 100644 --- a/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx @@ -20,7 +20,7 @@ import { useEffect, useMemo, useState } from 'react'; import { shallowEqual, useSelector } from 'react-redux'; import { useInView } from 'react-intersection-observer'; import { omit } from 'lodash'; -import { EmptyState, Skeleton } from 'src/components'; +import { EmptyState, Skeleton } from '@superset-ui/core/components'; import { t, styled, diff --git a/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx b/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx index 8d421f92c92..bbaa76720b0 100644 --- a/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx +++ b/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx @@ -35,10 +35,10 @@ import QueryLimitSelect, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/QueryLimitSelect/index.tsx b/superset-frontend/src/SqlLab/components/QueryLimitSelect/index.tsx index 665141f8392..bb6e45b405f 100644 --- a/superset-frontend/src/SqlLab/components/QueryLimitSelect/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryLimitSelect/index.tsx @@ -18,9 +18,9 @@ */ import { useDispatch } from 'react-redux'; import { t } from '@superset-ui/core'; -import { Dropdown, Button } from 'src/components'; -import { Menu } from 'src/components/Menu'; -import { Icons } from 'src/components/Icons'; +import { Dropdown, Button } from '@superset-ui/core/components'; +import { Menu } from '@superset-ui/core/components/Menu'; +import { Icons } from '@superset-ui/core/components/Icons'; import { queryEditorSetQueryLimit } from 'src/SqlLab/actions/sqlLab'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; diff --git a/superset-frontend/src/SqlLab/components/QueryStateLabel/QueryStateLabel.test.tsx b/superset-frontend/src/SqlLab/components/QueryStateLabel/QueryStateLabel.test.tsx index 55ddd71c478..d02428bf2d0 100644 --- a/superset-frontend/src/SqlLab/components/QueryStateLabel/QueryStateLabel.test.tsx +++ b/superset-frontend/src/SqlLab/components/QueryStateLabel/QueryStateLabel.test.tsx @@ -21,7 +21,7 @@ import type { QueryState } from '@superset-ui/core'; import { render } from 'spec/helpers/testing-library'; import QueryStateLabel from '.'; -jest.mock('src/components/Label', () => ({ +jest.mock('@superset-ui/core/components/Label', () => ({ __esModule: true, Label: () =>
, })); diff --git a/superset-frontend/src/SqlLab/components/QueryStateLabel/index.tsx b/superset-frontend/src/SqlLab/components/QueryStateLabel/index.tsx index 2b234c341f8..5d2625dbc78 100644 --- a/superset-frontend/src/SqlLab/components/QueryStateLabel/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryStateLabel/index.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Label } from 'src/components'; +import { Label } from '@superset-ui/core/components'; import { STATE_TYPE_MAP, STATE_TYPE_MAP_LOCALIZED } from 'src/SqlLab/constants'; import { styled, Query } from '@superset-ui/core'; diff --git a/superset-frontend/src/SqlLab/components/QueryTable/index.tsx b/superset-frontend/src/SqlLab/components/QueryTable/index.tsx index 3b675664660..f892913ca43 100644 --- a/superset-frontend/src/SqlLab/components/QueryTable/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryTable/index.tsx @@ -17,8 +17,16 @@ * under the License. */ import { useMemo, ReactNode } from 'react'; -import { Card, Button, Tooltip, Label } from 'src/components'; -import ProgressBar from 'src/components/ProgressBar'; +import { + Card, + Button, + Tooltip, + Label, + Icons, + ModalTrigger, + TableView, +} from '@superset-ui/core/components'; +import ProgressBar from '@superset-ui/core/components/ProgressBar'; import { t, useTheme, QueryResponse } from '@superset-ui/core'; import { useDispatch, useSelector } from 'react-redux'; @@ -29,11 +37,8 @@ import { clearQueryResults, removeQuery, } from 'src/SqlLab/actions/sqlLab'; -import TableView from 'src/components/TableView'; -import { fDuration, extendedDayjs } from 'src/utils/dates'; -import { Icons } from 'src/components/Icons'; +import { fDuration, extendedDayjs } from '@superset-ui/core/utils/dates'; import { SqlLabRootState } from 'src/SqlLab/types'; -import ModalTrigger from 'src/components/ModalTrigger'; import { UserWithPermissionsAndRoles as User } from 'src/types/bootstrapTypes'; import ResultSet from '../ResultSet'; import HighlightedSql from '../HighlightedSql'; diff --git a/superset-frontend/src/SqlLab/components/QueryTable/styles.ts b/superset-frontend/src/SqlLab/components/QueryTable/styles.ts index 838911994e1..03f0eb3e679 100644 --- a/superset-frontend/src/SqlLab/components/QueryTable/styles.ts +++ b/superset-frontend/src/SqlLab/components/QueryTable/styles.ts @@ -17,7 +17,7 @@ * under the License. */ import { styled, css } from '@superset-ui/core'; -import { IconTooltip } from 'src/components'; +import { IconTooltip } from '@superset-ui/core/components'; export const StaticPosition = css` position: static; diff --git a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx index ae289f57acb..60edbd141a5 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx @@ -34,13 +34,15 @@ import { ButtonGroup, Tooltip, Card, - CopyToClipboard, - ErrorMessageWithStackTrace, Modal, - FilterableTable, Input, Label, Loading, +} from '@superset-ui/core/components'; +import { + CopyToClipboard, + FilterableTable, + ErrorMessageWithStackTrace, } from 'src/components'; import { nanoid } from 'nanoid'; import { @@ -63,7 +65,7 @@ import { import { EXPLORE_CHART_DEFAULT, SqlLabRootState } from 'src/SqlLab/types'; import { mountExploreUrl } from 'src/explore/exploreUtils'; import { postFormData } from 'src/explore/exploreUtils/formData'; -import ProgressBar from 'src/components/ProgressBar'; +import ProgressBar from '@superset-ui/core/components/ProgressBar'; import { addDangerToast } from 'src/components/MessageToasts/actions'; import { prepareCopyToClipboardTabularData } from 'src/utils/common'; import { getItem, LocalStorageKeys } from 'src/utils/localStorageHelpers'; @@ -82,7 +84,7 @@ import { LOG_ACTIONS_SQLLAB_CREATE_CHART, LOG_ACTIONS_SQLLAB_DOWNLOAD_CSV, } from 'src/logger/LogUtils'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { findPermission } from 'src/utils/findPermission'; import ExploreCtasResultsButton from '../ExploreCtasResultsButton'; import ExploreResultsButton from '../ExploreResultsButton'; diff --git a/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx b/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx index 40df87b68e4..798a98b3ff3 100644 --- a/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx @@ -29,10 +29,10 @@ import RunQueryActionButton, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx b/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx index 052ffed4001..79d6f962600 100644 --- a/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx @@ -20,8 +20,8 @@ import { useMemo, FC, ReactElement } from 'react'; import { t, styled, useTheme, SupersetTheme } from '@superset-ui/core'; -import { Button, DropdownButton } from 'src/components'; -import { Icons } from 'src/components/Icons'; +import { Button, DropdownButton } from '@superset-ui/core/components'; +import { Icons } from '@superset-ui/core/components/Icons'; import { detectOS } from 'src/utils/common'; import { QueryButtonProps } from 'src/SqlLab/types'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx index f5283dfd1e3..0ab7237a037 100644 --- a/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { render, screen, userEvent } from 'spec/helpers/testing-library'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import SaveDatasetActionButton from 'src/SqlLab/components/SaveDatasetActionButton'; const overlayMenu = ( diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/index.tsx b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/index.tsx index 4c9464a04c6..bcdc8370357 100644 --- a/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/index.tsx @@ -17,8 +17,8 @@ * under the License. */ import { t, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import { Button, DropdownButton } from 'src/components'; +import { Icons } from '@superset-ui/core/components/Icons'; +import { Button, DropdownButton } from '@superset-ui/core/components'; interface SaveDatasetActionButtonProps { setShowSave: (arg0: boolean) => void; diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx index f6dff994e8f..22df5b4c6c7 100644 --- a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx +++ b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx @@ -19,14 +19,14 @@ import { useCallback, useState, FormEvent } from 'react'; -import { Radio, RadioChangeEvent } from 'src/components/Radio'; +import { Radio, RadioChangeEvent } from '@superset-ui/core/components/Radio'; import { AsyncSelect, Button, Modal, Input, type SelectValue, -} from 'src/components'; +} from '@superset-ui/core/components'; import { styled, t, diff --git a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx index e6e94ca71e3..5a5fa55b3fb 100644 --- a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx +++ b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx @@ -20,8 +20,16 @@ import { useState, useEffect, useMemo, ChangeEvent } from 'react'; import type { DatabaseObject } from 'src/features/databases/types'; import { t, styled } from '@superset-ui/core'; -import { Input, Button, Form, FormItem, Modal, Row, Col } from 'src/components'; -import { Menu } from 'src/components/Menu'; +import { + Input, + Button, + Form, + FormItem, + Modal, + Row, + Col, +} from '@superset-ui/core/components'; +import { Menu } from '@superset-ui/core/components/Menu'; import SaveDatasetActionButton from 'src/SqlLab/components/SaveDatasetActionButton'; import { SaveDatasetModal, diff --git a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx index af42121ce0d..7c68662cf60 100644 --- a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx +++ b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx @@ -23,8 +23,18 @@ import { FormValidation } from '@rjsf/utils'; import validator from '@rjsf/validator-ajv8'; import { t, styled } from '@superset-ui/core'; import { parseDate } from 'chrono-node'; -import ModalTrigger, { ModalTriggerRef } from 'src/components/ModalTrigger'; -import { Input, Button, Form, FormItem, Row, Col } from 'src/components'; +import { + ModalTrigger, + ModalTriggerRef, +} from '@superset-ui/core/components/ModalTrigger'; +import { + Input, + Button, + Form, + FormItem, + Row, + Col, +} from '@superset-ui/core/components'; import getBootstrapData from 'src/utils/getBootstrapData'; const bootstrapData = getBootstrapData(); diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx index f57d8d338ff..7249d5909fb 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx @@ -22,8 +22,9 @@ import { SupersetClient, css, } from '@superset-ui/core'; -import { Button, CopyToClipboard } from 'src/components'; -import { Icons } from 'src/components/Icons'; +import { Button } from '@superset-ui/core/components'; +import { CopyToClipboard } from 'src/components'; +import { Icons } from '@superset-ui/core/components/Icons'; import withToasts from 'src/components/MessageToasts/withToasts'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; import { LOG_ACTIONS_SQLLAB_COPY_LINK } from 'src/logger/LogUtils'; diff --git a/superset-frontend/src/SqlLab/components/ShowSQL/index.tsx b/superset-frontend/src/SqlLab/components/ShowSQL/index.tsx index e0b27265094..a9739faacee 100644 --- a/superset-frontend/src/SqlLab/components/ShowSQL/index.tsx +++ b/superset-frontend/src/SqlLab/components/ShowSQL/index.tsx @@ -19,9 +19,8 @@ import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/light'; import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; -import { IconTooltip } from 'src/components/IconTooltip'; -import ModalTrigger from 'src/components/ModalTrigger'; -import { Icons } from 'src/components/Icons'; +import { IconTooltip, ModalTrigger } from '@superset-ui/core/components'; +import { Icons } from '@superset-ui/core/components/Icons'; SyntaxHighlighter.registerLanguage('sql', sql); diff --git a/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx b/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx index 7ba0d9b4f39..06b7033c254 100644 --- a/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx +++ b/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx @@ -18,7 +18,7 @@ */ import { FC } from 'react'; import { shallowEqual, useSelector } from 'react-redux'; -import { Alert, EmptyState } from 'src/components'; +import { Alert, EmptyState } from '@superset-ui/core/components'; import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core'; import { SqlLabRootState } from 'src/SqlLab/types'; diff --git a/superset-frontend/src/SqlLab/components/SouthPane/index.tsx b/superset-frontend/src/SqlLab/components/SouthPane/index.tsx index ed0128c23d6..7096f4d6328 100644 --- a/superset-frontend/src/SqlLab/components/SouthPane/index.tsx +++ b/superset-frontend/src/SqlLab/components/SouthPane/index.tsx @@ -19,13 +19,13 @@ import { createRef, useCallback, useMemo } from 'react'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { nanoid } from 'nanoid'; -import Tabs from 'src/components/Tabs'; +import Tabs from '@superset-ui/core/components/Tabs'; import { css, styled, t, useTheme } from '@superset-ui/core'; import { removeTables, setActiveSouthPaneTab } from 'src/SqlLab/actions/sqlLab'; -import { Label } from 'src/components'; -import { Icons } from 'src/components/Icons'; +import { Label } from '@superset-ui/core/components'; +import { Icons } from '@superset-ui/core/components/Icons'; import { SqlLabRootState } from 'src/SqlLab/types'; import QueryHistory from '../QueryHistory'; import { diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx index f5d0277a894..119021f722b 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx @@ -45,8 +45,8 @@ import setupExtensions from 'src/setup/setupExtensions'; import type { Action, Middleware, Store } from 'redux'; import SqlEditor, { Props } from '.'; -jest.mock('src/components/AsyncAceEditor', () => ({ - ...jest.requireActual('src/components/AsyncAceEditor'), +jest.mock('@superset-ui/core/components/AsyncAceEditor', () => ({ + ...jest.requireActual('@superset-ui/core/components/AsyncAceEditor'), FullSQLEditor: ({ onChange, onBlur, diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx index 85673b3073d..93f6e831a2c 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx @@ -53,19 +53,19 @@ import type { DatabaseObject } from 'src/features/databases/types'; import { debounce, throttle, isEmpty } from 'lodash'; import Mousetrap from 'mousetrap'; import { - Input, - Button, Alert, + Button, Dropdown, EmptyState, + Input, Modal, -} from 'src/components'; -import Timer from 'src/components/Timer'; + Timer, +} from '@superset-ui/core/components'; import ResizableSidebar from 'src/components/ResizableSidebar'; -import { Skeleton } from 'src/components/Skeleton'; -import { Switch } from 'src/components/Switch'; -import { Menu } from 'src/components/Menu'; -import { Icons } from 'src/components/Icons'; +import { Skeleton } from '@superset-ui/core/components/Skeleton'; +import { Switch } from '@superset-ui/core/components/Switch'; +import { Menu } from '@superset-ui/core/components/Menu'; +import { Icons } from '@superset-ui/core/components/Icons'; import { detectOS } from 'src/utils/common'; import { addNewQueryEditor, diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx index 5991040389c..2b1656125b3 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx @@ -33,7 +33,8 @@ import { addDangerToast, resetState, } from 'src/SqlLab/actions/sqlLab'; -import { Button, EmptyState, Icons, type DatabaseObject } from 'src/components'; +import { Button, EmptyState, Icons } from '@superset-ui/core/components'; +import { type DatabaseObject } from 'src/components'; import { t, styled, css } from '@superset-ui/core'; import { TableSelectorMultiple } from 'src/components/TableSelector'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; diff --git a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx index 3e10def3757..ae79d42ecb4 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx @@ -41,10 +41,10 @@ import { } from 'src/SqlLab/actions/sqlLab'; import SqlEditorTabHeader from 'src/SqlLab/components/SqlEditorTabHeader'; -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/index.tsx index 0f19e341e57..d99c2d95762 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/index.tsx @@ -20,8 +20,8 @@ import { useMemo, FC } from 'react'; import { bindActionCreators } from 'redux'; import { useSelector, useDispatch, shallowEqual } from 'react-redux'; -import { MenuDotsDropdown } from 'src/components'; -import { Menu } from 'src/components/Menu'; +import { MenuDotsDropdown } from '@superset-ui/core/components'; +import { Menu } from '@superset-ui/core/components/Menu'; import { styled, css, @@ -38,8 +38,8 @@ import { toggleLeftBar, } from 'src/SqlLab/actions/sqlLab'; import { QueryEditor, SqlLabRootState } from 'src/SqlLab/types'; -import { Icons } from 'src/components/Icons'; -import type { IconType } from 'src/components/Icons/types'; +import { Icons } from '@superset-ui/core/components/Icons'; +import type { IconType } from '@superset-ui/core/components/Icons/types'; const TabTitleWrapper = styled.div` display: flex; diff --git a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx index 9cb78f7e0b2..414cff18645 100644 --- a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx +++ b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx @@ -18,7 +18,7 @@ */ import { PureComponent } from 'react'; import { pick } from 'lodash'; -import { EditableTabs } from 'src/components/Tabs'; +import { EditableTabs } from '@superset-ui/core/components/Tabs'; import { connect } from 'react-redux'; import URI from 'urijs'; import type { QueryEditor, SqlLabRootState } from 'src/SqlLab/types'; @@ -30,13 +30,13 @@ import { css, } from '@superset-ui/core'; import { Logger } from 'src/logger/LogUtils'; -import { EmptyState, Tooltip } from 'src/components'; +import { EmptyState, Tooltip } from '@superset-ui/core/components'; import { detectOS } from 'src/utils/common'; import * as Actions from 'src/SqlLab/actions/sqlLab'; import getBootstrapData from 'src/utils/getBootstrapData'; import { locationContext } from 'src/pages/SqlLab/LocationContext'; import { navigateWithState } from 'src/utils/navigationUtils'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import SqlEditor from '../SqlEditor'; import SqlEditorTabHeader from '../SqlEditorTabHeader'; diff --git a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx index 1e34738cf67..96f68b6666a 100644 --- a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx +++ b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx @@ -30,10 +30,10 @@ jest.mock('@superset-ui/core', () => ({ const mockedIsFeatureEnabled = isFeatureEnabled as jest.Mock; -jest.mock('src/components/Loading', () => ({ +jest.mock('@superset-ui/core/components/Loading', () => ({ Loading: () =>
, })); -jest.mock('src/components/IconTooltip', () => ({ +jest.mock('@superset-ui/core/components/IconTooltip', () => ({ IconTooltip: ({ onClick, tooltip, diff --git a/superset-frontend/src/SqlLab/components/TableElement/index.tsx b/superset-frontend/src/SqlLab/components/TableElement/index.tsx index 0deda9875bf..e15f4ccacad 100644 --- a/superset-frontend/src/SqlLab/components/TableElement/index.tsx +++ b/superset-frontend/src/SqlLab/components/TableElement/index.tsx @@ -26,12 +26,13 @@ import { Card, Collapse, Tooltip, - CopyToClipboard, Flex, IconTooltip, Loading, + ModalTrigger, type CollapseProps, -} from 'src/components'; +} from '@superset-ui/core/components'; +import { CopyToClipboard } from 'src/components'; import { t, styled, useTheme } from '@superset-ui/core'; import { debounce } from 'lodash'; @@ -46,11 +47,10 @@ import { useTableExtendedMetadataQuery, useTableMetadataQuery, } from 'src/hooks/apiResources'; -import ModalTrigger from 'src/components/ModalTrigger'; import useEffectEvent from 'src/hooks/useEffectEvent'; import { ActionType } from 'src/types/Action'; -import { Icons } from 'src/components/Icons'; -import { Space } from 'src/components/Space'; +import { Icons } from '@superset-ui/core/components/Icons'; +import { Space } from '@superset-ui/core/components/Space'; import ColumnElement, { ColumnKeyTypeType } from '../ColumnElement'; import ShowSQL from '../ShowSQL'; diff --git a/superset-frontend/src/SqlLab/components/TablePreview/TablePreview.test.tsx b/superset-frontend/src/SqlLab/components/TablePreview/TablePreview.test.tsx index 5c92308d36f..5f3a7f23c3c 100644 --- a/superset-frontend/src/SqlLab/components/TablePreview/TablePreview.test.tsx +++ b/superset-frontend/src/SqlLab/components/TablePreview/TablePreview.test.tsx @@ -45,7 +45,7 @@ jest.mock( ({ children }: { children: (params: { height: number }) => ReactChild }) => children({ height: 500 }), ); -jest.mock('src/components/IconTooltip', () => ({ +jest.mock('@superset-ui/core/components/IconTooltip', () => ({ IconTooltip: ({ onClick, tooltip, diff --git a/superset-frontend/src/SqlLab/components/TablePreview/index.tsx b/superset-frontend/src/SqlLab/components/TablePreview/index.tsx index d0364fcde52..2b409a8fcf3 100644 --- a/superset-frontend/src/SqlLab/components/TablePreview/index.tsx +++ b/superset-frontend/src/SqlLab/components/TablePreview/index.tsx @@ -25,24 +25,23 @@ import { ClientErrorObject, css, getExtensionsRegistry, - SafeMarkdown, styled, t, } from '@superset-ui/core'; -import AutoSizer from 'react-virtualized-auto-sizer'; -import { Icons } from 'src/components/Icons'; -import type { SqlLabRootState } from 'src/SqlLab/types'; import { + SafeMarkdown, Alert, Breadcrumb, Button, Card, - CopyToClipboard, Dropdown, - FilterableTable, Skeleton, -} from 'src/components'; -import Tabs from 'src/components/Tabs'; +} from '@superset-ui/core/components'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { Icons } from '@superset-ui/core/components/Icons'; +import type { SqlLabRootState } from 'src/SqlLab/types'; +import { CopyToClipboard, FilterableTable } from 'src/components'; +import Tabs from '@superset-ui/core/components/Tabs'; import { tableApiUtil, TableMetaData, @@ -50,7 +49,7 @@ import { useTableMetadataQuery, } from 'src/hooks/apiResources'; import { runTablePreviewQuery } from 'src/SqlLab/actions/sqlLab'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import ResultSet from '../ResultSet'; import ShowSQL from '../ShowSQL'; diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx index cdafc5ba177..acada8b861c 100644 --- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx +++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx @@ -32,13 +32,13 @@ import TemplateParamsEditor, { TemplateParamsEditorProps, } from 'src/SqlLab/components/TemplateParamsEditor'; -jest.mock('src/components/Select/Select', () => () => ( +jest.mock('@superset-ui/core/components/Select/Select', () => () => (
)); -jest.mock('src/components/Select/AsyncSelect', () => () => ( +jest.mock('@superset-ui/core/components/Select/AsyncSelect', () => () => (
)); -jest.mock('src/components/AsyncAceEditor', () => ({ +jest.mock('@superset-ui/core/components/AsyncAceEditor', () => ({ ConfigEditor: ({ value }: { value: string }) => (
{value}
), diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx index 2f8019f4d17..e10e0c78e40 100644 --- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx +++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx @@ -18,11 +18,15 @@ */ import { useState, useEffect } from 'react'; import { t, styled } from '@superset-ui/core'; -import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import { debounce } from 'lodash'; -import { Badge, ConfigEditor, Tooltip } from 'src/components'; -import ModalTrigger from 'src/components/ModalTrigger'; -import { FAST_DEBOUNCE } from 'src/constants'; +import { + Badge, + ConfigEditor, + InfoTooltip, + ModalTrigger, + Tooltip, + Constants, +} from '@superset-ui/core/components'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; const StyledConfigEditor = styled(ConfigEditor)` @@ -80,7 +84,7 @@ const TemplateParamsEditor = ({ mode={language} minLines={25} maxLines={50} - onChange={debounce(onChange, FAST_DEBOUNCE)} + onChange={debounce(onChange, Constants.FAST_DEBOUNCE)} width="100%" editorProps={{ $blockScrolling: true }} enableLiveAutocompletion @@ -105,7 +109,7 @@ const TemplateParamsEditor = ({ {t('Parameters ')} {!isValid && ( - = { offline: 'error', diff --git a/superset-frontend/src/SqlLab/reducers/sqlLab.js b/superset-frontend/src/SqlLab/reducers/sqlLab.js index e0bc4307dcc..c77f708653f 100644 --- a/superset-frontend/src/SqlLab/reducers/sqlLab.js +++ b/superset-frontend/src/SqlLab/reducers/sqlLab.js @@ -19,8 +19,8 @@ import { normalizeTimestamp, QueryState, t } from '@superset-ui/core'; import { isEqual, omit } from 'lodash'; import { shallowEqual } from 'react-redux'; +import { now } from '@superset-ui/core/utils/dates'; import * as actions from '../actions/sqlLab'; -import { now } from '../../utils/dates'; import { addToObject, alterInObject, diff --git a/superset-frontend/src/SqlLab/types.ts b/superset-frontend/src/SqlLab/types.ts index 6438db4e562..cc5a4469bea 100644 --- a/superset-frontend/src/SqlLab/types.ts +++ b/superset-frontend/src/SqlLab/types.ts @@ -22,7 +22,10 @@ import { UserWithPermissionsAndRoles, } from 'src/types/bootstrapTypes'; import { ToastType } from 'src/components/MessageToasts/types'; -import type { ButtonProps, DropdownButtonProps } from 'src/components'; +import type { + ButtonProps, + DropdownButtonProps, +} from '@superset-ui/core/components'; import type { TableMetaData } from 'src/hooks/apiResources'; export type QueryButtonProps = DropdownButtonProps | ButtonProps; diff --git a/superset-frontend/src/assets/branding/.!4592!superset-logo-horiz-apache-dark.png b/superset-frontend/src/assets/branding/.!4592!superset-logo-horiz-apache-dark.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/src/assets/branding/.!4862!superset-logo-horiz-apache-dark.png b/superset-frontend/src/assets/branding/.!4862!superset-logo-horiz-apache-dark.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/src/assets/branding/.!4993!superset-logo-horiz-apache-dark.png b/superset-frontend/src/assets/branding/.!4993!superset-logo-horiz-apache-dark.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/superset-frontend/src/components/AlteredSliceTag/index.tsx b/superset-frontend/src/components/AlteredSliceTag/index.tsx index be63b84eddb..43fd0d7a4f9 100644 --- a/superset-frontend/src/components/AlteredSliceTag/index.tsx +++ b/superset-frontend/src/components/AlteredSliceTag/index.tsx @@ -23,11 +23,13 @@ import { t } from '@superset-ui/core'; import { sanitizeFormData } from 'src/explore/exploreUtils/formData'; import getControlsForVizType from 'src/utils/getControlsForVizType'; import { safeStringify } from 'src/utils/safeStringify'; -import { Icons } from 'src/components/Icons'; -import { Label } from '../Label'; -import { Tooltip } from '../Tooltip'; -import ModalTrigger from '../ModalTrigger'; -import TableView from '../TableView'; +import { + Label, + Icons, + Tooltip, + ModalTrigger, + TableView, +} from '@superset-ui/core/components'; import type { AlteredSliceTagProps, ControlMap, diff --git a/superset-frontend/src/components/AuditInfo/ModifiedInfo.test.tsx b/superset-frontend/src/components/AuditInfo/ModifiedInfo.test.tsx index 11f9e95ca2e..177772b4df6 100644 --- a/superset-frontend/src/components/AuditInfo/ModifiedInfo.test.tsx +++ b/superset-frontend/src/components/AuditInfo/ModifiedInfo.test.tsx @@ -39,7 +39,7 @@ test('should render a tooltip when user is provided', async () => { expect(dateElement).toBeInTheDocument(); expect(screen.getByText(TEST_DATE)).toBeInTheDocument(); expect(screen.queryByText('Modified by: Foo Bar')).not.toBeInTheDocument(); - userEvent.hover(dateElement); + await userEvent.hover(dateElement); const tooltip = await screen.findByRole('tooltip'); expect(tooltip).toBeInTheDocument(); expect(screen.getByText('Modified by: Foo Bar')).toBeInTheDocument(); @@ -51,7 +51,7 @@ test('should render only the date if username is not provided', async () => { const dateElement = screen.getByTestId('audit-info-date'); expect(dateElement).toBeInTheDocument(); expect(screen.getByText(TEST_DATE)).toBeInTheDocument(); - userEvent.hover(dateElement); + await userEvent.hover(dateElement); await waitFor( () => { const tooltip = screen.queryByRole('tooltip'); diff --git a/superset-frontend/src/components/AuditInfo/index.tsx b/superset-frontend/src/components/AuditInfo/index.tsx index 75aaa5d3936..2bb34906e23 100644 --- a/superset-frontend/src/components/AuditInfo/index.tsx +++ b/superset-frontend/src/components/AuditInfo/index.tsx @@ -18,7 +18,7 @@ */ import getOwnerName from 'src/utils/getOwnerName'; import { t } from '@superset-ui/core'; -import { Tooltip } from '../Tooltip'; +import { Tooltip } from '@superset-ui/core/components'; import type { ModifiedInfoProps } from './types'; export const ModifiedInfo = ({ user, date }: ModifiedInfoProps) => { diff --git a/superset-frontend/src/components/Chart/Chart.tsx b/superset-frontend/src/components/Chart/Chart.tsx index c7264a449f5..c4d89b5eb13 100644 --- a/superset-frontend/src/components/Chart/Chart.tsx +++ b/superset-frontend/src/components/Chart/Chart.tsx @@ -30,7 +30,8 @@ import { ChartDataResponse, } from '@superset-ui/core'; import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants'; -import { EmptyState, ErrorBoundary, Loading } from 'src/components'; +import { EmptyState, Loading } from '@superset-ui/core/components'; +import { ErrorBoundary } from 'src/components'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; import { URL_PARAMS } from 'src/constants'; import { getUrlParam } from 'src/utils/urlUtils'; diff --git a/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx b/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx index a1e08b3af17..5095da6c9c1 100644 --- a/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx +++ b/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx @@ -41,9 +41,9 @@ import { useTheme, } from '@superset-ui/core'; import { RootState } from 'src/dashboard/types'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { usePermissions } from 'src/hooks/usePermissions'; -import { Dropdown } from 'src/components'; +import { Dropdown } from '@superset-ui/core/components'; import { updateDataMask } from 'src/dataMask/actions'; import DrillByModal from 'src/components/Chart/DrillBy/DrillByModal'; import { useVerboseMap } from 'src/hooks/apiResources/datasets'; diff --git a/superset-frontend/src/components/Chart/ChartErrorMessage.test.tsx b/superset-frontend/src/components/Chart/ChartErrorMessage.test.tsx index 98c099d3266..40ce7a86527 100644 --- a/superset-frontend/src/components/Chart/ChartErrorMessage.test.tsx +++ b/superset-frontend/src/components/Chart/ChartErrorMessage.test.tsx @@ -23,7 +23,7 @@ import { useChartOwnerNames } from 'src/hooks/apiResources'; import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; import { ErrorType } from '@superset-ui/core'; import type { ErrorMessageComponentProps } from 'src/components/ErrorMessage/types'; -import { getErrorMessageComponentRegistry } from 'src/components'; +import { getErrorMessageComponentRegistry } from 'src/components/ErrorMessage'; import { ChartErrorMessage } from './ChartErrorMessage'; // Mock the useChartOwnerNames hook diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx index 9ac9029c9cf..4100e9b9aca 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx @@ -30,7 +30,7 @@ import { FeatureFlag, } from '@superset-ui/core'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; -import { EmptyState } from 'src/components'; +import { EmptyState } from '@superset-ui/core/components'; import { ChartSource } from 'src/types/ChartSource'; import ChartContextMenu from './ChartContextMenu/ChartContextMenu'; diff --git a/superset-frontend/src/components/Chart/DisabledMenuItemTooltip.tsx b/superset-frontend/src/components/Chart/DisabledMenuItemTooltip.tsx index fdaa296f4df..b74ccb7e172 100644 --- a/superset-frontend/src/components/Chart/DisabledMenuItemTooltip.tsx +++ b/superset-frontend/src/components/Chart/DisabledMenuItemTooltip.tsx @@ -19,8 +19,8 @@ import { ReactNode } from 'react'; import { css, SupersetTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import { Tooltip } from 'src/components'; +import { Icons } from '@superset-ui/core/components/Icons'; +import { Tooltip } from '@superset-ui/core/components'; export const MenuItemTooltip = ({ title, diff --git a/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.test.tsx b/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.test.tsx index ad3da909b2f..fd838f0108c 100644 --- a/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.test.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.test.tsx @@ -30,7 +30,7 @@ import { waitFor, } from 'spec/helpers/testing-library'; import chartQueries, { sliceId } from 'spec/fixtures/mockChartQueries'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { supersetGetCache } from 'src/utils/cachedSupersetGet'; import { DrillByMenuItems, DrillByMenuItemsProps } from './DrillByMenuItems'; diff --git a/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.tsx b/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.tsx index f2bf2128435..c0ffc795e26 100644 --- a/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/DrillByMenuItems.tsx @@ -26,13 +26,12 @@ import { useRef, useState, } from 'react'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { BaseFormData, Behavior, Column, ContextMenuFilters, - FAST_DEBOUNCE, JsonResponse, css, ensureIsArray, @@ -42,12 +41,12 @@ import { t, useTheme, } from '@superset-ui/core'; +import { Constants, Input, Loading } from '@superset-ui/core/components'; import rison from 'rison'; import { debounce } from 'lodash'; import { FixedSizeList as List } from 'react-window'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { useToasts } from 'src/components/MessageToasts/withToasts'; -import { Input, Loading } from 'src/components'; import { cachedSupersetGet, supersetGetCache, @@ -203,7 +202,7 @@ export const DrillByMenuItems = ({ () => debounce((value: string) => { setDebouncedSearchInput(value); - }, FAST_DEBOUNCE), + }, Constants.FAST_DEBOUNCE), [], ); diff --git a/superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx b/superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx index 305e8a0b710..f990ec3529b 100644 --- a/superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx @@ -40,7 +40,7 @@ import { Loading, Breadcrumb, Flex, -} from 'src/components'; +} from '@superset-ui/core/components'; import { RootState } from 'src/dashboard/types'; import { DashboardPageIdContext } from 'src/dashboard/containers/DashboardPage'; import { postFormData } from 'src/explore/exploreUtils/formData'; diff --git a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx index addd4fd1c58..e8fb13e0163 100644 --- a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx @@ -19,7 +19,7 @@ import { useMemo, useState } from 'react'; import { css, SupersetTheme, t } from '@superset-ui/core'; -import { Radio } from 'src/components/Radio'; +import { Radio } from '@superset-ui/core/components/Radio'; import { DrillByType } from '../types'; export const useDisplayModeToggle = () => { diff --git a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx index 8635c8981b1..bda96d35aa8 100644 --- a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx @@ -18,7 +18,7 @@ */ import { css, styled, isDefined, QueryData, t } from '@superset-ui/core'; import { SingleQueryResultPane } from 'src/explore/components/DataTablesPane/components/SingleQueryResultPane'; -import Tabs from 'src/components/Tabs'; +import Tabs from '@superset-ui/core/components/Tabs'; const DATA_SIZE = 15; diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx index 31f8f14803e..db5cd63b986 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx @@ -28,7 +28,7 @@ import setupPlugins from 'src/setup/setupPlugins'; import { getMockStoreWithNativeFilters } from 'spec/fixtures/mockStore'; import chartQueries, { sliceId } from 'spec/fixtures/mockChartQueries'; import { BinaryQueryObjectFilterClause, VizType } from '@superset-ui/core'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import DrillDetailMenuItems, { DrillDetailMenuItemsProps, } from './DrillDetailMenuItems'; diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx index 1059fc89517..6fef045ceaa 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx @@ -37,7 +37,7 @@ import { t, } from '@superset-ui/core'; import { useSelector } from 'react-redux'; -import { Menu } from 'src/components/Menu'; +import { Menu } from '@superset-ui/core/components/Menu'; import { RootState } from 'src/dashboard/types'; import { getSubmenuYOffset } from '../utils'; import { MenuItemTooltip } from '../DisabledMenuItemTooltip'; diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailModal.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailModal.tsx index a826216ac06..915e968609c 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailModal.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailModal.tsx @@ -26,7 +26,7 @@ import { t, useTheme, } from '@superset-ui/core'; -import { Button, Modal } from 'src/components'; +import { Button, Modal } from '@superset-ui/core/components'; import { useSelector } from 'react-redux'; import { DashboardPageIdContext } from 'src/dashboard/containers/DashboardPage'; import { Slice } from 'src/types/Chart'; diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx index 191423f805f..62b82f03e27 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx @@ -37,13 +37,16 @@ import { useTheme, } from '@superset-ui/core'; import { useResizeDetector } from 'react-resize-detector'; -import BooleanCell from 'src/components/Table/cell-renderers/BooleanCell'; -import NullCell from 'src/components/Table/cell-renderers/NullCell'; -import TimeCell from 'src/components/Table/cell-renderers/TimeCell'; -import { EmptyState, Loading } from 'src/components'; +import BooleanCell from '@superset-ui/core/components/Table/cell-renderers/BooleanCell'; +import NullCell from '@superset-ui/core/components/Table/cell-renderers/NullCell'; +import TimeCell from '@superset-ui/core/components/Table/cell-renderers/TimeCell'; +import { EmptyState, Loading } from '@superset-ui/core/components'; import { getDatasourceSamples } from 'src/components/Chart/chartAction'; -import Table, { ColumnsType, TableSize } from 'src/components/Table'; -import HeaderWithRadioGroup from 'src/components/Table/header-renderers/HeaderWithRadioGroup'; +import Table, { + ColumnsType, + TableSize, +} from '@superset-ui/core/components/Table'; +import HeaderWithRadioGroup from '@superset-ui/core/components/Table/header-renderers/HeaderWithRadioGroup'; import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; import { useDatasetMetadataBar } from 'src/features/datasets/metadataBar/useDatasetMetadataBar'; import TableControls from './DrillDetailTableControls'; diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailTableControls.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailTableControls.tsx index eecf312e14f..27f3fee8e01 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailTableControls.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailTableControls.tsx @@ -27,7 +27,7 @@ import { useTheme, } from '@superset-ui/core'; import RowCountLabel from 'src/explore/components/RowCountLabel'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; export type TableControlsProps = { filters: BinaryQueryObjectFilterClause[]; diff --git a/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx b/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx index 29102cbe050..89e246ed1b5 100644 --- a/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx +++ b/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx @@ -19,8 +19,8 @@ import { ReactNode, CSSProperties } from 'react'; import { css, truncationCSS, useCSSTextTruncation } from '@superset-ui/core'; -import { Menu } from 'src/components/Menu'; -import { Tooltip } from 'src/components'; +import { Menu } from '@superset-ui/core/components/Menu'; +import { Tooltip } from '@superset-ui/core/components'; import { MenuItemProps } from 'antd'; export type MenuItemWithTruncationProps = { diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index a12ae44e2b1..575402b525f 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -43,7 +43,7 @@ import { updateDataMask } from 'src/dataMask/actions'; import { waitForAsyncData } from 'src/middleware/asyncEvent'; import { ensureAppRoot } from 'src/utils/pathUtils'; import { safeStringify } from 'src/utils/safeStringify'; -import { extendedDayjs } from 'src/utils/dates'; +import { extendedDayjs } from '@superset-ui/core/utils/dates'; export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED'; export function chartUpdateStarted(queryController, latestQueryFormData, key) { diff --git a/superset-frontend/src/components/Chart/chartReducer.ts b/superset-frontend/src/components/Chart/chartReducer.ts index 997c5bf7b7c..081bd415472 100644 --- a/superset-frontend/src/components/Chart/chartReducer.ts +++ b/superset-frontend/src/components/Chart/chartReducer.ts @@ -24,7 +24,7 @@ import { DatasourcesAction } from 'src/dashboard/actions/datasources'; import { ChartState } from 'src/explore/types'; import { getFormDataFromControls } from 'src/explore/controlUtils'; import { HYDRATE_EXPLORE } from 'src/explore/actions/hydrateExplore'; -import { now } from 'src/utils/dates'; +import { now } from '@superset-ui/core/utils/dates'; import * as actions from './chartAction'; export const chart: ChartState = { diff --git a/superset-frontend/src/components/CopyToClipboard/CopyToClipboard.stories.tsx b/superset-frontend/src/components/CopyToClipboard/CopyToClipboard.stories.tsx index c725ce032df..64ea320157a 100644 --- a/superset-frontend/src/components/CopyToClipboard/CopyToClipboard.stories.tsx +++ b/superset-frontend/src/components/CopyToClipboard/CopyToClipboard.stories.tsx @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import ToastContainer from 'src/components/MessageToasts/ToastContainer'; -import { Button } from '../Button'; +import { Button } from '@superset-ui/core/components'; import { CopyToClipboard } from '.'; export default { diff --git a/superset-frontend/src/components/CopyToClipboard/index.tsx b/superset-frontend/src/components/CopyToClipboard/index.tsx index 019bdc3b0b6..92263d261f7 100644 --- a/superset-frontend/src/components/CopyToClipboard/index.tsx +++ b/superset-frontend/src/components/CopyToClipboard/index.tsx @@ -19,8 +19,8 @@ import { Component, cloneElement, ReactElement } from 'react'; import { t } from '@superset-ui/core'; import copyTextToClipboard from 'src/utils/copy'; +import { Tooltip } from '@superset-ui/core/components'; import withToasts from '../MessageToasts/withToasts'; -import { Tooltip } from '../Tooltip'; import type { CopyToClipboardProps } from './types'; const defaultProps: Partial = { diff --git a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx index 957d5c33f32..a409f3a4576 100644 --- a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx +++ b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx @@ -27,7 +27,7 @@ import { waitFor, } from 'spec/helpers/testing-library'; import { api } from 'src/hooks/apiResources/queryApi'; -import { EmptyState } from '../EmptyState'; +import { EmptyState } from '@superset-ui/core/components'; import { DatabaseSelector } from '.'; import type { DatabaseSelectorProps } from './types'; @@ -215,7 +215,7 @@ test('Refresh should work', async () => { name: 'Select schema or type to search schemas', }); - userEvent.click(select); + await userEvent.click(select); await waitFor(() => { expect(fetchMock.calls(databaseApiRoute).length).toBe(1); @@ -226,7 +226,7 @@ test('Refresh should work', async () => { }); // click schema reload - userEvent.click(screen.getByRole('button', { name: 'sync' })); + await userEvent.click(screen.getByRole('button', { name: 'sync' })); await waitFor(() => { expect(fetchMock.calls(databaseApiRoute).length).toBe(1); @@ -244,7 +244,7 @@ test('Should database select display options', async () => { name: 'Select database or type to search databases', }); expect(select).toBeInTheDocument(); - userEvent.click(select); + await userEvent.click(select); expect(await screen.findByText('test-mysql')).toBeInTheDocument(); }); @@ -261,7 +261,7 @@ test('should display options in order of the api response', async () => { name: 'Select database or type to search databases', }); expect(select).toBeInTheDocument(); - userEvent.click(select); + await userEvent.click(select); const options = await screen.findAllByRole('option'); expect(options[0]).toHaveTextContent( @@ -291,7 +291,7 @@ test('Should fetch the search keyword when total count exceeds initial options', expect(fetchMock.calls(databaseApiRoute)).toHaveLength(1), ); expect(select).toBeInTheDocument(); - userEvent.type(select, 'keywordtest'); + await userEvent.type(select, 'keywordtest'); await waitFor(() => expect(fetchMock.calls(databaseApiRoute)).toHaveLength(2), ); @@ -315,7 +315,7 @@ test('should show empty state if there are no options', async () => { const select = screen.getByRole('combobox', { name: 'Select database or type to search databases', }); - userEvent.click(select); + await userEvent.click(select); const emptystate = await screen.findByText('empty'); expect(emptystate).toBeInTheDocument(); expect(screen.queryByText('test-mysql')).not.toBeInTheDocument(); @@ -328,7 +328,7 @@ test('Should schema select display options', async () => { name: 'Select schema or type to search schemas', }); expect(select).toBeInTheDocument(); - userEvent.click(select); + await userEvent.click(select); await waitFor(() => { expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); }); @@ -348,8 +348,8 @@ test('Sends the correct db when changing the database', async () => { name: 'Select database or type to search databases', }); expect(select).toBeInTheDocument(); - userEvent.click(select); - userEvent.click(await screen.findByText('test-mysql')); + await userEvent.click(select); + await userEvent.click(await screen.findByText('test-mysql')); await waitFor(() => expect(props.onDbChange).toHaveBeenCalledWith( expect.objectContaining({ @@ -374,9 +374,9 @@ test('Sends the correct schema when changing the schema', async () => { name: 'Select schema or type to search schemas', }); expect(select).toBeInTheDocument(); - userEvent.click(select); + await userEvent.click(select); const schemaOption = await screen.findByText('information_schema'); - userEvent.click(schemaOption); + await userEvent.click(schemaOption); await waitFor(() => expect(props.onSchemaChange).toHaveBeenCalledWith('information_schema'), ); diff --git a/superset-frontend/src/components/DatabaseSelector/index.tsx b/superset-frontend/src/components/DatabaseSelector/index.tsx index 1399b8e91a1..7f7eb792bdb 100644 --- a/superset-frontend/src/components/DatabaseSelector/index.tsx +++ b/superset-frontend/src/components/DatabaseSelector/index.tsx @@ -26,7 +26,7 @@ import { } from 'react'; import { styled, SupersetClient, SupersetError, t } from '@superset-ui/core'; import rison from 'rison'; -import RefreshLabel from 'src/components/RefreshLabel'; +import RefreshLabel from '@superset-ui/core/components/RefreshLabel'; import { useToasts } from 'src/components/MessageToasts/withToasts'; import { useCatalogs, @@ -34,12 +34,15 @@ import { useSchemas, SchemaOption, } from 'src/hooks/apiResources'; -import { Label } from '../Label'; -import { Select, AsyncSelect } from '../Select'; -import { FormLabel } from '../Form'; -import { ErrorMessageWithStackTrace } from '../ErrorMessage'; +import { + Select, + AsyncSelect, + Label, + FormLabel, + LabeledValue as AntdLabeledValue, +} from '@superset-ui/core/components'; -import type { LabeledValue as AntdLabeledValue } from '../Select'; +import { ErrorMessageWithStackTrace } from 'src/components'; import type { DatabaseSelectorProps, DatabaseValue, diff --git a/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx b/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx index 8331ede7feb..e0cafe52e80 100644 --- a/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx +++ b/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx @@ -31,24 +31,30 @@ import { styled, getClientErrorObject, } from '@superset-ui/core'; -import TableView, { EmptyWrapperType } from 'src/components/TableView'; -import { ServerPagination, SortByType } from 'src/components/TableView/types'; +import { + Alert, + Button, + Constants, + EmptyWrapperType, + Input, + Loading, + Modal, + TableView, +} from '@superset-ui/core/components'; +import { + ServerPagination, + SortByType, +} from '@superset-ui/core/components/TableView/types'; +import { FacePile } from 'src/components'; import { useListViewResource } from 'src/views/CRUD/hooks'; import Dataset from 'src/types/Dataset'; import { useDebouncedEffect } from 'src/explore/exploreUtils'; -import { SLOW_DEBOUNCE } from 'src/constants'; import { PAGE_SIZE as DATASET_PAGE_SIZE, SORT_BY as DATASET_SORT_BY, } from 'src/features/datasets/constants'; import withToasts from 'src/components/MessageToasts/withToasts'; import { InputRef } from 'antd'; -import { Loading } from '../Loading'; -import { Input } from '../Input'; -import { FacePile } from '../FacePile'; -import { Button } from '../Button'; -import { Alert } from '../Alert'; -import { Modal } from '../Modal'; import type { Datasource, ChangeDatasourceModalProps } from './types'; const CONFIRM_WARNING_MESSAGE = t( @@ -135,7 +141,7 @@ const ChangeDatasourceModal: FunctionComponent = ({ }), }); }, - SLOW_DEBOUNCE, + Constants.SLOW_DEBOUNCE, [filter, pageIndex, sortBy], ); diff --git a/superset-frontend/src/components/Datasource/CollectionTable.tsx b/superset-frontend/src/components/Datasource/CollectionTable.tsx index 63bfb2ebf9d..adb135a0ab7 100644 --- a/superset-frontend/src/components/Datasource/CollectionTable.tsx +++ b/superset-frontend/src/components/Datasource/CollectionTable.tsx @@ -20,12 +20,17 @@ import { PureComponent, ReactNode } from 'react'; import { nanoid } from 'nanoid'; -import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import { t, styled, css } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons, Button, InfoTooltip } from '@superset-ui/core/components'; import { FilterValue } from 'react-table'; -import { Button } from '../Button'; +import Table, { + type ColumnsType, + type SortOrder, + type SorterResult, + type TablePaginationConfig, + TableSize, +} from '@superset-ui/core/components/Table'; import Fieldset from './Fieldset'; import { recurseReactClone } from './utils'; import { @@ -33,13 +38,6 @@ import { type CRUDCollectionState, type Sort, } from './types'; -import Table, { - type ColumnsType, - type SortOrder, - type SorterResult, - type TablePaginationConfig, - TableSize, -} from '../Table'; const CrudButtonWrapper = styled.div` text-align: right; @@ -324,7 +322,7 @@ export default class CRUDCollection extends PureComponent< {tooltip && ( <> {' '} - ({ ...jest.requireActual('@superset-ui/core'), isFeatureEnabled: jest.fn(), @@ -64,7 +67,7 @@ describe('DatasourceEditor', () => { afterEach(() => { fetchMock.restore(); - jest.clearAllMocks(); + // jest.clearAllMocks(); }); it('renders Tabs', () => { @@ -73,7 +76,7 @@ describe('DatasourceEditor', () => { it('can sync columns from source', async () => { const columnsTab = screen.getByTestId('collection-tab-Columns'); - userEvent.click(columnsTab); + await userEvent.click(columnsTab); const syncButton = screen.getByText(/sync columns from source/i); expect(syncButton).toBeInTheDocument(); @@ -90,7 +93,7 @@ describe('DatasourceEditor', () => { ); }); - userEvent.click(syncButton); + await userEvent.click(syncButton); // Wait for the fetch to be called const url = await fetchPromise; @@ -100,12 +103,12 @@ describe('DatasourceEditor', () => { // to add, remove and modify columns accordingly it('can modify columns', async () => { const columnsTab = screen.getByTestId('collection-tab-Columns'); - userEvent.click(columnsTab); + await userEvent.click(columnsTab); const getToggles = screen.getAllByRole('button', { name: /expand row/i, }); - userEvent.click(getToggles[0]); + await userEvent.click(getToggles[0]); const getTextboxes = await screen.findAllByRole('textbox'); expect(getTextboxes.length).toBeGreaterThanOrEqual(5); @@ -118,22 +121,22 @@ describe('DatasourceEditor', () => { 'Certification details', ); - userEvent.type(inputLabel, 'test_label'); - userEvent.type(inputDescription, 'test'); - userEvent.type(inputDtmFormat, 'test'); - userEvent.type(inputCertifiedBy, 'test'); - userEvent.type(inputCertDetails, 'test'); + await userEvent.type(inputLabel, 'test_label'); + await userEvent.type(inputDescription, 'test'); + await userEvent.type(inputDtmFormat, 'test'); + await userEvent.type(inputCertifiedBy, 'test'); + await userEvent.type(inputCertDetails, 'test'); }); it('can delete columns', async () => { const columnsTab = screen.getByTestId('collection-tab-Columns'); - userEvent.click(columnsTab); + await userEvent.click(columnsTab); const getToggles = screen.getAllByRole('button', { name: /expand row/i, }); - userEvent.click(getToggles[0]); + await userEvent.click(getToggles[0]); const deleteButtons = await screen.findAllByRole('button', { name: /delete item/i, @@ -141,7 +144,7 @@ describe('DatasourceEditor', () => { const initialCount = deleteButtons.length; expect(initialCount).toBeGreaterThan(0); - userEvent.click(deleteButtons[0]); + await userEvent.click(deleteButtons[0]); await waitFor(() => { const countRows = screen.getAllByRole('button', { name: /delete item/i }); @@ -151,14 +154,14 @@ describe('DatasourceEditor', () => { it('can add new columns', async () => { const calcColsTab = screen.getByTestId('collection-tab-Calculated columns'); - userEvent.click(calcColsTab); + await userEvent.click(calcColsTab); const addBtn = screen.getByRole('button', { name: /add item/i, }); expect(addBtn).toBeInTheDocument(); - userEvent.click(addBtn); + await userEvent.click(addBtn); // newColumn (Column name) is the first textbox in the tab await waitFor(() => { @@ -167,11 +170,11 @@ describe('DatasourceEditor', () => { }); }); - it('renders isSqla fields', () => { + it('renders isSqla fields', async () => { const columnsTab = screen.getByRole('tab', { name: /settings/i, }); - userEvent.click(columnsTab); + await userEvent.click(columnsTab); const extraField = screen.getAllByText(/extra/i); expect(extraField.length).toBeGreaterThan(0); @@ -203,9 +206,9 @@ describe('DatasourceEditor Source Tab', () => { isFeatureEnabled.mockRestore(); }); - it('Source Tab: edit mode', () => { + it('Source Tab: edit mode', async () => { const getLockBtn = screen.getByRole('img', { name: /lock/i }); - userEvent.click(getLockBtn); + await userEvent.click(getLockBtn); const physicalRadioBtn = screen.getByRole('radio', { name: /physical \(table or view\)/i, diff --git a/superset-frontend/src/components/Datasource/DatasourceEditorCurrency.test.jsx b/superset-frontend/src/components/Datasource/DatasourceEditorCurrency.test.jsx index 6ccf06c17a6..9fdff4fb3c0 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditorCurrency.test.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditorCurrency.test.jsx @@ -19,7 +19,7 @@ import fetchMock from 'fetch-mock'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; import userEvent from '@testing-library/user-event'; -import DatasourceEditor from 'src/components/Datasource/DatasourceEditor'; +import DatasourceEditor from './DatasourceEditor'; import { props, DATASOURCE_ENDPOINT } from './DatasourceEditor.test'; // Optimized render function that doesn't use waitFor initially diff --git a/superset-frontend/src/components/Datasource/DatasourceEditorRTL.test.jsx b/superset-frontend/src/components/Datasource/DatasourceEditorRTL.test.jsx index 41f46110a7b..5a4b869e7a7 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditorRTL.test.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditorRTL.test.jsx @@ -17,8 +17,7 @@ * under the License. */ import fetchMock from 'fetch-mock'; -import { screen, waitFor } from 'spec/helpers/testing-library'; -import userEvent from '@testing-library/user-event'; +import { screen, userEvent, waitFor } from 'spec/helpers/testing-library'; import { props, asyncRender, @@ -39,10 +38,10 @@ describe('DatasourceEditor RTL Metrics Tests', () => { await asyncRender(props); const metricButton = screen.getByTestId('collection-tab-Metrics'); - userEvent.click(metricButton); + await userEvent.click(metricButton); const expandToggle = await screen.findAllByLabelText(/expand row/i); - userEvent.click(expandToggle[0]); + await userEvent.click(expandToggle[0]); const certificationDetails = await screen.findByPlaceholderText( /certification details/i, @@ -57,15 +56,15 @@ describe('DatasourceEditor RTL Metrics Tests', () => { await asyncRender(props); const metricButton = screen.getByTestId('collection-tab-Metrics'); - userEvent.click(metricButton); + await userEvent.click(metricButton); const expandToggle = await screen.findAllByLabelText(/expand row/i); - userEvent.click(expandToggle[1]); + await userEvent.click(expandToggle[1]); const certifiedBy = await screen.findByPlaceholderText(/certified by/i); // Use userEvent.clear and userEvent.type instead of directly setting value - userEvent.clear(certifiedBy); - userEvent.type(certifiedBy, 'I am typing a new name'); + await userEvent.clear(certifiedBy); + await userEvent.type(certifiedBy, 'I am typing a new name'); const certificationDetails = await screen.findByPlaceholderText( /certification details/i, @@ -74,8 +73,8 @@ describe('DatasourceEditor RTL Metrics Tests', () => { expect(certifiedBy.value).toEqual('I am typing a new name'); }); - userEvent.clear(certificationDetails); - userEvent.type(certificationDetails, 'I am typing something new'); + await userEvent.clear(certificationDetails); + await userEvent.type(certificationDetails, 'I am typing something new'); await waitFor(() => { expect(certificationDetails.value).toEqual('I am typing something new'); @@ -97,7 +96,7 @@ describe('DatasourceEditor RTL Columns Tests', () => { await asyncRender(props); const columnsButton = screen.getByTestId('collection-tab-Columns'); - userEvent.click(columnsButton); + await userEvent.click(columnsButton); const dsDefaultDatetimeRadio = screen.getByTestId('radio-default-dttm-ds'); expect(dsDefaultDatetimeRadio).toBeChecked(); @@ -112,7 +111,7 @@ describe('DatasourceEditor RTL Columns Tests', () => { await asyncRender(props); const columnsButton = screen.getByTestId('collection-tab-Columns'); - userEvent.click(columnsButton); + await userEvent.click(columnsButton); const dsDefaultDatetimeRadio = screen.getByTestId('radio-default-dttm-ds'); expect(dsDefaultDatetimeRadio).toBeEnabled(); diff --git a/superset-frontend/src/components/Datasource/DatasourceModal.tsx b/superset-frontend/src/components/Datasource/DatasourceModal.tsx index 02ec1fbc49d..b5db44b8b16 100644 --- a/superset-frontend/src/components/Datasource/DatasourceModal.tsx +++ b/superset-frontend/src/components/Datasource/DatasourceModal.tsx @@ -29,8 +29,15 @@ import { css, } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { + Icons, + Alert, + Button, + Modal, + AsyncEsmComponent, +} from '@superset-ui/core/components'; import withToasts from 'src/components/MessageToasts/withToasts'; +import { ErrorMessageWithStackTrace } from 'src/components'; import { startMetaDataLoading, stopMetaDataLoading, @@ -41,11 +48,6 @@ import { updateColumns, } from 'src/components/Datasource/utils'; import type { DatasetObject } from 'src/features/datasets/types'; -import { ErrorMessageWithStackTrace } from '../ErrorMessage'; -import { AsyncEsmComponent } from '../AsyncEsmComponent'; -import { Button } from '../Button'; -import { Alert } from '../Alert'; -import { Modal } from '../Modal'; import type { DatasourceModalProps } from './types'; const DatasourceEditor = AsyncEsmComponent(() => import('./DatasourceEditor')); diff --git a/superset-frontend/src/components/Datasource/Field.test.tsx b/superset-frontend/src/components/Datasource/Field.test.tsx index f04af96c231..3f2d3ee8c98 100644 --- a/superset-frontend/src/components/Datasource/Field.test.tsx +++ b/superset-frontend/src/components/Datasource/Field.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { fireEvent, render, screen } from 'spec/helpers/testing-library'; -import { Input } from '../Input'; +import { Input } from '@superset-ui/core/components'; import Field from './Field'; diff --git a/superset-frontend/src/components/Datasource/Field.tsx b/superset-frontend/src/components/Datasource/Field.tsx index a392dadd7c6..e228f378479 100644 --- a/superset-frontend/src/components/Datasource/Field.tsx +++ b/superset-frontend/src/components/Datasource/Field.tsx @@ -19,9 +19,12 @@ import { useCallback, ReactNode, ReactElement, cloneElement } from 'react'; import { css, SupersetTheme, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import { FormItem, FormLabel } from '../Form'; -import { Tooltip } from '../Tooltip'; +import { + Icons, + Tooltip, + FormItem, + FormLabel, +} from '@superset-ui/core/components'; const formItemInlineCss = css` .ant-form-item-control-input-content { diff --git a/superset-frontend/src/components/Datasource/Fieldset.tsx b/superset-frontend/src/components/Datasource/Fieldset.tsx index 4ca185b1354..cf1efd4434d 100644 --- a/superset-frontend/src/components/Datasource/Fieldset.tsx +++ b/superset-frontend/src/components/Datasource/Fieldset.tsx @@ -17,11 +17,9 @@ * under the License. */ import { ReactNode, useCallback } from 'react'; -import { Divider } from '../Divider'; -import { Typography } from '../Typography'; +import { Divider, Form, Typography } from '@superset-ui/core/components'; import { recurseReactClone } from './utils'; import Field from './Field'; -import { Form } from '../Form'; interface FieldsetProps { children: ReactNode; diff --git a/superset-frontend/src/components/DropdownContainer/DropdownContainer.test.tsx b/superset-frontend/src/components/DropdownContainer/DropdownContainer.test.tsx deleted file mode 100644 index 69dcba0f340..00000000000 --- a/superset-frontend/src/components/DropdownContainer/DropdownContainer.test.tsx +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { screen, render, userEvent } from 'spec/helpers/testing-library'; -import { Icons } from 'src/components/Icons'; -import { Button } from '../Button'; -import { DropdownContainer } from '.'; - -const generateItems = (n: number) => - Array.from({ length: n }).map((_, i) => ({ - id: `el-${i + 1}`, - element: , - })); - -const ITEMS = generateItems(10); - -const mockOverflowingIndex = async ( - overflowingIndex: number, - func: Function, -) => { - const spy = jest.spyOn(global.React, 'useState'); - spy.mockImplementation(() => [overflowingIndex, jest.fn()]); - await func(); - spy.mockRestore(); -}; - -test('renders children', () => { - render(); - expect(screen.getByText('Element 1')).toBeInTheDocument(); - expect(screen.getByText('Element 2')).toBeInTheDocument(); - expect(screen.getByText('Element 3')).toBeInTheDocument(); -}); - -test('renders children with custom horizontal spacing', () => { - render(); - expect(screen.getByTestId('container')).toHaveStyle('gap: 20px'); -}); - -test('renders a dropdown trigger when overflowing', async () => { - await mockOverflowingIndex(3, () => { - render(); - expect(screen.getByText('More')).toBeInTheDocument(); - }); -}); - -test('renders a dropdown trigger with custom icon', async () => { - await mockOverflowingIndex(3, async () => { - render( - } - />, - ); - expect( - await screen.findByRole('img', { name: 'link' }), - ).toBeInTheDocument(); - }); -}); - -test('renders a dropdown trigger with custom text', async () => { - await mockOverflowingIndex(3, () => { - const customText = 'Custom text'; - render( - , - ); - expect(screen.getByText(customText)).toBeInTheDocument(); - }); -}); - -test('renders a dropdown trigger with custom count', async () => { - await mockOverflowingIndex(3, () => { - const customCount = 99; - render( - , - ); - expect(screen.getByTitle(customCount)).toBeInTheDocument(); - }); -}); - -test('does not render a dropdown button when not overflowing', () => { - render(); - expect(screen.queryByText('More')).not.toBeInTheDocument(); -}); - -test('renders a dropdown when overflowing', async () => { - await mockOverflowingIndex(3, () => { - render(); - userEvent.click(screen.getByText('More')); - expect(screen.getByTestId('dropdown-content')).toBeInTheDocument(); - }); -}); - -test('renders children with custom vertical spacing', async () => { - await mockOverflowingIndex(3, () => { - render(); - userEvent.click(screen.getByText('More')); - expect(screen.getByTestId('dropdown-content')).toHaveStyle('gap: 20px'); - }); -}); - -test('fires event when overflowing state changes', async () => { - await mockOverflowingIndex(3, () => { - const onOverflowingStateChange = jest.fn(); - render( - , - ); - expect(onOverflowingStateChange).toHaveBeenCalledWith({ - notOverflowed: ['el-1', 'el-2', 'el-3'], - overflowed: ['el-4', 'el-5'], - }); - }); -}); - -test('renders a dropdown with custom content', async () => { - await mockOverflowingIndex(3, () => { - const customDropdownContent =
Custom content
; - render( - customDropdownContent} - />, - ); - userEvent.click(screen.getByText('More')); - expect(screen.getByText('Custom content')).toBeInTheDocument(); - }); -}); - -test('Shows tooltip on dropdown trigger hover', async () => { - await mockOverflowingIndex(3, async () => { - render( - , - ); - userEvent.hover(screen.getByText('More')); - expect(await screen.findByText('Test tooltip')).toBeInTheDocument(); - }); -}); diff --git a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx index 3b9f1a70490..17048e1e53a 100644 --- a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx @@ -22,7 +22,7 @@ import { ErrorLevel, supersetTheme } from '@superset-ui/core'; import { BasicErrorAlert } from './BasicErrorAlert'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx index 27a90054b61..218fbfd43df 100644 --- a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx +++ b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx @@ -17,7 +17,7 @@ * under the License. */ import { ErrorLevel, styled, themeObject, useTheme } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components'; const StyledContent = styled.div` display: flex; diff --git a/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx b/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx index fd8ddee9e0c..41367081224 100644 --- a/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx @@ -22,7 +22,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library'; import { DatabaseErrorMessage } from './DatabaseErrorMessage'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx b/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx index 76d5eefa416..cfe1b61a606 100644 --- a/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx @@ -22,7 +22,7 @@ import { render, screen } from 'spec/helpers/testing-library'; import { DatasetNotFoundErrorMessage } from './DatasetNotFoundErrorMessage'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx b/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx index e746afd747b..5ae44b2f738 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx @@ -17,9 +17,7 @@ * under the License. */ import { Meta, StoryFn } from '@storybook/react'; -import { Layout } from '../Layout'; -import { Card } from '../Card'; -import { Row, Col } from '../Grid'; +import { Card, Col, Layout, Row } from '@superset-ui/core/components'; import { ErrorAlert } from './ErrorAlert'; const { Content } = Layout; diff --git a/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx b/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx index b6f819f409d..2538b1e8008 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx @@ -17,8 +17,7 @@ * under the License. */ -import { screen, fireEvent } from '@testing-library/react'; -import { render } from 'spec/helpers/testing-library'; +import { screen, fireEvent, render } from 'spec/helpers/testing-library'; import { ErrorAlert } from './ErrorAlert'; describe('ErrorAlert', () => { diff --git a/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx b/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx index 1bb843fbc90..1c503de955c 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx @@ -17,13 +17,15 @@ * under the License. */ import { useState } from 'react'; -import { Icons } from 'src/components/Icons'; import { t, useTheme } from '@superset-ui/core'; -import { Tooltip } from '../Tooltip'; -import { Alert } from '../Alert'; -import { Modal } from '../Modal'; +import { + Alert, + Icons, + Modal, + Tooltip, + Typography, +} from '@superset-ui/core/components'; import type { ErrorAlertProps } from './types'; -import { Typography } from '../Typography'; export const ErrorAlert: React.FC = ({ errorType = t('Error'), diff --git a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx index b9003b5bfec..b27ff32d00a 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx @@ -23,7 +23,7 @@ import { ErrorMessageWithStackTrace } from './ErrorMessageWithStackTrace'; import { BasicErrorAlert } from './BasicErrorAlert'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx index fe9b840e553..c28e5b11366 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx @@ -18,7 +18,7 @@ */ import { ReactNode } from 'react'; import { ErrorSource, t, SupersetError } from '@superset-ui/core'; -import { Typography } from 'src/components/Typography'; +import { Typography } from '@superset-ui/core/components'; import { getErrorMessageComponentRegistry } from './getErrorMessageComponentRegistry'; import { ErrorAlert } from './ErrorAlert'; diff --git a/superset-frontend/src/components/ErrorMessage/FrontendNetworkErrorMessage.test.tsx b/superset-frontend/src/components/ErrorMessage/FrontendNetworkErrorMessage.test.tsx index 32026052eed..c7a1175efa9 100644 --- a/superset-frontend/src/components/ErrorMessage/FrontendNetworkErrorMessage.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/FrontendNetworkErrorMessage.test.tsx @@ -22,7 +22,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library'; import { FrontendNetworkErrorMessage } from './FrontendNetworkErrorMessage'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/IssueCode.tsx b/superset-frontend/src/components/ErrorMessage/IssueCode.tsx index e0aacdbaab0..62e71c572bb 100644 --- a/superset-frontend/src/components/ErrorMessage/IssueCode.tsx +++ b/superset-frontend/src/components/ErrorMessage/IssueCode.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components'; import { useTheme } from '@superset-ui/core'; interface IssueCodeProps { diff --git a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx index 2dbaa6f55ea..6612abd5be0 100644 --- a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx +++ b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx @@ -19,10 +19,8 @@ import { JSONTree } from 'react-json-tree'; import { t } from '@superset-ui/core'; import { useJsonTreeTheme } from 'src/hooks/useJsonTreeTheme'; -import { Collapse } from '../Collapse'; +import { Collapse, List, Typography } from '@superset-ui/core/components'; import type { ErrorMessageComponentProps } from './types'; -import { List } from '../List'; -import { Typography } from '../Typography'; interface MarshmallowErrorExtra { messages: object; diff --git a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx index 1ad69a21d0a..80a0f7e5500 100644 --- a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx @@ -22,7 +22,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library'; import { ParameterErrorMessage } from './ParameterErrorMessage'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.tsx b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.tsx index f1f8990b93e..9a9047fedac 100644 --- a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.tsx +++ b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.tsx @@ -20,10 +20,10 @@ import { ReactNode } from 'react'; import { t, tn } from '@superset-ui/core'; import levenshtein from 'js-levenshtein'; +import { List } from '@superset-ui/core/components'; import { ErrorMessageComponentProps } from './types'; import { IssueCode } from './IssueCode'; import { ErrorAlert } from './ErrorAlert'; -import { List } from '../List'; interface ParameterErrorExtra { undefined_parameters?: string[]; diff --git a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx index fa10f0a474c..7ceb0062c42 100644 --- a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx +++ b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx @@ -22,7 +22,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library'; import { TimeoutErrorMessage } from './TimeoutErrorMessage'; jest.mock( - 'src/components/Icons/AsyncIcon', + '@superset-ui/core/components/Icons/AsyncIcon', () => ({ fileName }: { fileName: string }) => ( diff --git a/superset-frontend/src/components/FacePile/index.tsx b/superset-frontend/src/components/FacePile/index.tsx index 8f59e9d6cb5..220209afc2d 100644 --- a/superset-frontend/src/components/FacePile/index.tsx +++ b/superset-frontend/src/components/FacePile/index.tsx @@ -23,7 +23,7 @@ import { FeatureFlag, } from '@superset-ui/core'; import getOwnerName from 'src/utils/getOwnerName'; -import { Avatar, AvatarGroup, Tooltip } from 'src/components'; +import { Avatar, AvatarGroup, Tooltip } from '@superset-ui/core/components'; import { ensureAppRoot } from 'src/utils/pathUtils'; import { getRandomColor } from './utils'; import type { FacePileProps } from './types'; diff --git a/superset-frontend/src/components/FilterableTable/index.tsx b/superset-frontend/src/components/FilterableTable/index.tsx index 989aad50315..e414bc7d80c 100644 --- a/superset-frontend/src/components/FilterableTable/index.tsx +++ b/superset-frontend/src/components/FilterableTable/index.tsx @@ -18,9 +18,9 @@ */ import { useMemo, useRef, useCallback } from 'react'; import { styled } from '@superset-ui/core'; -import type { ColDef } from '../GridTable/types'; -import { GridSize } from '../GridTable/constants'; -import { GridTable } from '../GridTable'; +import { GridSize } from 'src/components/GridTable/constants'; +import { GridTable } from 'src/components/GridTable'; +import { type ColDef } from 'src/components/GridTable/types'; import { useCellContentParser } from './useCellContentParser'; import { renderResultCell } from './utils'; diff --git a/superset-frontend/src/components/GridTable/Header.test.tsx b/superset-frontend/src/components/GridTable/Header.test.tsx index cbd3a677126..9976df6c814 100644 --- a/superset-frontend/src/components/GridTable/Header.test.tsx +++ b/superset-frontend/src/components/GridTable/Header.test.tsx @@ -21,12 +21,12 @@ import { act, fireEvent, render } from 'spec/helpers/testing-library'; import { Header } from './Header'; import { PIVOT_COL_ID } from './constants'; -jest.mock('src/components/Dropdown', () => ({ +jest.mock('@superset-ui/core/components/Dropdown', () => ({ Dropdown: () =>
, })); -jest.mock('src/components/Icons', () => { - const actualIcons = jest.requireActual('src/components/Icons'); +jest.mock('@superset-ui/core/components/Icons', () => { + const actualIcons = jest.requireActual('@superset-ui/core/components/Icons'); return { __esModule: true, Icons: { diff --git a/superset-frontend/src/components/GridTable/Header.tsx b/superset-frontend/src/components/GridTable/Header.tsx index eb2acb919bc..467918d5ec6 100644 --- a/superset-frontend/src/components/GridTable/Header.tsx +++ b/superset-frontend/src/components/GridTable/Header.tsx @@ -20,7 +20,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { styled, useTheme, t } from '@superset-ui/core'; import type { Column, GridApi } from 'ag-grid-community'; -import { Icons } from 'src/components/Icons'; +import { Icons } from '@superset-ui/core/components/Icons'; import { PIVOT_COL_ID } from './constants'; import { HeaderMenu } from './HeaderMenu'; diff --git a/superset-frontend/src/components/GridTable/HeaderMenu.test.tsx b/superset-frontend/src/components/GridTable/HeaderMenu.test.tsx index 525383425ee..72a5948d592 100644 --- a/superset-frontend/src/components/GridTable/HeaderMenu.test.tsx +++ b/superset-frontend/src/components/GridTable/HeaderMenu.test.tsx @@ -25,7 +25,7 @@ import { } from 'spec/helpers/testing-library'; import { HeaderMenu } from './HeaderMenu'; -jest.mock('src/components/Menu', () => { +jest.mock('@superset-ui/core/components/Menu', () => { const Menu = ({ children }: { children: React.ReactChild }) => (
{children}
); @@ -58,7 +58,7 @@ jest.mock('src/components/Menu', () => { return { Menu }; }); -jest.mock('src/components/Dropdown', () => ({ +jest.mock('@superset-ui/core/components/Dropdown', () => ({ MenuDotsDropdown: ({ overlay }: { overlay: React.ReactChild }) => (
{overlay}
), @@ -181,7 +181,7 @@ test('renders unhide when invisible column exists', async () => { }); describe('for main menu', () => { - test('renders Copy to Clipboard', async () => { + it('renders Copy to Clipboard', async () => { const { getByText } = render(); fireEvent.click(getByText('Copy the current data')); await waitFor(() => @@ -194,7 +194,7 @@ describe('for main menu', () => { }); }); - test('renders Download to CSV', async () => { + it('renders Download to CSV', async () => { const { getByText } = render(); fireEvent.click(getByText('Download to CSV')); await waitFor(() => @@ -205,7 +205,7 @@ describe('for main menu', () => { }); }); - test('renders autosize column', async () => { + it('renders autosize column', async () => { const { getByText } = render(); fireEvent.click(getByText('Autosize all columns')); await waitFor(() => @@ -213,7 +213,7 @@ describe('for main menu', () => { ); }); - test('renders all unhide all hidden columns when multiple invisible columns exist', async () => { + it('renders all unhide all hidden columns when multiple invisible columns exist', async () => { render( { ); }); - test('reset columns configuration', async () => { + it('reset columns configuration', async () => { const { getByText } = render( ({ ); return ( - + <> css` #grid-table.ag-theme-quartz { @@ -216,7 +215,7 @@ export function GridTable({ onCellKeyDown={onKeyDown} />
- + ); } diff --git a/superset-frontend/src/components/ImportModal/ErrorAlert.tsx b/superset-frontend/src/components/ImportModal/ErrorAlert.tsx index f2c14867a12..0d81b818e94 100644 --- a/superset-frontend/src/components/ImportModal/ErrorAlert.tsx +++ b/superset-frontend/src/components/ImportModal/ErrorAlert.tsx @@ -21,7 +21,7 @@ import { FunctionComponent } from 'react'; import { t, SupersetTheme } from '@superset-ui/core'; import { getDatabaseDocumentationLinks } from 'src/views/CRUD/hooks'; -import { Alert } from '../Alert'; +import { Alert } from '@superset-ui/core/components'; import { antdWarningAlertStyles } from './styles'; const supersetTextDocs = getDatabaseDocumentationLinks(); diff --git a/superset-frontend/src/components/ImportModal/ImportErrorAlert.tsx b/superset-frontend/src/components/ImportModal/ImportErrorAlert.tsx index 7579f941514..f835f6d9733 100644 --- a/superset-frontend/src/components/ImportModal/ImportErrorAlert.tsx +++ b/superset-frontend/src/components/ImportModal/ImportErrorAlert.tsx @@ -21,7 +21,7 @@ import { FunctionComponent } from 'react'; import { t } from '@superset-ui/core'; import { getDatabaseDocumentationLinks } from 'src/views/CRUD/hooks'; -import { ErrorAlert } from '../ErrorMessage'; +import { ErrorAlert } from 'src/components'; const supersetTextDocs = getDatabaseDocumentationLinks(); export const DOCUMENTATION_LINK = supersetTextDocs diff --git a/superset-frontend/src/components/ImportModal/index.tsx b/superset-frontend/src/components/ImportModal/index.tsx index 1a39c91a107..7cbc2de069a 100644 --- a/superset-frontend/src/components/ImportModal/index.tsx +++ b/superset-frontend/src/components/ImportModal/index.tsx @@ -19,10 +19,12 @@ import { FunctionComponent, useEffect, useState, ChangeEvent } from 'react'; import { styled, t, css } from '@superset-ui/core'; import { useImportResource } from 'src/views/CRUD/hooks'; -import { Upload, type UploadChangeParam, type UploadFile } from '../Upload'; -import { Button } from '../Button'; -import { Input } from '../Input'; -import { Modal } from '../Modal'; +import { + Upload, + type UploadChangeParam, + type UploadFile, +} from '@superset-ui/core/components/Upload'; +import { Button, Input, Modal } from '@superset-ui/core/components'; import { ImportErrorAlert } from './ImportErrorAlert'; import type { ImportModelsModalProps } from './types'; diff --git a/superset-frontend/src/components/InfoTooltip/index.tsx b/superset-frontend/src/components/InfoTooltip/index.tsx deleted file mode 100644 index 668b956e7bd..00000000000 --- a/superset-frontend/src/components/InfoTooltip/index.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { styled, useTheme, css } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import { Tooltip } from '../Tooltip'; -import type { InfoTooltipProps } from './types'; - -const StyledTooltip = styled(Tooltip)` - cursor: pointer; -`; - -const StyledTooltipTitle = styled.span` - display: -webkit-box; - -webkit-line-clamp: 20; - -webkit-box-orient: vertical; - overflow: hidden; - text-overflow: ellipsis; -`; - -const defaultOverlayStyle = { - fontSize: '12px', - lineHeight: '16px', -}; -const InfoIconContainer = styled.div` - ${({ theme }) => css` - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - margin-left: ${theme.sizeUnit}px; - `} -`; - -export function InfoTooltip({ - tooltip, - iconStyle = {}, - placement = 'right', - trigger = 'hover', - overlayStyle = defaultOverlayStyle, - bgColor, - viewBox = '0 -1 24 24', -}: InfoTooltipProps) { - const theme = useTheme(); - const alteredIconStyle = { - ...iconStyle, - color: iconStyle.color || theme.colorIcon, - }; - return ( - {tooltip}} - placement={placement} - trigger={trigger} - overlayStyle={overlayStyle} - color={bgColor} - > - - - - - ); -} - -export type { InfoTooltipProps }; diff --git a/superset-frontend/src/components/JsonModal/index.tsx b/superset-frontend/src/components/JsonModal/index.tsx index 57052d31f7d..f108c3dc19b 100644 --- a/superset-frontend/src/components/JsonModal/index.tsx +++ b/superset-frontend/src/components/JsonModal/index.tsx @@ -38,9 +38,8 @@ import { FC, useMemo } from 'react'; import { JSONTree } from 'react-json-tree'; import { useJsonTreeTheme } from 'src/hooks/useJsonTreeTheme'; -import { Button } from '../Button'; +import { Button, ModalTrigger } from '@superset-ui/core/components'; import { CopyToClipboard } from '../CopyToClipboard'; -import ModalTrigger from '../ModalTrigger'; import { convertBigIntStrToNumber } from './utils'; import type { JsonModalProps } from './types'; diff --git a/superset-frontend/src/components/ListView/ActionsBar.tsx b/superset-frontend/src/components/ListView/ActionsBar.tsx index 321ff2bbb60..e802005de74 100644 --- a/superset-frontend/src/components/ListView/ActionsBar.tsx +++ b/superset-frontend/src/components/ListView/ActionsBar.tsx @@ -37,9 +37,12 @@ */ import { ReactElement } from 'react'; import { styled } from '@superset-ui/core'; -import { Icons, IconNameType } from 'src/components/Icons'; -import { Tooltip } from '../Tooltip'; -import { TooltipPlacement } from '../Tooltip/types'; +import { + Icons, + IconNameType, + Tooltip, + type TooltipPlacement, +} from '@superset-ui/core/components'; export type ActionProps = { label: string; diff --git a/superset-frontend/src/components/ListView/CardSortSelect.tsx b/superset-frontend/src/components/ListView/CardSortSelect.tsx index 3a8ec86e7ac..9be9b7cc1bb 100644 --- a/superset-frontend/src/components/ListView/CardSortSelect.tsx +++ b/superset-frontend/src/components/ListView/CardSortSelect.tsx @@ -18,8 +18,7 @@ */ import { useState, useMemo } from 'react'; import { styled, t } from '@superset-ui/core'; -import { FormLabel } from '../Form'; -import { Select } from '../Select'; +import { FormLabel, Select } from '@superset-ui/core/components'; import { SELECT_WIDTH } from './utils'; import { CardSortSelectOption, SortColumn } from './types'; diff --git a/superset-frontend/src/components/ListView/CrossLinksTooltip.test.tsx b/superset-frontend/src/components/ListView/CrossLinksTooltip.test.tsx index b17b417269f..08a863c9875 100644 --- a/superset-frontend/src/components/ListView/CrossLinksTooltip.test.tsx +++ b/superset-frontend/src/components/ListView/CrossLinksTooltip.test.tsx @@ -65,7 +65,7 @@ test('should render', () => { test('should render multiple links', async () => { setup(); - userEvent.hover(screen.getByText('Hover me')); + await userEvent.hover(screen.getByText('Hover me')); await waitFor(() => { expect(screen.getByText('Test dashboard')).toBeInTheDocument(); @@ -76,9 +76,9 @@ test('should render multiple links', async () => { }); }); -test('should not render the "+ {x} more"', () => { +test('should not render the "+ {x} more"', async () => { setup(); - userEvent.hover(screen.getByText('Hover me')); + await userEvent.hover(screen.getByText('Hover me')); expect(screen.queryByTestId('plus-more')).not.toBeInTheDocument(); }); @@ -86,7 +86,7 @@ test('should render the "+ {x} more"', async () => { setup({ moreItems: 3, }); - userEvent.hover(screen.getByText('Hover me')); + await userEvent.hover(screen.getByText('Hover me')); expect(await screen.findByTestId('plus-more')).toBeInTheDocument(); expect(await screen.findByText('+ 3 more')).toBeInTheDocument(); }); diff --git a/superset-frontend/src/components/ListView/CrossLinksTooltip.tsx b/superset-frontend/src/components/ListView/CrossLinksTooltip.tsx index 723cfd7d6e7..52517869ab7 100644 --- a/superset-frontend/src/components/ListView/CrossLinksTooltip.tsx +++ b/superset-frontend/src/components/ListView/CrossLinksTooltip.tsx @@ -19,7 +19,7 @@ import { ReactNode } from 'react'; import { styled, t } from '@superset-ui/core'; import { Link } from 'react-router-dom'; -import { Tooltip } from '../Tooltip'; +import { Tooltip } from '@superset-ui/core/components'; export type CrossLinksTooltipProps = { children: ReactNode; diff --git a/superset-frontend/src/components/ListView/Filters/DateRange.tsx b/superset-frontend/src/components/ListView/Filters/DateRange.tsx index 326374e59f5..619880a5775 100644 --- a/superset-frontend/src/components/ListView/Filters/DateRange.tsx +++ b/superset-frontend/src/components/ListView/Filters/DateRange.tsx @@ -25,13 +25,15 @@ import { } from 'react'; import { styled, t } from '@superset-ui/core'; -import { extendedDayjs } from 'src/utils/dates'; import { Dayjs } from 'dayjs'; import { useLocale } from 'src/hooks/useLocale'; -import { Loading } from '../../Loading'; -import { AntdThemeProvider } from '../../AntdThemeProvider'; -import { FormLabel } from '../../Form'; -import { RangePicker } from '../../DatePicker'; +import { extendedDayjs } from '@superset-ui/core/utils/dates'; +import { + AntdThemeProvider, + Loading, + FormLabel, + RangePicker, +} from '@superset-ui/core/components'; import { BaseFilter, FilterHandler } from './Base'; interface DateRangeFilterProps extends BaseFilter { diff --git a/superset-frontend/src/components/ListView/Filters/NumericalRange.tsx b/superset-frontend/src/components/ListView/Filters/NumericalRange.tsx index 0283015fecb..53c94b79c93 100644 --- a/superset-frontend/src/components/ListView/Filters/NumericalRange.tsx +++ b/superset-frontend/src/components/ListView/Filters/NumericalRange.tsx @@ -18,8 +18,8 @@ */ import { useState, forwardRef, useImperativeHandle, RefObject } from 'react'; import { styled, t } from '@superset-ui/core'; -import { InputNumber } from 'src/components/Input'; -import { FormLabel } from 'src/components/Form'; +import { InputNumber } from '@superset-ui/core/components/Input'; +import { FormLabel } from '@superset-ui/core/components/Form'; import { BaseFilter, FilterHandler } from './Base'; const RangeFilterContainer = styled.div` diff --git a/superset-frontend/src/components/ListView/Filters/Search.tsx b/superset-frontend/src/components/ListView/Filters/Search.tsx index c1a163b53ae..0ca61d72c8b 100644 --- a/superset-frontend/src/components/ListView/Filters/Search.tsx +++ b/superset-frontend/src/components/ListView/Filters/Search.tsx @@ -25,10 +25,12 @@ import { } from 'react'; import { t, styled, useTheme, css } from '@superset-ui/core'; -import { Icons } from 'src/components/Icons'; -import { FormLabel } from '../../Form'; -import { Input } from '../../Input'; -import { InfoTooltip } from '../../InfoTooltip'; +import { + Input, + InfoTooltip, + FormLabel, + Icons, +} from '@superset-ui/core/components'; import { BaseFilter, FilterHandler, FilterContainer } from './Base'; interface SearchHeaderProps extends BaseFilter { @@ -81,9 +83,7 @@ function SearchFilter( `} > {Header} - {toolTipDescription && ( - - )} + {toolTipDescription && }
{ const tableSelect = screen.getByRole('combobox', { name: 'Select table or type to search tables', }); - userEvent.click(tableSelect); + await userEvent.click(tableSelect); expect(await screen.findByText('table_a')).toBeInTheDocument(); expect( screen.queryByRole('option', { name: /Select All/i }), @@ -138,7 +138,7 @@ test('renders table options without Select All option', async () => { }); await act(async () => { - userEvent.click(tableSelect); + await userEvent.click(tableSelect); }); await waitFor( @@ -171,7 +171,7 @@ test('table select retain value if not in SQL Lab mode', async () => { expect(getSelectItemContainer(tableSelect)).toHaveLength(0); await act(async () => { - userEvent.click(tableSelect); + await userEvent.click(tableSelect); }); await waitFor( @@ -182,7 +182,7 @@ test('table select retain value if not in SQL Lab mode', async () => { ); await act(async () => { - userEvent.click(screen.getByText('table_a')); + await userEvent.click(screen.getByText('table_a')); }); await waitFor( @@ -242,16 +242,16 @@ test('table multi select retain all the values selected', async () => { expect(screen.queryByText('table_a')).not.toBeInTheDocument(); expect(getSelectItemContainer(tableSelect)).toHaveLength(0); - userEvent.click(tableSelect); + await userEvent.click(tableSelect); await waitFor(async () => { const item = await screen.findAllByText('table_b'); - userEvent.click(item[item.length - 1]); + await userEvent.click(item[item.length - 1]); }); await waitFor(async () => { const item = await screen.findAllByText('table_c'); - userEvent.click(item[item.length - 1]); + await userEvent.click(item[item.length - 1]); }); const selections = await screen.findAllByRole('option', { selected: true }); diff --git a/superset-frontend/src/components/TableSelector/index.tsx b/superset-frontend/src/components/TableSelector/index.tsx index 7fa1b53a4f4..a557a7c0339 100644 --- a/superset-frontend/src/components/TableSelector/index.tsx +++ b/superset-frontend/src/components/TableSelector/index.tsx @@ -23,7 +23,7 @@ import { useMemo, useEffect, } from 'react'; -import type { SelectValue } from 'src/components'; +import type { SelectValue } from '@superset-ui/core/components'; import { styled, @@ -34,13 +34,13 @@ import { import { FormLabel, CertifiedBadge, - DatabaseSelector, Select, -} from 'src/components'; -import { Icons } from 'src/components/Icons'; +} from '@superset-ui/core/components'; +import { DatabaseSelector } from 'src/components'; +import { Icons } from '@superset-ui/core/components/Icons'; import type { DatabaseObject } from 'src/components/DatabaseSelector/types'; -import RefreshLabel from 'src/components/RefreshLabel'; -import WarningIconWithTooltip from 'src/components/WarningIconWithTooltip'; +import RefreshLabel from '@superset-ui/core/components/RefreshLabel'; +import WarningIconWithTooltip from '@superset-ui/core/components/WarningIconWithTooltip'; import { useToasts } from 'src/components/MessageToasts/withToasts'; import { useTables, Table } from 'src/hooks/apiResources'; diff --git a/superset-frontend/src/components/InfoTooltip/types.ts b/superset-frontend/src/components/Tag/TagType.ts similarity index 57% rename from superset-frontend/src/components/InfoTooltip/types.ts rename to superset-frontend/src/components/Tag/TagType.ts index 1c5e9c44fb0..e7165234a38 100644 --- a/superset-frontend/src/components/InfoTooltip/types.ts +++ b/superset-frontend/src/components/Tag/TagType.ts @@ -16,27 +16,26 @@ * specific language governing permissions and limitations * under the License. */ -import { ActionType } from 'src/types/Action'; +import { CSSProperties, MouseEventHandler, ReactNode } from 'react'; +import { SerializedStyles } from '@emotion/react'; -export interface InfoTooltipProps { - iconStyle?: React.CSSProperties; - tooltip: string; - placement?: - | 'bottom' - | 'left' - | 'right' - | 'top' - | 'topLeft' - | 'topRight' - | 'bottomLeft' - | 'bottomRight' - | 'leftTop' - | 'leftBottom' - | 'rightTop' - | 'rightBottom' - | undefined; - trigger?: ActionType | ActionType[]; - overlayStyle?: any; - bgColor?: string; - viewBox?: string; +export interface TagType { + id?: number; + className?: string; + type?: string | number; + editable?: boolean; + onDelete?: (index: number) => void; + onClick?: MouseEventHandler; + onMouseDown?: MouseEventHandler; + onClose?: () => void; + color?: string; + name?: string; + index?: number; + toolTipTitle?: string; + children?: ReactNode; + role?: string; + style?: CSSProperties; + icon?: ReactNode; + css?: SerializedStyles; + closable?: boolean; } diff --git a/superset-frontend/src/components/Tag/index.tsx b/superset-frontend/src/components/Tag/index.tsx index b9065686136..503bc9fef1d 100644 --- a/superset-frontend/src/components/Tag/index.tsx +++ b/superset-frontend/src/components/Tag/index.tsx @@ -20,11 +20,10 @@ import { styled } from '@superset-ui/core'; import { Link } from 'react-router-dom'; import TagType from 'src/types/TagType'; -import { Tag as AntdTag } from 'antd'; +import { Tag as AntdTag, Tooltip } from '@superset-ui/core/components'; import type { TagProps } from 'antd/es'; import type { CheckableTagProps } from 'antd/es/tag'; import { useMemo } from 'react'; -import { Tooltip } from '../Tooltip'; const StyledTag = styled(AntdTag)` ${({ theme }) => ` @@ -103,4 +102,4 @@ const SupersetTag = ({ export const Tag = Object.assign(SupersetTag, { CheckableTag: AntdTag.CheckableTag, }); -export type { TagProps, CheckableTagProps }; +export type { TagProps, CheckableTagProps, TagType }; diff --git a/superset-frontend/src/components/TagsList/TagsList.stories.tsx b/superset-frontend/src/components/TagsList/TagsList.stories.tsx index e2eb2e77757..75c1a5fcd22 100644 --- a/superset-frontend/src/components/TagsList/TagsList.stories.tsx +++ b/superset-frontend/src/components/TagsList/TagsList.stories.tsx @@ -17,7 +17,7 @@ * under the License. */ import { Meta, StoryObj } from '@storybook/react'; -import TagsList, { type TagsListProps } from 'src/components/TagsList'; +import { TagsList, type TagsListProps } from 'src/components/TagsList'; export default { title: 'Components/TagsList', diff --git a/superset-frontend/src/components/TagsList/TagsList.test.tsx b/superset-frontend/src/components/TagsList/TagsList.test.tsx index 6d4eb048b64..d8001bb6e65 100644 --- a/superset-frontend/src/components/TagsList/TagsList.test.tsx +++ b/superset-frontend/src/components/TagsList/TagsList.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import { render, waitFor } from 'spec/helpers/testing-library'; -import TagsList, { TagsListProps } from '.'; +import { TagsList, TagsListProps } from '.'; const testTags = [ { diff --git a/superset-frontend/src/components/TagsList/index.tsx b/superset-frontend/src/components/TagsList/index.tsx index d63d73f0743..61086bf28ea 100644 --- a/superset-frontend/src/components/TagsList/index.tsx +++ b/superset-frontend/src/components/TagsList/index.tsx @@ -41,7 +41,7 @@ const TagsDiv = styled.div` flex-wrap: wrap; `; -const TagsList = ({ +export const TagsList = ({ tags, editable = false, onDelete, @@ -112,5 +112,3 @@ const TagsList = ({ ); }; - -export default TagsList; diff --git a/superset-frontend/src/components/index.ts b/superset-frontend/src/components/index.ts index 7cef78f5a60..09d50bb315a 100644 --- a/superset-frontend/src/components/index.ts +++ b/superset-frontend/src/components/index.ts @@ -16,154 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - -/* - * Re-exporting of components in src/components to facilitate - * their imports by other components. - * E.g. import { Select } from 'src/components', probably in the future from '@superset-ui/components' - */ -export { AntdThemeProvider } from './AntdThemeProvider'; -export { Alert, type AlertProps } from './Alert'; -export { Icons } from './Icons'; -export { - AsyncEsmComponent, - type PlaceholderProps as AsyncEsmPlaceholderProps, -} from './AsyncEsmComponent'; -export { - AsyncAceEditor, - CssEditor, - JsonEditor, - SQLEditor, - FullSQLEditor, - MarkdownEditor, - TextAreaEditor, - ConfigEditor, - type AsyncAceEditorProps, - type Editor, -} from './AsyncAceEditor'; -export { AlteredSliceTag, type AlteredSliceTagProps } from './AlteredSliceTag'; -export { ModifiedInfo, type ModifiedInfoProps } from './AuditInfo'; -export { AutoComplete, type AutoCompleteProps } from './AutoComplete'; -export { - Avatar, - AvatarGroup, - type AvatarProps, - type AvatarGroupProps, -} from './Avatar'; -export { Badge, type BadgeProps } from './Badge'; -export { Tooltip, type TooltipProps } from './Tooltip'; -export { Button, type ButtonProps, type OnClickHandler } from './Button'; -export { ButtonGroup, type ButtonGroupProps } from './ButtonGroup'; -export { Breadcrumb, type BreadcrumbProps } from './Breadcrumb'; -export { CachedLabel, type CacheLabelProps } from './CachedLabel'; -export { Card } from './Card'; -export { CertifiedBadge } from './CertifiedBadge'; -export { - Checkbox, - type CheckboxProps, - type CheckboxChangeEvent, -} from './Checkbox'; -export { - Collapse, - type CollapseProps, - CollapseLabelInModal, - type CollapseLabelInModalProps, -} from './Collapse'; -export { - ConfirmStatusChange, - type ConfirmStatusChangeProps, -} from './ConfirmStatusChange'; -export { CopyToClipboard, type CopyToClipboardProps } from './CopyToClipboard'; -export { CronPicker, type CronError } from './CronPicker'; -export { DatabaseSelector, type DatabaseObject } from './DatabaseSelector'; -export { - DatasourceModal, - ChangeDatasourceModal, - type DatasourceModalProps, - type ChangeDatasourceModalProps, -} from './Datasource'; -export { - DatePicker, - RangePicker, - type DatePickerProps, - type RangePickerProps, -} from './DatePicker'; -export { DeleteModal, type DeleteModalProps } from './DeleteModal'; -export { Divider, type DividerProps } from './Divider'; -export { - Dropdown, - MenuDotsDropdown, - NoAnimationDropdown, - type DropdownProps, - type NoAnimationDropdownProps, - type MenuDotsDropdownProps, -} from './Dropdown'; -export { DropdownButton, type DropdownButtonProps } from './DropdownButton'; -export { - DropdownContainer, - type DropdownItem, - type DropdownRef, -} from './DropdownContainer'; -export { - DynamicEditableTitle, - type DynamicEditableTitleProps, -} from './DynamicEditableTitle'; -export { - DynamicPluginProvider, - PluginContext, - usePluginContext, - type PluginContextType, -} from './DynamicPlugins'; -export { EditableTitle, type EditableTitleProps } from './EditableTitle'; -export { EmptyState, type EmptyStateProps } from './EmptyState'; -export { Empty, type EmptyProps } from './EmptyState/Empty'; -export { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary'; -export * from './ErrorMessage'; -export { FacePile, type FacePileProps } from './FacePile'; -export { FaveStar, type FaveStarProps } from './FaveStar'; -export { - Modal, - FormModal, - StyledModal, - type ModalProps, - type FormModalProps, -} from './Modal'; -export { FilterableTable, type FilterableTableProps } from './FilterableTable'; -export { FlashProvider, type FlashMessage } from './FlashProvider'; -export { Flex, type FlexProps } from './Flex'; -export { - Form, - FormItem, - FormLabel, - LabeledErrorBoundInput, - type FormInstance, - type FormProps, - type FormItemProps, -} from './Form'; -export { GenericLink } from './GenericLink'; -export { Grid, Row, Col, type RowProps, type ColProps } from './Grid'; -export { GridTable, type TableProps } from './GridTable'; -export { IconButton, type IconButtonProps } from './IconButton'; -export { IconTooltip, type IconTooltipProps } from './IconTooltip'; -export { ImportModal, type ImportModelsModalProps } from './ImportModal'; -export { InfoTooltip, type InfoTooltipProps } from './InfoTooltip'; -export { - Input, - InputNumber, - type InputProps, - type TextAreaProps, - type InputNumberProps, -} from './Input'; -export { JsonModal, type JsonModalProps } from './JsonModal'; -export { - Label, - DatasetTypeLabel, - PublishedLabel, - type LabelType, -} from './Label'; -export { LastUpdated, type LastUpdatedProps } from './LastUpdated'; -export { Layout, type LayoutProps, type SiderProps } from './Layout'; -export { List, type ListProps, type ListItemProps } from './List'; +export * from './CopyToClipboard'; +export * from './FilterableTable'; +export * from './AlteredSliceTag'; export { ListView, ListViewActionsBar, @@ -177,40 +32,21 @@ export { type ListViewFetchDataConfig, type ListViewFilterValue, } from './ListView'; +export { DatabaseSelector, type DatabaseObject } from './DatabaseSelector'; +export * from './Datasource'; +export * from './ErrorMessage'; +export { ImportModal, type ImportModelsModalProps } from './ImportModal'; +export { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary'; +export * from './GenericLink'; +export { FlashProvider, type FlashMessage } from './FlashProvider'; +export { GridTable, type TableProps } from './GridTable'; +export * from './Tag'; +export * from './TagsList'; +export { ModifiedInfo, type ModifiedInfoProps } from './AuditInfo'; export { - ListViewCard, - ImageLoader, - type ListViewCardProps, -} from './ListViewCard'; -export { Loading, type LoadingProps } from './Loading'; - -export { - Select, - AsyncSelect, - type SelectProps, - type SelectValue, - type SelectOptionsType, - type LabeledValue, - type RefSelectProps, -} from './Select'; - -export { Steps, type StepsProps } from './Steps'; - -export { Space, type SpaceProps } from './Space'; - -export { Skeleton, type SkeletonProps } from './Skeleton'; - -export { Switch, type SwitchProps } from './Switch'; - -export { Tag } from './Tag'; - -export { TreeSelect, type TreeSelectProps } from './TreeSelect'; - -export { - Typography, - type TypographyProps, - type ParagraphProps, -} from './Typography'; - -export { Image, type ImageProps } from './Image'; -export { Upload, type UploadFile, type UploadChangeParam } from './Upload'; + DynamicPluginProvider, + PluginContext, + usePluginContext, + type PluginContextType, +} from './DynamicPlugins'; +export * from './FacePile'; diff --git a/superset-frontend/src/constants.ts b/superset-frontend/src/constants.ts index 98abb6c2b12..4dc734651d5 100644 --- a/superset-frontend/src/constants.ts +++ b/superset-frontend/src/constants.ts @@ -16,20 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { - t, - DEFAULT_D3_FORMAT, - DEFAULT_D3_TIME_FORMAT, -} from '@superset-ui/core'; +import { DEFAULT_D3_FORMAT, DEFAULT_D3_TIME_FORMAT } from '@superset-ui/core'; import { BootstrapData, CommonBootstrapData } from './types/bootstrapTypes'; export const DATETIME_WITH_TIME_ZONE = 'YYYY-MM-DD HH:mm:ssZ'; export const TIME_WITH_MS = 'HH:mm:ss.SSS'; -export const BOOL_TRUE_DISPLAY = 'True'; -export const BOOL_FALSE_DISPLAY = 'False'; - export const URL_PARAMS = { standalone: { name: 'standalone', @@ -127,21 +120,6 @@ export const RESERVED_DASHBOARD_URL_PARAMS: string[] = [ URL_PARAMS.preselectFilters.name, ]; -/** - * Faster debounce delay for inputs without expensive operation. - */ -export const FAST_DEBOUNCE = 250; - -/** - * Slower debounce delay for inputs with expensive API calls. - */ -export const SLOW_DEBOUNCE = 500; - -/** - * Display null as `N/A` - */ -export const NULL_DISPLAY = t('N/A'); - export const DEFAULT_COMMON_BOOTSTRAP_DATA: CommonBootstrapData = { application_root: '/', static_assets_prefix: '', diff --git a/superset-frontend/src/dashboard/components/AddSliceCard/AddSliceCard.tsx b/superset-frontend/src/dashboard/components/AddSliceCard/AddSliceCard.tsx index b93e9f4b726..d684456a98c 100644 --- a/superset-frontend/src/dashboard/components/AddSliceCard/AddSliceCard.tsx +++ b/superset-frontend/src/dashboard/components/AddSliceCard/AddSliceCard.tsx @@ -30,12 +30,8 @@ import { } from 'react'; import { t, isFeatureEnabled, FeatureFlag, css } from '@superset-ui/core'; -import { - GenericLink, - Tooltip, - usePluginContext, - ImageLoader, -} from 'src/components'; +import { Tooltip, ImageLoader } from '@superset-ui/core/components'; +import { GenericLink, usePluginContext } from 'src/components'; import { assetUrl } from 'src/utils/assetUrl'; import { Theme } from '@emotion/react'; diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane/index.tsx b/superset-frontend/src/dashboard/components/BuilderComponentPane/index.tsx index 0aaa6d886b7..e279d3e35a4 100644 --- a/superset-frontend/src/dashboard/components/BuilderComponentPane/index.tsx +++ b/superset-frontend/src/dashboard/components/BuilderComponentPane/index.tsx @@ -18,7 +18,7 @@ */ /* eslint-env browser */ import { rgba } from 'emotion-rgba'; -import Tabs from 'src/components/Tabs'; +import Tabs from '@superset-ui/core/components/Tabs'; import { t, css, SupersetTheme } from '@superset-ui/core'; import SliceAdder from 'src/dashboard/containers/SliceAdder'; import dashboardComponents from 'src/visualizations/presets/dashboardComponents'; diff --git a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx index fbaadf89128..63bdea50792 100644 --- a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx +++ b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx @@ -22,12 +22,12 @@ import { userEvent, waitFor, } from 'spec/helpers/testing-library'; -import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor'; +import { CssEditor as AceCssEditor } from '@superset-ui/core/components/AsyncAceEditor'; import { IAceEditorProps } from 'react-ace'; import fetchMock from 'fetch-mock'; import CssEditor from '.'; -jest.mock('src/components/AsyncAceEditor', () => ({ +jest.mock('@superset-ui/core/components/AsyncAceEditor', () => ({ CssEditor: ({ value, onChange }: IAceEditorProps) => (