You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by am...@apache.org on 2022/02/09 15:45:59 UTC

[superset] branch master updated: feat: Dynamic dashboard component (#17208)

This is an automated email from the ASF dual-hosted git repository.

amitmiran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new bcad1ac  feat: Dynamic dashboard component (#17208)
bcad1ac is described below

commit bcad1acec27823756dc403f6e982f5e59ec6d6cf
Author: simcha90 <56...@users.noreply.github.com>
AuthorDate: Wed Feb 9 17:44:40 2022 +0200

    feat: Dynamic dashboard component (#17208)
    
    * fix:fix get permission function
    
    * feat: dynamic loading of dashboard components
    
    * fix: revert image
    
    * fix: fix py
    
    * fix: fix py
    
    * fix: pass state to dynamic component
    
    * lint: add typing
    
    * lint: fix lint
    
    * lint: fix lint
    
    * refactor: re-run pipeline
    
    * fix: fix CR notes
    
    * fix: fix CR notes
    
    * move types and interfaces to core
    
    * reorder exports
    
    * rename Scope and Target
    
    Co-authored-by: Ville Brofeldt <vi...@gmail.com>
---
 .../superset-ui-core/src/dashboard/index.ts}       |  11 +-
 .../superset-ui-core/src/dashboard/types/Base.ts}  |  49 +++++-
 .../packages/superset-ui-core/src/index.ts         |   2 +
 .../spec/fixtures/mockNativeFilters.ts             |  10 +-
 .../src/dashboard/actions/nativeFilters.ts         |  16 +-
 .../dashboard/components/BuilderComponentPane.tsx  |  10 ++
 .../CrossFilterScopingForm/index.tsx               |   4 +-
 .../components/CrossFilterScopingModal/types.ts    |   4 +-
 .../DashboardBuilder/DashboardContainer.tsx        |   3 +-
 .../dashboard/components/DashboardBuilder/state.ts |   2 +-
 .../dashboard/components/FiltersBadge/index.tsx    |   3 +-
 .../dashboard/components/FiltersBadge/selectors.ts |   8 +-
 .../components/gridComponents/DynamicComponent.tsx | 177 +++++++++++++++++++++
 .../dashboard/components/gridComponents/index.js   |   4 +
 .../gridComponents/new/DraggableNewComponent.jsx   |   4 +-
 .../new/NewDynamicComponent.tsx}                   |  28 +++-
 .../CascadeFilters/CascadeFilterControl/index.tsx  |   9 +-
 .../CascadeFilters/CascadePopover/index.tsx        |  12 +-
 .../FilterBar/CascadeFilters/types.ts              |   3 +-
 .../FilterBar/FilterConfigurationLink/index.tsx    |   3 +-
 .../FilterBar/FilterControls/FilterControls.tsx    |  14 +-
 .../FilterBar/FilterControls/state.ts              |   8 +-
 .../FilterBar/FilterControls/types.ts              |   4 +-
 .../FilterBar/FilterControls/utils.ts              |   2 +-
 .../FilterBar/FilterSets/EditSection.tsx           |   3 +-
 .../FilterBar/FilterSets/FilterSetUnit.tsx         |  11 +-
 .../FilterBar/FilterSets/FiltersHeader.tsx         |  12 +-
 .../nativeFilters/FilterBar/FilterSets/index.tsx   |  15 +-
 .../FilterSets/utils/findExistingFilterSet.test.ts |   2 +-
 .../FilterBar/FilterSets/utils/index.ts            |   4 +-
 .../nativeFilters/FilterBar/Header/index.tsx       |  11 +-
 .../components/nativeFilters/FilterBar/index.tsx   |  16 +-
 .../components/nativeFilters/FilterBar/state.ts    |  10 +-
 .../components/nativeFilters/FilterBar/utils.ts    |   9 +-
 .../FiltersConfigModal/DividerConfigForm.tsx       |   3 +-
 .../FiltersConfigModal/FilterConfigurePane.tsx     |   3 +-
 .../FiltersConfigModal/FilterTitlePane.tsx         |   3 +-
 .../FiltersConfigForm/FilterScope/FilterScope.tsx  |   7 +-
 .../FiltersConfigForm/FilterScope/ScopingTree.tsx  |   6 +-
 .../FiltersConfigForm/FilterScope/utils.ts         |  14 +-
 .../FiltersConfigForm/FiltersConfigForm.tsx        |   6 +-
 .../FiltersConfigForm/getControlItemsMap.test.tsx  |   5 +-
 .../FiltersConfigForm/getControlItemsMap.tsx       |   8 +-
 .../FiltersConfigModal/FiltersConfigForm/state.ts  |   3 +-
 .../FiltersConfigModal/FiltersConfigModal.tsx      |  16 +-
 .../nativeFilters/FiltersConfigModal/state.ts      |   2 +-
 .../nativeFilters/FiltersConfigModal/types.ts      |  10 +-
 .../nativeFilters/FiltersConfigModal/utils.ts      |  18 +--
 .../dashboard/components/nativeFilters/state.ts    |   2 +-
 .../dashboard/components/nativeFilters/utils.ts    |  12 +-
 .../src/dashboard/fixtures/mockNativeFilters.ts    |   8 +-
 .../src/dashboard/reducers/nativeFilters.ts        |   7 +-
 superset-frontend/src/dashboard/reducers/types.ts  |  27 +---
 superset-frontend/src/dashboard/types.ts           |   4 +-
 .../dashboard/util/activeAllDashboardFilters.ts    |  13 +-
 .../util/charts/getFormDataWithExtraFilters.ts     |  10 +-
 .../src/dashboard/util/componentIsResizable.ts     |  13 +-
 .../src/dashboard/util/componentTypes.ts           |   3 +
 superset-frontend/src/dashboard/util/constants.ts  |   1 +
 .../src/dashboard/util/filterboxMigrationHelper.ts |   6 +-
 .../dashboard/util/getDetailedComponentWidth.js    |   2 +
 .../util/getFormDataWithExtraFilters.test.ts       |   2 +-
 .../src/dashboard/util/isDashboardEmpty.ts         |   8 +-
 .../src/dashboard/util/isValidChild.ts             |   5 +
 .../src/dashboard/util/newComponentFactory.js      |   6 +
 superset-frontend/src/dataMask/actions.ts          |   4 +-
 superset-frontend/src/dataMask/reducer.ts          |  16 +-
 superset-frontend/src/preamble.ts                  |   3 +
 .../types.ts => setup/setupDasboardComponents.ts}  |  18 ++-
 superset-frontend/src/utils/functionalRegistry.ts  |  83 ++++++++++
 .../DashboardComponentsRegistry.ts                 |  62 ++++++++
 .../ExampleComponent/ExampleComponent.tsx}         |  22 +--
 .../dashboardComponents/ExampleComponent/index.ts} |  12 +-
 .../presets/dashboardComponents.ts}                |  17 +-
 74 files changed, 701 insertions(+), 252 deletions(-)

diff --git a/superset-frontend/src/dataMask/types.ts b/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts
similarity index 70%
copy from superset-frontend/src/dataMask/types.ts
copy to superset-frontend/packages/superset-ui-core/src/dashboard/index.ts
index 95d2073..10b785c 100644
--- a/superset-frontend/src/dataMask/types.ts
+++ b/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts
@@ -16,14 +16,5 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMask } from '@superset-ui/core';
 
-export enum DataMaskType {
-  NativeFilters = 'nativeFilters',
-  CrossFilters = 'crossFilters',
-}
-
-export type DataMaskState = { [id: string]: DataMask };
-
-export type DataMaskWithId = { id: string } & DataMask;
-export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
+export * from './types/Base';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/types.ts b/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts
similarity index 68%
rename from superset-frontend/src/dashboard/components/nativeFilters/types.ts
rename to superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts
index 85f1941..fbd631d 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/types.ts
+++ b/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts
@@ -19,20 +19,20 @@
 
 import { AdhocFilter, DataMask } from '@superset-ui/core';
 
