├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── src ├── App.css ├── App.js ├── App.test.js ├── EmojiResultRow.css ├── EmojiResultRow.js ├── EmojiResults.css ├── EmojiResults.js ├── Header.css ├── Header.js ├── SearchInput.css ├── SearchInput.js ├── emojiList.json ├── filterEmoji.js ├── index.css ├── index.js └── logo.svg └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://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 | # misc 13 | .DS_Store 14 | npm-debug.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Andrew H Farmer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Emoji Search 2 | --- 3 | 4 | Created with *create-react-app*. See the [full create-react-app guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md). 5 | 6 | 7 | 8 | Install 9 | --- 10 | 11 | `npm install` 12 | 13 | 14 | 15 | Usage 16 | --- 17 | 18 | `npm start` 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emoji-search", 3 | "version": "0.1.0", 4 | "license": "MIT", 5 | "homepage": "http://ahfarmer.github.io/emoji-search", 6 | "devDependencies": { 7 | "gh-pages": "^2.0.1", 8 | "prettier": "^1.17.1", 9 | "react-scripts": "^3.0.1" 10 | }, 11 | "dependencies": { 12 | "clipboard": "^2.0.4", 13 | "github-fork-ribbon-css": "^0.2.1", 14 | "react": "^16.8.6", 15 | "react-dom": "^16.8.6" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test --env=jsdom", 21 | "eject": "react-scripts eject", 22 | "deploy": "gh-pages -d build" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewagain/emoji-search/609bda65d274fdc0f8b7f73ec2f2025c4d58d49f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Emoji Search 9 | 10 | 11 | 14 |
15 | 19 | Fork me on GitHub 20 | 21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Emoji Search", 3 | "name": "Emoji Search Example App", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import Header from "./Header"; 3 | import SearchInput from "./SearchInput"; 4 | import EmojiResults from "./EmojiResults"; 5 | import filterEmoji from "./filterEmoji"; 6 | 7 | export default class App extends PureComponent { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | filteredEmoji: filterEmoji("", 20) 12 | }; 13 | } 14 | 15 | handleSearchChange = event => { 16 | this.setState({ 17 | filteredEmoji: filterEmoji(event.target.value, 20) 18 | }); 19 | }; 20 | 21 | render() { 22 | return ( 23 |
24 |
25 | 26 | 27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | 5 | it("renders without crashing", () => { 6 | const div = document.createElement("div"); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /src/EmojiResultRow.css: -------------------------------------------------------------------------------- 1 | .component-emoji-result-row { 2 | border-bottom: 1px solid #ccc; 3 | padding: 10px; 4 | height: 32px; 5 | position: relative; 6 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 7 | cursor: pointer; 8 | } 9 | 10 | .component-emoji-result-row:hover { 11 | background-color: #eee; 12 | } 13 | 14 | .component-emoji-result-row img { 15 | width: 32px; 16 | height: 32px; 17 | padding-right: 10px; 18 | } 19 | 20 | .component-emoji-result-row .title { 21 | position: relative; 22 | top: -8px; 23 | } 24 | 25 | .component-emoji-result-row .info { 26 | float: right; 27 | position: relative; 28 | top: 8px; 29 | right: 10px; 30 | color: #ccc; 31 | display: none; 32 | } 33 | 34 | .component-emoji-result-row:hover .info { 35 | display: inline-block; 36 | } 37 | -------------------------------------------------------------------------------- /src/EmojiResultRow.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import PropTypes from "prop-types"; 3 | import "./EmojiResultRow.css"; 4 | 5 | export default class EmojiResultsRow extends PureComponent { 6 | static propTypes = { 7 | title: PropTypes.string, 8 | symbol: PropTypes.string 9 | }; 10 | 11 | render() { 12 | const codePointHex = this.props.symbol.codePointAt(0).toString(16); 13 | const src = `//cdn.jsdelivr.net/emojione/assets/png/${codePointHex}.png`; 14 | return ( 15 |
19 | {this.props.title} 20 | {this.props.title} 21 | Click to copy emoji 22 |
23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/EmojiResults.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewagain/emoji-search/609bda65d274fdc0f8b7f73ec2f2025c4d58d49f/src/EmojiResults.css -------------------------------------------------------------------------------- /src/EmojiResults.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import PropTypes from "prop-types"; 3 | import Clipboard from "clipboard"; 4 | 5 | import EmojiResultRow from "./EmojiResultRow"; 6 | import "./EmojiResults.css"; 7 | 8 | export default class EmojiResults extends PureComponent { 9 | static propTypes = { 10 | emojiData: PropTypes.array 11 | }; 12 | 13 | componentDidMount() { 14 | this.clipboard = new Clipboard(".copy-to-clipboard"); 15 | } 16 | 17 | componentWillUnmount() { 18 | this.clipboard.destroy(); 19 | } 20 | 21 | render() { 22 | return ( 23 |
24 | {this.props.emojiData.map(emojiData => ( 25 | 30 | ))} 31 |
32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Header.css: -------------------------------------------------------------------------------- 1 | .component-header { 2 | padding: 15px; 3 | position: relative; 4 | font-weight: normal; 5 | font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; 6 | font-size: 32px; 7 | text-align: center; 8 | color: #333; 9 | } 10 | 11 | .component-header img { 12 | position: relative; 13 | top: 6px; 14 | padding: 0 14px; 15 | } 16 | -------------------------------------------------------------------------------- /src/Header.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import "./Header.css"; 3 | 4 | export default class Header extends PureComponent { 5 | render() { 6 | return ( 7 |
8 | 14 | Emoji Search 15 | 21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/SearchInput.css: -------------------------------------------------------------------------------- 1 | .component-search-input { 2 | border-bottom: 1px solid #ccc; 3 | } 4 | 5 | .component-search-input > div { 6 | margin: 0 10px 10px 10px; 7 | } 8 | 9 | .component-search-input input { 10 | border-radius: 4px; 11 | border: 1px solid #bbb; 12 | box-sizing: border-box; 13 | font-size: 18px; 14 | padding: 10px 8px; 15 | width: 100%; 16 | } 17 | -------------------------------------------------------------------------------- /src/SearchInput.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | import "./SearchInput.css"; 5 | 6 | export default class SearchInput extends PureComponent { 7 | static propTypes = { 8 | textChange: PropTypes.func 9 | }; 10 | 11 | handleChange = event => { 12 | this.props.textChange(event); 13 | }; 14 | 15 | render() { 16 | return ( 17 |
18 |
19 | 20 |
21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/filterEmoji.js: -------------------------------------------------------------------------------- 1 | import emojiList from "./emojiList.json"; 2 | 3 | export default function filterEmoji(searchText, maxResults) { 4 | return emojiList 5 | .filter(emoji => { 6 | if (emoji.title.toLowerCase().includes(searchText.toLowerCase())) { 7 | return true; 8 | } 9 | if (emoji.keywords.includes(searchText)) { 10 | return true; 11 | } 12 | return false; 13 | }) 14 | .slice(0, maxResults); 15 | } 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | body .github-fork-ribbon:before { 8 | background-color: #333; 9 | } 10 | 11 | @media screen and (max-width: 500px) { 12 | .github-fork-ribbon { 13 | display: none; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | import "github-fork-ribbon-css/gh-fork-ribbon.css"; 6 | 7 | ReactDOM.render(, document.getElementById("root")); 8 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | --------------------------------------------------------------------------------