├── .gitignore ├── README.md ├── dark-theme.png ├── data ├── emoji.json ├── twemoji.json └── twemoji.svg ├── deploy.sh ├── dist ├── Emoji.css ├── EmojiPicker.css ├── cjs │ ├── Emoji.css │ ├── Emoji.js │ ├── Emoji.js.map │ ├── EmojiPicker.css │ ├── EmojiPicker.js │ ├── EmojiPicker.js.map │ ├── EmojiPicker │ │ ├── Footer.js │ │ ├── Footer.js.map │ │ ├── Navbar.js │ │ ├── Navbar.js.map │ │ ├── Scroll.js │ │ └── Scroll.js.map │ ├── index.js │ ├── index.js.map │ ├── twemoji.svg │ ├── utils.js │ └── utils.js.map ├── esm │ ├── Emoji.css │ ├── Emoji.js │ ├── Emoji.js.map │ ├── EmojiPicker.css │ ├── EmojiPicker.js │ ├── EmojiPicker.js.map │ ├── EmojiPicker │ │ ├── Footer.js │ │ ├── Footer.js.map │ │ ├── Navbar.js │ │ ├── Navbar.js.map │ │ ├── Scroll.js │ │ └── Scroll.js.map │ ├── index.js │ ├── index.js.map │ ├── twemoji.svg │ ├── utils.js │ └── utils.js.map └── types │ ├── Emoji.d.ts │ ├── Emoji.d.ts.map │ ├── EmojiPicker.d.ts │ ├── EmojiPicker.d.ts.map │ ├── EmojiPicker │ ├── Footer.d.ts │ ├── Footer.d.ts.map │ ├── Navbar.d.ts │ ├── Navbar.d.ts.map │ ├── Scroll.d.ts │ └── Scroll.d.ts.map │ ├── index.d.ts │ ├── index.d.ts.map │ ├── utils.d.ts │ └── utils.d.ts.map ├── index.html ├── light-theme.png ├── package-lock.json ├── package.json ├── public ├── .nojekyll ├── favicon.ico └── robots.txt ├── scripts ├── json.js ├── sprite.js └── utils.js ├── src ├── Emoji.css ├── Emoji.tsx ├── EmojiPicker.css ├── EmojiPicker.tsx ├── EmojiPicker │ ├── Footer.tsx │ ├── Navbar.tsx │ └── Scroll.tsx ├── index.ts ├── static.d.ts ├── twemoji.svg └── utils.ts ├── tsconfig.json ├── vercel.json ├── vite.config.js └── website ├── index.css └── index.tsx /.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | build 3 | web_modules 4 | node_modules 5 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
React Twemoji Picker is an emoji component 3 |
made for fast show-and-scroll and filtering 4 |
demo 5 |
image of emoji picker 6 |
image of emoji picker 7 |
8 | 9 | To do this, we virtualize emoji elements with [`react-window`](https://github.com/bvaughn/react-window) 10 | and [`react-window-infinite-loader`](), meaning elements are not rendered into the DOM until they 11 | are visible through the scroll viewport. This allows [`react-twemoji-picker`](https://github.com/BrianHung/EmojiPicker) to be used with input or contenteditable components which require fast responsivity. 12 | 13 | Original svg sources for emoji spritesheet comes from Twitter's [`twemoji`](https://github.com/twitter/twemoji) library. 😊 14 | 15 | ## Installation 16 | 17 | ```bash 18 | npm install --save github:brianhung/emojipicker 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```js 24 | import { EmojiPicker } from 'react-twemoji-picker'; 25 | import EmojiData from "react-twemoji-picker/data/twemoji.json"; 26 | import "react-twemoji-picker/dist/EmojiPicker.css" 27 | 28 | const emojiData = Object.freeze(EmojiData); 29 | const handleEmojiSelect = (emoji: EmojiObject) => console.log(emoji); 30 | 31 | 32 | ``` 33 | 34 | If you want to programatically get or set internal state (e.g. `search`), you have to use `EmojiPickertRef` 35 | since `EmojiPicker` is a functional component. As an example, 36 | 37 | ```jsx 38 | import { EmojiPicker, EmojiPickerRef } from 'react-twemoji-picker'; 39 | const ref = React.createRef() 40 | const handleSearch = (query: string) => ref.current.search(query); 41 | 42 | handleSearch(event.target.value)} placeholder="search"> 43 | ``` 44 | 45 | To see an example, look at the source code for the demo. 46 | 47 | ### Props 48 | 49 | | prop | default | description | 50 | |:-----|:--------|:------------| 51 | | emojiData: Record | `{}` | map of categories to list of emoji objects | 52 | | emojiSize?: number | `36` | pixel size of an emoji | 53 | | numberScrollRows?: number | `12` | number of rows in the scroll element | 54 | | onEmojiSelect?: (emoji: EmojiObject, event: KeyboardEvent | MouseEvent) => void, | `(emoji: EmojiObject) => console.log(emoji)` | handle emoji click or enter key here | 55 | | showNavbar?: boolean; | `false` | allows navigation to categories | 56 | | showFooter?: boolean; | `false` | show focused emoji and its name | 57 | | showScroll?: boolean; | `true` | turn off if query is always not null | 58 | | emojisPerRow?: number; | `9` | number of emojis to show per row | 59 | | onKeyDownScroll?: Function; | `(event) => null` | handle additional key events like 'ctrl-c' here | 60 | | collapseCategoriesOnSearch?: boolean; | `true` | merge categories into single 'search results' category | 61 | | collapseHeightOnSearch?: boolean; | `true` | scroll height changes with number of emojis | 62 | | theme?: "system", "light", "dark" | `"system"` | css theme | -------------------------------------------------------------------------------- /dark-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrianHung/EmojiPicker/d047c8380bbdbda5b727ea1fa5402d3bdbc6a825/dark-theme.png -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # abort on errors 4 | set -e 5 | 6 | # build 7 | npm run build:website 8 | 9 | # navigate into the build output directory 10 | cd dist 11 | 12 | # if you are deploying to a custom domain 13 | # echo 'www.example.com' > CNAME 14 | 15 | git init 16 | git add -A 17 | git commit -m 'deploy' 18 | 19 | # if you are deploying to https://.github.io 20 | # git push -f git@github.com:/.github.io.git master 21 | 22 | # if you are deploying to https://.github.io/ 23 | git push -f https://github.com/brianhung/EmojiPicker.git master:gh-pages 24 | 25 | cd - -------------------------------------------------------------------------------- /dist/Emoji.css: -------------------------------------------------------------------------------- 1 | /* https://github.com/twitter/twemoji#inline-styles */ 2 | .emoji-picker-emoji-inline { 3 | height: 1em; 4 | width: 1em; 5 | margin: 0 .05em 0 .1em; 6 | vertical-align: -0.1em; 7 | } -------------------------------------------------------------------------------- /dist/EmojiPicker.css: -------------------------------------------------------------------------------- 1 | .emoji-picker { 2 | display: flex; 3 | flex-direction: column; 4 | border-radius: 3px; 5 | background: white; 6 | border: 1px solid #E5E5E5; 7 | contain: content; 8 | } 9 | 10 | .emoji-picker .emoji-picker-scroll { 11 | -webkit-overflow-scrolling: touch; 12 | } 13 | 14 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-title { 15 | padding: 0 0.75em; 16 | text-transform: uppercase; 17 | font-weight: 500; 18 | font-size: 16px; 19 | color: #A3A3A3; 20 | user-select: none; 21 | height: 100%; 22 | display: flex; 23 | align-items: center; 24 | } 25 | 26 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-emoji { 27 | padding: 0 0.50em; 28 | display: flex; 29 | list-style-type: none; 30 | margin: 0; 31 | height: 100%; 32 | } 33 | 34 | .emoji-picker .emoji-picker-emoji { 35 | display: inline-block; 36 | user-select: none; 37 | cursor: pointer; 38 | width: 28px; 39 | height: 28px; 40 | margin: 0; 41 | padding: 4px; 42 | border-radius: 3px; 43 | flex-shrink: 0; 44 | box-sizing: content-box; 45 | } 46 | 47 | .emoji-picker .emoji-picker-emoji-focused, 48 | .emoji-picker .emoji-picker-scroll .emoji-picker-emoji:hover, 49 | .emoji-picker .emoji-picker-navbar .emoji-picker-emoji:hover { 50 | background: #E5E5E5; 51 | } 52 | 53 | .emoji-picker .emoji-picker-category-emoji > li:active .emoji-picker-emoji { 54 | background: #D4D4D4; 55 | } 56 | 57 | .emoji-picker .emoji-picker-navbar { 58 | display: flex; 59 | height: fit-content; 60 | flex-direction: row; 61 | justify-content: space-evenly; 62 | border-bottom: 1px solid #E5E5E5; 63 | padding: 0.25em 9px; 64 | } 65 | 66 | .emoji-picker .emoji-picker-navbar .emoji-picker-navbar-category { 67 | appearance: none; 68 | background-color: inherit; 69 | margin: 0; 70 | padding: 0; 71 | border: none; 72 | height: 36px; 73 | } 74 | 75 | .emoji-picker .emoji-picker-footer { 76 | display: flex; 77 | flex-flow: row; 78 | align-items: center; 79 | border-top: 1px solid #E5E5E5; 80 | user-select: none; 81 | } 82 | 83 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji { 84 | width: 2.5em; 85 | height: 2.5em; 86 | padding: 0.50em; 87 | cursor: inherit; 88 | } 89 | 90 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji:active { 91 | background: inherit !important; 92 | } 93 | 94 | .emoji-picker .emoji-picker-footer .emoji-picker-name { 95 | text-align: left; 96 | padding: 0 0.25em; 97 | } 98 | 99 | /* DARK THEME */ 100 | 101 | .emoji-picker.emoji-picker-dark { 102 | background: #404040; 103 | color: white; 104 | } 105 | .emoji-picker.emoji-picker-dark, .emoji-picker.emoji-picker-dark .emoji-picker-navbar, .emoji-picker.emoji-picker-dark .emoji-picker-footer { 106 | border-color: #404040; 107 | } 108 | .emoji-picker.emoji-picker-dark .emoji-picker-category-title { 109 | color: #D4D4D4; 110 | } 111 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji-focused, 112 | .emoji-picker.emoji-picker-dark .emoji-picker-scroll .emoji-picker-emoji:hover, 113 | .emoji-picker.emoji-picker-dark .emoji-picker-navbar .emoji-picker-emoji:hover { 114 | background: #737373; 115 | } 116 | .emoji-picker.emoji-picker-dark .emoji-picker-category-emoji > li:active .emoji-picker-emoji, 117 | .emoji-picker.emoji-picker-dark .emoji-picker-navbar-category:active .emoji-picker-emoji { 118 | background: #A3A3A3; 119 | } 120 | 121 | @media (prefers-color-scheme: dark) { 122 | .emoji-picker.emoji-picker-system { 123 | background: #404040; 124 | color: white; 125 | } 126 | .emoji-picker.emoji-picker-system, .emoji-picker.emoji-picker-system .emoji-picker-navbar, .emoji-picker.emoji-picker-system .emoji-picker-footer { 127 | border-color: #404040; 128 | } 129 | .emoji-picker.emoji-picker-system .emoji-picker-category-title { 130 | color: #D4D4D4; 131 | } 132 | .emoji-picker.emoji-picker-system .emoji-picker-emoji-focused, 133 | .emoji-picker.emoji-picker-system .emoji-picker-scroll .emoji-picker-emoji:hover, 134 | .emoji-picker.emoji-picker-system .emoji-picker-navbar .emoji-picker-emoji:hover { 135 | background: #737373; 136 | } 137 | .emoji-picker.emoji-picker-system .emoji-picker-category-emoji > li:active .emoji-picker-emoji, 138 | .emoji-picker.emoji-picker-system .emoji-picker-navbar-category:active .emoji-picker-emoji { 139 | background: #A3A3A3; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /dist/cjs/Emoji.css: -------------------------------------------------------------------------------- 1 | /* https://github.com/twitter/twemoji#inline-styles */ 2 | .emoji-picker-emoji-inline { 3 | height: 1em; 4 | width: 1em; 5 | margin: 0 .05em 0 .1em; 6 | vertical-align: -0.1em; 7 | } -------------------------------------------------------------------------------- /dist/cjs/Emoji.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __rest = (this && this.__rest) || function (s, e) { 3 | var t = {}; 4 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 5 | t[p] = s[p]; 6 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 7 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 8 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 9 | t[p[i]] = s[p[i]]; 10 | } 11 | return t; 12 | }; 13 | var __importDefault = (this && this.__importDefault) || function (mod) { 14 | return (mod && mod.__esModule) ? mod : { "default": mod }; 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.Emoji = void 0; 18 | const react_1 = __importDefault(require("react")); 19 | const utils_1 = require("./utils"); 20 | const twemoji_svg_1 = __importDefault(require("./twemoji.svg")); 21 | const Emoji = (_a) => { 22 | var { emoji, className } = _a, props = __rest(_a, ["emoji", "className"]); 23 | className = className ? `emoji-picker-emoji ${className}` : `emoji-picker-emoji`; 24 | return (react_1.default.createElement("img", Object.assign({ className: className, "data-unicode": emoji.unicode, alt: (0, utils_1.unifiedToNative)(emoji.unicode), src: `${twemoji_svg_1.default}#${emoji.unicode}`, draggable: "false", "aria-label": emoji.name }, props))); 25 | }; 26 | exports.Emoji = Emoji; 27 | exports.default = Emoji; 28 | //# sourceMappingURL=Emoji.js.map -------------------------------------------------------------------------------- /dist/cjs/Emoji.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Emoji.js","sourceRoot":"","sources":["../../src/Emoji.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,kDAAkC;AAClC,mCAAsD;AACtD,gEAAmC;AAQnC,MAAM,KAAK,GAAmB,CAAC,EAA4B,EAAE,EAAE;QAAhC,EAAC,KAAK,EAAE,SAAS,OAAW,EAAN,KAAK,cAA3B,sBAA4B,CAAD;IACxD,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAA;IAChF,OAAO,CACL,qDACE,SAAS,EAAE,SAAS,kBACN,KAAK,CAAC,OAAO,EAC3B,GAAG,EAAE,IAAA,uBAAe,EAAC,KAAK,CAAC,OAAO,CAAC,EACnC,GAAG,EAAE,GAAG,qBAAO,IAAI,KAAK,CAAC,OAAO,EAAE,EAClC,SAAS,EAAC,OAAO,gBACL,KAAK,CAAC,IAAI,IAClB,KAAK,EACT,CACH,CAAA;AACH,CAAC,CAAA;AAEoB,sBAAK;AAC1B,kBAAe,KAAK,CAAC"} -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker.css: -------------------------------------------------------------------------------- 1 | .emoji-picker { 2 | display: flex; 3 | flex-direction: column; 4 | border-radius: 3px; 5 | background: white; 6 | border: 1px solid #E1E1E0; 7 | overflow: hidden; 8 | } 9 | 10 | .emoji-picker .emoji-picker-scroll { 11 | overflow-y: hidden; 12 | -webkit-overflow-scrolling: touch; 13 | display: inline-block; 14 | outline: none; 15 | } 16 | 17 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-title { 18 | padding: 8px 0.75em; 19 | text-transform: uppercase; 20 | text-align: left; 21 | font-weight: 500; 22 | font-size: 16px; 23 | color: rgba(55, 53, 47, 0.6); 24 | background: white; 25 | user-select: none; 26 | } 27 | 28 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-emoji { 29 | padding: 0em 0.50em; 30 | display: flex; 31 | list-style-type: none; 32 | margin: 0; 33 | } 34 | 35 | .emoji-picker .emoji-picker-emoji { 36 | display: inline-block; 37 | user-select: none; 38 | cursor: pointer; 39 | width: 28px; 40 | height: 28px; 41 | margin: 0; 42 | padding: 4px; 43 | border-radius: 3px; 44 | flex-shrink: 0; 45 | } 46 | 47 | .emoji-picker .emoji-picker-emoji-focused { 48 | background: rgba(55, 53, 47, 0.15); 49 | } 50 | 51 | .emoji-picker .emoji-picker-emoji:active { 52 | background: rgba(55, 53, 47, 0.25); 53 | } 54 | 55 | .emoji-picker .emoji-picker-emoji-img { 56 | height: 100%; 57 | width: 100%; 58 | } 59 | 60 | .emoji-picker .emoji-picker-navbar { 61 | display: flex; 62 | height: fit-content; 63 | flex-direction: row; 64 | justify-content: space-evenly; 65 | border-bottom: 1px solid #E1E1E0; 66 | padding: 0.25em 9px; 67 | } 68 | 69 | .emoji-picker .emoji-picker-navbar .emoji-picker-navbar-category { 70 | appearance: none; 71 | padding: 0; 72 | border: none; 73 | background-color: inherit; 74 | } 75 | 76 | .emoji-picker .emoji-picker-footer { 77 | display: flex; 78 | flex-flow: row; 79 | align-items: center; 80 | border-top: 1px solid #E1E1E0; 81 | user-select: none; 82 | } 83 | 84 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji { 85 | width: 2.5em; 86 | height: 2.5em; 87 | padding: 0.50em; 88 | cursor: inherit; 89 | } 90 | 91 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji:active { 92 | background: inherit; 93 | } 94 | 95 | .emoji-picker .emoji-picker-footer .emoji-picker-name { 96 | text-align: left; 97 | padding: 0 0.25em; 98 | } 99 | 100 | /* DARK THEME */ 101 | 102 | .emoji-picker.emoji-picker-dark { 103 | background: rgb(63, 68, 71); 104 | color: #ffffff; 105 | } 106 | .emoji-picker.emoji-picker-dark, .emoji-picker.emoji-picker-dark .emoji-picker-navbar, .emoji-picker.emoji-picker-dark .emoji-picker-footer { 107 | border-color: rgb(63, 68, 71); 108 | } 109 | .emoji-picker.emoji-picker-dark .emoji-picker-category-title { 110 | color: rgba(255, 255, 255, 0.6); 111 | background-color: rgb(63, 68, 71); 112 | } 113 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji-focused { 114 | background: rgba(225, 225, 224, 0.25); 115 | } 116 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji:active { 117 | background: rgba(225, 225, 224, 0.50); 118 | } 119 | 120 | @media (prefers-color-scheme: dark) { 121 | .emoji-picker.emoji-picker-system { 122 | background: rgb(63, 68, 71); 123 | color: white; 124 | } 125 | .emoji-picker.emoji-picker-system, .emoji-picker.emoji-picker-system .emoji-picker-navbar, .emoji-picker.emoji-picker-system .emoji-picker-footer { 126 | border-color: rgb(63, 68, 71); 127 | } 128 | .emoji-picker.emoji-picker-system .emoji-picker-category-title { 129 | color: rgba(255, 255, 255, 0.6); 130 | background-color: rgb(63, 68, 71); 131 | } 132 | .emoji-picker.emoji-picker-system .emoji-picker-emoji-focused { 133 | background: rgba(225, 225, 224, 0.25); 134 | } 135 | .emoji-picker.emoji-picker-system .emoji-picker-emoji:active { 136 | background: rgba(225, 225, 224, 0.50); 137 | } 138 | } -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 10 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 11 | }) : function(o, v) { 12 | o["default"] = v; 13 | }); 14 | var __importStar = (this && this.__importStar) || function (mod) { 15 | if (mod && mod.__esModule) return mod; 16 | var result = {}; 17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 18 | __setModuleDefault(result, mod); 19 | return result; 20 | }; 21 | var __importDefault = (this && this.__importDefault) || function (mod) { 22 | return (mod && mod.__esModule) ? mod : { "default": mod }; 23 | }; 24 | Object.defineProperty(exports, "__esModule", { value: true }); 25 | exports.EmojiPicker = void 0; 26 | const react_1 = __importStar(require("react")); 27 | const utils_1 = require("./utils"); 28 | const Navbar_1 = __importDefault(require("./EmojiPicker/Navbar")); 29 | const Footer_1 = __importDefault(require("./EmojiPicker/Footer")); 30 | const Scroll_1 = __importDefault(require("./EmojiPicker/Scroll")); 31 | function EmojiPickerReducer({ emojiData }) { 32 | return (prevState, nextState) => { 33 | var _a, _b, _c; 34 | if (nextState.searchEmojis && prevState.searchEmojis != nextState.searchEmojis) { 35 | let emojis = (((_a = nextState.searchEmojis) === null || _a === void 0 ? void 0 : _a.query) && ((_b = nextState.searchEmojis) === null || _b === void 0 ? void 0 : _b.emojis)) || emojiData, category = emojis[Object.keys(emojis)[0]]; 36 | let emoji = category[0]; 37 | nextState.focusedEmoji = { row: 1, emoji, focusOnRender: Boolean((_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.closest(".emoji-picker-scroll")), preventScroll: false }; 38 | } 39 | return Object.assign(Object.assign({}, prevState), nextState); 40 | }; 41 | } 42 | function EmojiPickerRefComponent({ emojiData = {}, emojiSize = 36, numberScrollRows = 12, onEmojiSelect = (emoji) => console.log(emoji), showNavbar = false, showFooter = false, showScroll = true, emojisPerRow = 9, onKeyDownScroll = (event) => null, collapseCategoriesOnSearch = true, collapseHeightOnSearch = true, theme = "system", emojiPreviewName = (emoji) => emoji.name }, ref) { 43 | var _a, _b; 44 | const pickerStateReducer = (0, react_1.useCallback)(EmojiPickerReducer({ emojiData }), [emojiData]); 45 | const [pickerState, setPickerState] = (0, react_1.useReducer)(pickerStateReducer, { 46 | searchEmojis: { emojis: null, query: "" }, 47 | focusedEmoji: { row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } 48 | }); 49 | const { itemCount, itemRanges } = (0, react_1.useMemo)(() => (0, utils_1.calcCountAndRange)(pickerState.searchEmojis.emojis || emojiData, emojisPerRow), [pickerState.searchEmojis, emojisPerRow]); 50 | const search = (query) => { 51 | var _a; 52 | const { searchEmojis } = pickerState; 53 | if (!query) 54 | return setPickerState({ 55 | searchEmojis: { emojis: null, query: "" }, 56 | focusedEmoji: { row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } 57 | }); 58 | if ((searchEmojis === null || searchEmojis === void 0 ? void 0 : searchEmojis.emojis) && !Object.values(searchEmojis.emojis).flat().length && searchEmojis.query.length < query.length) 59 | return setPickerState({ searchEmojis: { emojis: searchEmojis.emojis, query } }); 60 | const index = query.length > searchEmojis.query.length && searchEmojis.emojis != null 61 | ? Object.values(searchEmojis.emojis).flat() 62 | : Object.values(emojiData).flat(); 63 | let results = index 64 | .map(emoji => ({ emoji, score: (emoji.keywords || []).map(word => word.indexOf(query) != -1).reduce((a, b) => a + Number(b), Number(emoji.name.indexOf(query) != -1) * 3) })) 65 | .filter(a => a.score) 66 | .sort((a, b) => b.score - a.score) 67 | .map(({ emoji }) => emoji); 68 | if (collapseCategoriesOnSearch) { 69 | return setPickerState({ searchEmojis: { emojis: { "Search Results": results }, query } }); 70 | } 71 | else { 72 | let grouped = Object.entries(emojiData).map(([category, list]) => ([category, list.filter(emoji => results.includes(emoji))])).reduce((sum, [category, list]) => Object.assign(sum, { [category]: list }), {}); 73 | return setPickerState({ searchEmojis: { emojis: grouped, query } }); 74 | } 75 | }; 76 | const refVirtualList = (0, react_1.useRef)(null); 77 | const refScroll = (0, react_1.useRef)(null); 78 | const handleClickInScroll = (emoji, row) => (event) => { 79 | event.preventDefault(); 80 | onEmojiSelect(emoji, event); 81 | setPickerState({ focusedEmoji: { row, emoji, focusOnRender: true, preventScroll: true } }); 82 | }; 83 | const handleMouseInScroll = (emoji, row) => (event) => { 84 | var _a; 85 | if (emoji == ((_a = pickerState.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji) || event.movementX == 0 && event.movementY == 0) 86 | return; 87 | event.preventDefault(); 88 | const isSafari = window.safari !== undefined; 89 | setPickerState({ focusedEmoji: { row, emoji, focusOnRender: true, preventScroll: true } }); 90 | isSafari && refScroll.current && refScroll.current.focus(); 91 | }; 92 | const handleKeyDownScroll = (event) => { 93 | var _a, _b, _c, _d, _e, _f, _g, _h; 94 | const { searchEmojis, focusedEmoji } = pickerState; 95 | const emojis = Object.values(searchEmojis.emojis || emojiData).filter(array => array.length !== 0); 96 | switch (event.key) { 97 | case "Enter": { 98 | event.preventDefault(); 99 | if (!focusedEmoji) { 100 | let emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 101 | emoji && setPickerState({ focusedEmoji: { row: 1, emoji, focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } }); 102 | } 103 | else { 104 | focusedEmoji.emoji && onEmojiSelect(focusedEmoji.emoji, event); 105 | } 106 | return; 107 | } 108 | case 'Home': { 109 | event.preventDefault(); 110 | let emoji = undefined, row = undefined; 111 | let emojis = searchEmojis.emojis || emojiData, category = emojis[Object.keys(emojis)[0]]; 112 | emoji = category[0]; 113 | row = 1; 114 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_b = document.activeElement) === null || _b === void 0 ? void 0 : _b.closest(".emoji-picker-scroll")), preventScroll: false } }); 115 | } 116 | case 'End': { 117 | event.preventDefault(); 118 | let emoji = undefined, row = undefined; 119 | let emojis = searchEmojis.emojis || emojiData, category = emojis[Object.keys(emojis).pop()]; 120 | emoji = category[category.length - 1]; 121 | row = ((_c = itemRanges[itemRanges.length - 1]) === null || _c === void 0 ? void 0 : _c.to) - 1; 122 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_d = document.activeElement) === null || _d === void 0 ? void 0 : _d.closest(".emoji-picker-scroll")), preventScroll: false } }); 123 | } 124 | case "ArrowUp": { 125 | event.preventDefault(); 126 | let emoji = undefined, row = undefined; 127 | if (!focusedEmoji) { 128 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 129 | row = 1; 130 | } 131 | else { 132 | let arrayIndex, arrayEmoji, emojiIndex; 133 | emojis.find((array, index) => { 134 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 135 | return emojiIndex !== -1; 136 | }); 137 | if (emojiIndex != undefined) { 138 | if (emojiIndex - emojisPerRow >= 0) { 139 | emoji = arrayEmoji[emojiIndex - emojisPerRow]; 140 | row = focusedEmoji.row - 1; 141 | } 142 | else if (arrayIndex !== 0) { 143 | const arrayAbove = emojis[arrayIndex - 1]; 144 | const index = (emojiIndex > (arrayAbove.length - 1) % emojisPerRow) ? arrayAbove.length - 1 : Math.floor((arrayAbove.length - 1 - emojiIndex) / emojisPerRow) * emojisPerRow + emojiIndex; 145 | emoji = arrayAbove[index]; 146 | row = focusedEmoji.row - 2; 147 | } 148 | } 149 | } 150 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_e = document.activeElement) === null || _e === void 0 ? void 0 : _e.closest(".emoji-picker-scroll")), preventScroll: false } }); 151 | } 152 | case "ArrowDown": { 153 | event.preventDefault(); 154 | let emoji = undefined, row = undefined; 155 | if (!focusedEmoji) { 156 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 157 | row = 1; 158 | } 159 | else { 160 | let arrayIndex, arrayEmoji, emojiIndex; 161 | emojis.find((array, index) => { 162 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 163 | return emojiIndex !== -1; 164 | }); 165 | if (emojiIndex != undefined) { 166 | if (emojiIndex + emojisPerRow < arrayEmoji.length) { 167 | emoji = arrayEmoji[emojiIndex + emojisPerRow]; 168 | row = focusedEmoji.row + 1; 169 | } 170 | else if (emojiIndex + emojisPerRow < Math.ceil(arrayEmoji.length / emojisPerRow) * emojisPerRow) { 171 | emoji = arrayEmoji[arrayEmoji.length - 1]; 172 | row = focusedEmoji.row + 1; 173 | } 174 | else if (arrayIndex !== emojis.length - 1) { 175 | const arrayBelow = emojis[arrayIndex + 1], modIndex = emojiIndex % emojisPerRow; 176 | emoji = arrayBelow[modIndex] || arrayBelow[arrayBelow.length - 1]; 177 | row = focusedEmoji.row + 2; 178 | } 179 | } 180 | } 181 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_f = document.activeElement) === null || _f === void 0 ? void 0 : _f.closest(".emoji-picker-scroll")), preventScroll: false } }); 182 | } 183 | case "ArrowLeft": { 184 | event.preventDefault(); 185 | let emoji = undefined, row = undefined; 186 | if (!focusedEmoji) { 187 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 188 | row = 1; 189 | } 190 | else { 191 | let arrayIndex, arrayEmoji, emojiIndex; 192 | emojis.find((array, index) => { 193 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 194 | return emojiIndex !== -1; 195 | }); 196 | if (emojiIndex != undefined) { 197 | if (emojiIndex - 1 >= 0) { 198 | emoji = arrayEmoji[emojiIndex - 1]; 199 | row = Math.floor(emojiIndex / emojisPerRow) == Math.floor((emojiIndex - 1) / emojisPerRow) ? focusedEmoji.row : focusedEmoji.row - 1; 200 | } 201 | else if (arrayIndex !== 0) { 202 | const arrayAbove = emojis[arrayIndex - 1]; 203 | emoji = arrayAbove[arrayAbove.length - 1]; 204 | row = focusedEmoji.row - 2; 205 | } 206 | } 207 | } 208 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_g = document.activeElement) === null || _g === void 0 ? void 0 : _g.closest(".emoji-picker-scroll")), preventScroll: false } }); 209 | } 210 | case "ArrowRight": { 211 | event.preventDefault(); 212 | let emoji = undefined, row = undefined; 213 | if (!focusedEmoji) { 214 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 215 | row = 1; 216 | } 217 | else { 218 | let arrayIndex, arrayEmoji, emojiIndex; 219 | emojis.find((array, index) => { 220 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 221 | return emojiIndex !== -1; 222 | }); 223 | if (emojiIndex != undefined) { 224 | let newIndex = emojiIndex + 1; 225 | if (newIndex < arrayEmoji.length) { 226 | emoji = arrayEmoji[newIndex]; 227 | row = Math.floor(emojiIndex / emojisPerRow) == Math.floor(newIndex / emojisPerRow) ? focusedEmoji.row : focusedEmoji.row + 1; 228 | } 229 | else if (arrayIndex !== emojis.length - 1) { 230 | let arrayBelow = emojis[arrayIndex + 1]; 231 | emoji = arrayBelow[0]; 232 | row = focusedEmoji.row + 2; 233 | } 234 | } 235 | } 236 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_h = document.activeElement) === null || _h === void 0 ? void 0 : _h.closest(".emoji-picker-scroll")), preventScroll: false } }); 237 | } 238 | default: 239 | return onKeyDownScroll(event); 240 | } 241 | }; 242 | (0, react_1.useImperativeHandle)(ref, () => { 243 | var _a; 244 | return ({ 245 | search, 246 | handleKeyDownScroll, 247 | emojis: pickerState.searchEmojis.emojis || emojiData, 248 | focusedEmoji: (_a = pickerState.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji, 249 | }); 250 | }); 251 | const ScrollProps = { 252 | emojiData: pickerState.searchEmojis.emojis || emojiData, 253 | emojisPerRow: emojisPerRow, 254 | emojiSize, 255 | numberScrollRows, 256 | focusedEmoji: pickerState.focusedEmoji, 257 | refVirtualList, 258 | handleClickInScroll, 259 | handleMouseInScroll, 260 | collapseHeightOnSearch, 261 | itemCount, 262 | itemRanges, 263 | }; 264 | const handleSelectInNavbar = (category) => { 265 | let virtualList = refVirtualList.current; 266 | if (virtualList) { 267 | let range = itemRanges.find(range => range.key === category); 268 | if (range) { 269 | setPickerState({ focusedEmoji: { row: range.from + 1, emoji: emojiData[category][0], focusOnRender: false, preventScroll: false } }); 270 | virtualList.scrollToItem(range.from, "start"); 271 | } 272 | } 273 | }; 274 | const getWidths = () => { 275 | const scrollbarWidth = (0, utils_1.measureScrollbar)(); 276 | return { 277 | scrollbarWidth, 278 | width: `calc(${emojiSize}px * ${emojisPerRow} + 1em + ${scrollbarWidth}px)` 279 | }; 280 | }; 281 | const [width, setWidth] = (0, react_1.useState)(getWidths); 282 | (0, react_1.useLayoutEffect)(() => { 283 | let resizeWidth = () => setWidth(getWidths); 284 | window.addEventListener("resize", resizeWidth); 285 | return () => window.removeEventListener("resize", resizeWidth); 286 | }, []); 287 | return (react_1.default.createElement("div", { className: `emoji-picker emoji-picker-${theme}`, style: { width: width.width } }, 288 | showNavbar && 289 | react_1.default.createElement(Navbar_1.default, { data: emojiData, handleSelectInNavbar: handleSelectInNavbar, style: { marginRight: width.scrollbarWidth } }), 290 | react_1.default.createElement("div", { className: "emoji-picker-scroll", role: "grid", "aria-rowcount": itemCount, "aria-colcount": emojisPerRow, onKeyDown: handleKeyDownScroll, ref: refScroll }, pickerState.searchEmojis.emojis 291 | ? Object.values(pickerState.searchEmojis.emojis).flat().length 292 | ? react_1.default.createElement(Scroll_1.default, Object.assign({}, ScrollProps)) 293 | : react_1.default.createElement("div", { className: "emoji-picker-category", style: { height: collapseHeightOnSearch ? 'inherit' : '432px' } }, 294 | react_1.default.createElement("div", { className: "emoji-picker-category-title" }, "No results")) 295 | : showScroll && 296 | react_1.default.createElement(Scroll_1.default, Object.assign({}, ScrollProps))), 297 | showFooter && 298 | react_1.default.createElement(Footer_1.default, { emoji: (_b = pickerState.focusedEmoji) === null || _b === void 0 ? void 0 : _b.emoji, emojiPreviewName: emojiPreviewName }))); 299 | } 300 | exports.EmojiPicker = (0, react_1.forwardRef)(EmojiPickerRefComponent); 301 | //# sourceMappingURL=EmojiPicker.js.map -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"EmojiPicker.js","sourceRoot":"","sources":["../../src/EmojiPicker.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Footer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 10 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 11 | }) : function(o, v) { 12 | o["default"] = v; 13 | }); 14 | var __importStar = (this && this.__importStar) || function (mod) { 15 | if (mod && mod.__esModule) return mod; 16 | var result = {}; 17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 18 | __setModuleDefault(result, mod); 19 | return result; 20 | }; 21 | var __rest = (this && this.__rest) || function (s, e) { 22 | var t = {}; 23 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 24 | t[p] = s[p]; 25 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 26 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 27 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 28 | t[p[i]] = s[p[i]]; 29 | } 30 | return t; 31 | }; 32 | var __importDefault = (this && this.__importDefault) || function (mod) { 33 | return (mod && mod.__esModule) ? mod : { "default": mod }; 34 | }; 35 | Object.defineProperty(exports, "__esModule", { value: true }); 36 | const react_1 = __importStar(require("react")); 37 | const Emoji_1 = __importDefault(require("../Emoji")); 38 | const Footer = (_a) => { 39 | var { emoji, emojiPreviewName } = _a, props = __rest(_a, ["emoji", "emojiPreviewName"]); 40 | return (react_1.default.createElement("div", Object.assign({ className: "emoji-picker-footer" }, props), 41 | react_1.default.createElement(Emoji_1.default, { emoji: emoji || { name: "wave", unicode: "1f44b" } }), 42 | react_1.default.createElement("div", { className: "emoji-picker-name" }, emoji ? emojiPreviewName(emoji) : react_1.default.createElement("span", { style: { 'fontSize': '1.25em' } }, "Emoji Picker")))); 43 | }; 44 | const MemoizedFooter = (0, react_1.memo)(Footer); 45 | exports.default = MemoizedFooter; 46 | //# sourceMappingURL=Footer.js.map -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Footer.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Footer.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Footer.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAuD;AACvD,qDAA4B;AAG5B,MAAM,MAAM,GAA8F,CAAC,EAAmC,EAAE,EAAE;QAAvC,EAAC,KAAK,EAAE,gBAAgB,OAAW,EAAN,KAAK,cAAlC,6BAAmC,CAAD;IAC3I,OAAO,CACL,qDAAK,SAAS,EAAC,qBAAqB,IAAK,KAAK;QAC1C,8BAAC,eAAK,IAAC,KAAK,EAAE,KAAK,IAAI,EAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAC,GAAG;QAC5D,uCAAK,SAAS,EAAC,mBAAmB,IAC9B,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,wCAAM,KAAK,EAAE,EAAC,UAAU,EAAE,QAAQ,EAAC,mBAAqB,CACxF,CACF,CACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,IAAA,YAAI,EAAC,MAAM,CAAC,CAAA;AACnC,kBAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Navbar.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 10 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 11 | }) : function(o, v) { 12 | o["default"] = v; 13 | }); 14 | var __importStar = (this && this.__importStar) || function (mod) { 15 | if (mod && mod.__esModule) return mod; 16 | var result = {}; 17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 18 | __setModuleDefault(result, mod); 19 | return result; 20 | }; 21 | var __rest = (this && this.__rest) || function (s, e) { 22 | var t = {}; 23 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 24 | t[p] = s[p]; 25 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 26 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 27 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 28 | t[p[i]] = s[p[i]]; 29 | } 30 | return t; 31 | }; 32 | var __importDefault = (this && this.__importDefault) || function (mod) { 33 | return (mod && mod.__esModule) ? mod : { "default": mod }; 34 | }; 35 | Object.defineProperty(exports, "__esModule", { value: true }); 36 | const react_1 = __importStar(require("react")); 37 | const Emoji_1 = __importDefault(require("../Emoji")); 38 | const Navbar = (_a) => { 39 | var { data, handleSelectInNavbar } = _a, props = __rest(_a, ["data", "handleSelectInNavbar"]); 40 | const [index, setIndex] = (0, react_1.useState)(0); 41 | const onNavbarKeyDown = (event) => { 42 | switch (event.key) { 43 | case 'Enter': 44 | return handleSelectInNavbar(Object.keys(data)[index]); 45 | case 'ArrowLeft': 46 | return index > 0 && setIndex(index => index - 1); 47 | case 'ArrowRight': 48 | return index < Object.keys(data).length - 1 && setIndex(index => index + 1); 49 | case 'Home': 50 | return index > 0 && setIndex(0); 51 | case 'End': 52 | return index < Object.keys(data).length - 1 && setIndex(Object.keys(data).length - 1); 53 | } 54 | }; 55 | const onNavbarClick = (index, category) => (event) => { 56 | setIndex(index); 57 | handleSelectInNavbar(category); 58 | }; 59 | return (react_1.default.createElement("div", Object.assign({ className: "emoji-picker-navbar" }, props, { role: "tablist", "aria-label": "emoji categories" }), Object.entries(data).map(([category, list], i) => { 60 | const props = Object.assign({ className: "emoji-picker-navbar-category", key: `navbar-${category}`, onClick: onNavbarClick(i, category), onKeyDown: onNavbarKeyDown, role: "tab", "aria-label": category, "aria-selected": false, tabIndex: -1 }, i == index && { 61 | "aria-selected": true, 62 | tabIndex: 0, 63 | ref: (button) => { var _a; return Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-navbar")) && (button === null || button === void 0 ? void 0 : button.focus()); }, 64 | }); 65 | return (react_1.default.createElement("button", Object.assign({}, props), react_1.default.createElement(Emoji_1.default, { emoji: list[0] }))); 66 | }))); 67 | }; 68 | const MemoizedNavbar = (0, react_1.memo)(Navbar); 69 | exports.default = MemoizedNavbar; 70 | //# sourceMappingURL=Navbar.js.map -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Navbar.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Navbar.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Navbar.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA4F;AAC5F,qDAA4B;AAG5B,MAAM,MAAM,GAAiH,CAAC,EAAsC,EAAE,EAAE;QAA1C,EAAC,IAAI,EAAE,oBAAoB,OAAW,EAAN,KAAK,cAArC,gCAAsC,CAAD;IAGjK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IAEtC,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,EAAE;QAC/C,QAAQ,KAAK,CAAC,GAAG,EAAE;YACjB,KAAK,OAAO;gBACV,OAAO,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,KAAK,WAAW;gBACd,OAAO,KAAK,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACnD,KAAK,YAAY;gBACf,OAAO,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YAC7E,KAAK,MAAM;gBACT,OAAO,KAAK,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;YAClC,KAAK,KAAK;gBACR,OAAO,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;SACxF;IACH,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC,KAAiB,EAAE,EAAE;QAC/E,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAA;IAED,OAAO,CACL,qDAAK,SAAS,EAAC,qBAAqB,IAAK,KAAK,IAAE,IAAI,EAAC,SAAS,gBAAY,kBAAkB,KACxF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QAC/C,MAAM,KAAK,mBACT,SAAS,EAAE,8BAA8B,EACzC,GAAG,EAAE,UAAU,QAAQ,EAAE,EACzB,OAAO,EAAE,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,EACnC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,KAAK,EACX,YAAY,EAAE,QAAQ,EACtB,eAAe,EAAE,KAAK,EACtB,QAAQ,EAAE,CAAC,CAAC,IACT,CAAC,IAAI,KAAK,IAAI;YACf,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;YACX,GAAG,EAAE,CAAC,MAAyB,EAAE,EAAE,WAAC,OAAA,OAAO,CAAC,MAAA,QAAQ,CAAC,aAAa,0CAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC,KAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,EAAE,CAAA,CAAA,EAAA;SACxH,CACF,CAAA;QACD,OAAO,CACL,0DAAY,KAAK,GACb,8BAAC,eAAK,IAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CACnB,CACV,CAAA;IACH,CAAC,CACF,CACG,CACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,IAAA,YAAI,EAAC,MAAM,CAAC,CAAA;AACnC,kBAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Scroll.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 10 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 11 | }) : function(o, v) { 12 | o["default"] = v; 13 | }); 14 | var __importStar = (this && this.__importStar) || function (mod) { 15 | if (mod && mod.__esModule) return mod; 16 | var result = {}; 17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 18 | __setModuleDefault(result, mod); 19 | return result; 20 | }; 21 | var __rest = (this && this.__rest) || function (s, e) { 22 | var t = {}; 23 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 24 | t[p] = s[p]; 25 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 26 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 27 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 28 | t[p[i]] = s[p[i]]; 29 | } 30 | return t; 31 | }; 32 | var __importDefault = (this && this.__importDefault) || function (mod) { 33 | return (mod && mod.__esModule) ? mod : { "default": mod }; 34 | }; 35 | Object.defineProperty(exports, "__esModule", { value: true }); 36 | const react_1 = __importStar(require("react")); 37 | const react_window_1 = require("react-window"); 38 | const react_window_infinite_loader_1 = __importDefault(require("react-window-infinite-loader")); 39 | const utils_1 = require("../utils"); 40 | const Emoji_1 = __importDefault(require("../Emoji")); 41 | const Scroll = ({ emojisPerRow, emojiSize, numberScrollRows, focusedEmoji, emojiData, refVirtualList, handleClickInScroll, handleMouseInScroll, itemCount, itemRanges, collapseHeightOnSearch }) => { 42 | const [arrayOfRows, setArrayOfRows] = (0, react_1.useState)({}); 43 | const infiniteLoaderRef = (0, react_1.useRef)(null); 44 | const prevFocusedEmoji = (0, react_1.useRef)(null); 45 | (0, react_1.useEffect)(function resetScrollState() { 46 | setArrayOfRows({}); 47 | infiniteLoaderRef === null || infiniteLoaderRef === void 0 ? void 0 : infiniteLoaderRef.current.resetloadMoreItemsCache(); 48 | prevFocusedEmoji.current = focusedEmoji; 49 | refVirtualList === null || refVirtualList === void 0 ? void 0 : refVirtualList.current.scrollToItem(0); 50 | loadMoreItems(0, Math.min(numberScrollRows + 10 - 1, itemRanges[itemRanges.length - 1].to)); 51 | }, [emojiData, emojisPerRow]); 52 | (0, react_1.useEffect)(function resetRowsWithFocusedEmoji() { 53 | var _a; 54 | let prevEmoji = prevFocusedEmoji.current, nextEmoji = focusedEmoji; 55 | if (prevEmoji == nextEmoji) { 56 | return; 57 | } 58 | let rowsToUpdate = (prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row) == (nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row) ? [prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row] : [prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row, nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row]; 59 | rowsToUpdate.forEach(row => row && loadMoreItems(row, row)); 60 | prevFocusedEmoji.current = nextEmoji; 61 | (nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row) && ((_a = refVirtualList.current) === null || _a === void 0 ? void 0 : _a.scrollToItem(nextEmoji.row)); 62 | }, [focusedEmoji]); 63 | const loadMoreItems = (startIndex, endIndex) => { 64 | const nextArrayOfRows = {}; 65 | let i = startIndex, range; 66 | while (i <= endIndex) { 67 | range = itemRanges.find(range => range.from <= i && i < range.to); 68 | if (range === undefined) 69 | break; 70 | for (let rowIndex = i; rowIndex < Math.min(range.to, endIndex + 1); rowIndex++) { 71 | if (rowIndex == range.from) { 72 | nextArrayOfRows[rowIndex] = react_1.default.createElement("div", { className: "emoji-picker-category-title", "aria-rowindex": rowIndex + 1, "aria-colindex": 1 }, range.key); 73 | } 74 | else { 75 | const offset = rowIndex - range.from; 76 | const row = emojiData[range.key].slice((offset - 1) * emojisPerRow, offset * emojisPerRow); 77 | nextArrayOfRows[rowIndex] = (react_1.default.createElement("ul", { className: "emoji-picker-category-emoji", role: "row", "aria-rowindex": rowIndex + 1 }, row.map((emoji, colIndex) => { 78 | const liProps = Object.assign({ key: emoji.unicode, onClick: handleClickInScroll(emoji, rowIndex), onMouseMove: handleMouseInScroll(emoji, rowIndex), role: "gridcell", "aria-rowindex": rowIndex + 1, "aria-colindex": colIndex + 1, tabIndex: -1 }, emoji === (focusedEmoji === null || focusedEmoji === void 0 ? void 0 : focusedEmoji.emoji) && { 79 | tabIndex: 0, 80 | ref: (li) => focusedEmoji.focusOnRender && (li === null || li === void 0 ? void 0 : li.focus({ preventScroll: focusedEmoji.preventScroll })), 81 | }); 82 | const emojiProps = Object.assign({ emoji }, emoji === (focusedEmoji === null || focusedEmoji === void 0 ? void 0 : focusedEmoji.emoji) && { 83 | className: "emoji-picker-emoji-focused", 84 | }); 85 | return (react_1.default.createElement("li", Object.assign({}, liProps), 86 | react_1.default.createElement(Emoji_1.default, Object.assign({}, emojiProps)))); 87 | }))); 88 | } 89 | } 90 | i = range.to; 91 | } 92 | setArrayOfRows(prev => Object.assign({}, prev, nextArrayOfRows)); 93 | }; 94 | return (react_1.default.createElement(react_window_infinite_loader_1.default, { ref: infiniteLoaderRef, itemCount: itemCount, loadMoreItems: loadMoreItems, isItemLoaded: index => !!arrayOfRows[index], minimumBatchSize: numberScrollRows, threshold: 10 }, ({ onItemsRendered, ref }) => (react_1.default.createElement(react_window_1.FixedSizeList, { onItemsRendered: onItemsRendered, ref: list => { ref(list); refVirtualList && (refVirtualList.current = list); }, itemCount: itemCount, itemData: arrayOfRows, itemSize: emojiSize, height: collapseHeightOnSearch ? Math.min(itemCount * emojiSize + 9, numberScrollRows * emojiSize) : numberScrollRows * emojiSize, innerElementType: innerElementType }, MemoizedRow)))); 95 | }; 96 | const MemoizedScroll = (0, react_1.memo)(Scroll, function ScrollPropsAreEqual(prevProps, nextProps) { 97 | var _a, _b; 98 | return ((_a = prevProps.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji) == ((_b = nextProps.focusedEmoji) === null || _b === void 0 ? void 0 : _b.emoji) 99 | && prevProps.emojiData == nextProps.emojiData 100 | && prevProps.collapseHeightOnSearch == nextProps.collapseHeightOnSearch 101 | && prevProps.emojiSize == nextProps.emojiSize 102 | && prevProps.emojisPerRow == nextProps.emojisPerRow; 103 | }); 104 | exports.default = MemoizedScroll; 105 | const VirtualRow = ({ index, style, data }) => { 106 | return (react_1.default.createElement("div", { className: "emoji-picker-virtual-row", style: style }, data[index])); 107 | }; 108 | const MemoizedRow = (0, react_1.memo)(VirtualRow, function compareRowProps(prevProps, nextProps) { 109 | const { style: prevStyle, data: prevData, index: prevIndex } = prevProps, prevRest = __rest(prevProps, ["style", "data", "index"]); 110 | const { style: nextStyle, data: nextData, index: nextIndex } = nextProps, nextRest = __rest(nextProps, ["style", "data", "index"]); 111 | return prevData[prevIndex] === nextData[nextIndex] && !(0, utils_1.shallowDiffer)(prevStyle, nextStyle) && !(0, utils_1.shallowDiffer)(prevRest, nextRest); 112 | }); 113 | const LIST_PADDING_SIZE = 9; 114 | const innerElementType = (0, react_1.forwardRef)((_a, ref) => { 115 | var { style } = _a, props = __rest(_a, ["style"]); 116 | return (react_1.default.createElement("div", Object.assign({ ref: ref, style: Object.assign(Object.assign({}, style), { height: `${parseFloat(style.height) + LIST_PADDING_SIZE}px` }) }, props))); 117 | }); 118 | //# sourceMappingURL=Scroll.js.map -------------------------------------------------------------------------------- /dist/cjs/EmojiPicker/Scroll.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Scroll.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Scroll.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/cjs/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 10 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 11 | }; 12 | Object.defineProperty(exports, "__esModule", { value: true }); 13 | __exportStar(require("./EmojiPicker"), exports); 14 | __exportStar(require("./Emoji"), exports); 15 | __exportStar(require("./utils"), exports); 16 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/cjs/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0CAAwB;AACxB,0CAAwB"} -------------------------------------------------------------------------------- /dist/cjs/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.throttleIdleTask = exports.shallowDiffer = exports.calcCountAndRange = exports.measureScrollbar = exports.unifiedToNative = void 0; 4 | function unifiedToNative(unified) { 5 | const codePoints = unified.split('-').map(u => parseInt(u, 16)); 6 | return String.fromCodePoint.apply(String, codePoints); 7 | } 8 | exports.unifiedToNative = unifiedToNative; 9 | function measureScrollbar() { 10 | if (typeof document == 'undefined') 11 | return 0; 12 | const div = document.createElement('div'); 13 | div.style.cssText = "width:100px; height:100px; overflow:scroll; position:absolute; top:-9999px"; 14 | document.body.appendChild(div); 15 | const scrollbarWidth = div.offsetWidth - div.clientWidth; 16 | document.body.removeChild(div); 17 | return scrollbarWidth; 18 | } 19 | exports.measureScrollbar = measureScrollbar; 20 | function calcCountAndRange(data, perRow) { 21 | let itemCount = 0, itemRanges = []; 22 | Object.entries(data).forEach(([key, array]) => { 23 | if (array.length === 0) 24 | return; 25 | let from = itemCount, to = itemCount + 1 + Math.ceil(array.length / perRow); 26 | itemRanges.push({ key, from, to, length: array.length }); 27 | itemCount = to; 28 | }); 29 | return { itemCount, itemRanges }; 30 | } 31 | exports.calcCountAndRange = calcCountAndRange; 32 | function shallowDiffer(prev, next) { 33 | for (let attribute in prev) { 34 | if (!(attribute in next)) { 35 | return true; 36 | } 37 | } 38 | for (let attribute in next) { 39 | if (prev[attribute] !== next[attribute]) { 40 | return true; 41 | } 42 | } 43 | return false; 44 | } 45 | exports.shallowDiffer = shallowDiffer; 46 | function throttleIdleTask(callback) { 47 | const idleHandler = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout; 48 | let running = false, argsFunc; 49 | return function throttled(...args) { 50 | argsFunc = args; 51 | if (running) { 52 | return; 53 | } 54 | running = true; 55 | idleHandler(() => { 56 | running = false; 57 | callback.apply(null, argsFunc); 58 | }); 59 | }; 60 | } 61 | exports.throttleIdleTask = throttleIdleTask; 62 | //# sourceMappingURL=utils.js.map -------------------------------------------------------------------------------- /dist/cjs/utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":";;;AAUA,SAAgB,eAAe,CAAC,OAAe;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAHD,0CAGC;AAMD,SAAgB,gBAAgB;IAC9B,IAAI,OAAO,QAAQ,IAAI,WAAW;QAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC1C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,4EAA4E,CAAC;IACjG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,cAAc,GAAG,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;IACzD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,cAAc,CAAC;AACxB,CAAC;AARD,4CAQC;AASD,SAAgB,iBAAiB,CAAC,IAA2B,EAAE,MAAc;IAC3E,IAAI,SAAS,GAAG,CAAC,EAAE,UAAU,GAAgB,EAAE,CAAC;IAChD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,IAAI,IAAI,GAAG,SAAS,EAAE,EAAE,GAAG,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC5E,UAAU,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;QACvD,SAAS,GAAG,EAAE,CAAC;IACjB,CAAC,CAAC,CAAA;IACF,OAAO,EAAC,SAAS,EAAE,UAAU,EAAC,CAAC;AACjC,CAAC;AATD,8CASC;AAGD,SAAgB,aAAa,CAAC,IAAY,EAAE,IAAY;IACtD,KAAK,IAAI,SAAS,IAAI,IAAI,EAAE;QAAE,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;SAAE;KAAC;IACzE,KAAK,IAAI,SAAS,IAAI,IAAI,EAAE;QAAE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;SAAE;KAAC;IACxF,OAAO,KAAK,CAAC;AACf,CAAC;AAJD,sCAIC;AAGD,SAAgB,gBAAgB,CAAC,QAAkB;IAEjD,MAAM,WAAW,GAAG,OAAO,mBAAmB,KAAK,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC;IACjG,IAAI,OAAO,GAAG,KAAK,EAAE,QAAa,CAAC;IACnC,OAAO,SAAS,SAAS,CAAC,GAAG,IAAW;QACtC,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,OAAO,EAAE;YAAE,OAAO;SAAE;QACxB,OAAO,GAAG,IAAI,CAAC;QACf,WAAW,CAAC,GAAG,EAAE;YACf,OAAO,GAAG,KAAK,CAAC;YAChB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC;AAbD,4CAaC"} -------------------------------------------------------------------------------- /dist/esm/Emoji.css: -------------------------------------------------------------------------------- 1 | /* https://github.com/twitter/twemoji#inline-styles */ 2 | .emoji-picker-emoji-inline { 3 | height: 1em; 4 | width: 1em; 5 | margin: 0 .05em 0 .1em; 6 | vertical-align: -0.1em; 7 | } -------------------------------------------------------------------------------- /dist/esm/Emoji.js: -------------------------------------------------------------------------------- 1 | var __rest = (this && this.__rest) || function (s, e) { 2 | var t = {}; 3 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 4 | t[p] = s[p]; 5 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 6 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 7 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 8 | t[p[i]] = s[p[i]]; 9 | } 10 | return t; 11 | }; 12 | import React from 'react'; 13 | import { unifiedToNative } from './utils'; 14 | import twemoji from "./twemoji.svg"; 15 | const Emoji = (_a) => { 16 | var { emoji, className } = _a, props = __rest(_a, ["emoji", "className"]); 17 | className = className ? `emoji-picker-emoji ${className}` : `emoji-picker-emoji`; 18 | return (React.createElement("img", Object.assign({ className: className, "data-unicode": emoji.unicode, alt: unifiedToNative(emoji.unicode), src: `${twemoji}#${emoji.unicode}`, draggable: "false", "aria-label": emoji.name }, props))); 19 | }; 20 | export { Emoji }; 21 | export default Emoji; 22 | //# sourceMappingURL=Emoji.js.map -------------------------------------------------------------------------------- /dist/esm/Emoji.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Emoji.js","sourceRoot":"","sources":["../../src/Emoji.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAa,MAAM,OAAO,CAAC;AAClC,OAAO,EAAe,eAAe,EAAE,MAAM,SAAS,CAAA;AACtD,OAAO,OAAO,MAAM,eAAe,CAAA;AAQnC,MAAM,KAAK,GAAmB,CAAC,EAA4B,EAAE,EAAE;QAAhC,EAAC,KAAK,EAAE,SAAS,OAAW,EAAN,KAAK,cAA3B,sBAA4B,CAAD;IACxD,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAA;IAChF,OAAO,CACL,2CACE,SAAS,EAAE,SAAS,kBACN,KAAK,CAAC,OAAO,EAC3B,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EACnC,GAAG,EAAE,GAAG,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,EAClC,SAAS,EAAC,OAAO,gBACL,KAAK,CAAC,IAAI,IAClB,KAAK,EACT,CACH,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAc,KAAK,EAAE,CAAC;AAC7B,eAAe,KAAK,CAAC"} -------------------------------------------------------------------------------- /dist/esm/EmojiPicker.css: -------------------------------------------------------------------------------- 1 | .emoji-picker { 2 | display: flex; 3 | flex-direction: column; 4 | border-radius: 3px; 5 | background: white; 6 | border: 1px solid #E1E1E0; 7 | overflow: hidden; 8 | } 9 | 10 | .emoji-picker .emoji-picker-scroll { 11 | overflow-y: hidden; 12 | -webkit-overflow-scrolling: touch; 13 | display: inline-block; 14 | outline: none; 15 | } 16 | 17 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-title { 18 | padding: 8px 0.75em; 19 | text-transform: uppercase; 20 | text-align: left; 21 | font-weight: 500; 22 | font-size: 16px; 23 | color: rgba(55, 53, 47, 0.6); 24 | background: white; 25 | user-select: none; 26 | } 27 | 28 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-emoji { 29 | padding: 0em 0.50em; 30 | display: flex; 31 | list-style-type: none; 32 | margin: 0; 33 | } 34 | 35 | .emoji-picker .emoji-picker-emoji { 36 | display: inline-block; 37 | user-select: none; 38 | cursor: pointer; 39 | width: 28px; 40 | height: 28px; 41 | margin: 0; 42 | padding: 4px; 43 | border-radius: 3px; 44 | flex-shrink: 0; 45 | } 46 | 47 | .emoji-picker .emoji-picker-emoji-focused { 48 | background: rgba(55, 53, 47, 0.15); 49 | } 50 | 51 | .emoji-picker .emoji-picker-emoji:active { 52 | background: rgba(55, 53, 47, 0.25); 53 | } 54 | 55 | .emoji-picker .emoji-picker-emoji-img { 56 | height: 100%; 57 | width: 100%; 58 | } 59 | 60 | .emoji-picker .emoji-picker-navbar { 61 | display: flex; 62 | height: fit-content; 63 | flex-direction: row; 64 | justify-content: space-evenly; 65 | border-bottom: 1px solid #E1E1E0; 66 | padding: 0.25em 9px; 67 | } 68 | 69 | .emoji-picker .emoji-picker-navbar .emoji-picker-navbar-category { 70 | appearance: none; 71 | padding: 0; 72 | border: none; 73 | background-color: inherit; 74 | } 75 | 76 | .emoji-picker .emoji-picker-footer { 77 | display: flex; 78 | flex-flow: row; 79 | align-items: center; 80 | border-top: 1px solid #E1E1E0; 81 | user-select: none; 82 | } 83 | 84 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji { 85 | width: 2.5em; 86 | height: 2.5em; 87 | padding: 0.50em; 88 | cursor: inherit; 89 | } 90 | 91 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji:active { 92 | background: inherit; 93 | } 94 | 95 | .emoji-picker .emoji-picker-footer .emoji-picker-name { 96 | text-align: left; 97 | padding: 0 0.25em; 98 | } 99 | 100 | /* DARK THEME */ 101 | 102 | .emoji-picker.emoji-picker-dark { 103 | background: rgb(63, 68, 71); 104 | color: #ffffff; 105 | } 106 | .emoji-picker.emoji-picker-dark, .emoji-picker.emoji-picker-dark .emoji-picker-navbar, .emoji-picker.emoji-picker-dark .emoji-picker-footer { 107 | border-color: rgb(63, 68, 71); 108 | } 109 | .emoji-picker.emoji-picker-dark .emoji-picker-category-title { 110 | color: rgba(255, 255, 255, 0.6); 111 | background-color: rgb(63, 68, 71); 112 | } 113 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji-focused { 114 | background: rgba(225, 225, 224, 0.25); 115 | } 116 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji:active { 117 | background: rgba(225, 225, 224, 0.50); 118 | } 119 | 120 | @media (prefers-color-scheme: dark) { 121 | .emoji-picker.emoji-picker-system { 122 | background: rgb(63, 68, 71); 123 | color: white; 124 | } 125 | .emoji-picker.emoji-picker-system, .emoji-picker.emoji-picker-system .emoji-picker-navbar, .emoji-picker.emoji-picker-system .emoji-picker-footer { 126 | border-color: rgb(63, 68, 71); 127 | } 128 | .emoji-picker.emoji-picker-system .emoji-picker-category-title { 129 | color: rgba(255, 255, 255, 0.6); 130 | background-color: rgb(63, 68, 71); 131 | } 132 | .emoji-picker.emoji-picker-system .emoji-picker-emoji-focused { 133 | background: rgba(225, 225, 224, 0.25); 134 | } 135 | .emoji-picker.emoji-picker-system .emoji-picker-emoji:active { 136 | background: rgba(225, 225, 224, 0.50); 137 | } 138 | } -------------------------------------------------------------------------------- /dist/esm/EmojiPicker.js: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useCallback, useState, useImperativeHandle, useMemo, useLayoutEffect, useRef, useReducer } from "react"; 2 | import { measureScrollbar, calcCountAndRange } from './utils'; 3 | import Navbar from "./EmojiPicker/Navbar"; 4 | import Footer from "./EmojiPicker/Footer"; 5 | import Scroll from "./EmojiPicker/Scroll"; 6 | function EmojiPickerReducer({ emojiData }) { 7 | return (prevState, nextState) => { 8 | var _a, _b, _c; 9 | if (nextState.searchEmojis && prevState.searchEmojis != nextState.searchEmojis) { 10 | let emojis = (((_a = nextState.searchEmojis) === null || _a === void 0 ? void 0 : _a.query) && ((_b = nextState.searchEmojis) === null || _b === void 0 ? void 0 : _b.emojis)) || emojiData, category = emojis[Object.keys(emojis)[0]]; 11 | let emoji = category[0]; 12 | nextState.focusedEmoji = { row: 1, emoji, focusOnRender: Boolean((_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.closest(".emoji-picker-scroll")), preventScroll: false }; 13 | } 14 | return Object.assign(Object.assign({}, prevState), nextState); 15 | }; 16 | } 17 | function EmojiPickerRefComponent({ emojiData = {}, emojiSize = 36, numberScrollRows = 12, onEmojiSelect = (emoji) => console.log(emoji), showNavbar = false, showFooter = false, showScroll = true, emojisPerRow = 9, onKeyDownScroll = (event) => null, collapseCategoriesOnSearch = true, collapseHeightOnSearch = true, theme = "system", emojiPreviewName = (emoji) => emoji.name }, ref) { 18 | var _a, _b; 19 | const pickerStateReducer = useCallback(EmojiPickerReducer({ emojiData }), [emojiData]); 20 | const [pickerState, setPickerState] = useReducer(pickerStateReducer, { 21 | searchEmojis: { emojis: null, query: "" }, 22 | focusedEmoji: { row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } 23 | }); 24 | const { itemCount, itemRanges } = useMemo(() => calcCountAndRange(pickerState.searchEmojis.emojis || emojiData, emojisPerRow), [pickerState.searchEmojis, emojisPerRow]); 25 | const search = (query) => { 26 | var _a; 27 | const { searchEmojis } = pickerState; 28 | if (!query) 29 | return setPickerState({ 30 | searchEmojis: { emojis: null, query: "" }, 31 | focusedEmoji: { row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } 32 | }); 33 | if ((searchEmojis === null || searchEmojis === void 0 ? void 0 : searchEmojis.emojis) && !Object.values(searchEmojis.emojis).flat().length && searchEmojis.query.length < query.length) 34 | return setPickerState({ searchEmojis: { emojis: searchEmojis.emojis, query } }); 35 | const index = query.length > searchEmojis.query.length && searchEmojis.emojis != null 36 | ? Object.values(searchEmojis.emojis).flat() 37 | : Object.values(emojiData).flat(); 38 | let results = index 39 | .map(emoji => ({ emoji, score: (emoji.keywords || []).map(word => word.indexOf(query) != -1).reduce((a, b) => a + Number(b), Number(emoji.name.indexOf(query) != -1) * 3) })) 40 | .filter(a => a.score) 41 | .sort((a, b) => b.score - a.score) 42 | .map(({ emoji }) => emoji); 43 | if (collapseCategoriesOnSearch) { 44 | return setPickerState({ searchEmojis: { emojis: { "Search Results": results }, query } }); 45 | } 46 | else { 47 | let grouped = Object.entries(emojiData).map(([category, list]) => ([category, list.filter(emoji => results.includes(emoji))])).reduce((sum, [category, list]) => Object.assign(sum, { [category]: list }), {}); 48 | return setPickerState({ searchEmojis: { emojis: grouped, query } }); 49 | } 50 | }; 51 | const refVirtualList = useRef(null); 52 | const refScroll = useRef(null); 53 | const handleClickInScroll = (emoji, row) => (event) => { 54 | event.preventDefault(); 55 | onEmojiSelect(emoji, event); 56 | setPickerState({ focusedEmoji: { row, emoji, focusOnRender: true, preventScroll: true } }); 57 | }; 58 | const handleMouseInScroll = (emoji, row) => (event) => { 59 | var _a; 60 | if (emoji == ((_a = pickerState.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji) || event.movementX == 0 && event.movementY == 0) 61 | return; 62 | event.preventDefault(); 63 | const isSafari = window.safari !== undefined; 64 | setPickerState({ focusedEmoji: { row, emoji, focusOnRender: true, preventScroll: true } }); 65 | isSafari && refScroll.current && refScroll.current.focus(); 66 | }; 67 | const handleKeyDownScroll = (event) => { 68 | var _a, _b, _c, _d, _e, _f, _g, _h; 69 | const { searchEmojis, focusedEmoji } = pickerState; 70 | const emojis = Object.values(searchEmojis.emojis || emojiData).filter(array => array.length !== 0); 71 | switch (event.key) { 72 | case "Enter": { 73 | event.preventDefault(); 74 | if (!focusedEmoji) { 75 | let emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 76 | emoji && setPickerState({ focusedEmoji: { row: 1, emoji, focusOnRender: Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-scroll")), preventScroll: false } }); 77 | } 78 | else { 79 | focusedEmoji.emoji && onEmojiSelect(focusedEmoji.emoji, event); 80 | } 81 | return; 82 | } 83 | case 'Home': { 84 | event.preventDefault(); 85 | let emoji = undefined, row = undefined; 86 | let emojis = searchEmojis.emojis || emojiData, category = emojis[Object.keys(emojis)[0]]; 87 | emoji = category[0]; 88 | row = 1; 89 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_b = document.activeElement) === null || _b === void 0 ? void 0 : _b.closest(".emoji-picker-scroll")), preventScroll: false } }); 90 | } 91 | case 'End': { 92 | event.preventDefault(); 93 | let emoji = undefined, row = undefined; 94 | let emojis = searchEmojis.emojis || emojiData, category = emojis[Object.keys(emojis).pop()]; 95 | emoji = category[category.length - 1]; 96 | row = ((_c = itemRanges[itemRanges.length - 1]) === null || _c === void 0 ? void 0 : _c.to) - 1; 97 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_d = document.activeElement) === null || _d === void 0 ? void 0 : _d.closest(".emoji-picker-scroll")), preventScroll: false } }); 98 | } 99 | case "ArrowUp": { 100 | event.preventDefault(); 101 | let emoji = undefined, row = undefined; 102 | if (!focusedEmoji) { 103 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 104 | row = 1; 105 | } 106 | else { 107 | let arrayIndex, arrayEmoji, emojiIndex; 108 | emojis.find((array, index) => { 109 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 110 | return emojiIndex !== -1; 111 | }); 112 | if (emojiIndex != undefined) { 113 | if (emojiIndex - emojisPerRow >= 0) { 114 | emoji = arrayEmoji[emojiIndex - emojisPerRow]; 115 | row = focusedEmoji.row - 1; 116 | } 117 | else if (arrayIndex !== 0) { 118 | const arrayAbove = emojis[arrayIndex - 1]; 119 | const index = (emojiIndex > (arrayAbove.length - 1) % emojisPerRow) ? arrayAbove.length - 1 : Math.floor((arrayAbove.length - 1 - emojiIndex) / emojisPerRow) * emojisPerRow + emojiIndex; 120 | emoji = arrayAbove[index]; 121 | row = focusedEmoji.row - 2; 122 | } 123 | } 124 | } 125 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_e = document.activeElement) === null || _e === void 0 ? void 0 : _e.closest(".emoji-picker-scroll")), preventScroll: false } }); 126 | } 127 | case "ArrowDown": { 128 | event.preventDefault(); 129 | let emoji = undefined, row = undefined; 130 | if (!focusedEmoji) { 131 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 132 | row = 1; 133 | } 134 | else { 135 | let arrayIndex, arrayEmoji, emojiIndex; 136 | emojis.find((array, index) => { 137 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 138 | return emojiIndex !== -1; 139 | }); 140 | if (emojiIndex != undefined) { 141 | if (emojiIndex + emojisPerRow < arrayEmoji.length) { 142 | emoji = arrayEmoji[emojiIndex + emojisPerRow]; 143 | row = focusedEmoji.row + 1; 144 | } 145 | else if (emojiIndex + emojisPerRow < Math.ceil(arrayEmoji.length / emojisPerRow) * emojisPerRow) { 146 | emoji = arrayEmoji[arrayEmoji.length - 1]; 147 | row = focusedEmoji.row + 1; 148 | } 149 | else if (arrayIndex !== emojis.length - 1) { 150 | const arrayBelow = emojis[arrayIndex + 1], modIndex = emojiIndex % emojisPerRow; 151 | emoji = arrayBelow[modIndex] || arrayBelow[arrayBelow.length - 1]; 152 | row = focusedEmoji.row + 2; 153 | } 154 | } 155 | } 156 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_f = document.activeElement) === null || _f === void 0 ? void 0 : _f.closest(".emoji-picker-scroll")), preventScroll: false } }); 157 | } 158 | case "ArrowLeft": { 159 | event.preventDefault(); 160 | let emoji = undefined, row = undefined; 161 | if (!focusedEmoji) { 162 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 163 | row = 1; 164 | } 165 | else { 166 | let arrayIndex, arrayEmoji, emojiIndex; 167 | emojis.find((array, index) => { 168 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 169 | return emojiIndex !== -1; 170 | }); 171 | if (emojiIndex != undefined) { 172 | if (emojiIndex - 1 >= 0) { 173 | emoji = arrayEmoji[emojiIndex - 1]; 174 | row = Math.floor(emojiIndex / emojisPerRow) == Math.floor((emojiIndex - 1) / emojisPerRow) ? focusedEmoji.row : focusedEmoji.row - 1; 175 | } 176 | else if (arrayIndex !== 0) { 177 | const arrayAbove = emojis[arrayIndex - 1]; 178 | emoji = arrayAbove[arrayAbove.length - 1]; 179 | row = focusedEmoji.row - 2; 180 | } 181 | } 182 | } 183 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_g = document.activeElement) === null || _g === void 0 ? void 0 : _g.closest(".emoji-picker-scroll")), preventScroll: false } }); 184 | } 185 | case "ArrowRight": { 186 | event.preventDefault(); 187 | let emoji = undefined, row = undefined; 188 | if (!focusedEmoji) { 189 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 190 | row = 1; 191 | } 192 | else { 193 | let arrayIndex, arrayEmoji, emojiIndex; 194 | emojis.find((array, index) => { 195 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 196 | return emojiIndex !== -1; 197 | }); 198 | if (emojiIndex != undefined) { 199 | let newIndex = emojiIndex + 1; 200 | if (newIndex < arrayEmoji.length) { 201 | emoji = arrayEmoji[newIndex]; 202 | row = Math.floor(emojiIndex / emojisPerRow) == Math.floor(newIndex / emojisPerRow) ? focusedEmoji.row : focusedEmoji.row + 1; 203 | } 204 | else if (arrayIndex !== emojis.length - 1) { 205 | let arrayBelow = emojis[arrayIndex + 1]; 206 | emoji = arrayBelow[0]; 207 | row = focusedEmoji.row + 2; 208 | } 209 | } 210 | } 211 | return row && emoji && setPickerState({ focusedEmoji: { row, emoji, focusOnRender: Boolean((_h = document.activeElement) === null || _h === void 0 ? void 0 : _h.closest(".emoji-picker-scroll")), preventScroll: false } }); 212 | } 213 | default: 214 | return onKeyDownScroll(event); 215 | } 216 | }; 217 | useImperativeHandle(ref, () => { 218 | var _a; 219 | return ({ 220 | search, 221 | handleKeyDownScroll, 222 | emojis: pickerState.searchEmojis.emojis || emojiData, 223 | focusedEmoji: (_a = pickerState.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji, 224 | }); 225 | }); 226 | const ScrollProps = { 227 | emojiData: pickerState.searchEmojis.emojis || emojiData, 228 | emojisPerRow: emojisPerRow, 229 | emojiSize, 230 | numberScrollRows, 231 | focusedEmoji: pickerState.focusedEmoji, 232 | refVirtualList, 233 | handleClickInScroll, 234 | handleMouseInScroll, 235 | collapseHeightOnSearch, 236 | itemCount, 237 | itemRanges, 238 | }; 239 | const handleSelectInNavbar = (category) => { 240 | let virtualList = refVirtualList.current; 241 | if (virtualList) { 242 | let range = itemRanges.find(range => range.key === category); 243 | if (range) { 244 | setPickerState({ focusedEmoji: { row: range.from + 1, emoji: emojiData[category][0], focusOnRender: false, preventScroll: false } }); 245 | virtualList.scrollToItem(range.from, "start"); 246 | } 247 | } 248 | }; 249 | const getWidths = () => { 250 | const scrollbarWidth = measureScrollbar(); 251 | return { 252 | scrollbarWidth, 253 | width: `calc(${emojiSize}px * ${emojisPerRow} + 1em + ${scrollbarWidth}px)` 254 | }; 255 | }; 256 | const [width, setWidth] = useState(getWidths); 257 | useLayoutEffect(() => { 258 | let resizeWidth = () => setWidth(getWidths); 259 | window.addEventListener("resize", resizeWidth); 260 | return () => window.removeEventListener("resize", resizeWidth); 261 | }, []); 262 | return (React.createElement("div", { className: `emoji-picker emoji-picker-${theme}`, style: { width: width.width } }, 263 | showNavbar && 264 | React.createElement(Navbar, { data: emojiData, handleSelectInNavbar: handleSelectInNavbar, style: { marginRight: width.scrollbarWidth } }), 265 | React.createElement("div", { className: "emoji-picker-scroll", role: "grid", "aria-rowcount": itemCount, "aria-colcount": emojisPerRow, onKeyDown: handleKeyDownScroll, ref: refScroll }, pickerState.searchEmojis.emojis 266 | ? Object.values(pickerState.searchEmojis.emojis).flat().length 267 | ? React.createElement(Scroll, Object.assign({}, ScrollProps)) 268 | : React.createElement("div", { className: "emoji-picker-category", style: { height: collapseHeightOnSearch ? 'inherit' : '432px' } }, 269 | React.createElement("div", { className: "emoji-picker-category-title" }, "No results")) 270 | : showScroll && 271 | React.createElement(Scroll, Object.assign({}, ScrollProps))), 272 | showFooter && 273 | React.createElement(Footer, { emoji: (_b = pickerState.focusedEmoji) === null || _b === void 0 ? void 0 : _b.emoji, emojiPreviewName: emojiPreviewName }))); 274 | } 275 | export const EmojiPicker = forwardRef(EmojiPickerRefComponent); 276 | //# sourceMappingURL=EmojiPicker.js.map -------------------------------------------------------------------------------- /dist/esm/EmojiPicker.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"EmojiPicker.js","sourceRoot":"","sources":["../../src/EmojiPicker.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Footer.js: -------------------------------------------------------------------------------- 1 | var __rest = (this && this.__rest) || function (s, e) { 2 | var t = {}; 3 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 4 | t[p] = s[p]; 5 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 6 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 7 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 8 | t[p[i]] = s[p[i]]; 9 | } 10 | return t; 11 | }; 12 | import React, { memo } from "react"; 13 | import Emoji from "../Emoji"; 14 | const Footer = (_a) => { 15 | var { emoji, emojiPreviewName } = _a, props = __rest(_a, ["emoji", "emojiPreviewName"]); 16 | return (React.createElement("div", Object.assign({ className: "emoji-picker-footer" }, props), 17 | React.createElement(Emoji, { emoji: emoji || { name: "wave", unicode: "1f44b" } }), 18 | React.createElement("div", { className: "emoji-picker-name" }, emoji ? emojiPreviewName(emoji) : React.createElement("span", { style: { 'fontSize': '1.25em' } }, "Emoji Picker")))); 19 | }; 20 | const MemoizedFooter = memo(Footer); 21 | export default MemoizedFooter; 22 | //# sourceMappingURL=Footer.js.map -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Footer.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Footer.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Footer.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAqB,IAAI,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,KAAK,MAAM,UAAU,CAAA;AAG5B,MAAM,MAAM,GAA8F,CAAC,EAAmC,EAAE,EAAE;QAAvC,EAAC,KAAK,EAAE,gBAAgB,OAAW,EAAN,KAAK,cAAlC,6BAAmC,CAAD;IAC3I,OAAO,CACL,2CAAK,SAAS,EAAC,qBAAqB,IAAK,KAAK;QAC1C,oBAAC,KAAK,IAAC,KAAK,EAAE,KAAK,IAAI,EAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAC,GAAG;QAC5D,6BAAK,SAAS,EAAC,mBAAmB,IAC9B,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,8BAAM,KAAK,EAAE,EAAC,UAAU,EAAE,QAAQ,EAAC,mBAAqB,CACxF,CACF,CACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;AACnC,eAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Navbar.js: -------------------------------------------------------------------------------- 1 | var __rest = (this && this.__rest) || function (s, e) { 2 | var t = {}; 3 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 4 | t[p] = s[p]; 5 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 6 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 7 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 8 | t[p[i]] = s[p[i]]; 9 | } 10 | return t; 11 | }; 12 | import React, { useState, memo } from "react"; 13 | import Emoji from "../Emoji"; 14 | const Navbar = (_a) => { 15 | var { data, handleSelectInNavbar } = _a, props = __rest(_a, ["data", "handleSelectInNavbar"]); 16 | const [index, setIndex] = useState(0); 17 | const onNavbarKeyDown = (event) => { 18 | switch (event.key) { 19 | case 'Enter': 20 | return handleSelectInNavbar(Object.keys(data)[index]); 21 | case 'ArrowLeft': 22 | return index > 0 && setIndex(index => index - 1); 23 | case 'ArrowRight': 24 | return index < Object.keys(data).length - 1 && setIndex(index => index + 1); 25 | case 'Home': 26 | return index > 0 && setIndex(0); 27 | case 'End': 28 | return index < Object.keys(data).length - 1 && setIndex(Object.keys(data).length - 1); 29 | } 30 | }; 31 | const onNavbarClick = (index, category) => (event) => { 32 | setIndex(index); 33 | handleSelectInNavbar(category); 34 | }; 35 | return (React.createElement("div", Object.assign({ className: "emoji-picker-navbar" }, props, { role: "tablist", "aria-label": "emoji categories" }), Object.entries(data).map(([category, list], i) => { 36 | const props = Object.assign({ className: "emoji-picker-navbar-category", key: `navbar-${category}`, onClick: onNavbarClick(i, category), onKeyDown: onNavbarKeyDown, role: "tab", "aria-label": category, "aria-selected": false, tabIndex: -1 }, i == index && { 37 | "aria-selected": true, 38 | tabIndex: 0, 39 | ref: (button) => { var _a; return Boolean((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(".emoji-picker-navbar")) && (button === null || button === void 0 ? void 0 : button.focus()); }, 40 | }); 41 | return (React.createElement("button", Object.assign({}, props), React.createElement(Emoji, { emoji: list[0] }))); 42 | }))); 43 | }; 44 | const MemoizedNavbar = memo(Navbar); 45 | export default MemoizedNavbar; 46 | //# sourceMappingURL=Navbar.js.map -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Navbar.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Navbar.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Navbar.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAqB,QAAQ,EAA6B,IAAI,EAAE,MAAM,OAAO,CAAC;AAC5F,OAAO,KAAK,MAAM,UAAU,CAAA;AAG5B,MAAM,MAAM,GAAiH,CAAC,EAAsC,EAAE,EAAE;QAA1C,EAAC,IAAI,EAAE,oBAAoB,OAAW,EAAN,KAAK,cAArC,gCAAsC,CAAD;IAGjK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,EAAE;QAC/C,QAAQ,KAAK,CAAC,GAAG,EAAE;YACjB,KAAK,OAAO;gBACV,OAAO,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,KAAK,WAAW;gBACd,OAAO,KAAK,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACnD,KAAK,YAAY;gBACf,OAAO,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YAC7E,KAAK,MAAM;gBACT,OAAO,KAAK,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;YAClC,KAAK,KAAK;gBACR,OAAO,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;SACxF;IACH,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC,KAAiB,EAAE,EAAE;QAC/E,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAA;IAED,OAAO,CACL,2CAAK,SAAS,EAAC,qBAAqB,IAAK,KAAK,IAAE,IAAI,EAAC,SAAS,gBAAY,kBAAkB,KACxF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QAC/C,MAAM,KAAK,mBACT,SAAS,EAAE,8BAA8B,EACzC,GAAG,EAAE,UAAU,QAAQ,EAAE,EACzB,OAAO,EAAE,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,EACnC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,KAAK,EACX,YAAY,EAAE,QAAQ,EACtB,eAAe,EAAE,KAAK,EACtB,QAAQ,EAAE,CAAC,CAAC,IACT,CAAC,IAAI,KAAK,IAAI;YACf,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;YACX,GAAG,EAAE,CAAC,MAAyB,EAAE,EAAE,WAAC,OAAA,OAAO,CAAC,MAAA,QAAQ,CAAC,aAAa,0CAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC,KAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,EAAE,CAAA,CAAA,EAAA;SACxH,CACF,CAAA;QACD,OAAO,CACL,gDAAY,KAAK,GACb,oBAAC,KAAK,IAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CACnB,CACV,CAAA;IACH,CAAC,CACF,CACG,CACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;AACnC,eAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Scroll.js: -------------------------------------------------------------------------------- 1 | var __rest = (this && this.__rest) || function (s, e) { 2 | var t = {}; 3 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 4 | t[p] = s[p]; 5 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 6 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 7 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 8 | t[p[i]] = s[p[i]]; 9 | } 10 | return t; 11 | }; 12 | import React, { useEffect, useRef, useState, memo, forwardRef } from "react"; 13 | import { FixedSizeList as VirtualList } from 'react-window'; 14 | import InfiniteLoader from "react-window-infinite-loader"; 15 | import { shallowDiffer } from '../utils'; 16 | import Emoji from "../Emoji"; 17 | const Scroll = ({ emojisPerRow, emojiSize, numberScrollRows, focusedEmoji, emojiData, refVirtualList, handleClickInScroll, handleMouseInScroll, itemCount, itemRanges, collapseHeightOnSearch }) => { 18 | const [arrayOfRows, setArrayOfRows] = useState({}); 19 | const infiniteLoaderRef = useRef(null); 20 | const prevFocusedEmoji = useRef(null); 21 | useEffect(function resetScrollState() { 22 | setArrayOfRows({}); 23 | infiniteLoaderRef === null || infiniteLoaderRef === void 0 ? void 0 : infiniteLoaderRef.current.resetloadMoreItemsCache(); 24 | prevFocusedEmoji.current = focusedEmoji; 25 | refVirtualList === null || refVirtualList === void 0 ? void 0 : refVirtualList.current.scrollToItem(0); 26 | loadMoreItems(0, Math.min(numberScrollRows + 10 - 1, itemRanges[itemRanges.length - 1].to)); 27 | }, [emojiData, emojisPerRow]); 28 | useEffect(function resetRowsWithFocusedEmoji() { 29 | var _a; 30 | let prevEmoji = prevFocusedEmoji.current, nextEmoji = focusedEmoji; 31 | if (prevEmoji == nextEmoji) { 32 | return; 33 | } 34 | let rowsToUpdate = (prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row) == (nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row) ? [prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row] : [prevEmoji === null || prevEmoji === void 0 ? void 0 : prevEmoji.row, nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row]; 35 | rowsToUpdate.forEach(row => row && loadMoreItems(row, row)); 36 | prevFocusedEmoji.current = nextEmoji; 37 | (nextEmoji === null || nextEmoji === void 0 ? void 0 : nextEmoji.row) && ((_a = refVirtualList.current) === null || _a === void 0 ? void 0 : _a.scrollToItem(nextEmoji.row)); 38 | }, [focusedEmoji]); 39 | const loadMoreItems = (startIndex, endIndex) => { 40 | const nextArrayOfRows = {}; 41 | let i = startIndex, range; 42 | while (i <= endIndex) { 43 | range = itemRanges.find(range => range.from <= i && i < range.to); 44 | if (range === undefined) 45 | break; 46 | for (let rowIndex = i; rowIndex < Math.min(range.to, endIndex + 1); rowIndex++) { 47 | if (rowIndex == range.from) { 48 | nextArrayOfRows[rowIndex] = React.createElement("div", { className: "emoji-picker-category-title", "aria-rowindex": rowIndex + 1, "aria-colindex": 1 }, range.key); 49 | } 50 | else { 51 | const offset = rowIndex - range.from; 52 | const row = emojiData[range.key].slice((offset - 1) * emojisPerRow, offset * emojisPerRow); 53 | nextArrayOfRows[rowIndex] = (React.createElement("ul", { className: "emoji-picker-category-emoji", role: "row", "aria-rowindex": rowIndex + 1 }, row.map((emoji, colIndex) => { 54 | const liProps = Object.assign({ key: emoji.unicode, onClick: handleClickInScroll(emoji, rowIndex), onMouseMove: handleMouseInScroll(emoji, rowIndex), role: "gridcell", "aria-rowindex": rowIndex + 1, "aria-colindex": colIndex + 1, tabIndex: -1 }, emoji === (focusedEmoji === null || focusedEmoji === void 0 ? void 0 : focusedEmoji.emoji) && { 55 | tabIndex: 0, 56 | ref: (li) => focusedEmoji.focusOnRender && (li === null || li === void 0 ? void 0 : li.focus({ preventScroll: focusedEmoji.preventScroll })), 57 | }); 58 | const emojiProps = Object.assign({ emoji }, emoji === (focusedEmoji === null || focusedEmoji === void 0 ? void 0 : focusedEmoji.emoji) && { 59 | className: "emoji-picker-emoji-focused", 60 | }); 61 | return (React.createElement("li", Object.assign({}, liProps), 62 | React.createElement(Emoji, Object.assign({}, emojiProps)))); 63 | }))); 64 | } 65 | } 66 | i = range.to; 67 | } 68 | setArrayOfRows(prev => Object.assign({}, prev, nextArrayOfRows)); 69 | }; 70 | return (React.createElement(InfiniteLoader, { ref: infiniteLoaderRef, itemCount: itemCount, loadMoreItems: loadMoreItems, isItemLoaded: index => !!arrayOfRows[index], minimumBatchSize: numberScrollRows, threshold: 10 }, ({ onItemsRendered, ref }) => (React.createElement(VirtualList, { onItemsRendered: onItemsRendered, ref: list => { ref(list); refVirtualList && (refVirtualList.current = list); }, itemCount: itemCount, itemData: arrayOfRows, itemSize: emojiSize, height: collapseHeightOnSearch ? Math.min(itemCount * emojiSize + 9, numberScrollRows * emojiSize) : numberScrollRows * emojiSize, innerElementType: innerElementType }, MemoizedRow)))); 71 | }; 72 | const MemoizedScroll = memo(Scroll, function ScrollPropsAreEqual(prevProps, nextProps) { 73 | var _a, _b; 74 | return ((_a = prevProps.focusedEmoji) === null || _a === void 0 ? void 0 : _a.emoji) == ((_b = nextProps.focusedEmoji) === null || _b === void 0 ? void 0 : _b.emoji) 75 | && prevProps.emojiData == nextProps.emojiData 76 | && prevProps.collapseHeightOnSearch == nextProps.collapseHeightOnSearch 77 | && prevProps.emojiSize == nextProps.emojiSize 78 | && prevProps.emojisPerRow == nextProps.emojisPerRow; 79 | }); 80 | export default MemoizedScroll; 81 | const VirtualRow = ({ index, style, data }) => { 82 | return (React.createElement("div", { className: "emoji-picker-virtual-row", style: style }, data[index])); 83 | }; 84 | const MemoizedRow = memo(VirtualRow, function compareRowProps(prevProps, nextProps) { 85 | const { style: prevStyle, data: prevData, index: prevIndex } = prevProps, prevRest = __rest(prevProps, ["style", "data", "index"]); 86 | const { style: nextStyle, data: nextData, index: nextIndex } = nextProps, nextRest = __rest(nextProps, ["style", "data", "index"]); 87 | return prevData[prevIndex] === nextData[nextIndex] && !shallowDiffer(prevStyle, nextStyle) && !shallowDiffer(prevRest, nextRest); 88 | }); 89 | const LIST_PADDING_SIZE = 9; 90 | const innerElementType = forwardRef((_a, ref) => { 91 | var { style } = _a, props = __rest(_a, ["style"]); 92 | return (React.createElement("div", Object.assign({ ref: ref, style: Object.assign(Object.assign({}, style), { height: `${parseFloat(style.height) + LIST_PADDING_SIZE}px` }) }, props))); 93 | }); 94 | //# sourceMappingURL=Scroll.js.map -------------------------------------------------------------------------------- /dist/esm/EmojiPicker/Scroll.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Scroll.js","sourceRoot":"","sources":["../../../src/EmojiPicker/Scroll.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/esm/index.js: -------------------------------------------------------------------------------- 1 | export * from "./EmojiPicker"; 2 | export * from "./Emoji"; 3 | export * from "./utils"; 4 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/esm/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"} -------------------------------------------------------------------------------- /dist/esm/utils.js: -------------------------------------------------------------------------------- 1 | export function unifiedToNative(unified) { 2 | const codePoints = unified.split('-').map(u => parseInt(u, 16)); 3 | return String.fromCodePoint.apply(String, codePoints); 4 | } 5 | export function measureScrollbar() { 6 | if (typeof document == 'undefined') 7 | return 0; 8 | const div = document.createElement('div'); 9 | div.style.cssText = "width:100px; height:100px; overflow:scroll; position:absolute; top:-9999px"; 10 | document.body.appendChild(div); 11 | const scrollbarWidth = div.offsetWidth - div.clientWidth; 12 | document.body.removeChild(div); 13 | return scrollbarWidth; 14 | } 15 | export function calcCountAndRange(data, perRow) { 16 | let itemCount = 0, itemRanges = []; 17 | Object.entries(data).forEach(([key, array]) => { 18 | if (array.length === 0) 19 | return; 20 | let from = itemCount, to = itemCount + 1 + Math.ceil(array.length / perRow); 21 | itemRanges.push({ key, from, to, length: array.length }); 22 | itemCount = to; 23 | }); 24 | return { itemCount, itemRanges }; 25 | } 26 | export function shallowDiffer(prev, next) { 27 | for (let attribute in prev) { 28 | if (!(attribute in next)) { 29 | return true; 30 | } 31 | } 32 | for (let attribute in next) { 33 | if (prev[attribute] !== next[attribute]) { 34 | return true; 35 | } 36 | } 37 | return false; 38 | } 39 | export function throttleIdleTask(callback) { 40 | const idleHandler = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout; 41 | let running = false, argsFunc; 42 | return function throttled(...args) { 43 | argsFunc = args; 44 | if (running) { 45 | return; 46 | } 47 | running = true; 48 | idleHandler(() => { 49 | running = false; 50 | callback.apply(null, argsFunc); 51 | }); 52 | }; 53 | } 54 | //# sourceMappingURL=utils.js.map -------------------------------------------------------------------------------- /dist/esm/utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAMD,MAAM,UAAU,gBAAgB;IAC9B,IAAI,OAAO,QAAQ,IAAI,WAAW;QAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC1C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,4EAA4E,CAAC;IACjG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,cAAc,GAAG,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;IACzD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,cAAc,CAAC;AACxB,CAAC;AASD,MAAM,UAAU,iBAAiB,CAAC,IAA2B,EAAE,MAAc;IAC3E,IAAI,SAAS,GAAG,CAAC,EAAE,UAAU,GAAgB,EAAE,CAAC;IAChD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,IAAI,IAAI,GAAG,SAAS,EAAE,EAAE,GAAG,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC5E,UAAU,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;QACvD,SAAS,GAAG,EAAE,CAAC;IACjB,CAAC,CAAC,CAAA;IACF,OAAO,EAAC,SAAS,EAAE,UAAU,EAAC,CAAC;AACjC,CAAC;AAGD,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAAY;IACtD,KAAK,IAAI,SAAS,IAAI,IAAI,EAAE;QAAE,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;SAAE;KAAC;IACzE,KAAK,IAAI,SAAS,IAAI,IAAI,EAAE;QAAE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;SAAE;KAAC;IACxF,OAAO,KAAK,CAAC;AACf,CAAC;AAGD,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IAEjD,MAAM,WAAW,GAAG,OAAO,mBAAmB,KAAK,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC;IACjG,IAAI,OAAO,GAAG,KAAK,EAAE,QAAa,CAAC;IACnC,OAAO,SAAS,SAAS,CAAC,GAAG,IAAW;QACtC,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,OAAO,EAAE;YAAE,OAAO;SAAE;QACxB,OAAO,GAAG,IAAI,CAAC;QACf,WAAW,CAAC,GAAG,EAAE;YACf,OAAO,GAAG,KAAK,CAAC;YAChB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"} -------------------------------------------------------------------------------- /dist/types/Emoji.d.ts: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | import { EmojiObject } from './utils'; 3 | declare type EmojiProps = { 4 | emoji: EmojiObject; 5 | className?: string; 6 | [key: string]: any; 7 | }; 8 | declare const Emoji: FC; 9 | export { EmojiProps, Emoji }; 10 | export default Emoji; 11 | //# sourceMappingURL=Emoji.d.ts.map -------------------------------------------------------------------------------- /dist/types/Emoji.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Emoji.d.ts","sourceRoot":"","sources":["../../src/Emoji.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAA;AAGtD,aAAK,UAAU,GAAG;IAChB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAA;AAED,QAAA,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CAazB,CAAA;AAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC7B,eAAe,KAAK,CAAC"} -------------------------------------------------------------------------------- /dist/types/EmojiPicker.d.ts: -------------------------------------------------------------------------------- 1 | import React, { KeyboardEvent, MouseEvent } from "react"; 2 | import { EmojiObject } from './utils'; 3 | declare type EmojiPickerProps = { 4 | emojiData: Record; 5 | emojiSize?: number; 6 | onEmojiSelect?: (emoji: EmojiObject, event: KeyboardEvent | MouseEvent) => void; 7 | showNavbar?: boolean; 8 | showFooter?: boolean; 9 | showScroll?: boolean; 10 | emojisPerRow?: number; 11 | numberScrollRows?: number; 12 | onKeyDownScroll?: Function; 13 | collapseCategoriesOnSearch?: boolean; 14 | collapseHeightOnSearch?: boolean; 15 | theme?: "system" | "light" | "dark"; 16 | emojiPreviewName?: (emoji: EmojiObject) => string; 17 | }; 18 | export interface EmojiPickerRef { 19 | search: (query: string) => void; 20 | emojis: Record; 21 | focusedEmoji: EmojiObject | null; 22 | handleKeyDownScroll: (event: KeyboardEvent) => void; 23 | } 24 | export declare const EmojiPicker: React.ForwardRefExoticComponent>; 25 | export {}; 26 | //# sourceMappingURL=EmojiPicker.d.ts.map -------------------------------------------------------------------------------- /dist/types/EmojiPicker.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"EmojiPicker.d.ts","sourceRoot":"","sources":["../../src/EmojiPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAA6G,aAAa,EAAE,UAAU,EAAa,MAAM,OAAO,CAAA;AAE9K,OAAO,EAAE,WAAW,EAAkD,MAAM,SAAS,CAAA;AAMrF,aAAK,gBAAgB,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,GAAG,UAAU,KAAK,IAAI,CAAC;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC;CACnD,CAAA;AAID,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACtC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CAClE;AAmTD,eAAO,MAAM,WAAW,yFAAsC,CAAC"} -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Footer.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { EmojiObject } from "../utils"; 3 | declare const MemoizedFooter: React.NamedExoticComponent<{ 4 | [key: string]: any; 5 | emoji: EmojiObject | undefined; 6 | emojiPreviewName: any; 7 | }>; 8 | export default MemoizedFooter; 9 | //# sourceMappingURL=Footer.d.ts.map -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Footer.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Footer.d.ts","sourceRoot":"","sources":["../../../src/EmojiPicker/Footer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAatC,QAAA,MAAM,cAAc;;WAXoB,WAAW,GAAG,SAAS;;EAW5B,CAAA;AACnC,eAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Navbar.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { EmojiObject } from "../utils"; 3 | declare const MemoizedNavbar: React.NamedExoticComponent<{ 4 | [key: string]: any; 5 | data: Record; 6 | handleSelectInNavbar: Function; 7 | }>; 8 | export default MemoizedNavbar; 9 | //# sourceMappingURL=Navbar.d.ts.map -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Navbar.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Navbar.d.ts","sourceRoot":"","sources":["../../../src/EmojiPicker/Navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuE,MAAM,OAAO,CAAC;AAE5F,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAwDtC,QAAA,MAAM,cAAc;;UAtDmB,OAAO,MAAM,EAAE,WAAW,EAAE,CAAC;0BAAwB,QAAQ;EAsDjE,CAAA;AACnC,eAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Scroll.d.ts: -------------------------------------------------------------------------------- 1 | import React, { MutableRefObject, MouseEvent } from "react"; 2 | import { FixedSizeList as VirtualList } from 'react-window'; 3 | import { EmojiObject, itemRange } from '../utils'; 4 | declare type ScrollProps = { 5 | emojisPerRow: number; 6 | emojiSize: number; 7 | numberScrollRows: number; 8 | focusedEmoji: { 9 | emoji: EmojiObject; 10 | row: number; 11 | focusOnRender: boolean; 12 | preventScroll: boolean; 13 | } | null; 14 | emojiData: Record; 15 | refVirtualList: MutableRefObject; 16 | handleClickInScroll: (emoji: EmojiObject, row: number) => ((event: MouseEvent) => void) | undefined; 17 | handleMouseInScroll: (emoji: EmojiObject, row: number) => ((event: MouseEvent) => void) | undefined; 18 | itemCount: number; 19 | itemRanges: itemRange[]; 20 | collapseHeightOnSearch: boolean; 21 | }; 22 | declare const MemoizedScroll: React.NamedExoticComponent; 23 | export default MemoizedScroll; 24 | //# sourceMappingURL=Scroll.d.ts.map -------------------------------------------------------------------------------- /dist/types/EmojiPicker/Scroll.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Scroll.d.ts","sourceRoot":"","sources":["../../../src/EmojiPicker/Scroll.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAyE,gBAAgB,EAAiB,UAAU,EAAE,MAAM,OAAO,CAAC;AAClJ,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAiB,SAAS,EAAE,MAAM,UAAU,CAAA;AAGhE,aAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE;QAAC,KAAK,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAC,GAAG,IAAI,CAAC;IACvG,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,cAAc,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C,mBAAmB,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnH,mBAAmB,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnH,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,sBAAsB,EAAE,OAAO,CAAC;CACjC,CAAA;AA6GD,QAAA,MAAM,cAAc,yCAMlB,CAAC;AAEH,eAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./EmojiPicker"; 2 | export * from "./Emoji"; 3 | export * from "./utils"; 4 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /dist/types/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"} -------------------------------------------------------------------------------- /dist/types/utils.d.ts: -------------------------------------------------------------------------------- 1 | export interface EmojiObject { 2 | unicode: string; 3 | name: string; 4 | keywords?: string[]; 5 | } 6 | export declare function unifiedToNative(unified: string): any; 7 | export declare function measureScrollbar(): number; 8 | export declare type itemRange = { 9 | key: string; 10 | from: number; 11 | to: number; 12 | length: number; 13 | }; 14 | export declare function calcCountAndRange(data: Record, perRow: number): { 15 | itemCount: number; 16 | itemRanges: itemRange[]; 17 | }; 18 | export declare function shallowDiffer(prev: Object, next: Object): boolean; 19 | export declare function throttleIdleTask(callback: Function): (...args: any[]) => void; 20 | //# sourceMappingURL=utils.d.ts.map -------------------------------------------------------------------------------- /dist/types/utils.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,OAG9C;AAMD,wBAAgB,gBAAgB,IAAI,MAAM,CAQzC;AAQD,oBAAY,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AACjF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM;;;EAS5E;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIjE;AAGD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,aAId,GAAG,EAAE,UASzC"} -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Twemoji Picker 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /light-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrianHung/EmojiPicker/d047c8380bbdbda5b727ea1fa5402d3bdbc6a825/light-theme.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-twemoji-picker", 3 | "version": "0.1.0", 4 | "description": "👋 twitter emoji picker written in react", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/esm/index.js", 7 | "typings": "dist/types/index.d.ts", 8 | "sideEffects": [ 9 | "*.css" 10 | ], 11 | "repository": { 12 | "url": "https://github.com/brianhung/EmojiPicker" 13 | }, 14 | "scripts": { 15 | "start": "vite", 16 | "build": "rm -r -f dist/ && npm run build:esm && npm run build:cjs && npm run copy", 17 | "build:esm": "tsc --module es2020 --outDir dist/esm", 18 | "build:cjs": "tsc --module commonjs --outDir dist/cjs", 19 | "copy": "copyfiles -u 1 data/*.svg dist/cjs && copyfiles -u 1 data/*.svg dist/esm && copyfiles -u 1 src/**/*.css dist/", 20 | "build:website": "rm -r -f dist/ && vite build --sourcemap", 21 | "dev": "npm run start" 22 | }, 23 | "dependencies": { 24 | "react-window": "^1.8.6", 25 | "react-window-infinite-loader": "^1.0.7" 26 | }, 27 | "peerDependencies": { 28 | "react": "^16.8.0 || ^17.0.0" 29 | }, 30 | "devDependencies": { 31 | "@types/react": "^17.0.19", 32 | "@types/react-dom": "^17.0.9", 33 | "@vitejs/plugin-react-refresh": "^1.3.6", 34 | "adm-zip": "^0.5.5", 35 | "copyfiles": "^2.4.1", 36 | "emoji-keywords": "github:brianhung/emoji-keywords", 37 | "gulp": "^4.0.2", 38 | "gulp-filter": "^7.0.0", 39 | "gulp-svg-sprite": "^1.5.0", 40 | "lodash-es": "^4.17.21", 41 | "react": "^17.0.2", 42 | "react-dom": "^17.0.2", 43 | "superagent": "^6.1.0", 44 | "typescript": "^4.4.3", 45 | "vite": "^2.5.8" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /public/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrianHung/EmojiPicker/d047c8380bbdbda5b727ea1fa5402d3bdbc6a825/public/.nojekyll -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrianHung/EmojiPicker/d047c8380bbdbda5b727ea1fa5402d3bdbc6a825/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /scripts/json.js: -------------------------------------------------------------------------------- 1 | 2 | const { download, readJSON, saveJSON } = require("./utils"); 3 | 4 | const categories = ["Smileys & Emotion", "People & Body", "Animals & Nature", "Food & Drink", "Activities", "Travel & Places", "Objects", "Symbols", "Flags"]; 5 | 6 | const compareEmoji = (a, b) => { 7 | return a.category !== b.category ? categories.indexOf(a.category) - categories.indexOf(b.category) : a.sort_order - b.sort_order; 8 | } 9 | 10 | const unifiedToNative = (unified) => { 11 | const codePoints = unified.split('-').map(u => parseInt(u, 16)); 12 | return String.fromCodePoint.apply(String, codePoints); 13 | } 14 | 15 | const equalExceptVariationSelector = (a, b) => { 16 | return a == b || a == b.substring(0, b.length - 1) 17 | } 18 | 19 | const emojiKeywords = require("emoji-keywords"); 20 | 21 | function parseEmojiData({ name, unified, short_name, short_names, category, skin_variations }) { 22 | const emoji = { unicode: unified.toLowerCase(), name: short_name.replace(/_/g, '-'), category } 23 | const keywords = emojiKeywords.find(item => equalExceptVariationSelector(item.character, unifiedToNative(unified))) 24 | emoji.keywords = [...new Set([name && name.toLowerCase(), ...short_names.map(name => name.replace(/_/g, ' ')), ...(keywords && keywords.keywords)])].filter(Boolean) 25 | emoji.skins = skin_variations ? Object.values(skin_variations).map(v => v.unified.toLowerCase()) : undefined 26 | return emoji; 27 | } 28 | 29 | function groupByKey(list, key) { 30 | return list.reduce((groups, item) => { 31 | groups[item[key]] = groups[item[key]] || []; 32 | groups[item[key]].push(item); 33 | return groups; 34 | }, {}); 35 | } 36 | 37 | const parseEmojiJSON = (dataJSON) => { 38 | dataJSON = dataJSON.filter(d => !d.obsoleted_by && d.has_img_twitter && categories.includes(d.category)); // exclude 'Skin Tones' category 39 | dataJSON = dataJSON.sort(compareEmoji); // sort by category and by sort_order 40 | dataJSON = dataJSON.map(d => parseEmojiData(d)); // add keywords and skin variations 41 | dataJSON = groupByKey(dataJSON, "category"); // group by category 42 | Object.values(dataJSON).forEach(emojiList => emojiList.forEach(emoji => delete emoji["category"])) // delete the category key 43 | return dataJSON 44 | } 45 | 46 | download("https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji_pretty.json", "./data/emoji.json", 47 | (error) => { 48 | if (error !== undefined) { console.log(`handleJSON failed! ${error.message}`); return} 49 | const emojiJSON = readJSON("./data/emoji.json"); 50 | saveJSON(parseEmojiJSON(emojiJSON), "./data/twemoji.json") 51 | } 52 | ) 53 | 54 | -------------------------------------------------------------------------------- /scripts/sprite.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const filter = require('gulp-filter'); 3 | const sprite = require('gulp-svg-sprite'); 4 | const path = require('path'); 5 | 6 | const { download, extractZip, readJSON } = require("./utils"); 7 | 8 | const zipURL = "https://github.com/brianhung/twemoji/archive/master.zip" 9 | const zipPath = "./data/twemoji.zip" 10 | const svgPath = "./data/twemoji" 11 | 12 | /** 13 | * Callback function that's called when download completes. 14 | * @param {error} error 15 | */ 16 | function spriteCallback(error = undefined) { 17 | if (error !== undefined) { 18 | console.log(`handleZip failed! ${error.message}`) 19 | return 20 | } 21 | extractZip(zipPath, svgPath) 22 | 23 | let emojiJSON = readJSON("./data/twemoji.json") 24 | let emojiList = Object.values(emojiJSON).flat().map(emoji => emoji.unicode) 25 | 26 | const emojiFilter = filter(filename => emojiList.includes(path.parse(filename.relative).name)) 27 | const svgSprite = sprite({ 28 | mode: { defs: { dest: '.', prefix: 'emoji-%s', sprite: 'twemoji.svg', bust: false } } 29 | }) 30 | 31 | gulp.src(`${svgPath}/*.svg`) 32 | .pipe(emojiFilter) 33 | .pipe(svgSprite) 34 | .pipe(gulp.dest('./data/')) 35 | } 36 | 37 | download(zipURL, zipPath, spriteCallback) -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | const request = require('superagent'); 2 | const fs = require('fs'); 3 | const admZip = require('adm-zip'); 4 | 5 | exports.download = (url, dest, callback) => { 6 | request 7 | .get(url) 8 | .on('error', error => callback(error)) 9 | .pipe(fs.createWriteStream(dest)) 10 | .on('finish', () => callback()); 11 | } 12 | 13 | exports.readJSON = (path) => JSON.parse(fs.readFileSync(path)); 14 | 15 | exports.saveJSON = (objectJSON, dest) => fs.writeFileSync(dest, JSON.stringify(objectJSON)); 16 | 17 | exports.extractZip = (zipFile, outputDir) => { 18 | const zip = new admZip(zipFile) 19 | zip.extractEntryTo("twemoji-master/assets/svg/", outputDir, false, true); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Emoji.css: -------------------------------------------------------------------------------- 1 | /* https://github.com/twitter/twemoji#inline-styles */ 2 | .emoji-picker-emoji-inline { 3 | height: 1em; 4 | width: 1em; 5 | margin: 0 .05em 0 .1em; 6 | vertical-align: -0.1em; 7 | } -------------------------------------------------------------------------------- /src/Emoji.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { EmojiObject, unifiedToNative } from './utils' 3 | import twemoji from "./twemoji.svg" 4 | 5 | type EmojiProps = { 6 | emoji: EmojiObject; 7 | className?: string; 8 | [key: string]: any; 9 | } 10 | 11 | const Emoji: FC = ({emoji, className, ...props}) => { 12 | className = className ? `emoji-picker-emoji ${className}` : `emoji-picker-emoji` 13 | return ( 14 | {unifiedToNative(emoji.unicode)} 23 | ) 24 | } 25 | 26 | export { EmojiProps, Emoji }; 27 | export default Emoji; 28 | -------------------------------------------------------------------------------- /src/EmojiPicker.css: -------------------------------------------------------------------------------- 1 | .emoji-picker { 2 | display: flex; 3 | flex-direction: column; 4 | border-radius: 3px; 5 | background: white; 6 | border: 1px solid #E5E5E5; 7 | contain: content; 8 | } 9 | 10 | .emoji-picker .emoji-picker-scroll { 11 | -webkit-overflow-scrolling: touch; 12 | } 13 | 14 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-title { 15 | padding: 0 0.75em; 16 | text-transform: uppercase; 17 | font-weight: 500; 18 | font-size: 16px; 19 | color: #A3A3A3; 20 | user-select: none; 21 | height: 100%; 22 | display: flex; 23 | align-items: center; 24 | } 25 | 26 | .emoji-picker .emoji-picker-scroll .emoji-picker-category-emoji { 27 | padding: 0 0.50em; 28 | display: flex; 29 | list-style-type: none; 30 | margin: 0; 31 | height: 100%; 32 | } 33 | 34 | .emoji-picker .emoji-picker-emoji { 35 | display: inline-block; 36 | user-select: none; 37 | cursor: pointer; 38 | width: 28px; 39 | height: 28px; 40 | margin: 0; 41 | padding: 4px; 42 | border-radius: 3px; 43 | flex-shrink: 0; 44 | box-sizing: content-box; 45 | } 46 | 47 | .emoji-picker .emoji-picker-emoji-focused, 48 | .emoji-picker .emoji-picker-scroll .emoji-picker-emoji:hover, 49 | .emoji-picker .emoji-picker-navbar .emoji-picker-emoji:hover { 50 | background: #E5E5E5; 51 | } 52 | 53 | .emoji-picker .emoji-picker-category-emoji > li:active .emoji-picker-emoji { 54 | background: #D4D4D4; 55 | } 56 | 57 | .emoji-picker .emoji-picker-navbar { 58 | display: flex; 59 | height: fit-content; 60 | flex-direction: row; 61 | justify-content: space-evenly; 62 | border-bottom: 1px solid #E5E5E5; 63 | padding: 0.25em 9px; 64 | } 65 | 66 | .emoji-picker .emoji-picker-navbar .emoji-picker-navbar-category { 67 | appearance: none; 68 | background-color: inherit; 69 | margin: 0; 70 | padding: 0; 71 | border: none; 72 | height: 36px; 73 | } 74 | 75 | .emoji-picker .emoji-picker-footer { 76 | display: flex; 77 | flex-flow: row; 78 | align-items: center; 79 | border-top: 1px solid #E5E5E5; 80 | user-select: none; 81 | } 82 | 83 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji { 84 | width: 2.5em; 85 | height: 2.5em; 86 | padding: 0.50em; 87 | cursor: inherit; 88 | } 89 | 90 | .emoji-picker .emoji-picker-footer .emoji-picker-emoji:active { 91 | background: inherit !important; 92 | } 93 | 94 | .emoji-picker .emoji-picker-footer .emoji-picker-name { 95 | text-align: left; 96 | padding: 0 0.25em; 97 | } 98 | 99 | /* DARK THEME */ 100 | 101 | .emoji-picker.emoji-picker-dark { 102 | background: #404040; 103 | color: white; 104 | } 105 | .emoji-picker.emoji-picker-dark, .emoji-picker.emoji-picker-dark .emoji-picker-navbar, .emoji-picker.emoji-picker-dark .emoji-picker-footer { 106 | border-color: #404040; 107 | } 108 | .emoji-picker.emoji-picker-dark .emoji-picker-category-title { 109 | color: #D4D4D4; 110 | } 111 | .emoji-picker.emoji-picker-dark .emoji-picker-emoji-focused, 112 | .emoji-picker.emoji-picker-dark .emoji-picker-scroll .emoji-picker-emoji:hover, 113 | .emoji-picker.emoji-picker-dark .emoji-picker-navbar .emoji-picker-emoji:hover { 114 | background: #737373; 115 | } 116 | .emoji-picker.emoji-picker-dark .emoji-picker-category-emoji > li:active .emoji-picker-emoji, 117 | .emoji-picker.emoji-picker-dark .emoji-picker-navbar-category:active .emoji-picker-emoji { 118 | background: #A3A3A3; 119 | } 120 | 121 | @media (prefers-color-scheme: dark) { 122 | .emoji-picker.emoji-picker-system { 123 | background: #404040; 124 | color: white; 125 | } 126 | .emoji-picker.emoji-picker-system, .emoji-picker.emoji-picker-system .emoji-picker-navbar, .emoji-picker.emoji-picker-system .emoji-picker-footer { 127 | border-color: #404040; 128 | } 129 | .emoji-picker.emoji-picker-system .emoji-picker-category-title { 130 | color: #D4D4D4; 131 | } 132 | .emoji-picker.emoji-picker-system .emoji-picker-emoji-focused, 133 | .emoji-picker.emoji-picker-system .emoji-picker-scroll .emoji-picker-emoji:hover, 134 | .emoji-picker.emoji-picker-system .emoji-picker-navbar .emoji-picker-emoji:hover { 135 | background: #737373; 136 | } 137 | .emoji-picker.emoji-picker-system .emoji-picker-category-emoji > li:active .emoji-picker-emoji, 138 | .emoji-picker.emoji-picker-system .emoji-picker-navbar-category:active .emoji-picker-emoji { 139 | background: #A3A3A3; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/EmojiPicker.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useCallback, useState, useImperativeHandle, useMemo, useLayoutEffect, useRef, Ref, useReducer, KeyboardEvent, MouseEvent, useEffect } from "react" 2 | import { FixedSizeList as VirtualList } from 'react-window'; 3 | import { EmojiObject, measureScrollbar, calcCountAndRange, itemRange } from './utils' 4 | 5 | import Navbar from "./EmojiPicker/Navbar"; 6 | import Footer from "./EmojiPicker/Footer"; 7 | import Scroll from "./EmojiPicker/Scroll"; 8 | 9 | type EmojiPickerProps = { 10 | emojiData: Record; 11 | emojiSize?: number; 12 | onEmojiSelect?: (emoji: EmojiObject, event: KeyboardEvent | MouseEvent) => void; 13 | showNavbar?: boolean; 14 | showFooter?: boolean; 15 | showScroll?: boolean; 16 | emojisPerRow?: number; 17 | numberScrollRows?: number; 18 | onKeyDownScroll?: Function; 19 | collapseCategoriesOnSearch?: boolean; 20 | collapseHeightOnSearch?: boolean; 21 | theme?: "system" | "light" | "dark"; 22 | emojiPreviewName?: (emoji: EmojiObject) => string; 23 | } 24 | 25 | // Define public methods accessible via ref. 26 | 27 | export interface EmojiPickerRef { 28 | search: (query: string) => void; 29 | emojis: Record; 30 | focusedEmoji: EmojiObject | null; 31 | handleKeyDownScroll: (event: KeyboardEvent) => void; 32 | } 33 | 34 | type PickerState = { 35 | searchEmojis: {emojis: Record | null, query: string}, 36 | focusedEmoji: {emoji: EmojiObject, row: number, focusOnRender: boolean, preventScroll: boolean} | null 37 | } 38 | 39 | 40 | // Use state reducer to avoid separate re-renders to changes to searchEmojis and focusedEmoji. 41 | function EmojiPickerReducer({emojiData}) { 42 | return (prevState: PickerState, nextState: any): PickerState => { 43 | // reset focusedEmoji to first emoji on searchEmojis change 44 | if (nextState.searchEmojis && prevState.searchEmojis != nextState.searchEmojis) { 45 | let emojis = (nextState.searchEmojis?.query && nextState.searchEmojis?.emojis) || emojiData, 46 | category = emojis[Object.keys(emojis)[0]]; 47 | let emoji = category[0]; 48 | nextState.focusedEmoji = {row: 1, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false} 49 | } 50 | return {...prevState, ...nextState}; 51 | } 52 | } 53 | 54 | function EmojiPickerRefComponent({emojiData = {}, emojiSize = 36, numberScrollRows = 12, onEmojiSelect = (emoji: EmojiObject) => console.log(emoji), showNavbar = false, showFooter = false, showScroll = true, emojisPerRow = 9, onKeyDownScroll = (event) => null, collapseCategoriesOnSearch = true, collapseHeightOnSearch = true, theme = "system", emojiPreviewName = (emoji: EmojiObject) => emoji.name}: EmojiPickerProps, ref: Ref) { 55 | 56 | const pickerStateReducer = useCallback(EmojiPickerReducer({emojiData}), [emojiData]) 57 | const [ pickerState, setPickerState ] = useReducer(pickerStateReducer, { 58 | searchEmojis: {emojis: null, query: ""}, 59 | focusedEmoji: {row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false} 60 | }) 61 | 62 | const { itemCount, itemRanges } = useMemo(() => calcCountAndRange(pickerState.searchEmojis.emojis || emojiData, emojisPerRow), [pickerState.searchEmojis, emojisPerRow]); 63 | 64 | /** 65 | * TODO: Replace in-memory search with indexeddb index. 66 | * See as an example: https://github.com/nolanlawson/emoji-picker-element 67 | */ 68 | const search = (query: string): void => { 69 | const {searchEmojis} = pickerState; 70 | 71 | // reset pickerState when query is empty string 72 | if (!query) 73 | return setPickerState({ 74 | searchEmojis: {emojis: null, query: ""}, 75 | focusedEmoji: {row: 1, emoji: Object.values(emojiData).flat()[0], focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false} 76 | }); 77 | 78 | // assumption: increasing query length if prevSearchEmojis is empty will not change searchEmojis 79 | if (searchEmojis?.emojis && !Object.values(searchEmojis.emojis).flat().length && searchEmojis.query.length < query.length) 80 | return setPickerState({searchEmojis: {emojis: searchEmojis.emojis, query}}); 81 | 82 | // use prevSearchEmojis if query length has increased, else use full set 83 | const index = query.length > searchEmojis.query.length && searchEmojis.emojis != null 84 | ? Object.values(searchEmojis.emojis).flat() 85 | : Object.values(emojiData).flat(); 86 | 87 | // simple weighted search to filter emojiObjects 88 | let results = index 89 | .map(emoji => ({emoji, score: (emoji.keywords || []).map(word => word.indexOf(query) != -1).reduce((a, b) => a + Number(b), Number(emoji.name.indexOf(query) != -1) * 3)})) 90 | .filter(a => a.score) 91 | .sort((a, b) => b.score - a.score) 92 | .map(({emoji}) => emoji); 93 | 94 | if (collapseCategoriesOnSearch) { 95 | return setPickerState({searchEmojis: {emojis: {"Search Results": results}, query}}); 96 | } else { 97 | let grouped = Object.entries(emojiData).map(([category, list]) => ([category, list.filter(emoji => results.includes(emoji))])).reduce((sum, [category, list]) => Object.assign(sum, {[category as string]: list}), {}); 98 | return setPickerState({searchEmojis: {emojis: grouped, query}}); 99 | } 100 | } 101 | 102 | const refVirtualList = useRef(null); 103 | const refScroll = useRef(null); 104 | 105 | // Define event handlers in scroll element. 106 | 107 | const handleClickInScroll = (emoji: EmojiObject, row: number) => (event: MouseEvent) => { 108 | event.preventDefault(); // MDN docs: keep the focus from leaving the HTMLElement 109 | onEmojiSelect(emoji, event); 110 | setPickerState({focusedEmoji: {row, emoji, focusOnRender: true, preventScroll: true}}) 111 | } 112 | 113 | const handleMouseInScroll = (emoji: EmojiObject, row: number) => (event: MouseEvent) => { 114 | if (emoji == pickerState.focusedEmoji?.emoji || event.movementX == 0 && event.movementY == 0) return; 115 | event.preventDefault(); // MDN docs: keep the focus from leaving the HTMLElement 116 | // @ts-ignore 117 | const isSafari = window.safari !== undefined; // safari does not support preventScroll focus 118 | setPickerState({focusedEmoji: {row, emoji, focusOnRender: true, preventScroll: true}}) 119 | isSafari && refScroll.current && refScroll.current.focus(); 120 | } 121 | 122 | const handleKeyDownScroll = (event: KeyboardEvent) => { 123 | const {searchEmojis, focusedEmoji} = pickerState; 124 | const emojis = Object.values(searchEmojis.emojis || emojiData).filter(array => array.length !== 0); 125 | switch (event.key) { 126 | case "Enter": { 127 | event.preventDefault(); 128 | if (!focusedEmoji) { 129 | let emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0] 130 | emoji && setPickerState({focusedEmoji: {row: 1, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 131 | } else { 132 | focusedEmoji.emoji && onEmojiSelect(focusedEmoji.emoji, event); 133 | } 134 | return; 135 | } 136 | case 'Home': { 137 | event.preventDefault(); 138 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 139 | let emojis = searchEmojis.emojis || emojiData, 140 | category = emojis[Object.keys(emojis)[0]]; 141 | emoji = category[0] 142 | row = 1; 143 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 144 | } 145 | case 'End': { 146 | event.preventDefault(); 147 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 148 | let emojis = searchEmojis.emojis || emojiData, 149 | category = emojis[Object.keys(emojis).pop() as string]; 150 | emoji = category[category.length - 1] 151 | row = itemRanges[itemRanges.length - 1]?.to - 1; 152 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}); 153 | } 154 | case "ArrowUp": { 155 | event.preventDefault(); 156 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 157 | if (!focusedEmoji) { 158 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0]; 159 | row = 1; 160 | } else { 161 | let arrayIndex, arrayEmoji, emojiIndex; 162 | emojis.find((array, index) => { 163 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 164 | return emojiIndex !== -1; 165 | }) 166 | if (emojiIndex != undefined) { 167 | if (emojiIndex - emojisPerRow >= 0) { // not first row 168 | emoji = arrayEmoji[emojiIndex - emojisPerRow]; 169 | row = focusedEmoji.row - 1; 170 | } else if (arrayIndex !== 0) { 171 | const arrayAbove = emojis[arrayIndex - 1]; 172 | const index = (emojiIndex > (arrayAbove.length - 1) % emojisPerRow) ? arrayAbove.length - 1 : Math.floor((arrayAbove.length - 1 - emojiIndex) / emojisPerRow) * emojisPerRow + emojiIndex; 173 | emoji = arrayAbove[index]; // go directly up if possible; else last element 174 | row = focusedEmoji.row - 2; // skip category title row 175 | } 176 | } 177 | } 178 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 179 | } 180 | case "ArrowDown": { 181 | event.preventDefault(); 182 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 183 | if (!focusedEmoji) { 184 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0] 185 | row = 1; 186 | } else { 187 | let arrayIndex, arrayEmoji, emojiIndex; 188 | emojis.find((array, index) => { 189 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 190 | return emojiIndex !== -1; 191 | }) 192 | if (emojiIndex != undefined) { 193 | if (emojiIndex + emojisPerRow < arrayEmoji.length) { // not last row 194 | emoji = arrayEmoji[emojiIndex + emojisPerRow]; 195 | row = focusedEmoji.row + 1; 196 | } else if (emojiIndex + emojisPerRow < Math.ceil(arrayEmoji.length / emojisPerRow) * emojisPerRow) { 197 | emoji = arrayEmoji[arrayEmoji.length - 1]; 198 | row = focusedEmoji.row + 1; 199 | } else if (arrayIndex !== emojis.length - 1) { 200 | const arrayBelow = emojis[arrayIndex + 1], modIndex = emojiIndex % emojisPerRow; 201 | emoji = arrayBelow[modIndex] || arrayBelow[arrayBelow.length - 1] // go directly down if possible 202 | row = focusedEmoji.row + 2; // skip category title row 203 | } 204 | } 205 | } 206 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 207 | } 208 | case "ArrowLeft": { 209 | event.preventDefault(); 210 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 211 | if (!focusedEmoji) { 212 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0] 213 | row = 1; 214 | } else { 215 | let arrayIndex, arrayEmoji, emojiIndex; 216 | emojis.find((array, index) => { 217 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 218 | return emojiIndex !== -1; 219 | }) 220 | if (emojiIndex != undefined) { 221 | if (emojiIndex - 1 >= 0) { 222 | emoji = arrayEmoji[emojiIndex - 1]; 223 | row = Math.floor(emojiIndex/emojisPerRow) == Math.floor((emojiIndex - 1)/emojisPerRow) ? focusedEmoji.row : focusedEmoji.row - 1; 224 | } else if (arrayIndex !== 0) { // category above this one if it exists 225 | const arrayAbove = emojis[arrayIndex - 1]; 226 | emoji = arrayAbove[arrayAbove.length - 1]; 227 | row = focusedEmoji.row - 2; // skip category title row 228 | } 229 | } 230 | } 231 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 232 | } 233 | case "ArrowRight": { 234 | event.preventDefault(); 235 | let emoji: EmojiObject | undefined = undefined, row: number | undefined = undefined; 236 | if (!focusedEmoji) { 237 | emoji = Object.values(searchEmojis.emojis || emojiData).flat()[0] 238 | row = 1; 239 | } else { 240 | let arrayIndex, arrayEmoji, emojiIndex; 241 | emojis.find((array, index) => { 242 | emojiIndex = array.findIndex(emoji => emoji === focusedEmoji.emoji), arrayIndex = index, arrayEmoji = array; 243 | return emojiIndex !== -1; 244 | }) 245 | if (emojiIndex != undefined) { 246 | let newIndex = emojiIndex + 1; 247 | if (newIndex < arrayEmoji.length) { 248 | emoji = arrayEmoji[newIndex] 249 | row = Math.floor(emojiIndex/emojisPerRow) == Math.floor(newIndex/emojisPerRow) ? focusedEmoji.row : focusedEmoji.row + 1; 250 | } else if (arrayIndex !== emojis.length - 1) { 251 | let arrayBelow = emojis[arrayIndex + 1]; 252 | emoji = arrayBelow[0]; 253 | row = focusedEmoji.row + 2; // skip category title row 254 | } 255 | } 256 | } 257 | return row && emoji && setPickerState({focusedEmoji: {row, emoji, focusOnRender: Boolean(document.activeElement?.closest(".emoji-picker-scroll")), preventScroll: false}}) 258 | } 259 | default: 260 | return onKeyDownScroll(event); 261 | } 262 | } 263 | 264 | 265 | // Make internal state and methods as publicly accessible via ref. 266 | useImperativeHandle(ref, () => ({ 267 | search, 268 | handleKeyDownScroll, 269 | emojis: pickerState.searchEmojis.emojis || emojiData, 270 | focusedEmoji: pickerState.focusedEmoji?.emoji, 271 | }) as EmojiPickerRef) 272 | 273 | const ScrollProps = { 274 | emojiData: pickerState.searchEmojis.emojis || emojiData, 275 | emojisPerRow: emojisPerRow!, 276 | emojiSize, 277 | numberScrollRows, 278 | focusedEmoji: pickerState.focusedEmoji, 279 | refVirtualList, 280 | handleClickInScroll, 281 | handleMouseInScroll, 282 | collapseHeightOnSearch, 283 | itemCount, 284 | itemRanges, 285 | } 286 | 287 | 288 | // Define event handler for select in navbar element. 289 | const handleSelectInNavbar = (category: string) => { 290 | let virtualList = refVirtualList.current; 291 | if (virtualList) { 292 | let range: itemRange | undefined = itemRanges.find(range => range.key === category) 293 | if (range) { 294 | setPickerState({focusedEmoji: {row: range.from + 1, emoji: emojiData[category][0], focusOnRender: false, preventScroll: false}}) 295 | virtualList.scrollToItem(range.from, "start"); 296 | } 297 | } 298 | } 299 | 300 | const getWidths = () => { 301 | const scrollbarWidth = measureScrollbar() 302 | return { 303 | scrollbarWidth, 304 | width: `calc(${emojiSize}px * ${emojisPerRow} + 1em + ${scrollbarWidth}px)` 305 | } 306 | } 307 | 308 | // Compute width on window resize. 309 | const [width, setWidth] = useState(getWidths); 310 | useLayoutEffect(() => { 311 | let resizeWidth = () => setWidth(getWidths); 312 | window.addEventListener("resize", resizeWidth); 313 | return () => window.removeEventListener("resize", resizeWidth); 314 | }, []) 315 | 316 | return ( 317 |
318 | { showNavbar && 319 | 320 | } 321 |
322 | { pickerState.searchEmojis.emojis 323 | ? Object.values(pickerState.searchEmojis.emojis).flat().length 324 | ? 325 | :
326 |
No results
327 |
328 | : showScroll && 329 | 330 | } 331 |
332 | { showFooter && 333 |
334 | } 335 |
336 | ) 337 | } 338 | 339 | export const EmojiPicker = forwardRef(EmojiPickerRefComponent); -------------------------------------------------------------------------------- /src/EmojiPicker/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent, memo } from "react"; 2 | import Emoji from "../Emoji" 3 | import { EmojiObject } from "../utils" 4 | 5 | const Footer: FunctionComponent<{emoji: EmojiObject | undefined, emojiPreviewName, [key: string]: any}> = ({emoji, emojiPreviewName, ...props}) => { 6 | return ( 7 |
8 | { } 9 |
10 | { emoji ? emojiPreviewName(emoji) : Emoji Picker } 11 |
12 |
13 | ) 14 | } 15 | 16 | const MemoizedFooter = memo(Footer) 17 | export default MemoizedFooter; -------------------------------------------------------------------------------- /src/EmojiPicker/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent, useState, KeyboardEvent, MouseEvent, memo } from "react"; 2 | import Emoji from "../Emoji" 3 | import { EmojiObject } from "../utils" 4 | 5 | const Navbar: FunctionComponent<{data: Record, handleSelectInNavbar: Function, [key: string]: any}> = ({data, handleSelectInNavbar, ...props}) => { 6 | 7 | // roving tabindex 8 | const [index, setIndex] = useState(0); 9 | 10 | const onNavbarKeyDown = (event: KeyboardEvent) => { 11 | switch (event.key) { 12 | case 'Enter': 13 | return handleSelectInNavbar(Object.keys(data)[index]); 14 | case 'ArrowLeft': 15 | return index > 0 && setIndex(index => index - 1); 16 | case 'ArrowRight': 17 | return index < Object.keys(data).length - 1 && setIndex(index => index + 1) 18 | case 'Home': 19 | return index > 0 && setIndex(0); 20 | case 'End': 21 | return index < Object.keys(data).length - 1 && setIndex(Object.keys(data).length - 1) 22 | } 23 | } 24 | 25 | const onNavbarClick = (index: number, category: string) => (event: MouseEvent) => { 26 | setIndex(index); 27 | handleSelectInNavbar(category); 28 | } 29 | 30 | return ( 31 |
32 | { Object.entries(data).map(([category, list], i) => { 33 | const props = { 34 | className: "emoji-picker-navbar-category", 35 | key: `navbar-${category}`, 36 | onClick: onNavbarClick(i, category), 37 | onKeyDown: onNavbarKeyDown, 38 | role: "tab", 39 | "aria-label": category, 40 | "aria-selected": false, 41 | tabIndex: -1, 42 | ...i == index && { 43 | "aria-selected": true, 44 | tabIndex: 0, 45 | ref: (button: HTMLButtonElement) => Boolean(document.activeElement?.closest(".emoji-picker-navbar")) && button?.focus(), 46 | } 47 | } 48 | return ( 49 | 52 | ) 53 | } 54 | )} 55 |
56 | ) 57 | } 58 | 59 | const MemoizedNavbar = memo(Navbar) 60 | export default MemoizedNavbar; -------------------------------------------------------------------------------- /src/EmojiPicker/Scroll.tsx: -------------------------------------------------------------------------------- 1 | import React, { FunctionComponent, useEffect, useRef, Ref, useState, memo, forwardRef, MutableRefObject, CSSProperties, MouseEvent } from "react"; 2 | import { FixedSizeList as VirtualList } from 'react-window'; 3 | import InfiniteLoader from "react-window-infinite-loader"; 4 | import { EmojiObject, shallowDiffer, itemRange } from '../utils' 5 | import Emoji from "../Emoji"; 6 | 7 | type ScrollProps = { 8 | emojisPerRow: number, 9 | emojiSize: number, 10 | numberScrollRows: number, 11 | focusedEmoji: {emoji: EmojiObject, row: number, focusOnRender: boolean, preventScroll: boolean} | null, 12 | emojiData: Record; 13 | refVirtualList: MutableRefObject, 14 | handleClickInScroll: (emoji: EmojiObject, row: number) => ((event: MouseEvent) => void) | undefined, 15 | handleMouseInScroll: (emoji: EmojiObject, row: number) => ((event: MouseEvent) => void) | undefined, 16 | itemCount: number, 17 | itemRanges: itemRange[], 18 | collapseHeightOnSearch: boolean, 19 | } 20 | 21 | const Scroll: FunctionComponent = ({emojisPerRow, emojiSize, numberScrollRows, focusedEmoji, emojiData, refVirtualList, handleClickInScroll, handleMouseInScroll, itemCount, itemRanges, collapseHeightOnSearch}) => { 22 | 23 | const [arrayOfRows, setArrayOfRows] = useState>({}); 24 | const infiniteLoaderRef = useRef(null); 25 | 26 | // Keep track of previously focused emoji to avoid re-rendering all rows. 27 | const prevFocusedEmoji = useRef<{emoji: EmojiObject, row: number} | null>(null); 28 | 29 | // Reset arrayOfRows upon change in data or emojisPerRow. 30 | useEffect(function resetScrollState() { 31 | setArrayOfRows({}); 32 | infiniteLoaderRef?.current.resetloadMoreItemsCache(); 33 | prevFocusedEmoji.current = focusedEmoji; // focusedEmoji included in emojiData change render 34 | refVirtualList?.current.scrollToItem(0); 35 | loadMoreItems(0, Math.min(numberScrollRows + 10 - 1, itemRanges[itemRanges.length - 1].to)); // minimumBatchSize + threshold - 1 36 | }, [emojiData, emojisPerRow]); 37 | 38 | // Recompute the rows of the next and previous focusedEmoji upon change in focusedEmoji. 39 | useEffect(function resetRowsWithFocusedEmoji() { 40 | let prevEmoji = prevFocusedEmoji.current, nextEmoji = focusedEmoji; 41 | if (prevEmoji == nextEmoji) { return; } 42 | let rowsToUpdate = prevEmoji?.row == nextEmoji?.row ? [prevEmoji?.row] : [prevEmoji?.row, nextEmoji?.row] 43 | rowsToUpdate.forEach(row => row && loadMoreItems(row, row)); 44 | prevFocusedEmoji.current = nextEmoji; 45 | nextEmoji?.row && refVirtualList.current?.scrollToItem(nextEmoji.row); 46 | }, [focusedEmoji]); 47 | 48 | const loadMoreItems = (startIndex: number, endIndex: number) => { 49 | const nextArrayOfRows = {} 50 | let i = startIndex, range: itemRange | undefined; 51 | while (i <= endIndex) { 52 | 53 | range = itemRanges.find(range => range.from <= i && i < range.to); 54 | if (range === undefined) break; 55 | 56 | for (let rowIndex = i; rowIndex < Math.min(range.to, endIndex + 1); rowIndex++) { 57 | if (rowIndex == range.from) { 58 | nextArrayOfRows[rowIndex] =
{range.key}
59 | } else { 60 | 61 | const offset = rowIndex - range.from; 62 | const row = emojiData[range.key].slice((offset - 1) * emojisPerRow, offset * emojisPerRow) 63 | 64 | nextArrayOfRows[rowIndex] = ( 65 |
    66 | { row.map((emoji: EmojiObject, colIndex: number) => { 67 | const liProps = { 68 | key: emoji.unicode, 69 | onClick: handleClickInScroll(emoji, rowIndex), 70 | onMouseMove: handleMouseInScroll(emoji, rowIndex), 71 | role: "gridcell", 72 | "aria-rowindex": rowIndex + 1, 73 | "aria-colindex": colIndex + 1, 74 | tabIndex: -1, 75 | ...emoji === focusedEmoji?.emoji && { 76 | tabIndex: 0, 77 | ref: (li: HTMLLIElement) => focusedEmoji.focusOnRender && li?.focus({preventScroll: focusedEmoji.preventScroll}), 78 | } 79 | } 80 | const emojiProps = { 81 | emoji, 82 | ...emoji === focusedEmoji?.emoji && { 83 | className: "emoji-picker-emoji-focused", 84 | } 85 | } 86 | return ( 87 |
  • 88 | 89 |
  • 90 | ) 91 | }) 92 | } 93 |
94 | ) 95 | } 96 | } 97 | i = range.to; 98 | } 99 | setArrayOfRows(prev => Object.assign({}, prev, nextArrayOfRows)); 100 | } 101 | 102 | return ( 103 | !!arrayOfRows[index]} 108 | minimumBatchSize={numberScrollRows} 109 | threshold={10} 110 | > 111 | {({onItemsRendered, ref}) => ( 112 | {ref(list); refVirtualList && (refVirtualList.current = list);}} 115 | itemCount={itemCount} 116 | itemData={arrayOfRows} 117 | itemSize={emojiSize} 118 | height={collapseHeightOnSearch ? Math.min(itemCount * emojiSize + 9, numberScrollRows * emojiSize) : numberScrollRows * emojiSize} 119 | innerElementType={innerElementType} 120 | > 121 | {MemoizedRow} 122 | 123 | )} 124 | 125 | ) 126 | } 127 | 128 | const MemoizedScroll = memo(Scroll, function ScrollPropsAreEqual(prevProps, nextProps) { 129 | return prevProps.focusedEmoji?.emoji == nextProps.focusedEmoji?.emoji 130 | && prevProps.emojiData == nextProps.emojiData 131 | && prevProps.collapseHeightOnSearch == nextProps.collapseHeightOnSearch 132 | && prevProps.emojiSize == nextProps.emojiSize 133 | && prevProps.emojisPerRow == nextProps.emojisPerRow; 134 | }); 135 | 136 | export default MemoizedScroll; 137 | 138 | const VirtualRow: FunctionComponent<{index: number, style: CSSProperties, data}> = ({index, style, data}) => { 139 | return ( 140 |
141 | {data[index]} 142 |
143 | ) 144 | } 145 | 146 | /** 147 | * memoize rows of the virtualList, only re-rendering when changing in data[index] 148 | */ 149 | const MemoizedRow = memo(VirtualRow, function compareRowProps(prevProps, nextProps) { 150 | const { style: prevStyle, data: prevData, index: prevIndex, ...prevRest } = prevProps; 151 | const { style: nextStyle, data: nextData, index: nextIndex, ...nextRest } = nextProps; 152 | return prevData[prevIndex] === nextData[nextIndex] && !shallowDiffer(prevStyle, nextStyle) && !shallowDiffer(prevRest, nextRest) 153 | }); 154 | 155 | 156 | /** 157 | * adds padding to the bottom of virtual list 158 | * See: https://github.com/bvaughn/react-window#can-i-add-padding-to-the-top-and-bottom-of-a-list 159 | */ 160 | const LIST_PADDING_SIZE = 9; 161 | const innerElementType = forwardRef(({style, ...props }: {style: CSSProperties}, ref: Ref) => ( 162 | // @ts-ignore 163 |
166 | )); -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./EmojiPicker"; 2 | export * from "./Emoji"; 3 | export * from "./utils"; -------------------------------------------------------------------------------- /src/static.d.ts: -------------------------------------------------------------------------------- 1 | /* Use this file to declare any custom file extensions for importing */ 2 | /* Use this folder to also add/extend a package d.ts file, if needed. */ 3 | 4 | declare module '*.css'; 5 | 6 | declare module '*.svg' { 7 | const ref: string; 8 | export default ref; 9 | } 10 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export interface EmojiObject { 2 | unicode: string; 3 | name: string; 4 | keywords?: string[]; 5 | } 6 | 7 | /** 8 | * Converts from unified to native representation of an emoji. 9 | * @param unified unified representation 10 | */ 11 | export function unifiedToNative(unified: string) { 12 | const codePoints = unified.split('-').map(u => parseInt(u, 16)); 13 | return String.fromCodePoint.apply(String, codePoints); 14 | } 15 | 16 | /** 17 | * Measures the pixel width of a scrollbar. 18 | * source: https://github.com/sonicdoe/measure-scrollbar. 19 | */ 20 | export function measureScrollbar(): number { 21 | if (typeof document == 'undefined') return 0; 22 | const div = document.createElement('div'); 23 | div.style.cssText = "width:100px; height:100px; overflow:scroll; position:absolute; top:-9999px"; 24 | document.body.appendChild(div); 25 | const scrollbarWidth = div.offsetWidth - div.clientWidth; 26 | document.body.removeChild(div); 27 | return scrollbarWidth; 28 | } 29 | 30 | /** 31 | * Calculates the number of rows when key and array are flattened, along 32 | * with an array of ranges to map an index back to key. 33 | * @param data key array mapping 34 | * @param perRow number of elements to chunk array into 35 | */ 36 | export type itemRange = { key: string; from: number; to: number; length: number } 37 | export function calcCountAndRange(data: Record, perRow: number) { 38 | let itemCount = 0, itemRanges: itemRange[] = []; 39 | Object.entries(data).forEach(([key, array]) => { 40 | if (array.length === 0) return; 41 | let from = itemCount, to = itemCount + 1 + Math.ceil(array.length / perRow); 42 | itemRanges.push({key, from, to, length: array.length}); 43 | itemCount = to; 44 | }) 45 | return {itemCount, itemRanges}; 46 | } 47 | 48 | // Returns true if objects shallowly differ. 49 | export function shallowDiffer(prev: Object, next: Object): boolean { 50 | for (let attribute in prev) { if (!(attribute in next)) { return true; }} 51 | for (let attribute in next) { if (prev[attribute] !== next[attribute]) { return true; }} 52 | return false; 53 | } 54 | 55 | // Trailing throttle function. 56 | export function throttleIdleTask(callback: Function) { 57 | // @ts-ignore 58 | const idleHandler = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout; 59 | let running = false, argsFunc: any; 60 | return function throttled(...args: any[]) { 61 | argsFunc = args; 62 | if (running) { return; } 63 | running = true; 64 | idleHandler(() => { 65 | running = false; 66 | callback.apply(null, argsFunc); 67 | }) 68 | } 69 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/*"], 3 | "exclude": ["node_modules", "website"], 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "noEmit": false, 7 | "sourceMap": true, 8 | "strict": false, 9 | "strictNullChecks": true, 10 | "noImplicitAny": false, 11 | "esModuleInterop": true, 12 | "moduleResolution": "node", 13 | "allowJs": true, 14 | "target": "es6", 15 | "lib": ["es2019", "dom"], 16 | "jsx": "react", 17 | "types": ["react"], 18 | "rootDir": "src", 19 | "outDir": "dist", 20 | "stripInternal": true, 21 | "removeComments": true, 22 | "declarationMap": true, 23 | "declaration": true, 24 | "declarationDir": "dist/types" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "routes": [ 3 | { 4 | "src": "/_assets/(.*)", 5 | "headers": { "cache-control": "max-age=14400" }, 6 | "dest": "/_assets/$1" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import reactRefresh from '@vitejs/plugin-react-refresh' 3 | 4 | export default { 5 | plugins: [reactRefresh()], 6 | base: process.env["base"] || "/EmojiPicker/", 7 | json: { 8 | stringify: true, // faster parse for emoji data 9 | }, 10 | build: { 11 | rollupOptions: { 12 | output: { 13 | entryFileNames: `assets/[name].js`, 14 | chunkFileNames: `assets/[name].js`, 15 | assetFileNames: `assets/[name].[ext]` 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /website/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://rsms.me/inter/inter.css'); 2 | 3 | :root { 4 | --sansSerif: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | } 10 | 11 | html { 12 | background-color: rgb(255,255,255); 13 | color: rgb(29, 29, 31); 14 | font-family: 'Inter', var(--sansSerif); 15 | font-size: 18px; 16 | } 17 | 18 | body { 19 | margin: 0; 20 | } 21 | 22 | a { 23 | text-decoration: none; 24 | color: #06c; 25 | } 26 | 27 | a:hover, a:active, html a:focus { 28 | text-decoration: underline; 29 | } 30 | 31 | p { 32 | text-align: center; 33 | } 34 | 35 | h1 { 36 | font-size: 2.25rem; 37 | font-weight: 700; 38 | margin-bottom: 0; 39 | letter-spacing: -.01rem; 40 | } 41 | 42 | .emoji-picker { 43 | margin: 0.5rem 0; 44 | } 45 | 46 | input { 47 | font-size: 1rem; 48 | margin-top: 0.5rem; margin-bottom: 1rem; 49 | padding: 0.35rem 0.50rem; 50 | border-radius: 4px; 51 | border: 1px solid rgb(225, 225, 224); 52 | font-family: 'Inter', var(--sansSerif); 53 | } 54 | 55 | #notification { 56 | position: fixed; 57 | bottom: 20px; 58 | display: flex; 59 | justify-content: center; 60 | z-index: 1; 61 | pointer-events: none; 62 | } 63 | 64 | #notification div { 65 | background: black; 66 | color: white; 67 | font-size: 1rem; 68 | padding: 0.40rem 0.50rem; 69 | border-radius: 4px; 70 | opacity: 0.1; 71 | transition: 250ms all ease-in; 72 | transform: translate3d(0, 80px, 0); 73 | display: flex; 74 | align-items: center; 75 | } 76 | 77 | #notification.visible div { 78 | transform: translate3d(0, 0, 0); 79 | transition: 120ms all cubic-bezier(0.25, 0.47, 0.44, 0.93); 80 | opacity: 1; 81 | } 82 | -------------------------------------------------------------------------------- /website/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useCallback, useState, ChangeEvent, KeyboardEvent } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import type { EmojiObject } from '../src/index'; 4 | import { EmojiPicker, EmojiPickerRef, unifiedToNative, throttleIdleTask } from '../src/index'; 5 | import EmojiData from "../data/twemoji.json" 6 | import './index.css'; 7 | 8 | import "../src/EmojiPicker.css" 9 | import "../src/Emoji.css" 10 | 11 | const copyToClipboard = async (string: string) => { 12 | try { 13 | // Try to use the Async Clipboard API with fallback to the legacy approach. 14 | // @ts-ignore 15 | const {state} = await navigator.permissions.query({name: 'clipboard-write'}); 16 | if (state !== 'granted') { throw new Error('Clipboard permission not granted'); } 17 | await navigator.clipboard.writeText(string); 18 | } catch { 19 | const textArea = document.createElement('textarea'); 20 | textArea.value = string; 21 | document.body.appendChild(textArea); 22 | textArea.select(); 23 | document.execCommand('copy'); 24 | document.body.removeChild(textArea); 25 | } 26 | }; 27 | 28 | function ExampleSetup() { 29 | 30 | const picker = useRef() 31 | const input = useRef() 32 | 33 | // need reference to same function to throttle 34 | const throttledQuery = useCallback(throttleIdleTask((query: string) => picker.current?.search(query)), [picker.current]); 35 | 36 | const inputProps = { 37 | ref: input, 38 | placeholder: "search-or-navigate", 39 | onChange: (event: ChangeEvent) => throttledQuery((event.target as HTMLInputElement).value.toLowerCase()), 40 | onKeyDown: (event: KeyboardEvent) => { 41 | if (!["Enter", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return; 42 | picker.current.handleKeyDownScroll(event); 43 | if (event.key == "Enter" && !event.shiftKey) { 44 | picker.current.search(""); 45 | input.current.value = ""; 46 | } 47 | }, 48 | } 49 | 50 | const onEmojiSelect = (emoji: EmojiObject) => { 51 | const nativeEmoji = unifiedToNative(emoji.unicode); 52 | copyToClipboard(nativeEmoji); 53 | notification.show(`Copied ${nativeEmoji} to clipboard`); 54 | console.log(emoji); 55 | } 56 | 57 | const emojiPickerProps = { 58 | ref: picker, 59 | emojiData: EmojiData, 60 | onEmojiSelect, 61 | showNavbar: true, 62 | showFooter: true, 63 | collapseHeightOnSearch: false, 64 | } 65 | 66 | /** 67 | * Adaptation of show-and-hide popup from https://rsms.me/inter/#charset for React hooks. 68 | * Ignore this if you're just using this website as an example of how to setup the emoji picker. 69 | */ 70 | const [notification] = useState(() => { 71 | 72 | let timer = null 73 | let visible = false 74 | 75 | const show = (message) => { 76 | const el = document.querySelector('#notification') as HTMLDivElement; 77 | (el.firstChild as HTMLElement).innerText = message 78 | el.classList.add('visible') 79 | if (visible) { 80 | hide() 81 | setTimeout(() => show(message), 120) 82 | return 83 | } 84 | visible = true 85 | el.style.visibility = null 86 | clearTimeout(timer) 87 | timer = setTimeout(() => hide(), 1200) 88 | } 89 | 90 | const hide = () => { 91 | const el = document.querySelector('#notification') as HTMLDivElement; 92 | if (visible) { 93 | el.classList.remove('visible') 94 | visible = false 95 | el.style.visibility = 'hidden' 96 | } 97 | } 98 | 99 | return { show } 100 | }) 101 | 102 | return ( 103 |
104 |

Emoji Picker

105 |

A virtualized twemoji picker written in React and TypeScript.

106 | 107 | 108 | source code → 109 |
110 |
111 |
112 |
113 | ) 114 | } 115 | 116 | ReactDOM.render(, document.getElementById('example-setup')); --------------------------------------------------------------------------------