Skip to content

Commit

Permalink
Merge 4c906a7 into 85b0f3f
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardokl committed Jun 22, 2019
2 parents 85b0f3f + 4c906a7 commit 2855a6b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 62 deletions.
18 changes: 14 additions & 4 deletions README.md
Expand Up @@ -12,17 +12,27 @@ npm i -S react-palette

## Usage
```jsx
import Palette from 'react-palette'
import Palette from 'react-palette';
// In your render...
<Palette image={IMAGE_URL}>
{palette => (
<div style={{ color: palette.vibrant }}>
<Palette src={IMAGE_URL}>
{({ data, loading, error }) => (
<div style={{ color: data.vibrant }}>
Text with the vibrant color
</div>
)}
</Palette>
```

```jsx
import { usePalette } from 'react-palette'

const { data, loading, error } = usePalette(IMAGE_URL)

<div style={{ color: data.vibrant }}>
Text with the vibrant color
</div>
```

## Palette callback example
```js
{
Expand Down
55 changes: 8 additions & 47 deletions src/Palette.tsx
@@ -1,51 +1,12 @@
import { PureComponent, ReactNode } from "react";
import { getPalette, PaletteColors } from "./getPalette";

type PaletteState = {
palette: PaletteColors;
loaded: boolean;
error?: Error;
};
import React, { ReactNode } from "react";
import { PaletteState, usePalette } from "./usePalette";

export type PaletteProps = {
image: string;
children(palette: PaletteColors): ReactNode;
src: string;
children(palette: PaletteState): ReactNode;
};

export class Palette extends PureComponent<PaletteProps, PaletteState> {
state: PaletteState = {
palette: {},
loaded: false,
error: undefined
};

updatePalette = image => {
getPalette(image)
.then(palette => this.setState({ palette, loaded: true }))
.catch(error => {
console.error(error);
this.setState({ palette: {}, loaded: true, error });
});
};

componentDidMount() {
this.updatePalette(this.props.image);
}

componentDidUpdate(prevProps) {
const { image } = this.props;

if (prevProps.image !== image) {
this.updatePalette(image);
}
}

render() {
const { children } = this.props;
const { palette, loaded } = this.state;

return loaded && children(palette);
}
}

export default Palette;
export const Palette: React.FC<PaletteProps> = ({
src,
children
}: PaletteProps) => <>{children(usePalette(src))}</>;
23 changes: 15 additions & 8 deletions src/__tests__/Palette.tsx
@@ -1,18 +1,25 @@
import { render, wait } from "@testing-library/react";
import React from "react";
import Palette, { getPalette } from "../";
import { Palette, getPalette } from "../";

test("execute children with palette when its loaded", async () => {
test("execute children with palette", async () => {
const children = jest.fn(() => null);
const image = 'test'
const palette = await getPalette(image);
const src = "test";
const palette = await getPalette(src);

render(<Palette image={image} children={children} />);
render(<Palette src={src} children={children} />);

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

await wait();

expect(children).toHaveBeenCalledTimes(1);
expect(children).toHaveBeenCalledWith(palette);
expect(children).toHaveBeenCalledWith({
loading: false,
error: undefined,
data: palette
});
});
7 changes: 4 additions & 3 deletions src/index.ts
@@ -1,3 +1,4 @@
export * from "./getPalette"
export * from "./Palette"
export { default } from "./Palette"
export * from "./getPalette";
export * from "./Palette";
export { Palette as default } from "./Palette";
export * from "./usePalette";
43 changes: 43 additions & 0 deletions src/usePalette.tsx
@@ -0,0 +1,43 @@
import { useEffect, useReducer } from "react";
import { getPalette, PaletteColors } from "./getPalette";

export type PaletteState = {
loading: boolean;
error?: Error;
data: PaletteColors;
}

const initialState: PaletteState = {
loading: true,
data: {},
error: undefined
}

function reducer(state: PaletteState, action) {
switch (action.type) {
case 'getPalette':
return initialState;
case 'resolvePalette':
return { ...state, data: action.payload, loading: false };
case 'rejectPalette':
return { ...state, error: action.payload, loading: false };
}
}

export function usePalette(src: string) {
const [state, dispatch] = useReducer(reducer, initialState);

useEffect(() => {
dispatch({ type: 'getPalette' });

getPalette(src)
.then(palette => {
dispatch({ type: 'resolvePalette', payload: palette });
})
.catch(ex => {
dispatch({ type: 'rejectPalette', payload: ex });
});
}, [src]);

return state;
}

0 comments on commit 2855a6b

Please sign in to comment.