├── .babelrc ├── .gitignore ├── README.md ├── bin └── deploy.sh ├── docs └── README.md ├── example ├── bundle.js ├── example.txt ├── index.html └── index.js ├── lib ├── Panel │ └── index.js └── index.js ├── package.json ├── server.js ├── src ├── Panel │ ├── index.js │ └── panel.css └── index.js ├── test ├── Panel.spec.js └── setup.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-0"], 3 | "env": { 4 | "development": { 5 | "presets": ["react-hmre"] 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-image-panel 2 | [![npm version](https://badge.fury.io/js/react-image-panel.svg)](https://badge.fury.io/js/react-image-panel) 3 | [![Build Status](https://travis-ci.org/clintonhalpin/react-image-panel.svg?branch=gh-pages)](https://travis-ci.org/clintonhalpin/react-image-panel) 4 | 5 | A small module for showing image + title + description in a panel [Demo](http://clintonhalpin.github.io/react-image-panel/example/) 6 | 7 | ![screen shot 2016-03-05 at 2 14 29 pm](https://cloud.githubusercontent.com/assets/523933/13549840/9e3462ec-e2dc-11e5-829d-505a75996c21.png) 8 | 9 | ### get started 10 | ```shell 11 | npm i react-image-panel --save 12 | ``` 13 | 14 | Integrating component 15 | ```javascript 16 | import { Panel } from 'react-image-panel' 17 | 18 | // 19 | ``` 20 | 21 | Adding css! 22 | You can find all of the css for this module in `./node_modules/react-image-panel/src/panel.css` 23 | 24 | ### development 25 | Run's webpack and starts a tiny express server for testing 26 | 27 | ```shell 28 | npm i 29 | npm run start 30 | ``` 31 | 32 | ### hosting an example ( gh-pages ) 33 | By default components come with an examples page it order to publish that 34 | ``` 35 | npm run build 36 | git add . -A 37 | git commit -m "Your message" 38 | git push origin gh-pages 39 | ``` 40 | 41 | If you have an specific documentation in your component you can add that in `docs/README.md` 42 | 43 | ### testing 44 | 45 | ```shell 46 | npm run test 47 | ``` 48 | 49 | ### build-scripts 50 | 51 | | Script | Action | 52 | | ------------- | ------------- | 53 | | `start` | Run Dev Server | 54 | | `build` | compile `example` and build common:js | 55 | | `build:commonjs` | build common:js to lib | 56 | | `test` | run unit tests | 57 | | `test:watch` | run unit tests with watch | 58 | 59 | ### examples 60 | [tbd] 61 | 62 | = 63 | 64 | built by [@clintonhalpin](http://twitter.com/clintonhalpin) 65 | -------------------------------------------------------------------------------- /bin/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build 5 | npm run deploy 6 | 7 | # inside this git repo we'll pretend to be a new user 8 | git config user.name "Travis CI" 9 | git config user.email "clintonhalpin@gmail.com" 10 | 11 | git init 12 | 13 | # The first and only commit to this new Git repo contains all the 14 | # files present with the commit message "Deploy to GitHub Pages". 15 | git add . 16 | git commit -m "Built via travis!" 17 | 18 | # Force push from the current repo's master branch to the remote 19 | # repo's gh-pages branch. (All previous history on the gh-pages branch 20 | # will be lost, since we are overwriting it.) We redirect any output to 21 | # /dev/null to hide any sensitive credential data that might otherwise be exposed. 22 | <<<<<<< HEAD 23 | git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1 24 | ======= 25 | git push "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1 26 | >>>>>>> master 27 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | [tbd] -------------------------------------------------------------------------------- /example/example.txt: -------------------------------------------------------------------------------- 1 | // bool - toggles loading state -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | react-image-panel 5 | 6 | 7 | 8 | 9 | 10 | 11 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import React, { Component, PropTypes } from 'react'; 3 | import { render } from 'react-dom'; 4 | import { Panel } from './../src/'; 5 | import styles from './../src/Panel/panel.css'; 6 | import {PrismCode} from "react-prism"; 7 | 8 | export class Root extends Component { 9 | render() { 10 | return ( 11 |
12 |
13 |

