superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ccwilli...@apache.org
Subject [incubator-superset] branch master updated: [Refactor] Extend color scheme management to sequential schemes (#6150)
Date Mon, 22 Oct 2018 23:17:20 GMT
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/master by this push:
     new b9257b2  [Refactor] Extend color scheme management to sequential schemes (#6150)
b9257b2 is described below

commit b9257b2a09ba1e80dd73ce8cb344115f38f875ab
Author: Krist Wongsuphasawat <krist.wongz@gmail.com>
AuthorDate: Mon Oct 22 16:17:14 2018 -0700

    [Refactor] Extend color scheme management to sequential schemes (#6150)
    
    * refactor color scheme
    
    * Update data structure
    
    * Update color scheme files
    
    * wip
    
    * convert all sequential schemes
    
    * Update how color schemes are managed. Extend it for sequential schemes
    
    * extract color setup into separate file
    
    * Update imports
    
    * update imports
    
    * Add new functions to Registry
    
    * Update ColorSchemeManager to extends Registry and update unit tests
    
    * Add test for Registry
    
    * Rename ColorSchemeManager to ColorSchemeRegistry
    
    * Fix unit tests
    
    * Update API
    
    * Fix imports
    
    * Add label field
    
    * Fix reference to colors
    
    * update SequentialScheme contructor
    
    * Fix controls
    
    * rename manager to registry
    
    * Split sequential schemes into multiple files
    
    * update sequential color labels
    
    * add values and valuesAsPromise()
    
    * use .values()
---
 .../explore/components/ColorPickerControl_spec.jsx |   9 +-
 .../explore/components/ColorScheme_spec.jsx        |   4 +-
 .../javascripts/modules/ColorSchemeManager_spec.js | 139 ------
 .../spec/javascripts/modules/Registry_spec.js      |  70 +++
 .../{ => colors}/CategoricalColorNameSpace_spec.js |  16 +-
 .../{ => colors}/CategoricalColorScale_spec.js     |   2 +-
 .../modules/colors/ColorSchemeRegistry_spec.js     |  64 +++
 superset/assets/src/common.js                      |  13 +-
 .../src/dashboard/reducers/getInitialState.js      |   2 +-
 .../components/controls/AnnotationLayer.jsx        |   7 +-
 .../components/controls/ColorPickerControl.jsx     |  11 +-
 .../components/controls/ColorSchemeControl.jsx     |   2 +-
 superset/assets/src/explore/controls.jsx           |  63 +--
 superset/assets/src/modules/ColorSchemeManager.js  |  86 ----
 superset/assets/src/modules/Registry.js            |  32 ++
 superset/assets/src/modules/colorSchemes/airbnb.js |  25 -
 .../assets/src/modules/colorSchemes/categorical.js |  42 --
 superset/assets/src/modules/colorSchemes/lyft.js   |  14 -
 .../assets/src/modules/colorSchemes/sequential.js  | 433 -----------------
 superset/assets/src/modules/colors.js              |   4 +-
 .../{ => colors}/CategoricalColorNamespace.js      |   6 +-
 .../modules/{ => colors}/CategoricalColorScale.js  |   2 +-
 .../assets/src/modules/colors/CategoricalScheme.js |   3 +
 .../colors/CategoricalSchemeRegistrySingleton.js   |   8 +
 superset/assets/src/modules/colors/ColorScheme.js  |  15 +
 .../src/modules/colors/ColorSchemeRegistry.js      |  36 ++
 .../assets/src/modules/colors/SequentialScheme.js  |   9 +
 .../colors/SequentialSchemeRegistrySingleton.js    |   8 +
 .../colors/colorSchemes/categorical/airbnb.js      |  32 ++
 .../modules/colors/colorSchemes/categorical/d3.js  |  23 +
 .../colors/colorSchemes/categorical/google.js      |  46 ++
 .../colors/colorSchemes/categorical/lyft.js        |  21 +
 .../colors/colorSchemes/sequential/common.js       | 121 +++++
 .../modules/colors/colorSchemes/sequential/d3.js   | 510 +++++++++++++++++++++
 superset/assets/src/setup/setupColors.js           |  26 ++
 superset/assets/src/visualizations/Chord/Chord.js  |   2 +-
 .../src/visualizations/Histogram/Histogram.jsx     |   2 +-
 .../src/visualizations/Partition/Partition.js      |   2 +-
 superset/assets/src/visualizations/Rose/Rose.js    |   2 +-
 .../assets/src/visualizations/Sankey/Sankey.js     |   2 +-
 .../assets/src/visualizations/Sunburst/Sunburst.js |   2 +-
 .../assets/src/visualizations/Treemap/Treemap.js   |   2 +-
 .../deckgl/CategoricalDeckGLContainer.jsx          |   4 +-
 superset/assets/src/visualizations/nvd3/NVD3Vis.js |   2 +-
 .../src/visualizations/wordcloud/WordCloud.js      |   2 +-
 45 files changed, 1090 insertions(+), 836 deletions(-)

diff --git a/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
index 70f00aa..ca814ee 100644
--- a/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
@@ -7,7 +7,8 @@ import { SketchPicker } from 'react-color';
 import ColorPickerControl from
   '../../../../src/explore/components/controls/ColorPickerControl';
 import ControlHeader from '../../../../src/explore/components/ControlHeader';
-import { registerScheme } from '../../../../src/modules/ColorSchemeManager';
+import getCategoricalSchemeRegistry from '../../../../src/modules/colors/CategoricalSchemeRegistrySingleton';
+import CategoricalScheme from '../../../../src/modules/colors/CategoricalScheme';
 
 const defaultProps = {
   value: { },
@@ -17,7 +18,11 @@ describe('ColorPickerControl', () => {
   let wrapper;
   let inst;
   beforeEach(() => {
-    registerScheme('test', ['red', 'green', 'blue'])
+    getCategoricalSchemeRegistry()
+      .registerValue('test', new CategoricalScheme({
+        name: 'test',
+        colors: ['red', 'green', 'blue'],
+      }))
       .setDefaultSchemeName('test');
     wrapper = shallow(<ColorPickerControl {...defaultProps} />);
     inst = wrapper.instance();
diff --git a/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
index 5cf2be2..995bb59 100644
--- a/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
@@ -5,10 +5,10 @@ import { Creatable } from 'react-select';
 
 import ColorSchemeControl from
   '../../../../src/explore/components/controls/ColorSchemeControl';
-import { getAllSchemes } from '../../../../src/modules/ColorSchemeManager';
+import getCategoricalSchemeRegistry from '../../../../src/modules/colors/CategoricalSchemeRegistrySingleton';
 
 const defaultProps = {
-  options: Object.keys(getAllSchemes()).map(s => ([s, s])),
+  options: getCategoricalSchemeRegistry().keys().map(s => ([s, s])),
 };
 
 describe('ColorSchemeControl', () => {
diff --git a/superset/assets/spec/javascripts/modules/ColorSchemeManager_spec.js b/superset/assets/spec/javascripts/modules/ColorSchemeManager_spec.js
deleted file mode 100644
index 2f3fe33..0000000
--- a/superset/assets/spec/javascripts/modules/ColorSchemeManager_spec.js
+++ /dev/null
@@ -1,139 +0,0 @@
-import ColorSchemeManager, {
-  getInstance,
-  getScheme,
-  getAllSchemes,
-  getDefaultSchemeName,
-  setDefaultSchemeName,
-  registerScheme,
-  registerMultipleSchemes,
-} from '../../../src/modules/ColorSchemeManager';
-
-describe('ColorSchemeManager', () => {
-  beforeEach(() => {
-    const m = getInstance();
-    m.clearScheme();
-    m.registerScheme('test', ['red', 'green', 'blue']);
-    m.registerScheme('test2', ['orange', 'yellow', 'pink']);
-    m.setDefaultSchemeName('test');
-  });
-  it('The class constructor cannot be accessed directly', () => {
-    expect(typeof ColorSchemeManager).not.toBe('Function');
-  });
-  describe('static getInstance()', () => {
-    it('returns a singleton instance', () => {
-      const m1 = getInstance();
-      const m2 = getInstance();
-      expect(m1).toBeDefined();
-      expect(m1).toBe(m2);
-    });
-  });
-  describe('.getScheme()', () => {
-    it('.getScheme() returns default color scheme', () => {
-      const scheme = getInstance().getScheme();
-      expect(scheme).toEqual(['red', 'green', 'blue']);
-    });
-    it('.getScheme(name) returns color scheme with specified name', () => {
-      const scheme = getInstance().getScheme('test2');
-      expect(scheme).toEqual(['orange', 'yellow', 'pink']);
-    });
-  });
-  describe('.getAllSchemes()', () => {
-    it('returns all registered schemes', () => {
-      const schemes = getInstance().getAllSchemes();
-      expect(schemes).toEqual({
-        test: ['red', 'green', 'blue'],
-        test2: ['orange', 'yellow', 'pink'],
-      });
-    });
-  });
-  describe('.getDefaultSchemeName()', () => {
-    it('returns default scheme name', () => {
-      const name = getInstance().getDefaultSchemeName();
-      expect(name).toBe('test');
-    });
-  });
-  describe('.setDefaultSchemeName()', () => {
-    it('set default scheme name', () => {
-      getInstance().setDefaultSchemeName('test2');
-      const name = getInstance().getDefaultSchemeName();
-      expect(name).toBe('test2');
-      getInstance().setDefaultSchemeName('test');
-    });
-    it('returns the ColorSchemeManager instance', () => {
-      const instance = getInstance().setDefaultSchemeName('test');
-      expect(instance).toBe(getInstance());
-    });
-  });
-  describe('.registerScheme(name, colors)', () => {
-    it('sets schemename and color', () => {
-      getInstance().registerScheme('test3', ['cyan', 'magenta']);
-      const scheme = getInstance().getScheme('test3');
-      expect(scheme).toEqual(['cyan', 'magenta']);
-    });
-    it('returns the ColorSchemeManager instance', () => {
-      const instance = getInstance().registerScheme('test3', ['cyan', 'magenta']);
-      expect(instance).toBe(getInstance());
-    });
-  });
-  describe('.registerMultipleSchemes(object)', () => {
-    it('sets multiple schemes at once', () => {
-      getInstance().registerMultipleSchemes({
-        test4: ['cyan', 'magenta'],
-        test5: ['brown', 'purple'],
-      });
-      const scheme1 = getInstance().getScheme('test4');
-      expect(scheme1).toEqual(['cyan', 'magenta']);
-      const scheme2 = getInstance().getScheme('test5');
-      expect(scheme2).toEqual(['brown', 'purple']);
-    });
-    it('returns the ColorSchemeManager instance', () => {
-      const instance = getInstance().registerMultipleSchemes({
-        test4: ['cyan', 'magenta'],
-        test5: ['brown', 'purple'],
-      });
-      expect(instance).toBe(getInstance());
-    });
-  });
-  describe('static getScheme()', () => {
-    it('is equivalent to getInstance().getScheme()', () => {
-      expect(getInstance().getScheme()).toBe(getScheme());
-    });
-  });
-  describe('static getAllSchemes()', () => {
-    it('is equivalent to getInstance().getAllSchemes()', () => {
-      expect(getInstance().getAllSchemes()).toBe(getAllSchemes());
-    });
-  });
-  describe('static getDefaultSchemeName()', () => {
-    it('is equivalent to getInstance().getDefaultSchemeName()', () => {
-      expect(getInstance().getDefaultSchemeName()).toBe(getDefaultSchemeName());
-    });
-  });
-  describe('static setDefaultSchemeName()', () => {
-    it('is equivalent to getInstance().setDefaultSchemeName()', () => {
-      setDefaultSchemeName('test2');
-      const name = getInstance().getDefaultSchemeName();
-      expect(name).toBe('test2');
-      setDefaultSchemeName('test');
-    });
-  });
-  describe('static registerScheme()', () => {
-    it('is equivalent to getInstance().registerScheme()', () => {
-      registerScheme('test3', ['cyan', 'magenta']);
-      const scheme = getInstance().getScheme('test3');
-      expect(scheme).toEqual(['cyan', 'magenta']);
-    });
-  });
-  describe('static registerMultipleSchemes()', () => {
-    it('is equivalent to getInstance().registerMultipleSchemes()', () => {
-      registerMultipleSchemes({
-        test4: ['cyan', 'magenta'],
-        test5: ['brown', 'purple'],
-      });
-      const scheme1 = getInstance().getScheme('test4');
-      expect(scheme1).toEqual(['cyan', 'magenta']);
-      const scheme2 = getInstance().getScheme('test5');
-      expect(scheme2).toEqual(['brown', 'purple']);
-    });
-  });
-});
diff --git a/superset/assets/spec/javascripts/modules/Registry_spec.js b/superset/assets/spec/javascripts/modules/Registry_spec.js
index 5eb5791..111a614 100644
--- a/superset/assets/spec/javascripts/modules/Registry_spec.js
+++ b/superset/assets/spec/javascripts/modules/Registry_spec.js
@@ -17,6 +17,20 @@ describe('Registry', () => {
     });
   });
 
+  describe('.clear()', () => {
+    it('clears all registered items', () => {
+      const registry = new Registry();
+      registry.registerValue('a', 'testValue');
+      registry.clear();
+      expect(Object.keys(registry.items)).toHaveLength(0);
+      expect(Object.keys(registry.promises)).toHaveLength(0);
+    });
+    it('returns the registry itself', () => {
+      const registry = new Registry();
+      expect(registry.clear()).toBe(registry);
+    });
+  });
+
   describe('.has(key)', () => {
     it('returns true if an item with the given key exists', () => {
       const registry = new Registry();
@@ -134,6 +148,34 @@ describe('Registry', () => {
     );
   });
 
+  describe('.getMap()', () => {
+    it('returns key-value map as plain object', () => {
+      const registry = new Registry();
+      registry.registerValue('a', 'cat');
+      registry.registerLoader('b', () => 'dog');
+      expect(registry.getMap()).toEqual({
+        a: 'cat',
+        b: 'dog',
+      });
+    });
+  });
+
+  describe('.getMapAsPromise()', () => {
+    it('returns a promise of key-value map', () => {
+      const registry = new Registry();
+      registry.registerValue('a', 'test1');
+      registry.registerLoader('b', () => 'test2');
+      registry.registerLoader('c', () => Promise.resolve('test3'));
+      return registry.getMapAsPromise().then((map) => {
+        expect(map).toEqual({
+          a: 'test1',
+          b: 'test2',
+          c: 'test3',
+        });
+      });
+    });
+  });
+
   describe('.keys()', () => {
     it('returns an array of keys', () => {
       const registry = new Registry();
@@ -143,6 +185,34 @@ describe('Registry', () => {
     });
   });
 
+  describe('.values()', () => {
+    it('returns an array of values', () => {
+      const registry = new Registry();
+      registry.registerValue('a', 'test1');
+      registry.registerLoader('b', () => 'test2');
+      expect(registry.values()).toEqual([
+        'test1',
+        'test2',
+      ]);
+    });
+  });
+
+  describe('.valuesAsPromise()', () => {
+    it('returns a Promise of an array { key, value }', () => {
+      const registry = new Registry();
+      registry.registerValue('a', 'test1');
+      registry.registerLoader('b', () => 'test2');
+      registry.registerLoader('c', () => Promise.resolve('test3'));
+      return registry.valuesAsPromise().then((entries) => {
+        expect(entries).toEqual([
+          'test1',
+          'test2',
+          'test3',
+        ]);
+      });
+    });
+  });
+
   describe('.entries()', () => {
     it('returns an array of { key, value }', () => {
       const registry = new Registry();
diff --git a/superset/assets/spec/javascripts/modules/CategoricalColorNameSpace_spec.js b/superset/assets/spec/javascripts/modules/colors/CategoricalColorNameSpace_spec.js
similarity index 90%
rename from superset/assets/spec/javascripts/modules/CategoricalColorNameSpace_spec.js
rename to superset/assets/spec/javascripts/modules/colors/CategoricalColorNameSpace_spec.js
index 0be4996..8ff952a 100644
--- a/superset/assets/spec/javascripts/modules/CategoricalColorNameSpace_spec.js
+++ b/superset/assets/spec/javascripts/modules/colors/CategoricalColorNameSpace_spec.js
@@ -3,13 +3,21 @@ import CategoricalColorNamespace, {
   getScale,
   getColor,
   DEFAULT_NAMESPACE,
-} from '../../../src/modules/CategoricalColorNamespace';
-import { registerScheme } from '../../../src/modules/ColorSchemeManager';
+} from '../../../../src/modules/colors/CategoricalColorNamespace';
+import getCategoricalSchemeRegistry from '../../../../src/modules/colors/CategoricalSchemeRegistrySingleton';
+import CategoricalScheme from '../../../../src/modules/colors/CategoricalScheme';
 
 describe('CategoricalColorNamespace', () => {
   beforeAll(() => {
-    registerScheme('testColors', ['red', 'green', 'blue']);
-    registerScheme('testColors2', ['red', 'green', 'blue']);
+    getCategoricalSchemeRegistry()
+      .registerValue('testColors', new CategoricalScheme({
+        name: 'testColors',
+        colors: ['red', 'green', 'blue'],
+      }))
+      .registerValue('testColors2', new CategoricalScheme({
+        name: 'testColors2',
+        colors: ['red', 'green', 'blue'],
+      }));
   });
   it('The class constructor cannot be accessed directly', () => {
     expect(typeof CategoricalColorNamespace).not.toBe('Function');
diff --git a/superset/assets/spec/javascripts/modules/CategoricalColorScale_spec.js b/superset/assets/spec/javascripts/modules/colors/CategoricalColorScale_spec.js
similarity index 97%
rename from superset/assets/spec/javascripts/modules/CategoricalColorScale_spec.js
rename to superset/assets/spec/javascripts/modules/colors/CategoricalColorScale_spec.js
index 5cbf6e6..32a455d 100644
--- a/superset/assets/spec/javascripts/modules/CategoricalColorScale_spec.js
+++ b/superset/assets/spec/javascripts/modules/colors/CategoricalColorScale_spec.js
@@ -1,4 +1,4 @@
-import CategoricalColorScale from '../../../src/modules/CategoricalColorScale';
+import CategoricalColorScale from '../../../../src/modules/colors/CategoricalColorScale';
 
 describe('CategoricalColorScale', () => {
   it('exists', () => {
diff --git a/superset/assets/spec/javascripts/modules/colors/ColorSchemeRegistry_spec.js b/superset/assets/spec/javascripts/modules/colors/ColorSchemeRegistry_spec.js
new file mode 100644
index 0000000..94f6c89
--- /dev/null
+++ b/superset/assets/spec/javascripts/modules/colors/ColorSchemeRegistry_spec.js
@@ -0,0 +1,64 @@
+import ColorSchemeRegistry from '../../../../src/modules/colors/ColorSchemeRegistry';
+import CategoricalScheme from '../../../../src/modules/colors/CategoricalScheme';
+
+describe('ColorSchemeRegistry', () => {
+  const registry = new ColorSchemeRegistry();
+  const SCHEME1 = new CategoricalScheme({
+    name: 'test',
+    colors: ['red', 'green', 'blue'],
+  });
+  const SCHEME2 = new CategoricalScheme({
+    name: 'test2',
+    colors: ['orange', 'yellow', 'pink'],
+  });
+  const SCHEME3 = new CategoricalScheme({
+    name: 'test3',
+    colors: ['cyan', 'magenta'],
+  });
+
+  beforeEach(() => {
+    registry.clear();
+    registry.registerValue('test', SCHEME1);
+    registry.registerValue('test2', SCHEME2);
+    registry.setDefaultSchemeName('test');
+  });
+  describe('.get()', () => {
+    it('.get() returns default color scheme', () => {
+      const scheme = registry.get();
+      expect(scheme).toEqual(SCHEME1);
+    });
+    it('.get(name) returns color scheme with specified name', () => {
+      const scheme = registry.get('test2');
+      expect(scheme).toEqual(SCHEME2);
+    });
+  });
+  describe('.getDefaultSchemeName()', () => {
+    it('returns default scheme name', () => {
+      const name = registry.getDefaultSchemeName();
+      expect(name).toBe('test');
+    });
+  });
+  describe('.setDefaultSchemeName()', () => {
+    it('set default scheme name', () => {
+      registry.setDefaultSchemeName('test2');
+      const name = registry.getDefaultSchemeName();
+      expect(name).toBe('test2');
+      registry.setDefaultSchemeName('test');
+    });
+    it('returns the ColorSchemeRegistry instance', () => {
+      const instance = registry.setDefaultSchemeName('test');
+      expect(instance).toBe(registry);
+    });
+  });
+  describe('.registerValue(name, colors)', () => {
+    it('sets schemename and color', () => {
+      registry.registerValue('test3', SCHEME3);
+      const scheme = registry.get('test3');
+      expect(scheme).toEqual(SCHEME3);
+    });
+    it('returns the ColorSchemeRegistry instance', () => {
+      const instance = registry.registerValue('test3', SCHEME3);
+      expect(instance).toBe(registry);
+    });
+  });
+});
diff --git a/superset/assets/src/common.js b/superset/assets/src/common.js
index f479d22..f4f6621 100644
--- a/superset/assets/src/common.js
+++ b/superset/assets/src/common.js
@@ -2,12 +2,8 @@
 import $ from 'jquery';
 import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
 import { SupersetClient } from '@superset-ui/core';
-
-import airbnb from './modules/colorSchemes/airbnb';
-import categoricalSchemes from './modules/colorSchemes/categorical';
-import lyft from './modules/colorSchemes/lyft';
-import { getInstance } from './modules/ColorSchemeManager';
 import { toggleCheckbox } from './modules/utils';
+import setupColors from './setup/setupColors';
 
 $(document).ready(function () {
   $(':checkbox[data-checkbox-api-prefix]').change(function () {
@@ -28,12 +24,7 @@ $(document).ready(function () {
   });
 });
 
-// Register color schemes
-getInstance()
-  .registerScheme('bnbColors', airbnb.bnbColors)
-  .registerMultipleSchemes(categoricalSchemes)
-  .registerScheme('lyftColors', lyft.lyftColors)
-  .setDefaultSchemeName('bnbColors');
+setupColors();
 
 export function appSetup() {
   // A set of hacks to allow apps to run within a FAB template
diff --git a/superset/assets/src/dashboard/reducers/getInitialState.js b/superset/assets/src/dashboard/reducers/getInitialState.js
index 523db9f..c3b9dfd 100644
--- a/superset/assets/src/dashboard/reducers/getInitialState.js
+++ b/superset/assets/src/dashboard/reducers/getInitialState.js
@@ -18,7 +18,7 @@ import {
   CHART_TYPE,
   ROW_TYPE,
 } from '../util/componentTypes';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 
 export default function(bootstrapData) {
   const { user_id, datasources, common, editMode } = bootstrapData;
diff --git a/superset/assets/src/explore/components/controls/AnnotationLayer.jsx b/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
index cbf17a1..5fd580b 100644
--- a/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
+++ b/superset/assets/src/explore/components/controls/AnnotationLayer.jsx
@@ -25,7 +25,7 @@ import { nonEmpty } from '../../validators';
 import vizTypes from '../../visTypes';
 
 import { t } from '../../../locales';
-import { getScheme } from '../../../modules/ColorSchemeManager';
+import getCategoricalSchemeRegistry from '../../../modules/colors/CategoricalSchemeRegistrySingleton';
 
 const AUTOMATIC_COLOR = '';
 
@@ -484,7 +484,10 @@ export default class AnnotationLayer extends React.PureComponent {
 
   renderDisplayConfiguration() {
     const { color, opacity, style, width, showMarkers, hideLine, annotationType } = this.state;
-    const colorScheme = [...getScheme(this.props.colorScheme)];
+    const colorScheme = getCategoricalSchemeRegistry()
+      .get(this.props.colorScheme)
+      .colors
+      .concat();
     if (
       color &&
       color !== AUTOMATIC_COLOR &&
diff --git a/superset/assets/src/explore/components/controls/ColorPickerControl.jsx b/superset/assets/src/explore/components/controls/ColorPickerControl.jsx
index 55d7ce4..2c631c1 100644
--- a/superset/assets/src/explore/components/controls/ColorPickerControl.jsx
+++ b/superset/assets/src/explore/components/controls/ColorPickerControl.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { OverlayTrigger, Popover } from 'react-bootstrap';
 import { SketchPicker } from 'react-color';
 import ControlHeader from '../ControlHeader';
-import { getScheme } from '../../../modules/ColorSchemeManager';
+import getCategoricalSchemeRegistry from '../../../modules/colors/CategoricalSchemeRegistrySingleton';
 
 const propTypes = {
   onChange: PropTypes.func,
@@ -53,14 +53,19 @@ export default class ColorPickerControl extends React.Component {
     this.props.onChange(col.rgb);
   }
   renderPopover() {
+    const presetColors = getCategoricalSchemeRegistry()
+      .get()
+      .colors
+      .filter((s, i) => i < 7);
     return (
       <Popover id="filter-popover" className="color-popover">
         <SketchPicker
           color={this.props.value}
           onChange={this.onChange}
-          presetColors={getScheme().filter((s, i) => i < 7)}
+          presetColors={presetColors}
         />
-      </Popover>);
+      </Popover>
+    );
   }
   render() {
     const c = this.props.value || { r: 0, g: 0, b: 0, a: 0 };
diff --git a/superset/assets/src/explore/components/controls/ColorSchemeControl.jsx b/superset/assets/src/explore/components/controls/ColorSchemeControl.jsx
index f09125d..5d9ad46 100644
--- a/superset/assets/src/explore/components/controls/ColorSchemeControl.jsx
+++ b/superset/assets/src/explore/components/controls/ColorSchemeControl.jsx
@@ -49,7 +49,7 @@ export default class ColorSchemeControl extends React.PureComponent {
   renderOption(key) {
     const { schemes } = this.props;
     const schemeLookup = isFunction(schemes) ? schemes() : schemes;
-    const currentScheme = schemeLookup[key.value || defaultProps.value];
+    const currentScheme = schemeLookup[key.value || defaultProps.value].colors;
 
     let colors = currentScheme;
     if (this.props.isLinear) {
diff --git a/superset/assets/src/explore/controls.jsx b/superset/assets/src/explore/controls.jsx
index 67f21ac..05e4f54 100644
--- a/superset/assets/src/explore/controls.jsx
+++ b/superset/assets/src/explore/controls.jsx
@@ -50,8 +50,11 @@ import { defaultViewport } from '../modules/geo';
 import ColumnOption from '../components/ColumnOption';
 import OptionDescription from '../components/OptionDescription';
 import { t } from '../locales';
-import { getAllSchemes } from '../modules/ColorSchemeManager';
-import sequentialSchemes from '../modules/colorSchemes/sequential';
+import getCategoricalSchemeRegistry from '../modules/colors/CategoricalSchemeRegistrySingleton';
+import getSequentialSchemeRegistry from '../modules/colors/SequentialSchemeRegistrySingleton';
+
+const categoricalSchemeRegistry = getCategoricalSchemeRegistry();
+const sequentialSchemeRegistry = getSequentialSchemeRegistry();
 
 const D3_FORMAT_DOCS = 'D3 format syntax: https://github.com/d3/d3-format';
 
@@ -323,58 +326,14 @@ export const controls = {
   linear_color_scheme: {
     type: 'ColorSchemeControl',
     label: t('Linear Color Scheme'),
-    choices: [
-      ['fire', 'fire'],
-      ['white_black', 'white/black'],
-      ['black_white', 'black/white'],
-      ['dark_blue', 'light/dark blue'],
-      ['pink_grey', 'pink/white/grey'],
-      ['greens', 'greens'],
-      ['purples', 'purples'],
-      ['oranges', 'oranges'],
-      ['blue_white_yellow', 'blue/white/yellow'],
-      ['red_yellow_blue', 'red/yellowish/blue'],
-      ['brown_white_green', 'brown/white/green'],
-      ['purple_white_green', 'purple/white/green'],
-      ['schemeBrBG', 'brown/green'],
-      ['schemePRGn', 'purple/green'],
-      ['schemePiYG', 'pink/green'],
-      ['schemePuOr', 'purple/orange'],
-      ['schemeRdBu', 'red/blue'],
-      ['schemeRdGy', 'red/gray/black'],
-      ['schemeRdYlBu', 'red/yellow/blue'],
-      ['schemeRdYlGn', 'red/yellow/green'],
-      ['schemeSpectral', 'rainbow'],
-      ['schemeBlues', 'd3/blues'],
-      ['schemeGreens', 'd3/greens'],
-      ['schemeGrays', 'd3/grays'],
-      ['schemeOranges', 'd3/oranges'],
-      ['schemePurples', 'd3/purples'],
-      ['schemeReds', 'd3/reds'],
-      ['schemeViridis', 'd3/purple/blue/green/yellow'],
-      ['schemeInferno', 'd3/purple/red/orange/yellow'],
-      ['schemeMagma', 'd3/purple/pink/peach'],
-      ['schemeWarm', 'd3/warm/purple/pink/yellow/green'],
-      ['schemeCool', 'd3/cool/blue/green'],
-      ['schemeCubehelixDefault', 'd3/black/green/brown/pink/blue'],
-      ['schemeBuGn', 'd3/blue/green'],
-      ['schemeBuPu', 'd3/blue/purple'],
-      ['schemeGnBu', 'd3/green/blue'],
-      ['schemeOrRd', 'd3/orange/red'],
-      ['schemePuBuGn', 'd3/purple/blue/green'],
-      ['schemePuBu', 'd3/purple/blue'],
-      ['schemePuRd', 'd3/purple/red'],
-      ['schemeRdPu', 'd3/red/purple'],
-      ['schemeYlGnBu', 'd3/yellow/green/blue'],
-      ['schemeYlGn', 'd3/yellow/green'],
-      ['schemeYlOrBr', 'd3/yellow/brown'],
-      ['schemeYlOrRd', 'd3/yellow/orange/red'],
-    ],
+    choices: () => sequentialSchemeRegistry
+      .values()
+      .map(value => [value.name, value.label]),
     default: 'blue_white_yellow',
     clearable: false,
     description: '',
     renderTrigger: true,
-    schemes: sequentialSchemes,
+    schemes: () => sequentialSchemeRegistry.getMap(),
     isLinear: true,
   },
 
@@ -1965,9 +1924,9 @@ export const controls = {
     label: t('Color Scheme'),
     default: 'bnbColors',
     renderTrigger: true,
-    choices: () => Object.keys(getAllSchemes()).map(s => ([s, s])),
+    choices: () => categoricalSchemeRegistry.keys().map(s => ([s, s])),
     description: t('The color scheme for rendering chart'),
-    schemes: () => getAllSchemes(),
+    schemes: () => categoricalSchemeRegistry.getMap(),
   },
 
   significance_level: {
diff --git a/superset/assets/src/modules/ColorSchemeManager.js b/superset/assets/src/modules/ColorSchemeManager.js
deleted file mode 100644
index 9d21d26..0000000
--- a/superset/assets/src/modules/ColorSchemeManager.js
+++ /dev/null
@@ -1,86 +0,0 @@
-class ColorSchemeManager {
-  constructor() {
-    this.schemes = {};
-    this.defaultSchemeName = undefined;
-  }
-
-  clearScheme() {
-    this.schemes = {};
-    return this;
-  }
-
-  getScheme(schemeName) {
-    return this.schemes[schemeName || this.defaultSchemeName];
-  }
-
-  getAllSchemes() {
-    return this.schemes;
-  }
-
-  getDefaultSchemeName() {
-    return this.defaultSchemeName;
-  }
-
-  setDefaultSchemeName(schemeName) {
-    this.defaultSchemeName = schemeName;
-    return this;
-  }
-
-  registerScheme(schemeName, colors) {
-    this.schemes[schemeName] = colors;
-    // If there is no default, set as default
-    if (!this.defaultSchemeName) {
-      this.defaultSchemeName = schemeName;
-    }
-    return this;
-  }
-
-  registerMultipleSchemes(multipleSchemes) {
-    Object.assign(this.schemes, multipleSchemes);
-    // If there is no default, set the first scheme as default
-    const keys = Object.keys(multipleSchemes);
-    if (!this.defaultSchemeName && keys.length > 0) {
-      this.defaultSchemeName = keys[0];
-    }
-    return this;
-  }
-}
-
-let singleton;
-
-export function getInstance() {
-  if (!singleton) {
-    singleton = new ColorSchemeManager();
-  }
-  return singleton;
-}
-
-const staticFunctions = Object.getOwnPropertyNames(ColorSchemeManager.prototype)
-  .filter(fn => fn !== 'constructor')
-  .reduce((all, fn) => {
-    const functions = all;
-    functions[fn] = function (...args) {
-      return getInstance()[fn](...args);
-    };
-    return functions;
-  }, { getInstance });
-
-const {
-  clearScheme,
-  getScheme,
-  getAllSchemes,
-  getDefaultSchemeName,
-  setDefaultSchemeName,
-  registerScheme,
-  registerMultipleSchemes,
-} = staticFunctions;
-
-export {
-  clearScheme,
-  getScheme,
-  getAllSchemes,
-  getDefaultSchemeName,
-  setDefaultSchemeName,
-  registerScheme,
-  registerMultipleSchemes,
-};
diff --git a/superset/assets/src/modules/Registry.js b/superset/assets/src/modules/Registry.js
index f39a0c5..3b9ef44 100644
--- a/superset/assets/src/modules/Registry.js
+++ b/superset/assets/src/modules/Registry.js
@@ -5,6 +5,12 @@ export default class Registry {
     this.promises = {};
   }
 
+  clear() {
+    this.items = {};
+    this.promises = {};
+    return this;
+  }
+
   has(key) {
     const item = this.items[key];
     return item !== null && item !== undefined;
@@ -44,10 +50,36 @@ export default class Registry {
     return Promise.reject(`Item with key "${key}" is not registered.`);
   }
 
+  getMap() {
+    return this.keys().reduce((prev, key) => {
+      const map = prev;
+      map[key] = this.get(key);
+      return map;
+    }, {});
+  }
+
+  getMapAsPromise() {
+    const keys = this.keys();
+    return Promise.all(keys.map(key => this.getAsPromise(key)))
+      .then(values => values.reduce((prev, value, i) => {
+        const map = prev;
+        map[keys[i]] = value;
+        return map;
+      }, {}));
+  }
+
   keys() {
     return Object.keys(this.items);
   }
 
+  values() {
+    return this.keys().map(key => this.get(key));
+  }
+
+  valuesAsPromise() {
+    return Promise.all(this.keys().map(key => this.getAsPromise(key)));
+  }
+
   entries() {
     return this.keys().map(key => ({
       key,
diff --git a/superset/assets/src/modules/colorSchemes/airbnb.js b/superset/assets/src/modules/colorSchemes/airbnb.js
deleted file mode 100644
index d26a923..0000000
--- a/superset/assets/src/modules/colorSchemes/airbnb.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export default {
-  bnbColors: [
-    '#ff5a5f', // rausch
-    '#7b0051', // hackb
-    '#007A87', // kazan
-    '#00d1c1', // babu
-    '#8ce071', // lima
-    '#ffb400', // beach
-    '#b4a76c', // barol
-    '#ff8083',
-    '#cc0086',
-    '#00a1b3',
-    '#00ffeb',
-    '#bbedab',
-    '#ffd266',
-    '#cbc29a',
-    '#ff3339',
-    '#ff1ab1',
-    '#005c66',
-    '#00b3a5',
-    '#55d12e',
-    '#b37e00',
-    '#988b4e',
-  ],
-};
diff --git a/superset/assets/src/modules/colorSchemes/categorical.js b/superset/assets/src/modules/colorSchemes/categorical.js
deleted file mode 100644
index 946d14a..0000000
--- a/superset/assets/src/modules/colorSchemes/categorical.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import d3 from 'd3';
-
-export default {
-  d3Category10: d3.scale.category10().range(),
-  d3Category20: d3.scale.category20().range(),
-  d3Category20b: d3.scale.category20b().range(),
-  d3Category20c: d3.scale.category20c().range(),
-  googleCategory10c: [
-    '#3366cc',
-    '#dc3912',
-    '#ff9900',
-    '#109618',
-    '#990099',
-    '#0099c6',
-    '#dd4477',
-    '#66aa00',
-    '#b82e2e',
-    '#316395',
-  ],
-  googleCategory20c: [
-    '#3366cc',
-    '#dc3912',
-    '#ff9900',
-    '#109618',
-    '#990099',
-    '#0099c6',
-    '#dd4477',
-    '#66aa00',
-    '#b82e2e',
-    '#316395',
-    '#994499',
-    '#22aa99',
-    '#aaaa11',
-    '#6633cc',
-    '#e67300',
-    '#8b0707',
-    '#651067',
-    '#329262',
-    '#5574a6',
-    '#3b3eac',
-  ],
-};
diff --git a/superset/assets/src/modules/colorSchemes/lyft.js b/superset/assets/src/modules/colorSchemes/lyft.js
deleted file mode 100644
index cd94121..0000000
--- a/superset/assets/src/modules/colorSchemes/lyft.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export default {
-  lyftColors: [
-    '#EA0B8C',
-    '#6C838E',
-    '#29ABE2',
-    '#33D9C1',
-    '#9DACB9',
-    '#7560AA',
-    '#2D5584',
-    '#831C4A',
-    '#333D47',
-    '#AC2077',
-  ],
-};
diff --git a/superset/assets/src/modules/colorSchemes/sequential.js b/superset/assets/src/modules/colorSchemes/sequential.js
deleted file mode 100644
index 6970ed4..0000000
--- a/superset/assets/src/modules/colorSchemes/sequential.js
+++ /dev/null
@@ -1,433 +0,0 @@
-export default {
-  blue_white_yellow: [
-    '#00d1c1',
-    'white',
-    '#ffb400',
-  ],
-  fire: [
-    'white',
-    'yellow',
-    'red',
-    'black',
-  ],
-  white_black: [
-    'white',
-    'black',
-  ],
-  black_white: [
-    'black',
-    'white',
-  ],
-  dark_blue: [
-    '#EBF5F8',
-    '#6BB1CC',
-    '#357E9B',
-    '#1B4150',
-    '#092935',
-  ],
-  pink_grey: [
-    '#E70B81',
-    '#FAFAFA',
-    '#666666',
-  ],
-  greens: [
-    '#ffffcc',
-    '#78c679',
-    '#006837',
-  ],
-  purples: [
-    '#f2f0f7',
-    '#9e9ac8',
-    '#54278f',
-  ],
-  oranges: [
-    '#fef0d9',
-    '#fc8d59',
-    '#b30000',
-  ],
-  red_yellow_blue: [
-    '#d7191c',
-    '#fdae61',
-    '#ffffbf',
-    '#abd9e9',
-    '#2c7bb6',
-  ],
-  brown_white_green: [
-    '#a6611a',
-    '#dfc27d',
-    '#f5f5f5',
-    '#80cdc1',
-    '#018571',
-  ],
-  purple_white_green: [
-    '#7b3294',
-    '#c2a5cf',
-    '#f7f7f7',
-    '#a6dba0',
-    '#008837',
-  ],
-  schemeBrBG: [
-    '#543005',
-    '#8c510a',
-    '#bf812d',
-    '#dfc27d',
-    '#f6e8c3',
-    '#c7eae5',
-    '#80cdc1',
-    '#35978f',
-    '#01665e',
-    '#003c30',
-  ],
-  schemePRGn: [
-    '#40004b',
-    '#762a83',
-    '#9970ab',
-    '#c2a5cf',
-    '#e7d4e8',
-    '#d9f0d3',
-    '#a6dba0',
-    '#5aae61',
-    '#1b7837',
-    '#00441b',
-  ],
-  schemePiYG: [
-    '#8e0152',
-    '#c51b7d',
-    '#de77ae',
-    '#f1b6da',
-    '#fde0ef',
-    '#e6f5d0',
-    '#b8e186',
-    '#7fbc41',
-    '#4d9221',
-    '#276419',
-  ],
-  schemePuOr: [
-    '#2d004b',
-    '#542788',
-    '#8073ac',
-    '#b2abd2',
-    '#d8daeb',
-    '#fee0b6',
-    '#fdb863',
-    '#e08214',
-    '#b35806',
-    '#7f3b08',
-  ],
-  schemeRdBu: [
-    '#67001f',
-    '#b2182b',
-    '#d6604d',
-    '#f4a582',
-    '#fddbc7',
-    '#d1e5f0',
-    '#92c5de',
-    '#4393c3',
-    '#2166ac',
-    '#053061',
-  ],
-  schemeRdGy: [
-    '#67001f',
-    '#b2182b',
-    '#d6604d',
-    '#f4a582',
-    '#fddbc7',
-    '#e0e0e0',
-    '#bababa',
-    '#878787',
-    '#4d4d4d',
-    '#1a1a1a',
-  ],
-  schemeRdYlBu: [
-    '#a50026',
-    '#d73027',
-    '#f46d43',
-    '#fdae61',
-    '#fee090',
-    '#e0f3f8',
-    '#abd9e9',
-    '#74add1',
-    '#4575b4',
-    '#313695',
-  ],
-  schemeRdYlGn: [
-    '#a50026',
-    '#d73027',
-    '#f46d43',
-    '#fdae61',
-    '#fee08b',
-    '#d9ef8b',
-    '#a6d96a',
-    '#66bd63',
-    '#1a9850',
-    '#006837',
-  ],
-  schemeSpectral: [
-    '#9e0142',
-    '#d53e4f',
-    '#f46d43',
-    '#fdae61',
-    '#fee08b',
-    '#e6f598',
-    '#abdda4',
-    '#66c2a5',
-    '#3288bd',
-    '#5e4fa2',
-  ],
-  schemeBlues: [
-    '#b5d4e9',
-    '#93c3df',
-    '#6daed5',
-    '#4b97c9',
-    '#2f7ebc',
-    '#1864aa',
-    '#0a4a90',
-    '#08306b',
-  ],
-  schemeGreens: [
-    '#b7e2b1',
-    '#97d494',
-    '#73c378',
-    '#4daf62',
-    '#2f984f',
-    '#157f3b',
-    '#036429',
-    '#00441b',
-  ],
-  schemeGrays: [
-    '#cecece',
-    '#b4b4b4',
-    '#979797',
-    '#7a7a7a',
-    '#5f5f5f',
-    '#404040',
-    '#1e1e1e',
-    '#000000',
-  ],
-  schemeOranges: [
-    '#fdc28c',
-    '#fda762',
-    '#fb8d3d',
-    '#f2701d',
-    '#e25609',
-    '#c44103',
-    '#9f3303',
-    '#7f2704',
-  ],
-  schemePurples: [
-    '#cecee5',
-    '#b6b5d8',
-    '#9e9bc9',
-    '#8782bc',
-    '#7363ac',
-    '#61409b',
-    '#501f8c',
-    '#3f007d',
-  ],
-  schemeReds: [
-    '#fcaa8e',
-    '#fc8a6b',
-    '#f9694c',
-    '#ef4533',
-    '#d92723',
-    '#bb151a',
-    '#970b13',
-    '#67000d',
-  ],
-  schemeViridis: [
-    '#482475',
-    '#414487',
-    '#355f8d',
-    '#2a788e',
-    '#21918c',
-    '#22a884',
-    '#44bf70',
-    '#7ad151',
-    '#bddf26',
-    '#fde725',
-  ],
-  schemeInferno: [
-    '#160b39',
-    '#420a68',
-    '#6a176e',
-    '#932667',
-    '#bc3754',
-    '#dd513a',
-    '#f37819',
-    '#fca50a',
-    '#f6d746',
-    '#fcffa4',
-  ],
-  schemeMagma: [
-    '#140e36',
-    '#3b0f70',
-    '#641a80',
-    '#8c2981',
-    '#b73779',
-    '#de4968',
-    '#f7705c',
-    '#fe9f6d',
-    '#fecf92',
-    '#fcfdbf',
-  ],
-  schemeWarm: [
-    '#963db3',
-    '#bf3caf',
-    '#e4419d',
-    '#fe4b83',
-    '#ff5e63',
-    '#ff7847',
-    '#fb9633',
-    '#e2b72f',
-    '#c6d63c',
-    '#aff05b',
-  ],
-  schemeCool: [
-    '#6054c8',
-    '#4c6edb',
-    '#368ce1',
-    '#23abd8',
-    '#1ac7c2',
-    '#1ddfa3',
-    '#30ef82',
-    '#52f667',
-    '#7ff658',
-    '#aff05b',
-  ],
-  schemeCubehelixDefault: [
-    '#1a1530',
-    '#163d4e',
-    '#1f6642',
-    '#54792f',
-    '#a07949',
-    '#d07e93',
-    '#cf9cda',
-    '#c1caf3',
-    '#d2eeef',
-    '#ffffff',
-  ],
-  schemeBuGn: [
-    '#b7e4da',
-    '#8fd3c1',
-    '#68c2a3',
-    '#49b17f',
-    '#2f9959',
-    '#157f3c',
-    '#036429',
-    '#00441b',
-  ],
-  schemeBuPu: [
-    '#b2cae1',
-    '#9cb3d5',
-    '#8f95c6',
-    '#8c74b5',
-    '#8952a5',
-    '#852d8f',
-    '#730f71',
-    '#4d004b',
-  ],
-  schemeGnBu: [
-    '#bde5bf',
-    '#9ed9bb',
-    '#7bcbc4',
-    '#58b7cd',
-    '#399cc6',
-    '#1d7eb7',
-    '#0b60a1',
-    '#084081',
-  ],
-  schemeOrRd: [
-    '#fdca94',
-    '#fdb07a',
-    '#fa8e5d',
-    '#f16c49',
-    '#e04530',
-    '#c81d13',
-    '#a70403',
-    '#7f0000',
-  ],
-  schemePuBuGn: [
-    '#bec9e2',
-    '#98b9d9',
-    '#69a8cf',
-    '#4096c0',
-    '#19879f',
-    '#037877',
-    '#016353',
-    '#014636',
-  ],
-  schemePuBu: [
-    '#bfc9e2',
-    '#9bb9d9',
-    '#72a8cf',
-    '#4394c3',
-    '#1a7db6',
-    '#0667a1',
-    '#045281',
-    '#023858',
-  ],
-  schemePuRd: [
-    '#d0aad2',
-    '#d08ac2',
-    '#dd63ae',
-    '#e33890',
-    '#d71c6c',
-    '#b70b4f',
-    '#8f023a',
-    '#67001f',
-  ],
-  schemeRdPu: [
-    '#fbb5bc',
-    '#f993b0',
-    '#f369a3',
-    '#e03e98',
-    '#c01788',
-    '#99037c',
-    '#700174',
-    '#49006a',
-  ],
-  schemeYlGnBu: [
-    '#d5eeb3',
-    '#a9ddb7',
-    '#73c9bd',
-    '#45b4c2',
-    '#2897bf',
-    '#2073b2',
-    '#234ea0',
-    '#1c3185',
-    '#081d58',
-  ],
-  schemeYlGn: [
-    '#e4f4ac',
-    '#c7e89b',
-    '#a2d88a',
-    '#78c578',
-    '#4eaf63',
-    '#2f944e',
-    '#15793f',
-    '#036034',
-    '#004529',
-  ],
-  schemeYlOrBr: [
-    '#feeaa1',
-    '#fed676',
-    '#feba4a',
-    '#fb992c',
-    '#ee7918',
-    '#d85b0a',
-    '#b74304',
-    '#8f3204',
-    '#662506',
-  ],
-  schemeYlOrRd: [
-    '#fee087',
-    '#fec965',
-    '#feab4b',
-    '#fd893c',
-    '#fa5c2e',
-    '#ec3023',
-    '#d31121',
-    '#af0225',
-    '#800026',
-  ],
-};
diff --git a/superset/assets/src/modules/colors.js b/superset/assets/src/modules/colors.js
index 8e86d46..19cd351 100644
--- a/superset/assets/src/modules/colors.js
+++ b/superset/assets/src/modules/colors.js
@@ -1,5 +1,5 @@
 import d3 from 'd3';
-import sequentialSchemes from './colorSchemes/sequential';
+import getSequentialSchemeRegistry from './colors/SequentialSchemeRegistrySingleton';
 
 export const BRAND_COLOR = '#00A699';
 export const PRIMARY_COLOR = { r: 0, g: 122, b: 135, a: 1 };
@@ -18,7 +18,7 @@ export const colorScalerFactory = function (colors, data, accessor, extents, out
   // Returns a linear scaler our of an array of color
   if (!Array.isArray(colors)) {
     /* eslint no-param-reassign: 0 */
-    colors = sequentialSchemes[colors];
+    colors = getSequentialSchemeRegistry().get(colors).colors;
   }
   let ext = [0, 1];
   if (extents) {
diff --git a/superset/assets/src/modules/CategoricalColorNamespace.js b/superset/assets/src/modules/colors/CategoricalColorNamespace.js
similarity index 85%
rename from superset/assets/src/modules/CategoricalColorNamespace.js
rename to superset/assets/src/modules/colors/CategoricalColorNamespace.js
index d022bb2..ea5ea93 100644
--- a/superset/assets/src/modules/CategoricalColorNamespace.js
+++ b/superset/assets/src/modules/colors/CategoricalColorNamespace.js
@@ -1,5 +1,5 @@
 import CategoricalColorScale from './CategoricalColorScale';
-import { getScheme, getDefaultSchemeName } from './ColorSchemeManager';
+import getCategoricalSchemeRegistry from './CategoricalSchemeRegistrySingleton';
 
 class CategoricalColorNamespace {
   constructor(name) {
@@ -9,13 +9,13 @@ class CategoricalColorNamespace {
   }
 
   getScale(schemeName) {
-    const name = schemeName || getDefaultSchemeName();
+    const name = schemeName || getCategoricalSchemeRegistry().getDefaultSchemeName();
     const scale = this.scales[name];
     if (scale) {
       return scale;
     }
     const newScale = new CategoricalColorScale(
-      getScheme(name),
+      getCategoricalSchemeRegistry().get(name).colors,
       this.forcedItems,
     );
     this.scales[name] = newScale;
diff --git a/superset/assets/src/modules/CategoricalColorScale.js b/superset/assets/src/modules/colors/CategoricalColorScale.js
similarity index 96%
rename from superset/assets/src/modules/CategoricalColorScale.js
rename to superset/assets/src/modules/colors/CategoricalColorScale.js
index eab70d2..69d8ab2 100644
--- a/superset/assets/src/modules/CategoricalColorScale.js
+++ b/superset/assets/src/modules/colors/CategoricalColorScale.js
@@ -1,4 +1,4 @@
-import { TIME_SHIFT_PATTERN } from '../utils/common';
+import { TIME_SHIFT_PATTERN } from '../../utils/common';
 
 export function cleanValue(value) {
   // for superset series that should have the same color
diff --git a/superset/assets/src/modules/colors/CategoricalScheme.js b/superset/assets/src/modules/colors/CategoricalScheme.js
new file mode 100644
index 0000000..c70ee58
--- /dev/null
+++ b/superset/assets/src/modules/colors/CategoricalScheme.js
@@ -0,0 +1,3 @@
+import ColorScheme from './ColorScheme';
+
+export default class CategoricalScheme extends ColorScheme {}
diff --git a/superset/assets/src/modules/colors/CategoricalSchemeRegistrySingleton.js b/superset/assets/src/modules/colors/CategoricalSchemeRegistrySingleton.js
new file mode 100644
index 0000000..5417180
--- /dev/null
+++ b/superset/assets/src/modules/colors/CategoricalSchemeRegistrySingleton.js
@@ -0,0 +1,8 @@
+import ColorSchemeRegistry from './ColorSchemeRegistry';
+import makeSingleton from '../../utils/makeSingleton';
+
+class CategoricalSchemeRegistry extends ColorSchemeRegistry {}
+
+const getInstance = makeSingleton(CategoricalSchemeRegistry);
+
+export default getInstance;
diff --git a/superset/assets/src/modules/colors/ColorScheme.js b/superset/assets/src/modules/colors/ColorScheme.js
new file mode 100644
index 0000000..91936a0
--- /dev/null
+++ b/superset/assets/src/modules/colors/ColorScheme.js
@@ -0,0 +1,15 @@
+import isRequired from '../../utils/isRequired';
+
+export default class ColorScheme {
+  constructor({
+    name = isRequired('name'),
+    label,
+    colors = isRequired('colors'),
+    description = '',
+  }) {
+    this.name = name;
+    this.label = label || name;
+    this.colors = colors;
+    this.description = description;
+  }
+}
diff --git a/superset/assets/src/modules/colors/ColorSchemeRegistry.js b/superset/assets/src/modules/colors/ColorSchemeRegistry.js
new file mode 100644
index 0000000..59d798d
--- /dev/null
+++ b/superset/assets/src/modules/colors/ColorSchemeRegistry.js
@@ -0,0 +1,36 @@
+import Registry from '../Registry';
+
+class ColorSchemeRegistry extends Registry {
+  getDefaultSchemeName() {
+    return this.defaultSchemeName;
+  }
+
+  setDefaultSchemeName(schemeName) {
+    this.defaultSchemeName = schemeName;
+    return this;
+  }
+
+  get(schemeName) {
+    return super.get(schemeName || this.defaultSchemeName);
+  }
+
+  registerValue(schemeName, colors) {
+    super.registerValue(schemeName, colors);
+    // If there is no default, set as default
+    if (!this.defaultSchemeName) {
+      this.defaultSchemeName = schemeName;
+    }
+    return this;
+  }
+
+  registerLoader(schemeName, loader) {
+    super.registerLoader(schemeName, loader);
+    // If there is no default, set as default
+    if (!this.defaultSchemeName) {
+      this.defaultSchemeName = schemeName;
+    }
+    return this;
+  }
+}
+
+export default ColorSchemeRegistry;
diff --git a/superset/assets/src/modules/colors/SequentialScheme.js b/superset/assets/src/modules/colors/SequentialScheme.js
new file mode 100644
index 0000000..27ad849
--- /dev/null
+++ b/superset/assets/src/modules/colors/SequentialScheme.js
@@ -0,0 +1,9 @@
+import ColorScheme from './ColorScheme';
+
+export default class SequentialScheme extends ColorScheme {
+  constructor(input) {
+    super(input);
+    const { isDiverging = false } = input;
+    this.isDiverging = isDiverging;
+  }
+}
diff --git a/superset/assets/src/modules/colors/SequentialSchemeRegistrySingleton.js b/superset/assets/src/modules/colors/SequentialSchemeRegistrySingleton.js
new file mode 100644
index 0000000..6ba5202
--- /dev/null
+++ b/superset/assets/src/modules/colors/SequentialSchemeRegistrySingleton.js
@@ -0,0 +1,8 @@
+import ColorSchemeRegistry from './ColorSchemeRegistry';
+import makeSingleton from '../../utils/makeSingleton';
+
+class SequentialSchemeRegistry extends ColorSchemeRegistry {}
+
+const getInstance = makeSingleton(SequentialSchemeRegistry);
+
+export default getInstance;
diff --git a/superset/assets/src/modules/colors/colorSchemes/categorical/airbnb.js b/superset/assets/src/modules/colors/colorSchemes/categorical/airbnb.js
new file mode 100644
index 0000000..2047624
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/categorical/airbnb.js
@@ -0,0 +1,32 @@
+import CategoricalScheme from '../../CategoricalScheme';
+
+const schemes = [
+  {
+    name: 'bnbColors',
+    colors: [
+      '#ff5a5f', // rausch
+      '#7b0051', // hackb
+      '#007A87', // kazan
+      '#00d1c1', // babu
+      '#8ce071', // lima
+      '#ffb400', // beach
+      '#b4a76c', // barol
+      '#ff8083',
+      '#cc0086',
+      '#00a1b3',
+      '#00ffeb',
+      '#bbedab',
+      '#ffd266',
+      '#cbc29a',
+      '#ff3339',
+      '#ff1ab1',
+      '#005c66',
+      '#00b3a5',
+      '#55d12e',
+      '#b37e00',
+      '#988b4e',
+    ],
+  },
+].map(s => new CategoricalScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/modules/colors/colorSchemes/categorical/d3.js b/superset/assets/src/modules/colors/colorSchemes/categorical/d3.js
new file mode 100644
index 0000000..deac97a
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/categorical/d3.js
@@ -0,0 +1,23 @@
+import d3 from 'd3';
+import CategoricalScheme from '../../CategoricalScheme';
+
+const schemes = [
+  {
+    name: 'd3Category10',
+    colors: d3.scale.category10().range(),
+  },
+  {
+    name: 'd3Category20',
+    colors: d3.scale.category20().range(),
+  },
+  {
+    name: 'd3Category20b',
+    colors: d3.scale.category20b().range(),
+  },
+  {
+    name: 'd3Category20c',
+    colors: d3.scale.category20c().range(),
+  },
+].map(s => new CategoricalScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/modules/colors/colorSchemes/categorical/google.js b/superset/assets/src/modules/colors/colorSchemes/categorical/google.js
new file mode 100644
index 0000000..b4195db
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/categorical/google.js
@@ -0,0 +1,46 @@
+import CategoricalScheme from '../../CategoricalScheme';
+
+const schemes = [
+  {
+    name: 'googleCategory10c',
+    colors: [
+      '#3366cc',
+      '#dc3912',
+      '#ff9900',
+      '#109618',
+      '#990099',
+      '#0099c6',
+      '#dd4477',
+      '#66aa00',
+      '#b82e2e',
+      '#316395',
+    ],
+  },
+  {
+    name: 'googleCategory20c',
+    colors: [
+      '#3366cc',
+      '#dc3912',
+      '#ff9900',
+      '#109618',
+      '#990099',
+      '#0099c6',
+      '#dd4477',
+      '#66aa00',
+      '#b82e2e',
+      '#316395',
+      '#994499',
+      '#22aa99',
+      '#aaaa11',
+      '#6633cc',
+      '#e67300',
+      '#8b0707',
+      '#651067',
+      '#329262',
+      '#5574a6',
+      '#3b3eac',
+    ],
+  },
+].map(s => new CategoricalScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/modules/colors/colorSchemes/categorical/lyft.js b/superset/assets/src/modules/colors/colorSchemes/categorical/lyft.js
new file mode 100644
index 0000000..cb81cbb
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/categorical/lyft.js
@@ -0,0 +1,21 @@
+import CategoricalScheme from '../../CategoricalScheme';
+
+const schemes = [
+  {
+    name: 'lyftColors',
+    colors: [
+      '#EA0B8C',
+      '#6C838E',
+      '#29ABE2',
+      '#33D9C1',
+      '#9DACB9',
+      '#7560AA',
+      '#2D5584',
+      '#831C4A',
+      '#333D47',
+      '#AC2077',
+    ],
+  },
+].map(s => new CategoricalScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/modules/colors/colorSchemes/sequential/common.js b/superset/assets/src/modules/colors/colorSchemes/sequential/common.js
new file mode 100644
index 0000000..b5c4a24
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/sequential/common.js
@@ -0,0 +1,121 @@
+import SequentialScheme from '../../SequentialScheme';
+
+const schemes = [
+  {
+    name: 'blue_white_yellow',
+    label: 'blue/white/yellow',
+    colors: [
+      '#00d1c1',
+      'white',
+      '#ffb400',
+    ],
+  },
+  {
+    name: 'fire',
+    colors: [
+      'white',
+      'yellow',
+      'red',
+      'black',
+    ],
+  },
+  {
+    name: 'white_black',
+    label: 'white/black',
+    colors: [
+      'white',
+      'black',
+    ],
+  },
+  {
+    name: 'black_white',
+    label: 'black/white',
+    colors: [
+      'black',
+      'white',
+    ],
+  },
+  {
+    name: 'dark_blue',
+    label: 'dark blues',
+    colors: [
+      '#EBF5F8',
+      '#6BB1CC',
+      '#357E9B',
+      '#1B4150',
+      '#092935',
+    ],
+  },
+  {
+    name: 'pink_grey',
+    label: 'pink/grey',
+    colors: [
+      '#E70B81',
+      '#FAFAFA',
+      '#666666',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'greens',
+    colors: [
+      '#ffffcc',
+      '#78c679',
+      '#006837',
+    ],
+  },
+  {
+    name: 'purples',
+    colors: [
+      '#f2f0f7',
+      '#9e9ac8',
+      '#54278f',
+    ],
+  },
+  {
+    name: 'oranges',
+    colors: [
+      '#fef0d9',
+      '#fc8d59',
+      '#b30000',
+    ],
+  },
+  {
+    name: 'red_yellow_blue',
+    label: 'red/yellow/blue',
+    colors: [
+      '#d7191c',
+      '#fdae61',
+      '#ffffbf',
+      '#abd9e9',
+      '#2c7bb6',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'brown_white_green',
+    label: 'brown/white/green',
+    colors: [
+      '#a6611a',
+      '#dfc27d',
+      '#f5f5f5',
+      '#80cdc1',
+      '#018571',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'purple_white_green',
+    label: 'purple/white/green',
+    colors: [
+      '#7b3294',
+      '#c2a5cf',
+      '#f7f7f7',
+      '#a6dba0',
+      '#008837',
+    ],
+    isDiverging: true,
+  },
+].map(s => new SequentialScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/modules/colors/colorSchemes/sequential/d3.js b/superset/assets/src/modules/colors/colorSchemes/sequential/d3.js
new file mode 100644
index 0000000..e811b63
--- /dev/null
+++ b/superset/assets/src/modules/colors/colorSchemes/sequential/d3.js
@@ -0,0 +1,510 @@
+import SequentialScheme from '../../SequentialScheme';
+
+const schemes = [
+  {
+    name: 'schemeBrBG',
+    label: 'brown/green',
+    colors: [
+      '#543005',
+      '#8c510a',
+      '#bf812d',
+      '#dfc27d',
+      '#f6e8c3',
+      '#c7eae5',
+      '#80cdc1',
+      '#35978f',
+      '#01665e',
+      '#003c30',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemePRGn',
+    label: 'purple/green',
+    colors: [
+      '#40004b',
+      '#762a83',
+      '#9970ab',
+      '#c2a5cf',
+      '#e7d4e8',
+      '#d9f0d3',
+      '#a6dba0',
+      '#5aae61',
+      '#1b7837',
+      '#00441b',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemePiYG',
+    label: 'pink/green',
+    colors: [
+      '#8e0152',
+      '#c51b7d',
+      '#de77ae',
+      '#f1b6da',
+      '#fde0ef',
+      '#e6f5d0',
+      '#b8e186',
+      '#7fbc41',
+      '#4d9221',
+      '#276419',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemePuOr',
+    label: 'purple/orange',
+    colors: [
+      '#2d004b',
+      '#542788',
+      '#8073ac',
+      '#b2abd2',
+      '#d8daeb',
+      '#fee0b6',
+      '#fdb863',
+      '#e08214',
+      '#b35806',
+      '#7f3b08',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemeRdBu',
+    label: 'red/blue',
+    colors: [
+      '#67001f',
+      '#b2182b',
+      '#d6604d',
+      '#f4a582',
+      '#fddbc7',
+      '#d1e5f0',
+      '#92c5de',
+      '#4393c3',
+      '#2166ac',
+      '#053061',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemeRdGy',
+    label: 'red/gray/black',
+    colors: [
+      '#67001f',
+      '#b2182b',
+      '#d6604d',
+      '#f4a582',
+      '#fddbc7',
+      '#e0e0e0',
+      '#bababa',
+      '#878787',
+      '#4d4d4d',
+      '#1a1a1a',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemeRdYlBu',
+    label: 'red/yellow/blue',
+    colors: [
+      '#a50026',
+      '#d73027',
+      '#f46d43',
+      '#fdae61',
+      '#fee090',
+      '#e0f3f8',
+      '#abd9e9',
+      '#74add1',
+      '#4575b4',
+      '#313695',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemeRdYlGn',
+    label: 'red/yellow/green',
+    colors: [
+      '#a50026',
+      '#d73027',
+      '#f46d43',
+      '#fdae61',
+      '#fee08b',
+      '#d9ef8b',
+      '#a6d96a',
+      '#66bd63',
+      '#1a9850',
+      '#006837',
+    ],
+    isDiverging: true,
+  },
+  {
+    name: 'schemeSpectral',
+    label: 'rainbow',
+    colors: [
+      '#9e0142',
+      '#d53e4f',
+      '#f46d43',
+      '#fdae61',
+      '#fee08b',
+      '#e6f598',
+      '#abdda4',
+      '#66c2a5',
+      '#3288bd',
+      '#5e4fa2',
+    ],
+  },
+  {
+    name: 'schemeBlues',
+    label: 'blues',
+    colors: [
+      '#b5d4e9',
+      '#93c3df',
+      '#6daed5',
+      '#4b97c9',
+      '#2f7ebc',
+      '#1864aa',
+      '#0a4a90',
+      '#08306b',
+    ],
+  },
+  {
+    name: 'schemeGreens',
+    label: 'greens',
+    colors: [
+      '#b7e2b1',
+      '#97d494',
+      '#73c378',
+      '#4daf62',
+      '#2f984f',
+      '#157f3b',
+      '#036429',
+      '#00441b',
+    ],
+  },
+  {
+    name: 'schemeGrays',
+    label: 'grays',
+    colors: [
+      '#cecece',
+      '#b4b4b4',
+      '#979797',
+      '#7a7a7a',
+      '#5f5f5f',
+      '#404040',
+      '#1e1e1e',
+      '#000000',
+    ],
+  },
+  {
+    name: 'schemeOranges',
+    label: 'oranges',
+    colors: [
+      '#fdc28c',
+      '#fda762',
+      '#fb8d3d',
+      '#f2701d',
+      '#e25609',
+      '#c44103',
+      '#9f3303',
+      '#7f2704',
+    ],
+  },
+  {
+    name: 'schemePurples',
+    label: 'purples',
+    colors: [
+      '#cecee5',
+      '#b6b5d8',
+      '#9e9bc9',
+      '#8782bc',
+      '#7363ac',
+      '#61409b',
+      '#501f8c',
+      '#3f007d',
+    ],
+  },
+  {
+    name: 'schemeReds',
+    label: 'reds',
+    colors: [
+      '#fcaa8e',
+      '#fc8a6b',
+      '#f9694c',
+      '#ef4533',
+      '#d92723',
+      '#bb151a',
+      '#970b13',
+      '#67000d',
+    ],
+  },
+  {
+    name: 'schemeViridis',
+    label: 'Viridis',
+    colors: [
+      '#482475',
+      '#414487',
+      '#355f8d',
+      '#2a788e',
+      '#21918c',
+      '#22a884',
+      '#44bf70',
+      '#7ad151',
+      '#bddf26',
+      '#fde725',
+    ],
+  },
+  {
+    name: 'schemeInferno',
+    label: 'Inferno',
+    colors: [
+      '#160b39',
+      '#420a68',
+      '#6a176e',
+      '#932667',
+      '#bc3754',
+      '#dd513a',
+      '#f37819',
+      '#fca50a',
+      '#f6d746',
+      '#fcffa4',
+    ],
+  },
+  {
+    name: 'schemeMagma',
+    label: 'Magma',
+    colors: [
+      '#140e36',
+      '#3b0f70',
+      '#641a80',
+      '#8c2981',
+      '#b73779',
+      '#de4968',
+      '#f7705c',
+      '#fe9f6d',
+      '#fecf92',
+      '#fcfdbf',
+    ],
+  },
+  {
+    name: 'schemeWarm',
+    label: 'Warm',
+    colors: [
+      '#963db3',
+      '#bf3caf',
+      '#e4419d',
+      '#fe4b83',
+      '#ff5e63',
+      '#ff7847',
+      '#fb9633',
+      '#e2b72f',
+      '#c6d63c',
+      '#aff05b',
+    ],
+  },
+  {
+    name: 'schemeCool',
+    label: 'Cool',
+    colors: [
+      '#6054c8',
+      '#4c6edb',
+      '#368ce1',
+      '#23abd8',
+      '#1ac7c2',
+      '#1ddfa3',
+      '#30ef82',
+      '#52f667',
+      '#7ff658',
+      '#aff05b',
+    ],
+  },
+  {
+    name: 'schemeCubehelixDefault',
+    label: 'Cube Helix',
+    colors: [
+      '#1a1530',
+      '#163d4e',
+      '#1f6642',
+      '#54792f',
+      '#a07949',
+      '#d07e93',
+      '#cf9cda',
+      '#c1caf3',
+      '#d2eeef',
+      '#ffffff',
+    ],
+  },
+  {
+    name: 'schemeBuGn',
+    label: 'blue/green',
+    colors: [
+      '#b7e4da',
+      '#8fd3c1',
+      '#68c2a3',
+      '#49b17f',
+      '#2f9959',
+      '#157f3c',
+      '#036429',
+      '#00441b',
+    ],
+  },
+  {
+    name: 'schemeBuPu',
+    label: 'blue/purple',
+    colors: [
+      '#b2cae1',
+      '#9cb3d5',
+      '#8f95c6',
+      '#8c74b5',
+      '#8952a5',
+      '#852d8f',
+      '#730f71',
+      '#4d004b',
+    ],
+  },
+  {
+    name: 'schemeGnBu',
+    label: 'green/blue',
+    colors: [
+      '#bde5bf',
+      '#9ed9bb',
+      '#7bcbc4',
+      '#58b7cd',
+      '#399cc6',
+      '#1d7eb7',
+      '#0b60a1',
+      '#084081',
+    ],
+  },
+  {
+    name: 'schemeOrRd',
+    label: 'orange/red',
+    colors: [
+      '#fdca94',
+      '#fdb07a',
+      '#fa8e5d',
+      '#f16c49',
+      '#e04530',
+      '#c81d13',
+      '#a70403',
+      '#7f0000',
+    ],
+  },
+  {
+    name: 'schemePuBuGn',
+    label: 'purple/blue/green',
+    colors: [
+      '#bec9e2',
+      '#98b9d9',
+      '#69a8cf',
+      '#4096c0',
+      '#19879f',
+      '#037877',
+      '#016353',
+      '#014636',
+    ],
+  },
+  {
+    name: 'schemePuBu',
+    label: 'purple/blue',
+    colors: [
+      '#bfc9e2',
+      '#9bb9d9',
+      '#72a8cf',
+      '#4394c3',
+      '#1a7db6',
+      '#0667a1',
+      '#045281',
+      '#023858',
+    ],
+  },
+  {
+    name: 'schemePuRd',
+    label: 'purple/red',
+    colors: [
+      '#d0aad2',
+      '#d08ac2',
+      '#dd63ae',
+      '#e33890',
+      '#d71c6c',
+      '#b70b4f',
+      '#8f023a',
+      '#67001f',
+    ],
+  },
+  {
+    name: 'schemeRdPu',
+    label: 'red/purple',
+    colors: [
+      '#fbb5bc',
+      '#f993b0',
+      '#f369a3',
+      '#e03e98',
+      '#c01788',
+      '#99037c',
+      '#700174',
+      '#49006a',
+    ],
+  },
+  {
+    name: 'schemeYlGnBu',
+    label: 'yellow/green/blue',
+    colors: [
+      '#d5eeb3',
+      '#a9ddb7',
+      '#73c9bd',
+      '#45b4c2',
+      '#2897bf',
+      '#2073b2',
+      '#234ea0',
+      '#1c3185',
+      '#081d58',
+    ],
+  },
+  {
+    name: 'schemeYlGn',
+    label: 'yellow/green',
+    colors: [
+      '#e4f4ac',
+      '#c7e89b',
+      '#a2d88a',
+      '#78c578',
+      '#4eaf63',
+      '#2f944e',
+      '#15793f',
+      '#036034',
+      '#004529',
+    ],
+  },
+  {
+    name: 'schemeYlOrBr',
+    label: 'yellow/orange/brown',
+    colors: [
+      '#feeaa1',
+      '#fed676',
+      '#feba4a',
+      '#fb992c',
+      '#ee7918',
+      '#d85b0a',
+      '#b74304',
+      '#8f3204',
+      '#662506',
+    ],
+  },
+  {
+    name: 'schemeYlOrRd',
+    label: 'yellow/orange/red',
+    colors: [
+      '#fee087',
+      '#fec965',
+      '#feab4b',
+      '#fd893c',
+      '#fa5c2e',
+      '#ec3023',
+      '#d31121',
+      '#af0225',
+      '#800026',
+    ],
+  },
+].map(s => new SequentialScheme(s));
+
+export default schemes;
diff --git a/superset/assets/src/setup/setupColors.js b/superset/assets/src/setup/setupColors.js
new file mode 100644
index 0000000..e51ea3d
--- /dev/null
+++ b/superset/assets/src/setup/setupColors.js
@@ -0,0 +1,26 @@
+import airbnb from '../modules/colors/colorSchemes/categorical/airbnb';
+import categoricalD3 from '../modules/colors/colorSchemes/categorical/d3';
+import google from '../modules/colors/colorSchemes/categorical/google';
+import lyft from '../modules/colors/colorSchemes/categorical/lyft';
+import sequentialCommon from '../modules/colors/colorSchemes/sequential/common';
+import sequentialD3 from '../modules/colors/colorSchemes/sequential/d3';
+import getCategoricalSchemeRegistry from '../modules/colors/CategoricalSchemeRegistrySingleton';
+import getSequentialSchemeRegistry from '../modules/colors/SequentialSchemeRegistrySingleton';
+
+export default function setupColors() {
+  // Register color schemes
+  const categoricalSchemeRegistry = getCategoricalSchemeRegistry();
+  [airbnb, categoricalD3, google, lyft].forEach((group) => {
+    group.forEach((scheme) => {
+      categoricalSchemeRegistry.registerValue(scheme.name, scheme);
+    });
+  });
+  categoricalSchemeRegistry.setDefaultSchemeName('bnbColors');
+
+  const sequentialSchemeRegistry = getSequentialSchemeRegistry();
+  [sequentialCommon, sequentialD3].forEach((group) => {
+    group.forEach((scheme) => {
+      sequentialSchemeRegistry.registerValue(scheme.name, scheme);
+    });
+  });
+}
diff --git a/superset/assets/src/visualizations/Chord/Chord.js b/superset/assets/src/visualizations/Chord/Chord.js
index cb5ae6d..e650262 100644
--- a/superset/assets/src/visualizations/Chord/Chord.js
+++ b/superset/assets/src/visualizations/Chord/Chord.js
@@ -1,7 +1,7 @@
 /* eslint-disable no-param-reassign */
 import d3 from 'd3';
 import PropTypes from 'prop-types';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import './Chord.css';
 
 const propTypes = {
diff --git a/superset/assets/src/visualizations/Histogram/Histogram.jsx b/superset/assets/src/visualizations/Histogram/Histogram.jsx
index 34540bb..0b896d7 100644
--- a/superset/assets/src/visualizations/Histogram/Histogram.jsx
+++ b/superset/assets/src/visualizations/Histogram/Histogram.jsx
@@ -5,7 +5,7 @@ import { chartTheme } from '@data-ui/theme';
 import { LegendOrdinal } from '@vx/legend';
 import { scaleOrdinal } from '@vx/scale';
 import WithLegend from '../WithLegend';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 
 const propTypes = {
   className: PropTypes.string,
diff --git a/superset/assets/src/visualizations/Partition/Partition.js b/superset/assets/src/visualizations/Partition/Partition.js
index 9093d55..03b4df0 100644
--- a/superset/assets/src/visualizations/Partition/Partition.js
+++ b/superset/assets/src/visualizations/Partition/Partition.js
@@ -2,7 +2,7 @@
 import d3 from 'd3';
 import PropTypes from 'prop-types';
 import { hierarchy } from 'd3-hierarchy';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import { d3TimeFormatPreset } from '../../modules/utils';
 import './Partition.css';
 
diff --git a/superset/assets/src/visualizations/Rose/Rose.js b/superset/assets/src/visualizations/Rose/Rose.js
index 3c76d8f..2d48c5b 100644
--- a/superset/assets/src/visualizations/Rose/Rose.js
+++ b/superset/assets/src/visualizations/Rose/Rose.js
@@ -2,7 +2,7 @@
 import d3 from 'd3';
 import PropTypes from 'prop-types';
 import nv from 'nvd3';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import { d3TimeFormatPreset } from '../../modules/utils';
 import './Rose.css';
 
diff --git a/superset/assets/src/visualizations/Sankey/Sankey.js b/superset/assets/src/visualizations/Sankey/Sankey.js
index 0efca77..405f1b5 100644
--- a/superset/assets/src/visualizations/Sankey/Sankey.js
+++ b/superset/assets/src/visualizations/Sankey/Sankey.js
@@ -2,7 +2,7 @@
 import d3 from 'd3';
 import PropTypes from 'prop-types';
 import { sankey as d3Sankey } from 'd3-sankey';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import './Sankey.css';
 
 const propTypes = {
diff --git a/superset/assets/src/visualizations/Sunburst/Sunburst.js b/superset/assets/src/visualizations/Sunburst/Sunburst.js
index f557d8d..3cd9512 100644
--- a/superset/assets/src/visualizations/Sunburst/Sunburst.js
+++ b/superset/assets/src/visualizations/Sunburst/Sunburst.js
@@ -1,7 +1,7 @@
 /* eslint-disable no-param-reassign */
 import d3 from 'd3';
 import PropTypes from 'prop-types';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import { wrapSvgText } from '../../modules/utils';
 import './Sunburst.css';
 
diff --git a/superset/assets/src/visualizations/Treemap/Treemap.js b/superset/assets/src/visualizations/Treemap/Treemap.js
index 3596357..0ceef27 100644
--- a/superset/assets/src/visualizations/Treemap/Treemap.js
+++ b/superset/assets/src/visualizations/Treemap/Treemap.js
@@ -1,7 +1,7 @@
 /* eslint-disable no-shadow, no-param-reassign */
 import d3 from 'd3';
 import PropTypes from 'prop-types';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import './Treemap.css';
 
 // Declare PropTypes for recursive data structures
diff --git a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
index dd42017..49e37af 100644
--- a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
@@ -2,11 +2,9 @@
 
 import React from 'react';
 import PropTypes from 'prop-types';
-
 import AnimatableDeckGLContainer from './AnimatableDeckGLContainer';
 import Legend from '../Legend';
-
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 import { hexToRGB } from '../../modules/colors';
 import { getPlaySliderParams } from '../../modules/time';
 import sandboxedEval from '../../modules/sandbox';
diff --git a/superset/assets/src/visualizations/nvd3/NVD3Vis.js b/superset/assets/src/visualizations/nvd3/NVD3Vis.js
index 5000731..9ffe468 100644
--- a/superset/assets/src/visualizations/nvd3/NVD3Vis.js
+++ b/superset/assets/src/visualizations/nvd3/NVD3Vis.js
@@ -8,7 +8,7 @@ import 'nvd3/build/nv.d3.min.css';
 
 import { t } from '../../locales';
 import AnnotationTypes, { applyNativeColumns } from '../../modules/AnnotationTypes';
-import { getScale, getColor } from '../../modules/CategoricalColorNamespace';
+import { getScale, getColor } from '../../modules/colors/CategoricalColorNamespace';
 import { formatDateVerbose } from '../../modules/dates';
 import { d3TimeFormatPreset, d3FormatPreset } from '../../modules/utils';
 import { isTruthy } from '../../utils/common';
diff --git a/superset/assets/src/visualizations/wordcloud/WordCloud.js b/superset/assets/src/visualizations/wordcloud/WordCloud.js
index 2b91665..a165b01 100644
--- a/superset/assets/src/visualizations/wordcloud/WordCloud.js
+++ b/superset/assets/src/visualizations/wordcloud/WordCloud.js
@@ -1,7 +1,7 @@
 import d3 from 'd3';
 import PropTypes from 'prop-types';
 import cloudLayout from 'd3-cloud';
-import { getScale } from '../../modules/CategoricalColorNamespace';
+import { getScale } from '../../modules/colors/CategoricalColorNamespace';
 
 const ROTATION = {
   square: () => Math.floor((Math.random() * 2)) * 90,


Mime
View raw message