Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

components: Add deprecated props adapter for ColorPicker #34014

Merged
merged 6 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/components/src/ui/color-picker/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { useControlledValue } from '../../utils/hooks';

import type { ColorType } from './types';

interface ColorPickerProps {
export interface ColorPickerProps {
enableAlpha?: boolean;
color?: ColorFormats.HSL | ColorFormats.HSLA;
onChange?: ( color: ColorFormats.HSL | ColorFormats.HSLA ) => void;
Expand Down Expand Up @@ -62,6 +62,7 @@ const ColorPicker = (
onChange,
defaultValue,
copyFormat,
...divProps
} = useContextSystem( props, 'ColorPicker' );

const [ color, setColor ] = useControlledValue( {
Expand All @@ -88,7 +89,7 @@ const ColorPicker = (
);

return (
<ColorfulWrapper ref={ forwardedRef }>
<ColorfulWrapper ref={ forwardedRef } { ...divProps }>
sarayourfriend marked this conversation as resolved.
Show resolved Hide resolved
<Picker
onChange={ handleChange }
color={ safeColor }
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/ui/color-picker/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as ColorPicker } from './component';
export { LegacyAdapter as ColorPicker } from './legacy-adapter';
11 changes: 11 additions & 0 deletions packages/components/src/ui/color-picker/legacy-adapter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Internal dependencies
*/
import ColorPicker from './component';
import { useDeprecatedProps } from './use-deprecated-props';

type LegacyAdapterProps = Parameters< typeof useDeprecatedProps >[ 0 ];

export const LegacyAdapter = ( props: LegacyAdapterProps ) => {
return <ColorPicker { ...useDeprecatedProps( props ) } />;
};
20 changes: 20 additions & 0 deletions packages/components/src/ui/color-picker/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,23 @@ const Example = () => {
export const _default = () => {
return <Example />;
};

const LegacyExample = () => {
const [ legacyColor, setLegacyColor ] = useState( '#fff' );
const legacyProps = {
color: legacyColor,
onChangeComplete: setLegacyColor,
disableAlpha: boolean( 'disableAlpha', true ),
};

return (
<Flex align="flex-start" justify="flex-start">
<ColorPicker { ...legacyProps } />
<pre style={ { width: '20em' } }>
{ JSON.stringify( legacyColor, undefined, 4 ) }
</pre>
</Flex>
);
};

export const legacy = () => <LegacyExample />;
161 changes: 161 additions & 0 deletions packages/components/src/ui/color-picker/use-deprecated-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* External dependencies
*/
import colorize, { ColorFormats } from 'tinycolor2';
// eslint-disable-next-line no-restricted-imports
import type { ComponentProps } from 'react';
import memoize from 'memize';

/**
* WordPress dependencies
*/
import { useCallback, useMemo } from '@wordpress/element';

/**
* Internal dependencies
*/
import type ColorPicker from './component';

type ColorPickerProps = ComponentProps< typeof ColorPicker >;

/**
* @deprecated
*/
type LegacyColor =
| string
| {
hex: string;
hsl: ColorFormats.HSL | ColorFormats.HSLA;
hsv: ColorFormats.HSV | ColorFormats.HSVA;
rgb: ColorFormats.RGB | ColorFormats.RGBA;
/**
* @deprecated
*/
oldHue: number;
/**
* @deprecated
*/
source: 'hex';
draftHex: string;
draftHsl: ColorFormats.HSL | ColorFormats.HSLA;
draftRgb: ColorFormats.RGB | ColorFormats.RGBA;
};

/**
* @deprecated
*/
export interface LegacyProps {
color: LegacyColor;
/**
* @deprecated
*/
onChangeComplete: ( colors: LegacyColor ) => void;
/**
* @deprecated
*/
oldHue: string;
className: string;
/**
* @deprecated
*/
disableAlpha: boolean;
}

function isLegacyProps( props: any ): props is LegacyProps {
return (
typeof props.onChangeComplete !== 'undefined' ||
typeof props.color === 'string' ||
typeof props.hex === 'string'
sarayourfriend marked this conversation as resolved.
Show resolved Hide resolved
);
}

function getColorFromLegacyProps(
props: LegacyProps
): ColorFormats.HSL | ColorFormats.HSLA {
if ( typeof props.color === 'string' ) {
return colorize( props.color ).toHsl();
}

return props.color.hsl;
}

function toHsv(
color: colorize.Instance
): ColorFormats.HSV | ColorFormats.HSVA {
const { h, s, v, a } = color.toHsv();

return {
h: Math.round( h ),
s: Math.round( s * 100 ),
v: Math.round( v * 100 ),
a,
};
}

const transformHslToLegacyColor = memoize(
( hsla: ColorFormats.HSL | ColorFormats.HSLA ): LegacyColor => {
const color = colorize( hsla );
const rawHex = color.toHex();
const rgb = color.toRgb();
const hsv = toHsv( color );
const hsl = hsla;

const isTransparent = rawHex === '000000' && rgb.a === 0;
ciampo marked this conversation as resolved.
Show resolved Hide resolved

const hex = isTransparent ? 'transparent' : `#${ rawHex }`;

return {
hex,
ciampo marked this conversation as resolved.
Show resolved Hide resolved
rgb,
hsv,
hsl,
draftHex: hex.toLowerCase(),
draftHsl: hsl,
draftRgb: rgb,
source: 'hex',
oldHue: hsl.h,
};
}
);

export function useDeprecatedProps(
props: LegacyProps | ColorPickerProps
): ColorPickerProps {
const onChange = useCallback(
( hsla: ColorFormats.HSL | ColorFormats.HSLA ) => {
if ( isLegacyProps( props ) ) {
return props.onChangeComplete(
transformHslToLegacyColor( hsla )
);
}

return props.onChange?.( hsla );
},
[
( props as LegacyProps ).onChangeComplete,
( props as ColorPickerProps ).onChange,
]
);

const color = useMemo( () => {
return isLegacyProps( props )
? getColorFromLegacyProps( props )
: props.color;
}, [ props.color ] );

const enableAlpha = useMemo( () => {
return isLegacyProps( props )
? ! props.disableAlpha
: props.enableAlpha;
}, [
( props as LegacyProps ).disableAlpha,
( props as ColorPickerProps ).enableAlpha,
] );

return {
...( isLegacyProps( props ) ? {} : props ),
onChange,
color,
enableAlpha,
};
}