diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx index 2f088b32327..51abd5e9d58 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx @@ -9,15 +9,10 @@ import propDeprecationWarning from '../../utils/propDeprecationWarning'; type ColorPickerChangeHandler = (color: string) => void; -export const handleColorPickerPropsDeprecation = (componentName: string, props: ColorPickerProps) => { - const { onColorChange } = props; - if (onColorChange) { - propDeprecationWarning(componentName, 'onColorChange', 'onChange'); - } -}; export interface ColorPickerProps extends Themeable { color: string; onChange: ColorPickerChangeHandler; + /** * @deprecated Use onChange instead */ @@ -27,6 +22,13 @@ export interface ColorPickerProps extends Themeable { children?: JSX.Element; } +export const handleColorPickerPropsDeprecation = (componentName: string, props: ColorPickerProps) => { + const { onColorChange } = props; + if (onColorChange) { + propDeprecationWarning(componentName, 'onColorChange', 'onChange'); + } +}; + export const colorPickerFactory = ( popover: React.ComponentType, displayName = 'ColorPicker', diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx index 396488c8cad..03b6086b8dc 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx @@ -2,20 +2,28 @@ import React from 'react'; import { NamedColorsPalette } from './NamedColorsPalette'; import { getColorName, getColorFromHexRgbOrName } from '../../utils/namedColorsPalette'; import { ColorPickerProps, handleColorPickerPropsDeprecation } from './ColorPicker'; -import { GrafanaTheme, Themeable } from '../../types'; +import { GrafanaTheme } from '../../types'; import { PopperContentProps } from '../Tooltip/PopperController'; import SpectrumPalette from './SpectrumPalette'; -export interface Props extends ColorPickerProps, Themeable, PopperContentProps {} +export interface Props extends ColorPickerProps, PopperContentProps { + customPickers?: T; +} type PickerType = 'palette' | 'spectrum'; -interface State { - activePicker: PickerType; +interface CustomPickersDescriptor { + [key: string]: { + tabComponent: React.ComponentType; + name: string; + }; +} +interface State { + activePicker: PickerType | keyof T; } -export class ColorPickerPopover extends React.Component { - constructor(props: Props) { +export class ColorPickerPopover extends React.Component, State> { + constructor(props: Props) { super(props); this.state = { activePicker: 'palette', @@ -23,6 +31,11 @@ export class ColorPickerPopover extends React.Component { handleColorPickerPropsDeprecation('ColorPickerPopover', props); } + getTabClassName = (tabName: PickerType | keyof T) => { + const { activePicker } = this.state; + return `ColorPickerPopover__tab ${activePicker === tabName && 'ColorPickerPopover__tab--active'}`; + }; + handleChange = (color: any) => { const { onColorChange, onChange, enableNamedColors } = this.props; const changeHandler = onColorChange || onChange; @@ -33,55 +46,89 @@ export class ColorPickerPopover extends React.Component { changeHandler(getColorFromHexRgbOrName(color)); }; + handleTabChange = (tab: PickerType | keyof T, updatePopperPosition?: () => void) => { + return () => + this.setState({ activePicker: tab }, () => { + if (updatePopperPosition) { + updatePopperPosition(); + } + }); + }; + renderPicker = () => { const { activePicker } = this.state; const { color, theme } = this.props; - return activePicker === 'spectrum' ? ( - - ) : ( - + switch (activePicker) { + case 'spectrum': + return ; + case 'palette': + return ; + default: + return this.renderCustomPicker(activePicker); + } + }; + + renderCustomPicker = (tabKey: keyof T) => { + const { customPickers, color, theme } = this.props; + if (!customPickers) { + return null; + } + + return React.createElement(customPickers[tabKey].tabComponent, { + color, + theme, + onChange: this.handleChange, + }); + }; + + renderCustomPickerTabs = (updatePopperPosition?: () => void) => { + const { customPickers } = this.props; + + if (!customPickers) { + return null; + } + + return ( + <> + {Object.keys(customPickers).map(key => { + return ( +
+ {customPickers[key].name} +
+ ); + })} + ); }; render() { - const { activePicker } = this.state; - const { theme, children, updatePopperPosition } = this.props; + const { theme, updatePopperPosition } = this.props; const colorPickerTheme = theme || GrafanaTheme.Dark; return (
{ - this.setState({ activePicker: 'palette' }, () => { - if (updatePopperPosition) { - updatePopperPosition(); - } - }); - }} + className={this.getTabClassName('palette')} + onClick={this.handleTabChange('palette', updatePopperPosition)} > - Default + Colors
{ - this.setState({ activePicker: 'spectrum' }, () => { - if (updatePopperPosition) { - updatePopperPosition(); - } - }); - }} + className={this.getTabClassName('spectrum')} + onClick={this.handleTabChange('spectrum', updatePopperPosition)} > Custom
+ {this.renderCustomPickerTabs(updatePopperPosition)}
-
- {this.renderPicker()} - {children} -
+
{this.renderPicker()}
); } diff --git a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx index 559b3f4a550..0bc89c893cd 100644 --- a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx @@ -13,9 +13,16 @@ export const SeriesColorPickerPopover: FunctionComponent -
{yaxis && }
- +
{yaxis && }
+ }, + }} + /> ); };