diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx index 4e75ae882338..84bdee2a64bd 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx @@ -27,7 +27,6 @@ import { VECTOR_STYLES, STYLE_TYPE, } from '../../../../common/constants'; -// @ts-ignore import { COLOR_GRADIENTS } from '../../styles/color_utils'; export const clustersLayerWizardConfig: LayerWizard = { diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx index bda1a6650c48..8d7bf0d2af66 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx @@ -17,7 +17,6 @@ import { VECTOR_STYLES, STYLE_TYPE, } from '../../../../common/constants'; -// @ts-ignore import { COLOR_GRADIENTS } from '../../styles/color_utils'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; diff --git a/x-pack/plugins/maps/public/classes/styles/color_utils.test.js b/x-pack/plugins/maps/public/classes/styles/color_utils.test.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/styles/color_utils.test.js rename to x-pack/plugins/maps/public/classes/styles/color_utils.test.ts diff --git a/x-pack/plugins/maps/public/classes/styles/color_utils.js b/x-pack/plugins/maps/public/classes/styles/color_utils.tsx similarity index 53% rename from x-pack/plugins/maps/public/classes/styles/color_utils.js rename to x-pack/plugins/maps/public/classes/styles/color_utils.tsx index 9dc79c006dff..116e03096b0f 100644 --- a/x-pack/plugins/maps/public/classes/styles/color_utils.js +++ b/x-pack/plugins/maps/public/classes/styles/color_utils.tsx @@ -7,73 +7,85 @@ import React from 'react'; import tinycolor from 'tinycolor2'; import chroma from 'chroma-js'; +// @ts-ignore import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; import { ColorGradient } from './components/color_gradient'; -import { vislibColorMaps } from '../../../../../../src/plugins/charts/public'; +import { RawColorSchema, vislibColorMaps } from '../../../../../../src/plugins/charts/public'; export const GRADIENT_INTERVALS = 8; -export const DEFAULT_FILL_COLORS = euiPaletteColorBlind(); -export const DEFAULT_LINE_COLORS = [ - ...DEFAULT_FILL_COLORS.map((color) => tinycolor(color).darken().toHexString()), +export const DEFAULT_FILL_COLORS: string[] = euiPaletteColorBlind(); +export const DEFAULT_LINE_COLORS: string[] = [ + ...DEFAULT_FILL_COLORS.map((color: string) => tinycolor(color).darken().toHexString()), // Explicitly add black & white as border color options '#000', '#FFF', ]; -function getLegendColors(colorRamp, numLegendColors = 4) { +function getRGBColors(colorRamp: Array<[number, number[]]>, numLegendColors: number = 4): string[] { const colors = []; - colors[0] = getColor(colorRamp, 0); + colors[0] = getRGBColor(colorRamp, 0); for (let i = 1; i < numLegendColors - 1; i++) { - colors[i] = getColor(colorRamp, Math.floor((colorRamp.length * i) / numLegendColors)); + colors[i] = getRGBColor(colorRamp, Math.floor((colorRamp.length * i) / numLegendColors)); } - colors[numLegendColors - 1] = getColor(colorRamp, colorRamp.length - 1); + colors[numLegendColors - 1] = getRGBColor(colorRamp, colorRamp.length - 1); return colors; } -function getColor(colorRamp, i) { - const color = colorRamp[i][1]; - const red = Math.floor(color[0] * 255); - const green = Math.floor(color[1] * 255); - const blue = Math.floor(color[2] * 255); +function getRGBColor(colorRamp: Array<[number, number[]]>, i: number): string { + const rgbArray = colorRamp[i][1]; + const red = Math.floor(rgbArray[0] * 255); + const green = Math.floor(rgbArray[1] * 255); + const blue = Math.floor(rgbArray[2] * 255); return `rgb(${red},${green},${blue})`; } -function getColorRamp(colorRampName) { - const colorRamp = vislibColorMaps[colorRampName]; - if (!colorRamp) { +function getColorSchema(colorRampName: string): RawColorSchema { + const colorSchema = vislibColorMaps[colorRampName]; + if (!colorSchema) { throw new Error( `${colorRampName} not found. Expected one of following values: ${Object.keys( vislibColorMaps )}` ); } - return colorRamp; + return colorSchema; } -export function getRGBColorRangeStrings(colorRampName, numberColors = GRADIENT_INTERVALS) { - const colorRamp = getColorRamp(colorRampName); - return getLegendColors(colorRamp.value, numberColors); +export function getRGBColorRangeStrings( + colorRampName: string, + numberColors: number = GRADIENT_INTERVALS +): string[] { + const colorSchema = getColorSchema(colorRampName); + return getRGBColors(colorSchema.value, numberColors); } -export function getHexColorRangeStrings(colorRampName, numberColors = GRADIENT_INTERVALS) { +export function getHexColorRangeStrings( + colorRampName: string, + numberColors: number = GRADIENT_INTERVALS +): string[] { return getRGBColorRangeStrings(colorRampName, numberColors).map((rgbColor) => chroma(rgbColor).hex() ); } -export function getColorRampCenterColor(colorRampName) { +export function getColorRampCenterColor(colorRampName: string): string | null { if (!colorRampName) { return null; } - const colorRamp = getColorRamp(colorRampName); - const centerIndex = Math.floor(colorRamp.value.length / 2); - return getColor(colorRamp.value, centerIndex); + const colorSchema = getColorSchema(colorRampName); + const centerIndex = Math.floor(colorSchema.value.length / 2); + return getRGBColor(colorSchema.value, centerIndex); } // Returns an array of color stops // [ stop_input_1: number, stop_output_1: color, stop_input_n: number, stop_output_n: color ] -export function getOrdinalMbColorRampStops(colorRampName, min, max, numberColors) { +export function getOrdinalMbColorRampStops( + colorRampName: string, + min: number, + max: number, + numberColors: number +): Array | null { if (!colorRampName) { return null; } @@ -84,15 +96,18 @@ export function getOrdinalMbColorRampStops(colorRampName, min, max, numberColors const hexColors = getHexColorRangeStrings(colorRampName, numberColors); if (max === min) { - //just return single stop value + // just return single stop value return [max, hexColors[hexColors.length - 1]]; } const delta = max - min; - return hexColors.reduce((accu, stopColor, idx, srcArr) => { - const stopNumber = min + (delta * idx) / srcArr.length; - return [...accu, stopNumber, stopColor]; - }, []); + return hexColors.reduce( + (accu: Array, stopColor: string, idx: number, srcArr: string[]) => { + const stopNumber = min + (delta * idx) / srcArr.length; + return [...accu, stopNumber, stopColor]; + }, + [] + ); } export const COLOR_GRADIENTS = Object.keys(vislibColorMaps).map((colorRampName) => ({ @@ -102,7 +117,7 @@ export const COLOR_GRADIENTS = Object.keys(vislibColorMaps).map((colorRampName) export const COLOR_RAMP_NAMES = Object.keys(vislibColorMaps); -export function getLinearGradient(colorStrings) { +export function getLinearGradient(colorStrings: string[]): string { const intervals = colorStrings.length; let linearGradient = `linear-gradient(to right, ${colorStrings[0]} 0%,`; for (let i = 1; i < intervals - 1; i++) { @@ -112,7 +127,12 @@ export function getLinearGradient(colorStrings) { return `${linearGradient} ${colorStrings[colorStrings.length - 1]} 100%)`; } -const COLOR_PALETTES_CONFIGS = [ +export interface ColorPalette { + id: string; + colors: string[]; +} + +const COLOR_PALETTES_CONFIGS: ColorPalette[] = [ { id: 'palette_0', colors: euiPaletteColorBlind(), @@ -127,14 +147,14 @@ const COLOR_PALETTES_CONFIGS = [ }, ]; -export function getColorPalette(paletteId) { - const palette = COLOR_PALETTES_CONFIGS.find((palette) => palette.id === paletteId); +export function getColorPalette(paletteId: string): string[] | null { + const palette = COLOR_PALETTES_CONFIGS.find(({ id }: ColorPalette) => id === paletteId); return palette ? palette.colors : null; } export const COLOR_PALETTES = COLOR_PALETTES_CONFIGS.map((palette) => { const paletteDisplay = palette.colors.map((color) => { - const style = { + const style: React.CSSProperties = { backgroundColor: color, width: `${100 / palette.colors.length}%`, position: 'relative', diff --git a/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js b/x-pack/plugins/maps/public/classes/styles/components/color_gradient.tsx similarity index 72% rename from x-pack/plugins/maps/public/classes/styles/components/color_gradient.js rename to x-pack/plugins/maps/public/classes/styles/components/color_gradient.tsx index bf7e88df3a69..b29146062e46 100644 --- a/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js +++ b/x-pack/plugins/maps/public/classes/styles/components/color_gradient.tsx @@ -11,17 +11,20 @@ import { getRGBColorRangeStrings, getLinearGradient, } from '../color_utils'; -import classNames from 'classnames'; -export const ColorGradient = ({ colorRamp, colorRampName, className }) => { +interface Props { + colorRamp?: string[]; + colorRampName?: string; +} + +export const ColorGradient = ({ colorRamp, colorRampName }: Props) => { if (!colorRamp && (!colorRampName || !COLOR_RAMP_NAMES.includes(colorRampName))) { return null; } - const classes = classNames('mapColorGradient', className); const rgbColorStrings = colorRampName ? getRGBColorRangeStrings(colorRampName, GRADIENT_INTERVALS) - : colorRamp; + : colorRamp!; const background = getLinearGradient(rgbColorStrings); - return
; + return
; }; diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap b/x-pack/plugins/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap similarity index 100% rename from x-pack/plugins/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap rename to x-pack/plugins/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_constants.js b/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_constants.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_constants.js rename to x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_constants.ts diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.test.js b/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.test.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.test.js rename to x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.test.tsx diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.js b/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.tsx similarity index 85% rename from x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.js rename to x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.tsx index 6d38a7985269..d15fdbd79de7 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.js +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/components/heatmap_style_editor.tsx @@ -15,8 +15,13 @@ import { HEATMAP_COLOR_RAMP_LABEL, } from './heatmap_constants'; -export function HeatmapStyleEditor({ colorRampName, onHeatmapColorChange }) { - const onColorRampChange = (selectedColorRampName) => { +interface Props { + colorRampName: string; + onHeatmapColorChange: ({ colorRampName }: { colorRampName: string }) => void; +} + +export function HeatmapStyleEditor({ colorRampName, onHeatmapColorChange }: Props) { + const onColorRampChange = (selectedColorRampName: string) => { onHeatmapColorChange({ colorRampName: selectedColorRampName, }); diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js index 3b5bcf591c2a..5f920d0ba52d 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js @@ -91,6 +91,7 @@ export class HeatmapStyle extends AbstractStyle { MAX_RANGE, GRADIENT_INTERVALS ); + // TODO handle null mbMap.setPaintProperty(layerId, 'heatmap-color', [ 'interpolate', ['linear'], diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.ts index 71f77bc31319..dadb3f201fa3 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.ts @@ -43,7 +43,7 @@ export function extractColorFromStyleProperty( } const palette = getColorPalette(dynamicOptions.colorCategory); - return palette[0]; + return palette ? palette[0] : defaultColor; } else { // return middle of gradient for dynamic style property if (dynamicOptions.useCustomColorRamp) { @@ -58,6 +58,7 @@ export function extractColorFromStyleProperty( if (!dynamicOptions.color) { return defaultColor; } - return getColorRampCenterColor(dynamicOptions.color); + const centerColor = getColorRampCenterColor(dynamicOptions.color); + return centerColor ? centerColor : defaultColor; } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.test.ts b/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.test.ts new file mode 100644 index 000000000000..bc032639dd07 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../../../kibana_services', () => { + const mockUiSettings = { + get: () => { + return undefined; + }, + }; + return { + getUiSettings: () => { + return mockUiSettings; + }, + }; +}); + +import { VECTOR_STYLES } from '../../../../common/constants'; +import { getDefaultStaticProperties } from './vector_style_defaults'; + +describe('getDefaultStaticProperties', () => { + test('Should use first color in DEFAULT_*_COLORS when no colors are used on the map', () => { + const styleProperties = getDefaultStaticProperties([]); + expect(styleProperties[VECTOR_STYLES.FILL_COLOR]!.options.color).toBe('#54B399'); + expect(styleProperties[VECTOR_STYLES.LINE_COLOR]!.options.color).toBe('#41937c'); + }); + + test('Should next color in DEFAULT_*_COLORS when colors are used on the map', () => { + const styleProperties = getDefaultStaticProperties(['#54B399']); + expect(styleProperties[VECTOR_STYLES.FILL_COLOR]!.options.color).toBe('#6092C0'); + expect(styleProperties[VECTOR_STYLES.LINE_COLOR]!.options.color).toBe('#4379aa'); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.ts b/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.ts index 86602381cf61..a6878a0d760c 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style_defaults.ts @@ -16,7 +16,6 @@ import { COLOR_PALETTES, DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS, - // @ts-ignore } from '../color_utils'; import { VectorStylePropertiesDescriptor } from '../../../../common/descriptor_types'; // @ts-ignore @@ -58,9 +57,13 @@ export function getDefaultProperties(mapColors: string[] = []): VectorStylePrope export function getDefaultStaticProperties( mapColors: string[] = [] ): VectorStylePropertiesDescriptor { - // Colors must be state-aware to reduce unnecessary incrementation - const lastColor = mapColors.pop(); - const nextColorIndex = (DEFAULT_FILL_COLORS.indexOf(lastColor) + 1) % DEFAULT_FILL_COLORS.length; + let nextColorIndex = 0; + if (mapColors.length) { + const lastColor = mapColors[mapColors.length - 1]; + if (DEFAULT_FILL_COLORS.includes(lastColor)) { + nextColorIndex = (DEFAULT_FILL_COLORS.indexOf(lastColor) + 1) % DEFAULT_FILL_COLORS.length; + } + } const nextFillColor = DEFAULT_FILL_COLORS[nextColorIndex]; const nextLineColor = DEFAULT_LINE_COLORS[nextColorIndex];