@amaui/ui-react
Version:
UI for React
320 lines (319 loc) • 17.9 kB
JavaScript
"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;