├── tests ├── .eslintrc └── index-test.js ├── .gitignore ├── src ├── utils │ ├── isModern.js │ ├── states.js │ └── loadImage.js ├── index.css └── index.js ├── nwb.config.js ├── .travis.yml ├── demo └── src │ ├── index.css │ └── index.js ├── CONTRIBUTING.md ├── package.json └── 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 | **/.DS_Store 9 | -------------------------------------------------------------------------------- /src/utils/isModern.js: -------------------------------------------------------------------------------- 1 | const isModern = window.CSS && CSS.supports && CSS.supports('object-fit', 'cover') 2 | 3 | export default isModern -------------------------------------------------------------------------------- /src/utils/states.js: -------------------------------------------------------------------------------- 1 | const states = { 2 | PENDING: 0, 3 | LOADING: 1, 4 | LOADED: 2, 5 | DEAD: 3 6 | } 7 | 8 | export default states -------------------------------------------------------------------------------- /nwb.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | type: 'react-component', 3 | npm: { 4 | esModules: true, 5 | umd: false 6 | }, 7 | devServer: { 8 | port: 1234 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/utils/loadImage.js: -------------------------------------------------------------------------------- 1 | export default function loadImage(url) { 2 | return new Promise((resolve, reject) => { 3 | 4 | let image = new Image() 5 | 6 | image.onload = resolve 7 | 8 | image.onerror = () => reject(new Error('Error when loading ' + url)) 9 | 10 | image.src = url; 11 | 12 | }) 13 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - 8 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 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | .FittedImage { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | .FittedImage--contain { 7 | object-fit: contain; 8 | } 9 | 10 | .FittedImage--cover { 11 | object-fit: cover; 12 | } 13 | 14 | .FittedImage--background { 15 | background-repeat: no-repeat; 16 | background-position: center; 17 | } 18 | 19 | .FittedImage--background .FittedImage--contain { 20 | background-size: contain; 21 | } 22 | 23 | .FittedImage--background .FittedImage--cover { 24 | background-size: cover; 25 | } 26 | -------------------------------------------------------------------------------- /demo/src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | .App { 7 | margin: auto; 8 | padding: 0.5rem 0; 9 | max-width: 50rem; 10 | height: 100vh; 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | .Settings { 15 | margin-bottom: 0.5rem; 16 | display: flex; 17 | flex-direction: row; 18 | } 19 | .Settings > label { 20 | flex: 1; 21 | } 22 | .Settings > select { 23 | flex: 4; 24 | } 25 | .Wrapper { 26 | border: 1px solid #ddd; 27 | height: 90%; 28 | } 29 | .Loader { 30 | display: flex; 31 | justify-content: center; 32 | align-items: center; 33 | height: 100%; 34 | width: 100%; 35 | } 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | 3 | [Node.js](http://nodejs.org/) >= 6 must be installed. 4 | 5 | ## Installation 6 | 7 | - Running `npm install` in the component'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-fitted-image", 3 | "version": "1.0.1", 4 | "description": "React component for image handling with object-fit", 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 --copy-files", 15 | "clean": "nwb clean-module && nwb clean-demo", 16 | "prepublishOnly": "npm run build", 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": "16.x" 25 | }, 26 | "devDependencies": { 27 | "babel-runtime": "^6.26.0", 28 | "enzyme": "^3.9.0", 29 | "enzyme-adapter-react-16": "^1.13.2", 30 | "nwb": "0.23.x", 31 | "react": "^16.8.6", 32 | "react-dom": "^16.8.6" 33 | }, 34 | "author": "alexjoffroy", 35 | "homepage": "https://github.com/alexjoffroy/react-fitted-image", 36 | "license": "MIT", 37 | "repository": { 38 | "type": "git", 39 | "url": "https://github.com/alexjoffroy/react-fitted-image.git" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/alexjoffroy/react-fitted-image/issues" 43 | }, 44 | "keywords": [ 45 | "react", 46 | "image", 47 | "picture", 48 | "load", 49 | "object-fit", 50 | "img", 51 | "react-component" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /demo/src/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react' 2 | import {render} from 'react-dom' 3 | 4 | import FittedImage from '../../lib' 5 | 6 | import './index.css' 7 | 8 | const fitOptions = [ 9 | { value: 'auto', label: 'Auto' }, 10 | { value: 'contain', label: 'Contain' }, 11 | { value: 'cover', label: 'Cover' } 12 | ]; 13 | 14 | const sizeOptions = [ 15 | { value: '1200/700', label: '1200x700' }, 16 | { value: '500/800', label: '500x800' }, 17 | { value: '900/900', label: '900x900' } 18 | ]; 19 | 20 | class Demo extends Component { 21 | 22 | constructor(props) { 23 | super(props) 24 | 25 | this.state = { 26 | fit: 'contain', 27 | size: '1200/700' 28 | } 29 | } 30 | 31 | getFitOptions() { 32 | return fitOptions.map( (opt, key) => { 33 | return ; 34 | }); 35 | } 36 | 37 | getSizeOptions() { 38 | return sizeOptions.map( (opt, key) => { 39 | return ; 40 | }); 41 | } 42 | 43 | onPropChange(prop, e) { 44 | let state = {}; 45 | state[prop] = e.target.value; 46 | this.setState(state); 47 | } 48 | 49 | render() { 50 | return ( 51 |