diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/package.json b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/package.json index e7755bd671e8e..9ca10c56f2f02 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/package.json +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/package.json @@ -26,6 +26,7 @@ "access": "public" }, "dependencies": { - "@superset-ui/core": "^0.3.0" + "@superset-ui/core": "^0.3.0", + "d3-scale": "^2.1.2" } } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/SequentialScheme.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/SequentialScheme.js index 27ad849ec0798..69404cd05a350 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/SequentialScheme.js +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/SequentialScheme.js @@ -1,9 +1,38 @@ +import { scaleLinear } from 'd3-scale'; import ColorScheme from './ColorScheme'; +function range(count) { + return [...Array(count).keys()]; +} + export default class SequentialScheme extends ColorScheme { constructor(input) { super(input); const { isDiverging = false } = input; this.isDiverging = isDiverging; } + + createLinearScale(extent = [0, 1]) { + // Create matching domain + // because D3 continuous scale uses piecewise mapping + // between domain and range. + const valueScale = scaleLinear().range(extent); + const denominator = this.colors.length - 1; + const domain = range(this.colors.length).map(i => valueScale(i / denominator)); + + return scaleLinear() + .domain(domain) + .range(this.colors) + .clamp(true); + } + + getColors(numColors = this.colors.length) { + if (numColors === this.colors.length) { + return this.colors; + } + const colorScale = this.createLinearScale(); + const denominator = numColors - 1; + + return range(numColors).map(i => colorScale(i / denominator)); + } } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/index.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/index.js index 5db1ee840e125..d778fa1510ac3 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/index.js +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/src/index.js @@ -6,3 +6,5 @@ export { default as CategoricalScheme } from './CategoricalScheme'; export { default as getCategoricalSchemeRegistry } from './CategoricalSchemeRegistrySingleton'; export { default as getSequentialSchemeRegistry } from './SequentialSchemeRegistrySingleton'; export { default as SequentialScheme } from './SequentialScheme'; + +export const BRAND_COLOR = '#00A699'; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/SequentialScheme.test.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/SequentialScheme.test.js new file mode 100644 index 0000000000000..dc7bfdb991e22 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/SequentialScheme.test.js @@ -0,0 +1,57 @@ +import SequentialScheme from '../src/SequentialScheme'; + +describe('SequentialScheme', () => { + const scheme = new SequentialScheme({ + name: 'white to black', + colors: ['#fff', '#000'], + }); + it('exists', () => { + expect(SequentialScheme).toBeDefined(); + }); + describe('new SequentialScheme()', () => { + it('creates new instance', () => { + const scheme2 = new SequentialScheme({ + name: 'white to black', + colors: ['#fff', '#000'], + }); + expect(scheme2).toBeInstanceOf(SequentialScheme); + }); + }); + describe('.createLinearScale(extent)', () => { + it('returns a linear scale for the given extent', () => { + const scale = scheme.createLinearScale([10, 100]); + expect(scale(1)).toEqual('rgb(255, 255, 255)'); + expect(scale(10)).toEqual('rgb(255, 255, 255)'); + expect(scale(55)).toEqual('rgb(128, 128, 128)'); + expect(scale(100)).toEqual('rgb(0, 0, 0)'); + expect(scale(1000)).toEqual('rgb(0, 0, 0)'); + }); + it('uses [0, 1] as extent if not specified', () => { + const scale = scheme.createLinearScale(); + expect(scale(-1)).toEqual('rgb(255, 255, 255)'); + expect(scale(0)).toEqual('rgb(255, 255, 255)'); + expect(scale(0.5)).toEqual('rgb(128, 128, 128)'); + expect(scale(1)).toEqual('rgb(0, 0, 0)'); + expect(scale(2)).toEqual('rgb(0, 0, 0)'); + }); + }); + describe('.getColors(numColors)', () => { + it('returns the original colors if numColors is not specified', () => { + expect(scheme.getColors()).toEqual(['#fff', '#000']); + }); + it('returns the exact number of colors if numColors is specified', () => { + expect(scheme.getColors(2)).toEqual(['#fff', '#000']); + expect(scheme.getColors(3)).toEqual([ + 'rgb(255, 255, 255)', + 'rgb(128, 128, 128)', + 'rgb(0, 0, 0)', + ]); + expect(scheme.getColors(4)).toEqual([ + 'rgb(255, 255, 255)', + 'rgb(170, 170, 170)', + 'rgb(85, 85, 85)', + 'rgb(0, 0, 0)', + ]); + }); + }); +}); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/index.test.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/index.test.js index e1b0dd725f67e..542c469a60d29 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/index.test.js +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-color/test/index.test.js @@ -1,4 +1,5 @@ import { + BRAND_COLOR, CategoricalColorNamespace, CategoricalColorScale, CategoricalScheme, @@ -10,6 +11,7 @@ import { describe('index', () => { it('exports modules', () => { [ + BRAND_COLOR, CategoricalColorNamespace, CategoricalColorScale, CategoricalScheme,