emoji
This commit is contained in:
parent
a46d816dc5
commit
6e1e883fb4
|
@ -4,58 +4,58 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- このコンポーネントの要素のclassは親から利用されるのでむやみに弄らないこと -->
|
<!-- このコンポーネントの要素のclassは親から利用されるのでむやみに弄らないこと -->
|
||||||
<!-- フォルダの中にはカスタム絵文字だけ(Unicode絵文字もこっち) -->
|
<!-- フォルダの中にはカスタム絵文字だけ(Unicode絵文字もこっち) -->
|
||||||
<section v-if="!hasChildSection" v-panel style="border-radius: 6px; border-bottom: 0.5px solid var(--divider);">
|
<section v-if="!hasChildSection" style="border-radius: 6px;">
|
||||||
<header class="_acrylic" @click="shown = !shown">
|
<header class="_acrylic" @click="shown = !shown" >
|
||||||
<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> (<i class="ti ti-icons"></i>:{{ emojis.length }})
|
<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> ({{ emojis.length }})
|
||||||
</header>
|
</header>
|
||||||
<div v-if="shown" class="body">
|
<div v-if="shown" class="body">
|
||||||
<button
|
<button
|
||||||
v-for="emoji in emojis"
|
v-for="emoji in emojis"
|
||||||
:key="emoji"
|
:key="emoji"
|
||||||
:data-emoji="emoji"
|
:data-emoji="emoji"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
@pointerenter="computeButtonTitle"
|
@pointerenter="computeButtonTitle"
|
||||||
@click="emit('chosen', emoji, $event)"
|
@click="emit('chosen', emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
||||||
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<!-- フォルダの中にはカスタム絵文字やフォルダがある -->
|
<!-- フォルダの中にはカスタム絵文字やフォルダがある -->
|
||||||
<section v-else v-panel style="border-radius: 6px; border-bottom: 0.5px solid var(--divider);">
|
<section v-else style="border-radius: 6px; padding-top: 9px;">
|
||||||
<header class="_acrylic" @click="shown = !shown">
|
<header class="_acrylic" @click="shown = !shown">
|
||||||
<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> (<i class="ti ti-folder ti-fw"></i>:{{ customEmojiTree?.length }} <i class="ti ti-icons ti-fw"></i>:{{ emojis.length }})
|
<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> (フォルダー)
|
||||||
</header>
|
</header>
|
||||||
<div v-if="shown" style="padding-left: 9px;">
|
<div v-if="shown" style="padding-left: 9px; ">
|
||||||
<MkEmojiPickerSection
|
<MkEmojiPickerSection
|
||||||
v-for="child in customEmojiTree"
|
v-for="child in customEmojiTree"
|
||||||
:key="`custom:${child.value}`"
|
:key="`custom:${child.value}`"
|
||||||
:initialShown="initialShown"
|
:initialShown="initialShown"
|
||||||
:emojis="computed(() => customEmojis.filter(e => e.category === child.category).map(e => `:${e.name}:`))"
|
:emojis="computed(() => customEmojis.filter(e => e.category === child.category || e.category === child.category+'/'+child.category).map(e => `:${e.name}:`))"
|
||||||
:hasChildSection="child.children.length !== 0"
|
:hasChildSection="child.children.length !== 0"
|
||||||
:customEmojiTree="child.children"
|
:customEmojiTree="child.children"
|
||||||
@chosen="nestedChosen"
|
@chosen="nestedChosen"
|
||||||
>
|
>
|
||||||
{{ child.value || i18n.ts.other }}
|
{{ child.value || i18n.ts.other }}
|
||||||
</MkEmojiPickerSection>
|
</MkEmojiPickerSection>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="shown" class="body">
|
<div v-if="shown" class="body">
|
||||||
<button
|
<button
|
||||||
v-for="emoji in emojis"
|
v-for="emoji in emojis"
|
||||||
:key="emoji"
|
:key="emoji"
|
||||||
:data-emoji="emoji"
|
:data-emoji="emoji"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
@pointerenter="computeButtonTitle"
|
@pointerenter="computeButtonTitle"
|
||||||
@click="emit('chosen', emoji, $event)"
|
@click="emit('chosen', emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
||||||
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -66,15 +66,14 @@ import { customEmojis } from '@/custom-emojis.js';
|
||||||
import MkEmojiPickerSection from '@/components/MkEmojiPicker.section.vue';
|
import MkEmojiPickerSection from '@/components/MkEmojiPicker.section.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
category?: string[];
|
category?: string[];
|
||||||
emojis: string[] | Ref<string[]>;
|
emojis: string[] | Ref<string[]>;
|
||||||
initialShown?: boolean;
|
initialShown?: boolean;
|
||||||
hasChildSection?: boolean;
|
hasChildSection?: boolean;
|
||||||
customEmojiTree?: CustomEmojiFolderTree[];
|
customEmojiTree?: CustomEmojiFolderTree[];
|
||||||
}>();
|
}>();
|
||||||
console.log(props.customEmojiTree);
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'chosen', v: string, event: MouseEvent): void;
|
(ev: 'chosen', v: string, event: MouseEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emojis = computed(() => Array.isArray(props.emojis) ? props.emojis : props.emojis.value);
|
const emojis = computed(() => Array.isArray(props.emojis) ? props.emojis : props.emojis.value);
|
||||||
|
@ -82,12 +81,12 @@ const shown = ref(!!props.initialShown);
|
||||||
|
|
||||||
/** @see MkEmojiPicker.vue */
|
/** @see MkEmojiPicker.vue */
|
||||||
function computeButtonTitle(ev: MouseEvent): void {
|
function computeButtonTitle(ev: MouseEvent): void {
|
||||||
const elm = ev.target as HTMLElement;
|
const elm = ev.target as HTMLElement;
|
||||||
const emoji = elm.dataset.emoji as string;
|
const emoji = elm.dataset.emoji as string;
|
||||||
elm.title = getEmojiName(emoji) ?? emoji;
|
elm.title = getEmojiName(emoji) ?? emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
function nestedChosen(emoji: any, ev: MouseEvent) {
|
function nestedChosen(emoji: any, ev?: MouseEvent) {
|
||||||
emit('chosen', emoji, ev);
|
emit('chosen', emoji, ev);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,103 +4,103 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
||||||
<input ref="searchEl" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter">
|
<input ref="searchEl" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter">
|
||||||
<!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 -->
|
<!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 -->
|
||||||
<div ref="emojisEl" class="emojis" tabindex="-1">
|
<div ref="emojisEl" class="emojis" tabindex="-1">
|
||||||
<section class="result">
|
<section class="result">
|
||||||
<div v-if="searchResultCustom.length > 0" class="body">
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
<button
|
|
||||||
v-for="emoji in searchResultCustom"
|
|
||||||
:key="emoji.name"
|
|
||||||
class="_button item"
|
|
||||||
:title="emoji.name"
|
|
||||||
tabindex="0"
|
|
||||||
@click="chosen(emoji, $event)"
|
|
||||||
>
|
|
||||||
<MkCustomEmoji class="emoji" :name="emoji.name"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div v-if="searchResultUnicode.length > 0" class="body">
|
|
||||||
<button
|
|
||||||
v-for="emoji in searchResultUnicode"
|
|
||||||
:key="emoji.name"
|
|
||||||
class="_button item"
|
|
||||||
:title="emoji.name"
|
|
||||||
tabindex="0"
|
|
||||||
@click="chosen(emoji, $event)"
|
|
||||||
>
|
|
||||||
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div v-if="tab === 'index'" class="group index">
|
|
||||||
<section v-if="showPinned && (pinned && pinned.length > 0)">
|
|
||||||
<div style="display: flex; ">
|
|
||||||
<div v-for="a in profileMax" :key="a" :title="defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`]" class="sllfktkhgl" :class="{ active: activeIndex === a || isDefaultProfile === a }" @click="pinnedProfileSelect(a)">
|
|
||||||
{{ defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`] }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="body">
|
|
||||||
<button
|
<button
|
||||||
v-for="emoji in pinnedEmojis"
|
v-for="emoji in searchResultCustom"
|
||||||
:key="emoji"
|
:key="emoji.name"
|
||||||
:data-emoji="emoji"
|
|
||||||
class="_button item"
|
class="_button item"
|
||||||
|
:title="emoji.name"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@pointerenter="computeButtonTitle"
|
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
<MkCustomEmoji class="emoji" :name="emoji.name"/>
|
||||||
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||||
|
<button
|
||||||
|
v-for="emoji in searchResultUnicode"
|
||||||
|
:key="emoji.name"
|
||||||
|
class="_button item"
|
||||||
|
:title="emoji.name"
|
||||||
|
tabindex="0"
|
||||||
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<div v-if="tab === 'index'" class="group index">
|
||||||
<header class="_acrylic"><i class="ti ti-clock ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
<section v-if="showPinned">
|
||||||
<div class="body">
|
<div style="display: flex; ">
|
||||||
<button
|
<div v-for="a in profileMax" :key="a" :title="defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`]" class="sllfktkhgl" :class="{ active: activeIndex === a || isDefaultProfile === a }" @click="pinnedProfileSelect(a)">
|
||||||
v-for="emoji in recentlyUsedEmojis"
|
{{ defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`] }}
|
||||||
:key="emoji"
|
</div>
|
||||||
class="_button item"
|
</div>
|
||||||
:data-emoji="emoji"
|
<div class="body">
|
||||||
@pointerenter="computeButtonTitle"
|
<button
|
||||||
@click="chosen(emoji, $event)"
|
v-for="emoji in pinnedEmojis"
|
||||||
>
|
:key="emoji"
|
||||||
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
:data-emoji="emoji"
|
||||||
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
class="_button item"
|
||||||
</button>
|
tabindex="0"
|
||||||
</div>
|
@pointerenter="computeButtonTitle"
|
||||||
</section>
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
||||||
|
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<header class="_acrylic"><i class="ti ti-clock ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
||||||
|
<div class="body">
|
||||||
|
<button
|
||||||
|
v-for="emoji in recentlyUsedEmojis"
|
||||||
|
:key="emoji"
|
||||||
|
class="_button item"
|
||||||
|
:data-emoji="emoji"
|
||||||
|
@pointerenter="computeButtonTitle"
|
||||||
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
|
||||||
|
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div v-once class="group">
|
||||||
|
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
||||||
|
<XSection
|
||||||
|
v-for="child in customEmojiFolderRoot.children"
|
||||||
|
:key="`custom:${child.value}`"
|
||||||
|
:initialShown="false"
|
||||||
|
:emojis="computed(() => customEmojis.filter(e => child.value === '' ? (e.category === 'null' || !e.category) : e.category === child.value && !customEmojis.some(emoji => emoji.category !== null && emoji.category.includes(e.category+'/')) || e.category === child.category+'/'+child.category && !e.category).filter(filterAvailable).map(e => `:${e.name}:`))"
|
||||||
|
:hasChildSection="child.children.length !== 0"
|
||||||
|
:customEmojiTree="child.children"
|
||||||
|
@chosen="chosen"
|
||||||
|
>
|
||||||
|
{{ child.value || i18n.ts.other }}
|
||||||
|
</XSection>
|
||||||
|
</div>
|
||||||
|
<div v-once class="group">
|
||||||
|
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
||||||
|
<XSection v-for="category in categories" :key="category" :emojis="emojiCharByCategory.get(category) ?? []" :hasChildSection="false" @chosen="chosen">{{ category }}</XSection>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-once class="group">
|
<div class="tabs">
|
||||||
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ti ti-asterisk ti-fw"></i></button>
|
||||||
<XSection
|
<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ti ti-mood-happy ti-fw"></i></button>
|
||||||
v-for="child in customEmojiFolderRoot.children"
|
<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ti ti-leaf ti-fw"></i></button>
|
||||||
:key="`custom:${child.value}`"
|
<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ti ti-hash ti-fw"></i></button>
|
||||||
:initialShown="false"
|
|
||||||
:emojis="computed(() => customEmojis.filter(e => child.value === '' ? (e.category === 'null' || !e.category) : e.category === child.value && !customEmojis.some(emoji => emoji.category !== null && emoji.category.includes(e.category+'/')) || e.category === child.category+'/'+child.category && !e.category).filter(filterAvailable).map(e => `:${e.name}:`))"
|
|
||||||
:hasChildSection="child.children.length !== 0"
|
|
||||||
:customEmojiTree="child.children"
|
|
||||||
@chosen="chosen"
|
|
||||||
>
|
|
||||||
{{ child.value || i18n.ts.other }}
|
|
||||||
</XSection>
|
|
||||||
</div>
|
|
||||||
<div v-once class="group">
|
|
||||||
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
|
||||||
<XSection v-for="category in categories" :key="category" :emojis="emojiCharByCategory.get(category) ?? []" :hasChildSection="false" @chosen="chosen">{{ category }}</XSection>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
|
||||||
<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ti ti-asterisk ti-fw"></i></button>
|
|
||||||
<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ti ti-mood-happy ti-fw"></i></button>
|
|
||||||
<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ti ti-leaf ti-fw"></i></button>
|
|
||||||
<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ti ti-hash ti-fw"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -127,18 +127,18 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
import { deepClone } from '@/scripts/clone.js';
|
import { deepClone } from '@/scripts/clone.js';
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
showPinned?: boolean;
|
showPinned?: boolean;
|
||||||
pinnedEmojis?: string[];
|
pinnedEmojis?: string[];
|
||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
asDrawer?: boolean;
|
asDrawer?: boolean;
|
||||||
asWindow?: boolean;
|
asWindow?: boolean;
|
||||||
asReactionPicker?: boolean; // 今は使われてないが将来的に使いそう
|
asReactionPicker?: boolean; // 今は使われてないが将来的に使いそう
|
||||||
}>(), {
|
}>(), {
|
||||||
showPinned: true,
|
showPinned: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'chosen', v: string): void;
|
(ev: 'chosen', v: string): void;
|
||||||
}>();
|
}>();
|
||||||
const profileMax = $i.policies.emojiPickerProfileLimit;
|
const profileMax = $i.policies.emojiPickerProfileLimit;
|
||||||
const searchEl = shallowRef<HTMLInputElement>();
|
const searchEl = shallowRef<HTMLInputElement>();
|
||||||
|
@ -349,7 +349,7 @@ watch(q, () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function filterAvailable(emoji: Misskey.entities.EmojiSimple): boolean {
|
function filterAvailable(emoji: Misskey.entities.EmojiSimple): boolean {
|
||||||
return ((emoji.roleIdsThatCanBeUsedThisEmojiAsReaction == null || emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0) || ($i && $i.roles.some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction?.includes(r.id)))) ?? false;
|
return (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction == null || emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0) || ($i && $i.roles.some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function focus() {
|
function focus() {
|
||||||
|
@ -461,262 +461,262 @@ defineExpose({
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.omfetrab {
|
.omfetrab {
|
||||||
$pad: 8px;
|
$pad: 8px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
&.s1 {
|
&.s1 {
|
||||||
--eachSize: 40px;
|
--eachSize: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.s2 {
|
&.s2 {
|
||||||
--eachSize: 45px;
|
--eachSize: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.s3 {
|
&.s3 {
|
||||||
--eachSize: 50px;
|
--eachSize: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.w1 {
|
&.w1 {
|
||||||
width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
|
width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
|
||||||
--columns: 1fr 1fr 1fr 1fr 1fr;
|
--columns: 1fr 1fr 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.w2 {
|
&.w2 {
|
||||||
width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
|
width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
|
||||||
--columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
--columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.w3 {
|
&.w3 {
|
||||||
width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
|
width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
|
||||||
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.w4 {
|
&.w4 {
|
||||||
width: calc((var(--eachSize) * 8) + (#{$pad} * 2));
|
width: calc((var(--eachSize) * 8) + (#{$pad} * 2));
|
||||||
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.w5 {
|
&.w5 {
|
||||||
width: calc((var(--eachSize) * 9) + (#{$pad} * 2));
|
width: calc((var(--eachSize) * 9) + (#{$pad} * 2));
|
||||||
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
--columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.h1 {
|
&.h1 {
|
||||||
height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
|
height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.h2 {
|
&.h2 {
|
||||||
height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
|
height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.h3 {
|
&.h3 {
|
||||||
height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
|
height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.h4 {
|
&.h4 {
|
||||||
height: calc((var(--eachSize) * 10) + (#{$pad} * 2));
|
height: calc((var(--eachSize) * 10) + (#{$pad} * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.asDrawer {
|
&.asDrawer {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
|
|
||||||
> .emojis {
|
> .emojis {
|
||||||
::v-deep(section) {
|
::v-deep(section) {
|
||||||
> header {
|
> header {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .body {
|
> .body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--columns);
|
grid-template-columns: var(--columns);
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
|
|
||||||
> .item {
|
> .item {
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.asWindow {
|
&.asWindow {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
|
|
||||||
> .emojis {
|
> .emojis {
|
||||||
::v-deep(section) {
|
::v-deep(section) {
|
||||||
> .body {
|
> .body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--columns);
|
grid-template-columns: var(--columns);
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
|
|
||||||
> .item {
|
> .item {
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .search {
|
> .search {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
|
|
||||||
&:not(:focus):not(.filled) {
|
&:not(:focus):not(.filled) {
|
||||||
margin-bottom: env(safe-area-inset-bottom, 0px);
|
margin-bottom: env(safe-area-inset-bottom, 0px);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.filled) {
|
&:not(.filled) {
|
||||||
order: 1;
|
order: 1;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
box-shadow: 0px -1px 0 0px var(--divider);
|
box-shadow: 0px -1px 0 0px var(--divider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .tabs {
|
> .tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
> .tab {
|
> .tab {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
border-top: solid 0.5px var(--divider);
|
border-top: solid 0.5px var(--divider);
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-top: solid 1px var(--accent);
|
border-top: solid 1px var(--accent);
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .emojis {
|
> .emojis {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .group {
|
> .group {
|
||||||
&:not(.index) {
|
&:not(.index) {
|
||||||
padding: 4px 0 8px 0;
|
padding: 4px 0 8px 0;
|
||||||
border-top: solid 0.5px var(--divider);
|
border-top: solid 0.5px var(--divider);
|
||||||
}
|
}
|
||||||
|
|
||||||
> header {
|
> header {
|
||||||
/*position: sticky;
|
/*position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;*/
|
left: 0;*/
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep(section) {
|
::v-deep(section) {
|
||||||
> header {
|
> header {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .body {
|
> .body {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: $pad;
|
padding: $pad;
|
||||||
|
|
||||||
> .item {
|
> .item {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: var(--eachSize);
|
width: var(--eachSize);
|
||||||
height: var(--eachSize);
|
height: var(--eachSize);
|
||||||
contain: strict;
|
contain: strict;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: solid 2px var(--focus);
|
outline: solid 2px var(--focus);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.05);
|
background: rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
|
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .emoji {
|
> .emoji {
|
||||||
height: 1.25em;
|
height: 1.25em;
|
||||||
vertical-align: -.25em;
|
vertical-align: -.25em;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.result {
|
&.result {
|
||||||
border-bottom: solid 0.5px var(--divider);
|
border-bottom: solid 0.5px var(--divider);
|
||||||
|
|
||||||
&:empty {
|
&:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sllfktkhgl{
|
.sllfktkhgl{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
box-shadow: 0 1.5px 0 var(--divider);
|
box-shadow: 0 1.5px 0 var(--divider);
|
||||||
height: 32px;
|
height: 32px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: translateY(1.5px);
|
transform: translateY(1.5px);
|
||||||
}
|
}
|
||||||
&.active {
|
&.active {
|
||||||
transform: translateY(5px);
|
transform: translateY(5px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue