diff --git a/packages/base/src/dialogs/symbology/colorRampUtils.ts b/packages/base/src/dialogs/symbology/colorRampUtils.ts index 19b95908e..43e381ae3 100644 --- a/packages/base/src/dialogs/symbology/colorRampUtils.ts +++ b/packages/base/src/dialogs/symbology/colorRampUtils.ts @@ -15,7 +15,7 @@ Object.assign(colorScale, cmocean); export const COLOR_RAMP_NAMES = [ 'jet', - // 'hsv', 11 steps min + 'hsv', 'hot', 'cool', 'spring', @@ -30,7 +30,7 @@ export const COLOR_RAMP_NAMES = [ 'YiOrRd', 'bluered', 'RdBu', - // 'picnic', 11 steps min + 'picnic', 'rainbow', 'portland', 'blackbody', @@ -41,7 +41,7 @@ export const COLOR_RAMP_NAMES = [ 'magma', 'plasma', 'warm', - // 'rainbow-soft', 11 steps min + 'rainbow-soft', 'bathymetry', 'cdom', 'chlorophyll', @@ -56,7 +56,7 @@ export const COLOR_RAMP_NAMES = [ 'turbidity', 'velocity-blue', 'velocity-green', - // 'cubehelix' 16 steps min + 'cubehelix', 'ice', 'oxy', 'matter', @@ -71,6 +71,13 @@ export const COLOR_RAMP_NAMES = [ 'tarn', ] as const; +export const COLOR_RAMP_DEFAULTS: Partial> = { + hsv: 11, + picnic: 11, + 'rainbow-soft': 11, + cubehelix: 16, +} as const; + export type ColorRampName = (typeof COLOR_RAMP_NAMES)[number]; export const getColorMapList = (): IColorMap[] => { diff --git a/packages/base/src/dialogs/symbology/components/color_ramp/ColorRamp.tsx b/packages/base/src/dialogs/symbology/components/color_ramp/ColorRamp.tsx index 70af1d808..008bec47b 100644 --- a/packages/base/src/dialogs/symbology/components/color_ramp/ColorRamp.tsx +++ b/packages/base/src/dialogs/symbology/components/color_ramp/ColorRamp.tsx @@ -5,6 +5,7 @@ import React, { useEffect, useState } from 'react'; import { LoadingIcon } from '@/src/shared/components/loading'; import CanvasSelectComponent from './CanvasSelectComponent'; import ModeSelectRow from './ModeSelectRow'; +import { COLOR_RAMP_DEFAULTS, ColorRampName } from '../../colorRampUtils'; interface IColorRampProps { modeOptions: string[]; @@ -36,6 +37,7 @@ const ColorRamp: React.FC = ({ const [selectedMode, setSelectedMode] = useState(''); const [numberOfShades, setNumberOfShades] = useState(''); const [isLoading, setIsLoading] = useState(false); + const [warning, setWarning] = useState(null); useEffect(() => { if (selectedRamp === '' && selectedMode === '' && numberOfShades === '') { @@ -43,6 +45,38 @@ const ColorRamp: React.FC = ({ } }, [layerParams]); + useEffect(() => { + if (!selectedRamp) { + return; + } + + const defaultClasses = + COLOR_RAMP_DEFAULTS[selectedRamp as ColorRampName] ?? 9; + + setNumberOfShades(defaultClasses.toString()); + setWarning(null); + }, [selectedRamp]); + + useEffect(() => { + if (!selectedRamp || !numberOfShades) { + return; + } + + const minRequired = COLOR_RAMP_DEFAULTS[selectedRamp as ColorRampName]; + const shades = parseInt(numberOfShades, 10); + const rampLabel = selectedRamp + .split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join('-'); + + if (minRequired && shades < minRequired) { + setWarning( + `${rampLabel} requires at least ${minRequired} classes (got ${shades})`, + ); + } else { + setWarning(null); + } + }, [selectedRamp, numberOfShades]); const populateOptions = () => { let nClasses, singleBandMode, colorRamp; @@ -51,9 +85,13 @@ const ColorRamp: React.FC = ({ singleBandMode = layerParams.symbologyState.mode; colorRamp = layerParams.symbologyState.colorRamp; } - setNumberOfShades(nClasses ? nClasses : '9'); + const defaultRamp = colorRamp ? colorRamp : 'viridis'; + const defaultClasses = + nClasses ?? COLOR_RAMP_DEFAULTS[defaultRamp as ColorRampName] ?? 9; + + setNumberOfShades(defaultClasses.toString()); setSelectedMode(singleBandMode ? singleBandMode : 'equal interval'); - setSelectedRamp(colorRamp ? colorRamp : 'viridis'); + setSelectedRamp(defaultRamp); }; return ( @@ -76,11 +114,20 @@ const ColorRamp: React.FC = ({ setSelectedMode={setSelectedMode} /> )} + {warning && ( +
+ {warning} +
+ )} {isLoading ? ( ) : (