-export interface Column {
+export interface NativeFilterColumn {
   name: string;
   displayName?: string;
 }
 
-export interface Scope {
+export interface NativeFilterScope {
   rootPath: string[];
   excluded: number[];
 }
 
 /** The target of a filter is the datasource/column being filtered */
-export interface Target {
+export interface NativeFilterTarget {
   datasetId: number;
-  column: Column;
+  column: NativeFilterColumn;
 
   // maybe someday support this?
   // show values from these columns in the filter options selector
@@ -44,16 +44,37 @@ export enum NativeFilterType {
   DIVIDER = 'DIVIDER',
 }
 
+export enum DataMaskType {
+  NativeFilters = 'nativeFilters',
+  CrossFilters = 'crossFilters',
+}
+
+export type DataMaskState = { [id: string]: DataMask };
+
+export type DataMaskWithId = { id: string } & DataMask;
+export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
+
+export type FilterSet = {
+  id: number;
+  name: string;
+  nativeFilters: Filters;
+  dataMask: DataMaskStateWithId;
+};
+
+export type FilterSets = {
+  [filtersSetId: string]: FilterSet;
+};
+
 export interface Filter {
   cascadeParentIds: string[];
   defaultDataMask: DataMask;
   id: string; // randomly generated at filter creation
   name: string;
-  scope: Scope;
+  scope: NativeFilterScope;
   filterType: string;
   // for now there will only ever be one target
   // when multiple targets are supported, change this to Target[]
-  targets: [Partial<Target>];
+  targets: [Partial<NativeFilterTarget>];
   controlValues: {
     [key: string]: any;
   };
@@ -70,6 +91,7 @@ export interface Filter {
   type: typeof NativeFilterType.NATIVE_FILTER;
   description: string;
 }
+
 export interface Divider {
   id: string;
   title: string;
@@ -78,3 +100,18 @@ export interface Divider {
 }
 
 export type FilterConfiguration = Array<Filter | Divider>;
+
+export type Filters = {
+  [filterId: string]: Filter;
+};
+
+export type NativeFiltersState = {
+  filters: Filters;
+  filterSets: FilterSets;
+  focusedFilterId?: string;
+};
+
+export type DashboardComponentMetadata = {
+  nativeFilters: NativeFiltersState;
+  dataMask: DataMaskStateWithId;
+};
diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts
index 7ea8f2a..23d972f 100644
--- a/superset-frontend/packages/superset-ui-core/src/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/index.ts
@@ -16,11 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 export * from './models';
 export * from './utils';
 export * from './types';
 export * from './translation';
 export * from './connection';
+export * from './dashboard';
 export * from './dynamic-plugins';
 export * from './query';
 export * from './number-format';
diff --git a/superset-frontend/spec/fixtures/mockNativeFilters.ts b/superset-frontend/spec/fixtures/mockNativeFilters.ts
index 1381ff4..516a2c5 100644
--- a/superset-frontend/spec/fixtures/mockNativeFilters.ts
+++ b/superset-frontend/spec/fixtures/mockNativeFilters.ts
@@ -16,10 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { ExtraFormData } from '@superset-ui/core';
-import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types';
-import { NativeFiltersState } from 'src/dashboard/reducers/types';
-import { DataMaskStateWithId } from '../../src/dataMask/types';
+import {
+  DataMaskStateWithId,
+  ExtraFormData,
+  NativeFiltersState,
+  NativeFilterType,
+} from '@superset-ui/core';
 
 export const nativeFilters: NativeFiltersState = {
   filterSets: {},
diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts
index 337d304..71cc01d 100644
--- a/superset-frontend/src/dashboard/actions/nativeFilters.ts
+++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts
@@ -17,21 +17,21 @@
  * under the License.
  */
 
-import { makeApi } from '@superset-ui/core';
+import {
+  FilterConfiguration,
+  Filters,
+  FilterSet,
+  FilterSets,
+  makeApi,
+} from '@superset-ui/core';
 import { Dispatch } from 'redux';
-import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types';
 import {
   SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL,
   setDataMaskForFilterConfigComplete,
 } from 'src/dataMask/actions';
 import { HYDRATE_DASHBOARD } from './hydrate';
 import { dashboardInfoChanged } from './dashboardInfo';
-import {
-  Filters,
-  FilterSet,
-  FilterSetFullData,
-  FilterSets,
-} from '../reducers/types';
+import { FilterSetFullData } from '../reducers/types';
 import { DashboardInfo, RootState } from '../types';
 
 export const SET_FILTER_CONFIG_BEGIN = 'SET_FILTER_CONFIG_BEGIN';
diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx b/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx
index 3d2cbbb..9d2c2fb 100644
--- a/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx
+++ b/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx
@@ -31,6 +31,8 @@ import NewRow from './gridComponents/new/NewRow';
 import NewTabs from './gridComponents/new/NewTabs';
 import NewMarkdown from './gridComponents/new/NewMarkdown';
 import SliceAdder from '../containers/SliceAdder';
+import dashboardComponents from '../../visualizations/presets/dashboardComponents';
+import NewDynamicComponent from './gridComponents/new/NewDynamicComponent';
 
 export interface BCPProps {
   isStandalone: boolean;
@@ -106,6 +108,14 @@ const BuilderComponentPane: React.FC<BCPProps> = ({
                       <NewHeader />
                       <NewMarkdown />
                       <NewDivider />
+                      {dashboardComponents
+                        .getAll()
+                        .map(({ key: componentKey, metadata }) => (
+                          <NewDynamicComponent
+                            metadata={metadata}
+                            componentKey={componentKey}
+                          />
+                        ))}
                     </Tabs.TabPane>
                     <Tabs.TabPane
                       key={2}
diff --git a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/CrossFilterScopingForm/index.tsx b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/CrossFilterScopingForm/index.tsx
index d1364f3..7ef5a5e 100644
--- a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/CrossFilterScopingForm/index.tsx
+++ b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/CrossFilterScopingForm/index.tsx
@@ -18,15 +18,15 @@
  */
 import React, { FC } from 'react';
 import { FormInstance } from 'antd/lib/form';
+import { NativeFilterScope } from '@superset-ui/core';
 import FilterScope from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope';
 import { setCrossFilterFieldValues } from 'src/dashboard/components/CrossFilterScopingModal/utils';
-import { Scope } from 'src/dashboard/components/nativeFilters/types';
 import { useForceUpdate } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils';
 import { CrossFilterScopingFormType } from 'src/dashboard/components/CrossFilterScopingModal/types';
 
 type CrossFilterScopingFormProps = {
   chartId: number;
-  scope: Scope;
+  scope: NativeFilterScope;
   form: FormInstance<CrossFilterScopingFormType>;
 };
 
diff --git a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts
index b56ffc0..6dfd11f 100644
--- a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts
+++ b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts
@@ -17,8 +17,8 @@
  * under the License.
  */
 
-import { Scope } from '../nativeFilters/types';
+import { NativeFilterScope } from '@superset-ui/core';
 
 export type CrossFilterScopingFormType = {
-  scope: Scope;
+  scope: NativeFilterScope;
 };
diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
index cce9bf7..aebb2a1 100644
--- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
+++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
@@ -20,7 +20,7 @@
 // when its container size changes, due to e.g., builder side panel opening
 import React, { FC, useEffect, useState } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
-import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core';
+import { FeatureFlag, Filters, isFeatureEnabled } from '@superset-ui/core';
 import { ParentSize } from '@vx/responsive';
 import Tabs from 'src/components/Tabs';
 import DashboardGrid from 'src/dashboard/containers/DashboardGrid';
@@ -31,7 +31,6 @@ import {
   DASHBOARD_ROOT_DEPTH,
 } from 'src/dashboard/util/constants';
 import { getRootLevelTabIndex, getRootLevelTabsComponent } from './utils';
-import { Filters } from '../../reducers/types';
 import { getChartIdsInFilterScope } from '../../util/activeDashboardFilters';
 import findTabIndexByComponentId from '../../util/findTabIndexByComponentId';
 import { findTabsWithChartsInScope } from '../nativeFilters/utils';
diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts
index 31cf5ae..51d255d 100644
--- a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts
+++ b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { useSelector } from 'react-redux';
+import { Filter } from '@superset-ui/core';
 import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
 import { useCallback, useEffect, useState, useContext } from 'react';
 import { URL_PARAMS } from 'src/constants';
@@ -27,7 +28,6 @@ import {
   useFilters,
   useNativeFiltersDataMask,
 } from '../nativeFilters/FilterBar/state';
-import { Filter } from '../nativeFilters/types';
 
 // eslint-disable-next-line import/prefer-default-export
 export const useNativeFilters = () => {
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
index 921d8db..3165348 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
@@ -20,9 +20,9 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import { uniqWith } from 'lodash';
 import cx from 'classnames';
+import { DataMaskStateWithId, Filters } from '@superset-ui/core';
 import Icons from 'src/components/Icons';
 import { usePrevious } from 'src/hooks/usePrevious';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import DetailsPanelPopover from './DetailsPanel';
 import { Pill } from './Styles';
 import {
@@ -38,7 +38,6 @@ import {
   DashboardLayout,
   RootState,
 } from '../../types';
-import { Filters } from '../../reducers/types';
 
 export interface FiltersBadgeProps {
   chartId: number;
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
index 695e2f9..3eafe24 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
@@ -17,19 +17,21 @@
  * under the License.
  */
 import {
+  DataMaskStateWithId,
+  DataMaskType,
   ensureIsArray,
   FeatureFlag,
+  Filters,
   FilterState,
   isFeatureEnabled,
+  NativeFilterType,
 } from '@superset-ui/core';
 import { NO_TIME_RANGE, TIME_FILTER_MAP } from 'src/explore/constants';
 import { getChartIdsInFilterScope } from 'src/dashboard/util/activeDashboardFilters';
-import { ChartConfiguration, Filters } from 'src/dashboard/reducers/types';
-import { DataMaskStateWithId, DataMaskType } from 'src/dataMask/types';
+import { ChartConfiguration } from 'src/dashboard/reducers/types';
 import { areObjectsEqual } from 'src/reduxUtils';
 import { Layout } from '../../types';
 import { getTreeCheckedItems } from '../nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils';
-import { NativeFilterType } from '../nativeFilters/types';
 
 export enum IndicatorStatus {
   Unset = 'UNSET',
diff --git a/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx
new file mode 100644
index 0000000..707597d
--- /dev/null
+++ b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx
@@ -0,0 +1,177 @@
+/**
+ * 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 React, { FC, Suspense } from 'react';
+import { DashboardComponentMetadata, JsonObject, t } from '@superset-ui/core';
+import backgroundStyleOptions from 'src/dashboard/util/backgroundStyleOptions';
+import cx from 'classnames';
+import { useSelector } from 'react-redux';
+import DragDroppable from '../dnd/DragDroppable';
+import { COLUMN_TYPE, ROW_TYPE } from '../../util/componentTypes';
+import WithPopoverMenu from '../menu/WithPopoverMenu';
+import ResizableContainer from '../resizable/ResizableContainer';
+import {
+  BACKGROUND_TRANSPARENT,
+  GRID_BASE_UNIT,
+  GRID_MIN_COLUMN_COUNT,
+} from '../../util/constants';
+import HoverMenu from '../menu/HoverMenu';
+import DeleteComponentButton from '../DeleteComponentButton';
+import BackgroundStyleDropdown from '../menu/BackgroundStyleDropdown';
+import dashboardComponents from '../../../visualizations/presets/dashboardComponents';
+import { RootState } from '../../types';
+
+type FilterSummaryType = {
+  component: JsonObject;
+  parentComponent: JsonObject;
+  index: number;
+  depth: number;
+  handleComponentDrop: (...args: any[]) => any;
+  editMode: boolean;
+  columnWidth: number;
+  availableColumnCount: number;
+  onResizeStart: Function;
+  onResizeStop: Function;
+  onResize: Function;
+  deleteComponent: Function;
+  updateComponents: Function;
+  parentId: number;
+  id: number;
+};
+
+const DynamicComponent: FC<FilterSummaryType> = ({
+  component,
+  parentComponent,
+  index,
+  depth,
+  handleComponentDrop,
+  editMode,
+  columnWidth,
+  availableColumnCount,
+  onResizeStart,
+  onResizeStop,
+  onResize,
+  deleteComponent,
+  parentId,
+  updateComponents,
+  id,
+}) => {
+  // inherit the size of parent columns
+  const widthMultiple =
+    parentComponent.type === COLUMN_TYPE
+      ? parentComponent.meta.width || GRID_MIN_COLUMN_COUNT
+      : component.meta.width || GRID_MIN_COLUMN_COUNT;
+
+  const handleDeleteComponent = () => {
+    deleteComponent(id, parentId);
+  };
+
+  const rowStyle = backgroundStyleOptions.find(
+    opt => opt.value === (component.meta.background || BACKGROUND_TRANSPARENT),
+  );
+
+  const updateMeta = (metaKey: string, nextValue: string | number) => {
+    updateComponents({
+      [component.id]: {
+        ...component,
+        meta: {
+          ...component.meta,
+          [metaKey]: nextValue,
+        },
+      },
+    });
+  };
+
+  const { Component } = dashboardComponents.get(component.meta.componentKey);
+  const dashboardData = useSelector<RootState, DashboardComponentMetadata>(
+    ({ nativeFilters, dataMask }) => ({
+      nativeFilters,
+      dataMask,
+    }),
+  );
+
+  return (
+    <DragDroppable
+      // @ts-ignore
+      component={component}
+      // @ts-ignore
+      parentComponent={parentComponent}
+      orientation={parentComponent.type === ROW_TYPE ? 'column' : 'row'}
+      index={index}
+      depth={depth}
+      onDrop={handleComponentDrop}
+      editMode={editMode}
+    >
+      {({ dropIndicatorProps, dragSourceRef }) => (
+        <WithPopoverMenu
+          menuItems={[
+            <BackgroundStyleDropdown
+              id={`${component.id}-background`}
+              value={component.meta.background}
+              onChange={value => updateMeta('background', value)}
+            />,
+          ]}
+          editMode={editMode}
+        >
+          <div
+            data-test={`dashboard-${component.componentKey}`}
+            className={cx(
+              'dashboard-component',
+              `dashboard-${component.componentKey}`,
+              rowStyle?.className,
+            )}
+            id={component.id}
+          >
+            <ResizableContainer
+              id={component.id}
+              adjustableWidth={parentComponent.type === ROW_TYPE}
+              widthStep={columnWidth}
+              widthMultiple={widthMultiple}
+              heightStep={GRID_BASE_UNIT}
+              adjustableHeight={false}
+              heightMultiple={component.meta.height}
+              minWidthMultiple={GRID_MIN_COLUMN_COUNT}
+              minHeightMultiple={GRID_MIN_COLUMN_COUNT}
+              maxWidthMultiple={availableColumnCount + widthMultiple}
+              onResizeStart={onResizeStart}
+              onResize={onResize}
+              onResizeStop={onResizeStop}
+            >
+              <div
+                ref={dragSourceRef}
+                className="dashboard-component"
+                data-test="dashboard-component-chart-holder"
+              >
+                {editMode && (
+                  <HoverMenu position="top">
+                    <DeleteComponentButton onDelete={handleDeleteComponent} />
+                  </HoverMenu>
+                )}
+                <Suspense fallback={<div>{t('Loading...')}</div>}>
+                  <Component dashboardData={dashboardData} />
+                </Suspense>
+              </div>
+            </ResizableContainer>
+          </div>
+          {dropIndicatorProps && <div {...dropIndicatorProps} />}
+        </WithPopoverMenu>
+      )}
+    </DragDroppable>
+  );
+};
+export default DynamicComponent;
diff --git a/superset-frontend/src/dashboard/components/gridComponents/index.js b/superset-frontend/src/dashboard/components/gridComponents/index.js
index ce014f8..95c524f 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/index.js
+++ b/superset-frontend/src/dashboard/components/gridComponents/index.js
@@ -25,6 +25,7 @@ import {
   ROW_TYPE,
   TAB_TYPE,
   TABS_TYPE,
+  DYNAMIC_TYPE,
 } from '../../util/componentTypes';
 
 import ChartHolder from './ChartHolder';
@@ -35,6 +36,7 @@ import Header from './Header';
 import Row from './Row';
 import Tab from './Tab';
 import TabsConnected from './Tabs';
+import DynamicComponent from './DynamicComponent';
 
 export { default as ChartHolder } from './ChartHolder';
 export { default as Markdown } from './Markdown';
@@ -44,6 +46,7 @@ export { default as Header } from './Header';
 export { default as Row } from './Row';
 export { default as Tab } from './Tab';
 export { default as Tabs } from './Tabs';
+export { default as DynamicComponent } from './DynamicComponent';
 
 export const componentLookup = {
   [CHART_TYPE]: ChartHolder,
@@ -54,4 +57,5 @@ export const componentLookup = {
   [ROW_TYPE]: Row,
   [TAB_TYPE]: Tab,
   [TABS_TYPE]: TabsConnected,
+  [DYNAMIC_TYPE]: DynamicComponent,
 };
diff --git a/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx b/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx
index bfb799f..f4f33c9 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx
@@ -37,10 +37,10 @@ const defaultProps = {
 
 export default class DraggableNewComponent extends React.PureComponent {
   render() {
-    const { label, id, type, className } = this.props;
+    const { label, id, type, className, meta } = this.props;
     return (
       <DragDroppable
-        component={{ type, id }}
+        component={{ type, id, meta }}
         parentComponent={{
           id: NEW_COMPONENTS_SOURCE_ID,
           type: NEW_COMPONENT_SOURCE_TYPE,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts b/superset-frontend/src/dashboard/components/gridComponents/new/NewDynamicComponent.tsx
similarity index 50%
copy from superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts
copy to superset-frontend/src/dashboard/components/gridComponents/new/NewDynamicComponent.tsx
index c5a9d13..4fae53a 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts
+++ b/superset-frontend/src/dashboard/components/gridComponents/new/NewDynamicComponent.tsx
@@ -16,10 +16,28 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import React, { FC } from 'react';
+import DraggableNewComponent from './DraggableNewComponent';
+import { DYNAMIC_TYPE } from '../../../util/componentTypes';
+import { NEW_DYNAMIC_COMPONENT } from '../../../util/constants';
+import { DashboardComponentsRegistryMetadata } from '../../../../visualizations/dashboardComponents/DashboardComponentsRegistry';
 
-import { DataMask } from '@superset-ui/core';
-import { Filter } from '../../types';
-
-export type CascadeFilter = Filter & { dataMask?: DataMask } & {
-  cascadeChildren: CascadeFilter[];
+type DraggableNewDynamicComponent = {
+  componentKey: string;
+  metadata: DashboardComponentsRegistryMetadata;
 };
+
+const DraggableNewDynamicComponent: FC<DraggableNewDynamicComponent> = ({
+  componentKey,
+  metadata,
+}) => (
+  <DraggableNewComponent
+    id={NEW_DYNAMIC_COMPONENT}
+    type={DYNAMIC_TYPE}
+    label={metadata.name}
+    meta={{ metadata, componentKey }}
+    className={`fa fa-${metadata.iconName}`}
+  />
+);
+
+export default DraggableNewDynamicComponent;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx
index 5b30856..f19b6b0 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx
@@ -17,11 +17,14 @@
  * under the License.
  */
 import React, { RefObject } from 'react';
-import { styled, DataMask } from '@superset-ui/core';
+import {
+  DataMaskStateWithId,
+  Filter,
+  styled,
+  DataMask,
+} from '@superset-ui/core';
 import FilterControl from 'src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl';
 import { CascadeFilter } from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types';
-import { Filter } from 'src/dashboard/components/nativeFilters/types';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 
 export interface CascadeFilterControlProps {
   dataMaskSelected?: DataMaskStateWithId;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx
index b164e5a..0bb177b 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx
@@ -23,15 +23,21 @@ import React, {
   useState,
   useRef,
 } from 'react';
-import { styled, t, DataMask, css, SupersetTheme } from '@superset-ui/core';
+import {
+  css,
+  DataMask,
+  DataMaskStateWithId,
+  Filter,
+  styled,
+  SupersetTheme,
+  t,
+} from '@superset-ui/core';
 import Popover from 'src/components/Popover';
 import Icons from 'src/components/Icons';
 import { Pill } from 'src/dashboard/components/FiltersBadge/Styles';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import FilterControl from 'src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl';
 import CascadeFilterControl from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl';
 import { CascadeFilter } from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types';
-import { Filter } from 'src/dashboard/components/nativeFilters/types';
 
 interface CascadePopoverProps {
   dataMaskSelected: DataMaskStateWithId;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts
index c5a9d13..6d319f6 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts
@@ -17,8 +17,7 @@
  * under the License.
  */
 
-import { DataMask } from '@superset-ui/core';
-import { Filter } from '../../types';
+import { DataMask, Filter } from '@superset-ui/core';
 
 export type CascadeFilter = Filter & { dataMask?: DataMask } & {
   cascadeChildren: CascadeFilter[];
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx
index 106388d..bb3c151 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx
@@ -20,8 +20,7 @@ import React, { useState } from 'react';
 import { useDispatch } from 'react-redux';
 import { setFilterConfiguration } from 'src/dashboard/actions/nativeFilters';
 import Button from 'src/components/Button';
-import { styled } from '@superset-ui/core';
-import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types';
+import { FilterConfiguration, styled } from '@superset-ui/core';
 import { FiltersConfigModal } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal';
 import { getFilterBarTestId } from '..';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
index f0c0a56..fb83fc9 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
@@ -18,22 +18,24 @@
  */
 import React, { FC, useCallback, useMemo, useState } from 'react';
 import { css } from '@emotion/react';
-import { DataMask, styled, t } from '@superset-ui/core';
+import {
+  DataMask,
+  DataMaskStateWithId,
+  Filter,
+  NativeFilterType,
+  styled,
+  t,
+} from '@superset-ui/core';
 import {
   createHtmlPortalNode,
   InPortal,
   OutPortal,
 } from 'react-reverse-portal';
 import { Collapse } from 'src/common/components';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import {
   useDashboardHasTabs,
   useSelectFiltersInScope,
 } from 'src/dashboard/components/nativeFilters/state';
-import {
-  Filter,
-  NativeFilterType,
-} from 'src/dashboard/components/nativeFilters/types';
 import CascadePopover from '../CascadeFilters/CascadePopover';
 import { useFilters } from '../state';
 import { buildCascadeFiltersTree } from './utils';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts
index 810ef5d..80ce41b 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts
@@ -18,9 +18,11 @@
  */
 import { useMemo } from 'react';
 import { useSelector } from 'react-redux';
-import { NativeFiltersState } from 'src/dashboard/reducers/types';
-import { DataMaskStateWithId } from 'src/dataMask/types';
-import { ExtraFormData } from '@superset-ui/core';
+import {
+  DataMaskStateWithId,
+  ExtraFormData,
+  NativeFiltersState,
+} from '@superset-ui/core';
 import { mergeExtraFormData } from '../../utils';
 
 // eslint-disable-next-line import/prefer-default-export
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
index 52550c5..60a7b2d 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
@@ -17,9 +17,7 @@
  * under the License.
  */
 import React, { RefObject } from 'react';
-import { DataMask } from '@superset-ui/core';
-import { DataMaskStateWithId } from 'src/dataMask/types';
-import { Filter } from '../../types';
+import { DataMask, DataMaskStateWithId, Filter } from '@superset-ui/core';
 
 export interface FilterProps {
   dataMaskSelected?: DataMaskStateWithId;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts
index 12ca897..87f11a7 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts
@@ -18,11 +18,11 @@
  */
 import { debounce } from 'lodash';
 import { Dispatch } from 'react';
+import { Filter, NativeFilterType, Divider } from '@superset-ui/core';
 import {
   setFocusedNativeFilter,
   unsetFocusedNativeFilter,
 } from 'src/dashboard/actions/nativeFilters';
-import { Filter, NativeFilterType, Divider } from '../../types';
 import { CascadeFilter } from '../CascadeFilters/types';
 import { mapParentFiltersToChildren } from '../utils';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
index 5e78091..8658bcd 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
@@ -17,12 +17,11 @@
  * under the License.
  */
 import React, { FC, useMemo, useState } from 'react';
-import { HandlerFunction, styled, t } from '@superset-ui/core';
+import { DataMaskState, HandlerFunction, styled, t } from '@superset-ui/core';
 import { Typography, Tooltip } from 'src/common/components';
 import { useDispatch } from 'react-redux';
 import Button from 'src/components/Button';
 import { updateFilterSet } from 'src/dashboard/actions/nativeFilters';
-import { DataMaskState } from 'src/dataMask/types';
 import { WarningOutlined } from '@ant-design/icons';
 import { ActionButtons } from './Footer';
 import { useNativeFiltersDataMask, useFilters, useFilterSets } from '../state';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
index e667b27..00b3c9a 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
@@ -18,10 +18,15 @@
  */
 import { Typography, Dropdown, Menu } from 'src/common/components';
 import React, { FC } from 'react';
-import { FilterSet } from 'src/dashboard/reducers/types';
-import { DataMaskState } from 'src/dataMask/types';
+import {
+  DataMaskState,
+  FilterSet,
+  HandlerFunction,
+  styled,
+  supersetTheme,
+  t,
+} from '@superset-ui/core';
 import { CheckOutlined, EllipsisOutlined } from '@ant-design/icons';
-import { HandlerFunction, styled, supersetTheme, t } from '@superset-ui/core';
 import Button from 'src/components/Button';
 import { Tooltip } from 'src/components/Tooltip';
 import FiltersHeader from './FiltersHeader';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
index c263da6..8f5f4a1 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
@@ -17,16 +17,20 @@
  * under the License.
  */
 import React, { FC } from 'react';
-import { styled, t, useTheme } from '@superset-ui/core';
+import {
+  DataMaskState,
+  FilterSet,
+  NativeFilterType,
+  styled,
+  t,
+  useTheme,
+} from '@superset-ui/core';
 import { Collapse, Typography, Tooltip } from 'src/common/components';
-import { DataMaskState } from 'src/dataMask/types';
 import Icons from 'src/components/Icons';
 import { areObjectsEqual } from 'src/reduxUtils';
-import { FilterSet } from 'src/dashboard/reducers/types';
 import { getFilterValueForDisplay } from './utils';
 import { useFilters } from '../state';
 import { getFilterBarTestId } from '../index';
-import { NativeFilterType } from '../../types';
 
 const FilterHeader = styled.div`
   display: flex;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx
index 09a6304..18f5a56 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx
@@ -18,18 +18,25 @@
  */
 
 import React, { useEffect, useState } from 'react';
-import { DataMask, HandlerFunction, styled, t } from '@superset-ui/core';
+import {
+  DataMask,
+  DataMaskState,
+  DataMaskWithId,
+  Filter,
+  Filters,
+  FilterSet,
+  HandlerFunction,
+  styled,
+  t,
+} from '@superset-ui/core';
 import { useDispatch } from 'react-redux';
-import { DataMaskState, DataMaskWithId } from 'src/dataMask/types';
 import {
   createFilterSet,
   deleteFilterSet,
   updateFilterSet,
 } from 'src/dashboard/actions/nativeFilters';
-import { Filters, FilterSet } from 'src/dashboard/reducers/types';
 import { areObjectsEqual } from 'src/reduxUtils';
 import { findExistingFilterSet } from './utils';
-import { Filter } from '../../types';
 import { useFilters, useNativeFiltersDataMask, useFilterSets } from '../state';
 import Footer from './Footer';
 import FilterSetUnit from './FilterSetUnit';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts
index 4c17ac8..06821ff 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { FilterSet } from 'src/dashboard/reducers/types';
+import { FilterSet } from '@superset-ui/core';
 import { findExistingFilterSet } from '.';
 
 const createDataMaskSelected = () => ({
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts
index 368fbbb..187739f 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts
@@ -18,10 +18,8 @@
  */
 
 import shortid from 'shortid';
-import { t } from '@superset-ui/core';
+import { DataMaskState, FilterSet, t } from '@superset-ui/core';
 import { areObjectsEqual } from 'src/reduxUtils';
-import { DataMaskState } from 'src/dataMask/types';
-import { FilterSet } from 'src/dashboard/reducers/types';
 
 export const generateFiltersSetId = () => `FILTERS_SET-${shortid.generate()}`;
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx
index 9b35b18..2aac16e 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx
@@ -17,15 +17,20 @@
  * under the License.
  */
 /* eslint-disable no-param-reassign */
-import { styled, t, useTheme } from '@superset-ui/core';
+import {
+  DataMaskState,
+  DataMaskStateWithId,
+  Filter,
+  styled,
+  t,
+  useTheme,
+} from '@superset-ui/core';
 import React, { FC } from 'react';
 import Icons from 'src/components/Icons';
 import Button from 'src/components/Button';
 import { useSelector } from 'react-redux';
-import { DataMaskState, DataMaskStateWithId } from 'src/dataMask/types';
 import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink';
 import { useFilters } from 'src/dashboard/components/nativeFilters/FilterBar/state';
-import { Filter } from 'src/dashboard/components/nativeFilters/types';
 import { getFilterBarTestId } from '..';
 import { RootState } from '../../../../types';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
index 02156b2..6b07c2c 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
@@ -18,7 +18,16 @@
  */
 
 /* eslint-disable no-param-reassign */
-import { DataMask, HandlerFunction, styled, t } from '@superset-ui/core';
+import {
+  DataMaskStateWithId,
+  DataMaskWithId,
+  Filter,
+  NativeFilterType,
+  DataMask,
+  HandlerFunction,
+  styled,
+  t,
+} from '@superset-ui/core';
 import React, { useEffect, useState, useCallback, useMemo } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import cx from 'classnames';
@@ -28,14 +37,9 @@ import { useHistory } from 'react-router-dom';
 import { usePrevious } from 'src/hooks/usePrevious';
 import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
 import { updateDataMask, clearDataMask } from 'src/dataMask/actions';
-import { DataMaskStateWithId, DataMaskWithId } from 'src/dataMask/types';
 import { useImmer } from 'use-immer';
 import { isEmpty, isEqual } from 'lodash';
 import { testWithId } from 'src/utils/testUtils';
-import {
-  Filter,
-  NativeFilterType,
-} from 'src/dashboard/components/nativeFilters/types';
 import Loading from 'src/components/Loading';
 import { getInitialDataMask } from 'src/dataMask/reducer';
 import { URL_PARAMS } from 'src/constants';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts
index 8e7022f..054f440 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts
@@ -20,19 +20,17 @@
 import { useSelector } from 'react-redux';
 import { filter, keyBy } from 'lodash';
 import {
-  Filters,
-  FilterSets as FilterSetsType,
-} from 'src/dashboard/reducers/types';
-import {
   DataMaskState,
   DataMaskStateWithId,
   DataMaskWithId,
-} from 'src/dataMask/types';
+  Filter,
+  Filters,
+  FilterSets as FilterSetsType,
+} from '@superset-ui/core';
 import { useContext, useEffect, useMemo, useState } from 'react';
 import { ChartsState, RootState } from 'src/dashboard/types';
 import { MigrationContext } from 'src/dashboard/containers/DashboardPage';
 import { FILTER_BOX_MIGRATION_STATES } from 'src/explore/constants';
-import { Filter } from 'src/dashboard/components/nativeFilters/types';
 import { NATIVE_FILTER_PREFIX } from '../FiltersConfigModal/utils';
 
 export const useFilterSets = () =>
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts
index a2bc7ca..926abbf 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts
@@ -17,10 +17,13 @@
  * under the License.
  */
 
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import { areObjectsEqual } from 'src/reduxUtils';
-import { FilterState } from '@superset-ui/core';
-import { Filter, Divider } from '../types';
+import {
+  DataMaskStateWithId,
+  Filter,
+  FilterState,
+  Divider,
+} from '@superset-ui/core';
 
 export enum TabIds {
   AllFilters = 'allFilters',
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx
index 7ab2b10..afef496 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx
@@ -19,8 +19,7 @@
 import React from 'react';
 import { FormItem } from 'src/components/Form';
 import { Input, TextArea } from 'src/common/components';
-import { styled, t } from '@superset-ui/core';
-import { NativeFilterType } from '../types';
+import { NativeFilterType, styled, t } from '@superset-ui/core';
 
 interface Props {
   componentId: string;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx
index e77a29b..744bcf8 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx
@@ -16,9 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { styled } from '@superset-ui/core';
+import { NativeFilterType, styled } from '@superset-ui/core';
 import React from 'react';
-import { NativeFilterType } from '../types';
 import FilterTitlePane from './FilterTitlePane';
 import { FilterRemoval } from './types';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx
index 1a1f4cd..756a3e0 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx
@@ -16,10 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { styled, t, useTheme } from '@superset-ui/core';
+import { NativeFilterType, styled, t, useTheme } from '@superset-ui/core';
 import React from 'react';
 import { Dropdown, MainNav as Menu } from 'src/common/components';
-import { NativeFilterType } from '../types';
 import FilterTitleContainer from './FilterTitleContainer';
 import { FilterRemoval } from './types';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx
index 65ee3f0..877e43f 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx
@@ -18,11 +18,10 @@
  */
 
 import React, { FC, useCallback, useState } from 'react';
-import { t, styled } from '@superset-ui/core';
+import { NativeFilterScope, styled, t } from '@superset-ui/core';
 import { Radio } from 'src/components/Radio';
 import { Form, Typography } from 'src/common/components';
 import { useComponentDidUpdate } from 'src/hooks/useComponentDidUpdate/useComponentDidUpdate';
-import { Scope } from '../../../types';
 import { ScopingType } from './types';
 import ScopingTree from './ScopingTree';
 import { getDefaultScopeValue, isScopingAll } from './utils';
@@ -30,9 +29,9 @@ import { getDefaultScopeValue, isScopingAll } from './utils';
 type FilterScopeProps = {
   pathToFormValue?: string[];
   updateFormValues: (values: any) => void;
-  formFilterScope?: Scope;
+  formFilterScope?: NativeFilterScope;
   forceUpdate: Function;
-  filterScope?: Scope;
+  filterScope?: NativeFilterScope;
   formScopingType?: ScopingType;
   chartId?: number;
   initiallyExcludedCharts?: number[];
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx
index af140f8..713eb95 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx
@@ -18,19 +18,19 @@
  */
 
 import React, { FC, useMemo, useState } from 'react';
+import { NativeFilterScope } from '@superset-ui/core';
 import { Tree } from 'src/common/components';
 import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
 import { Tooltip } from 'src/components/Tooltip';
 import Icons from 'src/components/Icons';
 import { useFilterScopeTree } from './state';
 import { findFilterScope, getTreeCheckedItems } from './utils';
-import { Scope } from '../../../types';
 
 type ScopingTreeProps = {
   forceUpdate: Function;
   updateFormValues: (values: any) => void;
-  formScope?: Scope;
-  initialScope: Scope;
+  formScope?: NativeFilterScope;
+  initialScope: NativeFilterScope;
   chartId?: number;
   initiallyExcludedCharts?: number[];
 };
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts
index 555b87f..4bf04c7 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts
@@ -23,9 +23,8 @@ import {
   TAB_TYPE,
 } from 'src/dashboard/util/componentTypes';
 import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
-import { t } from '@superset-ui/core';
+import { NativeFilterScope, t } from '@superset-ui/core';
 import { BuildTreeLeafTitle, TreeItem } from './types';
-import { Scope } from '../../../types';
 
 export const isShowTypeInTree = ({ type, meta }: LayoutItem, charts?: Charts) =>
   (type === TAB_TYPE || type === CHART_TYPE || type === DASHBOARD_ROOT_TYPE) &&
@@ -114,7 +113,10 @@ const checkTreeItem = (
   });
 };
 
-export const getTreeCheckedItems = (scope: Scope, layout: Layout) => {
+export const getTreeCheckedItems = (
+  scope: NativeFilterScope,
+  layout: Layout,
+) => {
   const checkedItems: string[] = [];
   checkTreeItem(checkedItems, layout, [...scope.rootPath], [...scope.excluded]);
   return [...new Set(checkedItems)];
@@ -124,7 +126,7 @@ export const getTreeCheckedItems = (scope: Scope, layout: Layout) => {
 export const findFilterScope = (
   checkedKeys: string[],
   layout: Layout,
-): Scope => {
+): NativeFilterScope => {
   if (!checkedKeys.length) {
     return {
       rootPath: [],
@@ -170,14 +172,14 @@ export const findFilterScope = (
 export const getDefaultScopeValue = (
   chartId?: number,
   initiallyExcludedCharts: number[] = [],
-): Scope => ({
+): NativeFilterScope => ({
   rootPath: [DASHBOARD_ROOT_ID],
   excluded: chartId
     ? [chartId, ...initiallyExcludedCharts]
     : initiallyExcludedCharts,
 });
 
-export const isScopingAll = (scope: Scope, chartId?: number) =>
+export const isScopingAll = (scope: NativeFilterScope, chartId?: number) =>
   !scope ||
   (scope.rootPath[0] === DASHBOARD_ROOT_ID &&
     !scope.excluded.filter(item => item !== chartId).length);
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 387c18e..97e1d68 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -27,9 +27,11 @@ import {
   Behavior,
   ChartDataResponseResult,
   Column,
+  Filter,
   GenericDataType,
   getChartMetadataRegistry,
   JsonResponse,
+  NativeFilterType,
   styled,
   SupersetApiError,
   SupersetClient,
@@ -71,10 +73,6 @@ import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
 import { waitForAsyncData } from 'src/middleware/asyncEvent';
 import { cacheWrapper } from 'src/utils/cacheWrapper';
 import { ClientErrorObject } from 'src/utils/getClientErrorObject';
-import {
-  Filter,
-  NativeFilterType,
-} from 'src/dashboard/components/nativeFilters/types';
 import { SingleValueType } from 'src/filters/components/Range/SingleValueType';
 import { getFormData } from 'src/dashboard/components/nativeFilters/utils';
 import {
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx
index 25ed9ea..87cf536 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx
@@ -18,12 +18,9 @@
  */
 import userEvent from '@testing-library/user-event';
 import React from 'react';
+import { Filter, NativeFilterType } from '@superset-ui/core';
 import { render, screen } from 'spec/helpers/testing-library';
 import { FormInstance } from 'src/common/components';
-import {
-  Filter,
-  NativeFilterType,
-} from 'src/dashboard/components/nativeFilters/types';
 import getControlItemsMap, { ControlItemsProps } from './getControlItemsMap';
 import { getControlItems, setNativeFilterFieldValues } from './utils';
 
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx
index d202552..3fcf9f2 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx
@@ -23,7 +23,12 @@ import {
 import React from 'react';
 import { Checkbox } from 'src/common/components';
 import { FormInstance } from 'antd/lib/form';
-import { getChartControlPanelRegistry, styled, t } from '@superset-ui/core';
+import {
+  Filter,
+  getChartControlPanelRegistry,
+  styled,
+  t,
+} from '@superset-ui/core';
 import { Tooltip } from 'src/components/Tooltip';
 import { FormItem } from 'src/components/Form';
 import {
@@ -37,7 +42,6 @@ import {
   StyledLabel,
   StyledRowFormItem,
 } from './FiltersConfigForm';
-import { Filter } from '../../types';
 import { ColumnSelect } from './ColumnSelect';
 
 export interface ControlItemsProps {
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
index 0fa8c77..0b707d8 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
@@ -18,10 +18,9 @@
  */
 import { useEffect, useState } from 'react';
 import { FormInstance } from 'antd/lib/form';
-import { t } from '@superset-ui/core';
+import { Filter, t } from '@superset-ui/core';
 import { NativeFiltersForm, NativeFiltersFormItem } from '../types';
 import { setNativeFilterFieldValues, useForceUpdate } from './utils';
-import { Filter } from '../../types';
 
 // When some fields in form changed we need re-fetch data for Filter defaultValue
 // eslint-disable-next-line import/prefer-default-export
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
index e3fcfcf..d288bba 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx
@@ -24,18 +24,20 @@ import React, {
   useRef,
 } from 'react';
 import { uniq, isEqual, sortBy, debounce } from 'lodash';
-import { t, styled, SLOW_DEBOUNCE } from '@superset-ui/core';
-import { Form } from 'src/common/components';
-import ErrorBoundary from 'src/components/ErrorBoundary';
-import { StyledModal } from 'src/components/Modal';
-import { testWithId } from 'src/utils/testUtils';
-import { useFilterConfigMap, useFilterConfiguration } from '../state';
 import {
   Filter,
   FilterConfiguration,
   NativeFilterType,
   Divider,
-} from '../types';
+  styled,
+  SLOW_DEBOUNCE,
+  t,
+} from '@superset-ui/core';
+import { Form } from 'src/common/components';
+import ErrorBoundary from 'src/components/ErrorBoundary';
+import { StyledModal } from 'src/components/Modal';
+import { testWithId } from 'src/utils/testUtils';
+import { useFilterConfigMap, useFilterConfiguration } from '../state';
 import FiltureConfigurePane from './FilterConfigurePane';
 import FiltersConfigForm, {
   FilterPanels,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts
index 2ab54d9..285c30e 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts
@@ -1,7 +1,7 @@
 import { useEffect } from 'react';
 import { usePrevious } from 'src/hooks/usePrevious';
+import { NativeFilterType } from '@superset-ui/core';
 import { FilterRemoval } from './types';
-import { NativeFilterType } from '../types';
 
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts
index c5165fc..42daba8 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts
@@ -16,11 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { AdhocFilter, DataMask } from '@superset-ui/core';
-import { NativeFilterType, Scope } from '../types';
+import {
+  AdhocFilter,
+  DataMask,
+  NativeFilterType,
+  NativeFilterScope,
+} from '@superset-ui/core';
 
 export interface NativeFiltersFormItem {
-  scope: Scope;
+  scope: NativeFilterScope;
   name: string;
   filterType: string;
   dataset: {
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts
index 539a882..b6edd9f 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts
@@ -20,7 +20,14 @@ import { FormInstance } from 'antd/lib/form';
 import shortid from 'shortid';
 import { getInitialDataMask } from 'src/dataMask/reducer';
 
-import { t } from '@superset-ui/core';
+import {
+  Filter,
+  FilterConfiguration,
+  NativeFilterType,
+  Divider,
+  t,
+  NativeFilterTarget,
+} from '@superset-ui/core';
 import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
 import {
   FilterRemoval,
@@ -28,13 +35,6 @@ import {
   FilterHierarchy,
   FilterHierarchyNode,
 } from './types';
-import {
-  Filter,
-  FilterConfiguration,
-  NativeFilterType,
-  Divider,
-  Target,
-} from '../types';
 
 export const REMOVAL_DELAY_SECS = 5;
 
@@ -156,7 +156,7 @@ export const createHandleSave =
             description: formInputs.description,
           };
         }
-        const target: Partial<Target> = {};
+        const target: Partial<NativeFilterTarget> = {};
         if (formInputs.dataset) {
           target.datasetId = formInputs.dataset.value;
         }
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/state.ts
index da295a1..be2089c 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/state.ts
@@ -23,7 +23,7 @@ import {
   FilterConfiguration,
   NativeFilterType,
   Divider,
-} from './types';
+} from '@superset-ui/core';
 import { ActiveTabs, DashboardLayout, RootState } from '../../types';
 import { TAB_TYPE } from '../../util/componentTypes';
 import { CascadeFilter } from './FilterBar/CascadeFilters/types';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts
index 60925c7..1ebba46 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts
@@ -17,21 +17,21 @@
  * under the License.
  */
 import {
-  ExtraFormData,
-  QueryFormData,
-  getChartMetadataRegistry,
+  AdhocFilter,
   Behavior,
+  DataMaskStateWithId,
   EXTRA_FORM_DATA_APPEND_KEYS,
   EXTRA_FORM_DATA_OVERRIDE_KEYS,
-  AdhocFilter,
+  ExtraFormData,
   FeatureFlag,
+  Filter,
+  getChartMetadataRegistry,
+  QueryFormData,
 } from '@superset-ui/core';
 import { Charts, DashboardLayout } from 'src/dashboard/types';
 import { RefObject } from 'react';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import extractUrlParams from 'src/dashboard/util/extractUrlParams';
 import { isFeatureEnabled } from 'src/featureFlags';
-import { Filter } from './types';
 import { CHART_TYPE, TAB_TYPE } from '../../util/componentTypes';
 import { DASHBOARD_GRID_ID, DASHBOARD_ROOT_ID } from '../../util/constants';
 
diff --git a/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts b/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts
index f6766cf..9ace211 100644
--- a/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts
+++ b/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types';
-import { NativeFiltersState } from 'src/dashboard/reducers/types';
-import { DataMaskStateWithId } from 'src/dataMask/types';
+import {
+  DataMaskStateWithId,
+  NativeFiltersState,
+  NativeFilterType,
+} from '@superset-ui/core';
 
 export const mockDataMaskInfo: DataMaskStateWithId = {
   DefaultsID: {
diff --git a/superset-frontend/src/dashboard/reducers/nativeFilters.ts b/superset-frontend/src/dashboard/reducers/nativeFilters.ts
index 1521ec1..b3900af 100644
--- a/superset-frontend/src/dashboard/reducers/nativeFilters.ts
+++ b/superset-frontend/src/dashboard/reducers/nativeFilters.ts
@@ -24,8 +24,11 @@ import {
   SET_FOCUSED_NATIVE_FILTER,
   UNSET_FOCUSED_NATIVE_FILTER,
 } from 'src/dashboard/actions/nativeFilters';
-import { FilterSet, NativeFiltersState } from './types';
-import { FilterConfiguration } from '../components/nativeFilters/types';
+import {
+  FilterSet,
+  FilterConfiguration,
+  NativeFiltersState,
+} from '@superset-ui/core';
 import { HYDRATE_DASHBOARD } from '../actions/hydrate';
 
 export function getInitialState({
diff --git a/superset-frontend/src/dashboard/reducers/types.ts b/superset-frontend/src/dashboard/reducers/types.ts
index 5cef1a1..c1c723c 100644
--- a/superset-frontend/src/dashboard/reducers/types.ts
+++ b/superset-frontend/src/dashboard/reducers/types.ts
@@ -18,9 +18,7 @@
  */
 
 import componentTypes from 'src/dashboard/util/componentTypes';
-import { DataMaskStateWithId } from 'src/dataMask/types';
-import { JsonObject } from '@superset-ui/core';
-import { Filter, Scope } from '../components/nativeFilters/types';
+import { NativeFilterScope, JsonObject } from '@superset-ui/core';
 
 export enum Scoping {
   All = 'All',
@@ -31,7 +29,7 @@ export type ChartConfiguration = {
   [chartId: number]: {
     id: number;
     crossFilters: {
-      scope: Scope;
+      scope: NativeFilterScope;
     };
   };
 };
@@ -82,13 +80,6 @@ export type LayoutItem = {
   };
 };
 
-export type FilterSet = {
-  id: number;
-  name: string;
-  nativeFilters: Filters;
-  dataMask: DataMaskStateWithId;
-};
-
 export type FilterSetFullData = {
   changed_by_fk: string | null;
   changed_on: string | null;
@@ -101,17 +92,3 @@ export type FilterSetFullData = {
   owner_type: string;
   params: JsonObject;
 };
-
-export type FilterSets = {
-  [filtersSetId: string]: FilterSet;
-};
-
-export type Filters = {
-  [filterId: string]: Filter;
-};
-
-export type NativeFiltersState = {
-  filters: Filters;
-  filterSets: FilterSets;
-  focusedFilterId?: string;
-};
diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts
index 1496b98..24b7a5b 100644
--- a/superset-frontend/src/dashboard/types.ts
+++ b/superset-frontend/src/dashboard/types.ts
@@ -18,17 +18,17 @@
  */
 import {
   ChartProps,
+  DataMaskStateWithId,
   ExtraFormData,
   GenericDataType,
   JsonObject,
+  NativeFiltersState,
 } from '@superset-ui/core';
 import { DatasourceMeta } from '@superset-ui/chart-controls';
 import { chart } from 'src/chart/chartReducer';
 import componentTypes from 'src/dashboard/util/componentTypes';
 
 import { User } from 'src/types/bootstrapTypes';
-import { DataMaskStateWithId } from '../dataMask/types';
-import { NativeFiltersState } from './reducers/types';
 import { ChartState } from '../explore/types';
 
 export { Dashboard } from 'src/types/Dashboard';
diff --git a/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts b/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts
index 7b9dc10..f0a9b70 100644
--- a/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts
+++ b/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts
@@ -16,12 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMaskStateWithId } from 'src/dataMask/types';
-import { JsonObject } from '@superset-ui/core';
+import {
+  DataMaskStateWithId,
+  Filters,
+  JsonObject,
+  NativeFilterScope,
+} from '@superset-ui/core';
 import { CHART_TYPE } from './componentTypes';
-import { Scope } from '../components/nativeFilters/types';
 import { ActiveFilters, Layout, LayoutItem } from '../types';
-import { ChartConfiguration, Filters } from '../reducers/types';
+import { ChartConfiguration } from '../reducers/types';
 import { DASHBOARD_ROOT_ID } from './constants';
 
 // Looking for affected chart scopes and values
@@ -35,7 +38,7 @@ export const findAffectedCharts = ({
 }: {
   child: string;
   layout: { [key: string]: LayoutItem };
-  scope: Scope;
+  scope: NativeFilterScope;
   activeFilters: ActiveFilters;
   filterId: string;
   extraFormData: any;
diff --git a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
index 24aa2e8..90022a9 100644
--- a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
+++ b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
@@ -16,13 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataRecordFilters, JsonObject } from '@superset-ui/core';
+import {
+  DataMaskStateWithId,
+  DataRecordFilters,
+  JsonObject,
+  NativeFiltersState,
+} from '@superset-ui/core';
 import { ChartQueryPayload, Charts, LayoutItem } from 'src/dashboard/types';
 import { getExtraFormData } from 'src/dashboard/components/nativeFilters/utils';
-import { DataMaskStateWithId } from 'src/dataMask/types';
 import { areObjectsEqual } from 'src/reduxUtils';
 import getEffectiveExtraFilters from './getEffectiveExtraFilters';
-import { ChartConfiguration, NativeFiltersState } from '../../reducers/types';
+import { ChartConfiguration } from '../../reducers/types';
 import { getAllActiveFilters } from '../activeAllDashboardFilters';
 
 // We cache formData objects so that our connected container components don't always trigger
diff --git a/superset-frontend/src/dashboard/util/componentIsResizable.ts b/superset-frontend/src/dashboard/util/componentIsResizable.ts
index 21d0ef1..fd1d9d1 100644
--- a/superset-frontend/src/dashboard/util/componentIsResizable.ts
+++ b/superset-frontend/src/dashboard/util/componentIsResizable.ts
@@ -16,8 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE } from './componentTypes';
+import {
+  COLUMN_TYPE,
+  CHART_TYPE,
+  MARKDOWN_TYPE,
+  DYNAMIC_TYPE,
+} from './componentTypes';
 
 export default function componentIsResizable(entity: { type: string }) {
-  return [COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE].indexOf(entity.type) > -1;
+  return (
+    [COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE, DYNAMIC_TYPE].indexOf(
+      entity.type,
+    ) > -1
+  );
 }
diff --git a/superset-frontend/src/dashboard/util/componentTypes.ts b/superset-frontend/src/dashboard/util/componentTypes.ts
index 177aad0..0630d44 100644
--- a/superset-frontend/src/dashboard/util/componentTypes.ts
+++ b/superset-frontend/src/dashboard/util/componentTypes.ts
@@ -28,6 +28,8 @@ export const NEW_COMPONENT_SOURCE_TYPE = 'NEW_COMPONENT_SOURCE';
 export const ROW_TYPE = 'ROW';
 export const TABS_TYPE = 'TABS';
 export const TAB_TYPE = 'TAB';
+// Dynamic type proposes lazy loading of custom dashboard components that can be added in separate repository
+export const DYNAMIC_TYPE = 'DYNAMIC';
 
 export default {
   CHART_TYPE,
@@ -42,4 +44,5 @@ export default {
   ROW_TYPE,
   TABS_TYPE,
   TAB_TYPE,
+  DYNAMIC_TYPE,
 };
diff --git a/superset-frontend/src/dashboard/util/constants.ts b/superset-frontend/src/dashboard/util/constants.ts
index 9434a5a..640028e 100644
--- a/superset-frontend/src/dashboard/util/constants.ts
+++ b/superset-frontend/src/dashboard/util/constants.ts
@@ -31,6 +31,7 @@ export const NEW_MARKDOWN_ID = 'NEW_MARKDOWN_ID';
 export const NEW_ROW_ID = 'NEW_ROW_ID';
 export const NEW_TAB_ID = 'NEW_TAB_ID';
 export const NEW_TABS_ID = 'NEW_TABS_ID';
+export const NEW_DYNAMIC_COMPONENT = 'NEW_DYNAMIC_COMPONENT';
 
 // grid constants
 export const DASHBOARD_ROOT_DEPTH = 0;
diff --git a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts
index 87b3ab5..5235775 100644
--- a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts
+++ b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts
@@ -20,16 +20,12 @@ import shortid from 'shortid';
 import { find, isEmpty } from 'lodash';
 
 import {
-  Filter,
-  NativeFilterType,
-} from 'src/dashboard/components/nativeFilters/types';
-import {
   FILTER_CONFIG_ATTRIBUTES,
   TIME_FILTER_LABELS,
   TIME_FILTER_MAP,
 } from 'src/explore/constants';
 import { DASHBOARD_FILTER_SCOPE_GLOBAL } from 'src/dashboard/reducers/dashboardFilters';
-import { TimeGranularity } from '@superset-ui/core';
+import { Filter, NativeFilterType, TimeGranularity } from '@superset-ui/core';
 import { getChartIdsInFilterScope } from './activeDashboardFilters';
 import getFilterConfigsFromFormdata from './getFilterConfigsFromFormdata';
 
diff --git a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js
index efad55f..66a2dc5 100644
--- a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js
+++ b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js
@@ -23,6 +23,7 @@ import {
   COLUMN_TYPE,
   MARKDOWN_TYPE,
   CHART_TYPE,
+  DYNAMIC_TYPE,
 } from './componentTypes';
 
 function getTotalChildWidth({ id, components }) {
@@ -84,6 +85,7 @@ export default function getDetailedComponentWidth({
       }
     });
   } else if (
+    component.type === DYNAMIC_TYPE ||
     component.type === MARKDOWN_TYPE ||
     component.type === CHART_TYPE
   ) {
diff --git a/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts b/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts
index d60efaa..0756ef0 100644
--- a/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts
+++ b/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { Filter } from '@superset-ui/core';
 import getFormDataWithExtraFilters, {
   GetFormDataWithExtraFiltersArguments,
 } from 'src/dashboard/util/charts/getFormDataWithExtraFilters';
 import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
-import { Filter } from 'src/dashboard/components/nativeFilters/types';
 import { LayoutItem } from 'src/dashboard/types';
 import { dashboardLayout } from 'spec/fixtures/mockDashboardLayout';
 import { sliceId as chartId } from 'spec/fixtures/mockChartQueries';
diff --git a/superset-frontend/src/dashboard/util/isDashboardEmpty.ts b/superset-frontend/src/dashboard/util/isDashboardEmpty.ts
index 78481c5..7f3cc62 100644
--- a/superset-frontend/src/dashboard/util/isDashboardEmpty.ts
+++ b/superset-frontend/src/dashboard/util/isDashboardEmpty.ts
@@ -16,9 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { CHART_TYPE, MARKDOWN_TYPE } from './componentTypes';
+import { CHART_TYPE, MARKDOWN_TYPE, DYNAMIC_TYPE } from './componentTypes';
 
-const USER_CONTENT_COMPONENT_TYPE: string[] = [CHART_TYPE, MARKDOWN_TYPE];
+const USER_CONTENT_COMPONENT_TYPE: string[] = [
+  CHART_TYPE,
+  MARKDOWN_TYPE,
+  DYNAMIC_TYPE,
+];
 export default function isDashboardEmpty(layout: any): boolean {
   // has at least one chart or markdown component
   return !Object.values(layout).some(
diff --git a/superset-frontend/src/dashboard/util/isValidChild.ts b/superset-frontend/src/dashboard/util/isValidChild.ts
index 78d8984..6b2465e 100644
--- a/superset-frontend/src/dashboard/util/isValidChild.ts
+++ b/superset-frontend/src/dashboard/util/isValidChild.ts
@@ -43,6 +43,7 @@ import {
   ROW_TYPE,
   TABS_TYPE,
   TAB_TYPE,
+  DYNAMIC_TYPE,
 } from './componentTypes';
 
 import { DASHBOARD_ROOT_DEPTH as rootDepth } from './constants';
@@ -62,6 +63,7 @@ const parentMaxDepthLookup = {
 
   [DASHBOARD_GRID_TYPE]: {
     [CHART_TYPE]: depthOne,
+    [DYNAMIC_TYPE]: depthOne,
     [MARKDOWN_TYPE]: depthOne,
     [COLUMN_TYPE]: depthOne,
     [DIVIDER_TYPE]: depthOne,
@@ -72,6 +74,7 @@ const parentMaxDepthLookup = {
 
   [ROW_TYPE]: {
     [CHART_TYPE]: depthFour,
+    [DYNAMIC_TYPE]: depthFour,
     [MARKDOWN_TYPE]: depthFour,
     [COLUMN_TYPE]: depthFour,
   },
@@ -82,6 +85,7 @@ const parentMaxDepthLookup = {
 
   [TAB_TYPE]: {
     [CHART_TYPE]: depthFive,
+    [DYNAMIC_TYPE]: depthFive,
     [MARKDOWN_TYPE]: depthFive,
     [COLUMN_TYPE]: depthThree,
     [DIVIDER_TYPE]: depthFive,
@@ -101,6 +105,7 @@ const parentMaxDepthLookup = {
 
   // these have no valid children
   [CHART_TYPE]: {},
+  [DYNAMIC_TYPE]: {},
   [DIVIDER_TYPE]: {},
   [HEADER_TYPE]: {},
   [MARKDOWN_TYPE]: {},
diff --git a/superset-frontend/src/dashboard/util/newComponentFactory.js b/superset-frontend/src/dashboard/util/newComponentFactory.js
index 04dc71c..8fddfda 100644
--- a/superset-frontend/src/dashboard/util/newComponentFactory.js
+++ b/superset-frontend/src/dashboard/util/newComponentFactory.js
@@ -28,12 +28,14 @@ import {
   ROW_TYPE,
   TABS_TYPE,
   TAB_TYPE,
+  DYNAMIC_TYPE,
 } from './componentTypes';
 
 import {
   MEDIUM_HEADER,
   BACKGROUND_TRANSPARENT,
   GRID_DEFAULT_CHART_WIDTH,
+  GRID_COLUMN_COUNT,
 } from './constants';
 
 const typeToDefaultMetaData = {
@@ -56,6 +58,10 @@ const typeToDefaultMetaData = {
     defaultText: t('Tab title'),
     placeholder: t('Tab title'),
   },
+  [DYNAMIC_TYPE]: {
+    width: GRID_COLUMN_COUNT,
+    background: BACKGROUND_TRANSPARENT,
+  },
 };
 
 function uuid(type) {
diff --git a/superset-frontend/src/dataMask/actions.ts b/superset-frontend/src/dataMask/actions.ts
index b98f36e..a26b49f 100644
--- a/superset-frontend/src/dataMask/actions.ts
+++ b/superset-frontend/src/dataMask/actions.ts
@@ -16,10 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMask } from '@superset-ui/core';
-import { FilterConfiguration } from '../dashboard/components/nativeFilters/types';
+import { DataMask, FilterConfiguration, Filters } from '@superset-ui/core';
 import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
-import { Filters } from '../dashboard/reducers/types';
 import { getInitialDataMask } from './reducer';
 
 export const CLEAR_DATA_MASK_STATE = 'CLEAR_DATA_MASK_STATE';
diff --git a/superset-frontend/src/dataMask/reducer.ts b/superset-frontend/src/dataMask/reducer.ts
index 60d09f0..ae30d1b 100644
--- a/superset-frontend/src/dataMask/reducer.ts
+++ b/superset-frontend/src/dataMask/reducer.ts
@@ -20,23 +20,25 @@
 /* eslint-disable no-param-reassign */
 // <- When we work with Immer, we need reassign, so disabling lint
 import produce from 'immer';
-import { DataMask, FeatureFlag } from '@superset-ui/core';
+import {
+  DataMask,
+  DataMaskStateWithId,
+  DataMaskWithId,
+  FeatureFlag,
+  Filter,
+  FilterConfiguration,
+  Filters,
+} from '@superset-ui/core';
 import { NATIVE_FILTER_PREFIX } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/utils';
 import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate';
 import { isFeatureEnabled } from 'src/featureFlags';
-import { DataMaskStateWithId, DataMaskWithId } from './types';
 import {
   AnyDataMaskAction,
   CLEAR_DATA_MASK_STATE,
   SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE,
   UPDATE_DATA_MASK,
 } from './actions';
-import {
-  Filter,
-  FilterConfiguration,
-} from '../dashboard/components/nativeFilters/types';
 import { areObjectsEqual } from '../reduxUtils';
-import { Filters } from '../dashboard/reducers/types';
 
 export function getInitialDataMask(
   id?: string | number,
diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts
index 5380fe2..0547e8a 100644
--- a/superset-frontend/src/preamble.ts
+++ b/superset-frontend/src/preamble.ts
@@ -25,6 +25,7 @@ import { merge } from 'lodash';
 import setupClient from './setup/setupClient';
 import setupColors from './setup/setupColors';
 import setupFormatters from './setup/setupFormatters';
+import setupDashboardComponents from './setup/setupDasboardComponents';
 
 if (process.env.WEBPACK_MODE === 'development') {
   setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false });
@@ -60,6 +61,8 @@ setupColors(
 // Setup number formatters
 setupFormatters();
 
+setupDashboardComponents();
+
 export const theme = merge(
   supersetTheme,
   bootstrapData?.common?.theme_overrides ?? {},
diff --git a/superset-frontend/src/dataMask/types.ts b/superset-frontend/src/setup/setupDasboardComponents.ts
similarity index 60%
copy from superset-frontend/src/dataMask/types.ts
copy to superset-frontend/src/setup/setupDasboardComponents.ts
index 95d2073..f579933 100644
--- a/superset-frontend/src/dataMask/types.ts
+++ b/superset-frontend/src/setup/setupDasboardComponents.ts
@@ -16,14 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMask } from '@superset-ui/core';
 
-export enum DataMaskType {
-  NativeFilters = 'nativeFilters',
-  CrossFilters = 'crossFilters',
-}
+/*
+  This file can be overridden from outside by custom config, it will add/delete new components to existing config in
+  superset-frontend/src/visualizations/presets/dashboardComponents.ts file
+ */
 
-export type DataMaskState = { [id: string]: DataMask };
+// import dashboardComponentsRegistry from '../visualizations/presets/dashboardComponents';
+// import example from '../visualizations/dashboardComponents/ExampleComponent';
 
-export type DataMaskWithId = { id: string } & DataMask;
-export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
+export default function setupDashboardComponents() {
+  // Add custom dashboard components here. Example:
+  // dashboardComponentsRegistry.set('example', example);
+}
diff --git a/superset-frontend/src/utils/functionalRegistry.ts b/superset-frontend/src/utils/functionalRegistry.ts
new file mode 100644
index 0000000..7ae73f4
--- /dev/null
+++ b/superset-frontend/src/utils/functionalRegistry.ts
@@ -0,0 +1,83 @@
+/**
+ * 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 React, { ComponentType } from 'react';
+import { JsonObject } from '@superset-ui/core';
+
+export interface RegistryMetadata {
+  description: string;
+  name: string;
+}
+
+export interface ComponentItem<Metadata = RegistryMetadata> {
+  metadata: Metadata;
+  loadComponent: () => Promise<{ default: ComponentType<any> }>;
+}
+
+export interface ComponentRegistry<Metadata = RegistryMetadata> {
+  metadata: Metadata;
+  Component: ComponentType<any>;
+}
+
+export type FunctionalRegistryState<RegistryT> = {
+  registry: { [key: string]: RegistryT & { key: string } };
+  registryKeys: string[];
+};
+
+export const registryGetAll =
+  <RegistryT>({ registryKeys, registry }: FunctionalRegistryState<RegistryT>) =>
+  () =>
+    registryKeys.map(key => registry[key]);
+
+export const registryDelete =
+  <RegistryT>({ registryKeys, registry }: FunctionalRegistryState<RegistryT>) =>
+  (keyToDelete: string) => {
+    // eslint-disable-next-line no-param-reassign
+    registryKeys = registryKeys.filter(key => key !== keyToDelete);
+    // eslint-disable-next-line no-param-reassign
+    delete registry[keyToDelete];
+  };
+
+export const registryGet =
+  <RegistryT>({ registry }: FunctionalRegistryState<RegistryT>) =>
+  (key: string) =>
+    registry[key];
+
+export const registrySet =
+  ({ registryKeys, registry }: FunctionalRegistryState<JsonObject>) =>
+  (key: string, item: JsonObject) => {
+    registryKeys.push(key);
+    // eslint-disable-next-line no-param-reassign
+    registry[key] = {
+      key,
+      ...item,
+    };
+  };
+
+export const registrySetComponent =
+  ({ registryKeys, registry }: FunctionalRegistryState<ComponentRegistry>) =>
+  (key: string, item: ComponentItem) => {
+    registryKeys.push(key);
+    // eslint-disable-next-line no-param-reassign
+    registry[key] = {
+      key,
+      metadata: item.metadata,
+      Component: React.lazy(item.loadComponent),
+    };
+  };
diff --git a/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts b/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts
new file mode 100644
index 0000000..1b6faa6
--- /dev/null
+++ b/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts
@@ -0,0 +1,62 @@
+/**
+ * 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 {
+  ComponentItem,
+  ComponentRegistry,
+  FunctionalRegistryState,
+  registryDelete,
+  registryGet,
+  registryGetAll,
+  RegistryMetadata,
+  registrySetComponent,
+} from '../../utils/functionalRegistry';
+
+export interface DashboardComponentsRegistryMetadata extends RegistryMetadata {
+  iconName: string;
+}
+
+/*
+  This is registry that contains list of dynamic dashboard components that can be added in addition to main components
+ */
+
+const DashboardComponentsRegistry = (
+  initComponents: { key: string; item: ComponentItem }[] = [],
+) => {
+  const state: FunctionalRegistryState<
+    ComponentRegistry<DashboardComponentsRegistryMetadata>
+  > = {
+    registry: {},
+    registryKeys: [],
+  };
+
+  const set = registrySetComponent(state);
+
+  initComponents.forEach(({ key, item }) => {
+    set(key, item);
+  });
+
+  return {
+    set,
+    get: registryGet(state),
+    delete: registryDelete(state),
+    getAll: registryGetAll(state),
+  };
+};
+
+export default DashboardComponentsRegistry;
diff --git a/superset-frontend/src/dataMask/types.ts b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx
similarity index 68%
copy from superset-frontend/src/dataMask/types.ts
copy to superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx
index 95d2073..22c1353 100644
--- a/superset-frontend/src/dataMask/types.ts
+++ b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx
@@ -16,14 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMask } from '@superset-ui/core';
+import React from 'react';
+import { DashboardComponentMetadata, t } from '@superset-ui/core';
 
-export enum DataMaskType {
-  NativeFilters = 'nativeFilters',
-  CrossFilters = 'crossFilters',
-}
+// TODO: POC only component can be removed after PR approved
+const ExampleComponent = ({
+  metadata,
+}: {
+  metadata: DashboardComponentMetadata;
+}) => (
+  <div>
+    {t('We have the following keys: %s', Object.keys(metadata).join(', '))}
+  </div>
+);
 
-export type DataMaskState = { [id: string]: DataMask };
-
-export type DataMaskWithId = { id: string } & DataMask;
-export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
+export default ExampleComponent;
diff --git a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts
similarity index 77%
copy from superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts
copy to superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts
index b56ffc0..8e67d42 100644
--- a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts
+++ b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts
@@ -17,8 +17,12 @@
  * under the License.
  */
 
-import { Scope } from '../nativeFilters/types';
-
-export type CrossFilterScopingFormType = {
-  scope: Scope;
+// TODO: POC only component can be removed after PR approved
+export default {
+  metadata: {
+    name: 'Example',
+    description: 'Example description',
+    iconName: 'filter',
+  },
+  loadComponent: () => import('./ExampleComponent'),
 };
diff --git a/superset-frontend/src/dataMask/types.ts b/superset-frontend/src/visualizations/presets/dashboardComponents.ts
similarity index 70%
rename from superset-frontend/src/dataMask/types.ts
rename to superset-frontend/src/visualizations/presets/dashboardComponents.ts
index 95d2073..0d527f3 100644
--- a/superset-frontend/src/dataMask/types.ts
+++ b/superset-frontend/src/visualizations/presets/dashboardComponents.ts
@@ -16,14 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { DataMask } from '@superset-ui/core';
 
-export enum DataMaskType {
-  NativeFilters = 'nativeFilters',
-  CrossFilters = 'crossFilters',
-}
+/*
+  Preset dashboard components (in addition to basic components like row, column, chart, etc...)
+ */
+
+import DashboardComponentsRegistry from '../dashboardComponents/DashboardComponentsRegistry';
 
-export type DataMaskState = { [id: string]: DataMask };
+const dashboardComponents = DashboardComponentsRegistry([
+  // Here can be added default dashboard components
+]);
 
-export type DataMaskWithId = { id: string } & DataMask;
-export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
+export default dashboardComponents;