Refactor Wrap and Custom components (#1)

* Refactor Wrap

* Add custom elements

* Code style

* Update documentation

* Update version
This commit is contained in:
Danilo Woznica
2017-02-08 20:29:54 -02:00
committed by GitHub
parent ddb3e2b8dc
commit 9d3d6a3a8c
12 changed files with 217 additions and 175 deletions

View File

@@ -2,31 +2,66 @@
This project is a collection the loader based on styles cards on Facebook.
## Usage:
## You can use it in two ways:
First install the dependency:
**First install the dependency:**
```sh
npm i react-content-loader --save-dev
```
After import and use:
**Stylized:** [example](#facebook-style)
```js
// import the component
import ContentLoader from 'react-content-loader'
const MyPage = () => (<ContentLoader />);
const MyLoader = () => {
return(
<ContentLoader type="facebook" />
)
}
```
### Options
**Our in custom mode:** [example](#custom-style)
```js
// import the component
import ContentLoader, { Rect, Circle }
const MyLoader = () => {
return(
<ContentLoader height={140} speed={1} primaryColor={'#333'} secondaryColor={'#999'}>
<Circle x={195} y={30} radius={30} />
<Rect x={50} y={80} height={10} radius={5} width={300} />
<Rect x={75} y={100} height={10} radius={5} width={250} />
</ContentLoader>
)
}
```
## Options
**ContentLoader (wrap) options:**
| Name | Type | Default | Description |
|---|---|---|---|
| style | _Object_ | | |
| style | _Object_ | `null` | Ex: `{ marginTop: '50px' }` |
| type | _String_ | `facebook` | Options: `facebook`, `instagram`, `code` |
| speed | _Number_ | `2` | Animation speed |
| height | _Number_ | `130` | Height component |
| primaryColor | _String_ | `#f3f3f3` | Background the SVG |
| secondaryColor | _String_ | `#ecebeb` | Animation color |
**Custom element options:**
| | x | y | radius | width | height |
|---|---|---|---|---|---|
| **Rect** | × | × | × | × | × |
| **Circle** | × | × | × | | |
## Examples
#### Facebook Style
![Facebook Style](https://cloud.githubusercontent.com/assets/4838076/22555575/3a90ecee-e94b-11e6-97df-8054e7297bd8.gif)
@@ -36,11 +71,14 @@ const MyPage = () => (<ContentLoader />);
#### Code Style
![Code Style](https://cloud.githubusercontent.com/assets/4838076/22555473/effa54c2-e94a-11e6-9128-9b608bcc69d9.gif)
#### Custom Style
![Code Style](https://cloud.githubusercontent.com/assets/4838076/22760218/aa619f32-ee3c-11e6-9cd1-c4af9dd1278e.gif)
### Todo
- [x] Code component;
- [x] Custom elements;
- [ ] List component;
- [ ] Test in multiples browser;
- [ ] A more useful new project;
#### Credits

View File

@@ -1,7 +1,7 @@
{
"name": "react-content-loader",
"version": "1.1.0",
"description": "This project is a collection the loader based on styles cards on Facebook.",
"version": "1.2.0",
"description": "This project is a collection the loader based on styles cards on Facebook, make with SVG and React.",
"repository": {
"type": "git",
"url": "https://github.com/danilowoz/react-content-loader"

View File

@@ -1,43 +0,0 @@
import React from 'react';
const CodeStyle = (props ) => {
const gradient = {
fill: `url(#${props.classNameHash}1)`
}
return(
<svg viewBox = "0 0 400 70" version = "1.1" style={props.style} preserveAspectRatio="xMidYMid meet">
<rect style={gradient} clipPath={`url(#${props.classNameHash}2`} x="0" y="0" width="400" height="400" />
<defs>
<clipPath id={`${props.classNameHash}2`}>
<rect x="0" y="0" rx="3" ry="3" width="70" height="10" />
<rect x="80" y="0" rx="3" ry="3" width="100" height="10" />
<rect x="190" y="0" rx="3" ry="3" width="10" height="10" />
<rect x="15" y="20" rx="3" ry="3" width="130" height="10" />
<rect x="155" y="20" rx="3" ry="3" width="130" height="10" />
<rect x="15" y="40" rx="3" ry="3" width="90" height="10" />
<rect x="115" y="40" rx="3" ry="3" width="60" height="10" />
<rect x="185" y="40" rx="3" ry="3" width="60" height="10" />
<rect x="0" y="60" rx="3" ry="3" width="30" height="10" />
</clipPath>
<linearGradient id={`${props.classNameHash}1`}>
<stop offset="0%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-2; 1" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="50%" stopColor={props.secondaryColor}>
<animate attributeName="offset" values="-1.5; 1.5" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="100%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-1; 2" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
</linearGradient>
</defs>
</svg>
)
}
export default CodeStyle

View File

@@ -1,39 +0,0 @@
import React from 'react';
const FacebookStyle = (props ) => {
const gradient = {
fill: `url(#${props.classNameHash}1)`
}
return(
<svg viewBox = "0 0 400 130" version = "1.1" style={props.style} preserveAspectRatio="xMidYMid meet">
<rect style={gradient} clipPath={`url(#${props.classNameHash}2`} x="0" y="0" width="400" height="400" />
<defs>
<clipPath id={`${props.classNameHash}2`}>
<rect x="0" y="0" rx="5" ry="5" width="70" height="70" />
<rect x="80" y="17" rx="4" ry="4" width="300" height="13" />
<rect x="80" y="40" rx="3" ry="3" width="250" height="10" />
<rect x="0" y="80" rx="3" ry="3" width="350" height="10" />
<rect x="0" y="100" rx="3" ry="3" width="400" height="10" />
<rect x="0" y="120" rx="3" ry="3" width="360" height="10" />
</clipPath>
<linearGradient id={`${props.classNameHash}1`}>
<stop offset="0%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-2; 1" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="50%" stopColor={props.secondaryColor}>
<animate attributeName="offset" values="-1.5; 1.5" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="100%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-1; 2" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
</linearGradient>
</defs>
</svg>
)
}
export default FacebookStyle

View File

@@ -1,36 +0,0 @@
import React from 'react';
const InstagramStyle = (props ) => {
const gradient = {
fill: `url(#${props.classNameHash}1)`
}
return(
<svg viewBox = "0 0 400 480" version = "1.1" style={props.style} preserveAspectRatio="xMidYMid meet">
<rect style={gradient} clipPath={`url(#${props.classNameHash}2`} x="0" y="0" width="400" height="400" />
<defs>
<clipPath id={`${props.classNameHash}2`}>
<circle cx="30" cy="30" r="30" />
<rect x="75" y="13" rx="4" ry="4" width="100" height="13" />
<rect x="75" y="37" rx="4" ry="4" width="50" height="8" />
<rect x="0" y="70" rx="5" ry="5" width="400" height="400" />
</clipPath>
<linearGradient id={`${props.classNameHash}1`}>
<stop offset="0%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-2; 1" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="50%" stopColor={props.secondaryColor}>
<animate attributeName="offset" values="-1.5; 1.5" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="100%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-1; 2" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
</linearGradient>
</defs>
</svg>
)
}
export default InstagramStyle

43
src/Wrap.js Normal file
View File

@@ -0,0 +1,43 @@
import React from 'react'
const Wrap = (props) => {
const generateId = () => {
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
let text = ""
for( let i = 0; i < 10; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length))
return text
}
let idClip = generateId()
let idGradient = generateId()
return(
<svg viewBox={`0 0 400 ${props.height}`} version="1.1" style={props.style} preserveAspectRatio="xMidYMid meet">
<rect style={{fill: `url(#${idGradient})`}} clipPath={`url(#${idClip})`} x="0" y="0" width="400" height={props.height} />
<defs>
<clipPath id={`${idClip}`}>
{ props.children }
</clipPath>
<linearGradient id={`${idGradient}`}>
<stop offset="0%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-2; 1" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="50%" stopColor={props.secondaryColor}>
<animate attributeName="offset" values="-1.5; 1.5" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
<stop offset="100%" stopColor={props.primaryColor}>
<animate attributeName="offset" values="-1; 2" dur={`${props.speed}s`} repeatCount="indefinite" />
</stop>
</linearGradient>
</defs>
</svg>
)
}
export default Wrap

8
src/custom/Circle.js Normal file
View File

@@ -0,0 +1,8 @@
import React from 'react';
const Circle = (props) => {
const { x = 0, y = 0, radius = 50 } = props
return <circle cx={x} cy={y} r={radius} />
}
export default Circle

8
src/custom/Rect.js Normal file
View File

@@ -0,0 +1,8 @@
import React from 'react';
const Rect = (props) => {
const { x = 0, y = 0, radius = 0, width = 50, height = 50 } = props
return <rect x={x} y={y} rx={radius} ry={radius} width={width} height={height} />
}
export default Rect

View File

@@ -1,68 +1,73 @@
import React, { Component } from 'react'
import FacebookStyle from './FacebookStyle'
import InstagramStyle from './InstagramStyle'
import CodeStyle from './CodeStyle'
/**
* [hashCode - This function is to create an id for SVG]
* BUT, I can't believe this is the best approach
* If you know a better solution open a PR, please!
*/
const hashCode = function() {
var text = ""
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for( var i = 0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length))
return text
}
import Wrap from './Wrap'
// Stylized
import FacebookStyle from './stylized/FacebookStyle'
import InstagramStyle from './stylized/InstagramStyle'
import CodeStyle from './stylized/CodeStyle'
// Custom
import Rect from './custom/Rect'
import Circle from './custom/Circle'
class ContentLoader extends Component {
constructor(props) {
super(props)
this.state = {
style: props.style,
type: props.type || 'facebook',
speed: props.speed || 2,
primaryColor: props.primaryColor || '#f3f3f3',
secondaryColor: props.secondaryColor || '#ecebeb',
classNameHash: hashCode()
}
constructor(props) {
super(props)
this.state = {
style: props.style,
type: props.type || 'facebook',
speed: props.speed || 2,
height: props.height ||130,
primaryColor: props.primaryColor || '#f0f0f0',
secondaryColor: props.secondaryColor || '#e0e0e0'
}
}
render() {
if( this.props.children ) {
return(
<Wrap {...this.state}>
{ this.props.children }
</Wrap>
)
} else {
switch(this.state.type.toLowerCase()) {
case 'instagram':
return <InstagramStyle {...this.state} />
break
case 'code':
return <CodeStyle {...this.state} />
break
default:
case 'facebook':
return <FacebookStyle {...this.state} />
break
}
}
render() {
let elementContentLoader = {}
switch(this.state.type) {
case 'code':
elementContentLoader = <CodeStyle {...this.state} />
break
case 'instagram':
elementContentLoader = <InstagramStyle {...this.state} />
break
case 'facebook':
default:
elementContentLoader = <FacebookStyle {...this.state} />
}
return elementContentLoader
}
}
}
ContentLoader.propTypes = {
style: React.PropTypes.object,
type: React.PropTypes.string,
speed: React.PropTypes.number,
height: React.PropTypes.number,
primaryColor: React.PropTypes.string,
secondaryColor: React.PropTypes.string
}
export default ContentLoader
export { Rect, Circle }

23
src/stylized/CodeStyle.js Normal file
View File

@@ -0,0 +1,23 @@
import React from 'react'
import Wrap from '../Wrap'
const CodeStyle = (props ) => {
return(
<Wrap {...props}>
<rect x="0" y="0" rx="3" ry="3" width="70" height="10" />
<rect x="80" y="0" rx="3" ry="3" width="100" height="10" />
<rect x="190" y="0" rx="3" ry="3" width="10" height="10" />
<rect x="15" y="20" rx="3" ry="3" width="130" height="10" />
<rect x="155" y="20" rx="3" ry="3" width="130" height="10" />
<rect x="15" y="40" rx="3" ry="3" width="90" height="10" />
<rect x="115" y="40" rx="3" ry="3" width="60" height="10" />
<rect x="185" y="40" rx="3" ry="3" width="60" height="10" />
<rect x="0" y="60" rx="3" ry="3" width="30" height="10" />
</Wrap>
)
}
export default CodeStyle

View File

@@ -0,0 +1,19 @@
import React from 'react'
import Wrap from '../Wrap'
const FacebookStyle = (props ) => {
return(
<Wrap {...props}>
<rect x="0" y="0" rx="5" ry="5" width="70" height="70" />
<rect x="80" y="17" rx="4" ry="4" width="300" height="13" />
<rect x="80" y="40" rx="3" ry="3" width="250" height="10" />
<rect x="0" y="80" rx="3" ry="3" width="350" height="10" />
<rect x="0" y="100" rx="3" ry="3" width="400" height="10" />
<rect x="0" y="120" rx="3" ry="3" width="360" height="10" />
</Wrap>
)
}
export default FacebookStyle

View File

@@ -0,0 +1,16 @@
import React from 'react'
import Wrap from '../Wrap'
const InstagramStyle = (props ) => {
return(
<Wrap {...props} height="480">
<circle cx="30" cy="30" r="30" />
<rect x="75" y="13" rx="4" ry="4" width="100" height="13" />
<rect x="75" y="37" rx="4" ry="4" width="50" height="8" />
<rect x="0" y="70" rx="5" ry="5" width="400" height="400" />
</Wrap>
)
}
export default InstagramStyle