diff --git a/src/common/emoji-select/components/categories/categories.scss b/src/common/emoji-select/components/categories/categories.scss new file mode 100644 index 0000000000000000000000000000000000000000..1b268bee783fe30a0f0ae98eceb957a4778940fe --- /dev/null +++ b/src/common/emoji-select/components/categories/categories.scss @@ -0,0 +1,50 @@ +@include b('emoji-categories') { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; + height: getCssVar('height-control', 'large'); + padding: 0 getCssVar('spacing', 'base-loose'); + margin-bottom: getCssVar('spacing', 'tight'); + overflow-x: auto; + + @include e('category') { + display: flex; + align-items: center; + min-width: getCssVar('font-size', 'header-4'); + height: 100%; + font-size: getCssVar('font-size', 'header-4'); + cursor: pointer; + + @include m('svg') { + line-height: getCssVar('font-size', 'header-6'); + + svg { + fill: getCssVar('color', 'text', 3); + } + } + + &:hover, + &.is-active { + position: relative; + + &::after { + position: absolute; + bottom: 0; + display: block; + width: 100%; + content: ''; + border-top: getCssVar('spacing', 'super-tight') solid getCssVar('color', 'primary'); + } + } + + &:hover { + color: getCssVar('color', 'primary'); + + svg { + fill: getCssVar('color', 'primary'); + } + } + } +} diff --git a/src/common/emoji-select/components/categories/categories.tsx b/src/common/emoji-select/components/categories/categories.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3cce0c215db4d911e4f9b61bd798a96e798641d0 --- /dev/null +++ b/src/common/emoji-select/components/categories/categories.tsx @@ -0,0 +1,53 @@ +import { PropType, defineComponent } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import './categories.scss'; +import { showTitle } from '@ibiz-template/core'; + +export const Categories = defineComponent({ + name: 'IBizCategories', + props: { + categories: { + type: Array as PropType, + required: true, + default: () => [], + }, + current: { + type: String, + required: true, + }, + }, + emits: ['select'], + setup(props, { emit }) { + const ns = useNamespace('emoji-categories'); + + // 选择表情分类 + const onSelect = (category: IData) => { + emit('select', category); + }; + + return { ns, onSelect }; + }, + render() { + return ( +
+ {this.categories.map((category: IData) => { + return ( +
this.onSelect(category)} + > + +
+ ); + })} +
+ ); + }, +}); diff --git a/src/common/emoji-select/components/categories/index.ts b/src/common/emoji-select/components/categories/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..a8c829f2b3f70ca7e566d4ee2b357a1a8bdc2432 --- /dev/null +++ b/src/common/emoji-select/components/categories/index.ts @@ -0,0 +1 @@ +export * from './categories'; diff --git a/src/common/emoji-select/components/category-label/category-label.scss b/src/common/emoji-select/components/category-label/category-label.scss new file mode 100644 index 0000000000000000000000000000000000000000..6613dce3de4be50286f78a66f745996ec0cc78e6 --- /dev/null +++ b/src/common/emoji-select/components/category-label/category-label.scss @@ -0,0 +1,6 @@ +@include b('emoji-category-label') { + padding: getCssVar('spacing', 'tight') getCssVar('spacing', 'extra-tight'); + font-size: getCssVar('font-size', 'regular'); + color: getCssVar('color', 'text', 3); + text-transform: uppercase; +} diff --git a/src/common/emoji-select/components/category-label/category-label.tsx b/src/common/emoji-select/components/category-label/category-label.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8fab2f72331a31170406bae950878c2db8a44443 --- /dev/null +++ b/src/common/emoji-select/components/category-label/category-label.tsx @@ -0,0 +1,21 @@ +import { defineComponent } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import './category-label.scss'; + +export const CategoryLabel = defineComponent({ + name: 'IBizCategoryLabel', + props: { + name: { + type: String, + default: '', + }, + }, + emits: ['select'], + setup() { + const ns = useNamespace('emoji-category-label'); + return { ns }; + }, + render() { + return
{this.name}
; + }, +}); diff --git a/src/common/emoji-select/components/category-label/index.ts b/src/common/emoji-select/components/category-label/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..884ab4bb1e2831ff0bab670c37e9c510f4a623bf --- /dev/null +++ b/src/common/emoji-select/components/category-label/index.ts @@ -0,0 +1 @@ +export * from './category-label'; diff --git a/src/common/emoji-select/components/emoji-item/emoji-item.scss b/src/common/emoji-select/components/emoji-item/emoji-item.scss new file mode 100644 index 0000000000000000000000000000000000000000..caed7ec570dd031d6396f884554baf5d5df51bc7 --- /dev/null +++ b/src/common/emoji-select/components/emoji-item/emoji-item.scss @@ -0,0 +1,14 @@ +@include b('emoji-item') { + box-sizing: content-box; + display: flex; + align-items: center; + justify-self: center; + padding: getCssVar('spacing', 'tight'); + overflow: hidden; + cursor: pointer; + + &.is-border:hover { + background: getCssVar('color', 'bg', 0); + border-radius: getCssVar('border-radius', 'small'); + } +} diff --git a/src/common/emoji-select/components/emoji-item/emoji-item.tsx b/src/common/emoji-select/components/emoji-item/emoji-item.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f3af7d7f63f80afe0210b0358664337d9c8b4cbb --- /dev/null +++ b/src/common/emoji-select/components/emoji-item/emoji-item.tsx @@ -0,0 +1,53 @@ +import { PropType, defineComponent, computed } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import './emoji-item.scss'; + +export const EmojiItem = defineComponent({ + name: 'IBizEmojiItem', + props: { + emoji: { + type: Object as PropType, + required: true, + default: () => {}, + }, + size: { + type: Number, + required: true, + }, + withBorder: { + type: Boolean, + required: true, + }, + }, + emits: ['click'], + setup(props, { emit }) { + const ns = useNamespace('emoji-item'); + + // 用于动态计算表情的样式大小 + const styleSize = computed(() => { + return { + fontSize: `${props.size - 5}px`, + lineHeight: `${props.size}px`, + height: `${props.size}px`, + width: `${props.size}px`, + }; + }); + + // 点击表情项 + const onClick = () => { + emit('click', props.emoji); + }; + + return { ns, styleSize, onClick }; + }, + render() { + return ( + + ); + }, +}); diff --git a/src/common/emoji-select/components/emoji-item/index.ts b/src/common/emoji-select/components/emoji-item/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..950ea48af7eeb6472b78623047856904627df5f3 --- /dev/null +++ b/src/common/emoji-select/components/emoji-item/index.ts @@ -0,0 +1 @@ +export * from './emoji-item'; diff --git a/src/common/emoji-select/components/emoji-list/emoji-list.scss b/src/common/emoji-select/components/emoji-list/emoji-list.scss new file mode 100644 index 0000000000000000000000000000000000000000..26a834e68f0c8121c45ec984d3f72232dd4219b9 --- /dev/null +++ b/src/common/emoji-select/components/emoji-list/emoji-list.scss @@ -0,0 +1,26 @@ +@include b('emoji-list') { + display: block; + width: 100%; + max-width: 100%; + padding-top: getCssVar('spacing', 'tight'); + background-color: getCssVar('color', 'bg', 0); + + ::-webkit-scrollbar { + width: 0; + margin-right: 0; + overflow: hidden; + border-radius: 0; + } + + @include e('container') { + height: 100%; + max-height: 27vh; + padding: 0 getCssVar('spacing', 'super-tight'); + overflow-y: scroll; + } + + @include m('grid-emojis') { + display: grid; + justify-items: center; + } +} diff --git a/src/common/emoji-select/components/emoji-list/emoji-list.tsx b/src/common/emoji-select/components/emoji-list/emoji-list.tsx new file mode 100644 index 0000000000000000000000000000000000000000..183edcca3ac37d5584f0a98754a9c30f3d0b3e6b --- /dev/null +++ b/src/common/emoji-select/components/emoji-list/emoji-list.tsx @@ -0,0 +1,213 @@ +import { PropType, defineComponent, computed, watch, ref } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { CategoryLabel } from '../category-label'; +import { EmojiItem } from '../emoji-item'; +import './emoji-list.scss'; + +const searchByAlias = (term: string, emoji: IData) => { + const isRelevant = (alias: string) => alias.toLowerCase().includes(term); + + return emoji.aliases.some((alias: string) => isRelevant(alias)); +}; + +export const EmojiList = defineComponent({ + name: 'IBizEmojiList', + props: { + data: { + type: Object as PropType, + required: true, + }, + emojisByRow: { + type: Number, + required: true, + }, + emojiWithBorder: { + type: Boolean, + }, + emojiSize: { + type: Number, + }, + filter: { + type: String, + default: '', + }, + continuousList: { + type: Boolean, + }, + category: { + type: String, + default: '', + }, + categories: { + type: Object as PropType, + required: true, + default: () => {}, + }, + hasSearch: { + type: Boolean, + }, + }, + emits: ['select', 'data'], + setup(props, { emit }) { + const ns = useNamespace('emoji-list'); + const emojisRef = ref({}); + // 存储表情种类元素的Ref集合 + const categoryRefs = ref({}); + + // 用于过滤表情数据 + const dataFiltered = computed(() => { + // 从props中获取当前分类下的表情数据 + let data = props.data[props.category]; + const searchValue = props.filter.trim().toLowerCase(); + + if (searchValue) { + // 如果搜索值存在,过滤出匹配搜索值的表情 + data = data.filter((emoji: IData) => searchByAlias(searchValue, emoji)); + } + + return data; + }); + + // 用于获取所有的表情种类 + const categories = computed(() => { + return Object.keys(props.data); + }); + + // 设置动态引用的函数,将对应的DOM元素引用存储到categoryRefs中 + const setCategoryRef = (categoryName: string, el: Element): void => { + if (el) { + categoryRefs.value[categoryName] = el; + } + }; + + // 计算滚动条顶部的位置 + const calcScrollTop = () => { + return props.hasSearch ? 88 : 8; + }; + + // 用于动态计算网格布局 + const gridDynamic = computed(() => { + const percent = 100 / props.emojisByRow; + return { + gridTemplateColumns: `repeat(${props.emojisByRow}, ${percent}%)`, + }; + }); + + // 用于过滤每个分类下的表情数据 + const dataFilteredByCategory = computed(() => { + const _data: IData = {}; + Object.assign(_data, props.data); + const searchValue = props.filter.trim().toLowerCase(); + + if (searchValue) { + categories.value.forEach((category: string) => { + _data[category] = props.data[category].filter((item: IData) => + searchByAlias(searchValue, item), + ); + }); + } + + return _data; + }); + + // 当表情被选中时触发的函数 + const onSelect = (emoji: IData) => { + emit('select', emoji); + }; + + watch( + () => props.data, + () => { + // 将滚动条置为0 + emojisRef.value.$el.scrollTop = 0; + }, + ); + + watch( + () => props.category, + newValue => { + if (props.continuousList) { + const categoryEl = categoryRefs.value[newValue].$el; + // 计算滚动条位置 + emojisRef.value.scrollTop = categoryEl.offsetTop - calcScrollTop(); + } + }, + ); + + // 绘制表格展示表情包 + const renderGridEmojis = (params: IData) => { + const { emojis, style, size, withBorder } = params; + return emojis && emojis.length > 0 ? ( +
+ {emojis.map((emoji: IData) => { + return ( + onSelect(emoji)} + /> + ); + })} +
+ ) : ( + '' + ); + }; + + return { + ns, + emojisRef, + gridDynamic, + dataFiltered, + dataFilteredByCategory, + onSelect, + setCategoryRef, + renderGridEmojis, + }; + }, + render() { + return ( +
+
+ {this.continuousList + ? Object.keys(this.dataFilteredByCategory).map( + (categoryName: string) => { + const category = this.dataFilteredByCategory[categoryName]; + const categoriesItem = this.categories[categoryName]; + const labelName = categoriesItem + ? categoriesItem.text + : categoryName; + return ( +
+ {category.length ? ( + + this.setCategoryRef(categoryName, el as Element) + } + /> + ) : ( + '' + )} + {this.renderGridEmojis({ + emojis: category, + style: this.gridDynamic, + size: this.emojiSize!, + withBorder: this.emojiWithBorder, + })} +
+ ); + }, + ) + : this.renderGridEmojis({ + emojis: this.dataFiltered || [], + style: this.gridDynamic, + size: this.emojiSize!, + withBorder: this.emojiWithBorder, + })} +
+
+ ); + }, +}); diff --git a/src/common/emoji-select/components/emoji-list/index.ts b/src/common/emoji-select/components/emoji-list/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..d92cb0df6c789b28bd401289c82714a9bda36802 --- /dev/null +++ b/src/common/emoji-select/components/emoji-list/index.ts @@ -0,0 +1 @@ +export * from './emoji-list'; diff --git a/src/common/emoji-select/components/index.ts b/src/common/emoji-select/components/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f6b0fc0a0c77b62ffe6653c4b77e41e403b4464 --- /dev/null +++ b/src/common/emoji-select/components/index.ts @@ -0,0 +1,4 @@ +export * from './categories'; +export * from './category-label'; +export * from './emoji-item'; +export * from './emoji-list'; diff --git a/src/common/emoji-select/emoji-select.scss b/src/common/emoji-select/emoji-select.scss new file mode 100644 index 0000000000000000000000000000000000000000..4a70641dfb971687664e4cc1f149354d77feb47f --- /dev/null +++ b/src/common/emoji-select/emoji-select.scss @@ -0,0 +1,9 @@ +@include b('emoji-select') { + display: inline-flex; + flex-direction: column; + align-items: center; + width: 100%; + overflow: hidden; + font-size: getCssVar('font-size', 'regular'); + user-select: none; +} diff --git a/src/common/emoji-select/emoji-select.tsx b/src/common/emoji-select/emoji-select.tsx new file mode 100644 index 0000000000000000000000000000000000000000..31c1f54683cffb125b2579c1f20324e92048aa53 --- /dev/null +++ b/src/common/emoji-select/emoji-select.tsx @@ -0,0 +1,296 @@ +import { + PropType, + computed, + defineComponent, + onMounted, + onUnmounted, + ref, + watch, +} from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { Emoji, ICategory, IEmoji } from './interface'; +import { categoriesDefault, emojisDefault } from './icons'; +import { Categories, EmojiList } from './components'; +import './emoji-select.scss'; + +export const IBizEmojiSelect = defineComponent({ + name: 'IBizEmojiSelect', + props: { + // 自定义表情符号数组,类型为IEmoji[],必填项,默认值为emojisDefault + customEmojis: { + type: Array as PropType, + required: true, + default: () => emojisDefault, + }, + // 自定义分类数组,类型为ICategory[],必填项,默认值为categoriesDefault + customCategories: { + type: Array as PropType, + required: true, + default: () => [], + }, + // 频繁使用表情符号的数量限制 + limitFrequently: { + type: Number, + default: 15, + }, + // 每行显示的表情符号数量 + emojisByRow: { + type: Number, + default: 8, + }, + // 是否使用连续列表显示表情符号 + continuousList: { + type: Boolean, + default: false, + }, + // 表情符号的大小 + emojiSize: { + type: Number, + default: 27, + }, + // 表情符号是否带有边框 + emojiWithBorder: { + type: Boolean, + default: true, + }, + // 是否显示搜索框 + showSearch: { + type: Boolean, + default: true, + }, + // 是否显示分类 + showCategories: { + type: Boolean, + default: true, + }, + // 是否使用深色模式 + dark: { + type: Boolean, + default: false, + }, + // 初始选择的分类 + initialCategory: { + type: String, + default: 'peoples', + }, + // 需要排除的分类数组 + exceptCategories: { + type: Array as PropType, + default: () => [], + }, + // 需要排除的表情符号数组 + exceptEmojis: { + type: Array as PropType, + default: () => [], + }, + }, + emits: ['select', 'changeCategory', 'customEmojis'], + setup(props, { emit }) { + const ns = useNamespace('emoji-select'); + // 存储自定义的表情数据 + const customEmojis = ref([]); + // 存储自定义的表情分类数据 + const customCategories = ref([]); + // 存储初始的分类名 + const initialCategory = ref('peoples'); + // 存储需要排除的分类数据 + const exceptCategories = ref([]); + // 存储需要排除的表情数据 + const exceptEmojis = ref([]); + // 存储频繁使用的表情索引 + const frequentlyEmojis = ref([]); + + // 用于映射分类名到分类数据 + const mapCategories = ref({}); + // 用于映射表情到分类 + const mapEmojis = ref({}); + // 存储当前选中的分类名 + const currentCategory = ref(''); + currentCategory.value = initialCategory.value; + // 用于存储搜索过滤的关键词 + const filterEmoji = ref(''); + // 获取所有分类的名称 + const categoriesNames = customCategories.value.map((c: IData) => c.name); + // 如果初始分类不在提供的分类列表中,则将初始分类设置为第一个分类 + if (!categoriesNames.includes(initialCategory.value)) { + initialCategory.value = categoriesNames[0]; + } + + // 搜索函数,用于过滤表情 + const onSearch = async (term: string) => { + filterEmoji.value = term; + }; + + // 计算属性,用于过滤除排除分类外的所有分类 + const categoriesFiltered = computed(() => { + return customCategories.value.filter( + category => !exceptCategories.value.includes(category), + ); + }); + + // 映射分类数据到 mapCategories 对象 + const mapperCategories = (categories: IData[]) => { + categories.forEach((category: IData) => { + Object.assign(mapCategories.value, { [category.name]: category }); + }); + }; + + // 映射特定分类下的表情数据到 mapEmojis 对象 + const mapperEmojisCategory = (emojis: IData[]) => { + // 初始化 frequently(常用) 属性为一个空数组 + Object.assign(mapEmojis.value, { frequently: [] }); + + // 过滤掉需要排除的表情,并映射到对应的分类下 + emojis + .filter(emoji => !exceptEmojis.value.includes(emoji)) + .forEach(emoji => { + const _category = emoji.category; + + if (!mapEmojis.value[_category]) { + Object.assign(mapEmojis.value, { [_category]: [] }); + } + mapEmojis.value[_category].push(emoji); + }); + }; + + // 恢复频繁使用的表情到 mapEmojis 的 frequently 属性中 + const restoreFrequentlyEmojis = async () => { + // 获取频繁使用的表情索引 + const mapIndexEmojis: number[] = frequentlyEmojis.value || []; + // 使用索引从 customEmojis 中获取对应的表情,并赋值给 frequently 属性 + Object.assign(mapEmojis.value, { + frequently: mapIndexEmojis.map( + (index: number) => customEmojis.value[index], + ), + }); + }; + + // 保存频繁使用的表情的索引到 frequentlyEmojis 响应式引用中 + const saveFrequentlyEmojis = (emojis: IData[]) => { + const mapIndexEmojis = emojis.map(emoji => { + return customEmojis.value.indexOf(emoji); + }); + frequentlyEmojis.value = mapIndexEmojis; + }; + + // 更新表情列表 + const updateFrequently = async (emoji: IData) => { + const oldEmojis = mapEmojis.value.frequently; + const emojis = [...new Set([emoji, ...oldEmojis])]; + + mapEmojis.value.frequently = emojis.slice(0, props.limitFrequently); + + saveFrequentlyEmojis(emojis); + }; + + // 切换分类 + const changeCategory = async (category: IData) => { + const hasEmojis = mapEmojis.value[category.name].length; + currentCategory.value = category.name; + + if (hasEmojis) { + emit('changeCategory', category); + } + }; + + // 选中表情 + const onSelectEmoji = async (emoji: IData) => { + await updateFrequently(emoji); + emit('select', emoji); + }; + + watch( + () => props.customEmojis, + newEmojis => { + customEmojis.value = props.customEmojis; + if (newEmojis && newEmojis.length) { + mapEmojis.value = {}; + mapperEmojisCategory(newEmojis); + } + }, + { immediate: true, deep: true }, + ); + + watch( + () => props.customCategories, + newCategories => { + if (newCategories && newCategories.length > 0) { + customCategories.value = newCategories; + } else { + customCategories.value = categoriesDefault(); + } + mapperCategories(customCategories.value); + }, + { immediate: true, deep: true }, + ); + + watch( + () => props.initialCategory, + () => { + initialCategory.value = props.initialCategory; + }, + ); + + watch( + () => props.exceptCategories, + () => { + exceptCategories.value = props.exceptCategories; + }, + ); + + watch( + () => props.exceptEmojis, + () => { + exceptEmojis.value = props.exceptEmojis; + }, + ); + + onMounted(() => { + mapperEmojisCategory(customEmojis.value); + restoreFrequentlyEmojis(); + }); + + onUnmounted(() => { + mapEmojis.value = {}; + frequentlyEmojis.value = []; + }); + + return { + ns, + mapEmojis, + filterEmoji, + mapCategories, + currentCategory, + categoriesFiltered, + onSearch, + onSelectEmoji, + changeCategory, + }; + }, + render() { + return ( +
+ + + {this.showCategories && ( + + )} +
+ ); + }, +}); diff --git a/src/common/emoji-select/icons/categories.ts b/src/common/emoji-select/icons/categories.ts new file mode 100644 index 0000000000000000000000000000000000000000..157f71e54439f9201186d485b83bcb3e1090ef70 --- /dev/null +++ b/src/common/emoji-select/icons/categories.ts @@ -0,0 +1,111 @@ +import { Category, ICategory } from '../interface'; + +// 类别图标数据 +const icons = { + activity: ` + + + + + `, + flags: ` + + + + `, + foods: ` + + + + + `, + frequently: ` + + + + + `, + nature: ` + + + + `, + objects: ` + + + + `, + peoples: ` + + + + `, + places: ` + + + + `, + symbols: ` + + + + `, +}; + +// 导出默认分类数组,数组中的每个元素都是Category类的实例 +export const categoriesDefault = (): ICategory[] => [ + new Category( + 'frequently', + icons.frequently, + ibiz.i18n.t('component.emojiSelect.frequently'), + ), + new Category( + 'peoples', + icons.peoples, + ibiz.i18n.t('component.emojiSelect.peoples'), + ), + new Category( + 'nature', + icons.nature, + ibiz.i18n.t('component.emojiSelect.nature'), + ), + new Category( + 'foods', + icons.foods, + ibiz.i18n.t('component.emojiSelect.foods'), + ), + new Category( + 'activity', + icons.activity, + ibiz.i18n.t('component.emojiSelect.activity'), + ), + new Category( + 'objects', + icons.objects, + ibiz.i18n.t('component.emojiSelect.objects'), + ), + new Category( + 'places', + icons.places, + ibiz.i18n.t('component.emojiSelect.places'), + ), + new Category( + 'symbols', + icons.symbols, + ibiz.i18n.t('component.emojiSelect.symbols'), + ), + new Category( + 'flags', + icons.flags, + ibiz.i18n.t('component.emojiSelect.flags'), + ), +]; diff --git a/src/common/emoji-select/icons/emoji.ts b/src/common/emoji-select/icons/emoji.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb7d89b5f56dd2a14cbaaf58c6ddd544401fda77 --- /dev/null +++ b/src/common/emoji-select/icons/emoji.ts @@ -0,0 +1,1441 @@ +import { Emoji, IEmoji } from '../interface'; + +// 导出默认表情数组,数组中的每个元素都是Emoji类的实例 +export const emojisDefault: IEmoji[] = [ + new Emoji('😀', 'peoples', ['grinning']), + new Emoji('😃', 'peoples', ['smiley']), + new Emoji('😄', 'peoples', ['smile']), + new Emoji('😁', 'peoples', ['grin']), + new Emoji('😆', 'peoples', ['laughing', 'satisfied']), + new Emoji('😅', 'peoples', ['sweat_smile']), + new Emoji('😂', 'peoples', ['joy']), + new Emoji('🤣', 'peoples', ['rofl']), + new Emoji('😌', 'peoples', ['relaxed']), + new Emoji('😊', 'peoples', ['blush']), + new Emoji('😇', 'peoples', ['innocent']), + new Emoji('🙂', 'peoples', ['slightly_smiling_face']), + new Emoji('🙃', 'peoples', ['upside_down_face']), + new Emoji('😉', 'peoples', ['wink']), + new Emoji('😌', 'peoples', ['relieved']), + new Emoji('😍', 'peoples', ['heart_eyes']), + new Emoji('😘', 'peoples', ['kissing_heart']), + new Emoji('😗', 'peoples', ['kissing']), + new Emoji('😙', 'peoples', ['kissing_smiling_eyes']), + new Emoji('😚', 'peoples', ['kissing_closed_eyes']), + new Emoji('😋', 'peoples', ['yum']), + new Emoji('😜', 'peoples', ['stuck_out_tongue_winking_eye']), + new Emoji('😝', 'peoples', ['stuck_out_tongue_closed_eyes']), + new Emoji('😛', 'peoples', ['stuck_out_tongue']), + new Emoji('🤑', 'peoples', ['money_mouth_face']), + new Emoji('🤗', 'peoples', ['hugs']), + new Emoji('🤓', 'peoples', ['nerd_face']), + new Emoji('😎', 'peoples', ['sunglasses']), + new Emoji('🤡', 'peoples', ['clown_face']), + new Emoji('🤠', 'peoples', ['cowboy_hat_face']), + new Emoji('😏', 'peoples', ['smirk']), + new Emoji('😒', 'peoples', ['unamused']), + new Emoji('😞', 'peoples', ['disappointed']), + new Emoji('😔', 'peoples', ['pensive']), + new Emoji('😟', 'peoples', ['worried']), + new Emoji('😕', 'peoples', ['confused']), + new Emoji('🙁', 'peoples', ['slightly_frowning_face']), + new Emoji('☹️', 'peoples', ['frowning_face']), + new Emoji('😣', 'peoples', ['persevere']), + new Emoji('😖', 'peoples', ['confounded']), + new Emoji('😫', 'peoples', ['tired_face']), + new Emoji('😩', 'peoples', ['weary']), + new Emoji('😤', 'peoples', ['triumph']), + new Emoji('😠', 'peoples', ['angry']), + new Emoji('😡', 'peoples', ['rage', 'pout']), + new Emoji('😶', 'peoples', ['no_mouth']), + new Emoji('😐', 'peoples', ['neutral_face']), + new Emoji('😑', 'peoples', ['expressionless']), + new Emoji('😯', 'peoples', ['hushed']), + new Emoji('😦', 'peoples', ['frowning']), + new Emoji('😧', 'peoples', ['anguished']), + new Emoji('😮', 'peoples', ['open_mouth']), + new Emoji('😲', 'peoples', ['astonished']), + new Emoji('😵', 'peoples', ['dizzy_face']), + new Emoji('😳', 'peoples', ['flushed']), + new Emoji('😱', 'peoples', ['scream']), + new Emoji('😨', 'peoples', ['fearful']), + new Emoji('😰', 'peoples', ['cold_sweat']), + new Emoji('😢', 'peoples', ['cry']), + new Emoji('😥', 'peoples', ['disappointed_relieved']), + new Emoji('🤤', 'peoples', ['drooling_face']), + new Emoji('😭', 'peoples', ['sob']), + new Emoji('😓', 'peoples', ['sweat']), + new Emoji('😪', 'peoples', ['sleepy']), + new Emoji('😴', 'peoples', ['sleeping']), + new Emoji('🙄', 'peoples', ['roll_eyes']), + new Emoji('🤔', 'peoples', ['thinking']), + new Emoji('🤥', 'peoples', ['lying_face']), + new Emoji('😬', 'peoples', ['grimacing']), + new Emoji('🤐', 'peoples', ['zipper_mouth_face']), + new Emoji('🤢', 'peoples', ['nauseated_face']), + new Emoji('🤧', 'peoples', ['sneezing_face']), + new Emoji('😷', 'peoples', ['mask']), + new Emoji('🤒', 'peoples', ['face_with_thermometer']), + new Emoji('🤕', 'peoples', ['face_with_head_bandage']), + new Emoji('😈', 'peoples', ['smiling_imp']), + new Emoji('👿', 'peoples', ['imp']), + new Emoji('👹', 'peoples', ['japanese_ogre']), + new Emoji('👺', 'peoples', ['japanese_goblin']), + new Emoji('💩', 'peoples', ['hankey', 'poop', 'shit']), + new Emoji('👻', 'peoples', ['ghost']), + new Emoji('💀', 'peoples', ['skull']), + new Emoji('☠️', 'peoples', ['skull_and_crossbones']), + new Emoji('👽', 'peoples', ['alien']), + new Emoji('👾', 'peoples', ['space_invader']), + new Emoji('🤖', 'peoples', ['robot']), + new Emoji('🎃', 'peoples', ['jack_o_lantern']), + new Emoji('😺', 'peoples', ['smiley_cat']), + new Emoji('😸', 'peoples', ['smile_cat']), + new Emoji('😹', 'peoples', ['joy_cat']), + new Emoji('😻', 'peoples', ['heart_eyes_cat']), + new Emoji('😼', 'peoples', ['smirk_cat']), + new Emoji('😽', 'peoples', ['kissing_cat']), + new Emoji('🙀', 'peoples', ['scream_cat']), + new Emoji('😿', 'peoples', ['crying_cat_face']), + new Emoji('😾', 'peoples', ['pouting_cat']), + new Emoji('👐', 'peoples', ['open_hands']), + new Emoji('🙌', 'peoples', ['raised_hands']), + new Emoji('👏', 'peoples', ['clap']), + new Emoji('🙏', 'peoples', ['pray']), + new Emoji('🤝', 'peoples', ['handshake']), + new Emoji('👍', 'peoples', ['+1', 'thumbsup']), + new Emoji('👎', 'peoples', ['-1', 'thumbsdown']), + new Emoji('👊', 'peoples', ['fist_oncoming', 'facepunch', 'punch']), + new Emoji('✊', 'peoples', ['fist_raised', 'fist']), + new Emoji('🤛', 'peoples', ['fist_left']), + new Emoji('🤜', 'peoples', ['fist_right']), + new Emoji('🤞', 'peoples', ['crossed_fingers']), + new Emoji('✌️', 'peoples', ['v']), + new Emoji('🤘', 'peoples', ['metal']), + new Emoji('👌', 'peoples', ['ok_hand']), + new Emoji('👈', 'peoples', ['point_left']), + new Emoji('👉', 'peoples', ['point_right']), + new Emoji('👆', 'peoples', ['point_up_2']), + new Emoji('👇', 'peoples', ['point_down']), + new Emoji('☝️', 'peoples', ['point_up']), + new Emoji('✋', 'peoples', ['hand', 'raised_hand']), + new Emoji('🤚', 'peoples', ['raised_back_of_hand']), + new Emoji('🖐', 'peoples', ['raised_hand_with_fingers_splayed']), + new Emoji('🖖', 'peoples', ['vulcan_salute']), + new Emoji('👋', 'peoples', ['wave']), + new Emoji('🤙', 'peoples', ['call_me_hand']), + new Emoji('💪', 'peoples', ['muscle']), + new Emoji('🖕', 'peoples', ['middle_finger', 'fu']), + new Emoji('✍️', 'peoples', ['writing_hand']), + new Emoji('🤳', 'peoples', ['selfie']), + new Emoji('💅', 'peoples', ['nail_care']), + new Emoji('💍', 'peoples', ['ring']), + new Emoji('💄', 'peoples', ['lipstick']), + new Emoji('💋', 'peoples', ['kiss']), + new Emoji('👄', 'peoples', ['lips']), + new Emoji('👅', 'peoples', ['tongue']), + new Emoji('👂', 'peoples', ['ear']), + new Emoji('👃', 'peoples', ['nose']), + new Emoji('👣', 'peoples', ['footprints']), + new Emoji('👁', 'peoples', ['eye']), + new Emoji('👀', 'peoples', ['eyes']), + new Emoji('🗣', 'peoples', ['speaking_head']), + new Emoji('👤', 'peoples', ['bust_in_silhouette']), + new Emoji('👥', 'peoples', ['busts_in_silhouette']), + new Emoji('👶', 'peoples', ['baby']), + new Emoji('👦', 'peoples', ['boy']), + new Emoji('👧', 'peoples', ['girl']), + new Emoji('👨', 'peoples', ['man']), + new Emoji('👩', 'peoples', ['woman']), + new Emoji('👱‍♀', 'peoples', ['blonde_woman']), + new Emoji('👱', 'peoples', ['blonde_man', 'person_with_blond_hair']), + new Emoji('👴', 'peoples', ['older_man']), + new Emoji('👵', 'peoples', ['older_woman']), + new Emoji('👲', 'peoples', ['man_with_gua_pi_mao']), + new Emoji('👳‍♀', 'peoples', ['woman_with_turban']), + new Emoji('👳', 'peoples', ['man_with_turban']), + new Emoji('👮‍♀', 'peoples', ['policewoman']), + new Emoji('👮', 'peoples', ['policeman', 'cop']), + new Emoji('👷‍♀', 'peoples', ['construction_worker_woman']), + new Emoji('👷', 'peoples', [ + 'construction_worker_man', + 'construction_worker', + ]), + new Emoji('💂‍♀', 'peoples', ['guardswoman']), + new Emoji('💂', 'peoples', ['guardsman']), + new Emoji('👩‍⚕', 'peoples', ['woman_health_worker']), + new Emoji('👨‍⚕', 'peoples', ['man_health_worker']), + new Emoji('👩‍🌾', 'peoples', ['woman_farmer']), + new Emoji('👨‍🌾', 'peoples', ['man_farmer']), + new Emoji('👩‍🍳', 'peoples', ['woman_cook']), + new Emoji('👨‍🍳', 'peoples', ['man_cook']), + new Emoji('👩‍🎓', 'peoples', ['woman_student']), + new Emoji('👨‍🎓', 'peoples', ['man_student']), + new Emoji('👩‍🎤', 'peoples', ['woman_singer']), + new Emoji('👨‍🎤', 'peoples', ['man_singer']), + new Emoji('👩‍🏫', 'peoples', ['woman_teacher']), + new Emoji('👨‍🏫', 'peoples', ['man_teacher']), + new Emoji('👩‍🏭', 'peoples', ['woman_factory_worker']), + new Emoji('👨‍🏭', 'peoples', ['man_factory_worker']), + new Emoji('👩‍💻', 'peoples', ['woman_technologist']), + new Emoji('👨‍💻', 'peoples', ['man_technologist']), + new Emoji('👩‍💼', 'peoples', ['woman_office_worker']), + new Emoji('👨‍💼', 'peoples', ['man_office_worker']), + new Emoji('👩‍🔧', 'peoples', ['woman_mechanic']), + new Emoji('👨‍🔧', 'peoples', ['man_mechanic']), + new Emoji('👩‍🔬', 'peoples', ['woman_scientist']), + new Emoji('👨‍🔬', 'peoples', ['man_scientist']), + new Emoji('👩‍🎨', 'peoples', ['woman_artist']), + new Emoji('👨‍🎨', 'peoples', ['man_artist']), + new Emoji('👩‍🚒', 'peoples', ['woman_firefighter']), + new Emoji('👨‍🚒', 'peoples', ['man_firefighter']), + new Emoji('👩‍🚀', 'peoples', ['woman_astronaut']), + new Emoji('👨‍🚀', 'peoples', ['man_astronaut']), + new Emoji('🤶', 'peoples', ['mrs_claus']), + new Emoji('🎅', 'peoples', ['santa']), + new Emoji('👸', 'peoples', ['princess']), + new Emoji('🤴', 'peoples', ['prince']), + new Emoji('👰', 'peoples', ['bride_with_veil']), + new Emoji('🤵', 'peoples', ['man_in_tuxedo']), + new Emoji('👼', 'peoples', ['angel']), + new Emoji('🤰', 'peoples', ['pregnant_woman']), + new Emoji('🙇‍♀', 'peoples', ['bowing_woman']), + new Emoji('🙇', 'peoples', ['bowing_man', 'bow']), + new Emoji('💁', 'peoples', [ + 'tipping_hand_woman', + 'information_desk_person', + 'sassy_woman', + ]), + new Emoji('💁‍♂', 'peoples', ['tipping_hand_man', 'sassy_man']), + new Emoji('🙅', 'peoples', ['no_good_woman', 'no_good', 'ng_woman']), + new Emoji('🙅‍♂', 'peoples', ['no_good_man', 'ng_man']), + new Emoji('🙆', 'peoples', ['ok_woman']), + new Emoji('🙆‍♂', 'peoples', ['ok_man']), + new Emoji('🙋', 'peoples', ['raising_hand_woman', 'raising_hand']), + new Emoji('🙋‍♂', 'peoples', ['raising_hand_man']), + new Emoji('🤦‍♀', 'peoples', ['woman_facepalming']), + new Emoji('🤦‍♂', 'peoples', ['man_facepalming']), + new Emoji('🤷‍♀', 'peoples', ['woman_shrugging']), + new Emoji('🤷‍♂', 'peoples', ['man_shrugging']), + new Emoji('🙎', 'peoples', ['pouting_woman', 'person_with_pouting_face']), + new Emoji('🙎‍♂', 'peoples', ['pouting_man']), + new Emoji('🙍', 'peoples', ['frowning_woman', 'person_frowning']), + new Emoji('🙍‍♂', 'peoples', ['frowning_man']), + new Emoji('💇', 'peoples', ['haircut_woman', 'haircut']), + new Emoji('💇‍♂', 'peoples', ['haircut_man']), + new Emoji('💆', 'peoples', ['massage_woman', 'massage']), + new Emoji('💆‍♂', 'peoples', ['massage_man']), + new Emoji('🕴', 'peoples', ['business_suit_levitating']), + new Emoji('💃', 'peoples', ['dancer']), + new Emoji('🕺', 'peoples', ['man_dancing']), + new Emoji('👯', 'peoples', ['dancing_women', 'dancers']), + new Emoji('👯‍♂', 'peoples', ['dancing_men']), + new Emoji('🚶‍♀', 'peoples', ['walking_woman']), + new Emoji('🚶', 'peoples', ['walking_man', 'walking']), + new Emoji('🏃‍♀', 'peoples', ['running_woman']), + new Emoji('🏃', 'peoples', ['running_man', 'runner', 'running']), + new Emoji('👫', 'peoples', ['couple']), + new Emoji('👭', 'peoples', ['two_women_holding_hands']), + new Emoji('👬', 'peoples', ['two_men_holding_hands']), + new Emoji('💑', 'peoples', [ + 'couple_with_heart_woman_man', + 'couple_with_heart', + ]), + new Emoji('👩‍❤️‍👩', 'peoples', ['couple_with_heart_woman_woman']), + new Emoji('👨‍❤️‍👨', 'peoples', ['couple_with_heart_man_man']), + new Emoji('💏', 'peoples', ['couplekiss_man_woman']), + new Emoji('👩‍❤️‍💋‍👩', 'peoples', ['couplekiss_woman_woman']), + new Emoji('👨‍❤️‍💋‍👨', 'peoples', ['couplekiss_man_man']), + new Emoji('👪', 'peoples', ['family_man_woman_boy', 'family']), + new Emoji('👨‍👩‍👧', 'peoples', ['family_man_woman_girl']), + new Emoji('👨‍👩‍👧‍👦', 'peoples', ['family_man_woman_girl_boy']), + new Emoji('👨‍👩‍👦‍👦', 'peoples', ['family_man_woman_boy_boy']), + new Emoji('👨‍👩‍👧‍👧', 'peoples', ['family_man_woman_girl_girl']), + new Emoji('👩‍👩‍👦', 'peoples', ['family_woman_woman_boy']), + new Emoji('👩‍👩‍👧', 'peoples', ['family_woman_woman_girl']), + new Emoji('👩‍👩‍👧‍👦', 'peoples', ['family_woman_woman_girl_boy']), + new Emoji('👩‍👩‍👦‍👦', 'peoples', ['family_woman_woman_boy_boy']), + new Emoji('👩‍👩‍👧‍👧', 'peoples', ['family_woman_woman_girl_girl']), + new Emoji('👨‍👨‍👦', 'peoples', ['family_man_man_boy']), + new Emoji('👨‍👨‍👧', 'peoples', ['family_man_man_girl']), + new Emoji('👨‍👨‍👧‍👦', 'peoples', ['family_man_man_girl_boy']), + new Emoji('👨‍👨‍👦‍👦', 'peoples', ['family_man_man_boy_boy']), + new Emoji('👨‍👨‍👧‍👧', 'peoples', ['family_man_man_girl_girl']), + new Emoji('👩‍👦', 'peoples', ['family_woman_boy']), + new Emoji('👩‍👧', 'peoples', ['family_woman_girl']), + new Emoji('👩‍👧‍👦', 'peoples', ['family_woman_girl_boy']), + new Emoji('👩‍👦‍👦', 'peoples', ['family_woman_boy_boy']), + new Emoji('👩‍👧‍👧', 'peoples', ['family_woman_girl_girl']), + new Emoji('👨‍👦', 'peoples', ['family_man_boy']), + new Emoji('👨‍👧', 'peoples', ['family_man_girl']), + new Emoji('👨‍👧‍👦', 'peoples', ['family_man_girl_boy']), + new Emoji('👨‍👦‍👦', 'peoples', ['family_man_boy_boy']), + new Emoji('👨‍👧‍👧', 'peoples', ['family_man_girl_girl']), + new Emoji('👚', 'peoples', ['womans_clothes']), + new Emoji('👕', 'peoples', ['shirt', 'tshirt']), + new Emoji('👖', 'peoples', ['jeans']), + new Emoji('👔', 'peoples', ['necktie']), + new Emoji('👗', 'peoples', ['dress']), + new Emoji('👙', 'peoples', ['bikini']), + new Emoji('👘', 'peoples', ['kimono']), + new Emoji('👠', 'peoples', ['high_heel']), + new Emoji('👡', 'peoples', ['sandal']), + new Emoji('👢', 'peoples', ['boot']), + new Emoji('👞', 'peoples', ['mans_shoe', 'shoe']), + new Emoji('👟', 'peoples', ['athletic_shoe']), + new Emoji('👒', 'peoples', ['womans_hat']), + new Emoji('🎩', 'peoples', ['tophat']), + new Emoji('🎓', 'peoples', ['mortar_board']), + new Emoji('👑', 'peoples', ['crown']), + new Emoji('⛑', 'peoples', ['rescue_worker_helmet']), + new Emoji('🎒', 'peoples', ['school_satchel']), + new Emoji('👝', 'peoples', ['pouch']), + new Emoji('👛', 'peoples', ['purse']), + new Emoji('👜', 'peoples', ['handbag']), + new Emoji('💼', 'peoples', ['briefcase']), + new Emoji('👓', 'peoples', ['eyeglasses']), + new Emoji('🕶', 'peoples', ['dark_sunglasses']), + new Emoji('🌂', 'peoples', ['closed_umbrella']), + new Emoji('☂️', 'peoples', ['open_umbrella']), + new Emoji('🐶', 'nature', ['dog']), + new Emoji('🐱', 'nature', ['cat']), + new Emoji('🐭', 'nature', ['mouse']), + new Emoji('🐹', 'nature', ['hamster']), + new Emoji('🐰', 'nature', ['rabbit']), + new Emoji('🦊', 'nature', ['fox_face']), + new Emoji('🐻', 'nature', ['bear']), + new Emoji('🐼', 'nature', ['panda_face']), + new Emoji('🐨', 'nature', ['koala']), + new Emoji('🐯', 'nature', ['tiger']), + new Emoji('🦁', 'nature', ['lion']), + new Emoji('🐮', 'nature', ['cow']), + new Emoji('🐷', 'nature', ['pig']), + new Emoji('🐽', 'nature', ['pig_nose']), + new Emoji('🐸', 'nature', ['frog']), + new Emoji('🐵', 'nature', ['monkey_face']), + new Emoji('🙈', 'nature', ['see_no_evil']), + new Emoji('🙉', 'nature', ['hear_no_evil']), + new Emoji('🙊', 'nature', ['speak_no_evil']), + new Emoji('🐒', 'nature', ['monkey']), + new Emoji('🐔', 'nature', ['chicken']), + new Emoji('🐧', 'nature', ['penguin']), + new Emoji('🐦', 'nature', ['bird']), + new Emoji('🐤', 'nature', ['baby_chick']), + new Emoji('🐣', 'nature', ['hatching_chick']), + new Emoji('🐥', 'nature', ['hatched_chick']), + new Emoji('🦆', 'nature', ['duck']), + new Emoji('🦅', 'nature', ['eagle']), + new Emoji('🦉', 'nature', ['owl']), + new Emoji('🦇', 'nature', ['bat']), + new Emoji('🐺', 'nature', ['wolf']), + new Emoji('🐗', 'nature', ['boar']), + new Emoji('🐴', 'nature', ['horse']), + new Emoji('🦄', 'nature', ['unicorn']), + new Emoji('🐝', 'nature', ['bee', 'honeybee']), + new Emoji('🐛', 'nature', ['bug']), + new Emoji('🦋', 'nature', ['butterfly']), + new Emoji('🐌', 'nature', ['snail']), + new Emoji('🐚', 'nature', ['shell']), + new Emoji('🐞', 'nature', ['beetle']), + new Emoji('🐜', 'nature', ['ant']), + new Emoji('🕷', 'nature', ['spider']), + new Emoji('🕸', 'nature', ['spider_web']), + new Emoji('🐢', 'nature', ['turtle']), + new Emoji('🐍', 'nature', ['snake']), + new Emoji('🦎', 'nature', ['lizard']), + new Emoji('🦂', 'nature', ['scorpion']), + new Emoji('🦀', 'nature', ['crab']), + new Emoji('🦑', 'nature', ['squid']), + new Emoji('🐙', 'nature', ['octopus']), + new Emoji('🦐', 'nature', ['shrimp']), + new Emoji('🐠', 'nature', ['tropical_fish']), + new Emoji('🐟', 'nature', ['fish']), + new Emoji('🐡', 'nature', ['blowfish']), + new Emoji('🐬', 'nature', ['dolphin', 'flipper']), + new Emoji('🦈', 'nature', ['shark']), + new Emoji('🐳', 'nature', ['whale']), + new Emoji('🐋', 'nature', ['whale2']), + new Emoji('🐊', 'nature', ['crocodile']), + new Emoji('🐆', 'nature', ['leopard']), + new Emoji('🐅', 'nature', ['tiger2']), + new Emoji('🐃', 'nature', ['water_buffalo']), + new Emoji('🐂', 'nature', ['ox']), + new Emoji('🐄', 'nature', ['cow2']), + new Emoji('🦌', 'nature', ['deer']), + new Emoji('🐪', 'nature', ['dromedary_camel']), + new Emoji('🐫', 'nature', ['camel']), + new Emoji('🐘', 'nature', ['elephant']), + new Emoji('🦏', 'nature', ['rhinoceros']), + new Emoji('🦍', 'nature', ['gorilla']), + new Emoji('🐎', 'nature', ['racehorse']), + new Emoji('🐖', 'nature', ['pig2']), + new Emoji('🐐', 'nature', ['goat']), + new Emoji('🐏', 'nature', ['ram']), + new Emoji('🐑', 'nature', ['sheep']), + new Emoji('🐕', 'nature', ['dog2']), + new Emoji('🐩', 'nature', ['poodle']), + new Emoji('🐈', 'nature', ['cat2']), + new Emoji('🐓', 'nature', ['rooster']), + new Emoji('🦃', 'nature', ['turkey']), + new Emoji('🕊', 'nature', ['dove']), + new Emoji('🐇', 'nature', ['rabbit2']), + new Emoji('🐁', 'nature', ['mouse2']), + new Emoji('🐀', 'nature', ['rat']), + new Emoji('🐿', 'nature', ['chipmunk']), + new Emoji('🐾', 'nature', ['feet', 'paw_prints']), + new Emoji('🐉', 'nature', ['dragon']), + new Emoji('🐲', 'nature', ['dragon_face']), + new Emoji('🌵', 'nature', ['cactus']), + new Emoji('🎄', 'nature', ['christmas_tree']), + new Emoji('🌲', 'nature', ['evergreen_tree']), + new Emoji('🌳', 'nature', ['deciduous_tree']), + new Emoji('🌴', 'nature', ['palm_tree']), + new Emoji('🌱', 'nature', ['seedling']), + new Emoji('🌿', 'nature', ['herb']), + new Emoji('☘️', 'nature', ['shamrock']), + new Emoji('🍀', 'nature', ['four_leaf_clover']), + new Emoji('🎍', 'nature', ['bamboo']), + new Emoji('🎋', 'nature', ['tanabata_tree']), + new Emoji('🍃', 'nature', ['leaves']), + new Emoji('🍂', 'nature', ['fallen_leaf']), + new Emoji('🍁', 'nature', ['maple_leaf']), + new Emoji('🍄', 'nature', ['mushroom']), + new Emoji('🌾', 'nature', ['ear_of_rice']), + new Emoji('💐', 'nature', ['bouquet']), + new Emoji('🌷', 'nature', ['tulip']), + new Emoji('🌹', 'nature', ['rose']), + new Emoji('🥀', 'nature', ['wilted_flower']), + new Emoji('🌻', 'nature', ['sunflower']), + new Emoji('🌼', 'nature', ['blossom']), + new Emoji('🌸', 'nature', ['cherry_blossom']), + new Emoji('🌺', 'nature', ['hibiscus']), + new Emoji('🌎', 'nature', ['earth_americas']), + new Emoji('🌍', 'nature', ['earth_africa']), + new Emoji('🌏', 'nature', ['earth_asia']), + new Emoji('🌕', 'nature', ['full_moon']), + new Emoji('🌖', 'nature', ['waning_gibbous_moon']), + new Emoji('🌗', 'nature', ['last_quarter_moon']), + new Emoji('🌘', 'nature', ['waning_crescent_moon']), + new Emoji('🌑', 'nature', ['new_moon']), + new Emoji('🌒', 'nature', ['waxing_crescent_moon']), + new Emoji('🌓', 'nature', ['first_quarter_moon']), + new Emoji('🌔', 'nature', ['moon', 'waxing_gibbous_moon']), + new Emoji('🌚', 'nature', ['new_moon_with_face']), + new Emoji('🌝', 'nature', ['full_moon_with_face']), + new Emoji('🌞', 'nature', ['sun_with_face']), + new Emoji('🌛', 'nature', ['first_quarter_moon_with_face']), + new Emoji('🌜', 'nature', ['last_quarter_moon_with_face']), + new Emoji('🌙', 'nature', ['crescent_moon']), + new Emoji('💫', 'nature', ['dizzy']), + new Emoji('⭐️', 'nature', ['star']), + new Emoji('🌟', 'nature', ['star2']), + new Emoji('✨', 'nature', ['sparkles']), + new Emoji('⚡️', 'nature', ['zap']), + new Emoji('🔥', 'nature', ['fire']), + new Emoji('💥', 'nature', ['boom', 'collision']), + new Emoji('☄', 'nature', ['comet']), + new Emoji('☀️', 'nature', ['sunny']), + new Emoji('🌤', 'nature', ['sun_behind_small_cloud']), + new Emoji('⛅️', 'nature', ['partly_sunny']), + new Emoji('🌥', 'nature', ['sun_behind_large_cloud']), + new Emoji('🌦', 'nature', ['sun_behind_rain_cloud']), + new Emoji('🌈', 'nature', ['rainbow']), + new Emoji('☁️', 'nature', ['cloud']), + new Emoji('🌧', 'nature', ['cloud_with_rain']), + new Emoji('⛈', 'nature', ['cloud_with_lightning_and_rain']), + new Emoji('🌩', 'nature', ['cloud_with_lightning']), + new Emoji('🌨', 'nature', ['cloud_with_snow']), + new Emoji('☃️', 'nature', ['snowman_with_snow']), + new Emoji('⛄️', 'nature', ['snowman']), + new Emoji('❄️', 'nature', ['snowflake']), + new Emoji('🌬', 'nature', ['wind_face']), + new Emoji('💨', 'nature', ['dash']), + new Emoji('🌪', 'nature', ['tornado']), + new Emoji('🌫', 'nature', ['fog']), + new Emoji('🌊', 'nature', ['ocean']), + new Emoji('💧', 'nature', ['droplet']), + new Emoji('💦', 'nature', ['sweat_drops']), + new Emoji('☔️', 'nature', ['umbrella']), + new Emoji('🍏', 'foods', ['green_apple']), + new Emoji('🍎', 'foods', ['apple']), + new Emoji('🍐', 'foods', ['pear']), + new Emoji('🍊', 'foods', ['tangerine', 'orange', 'mandarin']), + new Emoji('🍋', 'foods', ['lemon']), + new Emoji('🍌', 'foods', ['banana']), + new Emoji('🍉', 'foods', ['watermelon']), + new Emoji('🍇', 'foods', ['grapes']), + new Emoji('🍓', 'foods', ['strawberry']), + new Emoji('🍈', 'foods', ['melon']), + new Emoji('🍒', 'foods', ['cherries']), + new Emoji('🍑', 'foods', ['peach']), + new Emoji('🍍', 'foods', ['pineapple']), + new Emoji('🥝', 'foods', ['kiwi_fruit']), + new Emoji('🥑', 'foods', ['avocado']), + new Emoji('🍅', 'foods', ['tomato']), + new Emoji('🍆', 'foods', ['eggplant']), + new Emoji('🥒', 'foods', ['cucumber']), + new Emoji('🥕', 'foods', ['carrot']), + new Emoji('🌽', 'foods', ['corn']), + new Emoji('🌶', 'foods', ['hot_pepper']), + new Emoji('🥔', 'foods', ['potato']), + new Emoji('🍠', 'foods', ['sweet_potato']), + new Emoji('🌰', 'foods', ['chestnut']), + new Emoji('🥜', 'foods', ['peanuts']), + new Emoji('🍯', 'foods', ['honey_pot']), + new Emoji('🥐', 'foods', ['croissant']), + new Emoji('🍞', 'foods', ['bread']), + new Emoji('🥖', 'foods', ['baguette_bread']), + new Emoji('🧀', 'foods', ['cheese']), + new Emoji('🥚', 'foods', ['egg']), + new Emoji('🍳', 'foods', ['fried_egg']), + new Emoji('🥓', 'foods', ['bacon']), + new Emoji('🥞', 'foods', ['pancakes']), + new Emoji('🍤', 'foods', ['fried_shrimp']), + new Emoji('🍗', 'foods', ['poultry_leg']), + new Emoji('🍖', 'foods', ['meat_on_bone']), + new Emoji('🍕', 'foods', ['pizza']), + new Emoji('🌭', 'foods', ['hotdog']), + new Emoji('🍔', 'foods', ['hamburger']), + new Emoji('🍟', 'foods', ['fries']), + new Emoji('🥙', 'foods', ['stuffed_flatbread']), + new Emoji('🌮', 'foods', ['taco']), + new Emoji('🌯', 'foods', ['burrito']), + new Emoji('🥗', 'foods', ['green_salad']), + new Emoji('🥘', 'foods', ['shallow_pan_of_food']), + new Emoji('🍝', 'foods', ['spaghetti']), + new Emoji('🍜', 'foods', ['ramen']), + new Emoji('🍲', 'foods', ['stew']), + new Emoji('🍥', 'foods', ['fish_cake']), + new Emoji('🍣', 'foods', ['sushi']), + new Emoji('🍱', 'foods', ['bento']), + new Emoji('🍛', 'foods', ['curry']), + new Emoji('🍚', 'foods', ['rice']), + new Emoji('🍙', 'foods', ['rice_ball']), + new Emoji('🍘', 'foods', ['rice_cracker']), + new Emoji('🍢', 'foods', ['oden']), + new Emoji('🍡', 'foods', ['dango']), + new Emoji('🍧', 'foods', ['shaved_ice']), + new Emoji('🍨', 'foods', ['ice_cream']), + new Emoji('🍦', 'foods', ['icecream']), + new Emoji('🍰', 'foods', ['cake']), + new Emoji('🎂', 'foods', ['birthday']), + new Emoji('🍮', 'foods', ['custard']), + new Emoji('🍭', 'foods', ['lollipop']), + new Emoji('🍬', 'foods', ['candy']), + new Emoji('🍫', 'foods', ['chocolate_bar']), + new Emoji('🍿', 'foods', ['popcorn']), + new Emoji('🍩', 'foods', ['doughnut']), + new Emoji('🍪', 'foods', ['cookie']), + new Emoji('🥛', 'foods', ['milk_glass']), + new Emoji('🍼', 'foods', ['baby_bottle']), + new Emoji('☕️', 'foods', ['coffee']), + new Emoji('🍵', 'foods', ['tea']), + new Emoji('🍶', 'foods', ['sake']), + new Emoji('🍺', 'foods', ['beer']), + new Emoji('🍻', 'foods', ['beers']), + new Emoji('🥂', 'foods', ['clinking_glasses']), + new Emoji('🍷', 'foods', ['wine_glass']), + new Emoji('🥃', 'foods', ['tumbler_glass']), + new Emoji('🍸', 'foods', ['cocktail']), + new Emoji('🍹', 'foods', ['tropical_drink']), + new Emoji('🍾', 'foods', ['champagne']), + new Emoji('🥄', 'foods', ['spoon']), + new Emoji('🍴', 'foods', ['fork_and_knife']), + new Emoji('🍽', 'foods', ['plate_with_cutlery']), + new Emoji('⚽️', 'activity', ['soccer']), + new Emoji('🏀', 'activity', ['basketball']), + new Emoji('🏈', 'activity', ['football']), + new Emoji('⚾️', 'activity', ['baseball']), + new Emoji('🎾', 'activity', ['tennis']), + new Emoji('🏐', 'activity', ['volleyball']), + new Emoji('🏉', 'activity', ['rugby_football']), + new Emoji('🎱', 'activity', ['8ball']), + new Emoji('🏓', 'activity', ['ping_pong']), + new Emoji('🏸', 'activity', ['badminton']), + new Emoji('🥅', 'activity', ['goal_net']), + new Emoji('🏒', 'activity', ['ice_hockey']), + new Emoji('🏑', 'activity', ['field_hockey']), + new Emoji('🏏', 'activity', ['cricket']), + new Emoji('⛳️', 'activity', ['golf']), + new Emoji('🏹', 'activity', ['bow_and_arrow']), + new Emoji('🎣', 'activity', ['fishing_pole_and_fish']), + new Emoji('🥊', 'activity', ['boxing_glove']), + new Emoji('🥋', 'activity', ['martial_arts_uniform']), + new Emoji('⛸', 'activity', ['ice_skate']), + new Emoji('🎿', 'activity', ['ski']), + new Emoji('⛷', 'activity', ['skier']), + new Emoji('🏂', 'activity', ['snowboarder']), + new Emoji('🏋️‍♀️', 'activity', ['weight_lifting_woman']), + new Emoji('🏋', 'activity', ['weight_lifting_man']), + new Emoji('🤺', 'activity', ['person_fencing']), + new Emoji('🤼‍♀', 'activity', ['women_wrestling']), + new Emoji('🤼‍♂', 'activity', ['men_wrestling']), + new Emoji('🤸‍♀', 'activity', ['woman_cartwheeling']), + new Emoji('🤸‍♂', 'activity', ['man_cartwheeling']), + new Emoji('⛹️‍♀️', 'activity', ['basketball_woman']), + new Emoji('⛹', 'activity', ['basketball_man']), + new Emoji('🤾‍♀', 'activity', ['woman_playing_handball']), + new Emoji('🤾‍♂', 'activity', ['man_playing_handball']), + new Emoji('🏌️‍♀️', 'activity', ['golfing_woman']), + new Emoji('🏌', 'activity', ['golfing_man']), + new Emoji('🏄‍♀', 'activity', ['surfing_woman']), + new Emoji('🏄', 'activity', ['surfing_man', 'surfer']), + new Emoji('🏊‍♀', 'activity', ['swimming_woman']), + new Emoji('🏊', 'activity', ['swimming_man', 'swimmer']), + new Emoji('🤽‍♀', 'activity', ['woman_playing_water_polo']), + new Emoji('🤽‍♂', 'activity', ['man_playing_water_polo']), + new Emoji('🚣‍♀', 'activity', ['rowing_woman']), + new Emoji('🚣', 'activity', ['rowing_man', 'rowboat']), + new Emoji('🏇', 'activity', ['horse_racing']), + new Emoji('🚴‍♀', 'activity', ['biking_woman']), + new Emoji('🚴', 'activity', ['biking_man', 'bicyclist']), + new Emoji('🚵‍♀', 'activity', ['mountain_biking_woman']), + new Emoji('🚵', 'activity', ['mountain_biking_man', 'mountain_bicyclist']), + new Emoji('🎽', 'activity', ['running_shirt_with_sash']), + new Emoji('🏅', 'activity', ['medal_sports']), + new Emoji('🎖', 'activity', ['medal_military']), + new Emoji('🥇', 'activity', ['1st_place_medal']), + new Emoji('🥈', 'activity', ['2nd_place_medal']), + new Emoji('🥉', 'activity', ['3rd_place_medal']), + new Emoji('🏆', 'activity', ['trophy']), + new Emoji('🏵', 'activity', ['rosette']), + new Emoji('🎗', 'activity', ['reminder_ribbon']), + new Emoji('🎫', 'activity', ['ticket']), + new Emoji('🎟', 'activity', ['tickets']), + new Emoji('🎪', 'activity', ['circus_tent']), + new Emoji('🤹‍♀', 'activity', ['woman_juggling']), + new Emoji('🤹‍♂', 'activity', ['man_juggling']), + new Emoji('🎭', 'activity', ['performing_arts']), + new Emoji('🎨', 'activity', ['art']), + new Emoji('🎬', 'activity', ['clapper']), + new Emoji('🎤', 'activity', ['microphone']), + new Emoji('🎧', 'activity', ['headphones']), + new Emoji('🎼', 'activity', ['musical_score']), + new Emoji('🎹', 'activity', ['musical_keyboard']), + new Emoji('🥁', 'activity', ['drum']), + new Emoji('🎷', 'activity', ['saxophone']), + new Emoji('🎺', 'activity', ['trumpet']), + new Emoji('🎸', 'activity', ['guitar']), + new Emoji('🎻', 'activity', ['violin']), + new Emoji('🎲', 'activity', ['game_die']), + new Emoji('🎯', 'activity', ['dart']), + new Emoji('🎳', 'activity', ['bowling']), + new Emoji('🎮', 'activity', ['video_game']), + new Emoji('🎰', 'activity', ['slot_machine']), + new Emoji('🚗', 'places', ['car', 'red_car']), + new Emoji('🚕', 'places', ['taxi']), + new Emoji('🚙', 'places', ['blue_car']), + new Emoji('🚌', 'places', ['bus']), + new Emoji('🚎', 'places', ['trolleybus']), + new Emoji('🏎', 'places', ['racing_car']), + new Emoji('🚓', 'places', ['police_car']), + new Emoji('🚑', 'places', ['ambulance']), + new Emoji('🚒', 'places', ['fire_engine']), + new Emoji('🚐', 'places', ['minibus']), + new Emoji('🚚', 'places', ['truck']), + new Emoji('🚛', 'places', ['articulated_lorry']), + new Emoji('🚜', 'places', ['tractor']), + new Emoji('🛴', 'places', ['kick_scooter']), + new Emoji('🚲', 'places', ['bike']), + new Emoji('🛵', 'places', ['motor_scooter']), + new Emoji('🏍', 'places', ['motorcycle']), + new Emoji('🚨', 'places', ['rotating_light']), + new Emoji('🚔', 'places', ['oncoming_police_car']), + new Emoji('🚍', 'places', ['oncoming_bus']), + new Emoji('🚘', 'places', ['oncoming_automobile']), + new Emoji('🚖', 'places', ['oncoming_taxi']), + new Emoji('🚡', 'places', ['aerial_tramway']), + new Emoji('🚠', 'places', ['mountain_cableway']), + new Emoji('🚟', 'places', ['suspension_railway']), + new Emoji('🚃', 'places', ['railway_car']), + new Emoji('🚋', 'places', ['train']), + new Emoji('🚞', 'places', ['mountain_railway']), + new Emoji('🚝', 'places', ['monorail']), + new Emoji('🚄', 'places', ['bullettrain_side']), + new Emoji('🚅', 'places', ['bullettrain_front']), + new Emoji('🚈', 'places', ['light_rail']), + new Emoji('🚂', 'places', ['steam_locomotive']), + new Emoji('🚆', 'places', ['train2']), + new Emoji('🚇', 'places', ['metro']), + new Emoji('🚊', 'places', ['tram']), + new Emoji('🚉', 'places', ['station']), + new Emoji('🚁', 'places', ['helicopter']), + new Emoji('🛩', 'places', ['small_airplane']), + new Emoji('✈️', 'places', ['airplane']), + new Emoji('🛫', 'places', ['flight_departure']), + new Emoji('🛬', 'places', ['flight_arrival']), + new Emoji('🚀', 'places', ['rocket']), + new Emoji('🛰', 'places', ['artificial_satellite']), + new Emoji('💺', 'places', ['seat']), + new Emoji('🛶', 'places', ['canoe']), + new Emoji('⛵️', 'places', ['boat', 'sailboat']), + new Emoji('🛥', 'places', ['motor_boat']), + new Emoji('🚤', 'places', ['speedboat']), + new Emoji('🛳', 'places', ['passenger_ship']), + new Emoji('⛴', 'places', ['ferry']), + new Emoji('🚢', 'places', ['ship']), + new Emoji('⚓️', 'places', ['anchor']), + new Emoji('🚧', 'places', ['construction']), + new Emoji('⛽️', 'places', ['fuelpump']), + new Emoji('🚏', 'places', ['busstop']), + new Emoji('🚦', 'places', ['vertical_traffic_light']), + new Emoji('🚥', 'places', ['traffic_light']), + new Emoji('🗺', 'places', ['world_map']), + new Emoji('🗿', 'places', ['moyai']), + new Emoji('🗽', 'places', ['statue_of_liberty']), + new Emoji('⛲️', 'places', ['fountain']), + new Emoji('🗼', 'places', ['tokyo_tower']), + new Emoji('🏰', 'places', ['european_castle']), + new Emoji('🏯', 'places', ['japanese_castle']), + new Emoji('🏟', 'places', ['stadium']), + new Emoji('🎡', 'places', ['ferris_wheel']), + new Emoji('🎢', 'places', ['roller_coaster']), + new Emoji('🎠', 'places', ['carousel_horse']), + new Emoji('⛱', 'places', ['parasol_on_ground']), + new Emoji('🏖', 'places', ['beach_umbrella']), + new Emoji('🏝', 'places', ['desert_island']), + new Emoji('⛰', 'places', ['mountain']), + new Emoji('🏔', 'places', ['mountain_snow']), + new Emoji('🗻', 'places', ['mount_fuji']), + new Emoji('🌋', 'places', ['volcano']), + new Emoji('🏜', 'places', ['desert']), + new Emoji('🏕', 'places', ['camping']), + new Emoji('⛺️', 'places', ['tent']), + new Emoji('🛤', 'places', ['railway_track']), + new Emoji('🛣', 'places', ['motorway']), + new Emoji('🏗', 'places', ['building_construction']), + new Emoji('🏭', 'places', ['factory']), + new Emoji('🏠', 'places', ['house']), + new Emoji('🏡', 'places', ['house_with_garden']), + new Emoji('🏘', 'places', ['houses']), + new Emoji('🏚', 'places', ['derelict_house']), + new Emoji('🏢', 'places', ['office']), + new Emoji('🏬', 'places', ['department_store']), + new Emoji('🏣', 'places', ['post_office']), + new Emoji('🏤', 'places', ['european_post_office']), + new Emoji('🏥', 'places', ['hospital']), + new Emoji('🏦', 'places', ['bank']), + new Emoji('🏨', 'places', ['hotel']), + new Emoji('🏪', 'places', ['convenience_store']), + new Emoji('🏫', 'places', ['school']), + new Emoji('🏩', 'places', ['love_hotel']), + new Emoji('💒', 'places', ['wedding']), + new Emoji('🏛', 'places', ['classical_building']), + new Emoji('⛪️', 'places', ['church']), + new Emoji('🕌', 'places', ['mosque']), + new Emoji('🕍', 'places', ['synagogue']), + new Emoji('🕋', 'places', ['kaaba']), + new Emoji('⛩', 'places', ['shinto_shrine']), + new Emoji('🗾', 'places', ['japan']), + new Emoji('🎑', 'places', ['rice_scene']), + new Emoji('🏞', 'places', ['national_park']), + new Emoji('🌅', 'places', ['sunrise']), + new Emoji('🌄', 'places', ['sunrise_over_mountains']), + new Emoji('🌠', 'places', ['stars']), + new Emoji('🎇', 'places', ['sparkler']), + new Emoji('🎆', 'places', ['fireworks']), + new Emoji('🌇', 'places', ['city_sunrise']), + new Emoji('🌆', 'places', ['city_sunset']), + new Emoji('🏙', 'places', ['cityscape']), + new Emoji('🌃', 'places', ['night_with_stars']), + new Emoji('🌌', 'places', ['milky_way']), + new Emoji('🌉', 'places', ['bridge_at_night']), + new Emoji('🌁', 'places', ['foggy']), + new Emoji('⌚️', 'objects', ['watch']), + new Emoji('📱', 'objects', ['iphone']), + new Emoji('📲', 'objects', ['calling']), + new Emoji('💻', 'objects', ['computer']), + new Emoji('⌨️', 'objects', ['keyboard']), + new Emoji('🖥', 'objects', ['desktop_computer']), + new Emoji('🖨', 'objects', ['printer']), + new Emoji('🖱', 'objects', ['computer_mouse']), + new Emoji('🖲', 'objects', ['trackball']), + new Emoji('🕹', 'objects', ['joystick']), + new Emoji('🗜', 'objects', ['clamp']), + new Emoji('💽', 'objects', ['minidisc']), + new Emoji('💾', 'objects', ['floppy_disk']), + new Emoji('💿', 'objects', ['cd']), + new Emoji('📀', 'objects', ['dvd']), + new Emoji('📼', 'objects', ['vhs']), + new Emoji('📷', 'objects', ['camera']), + new Emoji('📸', 'objects', ['camera_flash']), + new Emoji('📹', 'objects', ['video_camera']), + new Emoji('🎥', 'objects', ['movie_camera']), + new Emoji('📽', 'objects', ['film_projector']), + new Emoji('🎞', 'objects', ['film_strip']), + new Emoji('📞', 'objects', ['telephone_receiver']), + new Emoji('☎️', 'objects', ['phone', 'telephone']), + new Emoji('📟', 'objects', ['pager']), + new Emoji('📠', 'objects', ['fax']), + new Emoji('📺', 'objects', ['tv']), + new Emoji('📻', 'objects', ['radio']), + new Emoji('🎙', 'objects', ['studio_microphone']), + new Emoji('🎚', 'objects', ['level_slider']), + new Emoji('🎛', 'objects', ['control_knobs']), + new Emoji('⏱', 'objects', ['stopwatch']), + new Emoji('⏲', 'objects', ['timer_clock']), + new Emoji('⏰', 'objects', ['alarm_clock']), + new Emoji('🕰', 'objects', ['mantelpiece_clock']), + new Emoji('⌛️', 'objects', ['hourglass']), + new Emoji('⏳', 'objects', ['hourglass_flowing_sand']), + new Emoji('📡', 'objects', ['satellite']), + new Emoji('🔋', 'objects', ['battery']), + new Emoji('🔌', 'objects', ['electric_plug']), + new Emoji('💡', 'objects', ['bulb']), + new Emoji('🔦', 'objects', ['flashlight']), + new Emoji('🕯', 'objects', ['candle']), + new Emoji('🗑', 'objects', ['wastebasket']), + new Emoji('🛢', 'objects', ['oil_drum']), + new Emoji('💸', 'objects', ['money_with_wings']), + new Emoji('💵', 'objects', ['dollar']), + new Emoji('💴', 'objects', ['yen']), + new Emoji('💶', 'objects', ['euro']), + new Emoji('💷', 'objects', ['pound']), + new Emoji('💰', 'objects', ['moneybag']), + new Emoji('💳', 'objects', ['credit_card']), + new Emoji('💎', 'objects', ['gem']), + new Emoji('⚖️', 'objects', ['balance_scale']), + new Emoji('🔧', 'objects', ['wrench']), + new Emoji('🔨', 'objects', ['hammer']), + new Emoji('⚒', 'objects', ['hammer_and_pick']), + new Emoji('🛠', 'objects', ['hammer_and_wrench']), + new Emoji('⛏', 'objects', ['pick']), + new Emoji('🔩', 'objects', ['nut_and_bolt']), + new Emoji('⚙️', 'objects', ['gear']), + new Emoji('⛓', 'objects', ['chains']), + new Emoji('🔫', 'objects', ['gun']), + new Emoji('💣', 'objects', ['bomb']), + new Emoji('🔪', 'objects', ['hocho', 'knife']), + new Emoji('🗡', 'objects', ['dagger']), + new Emoji('⚔️', 'objects', ['crossed_swords']), + new Emoji('🛡', 'objects', ['shield']), + new Emoji('🚬', 'objects', ['smoking']), + new Emoji('⚰️', 'objects', ['coffin']), + new Emoji('⚱️', 'objects', ['funeral_urn']), + new Emoji('🏺', 'objects', ['amphora']), + new Emoji('🔮', 'objects', ['crystal_ball']), + new Emoji('📿', 'objects', ['prayer_beads']), + new Emoji('💈', 'objects', ['barber']), + new Emoji('⚗️', 'objects', ['alembic']), + new Emoji('🔭', 'objects', ['telescope']), + new Emoji('🔬', 'objects', ['microscope']), + new Emoji('🕳', 'objects', ['hole']), + new Emoji('💊', 'objects', ['pill']), + new Emoji('💉', 'objects', ['syringe']), + new Emoji('🌡', 'objects', ['thermometer']), + new Emoji('🚽', 'objects', ['toilet']), + new Emoji('🚰', 'objects', ['potable_water']), + new Emoji('🚿', 'objects', ['shower']), + new Emoji('🛁', 'objects', ['bathtub']), + new Emoji('🛀', 'objects', ['bath']), + new Emoji('🛎', 'objects', ['bellhop_bell']), + new Emoji('🔑', 'objects', ['key']), + new Emoji('🗝', 'objects', ['old_key']), + new Emoji('🚪', 'objects', ['door']), + new Emoji('🛋', 'objects', ['couch_and_lamp']), + new Emoji('🛏', 'objects', ['bed']), + new Emoji('🛌', 'objects', ['sleeping_bed']), + new Emoji('🖼', 'objects', ['framed_picture']), + new Emoji('🛍', 'objects', ['shopping']), + new Emoji('🛒', 'objects', ['shopping_cart']), + new Emoji('🎁', 'objects', ['gift']), + new Emoji('🎈', 'objects', ['balloon']), + new Emoji('🎏', 'objects', ['flags']), + new Emoji('🎀', 'objects', ['ribbon']), + new Emoji('🎊', 'objects', ['confetti_ball']), + new Emoji('🎉', 'objects', ['tada']), + new Emoji('🎎', 'objects', ['dolls']), + new Emoji('🏮', 'objects', ['izakaya_lantern', 'lantern']), + new Emoji('🎐', 'objects', ['wind_chime']), + new Emoji('✉️', 'objects', ['email', 'envelope']), + new Emoji('📩', 'objects', ['envelope_with_arrow']), + new Emoji('📨', 'objects', ['incoming_envelope']), + new Emoji('📧', 'objects', ['e-mail']), + new Emoji('💌', 'objects', ['love_letter']), + new Emoji('📥', 'objects', ['inbox_tray']), + new Emoji('📤', 'objects', ['outbox_tray']), + new Emoji('📦', 'objects', ['package']), + new Emoji('🏷', 'objects', ['label']), + new Emoji('📪', 'objects', ['mailbox_closed']), + new Emoji('📫', 'objects', ['mailbox']), + new Emoji('📬', 'objects', ['mailbox_with_mail']), + new Emoji('📭', 'objects', ['mailbox_with_no_mail']), + new Emoji('📮', 'objects', ['postbox']), + new Emoji('📯', 'objects', ['postal_horn']), + new Emoji('📜', 'objects', ['scroll']), + new Emoji('📃', 'objects', ['page_with_curl']), + new Emoji('📄', 'objects', ['page_facing_up']), + new Emoji('📑', 'objects', ['bookmark_tabs']), + new Emoji('📊', 'objects', ['bar_chart']), + new Emoji('📈', 'objects', ['chart_with_upwards_trend']), + new Emoji('📉', 'objects', ['chart_with_downwards_trend']), + new Emoji('🗒', 'objects', ['spiral_notepad']), + new Emoji('🗓', 'objects', ['spiral_calendar']), + new Emoji('📆', 'objects', ['calendar']), + new Emoji('📅', 'objects', ['date']), + new Emoji('📇', 'objects', ['card_index']), + new Emoji('🗃', 'objects', ['card_file_box']), + new Emoji('🗳', 'objects', ['ballot_box']), + new Emoji('🗄', 'objects', ['file_cabinet']), + new Emoji('📋', 'objects', ['clipboard']), + new Emoji('📁', 'objects', ['file_folder']), + new Emoji('📂', 'objects', ['open_file_folder']), + new Emoji('🗂', 'objects', ['card_index_dividers']), + new Emoji('🗞', 'objects', ['newspaper_roll']), + new Emoji('📰', 'objects', ['newspaper']), + new Emoji('📓', 'objects', ['notebook']), + new Emoji('📔', 'objects', ['notebook_with_decorative_cover']), + new Emoji('📒', 'objects', ['ledger']), + new Emoji('📕', 'objects', ['closed_book']), + new Emoji('📗', 'objects', ['green_book']), + new Emoji('📘', 'objects', ['blue_book']), + new Emoji('📙', 'objects', ['orange_book']), + new Emoji('📚', 'objects', ['books']), + new Emoji('📖', 'objects', ['book', 'open_book']), + new Emoji('🔖', 'objects', ['bookmark']), + new Emoji('🔗', 'objects', ['link']), + new Emoji('📎', 'objects', ['paperclip']), + new Emoji('🖇', 'objects', ['paperclips']), + new Emoji('📐', 'objects', ['triangular_ruler']), + new Emoji('📏', 'objects', ['straight_ruler']), + new Emoji('📌', 'objects', ['pushpin']), + new Emoji('📍', 'objects', ['round_pushpin']), + new Emoji('✂️', 'objects', ['scissors']), + new Emoji('🖊', 'objects', ['pen']), + new Emoji('🖋', 'objects', ['fountain_pen']), + new Emoji('✒️', 'objects', ['black_nib']), + new Emoji('🖌', 'objects', ['paintbrush']), + new Emoji('🖍', 'objects', ['crayon']), + new Emoji('📝', 'objects', ['memo', 'pencil']), + new Emoji('✏️', 'objects', ['pencil2']), + new Emoji('🔍', 'objects', ['mag']), + new Emoji('🔎', 'objects', ['mag_right']), + new Emoji('🔏', 'objects', ['lock_with_ink_pen']), + new Emoji('🔐', 'objects', ['closed_lock_with_key']), + new Emoji('🔒', 'objects', ['lock']), + new Emoji('🔓', 'objects', ['unlock']), + new Emoji('❤️', 'symbols', ['heart']), + new Emoji('💛', 'symbols', ['yellow_heart']), + new Emoji('💚', 'symbols', ['green_heart']), + new Emoji('💙', 'symbols', ['blue_heart']), + new Emoji('💜', 'symbols', ['purple_heart']), + new Emoji('🖤', 'symbols', ['black_heart']), + new Emoji('💔', 'symbols', ['broken_heart']), + new Emoji('❣️', 'symbols', ['heavy_heart_exclamation']), + new Emoji('💕', 'symbols', ['two_hearts']), + new Emoji('💞', 'symbols', ['revolving_hearts']), + new Emoji('💓', 'symbols', ['heartbeat']), + new Emoji('💗', 'symbols', ['heartpulse']), + new Emoji('💖', 'symbols', ['sparkling_heart']), + new Emoji('💘', 'symbols', ['cupid']), + new Emoji('💝', 'symbols', ['gift_heart']), + new Emoji('💟', 'symbols', ['heart_decoration']), + new Emoji('☮️', 'symbols', ['peace_symbol']), + new Emoji('✝️', 'symbols', ['latin_cross']), + new Emoji('☪️', 'symbols', ['star_and_crescent']), + new Emoji('🕉', 'symbols', ['om']), + new Emoji('☸️', 'symbols', ['wheel_of_dharma']), + new Emoji('✡️', 'symbols', ['star_of_david']), + new Emoji('🔯', 'symbols', ['six_pointed_star']), + new Emoji('🕎', 'symbols', ['menorah']), + new Emoji('☯️', 'symbols', ['yin_yang']), + new Emoji('☦️', 'symbols', ['orthodox_cross']), + new Emoji('🛐', 'symbols', ['place_of_worship']), + new Emoji('⛎', 'symbols', ['ophiuchus']), + new Emoji('♈️', 'symbols', ['aries']), + new Emoji('♉️', 'symbols', ['taurus']), + new Emoji('♊️', 'symbols', ['gemini']), + new Emoji('♋️', 'symbols', ['cancer']), + new Emoji('♌️', 'symbols', ['leo']), + new Emoji('♍️', 'symbols', ['virgo']), + new Emoji('♎️', 'symbols', ['libra']), + new Emoji('♏️', 'symbols', ['scorpius']), + new Emoji('♐️', 'symbols', ['sagittarius']), + new Emoji('♑️', 'symbols', ['capricorn']), + new Emoji('♒️', 'symbols', ['aquarius']), + new Emoji('♓️', 'symbols', ['pisces']), + new Emoji('🆔', 'symbols', ['id']), + new Emoji('⚛️', 'symbols', ['atom_symbol']), + new Emoji('🉑', 'symbols', ['accept']), + new Emoji('☢️', 'symbols', ['radioactive']), + new Emoji('☣️', 'symbols', ['biohazard']), + new Emoji('📴', 'symbols', ['mobile_phone_off']), + new Emoji('📳', 'symbols', ['vibration_mode']), + new Emoji('🈶', 'symbols', ['u6709']), + new Emoji('🈚️', 'symbols', ['u7121']), + new Emoji('🈸', 'symbols', ['u7533']), + new Emoji('🈺', 'symbols', ['u55b6']), + new Emoji('🈷️', 'symbols', ['u6708']), + new Emoji('✴️', 'symbols', ['eight_pointed_black_star']), + new Emoji('🆚', 'symbols', ['vs']), + new Emoji('💮', 'symbols', ['white_flower']), + new Emoji('🉐', 'symbols', ['ideograph_advantage']), + new Emoji('㊙️', 'symbols', ['secret']), + new Emoji('㊗️', 'symbols', ['congratulations']), + new Emoji('🈴', 'symbols', ['u5408']), + new Emoji('🈵', 'symbols', ['u6e80']), + new Emoji('🈹', 'symbols', ['u5272']), + new Emoji('🈲', 'symbols', ['u7981']), + new Emoji('🅰️', 'symbols', ['a']), + new Emoji('🅱️', 'symbols', ['b']), + new Emoji('🆎', 'symbols', ['ab']), + new Emoji('🆑', 'symbols', ['cl']), + new Emoji('🅾️', 'symbols', ['o2']), + new Emoji('🆘', 'symbols', ['sos']), + new Emoji('❌', 'symbols', ['x']), + new Emoji('⭕️', 'symbols', ['o']), + new Emoji('🛑', 'symbols', ['stop_sign']), + new Emoji('⛔️', 'symbols', ['no_entry']), + new Emoji('📛', 'symbols', ['name_badge']), + new Emoji('🚫', 'symbols', ['no_entry_sign']), + new Emoji('💯', 'symbols', ['100']), + new Emoji('💢', 'symbols', ['anger']), + new Emoji('♨️', 'symbols', ['hotsprings']), + new Emoji('🚷', 'symbols', ['no_pedestrians']), + new Emoji('🚯', 'symbols', ['do_not_litter']), + new Emoji('🚳', 'symbols', ['no_bicycles']), + new Emoji('🚱', 'symbols', ['non-potable_water']), + new Emoji('🔞', 'symbols', ['underage']), + new Emoji('📵', 'symbols', ['no_mobile_phones']), + new Emoji('🚭', 'symbols', ['no_smoking']), + new Emoji('❗️', 'symbols', ['exclamation', 'heavy_exclamation_mark']), + new Emoji('❕', 'symbols', ['grey_exclamation']), + new Emoji('❓', 'symbols', ['question']), + new Emoji('❔', 'symbols', ['grey_question']), + new Emoji('‼️', 'symbols', ['bangbang']), + new Emoji('⁉️', 'symbols', ['interrobang']), + new Emoji('🔅', 'symbols', ['low_brightness']), + new Emoji('🔆', 'symbols', ['high_brightness']), + new Emoji('〽️', 'symbols', ['part_alternation_mark']), + new Emoji('⚠️', 'symbols', ['warning']), + new Emoji('🚸', 'symbols', ['children_crossing']), + new Emoji('🔱', 'symbols', ['trident']), + new Emoji('⚜️', 'symbols', ['fleur_de_lis']), + new Emoji('🔰', 'symbols', ['beginner']), + new Emoji('♻️', 'symbols', ['recycle']), + new Emoji('✅', 'symbols', ['white_check_mark']), + new Emoji('🈯️', 'symbols', ['u6307']), + new Emoji('💹', 'symbols', ['chart']), + new Emoji('❇️', 'symbols', ['sparkle']), + new Emoji('✳️', 'symbols', ['eight_spoked_asterisk']), + new Emoji('❎', 'symbols', ['negative_squared_cross_mark']), + new Emoji('🌐', 'symbols', ['globe_with_meridians']), + new Emoji('💠', 'symbols', ['diamond_shape_with_a_dot_inside']), + new Emoji('Ⓜ️', 'symbols', ['m']), + new Emoji('🌀', 'symbols', ['cyclone']), + new Emoji('💤', 'symbols', ['zzz']), + new Emoji('🏧', 'symbols', ['atm']), + new Emoji('🚾', 'symbols', ['wc']), + new Emoji('♿️', 'symbols', ['wheelchair']), + new Emoji('🅿️', 'symbols', ['parking']), + new Emoji('🈳', 'symbols', ['u7a7a']), + new Emoji('🈂️', 'symbols', ['sa']), + new Emoji('🛂', 'symbols', ['passport_control']), + new Emoji('🛃', 'symbols', ['customs']), + new Emoji('🛄', 'symbols', ['baggage_claim']), + new Emoji('🛅', 'symbols', ['left_luggage']), + new Emoji('🚹', 'symbols', ['mens']), + new Emoji('🚺', 'symbols', ['womens']), + new Emoji('🚼', 'symbols', ['baby_symbol']), + new Emoji('🚻', 'symbols', ['restroom']), + new Emoji('🚮', 'symbols', ['put_litter_in_its_place']), + new Emoji('🎦', 'symbols', ['cinema']), + new Emoji('📶', 'symbols', ['signal_strength']), + new Emoji('🈁', 'symbols', ['koko']), + new Emoji('🔣', 'symbols', ['symbols']), + new Emoji('ℹ️', 'symbols', ['information_source']), + new Emoji('🔤', 'symbols', ['abc']), + new Emoji('🔡', 'symbols', ['abcd']), + new Emoji('🔠', 'symbols', ['capital_abcd']), + new Emoji('🆖', 'symbols', ['ng']), + new Emoji('🆗', 'symbols', ['ok']), + new Emoji('🆙', 'symbols', ['up']), + new Emoji('🆒', 'symbols', ['cool']), + new Emoji('🆕', 'symbols', ['new']), + new Emoji('🆓', 'symbols', ['free']), + new Emoji('0️⃣', 'symbols', ['zero']), + new Emoji('1️⃣', 'symbols', ['one']), + new Emoji('2️⃣', 'symbols', ['two']), + new Emoji('3️⃣', 'symbols', ['three']), + new Emoji('4️⃣', 'symbols', ['four']), + new Emoji('5️⃣', 'symbols', ['five']), + new Emoji('6️⃣', 'symbols', ['six']), + new Emoji('7️⃣', 'symbols', ['seven']), + new Emoji('8️⃣', 'symbols', ['eight']), + new Emoji('9️⃣', 'symbols', ['nine']), + new Emoji('🔟', 'symbols', ['keycap_ten']), + new Emoji('🔢', 'symbols', ['1234']), + new Emoji('#️⃣', 'symbols', ['hash']), + new Emoji('*️⃣', 'symbols', ['asterisk']), + new Emoji('▶️', 'symbols', ['arrow_forward']), + new Emoji('⏸', 'symbols', ['pause_button']), + new Emoji('⏯', 'symbols', ['play_or_pause_button']), + new Emoji('⏹', 'symbols', ['stop_button']), + new Emoji('⏺', 'symbols', ['record_button']), + new Emoji('⏭', 'symbols', ['next_track_button']), + new Emoji('⏮', 'symbols', ['previous_track_button']), + new Emoji('⏩', 'symbols', ['fast_forward']), + new Emoji('⏪', 'symbols', ['rewind']), + new Emoji('⏫', 'symbols', ['arrow_double_up']), + new Emoji('⏬', 'symbols', ['arrow_double_down']), + new Emoji('◀️', 'symbols', ['arrow_backward']), + new Emoji('🔼', 'symbols', ['arrow_up_small']), + new Emoji('🔽', 'symbols', ['arrow_down_small']), + new Emoji('➡️', 'symbols', ['arrow_right']), + new Emoji('⬅️', 'symbols', ['arrow_left']), + new Emoji('⬆️', 'symbols', ['arrow_up']), + new Emoji('⬇️', 'symbols', ['arrow_down']), + new Emoji('↗️', 'symbols', ['arrow_upper_right']), + new Emoji('↘️', 'symbols', ['arrow_lower_right']), + new Emoji('↙️', 'symbols', ['arrow_lower_left']), + new Emoji('↖️', 'symbols', ['arrow_upper_left']), + new Emoji('↕️', 'symbols', ['arrow_up_down']), + new Emoji('↔️', 'symbols', ['left_right_arrow']), + new Emoji('↪️', 'symbols', ['arrow_right_hook']), + new Emoji('↩️', 'symbols', ['leftwards_arrow_with_hook']), + new Emoji('⤴️', 'symbols', ['arrow_heading_up']), + new Emoji('⤵️', 'symbols', ['arrow_heading_down']), + new Emoji('🔀', 'symbols', ['twisted_rightwards_arrows']), + new Emoji('🔁', 'symbols', ['repeat']), + new Emoji('🔂', 'symbols', ['repeat_one']), + new Emoji('🔄', 'symbols', ['arrows_counterclockwise']), + new Emoji('🔃', 'symbols', ['arrows_clockwise']), + new Emoji('🎵', 'symbols', ['musical_note']), + new Emoji('🎶', 'symbols', ['notes']), + new Emoji('➕', 'symbols', ['heavy_plus_sign']), + new Emoji('➖', 'symbols', ['heavy_minus_sign']), + new Emoji('➗', 'symbols', ['heavy_division_sign']), + new Emoji('✖️', 'symbols', ['heavy_multiplication_x']), + new Emoji('💲', 'symbols', ['heavy_dollar_sign']), + new Emoji('💱', 'symbols', ['currency_exchange']), + new Emoji('™️', 'symbols', ['tm']), + new Emoji('©️', 'symbols', ['copyright']), + new Emoji('®️', 'symbols', ['registered']), + new Emoji('〰️', 'symbols', ['wavy_dash']), + new Emoji('➰', 'symbols', ['curly_loop']), + new Emoji('➿', 'symbols', ['loop']), + new Emoji('🔚', 'symbols', ['end']), + new Emoji('🔙', 'symbols', ['back']), + new Emoji('🔛', 'symbols', ['on']), + new Emoji('🔝', 'symbols', ['top']), + new Emoji('🔜', 'symbols', ['soon']), + new Emoji('✔️', 'symbols', ['heavy_check_mark']), + new Emoji('☑️', 'symbols', ['ballot_box_with_check']), + new Emoji('🔘', 'symbols', ['radio_button']), + new Emoji('⚪️', 'symbols', ['white_circle']), + new Emoji('⚫️', 'symbols', ['black_circle']), + new Emoji('🔴', 'symbols', ['red_circle']), + new Emoji('🔵', 'symbols', ['large_blue_circle']), + new Emoji('🔺', 'symbols', ['small_red_triangle']), + new Emoji('🔻', 'symbols', ['small_red_triangle_down']), + new Emoji('🔸', 'symbols', ['small_orange_diamond']), + new Emoji('🔹', 'symbols', ['small_blue_diamond']), + new Emoji('🔶', 'symbols', ['large_orange_diamond']), + new Emoji('🔷', 'symbols', ['large_blue_diamond']), + new Emoji('🔳', 'symbols', ['white_square_button']), + new Emoji('🔲', 'symbols', ['black_square_button']), + new Emoji('▪️', 'symbols', ['black_small_square']), + new Emoji('▫️', 'symbols', ['white_small_square']), + new Emoji('◾️', 'symbols', ['black_medium_small_square']), + new Emoji('◽️', 'symbols', ['white_medium_small_square']), + new Emoji('◼️', 'symbols', ['black_medium_square']), + new Emoji('◻️', 'symbols', ['white_medium_square']), + new Emoji('⬛️', 'symbols', ['black_large_square']), + new Emoji('⬜️', 'symbols', ['white_large_square']), + new Emoji('🔈', 'symbols', ['speaker']), + new Emoji('🔇', 'symbols', ['mute']), + new Emoji('🔉', 'symbols', ['sound']), + new Emoji('🔊', 'symbols', ['loud_sound']), + new Emoji('🔔', 'symbols', ['bell']), + new Emoji('🔕', 'symbols', ['no_bell']), + new Emoji('📣', 'symbols', ['mega']), + new Emoji('📢', 'symbols', ['loudspeaker']), + new Emoji('👁‍🗨', 'symbols', ['eye_speech_bubble']), + new Emoji('💬', 'symbols', ['speech_balloon']), + new Emoji('💭', 'symbols', ['thought_balloon']), + new Emoji('🗯', 'symbols', ['right_anger_bubble']), + new Emoji('♠️', 'symbols', ['spades']), + new Emoji('♣️', 'symbols', ['clubs']), + new Emoji('♥️', 'symbols', ['hearts']), + new Emoji('♦️', 'symbols', ['diamonds']), + new Emoji('🃏', 'symbols', ['black_joker']), + new Emoji('🎴', 'symbols', ['flower_playing_cards']), + new Emoji('🀄️', 'symbols', ['mahjong']), + new Emoji('🕐', 'symbols', ['clock1']), + new Emoji('🕑', 'symbols', ['clock2']), + new Emoji('🕒', 'symbols', ['clock3']), + new Emoji('🕓', 'symbols', ['clock4']), + new Emoji('🕔', 'symbols', ['clock5']), + new Emoji('🕕', 'symbols', ['clock6']), + new Emoji('🕖', 'symbols', ['clock7']), + new Emoji('🕗', 'symbols', ['clock8']), + new Emoji('🕘', 'symbols', ['clock9']), + new Emoji('🕙', 'symbols', ['clock10']), + new Emoji('🕚', 'symbols', ['clock11']), + new Emoji('🕛', 'symbols', ['clock12']), + new Emoji('🕜', 'symbols', ['clock130']), + new Emoji('🕝', 'symbols', ['clock230']), + new Emoji('🕞', 'symbols', ['clock330']), + new Emoji('🕟', 'symbols', ['clock430']), + new Emoji('🕠', 'symbols', ['clock530']), + new Emoji('🕡', 'symbols', ['clock630']), + new Emoji('🕢', 'symbols', ['clock730']), + new Emoji('🕣', 'symbols', ['clock830']), + new Emoji('🕤', 'symbols', ['clock930']), + new Emoji('🕥', 'symbols', ['clock1030']), + new Emoji('🕦', 'symbols', ['clock1130']), + new Emoji('🕧', 'symbols', ['clock1230']), + new Emoji('🏳️', 'flags', ['white_flag']), + new Emoji('🏴', 'flags', ['black_flag']), + new Emoji('🏁', 'flags', ['checkered_flag']), + new Emoji('🚩', 'flags', ['triangular_flag_on_post']), + new Emoji('🏳️‍🌈', 'flags', ['rainbow_flag']), + new Emoji('🇦🇫', 'flags', ['afghanistan']), + new Emoji('🇦🇽', 'flags', ['aland_islands']), + new Emoji('🇦🇱', 'flags', ['albania']), + new Emoji('🇩🇿', 'flags', ['algeria']), + new Emoji('🇦🇸', 'flags', ['american_samoa']), + new Emoji('🇦🇩', 'flags', ['andorra']), + new Emoji('🇦🇴', 'flags', ['angola']), + new Emoji('🇦🇮', 'flags', ['anguilla']), + new Emoji('🇦🇶', 'flags', ['antarctica']), + new Emoji('🇦🇬', 'flags', ['antigua_barbuda']), + new Emoji('🇦🇷', 'flags', ['argentina']), + new Emoji('🇦🇲', 'flags', ['armenia']), + new Emoji('🇦🇼', 'flags', ['aruba']), + new Emoji('🇦🇺', 'flags', ['australia']), + new Emoji('🇦🇹', 'flags', ['austria']), + new Emoji('🇦🇿', 'flags', ['azerbaijan']), + new Emoji('🇧🇸', 'flags', ['bahamas']), + new Emoji('🇧🇭', 'flags', ['bahrain']), + new Emoji('🇧🇩', 'flags', ['bangladesh']), + new Emoji('🇧🇧', 'flags', ['barbados']), + new Emoji('🇧🇾', 'flags', ['belarus']), + new Emoji('🇧🇪', 'flags', ['belgium']), + new Emoji('🇧🇿', 'flags', ['belize']), + new Emoji('🇧🇯', 'flags', ['benin']), + new Emoji('🇧🇲', 'flags', ['bermuda']), + new Emoji('🇧🇹', 'flags', ['bhutan']), + new Emoji('🇧🇴', 'flags', ['bolivia']), + new Emoji('🇧🇶', 'flags', ['caribbean_netherlands']), + new Emoji('🇧🇦', 'flags', ['bosnia_herzegovina']), + new Emoji('🇧🇼', 'flags', ['botswana']), + new Emoji('🇧🇷', 'flags', ['brazil']), + new Emoji('🇮🇴', 'flags', ['british_indian_ocean_territory']), + new Emoji('🇻🇬', 'flags', ['british_virgin_islands']), + new Emoji('🇧🇳', 'flags', ['brunei']), + new Emoji('🇧🇬', 'flags', ['bulgaria']), + new Emoji('🇧🇫', 'flags', ['burkina_faso']), + new Emoji('🇧🇮', 'flags', ['burundi']), + new Emoji('🇨🇻', 'flags', ['cape_verde']), + new Emoji('🇰🇭', 'flags', ['cambodia']), + new Emoji('🇨🇲', 'flags', ['cameroon']), + new Emoji('🇨🇦', 'flags', ['canada']), + new Emoji('🇮🇨', 'flags', ['canary_islands']), + new Emoji('🇰🇾', 'flags', ['cayman_islands']), + new Emoji('🇨🇫', 'flags', ['central_african_republic']), + new Emoji('🇹🇩', 'flags', ['chad']), + new Emoji('🇨🇱', 'flags', ['chile']), + new Emoji('🇨🇳', 'flags', ['cn']), + new Emoji('🇨🇽', 'flags', ['christmas_island']), + new Emoji('🇨🇨', 'flags', ['cocos_islands']), + new Emoji('🇨🇴', 'flags', ['colombia']), + new Emoji('🇰🇲', 'flags', ['comoros']), + new Emoji('🇨🇬', 'flags', ['congo_brazzaville']), + new Emoji('🇨🇩', 'flags', ['congo_kinshasa']), + new Emoji('🇨🇰', 'flags', ['cook_islands']), + new Emoji('🇨🇷', 'flags', ['costa_rica']), + new Emoji('🇨🇮', 'flags', ['cote_divoire']), + new Emoji('🇭🇷', 'flags', ['croatia']), + new Emoji('🇨🇺', 'flags', ['cuba']), + new Emoji('🇨🇼', 'flags', ['curacao']), + new Emoji('🇨🇾', 'flags', ['cyprus']), + new Emoji('🇨🇿', 'flags', ['czech_republic']), + new Emoji('🇩🇰', 'flags', ['denmark']), + new Emoji('🇩🇯', 'flags', ['djibouti']), + new Emoji('🇩🇲', 'flags', ['dominica']), + new Emoji('🇩🇴', 'flags', ['dominican_republic']), + new Emoji('🇪🇨', 'flags', ['ecuador']), + new Emoji('🇪🇬', 'flags', ['egypt']), + new Emoji('🇸🇻', 'flags', ['el_salvador']), + new Emoji('🇬🇶', 'flags', ['equatorial_guinea']), + new Emoji('🇪🇷', 'flags', ['eritrea']), + new Emoji('🇪🇪', 'flags', ['estonia']), + new Emoji('🇪🇹', 'flags', ['ethiopia']), + new Emoji('🇪🇺', 'flags', ['eu', 'european_union']), + new Emoji('🇫🇰', 'flags', ['falkland_islands']), + new Emoji('🇫🇴', 'flags', ['faroe_islands']), + new Emoji('🇫🇯', 'flags', ['fiji']), + new Emoji('🇫🇮', 'flags', ['finland']), + new Emoji('🇫🇷', 'flags', ['fr']), + new Emoji('🇬🇫', 'flags', ['french_guiana']), + new Emoji('🇵🇫', 'flags', ['french_polynesia']), + new Emoji('🇹🇫', 'flags', ['french_southern_territories']), + new Emoji('🇬🇦', 'flags', ['gabon']), + new Emoji('🇬🇲', 'flags', ['gambia']), + new Emoji('🇬🇪', 'flags', ['georgia']), + new Emoji('🇩🇪', 'flags', ['de']), + new Emoji('🇬🇭', 'flags', ['ghana']), + new Emoji('🇬🇮', 'flags', ['gibraltar']), + new Emoji('🇬🇷', 'flags', ['greece']), + new Emoji('🇬🇱', 'flags', ['greenland']), + new Emoji('🇬🇩', 'flags', ['grenada']), + new Emoji('🇬🇵', 'flags', ['guadeloupe']), + new Emoji('🇬🇺', 'flags', ['guam']), + new Emoji('🇬🇹', 'flags', ['guatemala']), + new Emoji('🇬🇬', 'flags', ['guernsey']), + new Emoji('🇬🇳', 'flags', ['guinea']), + new Emoji('🇬🇼', 'flags', ['guinea_bissau']), + new Emoji('🇬🇾', 'flags', ['guyana']), + new Emoji('🇭🇹', 'flags', ['haiti']), + new Emoji('🇭🇳', 'flags', ['honduras']), + new Emoji('🇭🇰', 'flags', ['hong_kong']), + new Emoji('🇭🇺', 'flags', ['hungary']), + new Emoji('🇮🇸', 'flags', ['iceland']), + new Emoji('🇮🇳', 'flags', ['india']), + new Emoji('🇮🇩', 'flags', ['indonesia']), + new Emoji('🇮🇷', 'flags', ['iran']), + new Emoji('🇮🇶', 'flags', ['iraq']), + new Emoji('🇮🇪', 'flags', ['ireland']), + new Emoji('🇮🇲', 'flags', ['isle_of_man']), + new Emoji('🇮🇱', 'flags', ['israel']), + new Emoji('🇮🇹', 'flags', ['it']), + new Emoji('🇯🇲', 'flags', ['jamaica']), + new Emoji('🇯🇵', 'flags', ['jp']), + new Emoji('🎌', 'flags', ['crossed_flags']), + new Emoji('🇯🇪', 'flags', ['jersey']), + new Emoji('🇯🇴', 'flags', ['jordan']), + new Emoji('🇰🇿', 'flags', ['kazakhstan']), + new Emoji('🇰🇪', 'flags', ['kenya']), + new Emoji('🇰🇮', 'flags', ['kiribati']), + new Emoji('🇽🇰', 'flags', ['kosovo']), + new Emoji('🇰🇼', 'flags', ['kuwait']), + new Emoji('🇰🇬', 'flags', ['kyrgyzstan']), + new Emoji('🇱🇦', 'flags', ['laos']), + new Emoji('🇱🇻', 'flags', ['latvia']), + new Emoji('🇱🇧', 'flags', ['lebanon']), + new Emoji('🇱🇸', 'flags', ['lesotho']), + new Emoji('🇱🇷', 'flags', ['liberia']), + new Emoji('🇱🇾', 'flags', ['libya']), + new Emoji('🇱🇮', 'flags', ['liechtenstein']), + new Emoji('🇱🇹', 'flags', ['lithuania']), + new Emoji('🇱🇺', 'flags', ['luxembourg']), + new Emoji('🇲🇴', 'flags', ['macau']), + new Emoji('🇲🇰', 'flags', ['macedonia']), + new Emoji('🇲🇬', 'flags', ['madagascar']), + new Emoji('🇲🇼', 'flags', ['malawi']), + new Emoji('🇲🇾', 'flags', ['malaysia']), + new Emoji('🇲🇻', 'flags', ['maldives']), + new Emoji('🇲🇱', 'flags', ['mali']), + new Emoji('🇲🇹', 'flags', ['malta']), + new Emoji('🇲🇭', 'flags', ['marshall_islands']), + new Emoji('🇲🇶', 'flags', ['martinique']), + new Emoji('🇲🇷', 'flags', ['mauritania']), + new Emoji('🇲🇺', 'flags', ['mauritius']), + new Emoji('🇾🇹', 'flags', ['mayotte']), + new Emoji('🇲🇽', 'flags', ['mexico']), + new Emoji('🇫🇲', 'flags', ['micronesia']), + new Emoji('🇲🇩', 'flags', ['moldova']), + new Emoji('🇲🇨', 'flags', ['monaco']), + new Emoji('🇲🇳', 'flags', ['mongolia']), + new Emoji('🇲🇪', 'flags', ['montenegro']), + new Emoji('🇲🇸', 'flags', ['montserrat']), + new Emoji('🇲🇦', 'flags', ['morocco']), + new Emoji('🇲🇿', 'flags', ['mozambique']), + new Emoji('🇲🇲', 'flags', ['myanmar']), + new Emoji('🇳🇦', 'flags', ['namibia']), + new Emoji('🇳🇷', 'flags', ['nauru']), + new Emoji('🇳🇵', 'flags', ['nepal']), + new Emoji('🇳🇱', 'flags', ['netherlands']), + new Emoji('🇳🇨', 'flags', ['new_caledonia']), + new Emoji('🇳🇿', 'flags', ['new_zealand']), + new Emoji('🇳🇮', 'flags', ['nicaragua']), + new Emoji('🇳🇪', 'flags', ['niger']), + new Emoji('🇳🇬', 'flags', ['nigeria']), + new Emoji('🇳🇺', 'flags', ['niue']), + new Emoji('🇳🇫', 'flags', ['norfolk_island']), + new Emoji('🇲🇵', 'flags', ['northern_mariana_islands']), + new Emoji('🇰🇵', 'flags', ['north_korea']), + new Emoji('🇳🇴', 'flags', ['norway']), + new Emoji('🇴🇲', 'flags', ['oman']), + new Emoji('🇵🇰', 'flags', ['pakistan']), + new Emoji('🇵🇼', 'flags', ['palau']), + new Emoji('🇵🇸', 'flags', ['palestinian_territories']), + new Emoji('🇵🇦', 'flags', ['panama']), + new Emoji('🇵🇬', 'flags', ['papua_new_guinea']), + new Emoji('🇵🇾', 'flags', ['paraguay']), + new Emoji('🇵🇪', 'flags', ['peru']), + new Emoji('🇵🇭', 'flags', ['philippines']), + new Emoji('🇵🇳', 'flags', ['pitcairn_islands']), + new Emoji('🇵🇱', 'flags', ['poland']), + new Emoji('🇵🇹', 'flags', ['portugal']), + new Emoji('🇵🇷', 'flags', ['puerto_rico']), + new Emoji('🇶🇦', 'flags', ['qatar']), + new Emoji('🇷🇪', 'flags', ['reunion']), + new Emoji('🇷🇴', 'flags', ['romania']), + new Emoji('🇷🇺', 'flags', ['ru']), + new Emoji('🇷🇼', 'flags', ['rwanda']), + new Emoji('🇧🇱', 'flags', ['st_barthelemy']), + new Emoji('🇸🇭', 'flags', ['st_helena']), + new Emoji('🇰🇳', 'flags', ['st_kitts_nevis']), + new Emoji('🇱🇨', 'flags', ['st_lucia']), + new Emoji('🇵🇲', 'flags', ['st_pierre_miquelon']), + new Emoji('🇻🇨', 'flags', ['st_vincent_grenadines']), + new Emoji('🇼🇸', 'flags', ['samoa']), + new Emoji('🇸🇲', 'flags', ['san_marino']), + new Emoji('🇸🇹', 'flags', ['sao_tome_principe']), + new Emoji('🇸🇦', 'flags', ['saudi_arabia']), + new Emoji('🇸🇳', 'flags', ['senegal']), + new Emoji('🇷🇸', 'flags', ['serbia']), + new Emoji('🇸🇨', 'flags', ['seychelles']), + new Emoji('🇸🇱', 'flags', ['sierra_leone']), + new Emoji('🇸🇬', 'flags', ['singapore']), + new Emoji('🇸🇽', 'flags', ['sint_maarten']), + new Emoji('🇸🇰', 'flags', ['slovakia']), + new Emoji('🇸🇮', 'flags', ['slovenia']), + new Emoji('🇸🇧', 'flags', ['solomon_islands']), + new Emoji('🇸🇴', 'flags', ['somalia']), + new Emoji('🇿🇦', 'flags', ['south_africa']), + new Emoji('🇬🇸', 'flags', ['south_georgia_south_sandwich_islands']), + new Emoji('🇰🇷', 'flags', ['kr']), + new Emoji('🇸🇸', 'flags', ['south_sudan']), + new Emoji('🇪🇸', 'flags', ['es']), + new Emoji('🇱🇰', 'flags', ['sri_lanka']), + new Emoji('🇸🇩', 'flags', ['sudan']), + new Emoji('🇸🇷', 'flags', ['suriname']), + new Emoji('🇸🇿', 'flags', ['swaziland']), + new Emoji('🇸🇪', 'flags', ['sweden']), + new Emoji('🇨🇭', 'flags', ['switzerland']), + new Emoji('🇸🇾', 'flags', ['syria']), + new Emoji('🇹🇼', 'flags', ['taiwan']), + new Emoji('🇹🇯', 'flags', ['tajikistan']), + new Emoji('🇹🇿', 'flags', ['tanzania']), + new Emoji('🇹🇭', 'flags', ['thailand']), + new Emoji('🇹🇱', 'flags', ['timor_leste']), + new Emoji('🇹🇬', 'flags', ['togo']), + new Emoji('🇹🇰', 'flags', ['tokelau']), + new Emoji('🇹🇴', 'flags', ['tonga']), + new Emoji('🇹🇹', 'flags', ['trinidad_tobago']), + new Emoji('🇹🇳', 'flags', ['tunisia']), + new Emoji('🇹🇷', 'flags', ['tr']), + new Emoji('🇹🇲', 'flags', ['turkmenistan']), + new Emoji('🇹🇨', 'flags', ['turks_caicos_islands']), + new Emoji('🇹🇻', 'flags', ['tuvalu']), + new Emoji('🇺🇬', 'flags', ['uganda']), + new Emoji('🇺🇦', 'flags', ['ukraine']), + new Emoji('🇦🇪', 'flags', ['united_arab_emirates']), + new Emoji('🇬🇧', 'flags', ['gb', 'uk']), + new Emoji('🇺🇸', 'flags', ['us']), + new Emoji('🇻🇮', 'flags', ['us_virgin_islands']), + new Emoji('🇺🇾', 'flags', ['uruguay']), + new Emoji('🇺🇿', 'flags', ['uzbekistan']), + new Emoji('🇻🇺', 'flags', ['vanuatu']), + new Emoji('🇻🇦', 'flags', ['vatican_city']), + new Emoji('🇻🇪', 'flags', ['venezuela']), + new Emoji('🇻🇳', 'flags', ['vietnam']), + new Emoji('🇼🇫', 'flags', ['wallis_futuna']), + new Emoji('🇪🇭', 'flags', ['western_sahara']), + new Emoji('🇾🇪', 'flags', ['yemen']), + new Emoji('🇿🇲', 'flags', ['zambia']), + new Emoji('🇿🇼', 'flags', ['zimbabwe']), +]; diff --git a/src/common/emoji-select/icons/index.ts b/src/common/emoji-select/icons/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..438bf79adf3383fb3e9eda610215b88b1355b435 --- /dev/null +++ b/src/common/emoji-select/icons/index.ts @@ -0,0 +1,3 @@ +export * from './emoji'; +export * from './categories'; +export { SearchSvg } from './search'; diff --git a/src/common/emoji-select/icons/search.tsx b/src/common/emoji-select/icons/search.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6bf73fb76e84b4817374ef20434df39d0e3179ea --- /dev/null +++ b/src/common/emoji-select/icons/search.tsx @@ -0,0 +1,13 @@ +export const SearchSvg = (): JSX.Element => ( + + + + + +); diff --git a/src/common/emoji-select/interface/category.ts b/src/common/emoji-select/interface/category.ts new file mode 100644 index 0000000000000000000000000000000000000000..792537205b767d1747941cfe48e2c17f94a547c0 --- /dev/null +++ b/src/common/emoji-select/interface/category.ts @@ -0,0 +1,58 @@ +/** + * 类别接口定义 + * + * @interface ICategory + */ +export interface ICategory { + /** + * 类别的名称 + * + * @type {string} + */ + name: string; + + /** + * 类别的图标(可能是 URL 或其他标识符) + * + * @type {string} + */ + icon: string; + + /** + * 类别相关的文本描述 + * + * @type {string} + */ + text: string; + + /** + * 获取类别的标签(通常是类别的名称) + * + * @returns {string} - 类别的名称 + */ + label: string; +} + +/** + * 类别类,实现 ICategory 接口 + * + * @class Category + * @implements ICategory + */ +export class Category implements ICategory { + public name: string; + + public icon: string; + + public text: string; + + constructor(name: string, icon: string, text: string) { + this.name = name; + this.icon = icon; + this.text = text; + } + + get label(): string { + return this.name; + } +} diff --git a/src/common/emoji-select/interface/emoji.ts b/src/common/emoji-select/interface/emoji.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b2480dbf6e90d4e86ec68ad284752a835a4ed3a --- /dev/null +++ b/src/common/emoji-select/interface/emoji.ts @@ -0,0 +1,47 @@ +/** + * 表情符号接口定义 + * + * @interface IEmoji + */ +export interface IEmoji { + /** + * 表情符号的数据,通常是Unicode编码或svg + * + * @type {string} + */ + data: string; + + /** + * 表情符号所属的分类 + * + * @type {string} + */ + category: string; + + /** + * 表情符号的别名列表 + * + * @type {string[]} + */ + aliases: string[]; +} + +/** + * 表情符号类,实现IEmoji接口 + * + * @class Emoji + * @implements IEmoji + */ +export class Emoji implements IEmoji { + public data: string; + + public category: string; + + public aliases: string[]; + + constructor(data: string, category: string, aliases: string[]) { + this.data = data; + this.category = category; + this.aliases = aliases; + } +} diff --git a/src/common/emoji-select/interface/index.ts b/src/common/emoji-select/interface/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..22725a8d60420ff792debf017437dd815a47585a --- /dev/null +++ b/src/common/emoji-select/interface/index.ts @@ -0,0 +1,3 @@ +export * from './category'; +export * from './emoji'; +export * from './map-emojis'; diff --git a/src/common/emoji-select/interface/map-emojis.ts b/src/common/emoji-select/interface/map-emojis.ts new file mode 100644 index 0000000000000000000000000000000000000000..45fb3169f86d86d2a50145c82f9b85665eee05f1 --- /dev/null +++ b/src/common/emoji-select/interface/map-emojis.ts @@ -0,0 +1,18 @@ +import { IEmoji } from './emoji'; + +/** + * 表情符号映射接口 + * + * 此接口定义了一个对象,其键为字符串类型(可能是某种分类或标识符), + * 对应的值为IEmoji接口的数组,表示属于该键所代表分类或标识符的表情符号列表。 + * + * @interface MapEmojis + */ +export interface MapEmojis { + /** + * 表情符号的分类或标识符,作为对象的键 + * + * @type {string} + */ + [x: string]: IEmoji[]; +} diff --git a/src/common/index.ts b/src/common/index.ts index 4be9af39f027019f90df6397336bab033ad73334..34bae54c3f76c85021572dfd445748b014a31c1a 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -18,6 +18,7 @@ import { IBizPresetViewBack } from './preset-view-back/preset-view-back'; import { IBizPresetViewHeader } from './preset-view-header/preset-view-header'; import { IBizFullscreenHeader } from './fullscreen-header/fullscreen-header'; import { IBizButtonList } from './button-list/button-list'; +import { IBizEmojiSelect } from './emoji-select/emoji-select'; export * from './col/col'; export * from './row/row'; @@ -42,6 +43,7 @@ export const IBizCommonComponents = { v.component(IBizCodeList.name, IBizCodeList); v.component(IBizFullscreenHeader.name, IBizFullscreenHeader); v.component(IBizButtonList.name, IBizButtonList); + v.component(IBizEmojiSelect.name, IBizEmojiSelect); }, }; diff --git a/src/common/rawitem/rawitem.tsx b/src/common/rawitem/rawitem.tsx index d7dca4a3c00399bff6b4c19341421b42281ae351..469ac23ba8cfa1e6c442377ce9bc49dac91fc1fe 100644 --- a/src/common/rawitem/rawitem.tsx +++ b/src/common/rawitem/rawitem.tsx @@ -9,6 +9,7 @@ import { IUnkownItem, } from '@ibiz/model-core'; import './rawitem.scss'; +import { parseHtml } from '../../panel-component/user-message/user-message.util'; export const IBizRawItem = defineComponent({ name: 'IBizRawItem', @@ -128,6 +129,11 @@ export const IBizRawItem = defineComponent({ } } + // 解析表情内容 + if (rawItemType.value === 'HTML') { + rawItemText.value = parseHtml(rawItemText.value as string); + } + if ( ['VIDEO', 'DIVIDER', 'INFO', 'WARNING', 'ERROR'].includes( rawItemType.value, diff --git a/src/control/tree/tree.tsx b/src/control/tree/tree.tsx index 23a8107be45d23c6266f68a80acec388d816d219..da56c508a105be526563ea932ebc673b6f41ae64 100644 --- a/src/control/tree/tree.tsx +++ b/src/control/tree/tree.tsx @@ -1,7 +1,11 @@ import { useControlController, useNamespace } from '@ibiz-template/vue3-util'; import { computed, defineComponent, PropType, ref, VNode } from 'vue'; import { IDETree } from '@ibiz/model-core'; -import { ITreeNodeData, TreeController } from '@ibiz-template/runtime'; +import { + ITreeController, + ITreeNodeData, + TreeController, +} from '@ibiz-template/runtime'; import { createUUID } from 'qx-util'; import { VsTreeComponent } from '@ibiz-template-package/vs-tree-ex'; import './tree.scss'; @@ -65,6 +69,24 @@ export const TreeControl = defineComponent({ }, []); }); + /** + * 根据id查找树节点数据对象 + * @export + * @param {string} key (数据的_uuid 或者 _id) + * @param {ITreeController} c + * @return {*} {(ITreeNodeData | undefined)} + */ + function findNodeData( + key: string, + controller: ITreeController, + ): ITreeNodeData | undefined { + const find = controller.state.items.find(item => item._id === key); + if (find) { + return find; + } + return controller.state.items.find(item => item._uuid === key); + } + /** * 触发节点加载数据 * @author zk @@ -81,7 +103,15 @@ export const TreeControl = defineComponent({ return; } // 加载时拦截点击事件 - const nodes = await c.loadNodes(item.data); + let nodes: ITreeNodeData[]; + const nodeData = findNodeData(item.data._uuid, c)!; + if (nodeData._children) { + ibiz.log.debug('节点展开加载-本地', nodeData); + nodes = nodeData._children; + } else { + ibiz.log.debug('节点展开加载-远程', nodeData); + nodes = await c.loadNodes(nodeData); + } callback(nodes); }; diff --git a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx index c44896c8f7eabf09c8b13ecdd3c36075743259cf..d2388e46969cc65bba4b3f117fdf86a5273fbbc4 100644 --- a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx +++ b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx @@ -71,6 +71,10 @@ export const IBizPicker = defineComponent({ }); } + Object.assign(data, { + [c.keyName]: data[c.keyName] ? data[c.keyName] : data.srfkey, + [c.textName]: data[c.textName] ? data[c.textName] : data.srfmajortext, + }); // 处理值项和本身的值 if (c.valueItem) { emit('change', data[c.keyName], c.valueItem); diff --git a/src/editor/dropdown-list/dropdown-list-editor.provider.ts b/src/editor/dropdown-list/dropdown-list-editor.provider.ts index f52c8303df7c09e3356fd55f3e7179906c0595cb..345ee4cd667c690a824685969bf0ae0335217b3d 100644 --- a/src/editor/dropdown-list/dropdown-list-editor.provider.ts +++ b/src/editor/dropdown-list/dropdown-list-editor.provider.ts @@ -21,11 +21,21 @@ export class DropDownListEditorProvider implements IEditorProvider { gridEditor: string = 'IBizDropdown'; constructor(editorType?: string) { - // 特殊识别标识MOBCHECKLIST 模型中文名称为:下拉列表多选 - if (editorType === 'MOBCHECKLIST') { - this.formEditor = 'IBizDropdownList'; - this.gridEditor = 'IBizDropdownList'; + let componentName = 'IBizDropdown'; + switch (editorType) { + // 特殊识别标识MOBCHECKLIST 模型中文名称为:下拉列表多选 + case 'MOBCHECKLIST': + componentName = 'IBizDropdownList'; + break; + // 模型中文名称为:表情选择 + case 'EMOJI_PICKER': + componentName = 'IBizEmojiPicker'; + break; + default: + break; } + this.formEditor = componentName; + this.gridEditor = componentName; } async createController( diff --git a/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.scss b/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.scss new file mode 100644 index 0000000000000000000000000000000000000000..a02fc5829a539a6d50796a3a9f2d3f9700768aee --- /dev/null +++ b/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.scss @@ -0,0 +1,42 @@ +@include b('emoji-picker') { + display: flex; + align-items: center; + width: 100%; + height: 100%; + min-height: getCssVar('height-control', 'default'); + + @include e('button-content') { + display: flex; + align-items: center; + line-height: getCssVar('font-size', 'header-4'); + + @include m('icon') { + margin-right: getCssVar('spacing', 'extra-tight'); + fill: getCssVar(color, primary, text); + } + @include m('icon-clear') { + margin-left: getCssVar('spacing', 'extra-tight'); + font-size: getCssVar('font-size', 'header-3'); + fill: getCssVar('color', 'text', 3); + } + } + + @include e('button') { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + } + + @include m('readonly') { + display: flex; + align-items: center; + pointer-events: none; + } + @include m('disabled') { + display: flex; + align-items: center; + opacity: .5; + pointer-events: none; + } +} diff --git a/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.tsx b/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5b88028abf5ef19b35bf932bbcc1065309d8744d --- /dev/null +++ b/src/editor/dropdown-list/ibiz-emoji-picker/ibiz-emoji-picker.tsx @@ -0,0 +1,172 @@ +import { defineComponent, ref, watch } from 'vue'; +import { + getDropdownProps, + getEditorEmits, + useNamespace, +} from '@ibiz-template/vue3-util'; +import { base64ToStr, strToBase64, isEmoji } from '@ibiz-template/core'; +import './ibiz-emoji-picker.scss'; +import { DropDownListEditorController } from '../dropdown-list-editor.controller'; + +export const IBizEmojiPicker = defineComponent({ + name: 'IBizEmojiPicker', + props: getDropdownProps(), + emits: getEditorEmits(), + setup(props, { emit }) { + const ns = useNamespace('emoji-picker'); + const c = props.controller; + + const emoji = ref(''); + const visible = ref(false); + + // 添加表情 + const onAddEmoji = (e: MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + visible.value = true; + }; + + // 清除表情 + const onClearEmoji = (e: MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + emoji.value = ''; + visible.value = false; + emit('change', ''); + }; + + // 选择表情 + const onSelect = (val: IData) => { + visible.value = false; + emoji.value = val.data; + emit('change', strToBase64(val.data)); + }; + + watch( + () => props.value, + (newVal, oldVal) => { + if (newVal !== oldVal) { + emoji.value = + newVal && isEmoji(`${newVal}`) + ? base64ToStr(newVal as string) + : newVal; + } + }, + { immediate: true }, + ); + + // 绘制按钮内容 + const renderButtonContent = () => { + // 无值时显示 + let content = ( + + + + + + {ibiz.i18n.t('editor.emojiPicker.addEmoji')} + + ); + // 有表情值时显示 + if (emoji.value) { + content = ( + + + + ); + } + return content; + }; + + // 绘制清空 + const renderClear = () => ( + + + + ); + + // 绘制触发 Popover 显示的元素 + const renderReference = () => { + return ( +
+ {renderButtonContent()} + {emoji.value && renderClear()} +
+ ); + }; + + const renderReadonly = () => { + return ( +
+ {renderButtonContent()} +
+ ); + }; + + return { + ns, + c, + emoji, + visible, + onSelect, + onAddEmoji, + onClearEmoji, + renderReference, + renderReadonly, + }; + }, + render() { + let content: JSX.Element | JSX.Element[] = [ + this.renderReference(), + + + , + ]; + + if (this.disabled || this.readonly) { + content = this.renderReadonly(); + } + + return ( +
+ {content} +
+ ); + }, +}); diff --git a/src/editor/dropdown-list/index.ts b/src/editor/dropdown-list/index.ts index 6d962698dfd2a3fa3b4cf87a81892cb7583827dd..78c0001b3f694604e3ef225815336885cb472db0 100644 --- a/src/editor/dropdown-list/index.ts +++ b/src/editor/dropdown-list/index.ts @@ -1,3 +1,4 @@ export { IBizDropdown } from './ibiz-dropdown/ibiz-dropdown'; +export { IBizEmojiPicker } from './ibiz-emoji-picker/ibiz-emoji-picker'; export * from './dropdown-list-editor.controller'; export * from './dropdown-list-editor.provider'; diff --git a/src/editor/index.ts b/src/editor/index.ts index 70f242e39b3de84c1622769a12c73267e4d970e3..5e815af23b2c0f35fa5b8bbb1bcbc41ce95c05fc 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -3,7 +3,11 @@ import { App, defineAsyncComponent } from 'vue'; import { NotSupportedEditor } from './not-supported-editor/not-supported-editor'; import { IBizSpan, SpanEditorProvider } from './span'; import { IBizInput, IBizInputNumber, TextBoxEditorProvider } from './text-box'; -import { IBizDropdown, DropDownListEditorProvider } from './dropdown-list'; +import { + IBizDropdown, + IBizEmojiPicker, + DropDownListEditorProvider, +} from './dropdown-list'; import { CheckBoxListEditorProvider, IBizCheckboxList } from './check-box-list'; import { IBizSwitch, SwitchEditorProvider } from './switch'; import { IBizRadio, RadioButtonListEditorProvider } from './radio-button-list'; @@ -46,6 +50,7 @@ export const IBizEditor = { v.component(IBizRadio.name, IBizRadio); v.component(IBizDropdown.name, IBizDropdown); v.component(IBizDropdownList.name, IBizDropdownList); + v.component(IBizEmojiPicker.name, IBizEmojiPicker); v.component(IBizCheckboxList.name, IBizCheckboxList); v.component(IBizSlider.name, IBizSlider); v.component(IBizStepper.name, IBizStepper); @@ -105,6 +110,12 @@ export const IBizEditor = { () => new DropDownListEditorProvider(), ); + // 表情选择 + registerEditorProvider( + 'MOBDROPDOWNLIST_EMOJI_PICKER', + () => new DropDownListEditorProvider('EMOJI_PICKER'), + ); + // 下拉列表框多选(复选框) registerEditorProvider( 'MOBCHECKLIST', diff --git a/src/editor/span/span/span.tsx b/src/editor/span/span/span.tsx index 1f28b784a5be4dd4ea9fb3d5fb4c8d948d11e76a..d78965d696e44a83598f60e94237d7a2611b87e0 100644 --- a/src/editor/span/span/span.tsx +++ b/src/editor/span/span/span.tsx @@ -7,7 +7,7 @@ import { import './span.scss'; import { CodeListItem } from '@ibiz-template/runtime'; import { isNil } from 'ramda'; -import { DataTypes } from '@ibiz-template/core'; +import { base64ToStr, DataTypes, isEmoji } from '@ibiz-template/core'; import dayjs from 'dayjs'; import customParseFormat from 'dayjs/plugin/customParseFormat'; import { SpanEditorController } from '../span-editor.controller'; @@ -99,6 +99,8 @@ export const IBizSpan = defineComponent({ text.value = `${newVal}`; ibiz.log.error(`${newVal} 值格式化错误`); } + } else if (isEmoji(`${newVal}`)) { + text.value = base64ToStr(`${newVal}`); } else { text.value = `${newVal}`; } diff --git a/src/editor/text-box/input/input.tsx b/src/editor/text-box/input/input.tsx index d2f10f4a1296f23706530782ad179d333755f754..1ee0e373e9cbd7a444455740c9aedd05b4fbddec 100644 --- a/src/editor/text-box/input/input.tsx +++ b/src/editor/text-box/input/input.tsx @@ -1,5 +1,6 @@ import { computed, defineComponent, ref, watch } from 'vue'; import { debounce } from 'lodash-es'; +import { base64ToStr, isEmoji } from '@ibiz-template/core'; import { getEditorEmits, getInputProps, @@ -46,6 +47,8 @@ export const IBizInput = defineComponent({ if (newVal !== oldVal) { if (!newVal) { currentVal.value = ''; + } else if (isEmoji(`${newVal}`)) { + currentVal.value = base64ToStr(`${newVal}`); } else { currentVal.value = newVal; } diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index 25841c827c07d2b47de9e8a1d20d3323af403cb5..0d69429f87578de11f1223e0b28d42aa3d9205c1 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -20,6 +20,17 @@ export default { errorConfig: '{type} type custom parameter configuration error', noSupportVideo: 'Your browser does not support video tags', }, + emojiSelect: { + frequently: 'Frequently', + peoples: 'Peoples', + nature: 'Nature', + foods: 'Foods', + activity: 'Activity', + objects: 'Objects', + places: 'Places', + symbols: 'Symbols', + flags: 'Flags', + }, }, // 部件 control: { @@ -125,6 +136,9 @@ export default { exportJsonFormatErr: 'The configuration of exportparams did not follow the standard JSON format', }, + emojiPicker: { + addEmoji: 'Add emoji', + }, }, // 多语言 locale: { diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index 76e491f3595db831acc5e61791a5368843d4e85e..9328c60ced4e1aea2e4ba26ba9dbd70896ed3af5 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -20,6 +20,17 @@ export default { errorConfig: '{type} 类型自定义参数配置错误', noSupportVideo: '你的浏览器不支持video标签', }, + emojiSelect: { + frequently: '常用', + peoples: '情绪', + nature: '自然', + foods: '食物与饮料', + activity: '活动', + objects: '对象', + places: '旅行与地方', + symbols: '符号', + flags: '旗帜', + }, }, // 部件 control: { @@ -119,6 +130,9 @@ export default { uploadJsonFormatErr: '配置uploadparams没有按标准JSON格式', exportJsonFormatErr: '配置exportparams没有按标准JSON格式', }, + emojiPicker: { + addEmoji: '添加表情', + }, }, // 多语言 locale: {