├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html └── src ├── App.css ├── App.js ├── FBPost.css ├── FBPost.js ├── imgs ├── angred.PNG ├── comment-btn.PNG ├── default-avatar.jpg ├── hahaed.PNG ├── like-btn.PNG ├── liked.PNG ├── loved.PNG ├── privacy-friends.PNG ├── privacy-public.PNG ├── saded.PNG ├── share-btn.PNG └── wowed.PNG ├── index.css ├── index.js └── react-fb-image-grid ├── components ├── Images.js └── Modal.js ├── css └── style.css └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # backup 13 | /src/Backup 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | .eslintrc.js 27 | .prettierrc.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dummy Facebook Post Creator 2 | 3 | Live: https://muhammadovi.github.io/react-fb-post-creator 4 | 5 | \*Use on PC/Laptop for good experience. 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-fb-post-creator", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "https://oyeovi.github.io/react-fb-post-creator", 6 | "dependencies": { 7 | "antd": "^3.9.2", 8 | "react": "^16.5.1", 9 | "react-bootstrap": "^0.32.4", 10 | "react-dom": "^16.5.1", 11 | "react-facebook-emoji": "^1.0.11", 12 | "react-fb-image-grid": "^0.1.3", 13 | "react-image-lightbox": "^5.0.0", 14 | "react-scripts": "1.1.5" 15 | }, 16 | "devDependencies": { 17 | "babel-eslint": "^8.2.6", 18 | "eslint": "4.19.1", 19 | "eslint-config-airbnb": "^17.0.0", 20 | "eslint-config-prettier": "^2.9.0", 21 | "eslint-plugin-import": "^2.13.0", 22 | "eslint-plugin-prettier": "^2.6.2", 23 | "eslint-plugin-react": "^7.10.0", 24 | "html-webpack-plugin": "^3.2.0", 25 | "prettier": "^1.14.2" 26 | }, 27 | "scripts": { 28 | "start": "react-scripts start", 29 | "build": "react-scripts build", 30 | "predeploy": "npm run build", 31 | "deploy": "gh-pages -d build", 32 | "test": "react-scripts test --env=jsdom", 33 | "eject": "react-scripts eject" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Facebook Post Creator 10 | 17 | 18 | 19 | 20 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | html::-webkit-scrollbar, 2 | body::-webkit-scrollbar { 3 | display: none; /* might be enought */ 4 | background: transparent; 5 | visibility: hidden; 6 | width: 0px; 7 | } 8 | 9 | body { 10 | background: #e9ebee !important; 11 | } 12 | 13 | .App { 14 | /* text-align: center; */ 15 | padding: 20px; 16 | background: #e9ebee; 17 | width: 100%; 18 | min-height: 100%; 19 | text-align: left; 20 | } 21 | 22 | .editor { 23 | position: relative; 24 | margin: auto; 25 | width: calc(50% - 20px); 26 | /* min-height: 400px; */ 27 | background: white; 28 | float: left; 29 | padding: 20px; 30 | margin-bottom: 20px; 31 | margin-right: 20px; 32 | } 33 | 34 | .editor-hide-button { 35 | display: none !important; 36 | width: 200px; 37 | position: absolute; 38 | left: calc(50% - 100px); 39 | margin-bottom: 20px; 40 | } 41 | 42 | .editor_avtar { 43 | width: 120px; 44 | float: left; 45 | margin-top: 5px; 46 | } 47 | 48 | .editor_name, 49 | .editor_caption, 50 | .editor_time_privacy { 51 | width: calc(100% - 120px); 52 | margin-bottom: 8px; 53 | float: left; 54 | } 55 | 56 | .select-time { 57 | width: calc(65% - 10px) !important; 58 | margin-right: 10px !important; 59 | } 60 | 61 | .editor-privacy { 62 | width: 35% !important; 63 | } 64 | 65 | .result { 66 | width: 50%; 67 | float: left; 68 | } 69 | 70 | @media screen and (max-width: 899px) { 71 | .App { 72 | padding: 20px 5px; 73 | } 74 | .editor { 75 | width: 100%; 76 | float: none; 77 | } 78 | .result { 79 | width: 100%; 80 | float: none; 81 | } 82 | .editor-hide-button { 83 | display: block !important; 84 | } 85 | .select-time { 86 | width: 100% !important; 87 | margin-right: 0 !important; 88 | } 89 | 90 | .editor-privacy { 91 | width: 100% !important; 92 | margin: 10px 0 0 0 !important; 93 | } 94 | .editor_caption { 95 | width: 100%; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import FBPost from './FBPost'; 3 | 4 | import { 5 | Upload, 6 | Icon, 7 | Divider, 8 | Input, 9 | Select, 10 | TimePicker, 11 | Button, 12 | InputNumber, 13 | Checkbox, 14 | } from 'antd'; 15 | 16 | import './App.css'; 17 | 18 | const { Option } = Select; 19 | 20 | class App extends Component { 21 | constructor(props) { 22 | super(props); 23 | 24 | this.state = { 25 | avtars: [], 26 | images: [], 27 | includeLike: false, 28 | includeLove: false, 29 | includeHaha: false, 30 | includeWow: false, 31 | includeSad: false, 32 | includeAngry: false, 33 | editorShown: true, 34 | }; 35 | } 36 | 37 | toggleEditor = () => { 38 | let { editorShown } = this.state; 39 | this.setState({ editorShown: !editorShown }); 40 | }; 41 | 42 | uploadAvtar = ({ fileList }) => this.setState({ avtars: fileList }); 43 | 44 | setTime = (time, timeString) => { 45 | this.setState({ time: timeString }); 46 | }; 47 | 48 | setPrivacy = value => { 49 | this.setState({ privacy: value }); 50 | }; 51 | 52 | uploadImages = ({ fileList }) => { 53 | const images = fileList.map(file => { 54 | return file.thumbUrl; 55 | }); 56 | this.setState({ images }); 57 | }; 58 | 59 | includeLike = () => { 60 | let { includeLike } = this.state; 61 | this.setState({ includeLike: !includeLike }); 62 | }; 63 | 64 | includeLove = () => { 65 | let { includeLove } = this.state; 66 | this.setState({ includeLove: !includeLove }); 67 | }; 68 | 69 | includeHaha = () => { 70 | let { includeHaha } = this.state; 71 | this.setState({ includeHaha: !includeHaha }); 72 | }; 73 | 74 | includeWow = () => { 75 | let { includeWow } = this.state; 76 | this.setState({ includeWow: !includeWow }); 77 | }; 78 | 79 | includeSad = () => { 80 | let { includeSad } = this.state; 81 | this.setState({ includeSad: !includeSad }); 82 | }; 83 | 84 | includeAngry = () => { 85 | let { includeAngry } = this.state; 86 | this.setState({ includeAngry: !includeAngry }); 87 | }; 88 | 89 | render() { 90 | const { 91 | avtars, 92 | name, 93 | caption, 94 | time, 95 | privacy, 96 | likes, 97 | images, 98 | editorShown, 99 | } = this.state; 100 | let { 101 | includeLike, 102 | includeLove, 103 | includeHaha, 104 | includeWow, 105 | includeSad, 106 | includeAngry, 107 | } = this.state; 108 | 109 | const uploadButton = ( 110 |
111 | 112 |
Upload Avtar
113 |
114 | ); 115 | 116 | return ( 117 |
118 | 121 | 122 | {editorShown && ( 123 |
124 |
125 | {}} 129 | accept="image/*" 130 | onChange={this.uploadAvtar} 131 | > 132 | {avtars.length >= 1 ? null : uploadButton} 133 | 134 |
135 | 136 |
137 | 141 | } 142 | onChange={e => this.setState({ name: e.target.value })} 143 | /> 144 |
145 | 146 |
147 | 154 | 155 | 166 |
167 | 168 |
169 | this.setState({ caption: e.target.value })} 173 | /> 174 |
175 | 176 | 177 | 178 |

179 | Upload Pictures:   Upload Multiples by clicking CTRL 180 | ;) 181 |

182 | {}} 187 | accept="image/*" 188 | onChange={this.uploadImages} 189 | > 190 | 193 | 194 | 195 | 196 | 197 | this.setState({ likes: value })} 201 | /> 202 | 203 |
204 |
205 | Includes: 206 |
207 | 211 | Likes 212 | 213 | 217 | Love 218 | 219 | 223 | Haha 224 | 225 | 229 | WoW 230 | 231 | 235 | Sad 236 | 237 | 241 | Angry 242 | 243 |
244 | )} 245 | 246 |
247 | 262 |
263 |
 
264 |
265 | ); 266 | } 267 | } 268 | 269 | export default App; 270 | -------------------------------------------------------------------------------- /src/FBPost.css: -------------------------------------------------------------------------------- 1 | .post { 2 | position: relative; 3 | margin: auto; 4 | /* min-height: 400px; */ 5 | background: white; 6 | width: 100%; 7 | float: left; 8 | padding-top: 55px; 9 | } 10 | 11 | .avatar { 12 | position: absolute; 13 | display: inline-block; 14 | top: 10px; 15 | width: 45px; 16 | height: 45px; 17 | margin-left: 10px; 18 | border-radius: 50%; 19 | background: #e8e8e8; 20 | } 21 | 22 | .avatar img, 23 | .privacy img { 24 | height: 100%; 25 | width: 100%; 26 | border-radius: inherit; 27 | cursor: pointer; 28 | } 29 | 30 | .name { 31 | position: absolute; 32 | top: 15px; 33 | left: 65px; 34 | font-weight: bold; 35 | color: #365899; 36 | cursor: pointer; 37 | font-size: 0.95em; 38 | } 39 | 40 | .time { 41 | position: absolute; 42 | top: 35px; 43 | left: 65px; 44 | color: #737880; 45 | cursor: pointer; 46 | font-size: 0.75em; 47 | } 48 | 49 | .time:hover { 50 | text-decoration: underline; 51 | } 52 | 53 | .privacy { 54 | position: absolute; 55 | top: -1px; 56 | height: 16px; 57 | width: 16px; 58 | right: -20px; 59 | color: #737880; 60 | font-size: 1em; 61 | } 62 | 63 | .dots { 64 | position: absolute; 65 | right: 10px; 66 | top: 10px; 67 | padding: 5px; 68 | cursor: pointer; 69 | } 70 | 71 | .dots span { 72 | display: block; 73 | float: right; 74 | margin: 2px; 75 | height: 4px; 76 | width: 4px; 77 | border-radius: 50%; 78 | background: #737880; 79 | } 80 | 81 | .dots:hover span { 82 | background: black; 83 | } 84 | 85 | .caption { 86 | position: relative; 87 | padding: 10px 10px 5px; 88 | font-size: 0.9em; 89 | } 90 | 91 | .images { 92 | height: 400px; 93 | } 94 | 95 | .likesCount { 96 | color: #737880; 97 | font-size: 0.9em; 98 | margin: 10px 10px 0; 99 | padding-bottom: 5px; 100 | border-bottom: 1px solid #e8e8e8; 101 | } 102 | 103 | .btns { 104 | display: flex; 105 | justify-content: space-evenly; 106 | align-items: center; 107 | height: 40px; 108 | text-align: center; 109 | padding: 0 5px; 110 | /* border: 1px solid lightgray; */ 111 | border-bottom: 1px solid #e8e8e8; 112 | } 113 | 114 | .likeBtn, 115 | .commentBtn, 116 | .shareBtn { 117 | width: 100%; 118 | height: 80%; 119 | border-radius: 5px; 120 | cursor: pointer; 121 | display: flex; 122 | justify-content: center; 123 | align-items: center; 124 | background: #fff; 125 | margin: 3px; 126 | } 127 | 128 | .likeBtn:hover, 129 | .commentBtn:hover, 130 | .shareBtn:hover { 131 | background: #f1f1f1; 132 | } 133 | 134 | .likeBtn { 135 | position: relative; 136 | } 137 | 138 | .likes img { 139 | height: 20px; 140 | } 141 | 142 | .emojies { 143 | position: absolute; 144 | bottom: 30px; 145 | width: 290px; 146 | left: -5px; 147 | background: #fff; 148 | padding: 5px 5px 0; 149 | border-radius: 20px; 150 | box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.1); 151 | } 152 | 153 | .emoji { 154 | display: inline-block; 155 | width: 40px; 156 | margin: 0 3px; 157 | transition: all 0.3s; 158 | cursor: pointer; 159 | } 160 | 161 | .emoji:hover { 162 | transform: scale(1.3); 163 | } 164 | -------------------------------------------------------------------------------- /src/FBPost.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import FbImageLibrary from './react-fb-image-grid'; 3 | import FacebookEmoji from 'react-facebook-emoji'; 4 | 5 | import './FBPost.css'; 6 | 7 | import defaultAvtar from './imgs/default-avatar.jpg'; 8 | import privacyPublic from './imgs/privacy-public.PNG'; 9 | import privacyFriends from './imgs/privacy-friends.PNG'; 10 | import LikeBtn from './imgs/like-btn.PNG'; 11 | import CommentBtn from './imgs/comment-btn.PNG'; 12 | import ShareBtn from './imgs/share-btn.PNG'; 13 | import Liked from './imgs/liked.PNG'; 14 | import Loved from './imgs/loved.PNG'; 15 | import Hahaed from './imgs/hahaed.PNG'; 16 | import Wowed from './imgs/wowed.PNG'; 17 | import Saded from './imgs/saded.PNG'; 18 | import Angred from './imgs/angred.PNG'; 19 | 20 | let LikeBtnImg = LikeBtn; 21 | 22 | class FBPost extends Component { 23 | static defaultProps = { 24 | avtar: false, 25 | name: 'Your Name', 26 | time: 'Just Now', 27 | privacy: 'public', 28 | caption: 'Some Awesome Caption', 29 | images: [], 30 | likes: 0, 31 | includeLike: false, 32 | includeLove: false, 33 | includeHaha: false, 34 | includeWow: false, 35 | includeSad: false, 36 | includeAngry: false, 37 | }; 38 | 39 | constructor(props) { 40 | super(props); 41 | 42 | this.state = { 43 | emojiesShown: false, 44 | emoji: null, 45 | iLiked: false, 46 | iLoved: false, 47 | iHahaed: false, 48 | iWowed: false, 49 | iSaded: false, 50 | iAngred: false, 51 | }; 52 | } 53 | 54 | showEmojies = isTrue => { 55 | this.setState({ emojiesShown: isTrue }); 56 | }; 57 | 58 | setEmoji = (newEmoji, fromBtn) => { 59 | const { emoji } = this.state; 60 | 61 | if (emoji && emoji !== 'like' && fromBtn) { 62 | this.setState({ emoji: null }, this.setEmojiImg(null)); 63 | return; 64 | } 65 | 66 | if (!emoji || emoji !== newEmoji) 67 | this.setState({ emoji: newEmoji }, this.setEmojiImg(newEmoji)); 68 | 69 | if (emoji === newEmoji) 70 | this.setState({ emoji: null }, this.setEmojiImg(null)); 71 | 72 | this.showEmojies(false); 73 | }; 74 | 75 | setEmojiImg = emoji => { 76 | let { iLiked, iLoved, iHahaed, iWowed, iSaded, iAngred } = this.state; 77 | 78 | switch (emoji) { 79 | case 'like': 80 | LikeBtnImg = Liked; 81 | this.setState({ 82 | iLiked: !iLiked, 83 | iLoved: false, 84 | iHahaed: false, 85 | iWowed: false, 86 | iSaded: false, 87 | iAngred: false, 88 | }); 89 | break; 90 | 91 | case 'love': 92 | LikeBtnImg = Loved; 93 | this.setState({ 94 | iLiked: false, 95 | iLoved: !iLoved, 96 | iHahaed: false, 97 | iWowed: false, 98 | iSaded: false, 99 | iAngred: false, 100 | }); 101 | break; 102 | 103 | case 'haha': 104 | LikeBtnImg = Hahaed; 105 | this.setState({ 106 | iLiked: false, 107 | iLoved: false, 108 | iHahaed: !iHahaed, 109 | iWowed: false, 110 | iSaded: false, 111 | iAngred: false, 112 | }); 113 | break; 114 | 115 | case 'wow': 116 | LikeBtnImg = Wowed; 117 | this.setState({ 118 | iLiked: false, 119 | iLoved: false, 120 | iHahaed: false, 121 | iWowed: !iWowed, 122 | iSaded: false, 123 | iAngred: false, 124 | }); 125 | break; 126 | 127 | case 'sad': 128 | LikeBtnImg = Saded; 129 | this.setState({ 130 | iLiked: false, 131 | iLoved: false, 132 | iHahaed: false, 133 | iWowed: false, 134 | iSaded: !iSaded, 135 | iAngred: false, 136 | }); 137 | break; 138 | 139 | case 'angry': 140 | LikeBtnImg = Angred; 141 | this.setState({ 142 | iLiked: false, 143 | iLoved: false, 144 | iHahaed: false, 145 | iWowed: false, 146 | iSaded: false, 147 | iAngred: !iAngred, 148 | }); 149 | break; 150 | 151 | default: 152 | LikeBtnImg = LikeBtn; 153 | this.setState({ 154 | iLiked: false, 155 | iLoved: false, 156 | iHahaed: false, 157 | iWowed: false, 158 | iSaded: false, 159 | iAngred: false, 160 | }); 161 | break; 162 | } 163 | }; 164 | 165 | render() { 166 | const { 167 | emojiesShown, 168 | emoji, 169 | iLiked, 170 | iLoved, 171 | iHahaed, 172 | iWowed, 173 | iSaded, 174 | iAngred, 175 | } = this.state; 176 | const { 177 | avtar, 178 | name, 179 | time, 180 | privacy, 181 | caption, 182 | images, 183 | likes, 184 | includeLike, 185 | includeLove, 186 | includeHaha, 187 | includeWow, 188 | includeSad, 189 | includeAngry, 190 | } = this.props; 191 | 192 | return ( 193 |
194 |
195 |
196 | Img 197 |
198 | 199 | {name} 200 | 201 |
202 | {time}  -  203 | 204 | . 208 | 209 |
210 | 211 |
212 | 213 | 214 | 215 |
216 |
217 | 218 |
{caption}
219 |
0 ? { height: 400 } : { height: 0 }} 222 | > 223 | 224 |
225 | 226 |
227 |
228 | {(includeLike || iLiked || likes > 0) && ( 229 | . 230 | )} 231 | {(includeLove || iLoved) && .} 232 | {(includeHaha || iHahaed) && .} 233 | {(includeWow || iWowed) && .} 234 | {(includeSad || iSaded) && .} 235 | {(includeAngry || iAngred) && .} 236 | {emoji && ' You'} {emoji && likes > 0 && ' & '} 237 | {likes > 0 && likes} {emoji && likes > 0 && ' Others'} 238 |
239 |
240 | 241 |
242 |
this.showEmojies(true)} 245 | onMouseLeave={() => this.showEmojies(false)} 246 | > 247 | {emojiesShown && ( 248 |
249 |
this.setEmoji('like')}> 250 | 251 |
252 |
this.setEmoji('love')}> 253 | 254 |
255 |
this.setEmoji('haha')}> 256 | 257 |
258 |
this.setEmoji('wow')}> 259 | 260 |
261 |
this.setEmoji('sad')}> 262 | 263 |
264 |
this.setEmoji('angry')}> 265 | 266 |
267 |
268 | )} 269 | this.setEmoji('like', true)} 271 | src={LikeBtnImg} 272 | alt="Like" 273 | /> 274 |
275 |
276 | Comment 277 |
278 |
279 | Share 280 |
281 |
282 |
283 | ); 284 | } 285 | } 286 | 287 | export default FBPost; 288 | -------------------------------------------------------------------------------- /src/imgs/angred.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/angred.PNG -------------------------------------------------------------------------------- /src/imgs/comment-btn.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/comment-btn.PNG -------------------------------------------------------------------------------- /src/imgs/default-avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/default-avatar.jpg -------------------------------------------------------------------------------- /src/imgs/hahaed.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/hahaed.PNG -------------------------------------------------------------------------------- /src/imgs/like-btn.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/like-btn.PNG -------------------------------------------------------------------------------- /src/imgs/liked.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/liked.PNG -------------------------------------------------------------------------------- /src/imgs/loved.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/loved.PNG -------------------------------------------------------------------------------- /src/imgs/privacy-friends.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/privacy-friends.PNG -------------------------------------------------------------------------------- /src/imgs/privacy-public.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/privacy-public.PNG -------------------------------------------------------------------------------- /src/imgs/saded.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/saded.PNG -------------------------------------------------------------------------------- /src/imgs/share-btn.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/share-btn.PNG -------------------------------------------------------------------------------- /src/imgs/wowed.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuhammadOvi/react-fb-post-creator/58a1aa03d61ea207dce9403739a62a0fab875313/src/imgs/wowed.PNG -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body { 8 | font-family: sans-serif; 9 | } 10 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | import 'antd/dist/antd.css'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | -------------------------------------------------------------------------------- /src/react-fb-image-grid/components/Images.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Row, Col } from 'react-bootstrap'; 3 | import PropTypes from 'prop-types'; 4 | import Modal from './Modal'; 5 | 6 | class Images extends Component { 7 | static defaultProps = { 8 | beautify: false, 9 | countFrom: 5, 10 | hideOverlay: false, 11 | images: [], 12 | onClickEach: null, 13 | overlayBackgroundColor: '#222222', 14 | renderOverlay: () => 'Preview Image', 15 | upperHeight: 65, 16 | width: 100, 17 | }; 18 | 19 | constructor(props) { 20 | super(props); 21 | 22 | this.state = { 23 | countFrom: 24 | props.countFrom > 0 && props.countFrom < 5 ? props.countFrom : 5, 25 | modal: false, 26 | }; 27 | 28 | this.openModal = this.openModal.bind(this); 29 | this.onClose = this.onClose.bind(this); 30 | 31 | if (props.countFrom <= 0 || props.countFrom > 5) { 32 | console.warn('countFrom is limited to 5!'); 33 | } 34 | } 35 | 36 | onClose() { 37 | this.setState({ modal: false }); 38 | } 39 | 40 | openModal(index) { 41 | const { onClickEach, images } = this.props; 42 | 43 | if (onClickEach) { 44 | return onClickEach({ index, src: images[index] }); 45 | } 46 | 47 | this.setState({ index, modal: true }); 48 | } 49 | 50 | renderOne() { 51 | const { images, beautify, upperHeight } = this.props; 52 | const { countFrom } = this.state; 53 | const height = images.length === 1 ? '100%' : `${upperHeight}%`; 54 | 55 | const overlay = 56 | images.length > countFrom && countFrom === 1 57 | ? this.renderCountOverlay(true) 58 | : this.renderOverlay(); 59 | 60 | return ( 61 | 62 | 63 | 71 | {overlay} 72 | 73 | 74 | 75 | ); 76 | } 77 | 78 | renderTwo() { 79 | const { images, beautify, upperHeight } = this.props; 80 | const { countFrom } = this.state; 81 | const overlay = 82 | images.length > countFrom && [2, 3].includes(+countFrom) 83 | ? this.renderCountOverlay(true) 84 | : this.renderOverlay(); 85 | const height = 86 | images.length === 2 87 | ? '100%' 88 | : images.length === 3 89 | ? `${100 - upperHeight}%` 90 | : `${upperHeight}%`; 91 | const conditionalRender = 92 | [3, 4].includes(images.length) || 93 | (images.length > +countFrom && [3, 4].includes(+countFrom)); 94 | 95 | return ( 96 | 97 | 98 | 109 | {this.renderOverlay()} 110 | 111 | 122 | {overlay} 123 | 124 | 125 | 126 | ); 127 | } 128 | 129 | renderThree() { 130 | const { images, beautify, upperHeight } = this.props; 131 | const { countFrom } = this.state; 132 | const overlay = 133 | !countFrom || 134 | countFrom > 5 || 135 | (images.length > countFrom && [4, 5].includes(+countFrom)) 136 | ? this.renderCountOverlay(true) 137 | : this.renderOverlay(); 138 | const height = `${100 - upperHeight}%`; 139 | const conditionalRender = 140 | images.length === 4 || (images.length > +countFrom && +countFrom === 4); 141 | 142 | return ( 143 | 144 | 145 | 156 | {this.renderOverlay()} 157 | 158 | 169 | {this.renderOverlay()} 170 | 171 | 182 | {overlay} 183 | 184 | 185 | 186 | ); 187 | } 188 | 189 | renderOverlay() { 190 | const { 191 | hideOverlay, 192 | renderOverlay, 193 | overlayBackgroundColor, 194 | width, 195 | beautify, 196 | } = this.props; 197 | const fontSize = `${3 * (width / 100)}%`; 198 | 199 | if (hideOverlay) { 200 | return false; 201 | } 202 | 203 | return [ 204 |
, 209 |
214 | {renderOverlay()} 215 |
, 216 | ]; 217 | } 218 | 219 | renderCountOverlay(more) { 220 | const { images, width, beautify } = this.props; 221 | const { countFrom } = this.state; 222 | const extra = images.length - (countFrom && countFrom > 5 ? 5 : countFrom); 223 | const fontSize = `${7 * (width / 100)}%`; 224 | 225 | return [ 226 | more && ( 227 |
231 | ), 232 | more && ( 233 |
234 |

+{extra}

235 |
236 | ), 237 | ]; 238 | } 239 | 240 | render() { 241 | const { modal, index, countFrom } = this.state; 242 | const { images, width } = this.props; 243 | const imagesToShow = [...images]; 244 | 245 | if (countFrom && images.length > countFrom) { 246 | imagesToShow.length = countFrom; 247 | } 248 | 249 | return ( 250 |
257 | {[1, 3, 4].includes(imagesToShow.length) && this.renderOne()} 258 | {imagesToShow.length >= 2 && 259 | imagesToShow.length !== 4 && 260 | this.renderTwo()} 261 | {imagesToShow.length >= 4 && this.renderThree()} 262 | 263 | {modal && ( 264 | 265 | )} 266 |
267 | ); 268 | } 269 | } 270 | 271 | Images.propTypes = { 272 | beautify: PropTypes.bool, 273 | countFrom: PropTypes.number, 274 | hideOverlay: PropTypes.bool, 275 | onClickEach: PropTypes.func, 276 | overlayBackgroundColor: PropTypes.string, 277 | renderOverlay: PropTypes.func, 278 | upperHeight: PropTypes.number, 279 | width: PropTypes.number, 280 | }; 281 | 282 | export default Images; 283 | -------------------------------------------------------------------------------- /src/react-fb-image-grid/components/Modal.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Lightbox from 'react-image-lightbox'; 3 | import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app 4 | 5 | class ModalComponent extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | currentImageIndex: props.index, 10 | images: props.images || [], 11 | }; 12 | 13 | this.onMovePrevRequest = this.onMovePrevRequest.bind(this); 14 | this.onMoveNextRequest = this.onMoveNextRequest.bind(this); 15 | } 16 | 17 | onMovePrevRequest() { 18 | const { currentImageIndex, images } = this.state; 19 | 20 | this.setState({ 21 | currentImageIndex: 22 | (currentImageIndex + images.length - 1) % images.length, 23 | }); 24 | } 25 | 26 | onMoveNextRequest() { 27 | const { currentImageIndex, images } = this.state; 28 | 29 | this.setState({ 30 | currentImageIndex: (currentImageIndex + 1) % images.length, 31 | }); 32 | } 33 | 34 | render() { 35 | const { images, currentImageIndex } = this.state; 36 | const { onClose } = this.props; 37 | 38 | return ( 39 | 49 | ); 50 | } 51 | } 52 | 53 | export default ModalComponent; 54 | -------------------------------------------------------------------------------- /src/react-fb-image-grid/css/style.css: -------------------------------------------------------------------------------- 1 | @import 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'; 2 | @import 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css'; 3 | 4 | html, 5 | body, 6 | #root, 7 | .App { 8 | height: 100%; 9 | } 10 | 11 | /* Images Component CSS */ 12 | 13 | .react-fb-image-grid { 14 | margin: auto; 15 | } 16 | 17 | .react-fb-image-grid * { 18 | margin: 0; 19 | box-sizing: border-box; 20 | padding: 0; 21 | /* cursor: pointer; */ 22 | } 23 | 24 | .col-md-4 { 25 | width: 33.33333333%; 26 | } 27 | 28 | .border { 29 | border: none; 30 | border-radius: 0; 31 | } 32 | 33 | .background { 34 | background-size: cover !important; 35 | background-position: center !important; 36 | background-repeat: no-repeat !important; 37 | } 38 | 39 | .height-one { 40 | height: 100%; 41 | width: 100% !important; 42 | } 43 | 44 | .height-two { 45 | height: 65%; 46 | width: 100% !important; 47 | } 48 | 49 | .cover { 50 | background-color: #222; 51 | opacity: 0.8; 52 | position: absolute; 53 | right: 0; 54 | top: 0; 55 | left: 0; 56 | bottom: 0; 57 | } 58 | 59 | .cover-text { 60 | right: 0; 61 | left: 0; 62 | bottom: 0; 63 | color: white; 64 | font-size: 1.2em !important; 65 | position: absolute; 66 | top: 50%; 67 | -webkit-transform: translate(0%, -50%); 68 | -ms-transform: translate(0%, -50%); 69 | transform: translate(0%, -50%); 70 | text-align: center; 71 | } 72 | 73 | .cover-text > p { 74 | margin: 0; 75 | position: absolute; 76 | font-size: 1.5em !important; 77 | top: 50%; 78 | left: 50%; 79 | transform: translate(-50%, -50%); 80 | } 81 | 82 | .slide { 83 | height: 0; 84 | bottom: 100%; 85 | transition: 0.4s ease; 86 | overflow: hidden; 87 | } 88 | 89 | .border:hover .slide { 90 | bottom: 0; 91 | height: auto; 92 | } 93 | 94 | .border:hover .animate-text { 95 | top: 62%; 96 | } 97 | 98 | .beautify { 99 | border: 2px solid white; 100 | border-radius: 6px; 101 | } 102 | 103 | .cover-beautify { 104 | border-radius: 6px; 105 | } 106 | -------------------------------------------------------------------------------- /src/react-fb-image-grid/index.js: -------------------------------------------------------------------------------- 1 | import './css/style.css'; 2 | import FbGridImages from './components/Images'; 3 | 4 | export default FbGridImages; 5 | --------------------------------------------------------------------------------