Skip to content

Commit

Permalink
Merge pull request #30 from EastSun5566/develop
Browse files Browse the repository at this point in the history
feat: develop
  • Loading branch information
EastSun5566 committed Oct 7, 2020
2 parents 28b400e + 895df1c commit ad1217a
Show file tree
Hide file tree
Showing 23 changed files with 2,243 additions and 1,244 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
🔗 <https://eastsun5566.github.io/cc-gram/>

![Demo GIF](./demo.gif)

## 🤔 Why

> [CSSgram](https://github.com/una/CSSgram) is a great CSS filters library, but sometimes you want to access/download the filter image. Then CCgram come into the play. It use CSS to preview filters and draw filter image with canvas filter API when you need it.
## Install
## Installation

```sh
npm i cc-gram
Expand Down Expand Up @@ -164,7 +166,7 @@ const blob = await cg.getBlob(image, {
- type: `string` - MIME types, default is `image/png`,
- quality: `number`- [0 - 1], default is `0.92`

## 🔧 Develop
## 🔧 Development

```sh
# install dep
Expand Down
7 changes: 1 addition & 6 deletions __tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ describe('Read/Write filter list', (): void => {
let cg: CCGram | null = null;

beforeEach(() => { cg = new CCGram({ init: false }); });
afterEach(() => { cg = null; });

test('get filter names list', (): void => {
expect(cg!.filterNames).toEqual([...DEFAULT_FILTERS.keys()]);
Expand Down Expand Up @@ -36,7 +35,7 @@ const getTargetImage = (dateAttr = 'filter'): HTMLImageElement | null => (
);

describe('Apply filter to target Image', () => {
afterEach(() => { document.body.innerHTML = ''; });
beforeEach(() => { document.body.innerHTML = ''; });

test('apply filter from init', (): void => {
document.body.innerHTML = `
Expand Down Expand Up @@ -97,10 +96,6 @@ describe.skip('Access filter image data', () => {

cg = new CCGram();
});
afterEach(() => {
document.body.innerHTML = '';
cg = null;
});

test('use getDataURL method', async (): Promise<void> => {
const target = getTargetImage()!;
Expand Down
Binary file added demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"analyze": "source-map-explorer 'build/static/js/*.js'",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
"deploy": "npm run build && gh-pages -d build"
},
"dependencies": {
"@babel/core": "7.10.5",
Expand Down
2 changes: 1 addition & 1 deletion demo/src/App/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
import App from '.';

test('renders learn react link', () => {
const { getByText } = render(<App />);
Expand Down
48 changes: 0 additions & 48 deletions demo/src/App/App.tsx

This file was deleted.

51 changes: 51 additions & 0 deletions demo/src/App/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { CSSTransition } from 'react-transition-group';

import './App.scss';

import {
UploadInput,
Preview,
GithubCorner,
Note,
} from '../components';
import { useFilters } from '../hooks';

const App: React.FC = () => {
const [imageURL, setImageURL] = useFilters();

return (
<>
<div id="app">
<h4 className="title my-3">🖼 CCgram</h4>

<CSSTransition
in={!!imageURL}
timeout={200}
classNames="fade"
>
{imageURL
? (
<Preview
imageURL={imageURL}
onClear={() => setImageURL('')}
/>
)
: (
<UploadInput
onUpload={
({ target }) => target.files && setImageURL(URL.createObjectURL(target.files[0]))
}
/>
)}
</CSSTransition>

<Note />
</div>

<GithubCorner />
</>
);
};

export default App;
1 change: 0 additions & 1 deletion demo/src/cg.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import CCGram from 'cc-gram';

export const cg = new CCGram({ init: false });

export default cg;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import './GithubCorner.scss';

const GithubCorner: React.FC = () => (
export const GithubCorner: React.FC = () => (
<a
href="https://github.com/EastSun5566/cc-gram"
className="github-corner"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

const Note: React.FC = () => (
export const Note: React.FC = () => (
<small className="d-block text-center my-3">
Made with
<span role="img" aria-label="heart"> ❤️ </span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,41 @@
/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
import React, { useState, useEffect, useRef } from 'react';
import React from 'react';

import './Preview.scss';

import { cg } from '../../cg';
import { useFilters, useDownloadImage } from '../../hooks';

const Preview: React.FC<{
imageURL: string;
setImageURL: React.Dispatch<React.SetStateAction<string>>;
}> = ({ imageURL, setImageURL }) => {
const [selectedFilter, setSelectedFilter] = useState('');
const image = useRef<HTMLImageElement>(null);
interface PreviewProps {
imageURL?: string;
onClear?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
}

useEffect(() => {
cg.applyFilter('#preview-image');
}, [selectedFilter]);
export const Preview: React.FC<PreviewProps> = ({
imageURL,
onClear,
}) => {
const [selectedFilter, setSelectedFilter] = useFilters({
selectors: '#preview-image',
});
const { imageRef, download } = useDownloadImage({ downloadFileName: selectedFilter });

const download = async () => {
const { current } = image;
if (!current) throw new Error('No Image');

const a = document.createElement('a');
a.href = await cg.getDataURL(current);
a.download = selectedFilter;
a.click();
};
if (!imageURL) return null;

return (
<div className="preview">

<div className="image-container">
<img
id="preview-image"
src={imageURL}
data-filter={selectedFilter}
alt={selectedFilter.toUpperCase()}
ref={image}
ref={imageRef}
/>
<button
type="button"
className="btn btn-cross"
onClick={() => setImageURL('')}
onClick={onClear}
>
<i className="fa fa-times" />
</button>
Expand Down Expand Up @@ -73,7 +68,6 @@ const Preview: React.FC<{
))
}
</div>

</div>
);
};
Expand Down
21 changes: 0 additions & 21 deletions demo/src/components/UploadInput/UploadInput.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions demo/src/components/UploadInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

import './UploadInput.scss';

interface UploadInputProps {
onUpload?: (event: React.ChangeEvent<HTMLInputElement>) => void
}

export const UploadInput: React.FC<UploadInputProps> = ({ onUpload }) => (
<div className="input-container">
<i className="fas fa-cloud-upload-alt" />
<input
type="file"
accept="image/*"
onChange={onUpload}
/>
</div>
);

export default UploadInput;
4 changes: 4 additions & 0 deletions demo/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './GithubCorner';
export * from './Note';
export * from './Preview';
export * from './UploadInput';
2 changes: 2 additions & 0 deletions demo/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './use-filters';
export * from './use-download-image';
29 changes: 29 additions & 0 deletions demo/src/hooks/use-download-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useRef } from 'react';
import { cg } from '../cg';

interface useDownloadImageOptions {
downloadFileName?: string;
}

export const useDownloadImage = ({
downloadFileName = 'download',
}: useDownloadImageOptions = {}): {
imageRef: React.RefObject<HTMLImageElement>;
download: () => void;
} => {
const imageRef = useRef<HTMLImageElement>(null);

const download = async () => {
const { current } = imageRef;
if (!current) throw new Error('No Image');

const a = document.createElement('a');
a.href = await cg.getDataURL(current);
a.download = downloadFileName;
a.click();
};

return { imageRef, download };
};

export default useDownloadImage;
25 changes: 25 additions & 0 deletions demo/src/hooks/use-filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState, useEffect } from 'react';
import { cg } from '../cg';

interface useFiltersOptions {
initialValue?: string;
selectors?: string;
}

export const useFilters = ({
initialValue = '',
selectors,
}: useFiltersOptions = {}): [
string,
React.Dispatch<React.SetStateAction<string>>
] => {
const [value, setValue] = useState(initialValue);

useEffect(() => {
cg.applyFilter(selectors);
}, [value]);

return [value, setValue];
};

export default useFilters;
4 changes: 3 additions & 1 deletion demo/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';

import './index.scss';
import App from './App/App';

import App from './App';
// import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
Expand Down
Loading

0 comments on commit ad1217a

Please sign in to comment.