react-native-emojis-picker
Version:
A simple emoji picker for React Native and Expo. It's built with TypeScript and uses Reanimated 2 for smooth animations.
383 lines (372 loc) • 11.9 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
EmojiModal: () => Modal,
EmojiProvider: () => Provider
});
module.exports = __toCommonJS(src_exports);
// src/components/modal/modal.tsx
var import_non_secure = require("nanoid/non-secure");
var import_react = require("react");
var import_portal = require("@gorhom/portal");
var import_react_native5 = require("react-native");
var import_expo_blur = require("expo-blur");
// src/components/modal/filterBar.tsx
var import_react_native2 = require("react-native");
// src/helper.ts
var import_emoji_datasource = __toESM(require("emoji-datasource"));
var emojis = import_emoji_datasource.default;
var Categories = [
{
symbol: "\u{1F600}",
key: "Smileys & Emotion"
},
{
symbol: "\u{1F9D1}",
key: "People & Body"
},
{
symbol: "\u{1F984}",
key: "Animals & Nature"
},
{
symbol: "\u{1F354}",
key: "Food & Drink"
},
{
symbol: "\u26BE\uFE0F",
key: "Activities"
},
{
symbol: "\u2708\uFE0F",
key: "Travel & Places"
},
{
symbol: "\u{1F4A1}",
key: "Objects"
},
{
symbol: "\u{1F523}",
key: "Symbols"
},
{
symbol: "\u{1F1F8}\u{1F1E6}",
key: "Flags"
}
];
function charFromUtf16(utf16) {
return String.fromCodePoint(
...utf16.split("-").map((u) => "0x" + u)
);
}
function charFromEmojiObject(obj) {
return charFromUtf16(obj.unified);
}
var filteredEmojis = emojis.filter((e2) => !e2["obsoleted_by"]);
// src/constants.ts
var import_react_native = require("react-native");
var { width: screenWidth, height: screenHeight } = import_react_native.Dimensions.get("window");
// src/components/modal/filterBar.tsx
var import_jsx_runtime = require("react/jsx-runtime");
function FilterBar({
onPress,
selectedCategory,
categories,
darkMode
}) {
const result = Categories.filter(
(item) => categories.find((el) => el === item.key)
);
const size = Math.floor((screenWidth - 80) / 9);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_native2.View,
{
style: [
styles.wrapper,
{ borderColor: darkMode ? "#5C5470" : "#f2f2f2" }
],
children: result.map((category, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_native2.TouchableOpacity,
{
onPress: () => onPress(category.key),
style: {
opacity: selectedCategory === category.key ? 1 : 0.3,
width: size,
height: size
},
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.icon, children: category.symbol })
},
index
))
}
);
}
var styles = import_react_native2.StyleSheet.create({
wrapper: {
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 20,
paddingBottom: 10,
borderBottomWidth: 2
},
icon: {
fontSize: screenHeight * 0.025
}
});
// src/components/modal/search.tsx
var import_react_native3 = require("react-native");
var import_jsx_runtime2 = require("react/jsx-runtime");
function Search({ darkMode, ...props }) {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_react_native3.TextInput,
{
style: [styles2.search, darkMode && { backgroundColor: "#5C5470" }],
placeholderTextColor: "#8E8E93",
...props
}
);
}
var styles2 = import_react_native3.StyleSheet.create({
search: {
paddingHorizontal: 10,
paddingVertical: 15,
marginHorizontal: 20,
marginVertical: 10,
borderRadius: 10,
backgroundColor: "#f2f2f2"
}
});
// src/components/modal/emojiCell.tsx
var import_react_native4 = require("react-native");
var import_jsx_runtime3 = require("react/jsx-runtime");
function EmojiCell({
emoji,
onPress,
colSize
}) {
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
import_react_native4.TouchableOpacity,
{
style: { ...styles3.wrapper, width: colSize, height: colSize },
onPress: () => onPress(emoji),
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: { fontSize: colSize - 5 }, children: charFromEmojiObject(emoji) })
}
);
}
var styles3 = import_react_native4.StyleSheet.create({
wrapper: {
borderRadius: 10,
justifyContent: "center",
alignItems: "center"
}
});
// src/components/modal/modal.tsx
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
var import_jsx_runtime4 = require("react/jsx-runtime");
var AnimatedBlurView = import_react_native_reanimated.default.createAnimatedComponent(import_expo_blur.BlurView);
function Modal({
intensityBlur = 20,
columns = 10,
onEmojiSelected,
onPressOutside,
categories = [
"Smileys & Emotion",
"Activities",
"Animals & Nature",
"Flags",
"Food & Drink",
"Objects",
"People & Body",
"Symbols",
"Travel & Places"
],
position = "center",
darkMode = false,
autoFocusSearch = false
}) {
const [search, setSearch] = (0, import_react.useState)("");
const [selectedCategory, setSelectedCategory] = (0, import_react.useState)(categories[0]);
const key = (0, import_react.useMemo)(() => `modal-${(0, import_non_secure.nanoid)()}`, []);
const colSize = Math.floor((screenWidth - 80) / columns);
const positionStyle = (0, import_react.useMemo)(() => {
switch (position) {
case "top":
return "flex-start";
case "bottom":
return "flex-end";
default:
return "center";
}
}, [position]);
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_portal.Portal, { name: key, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.SafeAreaView, { style: styles4.safeArea, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
import_react_native5.KeyboardAvoidingView,
{
keyboardVerticalOffset: import_react_native5.Platform.OS === "ios" ? 10 : 0,
style: [styles4.container, { justifyContent: positionStyle }],
behavior: import_react_native5.Platform.OS === "ios" ? "padding" : "height",
children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
AnimatedBlurView,
{
entering: import_react_native_reanimated.FadeIn,
exiting: import_react_native_reanimated.FadeOut,
onTouchStart: onPressOutside,
style: styles4.blur,
intensity: intensityBlur
}
),
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
import_react_native_reanimated.default.View,
{
entering: import_react_native_reanimated.FadeInDown.springify(),
exiting: import_react_native_reanimated.FadeOutDown,
style: [styles4.modal, darkMode && { backgroundColor: "#352F44" }],
children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
FilterBar,
{
darkMode,
categories,
onPress: (key2) => setSelectedCategory(key2),
selectedCategory
}
),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
Search,
{
darkMode,
autoFocus: autoFocusSearch,
placeholder: "Search..",
value: search,
onChangeText: (value) => setSearch(value)
}
),
!search && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
import_react_native5.Text,
{
style: [styles4.title, { color: darkMode ? "white" : "black" }],
children: selectedCategory
}
),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
import_react_native5.FlatList,
{
numColumns: columns,
showsVerticalScrollIndicator: false,
ListEmptyComponent: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.View, { style: styles4.noResultWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.Text, { style: styles4.noResultText, children: "No Results" }) }),
contentContainerStyle: styles4.flatlistContainer,
data: emojis.filter((item) => {
if (search === "") {
return item.category === selectedCategory;
} else {
return item.name.includes(search.toLocaleUpperCase());
}
}),
keyExtractor: (_, index) => index.toString(),
renderItem: ({ item }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
EmojiCell,
{
colSize,
emoji: item,
onPress: (emoji) => onEmojiSelected(charFromEmojiObject(emoji))
}
)
}
)
]
}
)
]
}
) }) }, key);
}
var styles4 = import_react_native5.StyleSheet.create({
safeArea: {
height: screenHeight,
width: screenWidth,
position: "absolute"
},
container: {
zIndex: 1e3,
alignItems: "center",
height: "100%",
width: "100%"
},
blur: {
position: "absolute",
zIndex: 1,
height: screenHeight,
width: screenWidth
},
modal: {
zIndex: 10,
paddingVertical: 20,
height: "auto",
maxHeight: screenHeight / 2,
width: screenWidth - 40,
borderRadius: 20,
backgroundColor: "white",
// shadow
shadowColor: "#000",
shadowOffset: { width: 2, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 30
},
title: {
marginLeft: 20,
fontSize: 20,
marginVertical: 10
},
flatlistContainer: {
marginHorizontal: 20
},
noResultWrapper: {
marginVertical: 10,
flex: 1,
justifyContent: "center",
alignItems: "center"
},
noResultText: {
fontSize: 16,
color: "#666"
}
});
// src/components/provider/provider.tsx
var import_portal2 = require("@gorhom/portal");
var import_jsx_runtime5 = require("react/jsx-runtime");
function Provider({ children }) {
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_portal2.PortalProvider, { children });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
EmojiModal,
EmojiProvider
});