react-image-panel

14 |

A reusable panel component! View Github repo!

15 |
16 |
17 | 22 |
23 |
24 | 29 |
30 |
31 | 36 |
37 |
38 | 44 |
45 |
46 | 50 |
51 |
52 |

Props

53 |

All of the options you can pass into react-image-panel

54 |
55 |
56 |
{require('raw-loader!./example.txt').trim()}
57 |
58 |
59 |

built with by @clintonhalpin

60 |
61 |
62 | ) 63 | } 64 | }; 65 | 66 | render( 67 | , 68 | document.getElementById('root') 69 | ) 70 | -------------------------------------------------------------------------------- /lib/Panel/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _reactRouter = require('react-router'); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | var Panel = function Panel(_ref) { 16 | var _ref$rootClass = _ref.rootClass; 17 | var rootClass = _ref$rootClass === undefined ? 'panel' : _ref$rootClass; 18 | var _ref$panelInnerYPosit = _ref.panelInnerYPosition; 19 | var panelInnerYPosition = _ref$panelInnerYPosit === undefined ? '' : _ref$panelInnerYPosit; 20 | var image = _ref.image; 21 | var _ref$title = _ref.title; 22 | var title = _ref$title === undefined ? '' : _ref$title; 23 | var _ref$description = _ref.description; 24 | var description = _ref$description === undefined ? '' : _ref$description; 25 | var _ref$height = _ref.height; 26 | var height = _ref$height === undefined ? 300 : _ref$height; 27 | var _ref$linkTo = _ref.linkTo; 28 | var linkTo = _ref$linkTo === undefined ? '/' : _ref$linkTo; 29 | var loading = _ref.loading; 30 | 31 | var renderReady = function renderReady() { 32 | return _react2.default.createElement( 33 | 'div', 34 | null, 35 | _react2.default.createElement( 36 | 'h2', 37 | { className: 'text-truncate m0 mb1' }, 38 | title 39 | ), 40 | _react2.default.createElement( 41 | 'p', 42 | { className: 'text-truncate h5 m0' }, 43 | description 44 | ) 45 | ); 46 | }; 47 | 48 | var renderLoading = function renderLoading() { 49 | return 'Loading...'; 50 | }; 51 | 52 | return _react2.default.createElement( 53 | _reactRouter.Link, 54 | { className: rootClass, to: linkTo }, 55 | _react2.default.createElement( 56 | 'div', 57 | { style: { height: height } }, 58 | image && !loading && _react2.default.createElement('img', { className: rootClass + '__image', src: image, alt: title }), 59 | _react2.default.createElement( 60 | 'div', 61 | { className: rootClass + '__inner ' + rootClass + '__inner--' + panelInnerYPosition }, 62 | loading ? renderLoading() : renderReady() 63 | ) 64 | ) 65 | ); 66 | }; 67 | 68 | exports.default = Panel; -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.Panel = undefined; 7 | 8 | var _Panel2 = require('./Panel/'); 9 | 10 | var _Panel3 = _interopRequireDefault(_Panel2); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | exports.Panel = _Panel3.default; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-image-panel", 3 | "version": "1.0.2", 4 | "description": "A beautiful looking image panel", 5 | "main": "lib/index.js", 6 | "directories": { 7 | "doc": "docs", 8 | "example": "example" 9 | }, 10 | "scripts": { 11 | "start": "node server.js", 12 | "build:example": "NODE_ENV=production webpack -p --optimize-dedupe", 13 | "build:commonjs": "BABEL_ENV=commonjs babel src --out-dir lib", 14 | "build": "npm run build:example && npm run build:commonjs", 15 | "test": "NODE_ENV=production mocha --compilers js:babel-core/register --recursive --require ./test/setup.js", 16 | "deploy": "npm run test && npm run build", 17 | "test:watch": "npm test --watch", 18 | "clean": "rm -rf dist" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/clintonhalpin/react-image-panel.git" 23 | }, 24 | "keywords": [ 25 | "React", 26 | "Component", 27 | "Boilerplate" 28 | ], 29 | "author": "clintonhalpin@gmail.com", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/clintonhalpin/react-image-panel/issues" 33 | }, 34 | "homepage": "https://github.com/clintonhalpin/react-image-panel#readme", 35 | "dependencies": { 36 | "react": "^0.14.7" 37 | }, 38 | "devDependencies": { 39 | "babel": "^6.5.2", 40 | "babel-cli": "^6.6.5", 41 | "babel-core": "^6.3.15", 42 | "babel-loader": "^6.2.0", 43 | "babel-polyfill": "^6.3.14", 44 | "babel-preset-es2015": "^6.3.13", 45 | "babel-preset-react": "^6.3.13", 46 | "babel-preset-react-hmre": "^1.0.1", 47 | "babel-preset-stage-0": "^6.5.0", 48 | "babel-preset-stage-2": "^6.5.0", 49 | "css-loader": "^0.23.1", 50 | "expect": "^1.14.0", 51 | "expect-jsx": "^2.3.0", 52 | "express": "^4.13.4", 53 | "jsdom": "^8.0.2", 54 | "mocha": "^2.4.5", 55 | "raw-loader": "^0.5.1", 56 | "react-addons-test-utils": "^0.14.7", 57 | "react-dom": "^0.14.7", 58 | "react-prism": "^3.1.1", 59 | "react-router": "2.0.0-rc5", 60 | "react-router-redux": "^2.1.0", 61 | "style-loader": "^0.13.0", 62 | "webpack": "^1.9.11", 63 | "webpack-dev-middleware": "^1.2.0", 64 | "webpack-hot-middleware": "^2.2.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var webpackDevMiddleware = require('webpack-dev-middleware'); 3 | var webpackHotMiddleware = require('webpack-hot-middleware'); 4 | var config = require('./webpack.config'); 5 | var app = new (require('express'))(); 6 | var port = 3000; 7 | var compiler = webpack(config); 8 | 9 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath })); 10 | app.use(webpackHotMiddleware(compiler)); 11 | 12 | app.use(function(req, res) { 13 | res.sendFile(__dirname + '/example/index.html') 14 | }); 15 | 16 | app.listen(port, function(error) { 17 | if (error) { 18 | console.error(error) 19 | } else { 20 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port) 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /src/Panel/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router'; 3 | 4 | const Panel = ({ 5 | rootClass = 'panel', 6 | panelInnerYPosition = '', 7 | image, 8 | title = '', 9 | description = '', 10 | height = 300, 11 | linkTo = '/', 12 | loading 13 | }) => { 14 | const renderReady = () => { 15 | return( 16 |
17 |

