Use render props pattern in color picker

This commit is contained in:
Andrej Ocenas 2019-03-12 22:37:55 +01:00
parent 4a2905de97
commit 96285c4f56
5 changed files with 32 additions and 14 deletions

View File

@ -50,7 +50,16 @@ ColorPickerStories.add('Series color picker', () => {
color={selectedColor}
onChange={color => updateSelectedColor(color)}
>
<div style={{ color: selectedColor, cursor: 'pointer' }}>Open color picker</div>
{({ ref, showColorPicker, hideColorPicker }) => (
<div
ref={ref}
onMouseLeave={hideColorPicker}
onClick={showColorPicker}
style={{ color: selectedColor, cursor: 'pointer' }}
>
Open color picker
</div>
)}
</SeriesColorPicker>
);
}}

View File

@ -1,4 +1,5 @@
import React, { Component, createRef } from 'react';
import { omit } from 'lodash';
import { PopperController } from '../Tooltip/PopperController';
import { Popper } from '../Tooltip/Popper';
import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover';
@ -8,13 +9,19 @@ import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
import { withTheme } from '../../themes/ThemeContext';
import { ColorPickerTrigger } from './ColorPickerTrigger';
type ColorPickerTriggerRenderer = (props: {
ref: React.RefObject<any>;
showColorPicker: () => void;
hideColorPicker: () => void;
}) => React.ReactNode;
export const colorPickerFactory = <T extends ColorPickerProps>(
popover: React.ComponentType<T>,
displayName = 'ColorPicker'
) => {
return class ColorPicker extends Component<T, any> {
return class ColorPicker extends Component<T & { children?: ColorPickerTriggerRenderer }, any> {
static displayName = displayName;
pickerTriggerRef = createRef<HTMLDivElement>();
pickerTriggerRef = createRef<any>();
onColorChange = (color: string) => {
const { onColorChange, onChange } = this.props;
@ -24,11 +31,11 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
};
render() {
const { theme, children } = this.props;
const popoverElement = React.createElement(popover, {
...this.props,
...omit(this.props, 'children'),
onChange: this.onColorChange,
});
const { theme, children } = this.props;
return (
<PopperController content={popoverElement} hideAfter={300}>
@ -46,10 +53,10 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
)}
{children ? (
React.cloneElement(children as JSX.Element, {
(children as ColorPickerTriggerRenderer)({
ref: this.pickerTriggerRef,
onClick: showPopper,
onMouseLeave: hidePopper,
showColorPicker: showPopper,
hideColorPicker: hidePopper,
})
) : (
<ColorPickerTrigger

View File

@ -17,8 +17,8 @@ export interface ColorPickerProps extends Themeable {
*/
onColorChange?: ColorPickerChangeHandler;
enableNamedColors?: boolean;
children?: JSX.Element;
}
export interface Props<T> extends ColorPickerProps, PopperContentProps {
customPickers?: T;
}

View File

@ -1,4 +1,4 @@
import React, { forwardRef, Ref } from 'react';
import React, { forwardRef } from 'react';
interface ColorPickerTriggerProps {
onClick: () => void;
@ -8,7 +8,7 @@ interface ColorPickerTriggerProps {
export const ColorPickerTrigger = forwardRef(function ColorPickerTrigger(
props: ColorPickerTriggerProps,
ref: Ref<HTMLDivElement>
ref: React.Ref<HTMLDivElement>
) {
return (
<div

View File

@ -174,9 +174,11 @@ class LegendSeriesIcon extends PureComponent<LegendSeriesIconProps, LegendSeries
onToggleAxis={this.props.onToggleAxis}
enableNamedColors
>
<span className="graph-legend-icon">
<SeriesIcon color={this.props.color} />
</span>
{({ ref, showColorPicker, hideColorPicker }) => (
<span ref={ref} onClick={showColorPicker} onMouseLeave={hideColorPicker} className="graph-legend-icon">
<SeriesIcon color={this.props.color} />
</span>
)}
</SeriesColorPicker>
);
}