├── tests
├── .eslintrc
└── index-test.js
├── .gitignore
├── nwb.config.js
├── .travis.yml
├── src
├── LoadingPlaceholder.css
└── index.js
├── CONTRIBUTING.md
├── package.json
├── demo
└── src
│ └── index.js
└── README.md
/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /demo/dist
3 | /es
4 | /lib
5 | /node_modules
6 | /umd
7 | npm-debug.log*
8 |
--------------------------------------------------------------------------------
/nwb.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | type: 'react-component',
3 | npm: {
4 | esModules: true,
5 | umd: {
6 | global: 'ReactLoadingPlaceholder',
7 | externals: {
8 | react: 'React'
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 6
6 |
7 | before_install:
8 | - npm install codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
17 |
--------------------------------------------------------------------------------
/tests/index-test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/src/LoadingPlaceholder.css:
--------------------------------------------------------------------------------
1 | @keyframes placeHolderShimmer{
2 | 0%{
3 | background-position: -1168px 0
4 | }
5 | 100%{
6 | background-position: 1168px 0
7 | }
8 | }
9 |
10 | .animated__background {
11 | animation-duration: 2s;
12 | animation-fill-mode: forwards;
13 | animation-iteration-count: infinite;
14 | animation-name: placeHolderShimmer;
15 | animation-timing-function: linear;
16 | background: #f6f7f8;
17 | background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
18 | background-size: 1200px 104px;
19 | height: 96px;
20 | position: relative;
21 | }
22 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Prerequisites
2 |
3 | [Node.js](http://nodejs.org/) >= v4 must be installed.
4 |
5 | ## Installation
6 |
7 | - Running `npm install` in the components's root directory will install everything you need for development.
8 |
9 | ## Demo Development Server
10 |
11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12 |
13 | ## Running Tests
14 |
15 | - `npm test` will run the tests once.
16 |
17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18 |
19 | - `npm run test:watch` will run the tests on every change.
20 |
21 | ## Building
22 |
23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app.
24 |
25 | - `npm run clean` will delete built resources.
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-loading-placeholder",
3 | "version": "1.0.6",
4 | "description": "react-loading-placeholder React component",
5 | "main": "lib/index.js",
6 | "module": "es/index.js",
7 | "files": [
8 | "css",
9 | "es",
10 | "lib",
11 | "umd"
12 | ],
13 | "scripts": {
14 | "build": "nwb build-react-component",
15 | "postbuild": "cp src/LoadingPlaceholder.css lib/ && cp src/LoadingPlaceholder.css es/",
16 | "clean": "nwb clean-module && nwb clean-demo",
17 | "start": "nwb serve-react-demo",
18 | "test": "nwb test-react",
19 | "test:coverage": "nwb test-react --coverage",
20 | "test:watch": "nwb test-react --server"
21 | },
22 | "dependencies": {},
23 | "peerDependencies": {
24 | "react": "15.x"
25 | },
26 | "devDependencies": {
27 | "nwb": "0.18.x",
28 | "react": "^16.0.0",
29 | "react-dom": "^16.0.0"
30 | },
31 | "author": "",
32 | "homepage": "",
33 | "license": "MIT",
34 | "repository": "",
35 | "keywords": [
36 | "react-component"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import {render} from 'react-dom'
3 |
4 | import LoadingPlaceholder from '../../src'
5 |
6 | class Demo extends Component {
7 |
8 | constructor(props) {
9 | super(props);
10 | };
11 |
12 | render() {
13 | return (
14 |
15 |
react-loading-placeholder Demo
16 |
17 |
Simple table or list
18 |
19 |
20 |
21 |
22 |
Table with filter
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
30 | render(, document.querySelector('#demo'))
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-loading-placeholder
2 |
3 | [![npm package][npm-badge]][npm]
4 |
5 | Inspired by Facebook Content Placeholder and this article: https://cloudcannon.com/deconstructions/2014/11/15/facebook-content-placeholder-deconstruction.html. Can be used for both tables and lists.
6 |
7 | 
8 |
9 |
10 |
11 | ## Installation
12 |
13 | ```bash
14 | npm install --save react-loading-placeholder
15 | ```
16 |
17 |
18 | ## Including it:
19 | ```javascript
20 | import LoadingPlaceholder from 'react-loading-placeholder'
21 |
22 |
23 | ```
24 |
25 | ## Settings:
26 |
27 | #### Set row height and space between:
28 | ```
29 |
30 | ```
31 |
32 | #### Table Layout:
33 | ```
34 |
35 | ```
36 |
37 | #### Set filter placeholder size:
38 | ```
39 |
40 | ```
41 |
42 | [npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
43 | [npm]: https://www.npmjs.com/package/react-loading-placeholder
44 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import styles from './LoadingPlaceholder.css';
3 |
4 | const defaultMarginTop = 40;
5 | const defaultSpaceBetween = 10;
6 | const defaultHeightOfRows = defaultMarginTop + defaultSpaceBetween;
7 |
8 | const placeholderOptions = {
9 | heightOfRows: defaultHeightOfRows,
10 | marginTop: defaultMarginTop,
11 | spaceBetween: defaultSpaceBetween
12 | };
13 |
14 | const filterOptions = {
15 | marginTop: 90,
16 | width: 400,
17 | height: 50
18 | }
19 |
20 | class LoadingPlaceholder extends Component {
21 | constructor(props) {
22 | super(props);
23 | };
24 |
25 | componentWillMount() {
26 | this._setStartValues();
27 | this._calculateHeight();
28 | };
29 |
30 | _setStartValues() {
31 | placeholderOptions.marginTop = defaultMarginTop;
32 | placeholderOptions.spaceBetween = this.props.spaceBetween || defaultSpaceBetween;
33 | if (this.props.heightOfRows) {
34 | placeholderOptions.heightOfRows = this.props.heightOfRows + placeholderOptions.spaceBetween;
35 | placeholderOptions.marginTop = this.props.heightOfRows;
36 | }
37 | else {
38 | placeholderOptions.heightOfRows = defaultHeightOfRows + this.props.spaceBetween || defaultHeightOfRows;
39 | }
40 |
41 | if (this.props.filterOptions) {
42 | filterOptions.width = this.props.filterOptions.width;
43 | filterOptions.height = this.props.filterOptions.height;
44 | if (this.props.filterOptions.marginTop) {
45 | filterOptions.marginTop = this.props.filterOptions.marginTop;
46 | }
47 | }
48 | };
49 |
50 | _calculateNumberOfRows() {
51 | let _numberOfRows = this.props.numberOfRows;
52 | if (this.props.tableLayout) {
53 | _numberOfRows = _numberOfRows + 1;
54 | }
55 | return _numberOfRows;
56 | };
57 |
58 | _calculateHeight() {
59 | let _height = placeholderOptions.marginTop;
60 | if (this.props.tableLayout) {
61 | _height = filterOptions.marginTop;
62 | }
63 | for (let i = 1; i < this._calculateNumberOfRows(); i++) {
64 | _height = _height + placeholderOptions.heightOfRows;
65 | };
66 | return _height;
67 | };
68 |
69 | _convertToPixels(_int) {
70 | return _int.toString() + 'px';
71 | };
72 |
73 | _renderRows() {
74 | let _rows = [];
75 | if (this.props.tableLayout) {
76 | placeholderOptions.marginTop = filterOptions.marginTop;
77 | }
78 | for (let i = 1; i < this._calculateNumberOfRows(); i++) {
79 | let marginTopString = this._convertToPixels(placeholderOptions.marginTop);
80 | _rows.push();
81 | placeholderOptions.marginTop = placeholderOptions.marginTop + placeholderOptions.heightOfRows;
82 | }
83 | this._setStartValues();
84 | return _rows;
85 | };
86 |
87 | _tableLayout() {
88 | return (
89 |
93 | )
94 | };
95 |
96 | render() {
97 | return (
98 |
99 | {this.props.tableLayout && this._tableLayout()}
100 | {this._renderRows()}
101 |
102 | );
103 | }
104 | }
105 |
106 | export default LoadingPlaceholder;
107 |
--------------------------------------------------------------------------------