Skip to content

Commit

Permalink
fix: update state type from children to change by format
Browse files Browse the repository at this point in the history
  • Loading branch information
jonyw4 committed Aug 17, 2020
1 parent 4452894 commit ec2e660
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 114 deletions.
34 changes: 6 additions & 28 deletions src/Color/Color.component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,6 @@ describe('Color', () => {
const src = 'https://homepages.cae.wisc.edu/~ece533/images/airplane.png';
const timeout = 15000;

test(
'should be a children with default format',
async () => {
const children = jest.fn(() => <></>);
await act(async () => {
render(<Color src={src} children={children} crossOrigin="Anonymous" />);
});

expect(children).toHaveBeenCalledWith({
loading: true,
error: undefined,
data: undefined
});

await waitFor(() => expect(children).toHaveBeenCalledTimes(2), {
timeout
});

expect(children).toHaveBeenCalledWith({
loading: false,
error: undefined,
data: 'rgb(199, 203, 205)'
});
},
timeout
);

test(
'should be a children with rgb array',
async () => {
Expand Down Expand Up @@ -143,7 +116,12 @@ describe('Color', () => {
const children = jest.fn(() => <></>);
await act(async () => {
render(
<Color src="error.jpg" children={children} crossOrigin="Anonymous" />
<Color
src="error.jpg"
format="hex"
children={children}
crossOrigin="Anonymous"
/>
);
});

Expand Down
24 changes: 15 additions & 9 deletions src/Color/Color.component.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import React from 'react';
import { ColorFormats } from '../types';
import useColor, { UseColorState } from './useColor';
import { ColorFormats, ReducerState, ArrayRGB } from '../types';
import useColor from './useColor';

function Color({
function Color<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB : string>
>({
src,
format = 'rgbString',
format,
crossOrigin = undefined,
quality = 10,
children
}: ColorProps): JSX.Element {
const state = useColor(src, format, { crossOrigin, quality });
}: ColorProps<F, S>): JSX.Element {
const state: S = useColor(src, format, { crossOrigin, quality });

return <>{children(state)}</>;
}

export type ColorProps = {
export type ColorProps<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB : string>
> = {
/**
* Link of the image
*/
src: string;
/**
* Format of the response.
*/
format?: ColorFormats;
format: F;
/**
* Tag cross-origin for image
*/
Expand All @@ -31,7 +37,7 @@ export type ColorProps = {
* Quality determines how many pixels are skipped before the nex one is sampled.We rarely need to sample every single pixel in the image to get good results. The bigger the number, the faster a value will be returned. Read more in https://lokeshdhakar.com/projects/color-thief/
*/
quality?: number;
children: (state: UseColorState) => React.ReactNode;
children: (state: S) => React.ReactNode;
};

export default Color;
22 changes: 9 additions & 13 deletions src/Color/useColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,22 @@ import {
reducer,
initialReducerState
} from '../utils';
import { ColorFormats, ReducerState, UnwrapPromise } from '../types';

export type UseColorState = ReducerState<
UnwrapPromise<ReturnType<typeof getPredominantColorFromImgURL>>
>;
import { ColorFormats, ReducerState, ArrayRGB } from '../types';

/**
* React Hook to use get color from img url
*/
export default function useColor(
export default function useColor<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB : string>
>(
imgSrc: string,
format: ColorFormats = 'rgbString',
format: F,
options: { crossOrigin?: string; quality?: number } = {}
): UseColorState {
): S {
const { crossOrigin = null, quality = 10 } = options;

const [state, dispatch] = useReducer(
reducer,
<UseColorState>initialReducerState
);
const [state, dispatch] = useReducer(reducer, <S>initialReducerState);

useCurrentEffect(
(isCurrent) => {
Expand All @@ -45,5 +41,5 @@ export default function useColor(
[imgSrc]
);

return state;
return <S>state;
}
31 changes: 1 addition & 30 deletions src/Palette/Palette.component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,6 @@ describe('Palette', () => {
const src = 'https://homepages.cae.wisc.edu/~ece533/images/airplane.png';
const timeout = 10000;

test(
'should be a children with default format',
async () => {
const children = jest.fn(() => <></>);

await act(async () => {
render(
<Palette src={src} children={children} crossOrigin="Anonymous" />
);
});

expect(children).toHaveBeenCalledWith({
loading: true,
error: undefined,
data: undefined
});

await waitFor(() => expect(children).toHaveBeenCalledTimes(2), {
timeout
});

expect(children).toHaveBeenCalledWith({
loading: false,
error: undefined,
data: ['rgb(188, 192, 199)', 'rgb(97, 61, 122)']
});
},
timeout
);

test(
'should be a children with rgb array',
async () => {
Expand Down Expand Up @@ -195,6 +165,7 @@ describe('Palette', () => {
src="error.jpg"
children={children}
crossOrigin="Anonymous"
format="rgbArray"
/>
);
});
Expand Down
27 changes: 18 additions & 9 deletions src/Palette/Palette.component.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
import React from 'react';
import { ColorFormats } from '../types';
import usePalette, { UsePaletteState } from './usePalette';
import { ColorFormats, ReducerState, ArrayRGB } from '../types';
import usePalette from './usePalette';

function Palette({
function Palette<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB[] : string[]>
>({
src,
colorCount = 2,
format = 'rgbString',
format,
crossOrigin = undefined,
quality = 10,
children
}: PaletteProps): JSX.Element {
const state = usePalette(src, colorCount, format, { crossOrigin, quality });
}: PaletteProps<F, S>): JSX.Element {
const state: S = usePalette(src, colorCount, format, {
crossOrigin,
quality
});

return <>{children(state)}</>;
}

export type PaletteProps = {
export type PaletteProps<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB[] : string[]>
> = {
/**
* Count of colors of the palette
*/
Expand All @@ -27,7 +36,7 @@ export type PaletteProps = {
/**
* Format of the response.
*/
format?: ColorFormats;
format: F;
/**
* Tag cross-origin for image
*/
Expand All @@ -36,7 +45,7 @@ export type PaletteProps = {
* Quality determines how many pixels are skipped before the nex one is sampled.We rarely need to sample every single pixel in the image to get good results. The bigger the number, the faster a value will be returned. Read more in https://lokeshdhakar.com/projects/color-thief/
*/
quality?: number;
children: (state: UsePaletteState) => React.ReactNode;
children: (state: S) => React.ReactNode;
};

export default Palette;
22 changes: 9 additions & 13 deletions src/Palette/usePalette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,23 @@ import {
reducer,
initialReducerState
} from '../utils';
import { ColorFormats, ReducerState, UnwrapPromise } from '../types';

export type UsePaletteState = ReducerState<
UnwrapPromise<ReturnType<typeof getColorsPaletteFromImgUrl>>
>;
import { ColorFormats, ReducerState, ArrayRGB } from '../types';

/**
* React Hook to get palette color from img url
*/
export default function usePalette(
export default function usePalette<
F extends ColorFormats,
S extends ReducerState<F extends 'rgbArray' ? ArrayRGB[] : string[]>
>(
imgSrc: string,
colorCount = 2,
format: ColorFormats = 'rgbString',
format: F,
options: { crossOrigin?: string; quality?: number } = {}
): UsePaletteState {
): S {
const { crossOrigin = null, quality = 10 } = options;

const [state, dispatch] = useReducer(
reducer,
<UsePaletteState>initialReducerState
);
const [state, dispatch] = useReducer(reducer, <S>initialReducerState);

useCurrentEffect(
(isCurrent) => {
Expand All @@ -52,5 +48,5 @@ export default function usePalette(
[imgSrc]
);

return state;
return <S>state;
}
8 changes: 4 additions & 4 deletions src/utils/formatRGB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import type { ColorFormats, ArrayRGB } from '../types';
/**
* Transform a RGB Array to another color format
*/
export default function formatRGB(
export default function formatRGB<T extends ColorFormats>(
arrayRGB: ArrayRGB,
format: ColorFormats
): string | ArrayRGB {
const responses: { [key in ColorFormats]: () => string | ArrayRGB } = {
format: T
): T extends 'rgbArray' ? ArrayRGB : string {
const responses: { [key in ColorFormats]: () => any } = {
rgbString: () => rgbStringfy(...arrayRGB),
hex: () => rgbToHex(...arrayRGB),
rgbArray: () => arrayRGB
Expand Down
8 changes: 5 additions & 3 deletions src/utils/getColorsPaletteFromImgUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import type { ColorFormats, ArrayRGB } from '../types';
/**
* Get a list of colors from img url
*/
export default async function getColorsPaletteFromImgUrl(
export default async function getColorsPaletteFromImgUrl<
T extends ColorFormats
>(
imgUrl: string,
colorCount = 2,
format: ColorFormats = 'rgbString',
format: T,
crossOrigin: string | null = null,
quality = 10
): Promise<(string | ArrayRGB)[]> {
): Promise<(T extends 'rgbArray' ? ArrayRGB : string)[]> {
const img = await loadImage(imgUrl, crossOrigin);
const cf = new ColorThief();
const arrayRGB = cf.getPalette(img, colorCount, quality);
Expand Down
8 changes: 5 additions & 3 deletions src/utils/getPredominantColorFromImgURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import ColorThief from 'colorthief/dist/color-thief.umd.js';
import { loadImage, formatRGB } from '.';
import type { ColorFormats, ArrayRGB } from '../types';

export default async function getPredominantColorFromImgURL(
export default async function getPredominantColorFromImgURL<
T extends ColorFormats
>(
imgSrc: string,
format: ColorFormats = 'rgbString' as const,
format: T,
crossOrigin: string | null = null,
quality = 10
): Promise<string | ArrayRGB> {
): Promise<T extends 'rgbArray' ? ArrayRGB : string> {
const img = await loadImage(imgSrc, crossOrigin);
const ct = new ColorThief();
const arrayRGB = ct.getColor(img, quality);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/rgbStringfy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Put RGB into a string
*/
export default function rgbStringfy(r: number, g: number, b: number) {
export default function rgbStringfy(r: number, g: number, b: number): string {
return `rgb(${r}, ${g}, ${b})`;
}
2 changes: 1 addition & 1 deletion src/utils/rgbToHex.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Transform RGB to HEX
*/
export default function rgbToHex(r: number, g: number, b: number) {
export default function rgbToHex(r: number, g: number, b: number): string {
function transform(number: number) {
const hex = number.toString(16);
return hex.length === 1 ? `0${hex}` : hex;
Expand Down

0 comments on commit ec2e660

Please sign in to comment.