{title}

18 |

{description}

19 |
20 | ) 21 | } 22 | 23 | const renderLoading = () => { 24 | return 'Loading...' 25 | } 26 | 27 | return( 28 | 29 |
30 | { image && !loading && {title} } 31 |
32 | { loading ? renderLoading() : renderReady() } 33 |
34 |
35 | 36 | ) 37 | }; 38 | 39 | export default Panel; -------------------------------------------------------------------------------- /src/Panel/panel.css: -------------------------------------------------------------------------------- 1 | .text-truncate { 2 | max-width: 100%; 3 | overflow: hidden; 4 | text-overflow: ellipsis; 5 | white-space: nowrap; 6 | word-wrap: normal; 7 | } 8 | 9 | .panel { 10 | position: relative; 11 | display: inline-block; 12 | width: 100%; 13 | overflow: hidden; 14 | transition: box-shadow .25s ease; 15 | } 16 | 17 | .panel:before { 18 | content: ""; 19 | background: rgba(0,0,0,.3); 20 | position: absolute; 21 | top: 0; 22 | left: 0; 23 | bottom: 0; 24 | right: 0; 25 | z-index: 101; 26 | } 27 | 28 | .panel:hover { 29 | cursor: pointer; 30 | } 31 | 32 | .panel:hover:before { 33 | background: rgba(0,0,0,.2); 34 | } 35 | 36 | .panel:active:before { 37 | background: rgba(0,0,0,.6); 38 | } 39 | 40 | .panel:active .panel__inner { 41 | opacity: .8; 42 | } 43 | 44 | .panel__image { 45 | vertical-align: middle; 46 | margin: 0; 47 | padding: 0; 48 | width: 100%; 49 | height: 100%; 50 | object-fit: cover; 51 | } 52 | 53 | .panel__inner { 54 | position: absolute; 55 | bottom: 0; 56 | left: 0; 57 | right: 0; 58 | color: white; 59 | z-index: 101; 60 | max-width: 100%; 61 | padding: 1rem; 62 | } 63 | 64 | .panel__inner--top { 65 | top: 0; 66 | bottom: inherit; 67 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export Panel from './Panel/'; -------------------------------------------------------------------------------- /test/Panel.spec.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import expect from 'expect'; 3 | import expectJSX from 'expect-jsx'; 4 | expect.extend(expectJSX); 5 | import React from 'react'; 6 | import TestUtils from 'react-addons-test-utils'; 7 | import { Panel } from './../src/'; 8 | 9 | function setup() { 10 | let renderer = TestUtils.createRenderer(); 11 | renderer.render() 12 | let output = renderer.getRenderOutput(); 13 | 14 | return { 15 | output, 16 | renderer 17 | } 18 | } 19 | 20 | describe('components', () => { 21 | describe('Panel', () => { 22 | it('should render', () => { 23 | const { output } = setup(); 24 | expect(output.type).toExist(); 25 | }); 26 | it('should have more tests', () => { 27 | expect(true).toBe(false); 28 | }); 29 | }) 30 | }) -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | import { jsdom } from 'jsdom'; 2 | 3 | global.document = jsdom(''); 4 | global.window = document.defaultView; 5 | global.navigator = global.window.navigator; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | var build = { 5 | entry: [ 6 | './example/' 7 | ], 8 | output: { 9 | path: path.join(__dirname, 'example'), 10 | filename: 'bundle.js', 11 | }, 12 | module: { 13 | loaders: [ 14 | { 15 | test: /\.js$/, 16 | loaders: [ 'babel' ], 17 | exclude: /node_modules/, 18 | include: __dirname 19 | }, 20 | { 21 | test: /\.less$/, 22 | loader: "style!css!less" 23 | }, 24 | { 25 | test: /\.css$/, 26 | loader: "style!css" 27 | } 28 | ] 29 | } 30 | } 31 | 32 | if (process.env.NODE_ENV === 'production') { 33 | build.stats = { 34 | assets: false, 35 | warnings: false 36 | }; 37 | build.plugins = [ 38 | new webpack.optimize.OccurenceOrderPlugin(), 39 | new webpack.NoErrorsPlugin(), 40 | new webpack.DefinePlugin({ 41 | 'process.env.NODE_ENV': '"production"' 42 | }), 43 | ]; 44 | module.exports = build 45 | } else { 46 | build.devtool = 'cheap-module-eval-source-map'; 47 | build.plugins = [ 48 | new webpack.optimize.OccurenceOrderPlugin(), 49 | new webpack.HotModuleReplacementPlugin(), 50 | new webpack.NoErrorsPlugin() 51 | ]; 52 | build.entry.push('webpack-hot-middleware/client'); 53 | module.exports = build 54 | } --------------------------------------------------------------------------------