UNPKG

@amaui/ui-react

Version:
320 lines (319 loc) 17.9 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = __importDefault(require("react")); const utils_1 = require("@amaui/utils"); const style_react_1 = require("@amaui/style-react"); const IconMaterialMoodW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialMoodW100")); const IconMaterialEmojiNatureW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiNatureW100")); const IconMaterialEmojiFoodBeverageW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiFoodBeverageW100")); const IconMaterialHikingW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialHikingW100")); const IconMaterialEmojiTransportationW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiTransportationW100")); const IconMaterialEmojiObjectsW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiObjectsW100")); const IconMaterialEmojiSymbolsW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiSymbolsW100")); const IconMaterialEmojiFlagsW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialEmojiFlagsW100")); const Menu_1 = __importDefault(require("../Menu/Menu")); const Line_1 = __importDefault(require("../Line")); const SpyScroll_1 = __importDefault(require("../SpyScroll")); const List_1 = __importDefault(require("../List")); const ListSubheader_1 = __importDefault(require("../ListSubheader")); const Tabs_1 = __importDefault(require("../Tabs")); const TextField_1 = __importDefault(require("../TextField")); const Tab_1 = __importDefault(require("../Tab")); const Type_1 = __importDefault(require("../Type")); const Surface_1 = __importDefault(require("../Surface")); const emojis_list_1 = __importDefault(require("./emojis_list")); const utils_2 = require("../utils"); const useStyle = (0, style_react_1.style)(theme => ({ root: {}, wrapper: { height: '70vh', width: '70vw', borderRadius: theme.methods.shape.radius.value(2, 'px'), boxShadow: 'rgba(0, 0, 0, 0.07) 0px 4px 32px 0px', overflow: 'hidden' }, size_small: { maxWidth: 276, maxHeight: 276 }, size_regular: { maxWidth: 340, maxHeight: 340 }, size_large: { maxWidth: 404, maxHeight: 404 }, main: { position: 'relative', height: 0, overflow: 'hidden auto' }, header: { padding: `${theme.methods.space.value(1.5, 'px')} ${theme.methods.space.value(1.5, 'px')} 0` }, categories: { height: '100%', userSelect: 'none' }, category: { paddingInlineStart: theme.methods.space.value(1.5, 'px') }, emoji: { position: 'relative', textAlign: 'center', cursor: 'pointer', transition: theme.methods.transitions.make('transform'), '&$emoji_selected': { '&::before': { content: '""', position: 'absolute', width: 'calc(100% + 4px)', height: 'auto', aspectRatio: '1/1', background: theme.palette.background.default.tertiary, inset: '0', borderRadius: theme.methods.shape.radius.value(40, 'px'), zIndex: '0', left: '50%', transform: 'translate(-50%)', top: '-1px' } }, '&:active': { transform: 'scale(0.94)' } }, emoji_size_small: { fontSize: '1.5rem', width: 24 }, emoji_size_regular: { fontSize: '2rem', width: 32 }, emoji_size_large: { fontSize: '2.5rem', width: 40 }, unicode: { position: 'relative', zIndex: 1 }, subheader: { backdropFilter: 'blur(2px)', background: 'transparent', '&.amaui-ListSubheader-root': { zIndex: 14 } }, tabs: { '&.amaui-Tabs-root': { background: 'transparent' }, '& .amaui-Tabs-tabs': { minWidth: '100%' } }, tab: { '&.amaui-Tab-root': { minWidth: 'unset' } }, tab_size_small: { '&.amaui-Tab-root': { padding: `${theme.methods.space.value(1, 'px')} ${theme.methods.space.value(0.75, 'px')}` } }, tab_size_regular: { '&.amaui-Tab-root': { padding: `${theme.methods.space.value(1, 'px')} ${theme.methods.space.value(1.25, 'px')}` } }, tab_size_large: { '&.amaui-Tab-root': { padding: `${theme.methods.space.value(1, 'px')} ${theme.methods.space.value(1.25, 'px')}` } } }), { name: 'amaui-Emojis' }); const Emojis = react_1.default.forwardRef((props_, ref) => { const theme = (0, style_react_1.useAmauiTheme)(); const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiEmojis) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]); const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]); const Menu = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Menu) || Menu_1.default; }, [theme]); const List = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.List) || List_1.default; }, [theme]); const ListSubheader = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ListSubheader) || ListSubheader_1.default; }, [theme]); const SpyScroll = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.SpyScroll) || SpyScroll_1.default; }, [theme]); const Tabs = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Tabs) || Tabs_1.default; }, [theme]); const TextField = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.TextField) || TextField_1.default; }, [theme]); const Tab = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Tab) || Tab_1.default; }, [theme]); const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]); const Surface = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Surface) || Surface_1.default; }, [theme]); const EMOJI_CATEGORIES = [ { "name": "Smileys and People", "groups": ["Smiley", "Gesture", "Person", "Clothing"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialMoodW100_1.default, {}) }, { "name": "Animals and Nature", "groups": ["Animal", "Nature"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiNatureW100_1.default, {}) }, { "name": "Food and Drink", "groups": ["Food"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiFoodBeverageW100_1.default, {}) }, { "name": "Activity", "groups": ["Activity"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialHikingW100_1.default, {}) }, { "name": "Travel and Places", "groups": ["Travel"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiTransportationW100_1.default, {}) }, { "name": "Objects", "groups": ["Object"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiObjectsW100_1.default, {}) }, { "name": "Symbols", "groups": ["Symbol"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiSymbolsW100_1.default, {}) }, { "name": "Flags and Countries", "groups": ["Flag", "Country"], "icon": (0, jsx_runtime_1.jsx)(IconMaterialEmojiFlagsW100_1.default, {}) } ]; const { tonal = true, color = 'themed', label: label_, onSelect: onSelect_, emojis = emojis_list_1.default, categories = EMOJI_CATEGORIES, selected, size = 'regular', search: search_ = true, tabs: tabs_ = true, className } = props, other = __rest(props, ["tonal", "color", "label", "onSelect", "emojis", "categories", "selected", "size", "search", "tabs", "className"]); const { classes } = useStyle(); const [open, setOpen] = react_1.default.useState(false); const [openElement, setOpenElement] = react_1.default.useState(); const [search, setSearch] = react_1.default.useState(); const [tab, setTab] = react_1.default.useState(categories[0].name); const refs = { main: react_1.default.useRef(undefined) }; const onOpen = react_1.default.useCallback(() => { setOpen(true); setTimeout(() => { setOpenElement(refs.main.current || null); }, 140); }, []); const onClose = react_1.default.useCallback(() => { setOpen(false); setTimeout(() => { setOpenElement(null); }, 140); }, []); const onSelect = react_1.default.useCallback((valueNew) => { if ((0, utils_1.is)('function', onSelect_)) onSelect_(valueNew); }, [onSelect_]); const emojisPerCategory = react_1.default.useMemo(() => { const value = {}; if ((0, utils_1.is)('array', categories)) { categories.forEach(item => { const groups = {}; emojis.forEach(emoji => { const alias = ((0, utils_1.is)('array', emoji.alias) ? emoji.alias : [emoji.alias]).join('').toLowerCase(); if (item.groups.includes(emoji.category) && (!search || alias.includes(search.toLowerCase()))) { if (!groups[emoji.category]) groups[emoji.category] = []; groups[emoji.category].unshift(emoji); } }); value[item.name] = []; item.groups.forEach(group => { var _a; if (!!((_a = groups[group]) === null || _a === void 0 ? void 0 : _a.length)) value[item.name].push(...groups[group]); }); }); Object.keys(value).forEach(item => { if (!value[item].length) delete value[item]; }); } return value; }, [search, emojis, categories]); const onChangeSearch = react_1.default.useCallback((0, utils_1.debounce)((valueNew) => { setSearch(valueNew); }, 140), []); const onChangeTabs = react_1.default.useCallback((valueNew) => { setTab(valueNew); }, []); const onActiveTab = react_1.default.useCallback((valueNew) => { setTab(valueNew.replace(/-/g, ' ')); }, []); const onTabClick = react_1.default.useCallback((valueNew) => { var _a; const elements = Array.from(((_a = refs.main.current) === null || _a === void 0 ? void 0 : _a.children) || []); if (!!elements.length) { const element = elements.find((item) => item.dataset.amauiCategory === valueNew); if (element) { const top = element.offsetTop; const offset = -1; refs.main.current.scroll({ left: 0, top: (0, utils_1.clamp)(top - offset, 0), behavior: 'smooth' }); } } }, []); const categoriesUsed = Object.keys(emojisPerCategory); const categoryToID = (valueNew) => valueNew.replace(/ /g, '-'); const categoriesUsedIDs = categoriesUsed.map(item => categoryToID(item)); const tabs = categories.filter(item => categoriesUsed.some(item_ => item.name === item_)).map(item => ({ name: item.icon, value: item.name })); const label = ((0, jsx_runtime_1.jsx)(Line, Object.assign({ tonal: tonal, color: color, Component: Surface, className: (0, style_react_1.classNames)([ classes.wrapper, classes[`size_${size}`] ]) }, { children: (0, jsx_runtime_1.jsx)(SpyScroll, Object.assign({ ids: categoriesUsedIDs, parent: openElement, onActive: onActiveTab }, { children: (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0, align: 'unset', justify: 'unset', fullWidth: true, className: classes.categories }, { children: [(search_ || tabs_) && ((0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 1, fullWidth: true, className: classes.header }, { children: [search_ && ((0, jsx_runtime_1.jsx)(TextField, { name: 'Search', version: 'outlined', onChange: onChangeSearch, size: ['small', 'regular'].includes(size) ? 'small' : 'regular', fullWidth: true, clear: true })), tabs_ && !!categoriesUsed.length && ((0, jsx_runtime_1.jsx)(Tabs, Object.assign({ valueDefault: tab, value: tab, onChange: onChangeTabs, size: 'small', initialLineUpdateTimeout: 440, noDivider: true, className: classes.tabs }, { children: tabs.map((item, index) => ((0, jsx_runtime_1.jsx)(Tab, Object.assign({ value: item.value, onClick: () => onTabClick(item.value), "data-amaui-spy-scroll": categoryToID(item.value), className: (0, style_react_1.classNames)([ classes.tab, classes[`tab_size_${size}`] ]) }, { children: react_1.default.cloneElement(item.name, { size: ['small', 'regular'].includes(size) ? 'small' : 'regular' }) }), index))) })))] }))), (0, jsx_runtime_1.jsx)(Line, Object.assign({ ref: refs.main, gap: 0, flex: true, fullWidth: true, className: classes.main }, { children: categoriesUsed.map((item, index) => ((0, jsx_runtime_1.jsxs)(List, Object.assign({ gap: 1, fullWidth: true, SurfaceProps: { id: categoryToID(item), 'data-amaui-category': item } }, { children: [(0, jsx_runtime_1.jsx)(ListSubheader, Object.assign({ className: classes.subheader }, { children: (0, jsx_runtime_1.jsx)(Type, Object.assign({ version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3' }, { children: item })) })), (0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 1, direction: 'row', align: 'center', wrap: 'wrap', Component: 'li', className: classes.category }, { children: emojisPerCategory[item].map((emoji, index_) => ((0, jsx_runtime_1.jsx)("span", Object.assign({ onClick: () => onSelect(emoji), title: (0, utils_1.capitalize)(((0, utils_1.is)('array', emoji.alias) ? emoji.alias.join(', ') : emoji.alias).replace(/_/g, ' ')), className: (0, style_react_1.classNames)([ classes.emoji, classes[`emoji_size_${size}`], (selected === null || selected === void 0 ? void 0 : selected.includes(emoji.unicode)) && classes.emoji_selected ]) }, { children: (0, jsx_runtime_1.jsx)("span", Object.assign({ className: classes.unicode }, { children: emoji.unicode })) }), index_))) }))] }), index))) }))] })) })) }))); return ((0, jsx_runtime_1.jsx)(Menu, Object.assign({ open: open, onOpen: onOpen, onClose: onClose, label: label, className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Emojis', theme) && [ 'amaui-Emojis-root', `amaui-Emojis-size-${size}` ], className, classes.root ]) }, other))); }); Emojis.displayName = 'amaui-Emojis'; exports.default = Emojis;