UNPKG

rn-emoji-picker

Version:

React ⚛️ Native ☎️ Emoji 😋 Picker ⛏️ | super light weight, dark/light mode, 0 dependencies, 6.45 kB

115 lines 6.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.emojiFromUtf16 = void 0; const react_1 = require("react"); const react_native_1 = require("react-native"); const tabBar_1 = require("./tabBar"); const input_1 = require("./input"); const constants_1 = require("./constants"); const sectionHeader_1 = require("./sectionHeader"); const emojiRow_1 = require("./emojiRow"); const utils_1 = require("./utils"); // helper fn for end users see https://github.com/yonahforst/react-native-emoji-picker/issues/4 const emojiFromUtf16 = (utf16) => String.fromCodePoint(...utf16.split('-').map(u => '0x' + u)); exports.emojiFromUtf16 = emojiFromUtf16; const EmojiPicker = ({ recent = [], emojis = [], loading = false, autoFocus = true, darkMode = true, backgroundColor = darkMode ? '#000' : '#fff', perLine = 8, onSelect = (emoji) => null, onChangeRecent = (recent) => { }, defaultCategory = 'emotion', enabledCategories = constants_1.categoryKeys, }) => { const [searchQuery, setSearchQuery] = (0, react_1.useState)(''); const [width, setWidth] = (0, react_1.useState)(0); const colSize = Math.floor(width / perLine); const sectionList = (0, react_1.useRef)(null); const [init, setInit] = (0, react_1.useState)(true); const finalCategories = constants_1.categories.filter(category => enabledCategories.includes(category.key)); const [category, setCategory] = (0, react_1.useState)(finalCategories.find(c => c.key === defaultCategory) || finalCategories[1]); // smiley const { sections } = (0, react_1.useMemo)(() => { const emojiList = {}; // map of emojis to categories finalCategories.forEach(category => { const key = category.key; const list = key === constants_1.RECENT ? recent : (0, utils_1.sortEmojis)((0, utils_1.emojiByCategory)(category.name, emojis)); emojiList[key] = (0, utils_1.chunkEmojis)(list, key, perLine); }); const sections = finalCategories.map(category => ({ name: category.name, key: category.key, data: emojiList[category.key] })); return ({ sections }); }, [emojis, finalCategories, recent]); const searchResults = (0, react_1.useMemo)(() => { if (!searchQuery.length) return []; let emoji; const filtered = emojis.filter(e => { const term = searchQuery.toLowerCase(); if (term.includes(e.emoji)) { emoji = e; // if user types an emoji select it return true; } return e.keywords.some(e => e.includes(term)); }); if (emoji) onSelect(emoji); return [{ name: 'Search results', key: constants_1.SEARCH, data: (0, utils_1.chunkEmojis)(filtered, constants_1.SEARCH, perLine) }]; // create one section on results }, [emojis, searchQuery]); const selectTab = (category) => { setSearchQuery(''); setCategory(category); setInit(false); }; const selectEmoji = (emoji) => { onSelect(emoji); addToRecent(emoji); }; const addToRecent = (emoji) => { const newRecent = []; const existing = recent.find(h => h.unified === emoji.unified); if (existing) { // if already saved, bump to the front const filtered = recent.filter(h => h.unified !== emoji.unified); newRecent.push(emoji, ...filtered); } else { // add to the front newRecent.push(emoji, ...recent); } onChangeRecent(newRecent.splice(0, 18)); }; const renderSectionHeader = ({ section }) => <sectionHeader_1.default name={section.name}/>; const renderEmojiRow = ({ item }) => <emojiRow_1.default selectEmoji={selectEmoji} rowItems={item.data} colSize={colSize}/>; const activeSection = sections.find(s => s.key === category.key); return (<react_native_1.View style={[styles.container, { backgroundColor }]} onLayout={event => setWidth(event.nativeEvent.layout.width)}> <tabBar_1.TabBar activeCategory={category} onPress={selectTab} categories={finalCategories} darkMode={darkMode} width={width}/> <react_native_1.View style={{ flex: 1 }}> <react_native_1.View style={styles.searchbarContainer}> <input_1.Input placeholder="Search..." value={searchQuery} onChangeText={setSearchQuery} autoFocus={autoFocus} darkMode={darkMode}/> </react_native_1.View> {!loading ? (<react_native_1.SectionList style={{ flex: 1 }} sections={searchQuery ? searchResults : init && recent.length ? [sections[0], activeSection] : [activeSection]} keyExtractor={(item) => item.key} renderItem={renderEmojiRow} renderSectionHeader={renderSectionHeader} contentContainerStyle={{ paddingBottom: colSize }} horizontal={false} keyboardShouldPersistTaps={"handled"} removeClippedSubviews showsVerticalScrollIndicator={false} stickySectionHeadersEnabled={false} ref={sectionList} onScrollBeginDrag={react_native_1.Keyboard.dismiss}/> // <SectionList // style={{flex: 1}} // sections={searchResults.length ? searchResults : sections} // keyExtractor={item => item.key} // renderItem={renderEmojiRow} // renderSectionHeader={renderSectionHeader} // contentContainerStyle={{paddingBottom: colSize}} // horizontal={false} // keyboardShouldPersistTaps={'handled'} // removeClippedSubviews={true} // showsVerticalScrollIndicator={false} // stickySectionHeadersEnabled={false} // ref={sectionList} // initialNumToRender={total} // @todo calc section list item layout see calcSectionItemLayout util method // onScrollBeginDrag={Keyboard.dismiss} // onViewableItemsChanged={data => { // update category from scroll pos // const categoryKey = data.viewableItems[0]?.item?.category // if (!categoryKey || categoryKey === category.key) return // if (categoryKey === 'search') return setCategory(categories[0]) // setCategory(categories.find(c => c.key === categoryKey)!) // }} // /> ) : (<react_native_1.View style={styles.loader}> <react_native_1.ActivityIndicator size="large" color="#323333"/> </react_native_1.View>)} </react_native_1.View> </react_native_1.View>); }; const styles = react_native_1.StyleSheet.create({ container: { flex: 1, width: '100%' }, loader: { flex: 1, alignItems: 'center', justifyContent: 'center' }, searchbarContainer: { width: '100%', zIndex: 1, padding: 8 }, sectionHeader: { margin: 8, fontSize: 17, width: '100%', color: '#999' } }); exports.default = EmojiPicker; //# sourceMappingURL=index.js.map