vuemoji-picker
Version:
Vue 2 and 3 lightweight emoji picker.
236 lines (231 loc) • 6.08 kB
JavaScript
// src/components/VuemojiPicker.ts
import Picker from "emoji-picker-element/picker";
import { defineComponent, isVue2 as isVue22, Vue2 } from "vue-demi";
// src/utils/dark-mode.ts
function isDarkMode() {
return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
}
// src/utils/h-demi.ts
import { h as hDemi, isVue2 } from "vue-demi";
function adaptOnsV3(ons) {
if (!ons)
return null;
return Object.entries(ons).reduce((ret, [key, handler]) => {
key = key.charAt(0).toUpperCase() + key.slice(1);
key = `on${key}`;
return { ...ret, [key]: handler };
}, {});
}
function h(type, options = {}, chidren) {
if (isVue2)
return hDemi(type, options, chidren);
const { props, domProps, on, ...extraOptions } = options;
const ons = adaptOnsV3(on);
const params = { ...extraOptions, ...props, ...domProps, ...ons };
return hDemi(type, params, chidren);
}
var h_demi_default = h;
// src/utils/to-dashes.ts
function toDashes(key) {
return key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
}
// src/components/VuemojiPicker.ts
if (isVue22)
Vue2.config.ignoredElements.push("emoji-picker");
var VuemojiPicker_default = defineComponent({
props: {
isDark: {
type: Boolean,
required: false,
default: isDarkMode()
},
skinToneEmoji: String,
customEmoji: Array,
dataSource: String,
locale: String,
customCategorySorting: Function,
i18n: Object,
pickerStyle: Object
},
emits: ["emojiClick", "skinToneChange"],
data: () => ({
picker: new Picker()
}),
watch: {
$props: {
handler() {
this.updatePickerProps();
},
deep: true
}
},
mounted() {
const root = this.$refs.root;
this.updatePickerProps();
root.appendChild(this.picker);
this.picker.addEventListener("emoji-click", this.handleClick);
this.picker.addEventListener("skin-tone-change", this.handleSkinToneChange);
},
beforeUnmount() {
this.picker.removeEventListener("emoji-click", this.handleClick);
this.picker.removeEventListener("skin-tone-change", this.handleSkinToneChange);
},
methods: {
handleClick(event) {
this.$emit("emojiClick", event.detail);
},
handleSkinToneChange(event) {
this.$emit("skinToneChange", event.detail);
},
updatePickerProps() {
const {
skinToneEmoji,
dataSource,
locale,
customEmoji,
i18n,
customCategorySorting,
isDark
} = this.$props;
if (skinToneEmoji)
this.picker.skinToneEmoji = skinToneEmoji;
if (dataSource)
this.picker.dataSource = dataSource;
if (locale)
this.picker.locale = locale;
if (customEmoji)
this.picker.customEmoji = customEmoji;
if (i18n)
this.picker.i18n = i18n;
if (customCategorySorting)
this.picker.customCategorySorting = customCategorySorting;
this.picker.classList.toggle("dark", isDark);
this.picker.classList.toggle("light", !isDark);
this.updatePickerStyle();
},
updatePickerStyle() {
if (this.pickerStyle && typeof this.pickerStyle === "object") {
Object.keys(this.pickerStyle).forEach((key) => {
if (key === "height" && this.pickerStyle?.height)
this.picker.style.setProperty("height", this.pickerStyle.height);
else if (key === "width" && this.pickerStyle?.width)
this.picker.style.setProperty("width", this.pickerStyle.width);
else
this.picker.style.setProperty(`--${toDashes(key)}`, this.pickerStyle[key]);
});
}
}
},
render() {
return h_demi_default("div", {
ref: "root"
});
}
});
// src/composables/useDatabase.ts
import Database from "emoji-picker-element/database";
import { onMounted, ref, unref, watchEffect } from "vue-demi";
function useDatabase() {
return new Database();
}
function useMounted() {
const isMounted = ref(false);
onMounted(() => {
isMounted.value = true;
});
return isMounted;
}
function useEmojiBySearchQuery(query) {
const db = useDatabase();
const isMounted = useMounted();
const result = ref([]);
const loading = ref(false);
watchEffect(async () => {
if (!isMounted.value)
return;
loading.value = true;
result.value = [];
try {
result.value = await db.getEmojiBySearchQuery(unref(query));
} catch {
} finally {
loading.value = false;
}
});
return {
result,
loading
};
}
function useEmojiByGroup(group) {
const db = useDatabase();
const isMounted = useMounted();
const result = ref([]);
const loading = ref(false);
watchEffect(async () => {
if (!isMounted.value)
return;
loading.value = true;
result.value = [];
try {
result.value = await db.getEmojiByGroup(unref(group));
} catch {
}
loading.value = false;
});
return {
result,
loading
};
}
function useEmojiByShortcode(shortcode) {
const db = useDatabase();
const isMounted = useMounted();
const result = ref(null);
const loading = ref(false);
watchEffect(async () => {
if (!isMounted.value)
return;
loading.value = true;
result.value = null;
try {
result.value = await db.getEmojiByShortcode(unref(shortcode));
} catch {
}
loading.value = false;
});
return {
result,
loading
};
}
function useEmojiByUnicodeOrName(unicodeOrName) {
const db = useDatabase();
const isMounted = useMounted();
const result = ref(null);
const loading = ref(false);
watchEffect(async () => {
if (!isMounted.value)
return;
loading.value = true;
result.value = null;
try {
result.value = await db.getEmojiByUnicodeOrName(unref(unicodeOrName));
} catch {
}
loading.value = false;
});
return {
result,
loading
};
}
export {
VuemojiPicker_default as VuemojiPicker,
useDatabase,
useEmojiByGroup,
useEmojiBySearchQuery,
useEmojiByShortcode,
useEmojiByUnicodeOrName
};
//# sourceMappingURL=index.js.map