add the focus trap thingies again
This commit is contained in:
parent
6498a90dc1
commit
3be2147397
@ -1,157 +1,159 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<FocusTrap v-bind:active="isActive">
|
||||||
class="omfetrab"
|
<div
|
||||||
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
class="omfetrab"
|
||||||
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
||||||
>
|
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
||||||
<input
|
>
|
||||||
ref="search"
|
<input
|
||||||
v-model.trim="q"
|
ref="search"
|
||||||
class="search"
|
v-model.trim="q"
|
||||||
data-prevent-emoji-insert
|
class="search"
|
||||||
:class="{ filled: q != null && q != '' }"
|
data-prevent-emoji-insert
|
||||||
:placeholder="i18n.ts.search"
|
:class="{ filled: q != null && q != '' }"
|
||||||
type="search"
|
:placeholder="i18n.ts.search"
|
||||||
@paste.stop="paste"
|
type="search"
|
||||||
@keyup.enter="done()"
|
@paste.stop="paste"
|
||||||
/>
|
@keyup.enter="done()"
|
||||||
<div ref="emojis" class="emojis">
|
/>
|
||||||
<section class="result">
|
<div ref="emojis" class="emojis">
|
||||||
<div v-if="searchResultCustom.length > 0" class="body">
|
<section class="result">
|
||||||
<button
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
v-for="emoji in searchResultCustom"
|
|
||||||
:key="emoji.id"
|
|
||||||
class="_button item"
|
|
||||||
:title="emoji.name"
|
|
||||||
tabindex="0"
|
|
||||||
@click="chosen(emoji, $event)"
|
|
||||||
>
|
|
||||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
|
||||||
<img
|
|
||||||
class="emoji"
|
|
||||||
:src="
|
|
||||||
disableShowingAnimatedImages
|
|
||||||
? getStaticImageUrl(emoji.url)
|
|
||||||
: emoji.url
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</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">
|
|
||||||
<div class="body">
|
|
||||||
<button
|
<button
|
||||||
v-for="emoji in pinned"
|
v-for="emoji in searchResultCustom"
|
||||||
:key="emoji"
|
:key="emoji.id"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
|
:title="emoji.name"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji
|
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||||
|
<img
|
||||||
class="emoji"
|
class="emoji"
|
||||||
:emoji="emoji"
|
:src="
|
||||||
:normal="true"
|
disableShowingAnimatedImages
|
||||||
|
? getStaticImageUrl(emoji.url)
|
||||||
|
: emoji.url
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
</section>
|
||||||
|
|
||||||
<section>
|
<div v-if="tab === 'index'" class="group index">
|
||||||
<header class="_acrylic">
|
<section v-if="showPinned">
|
||||||
<i class="ph-alarm ph-bold ph-fw ph-lg"></i>
|
<div class="body">
|
||||||
{{ i18n.ts.recentUsed }}
|
<button
|
||||||
</header>
|
v-for="emoji in pinned"
|
||||||
<div class="body">
|
:key="emoji"
|
||||||
<button
|
class="_button item"
|
||||||
v-for="emoji in recentlyUsedEmojis"
|
tabindex="0"
|
||||||
:key="emoji"
|
@click="chosen(emoji, $event)"
|
||||||
class="_button item"
|
>
|
||||||
@click="chosen(emoji, $event)"
|
<MkEmoji
|
||||||
>
|
class="emoji"
|
||||||
<MkEmoji
|
:emoji="emoji"
|
||||||
class="emoji"
|
:normal="true"
|
||||||
:emoji="emoji"
|
/>
|
||||||
:normal="true"
|
</button>
|
||||||
/>
|
</div>
|
||||||
</button>
|
</section>
|
||||||
</div>
|
|
||||||
</section>
|
<section>
|
||||||
|
<header class="_acrylic">
|
||||||
|
<i class="ph-alarm ph-bold ph-fw ph-lg"></i>
|
||||||
|
{{ i18n.ts.recentUsed }}
|
||||||
|
</header>
|
||||||
|
<div class="body">
|
||||||
|
<button
|
||||||
|
v-for="emoji in recentlyUsedEmojis"
|
||||||
|
:key="emoji"
|
||||||
|
class="_button item"
|
||||||
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkEmoji
|
||||||
|
class="emoji"
|
||||||
|
:emoji="emoji"
|
||||||
|
:normal="true"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div v-once class="group">
|
||||||
|
<header>{{ i18n.ts.customEmojis }}</header>
|
||||||
|
<XSection
|
||||||
|
v-for="category in customEmojiCategories"
|
||||||
|
:key="'custom:' + category"
|
||||||
|
:initial-shown="false"
|
||||||
|
:emojis="
|
||||||
|
customEmojis
|
||||||
|
.filter((e) => e.category === category)
|
||||||
|
.map((e) => ':' + e.name + ':')
|
||||||
|
"
|
||||||
|
@chosen="chosen"
|
||||||
|
>{{ category || i18n.ts.other }}</XSection
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div v-once class="group">
|
||||||
|
<header>{{ i18n.ts.emoji }}</header>
|
||||||
|
<XSection
|
||||||
|
v-for="category in categories"
|
||||||
|
:key="category"
|
||||||
|
:emojis="
|
||||||
|
emojilist
|
||||||
|
.filter((e) => e.category === category)
|
||||||
|
.map((e) => e.char)
|
||||||
|
"
|
||||||
|
@chosen="chosen"
|
||||||
|
>{{ category }}</XSection
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-once class="group">
|
<div class="tabs">
|
||||||
<header>{{ i18n.ts.customEmojis }}</header>
|
<button
|
||||||
<XSection
|
class="_button tab"
|
||||||
v-for="category in customEmojiCategories"
|
:class="{ active: tab === 'index' }"
|
||||||
:key="'custom:' + category"
|
@click="tab = 'index'"
|
||||||
:initial-shown="false"
|
|
||||||
:emojis="
|
|
||||||
customEmojis
|
|
||||||
.filter((e) => e.category === category)
|
|
||||||
.map((e) => ':' + e.name + ':')
|
|
||||||
"
|
|
||||||
@chosen="chosen"
|
|
||||||
>{{ category || i18n.ts.other }}</XSection
|
|
||||||
>
|
>
|
||||||
</div>
|
<i class="ph-asterisk ph-bold ph-lg ph-fw ph-lg"></i>
|
||||||
<div v-once class="group">
|
</button>
|
||||||
<header>{{ i18n.ts.emoji }}</header>
|
<button
|
||||||
<XSection
|
class="_button tab"
|
||||||
v-for="category in categories"
|
:class="{ active: tab === 'custom' }"
|
||||||
:key="category"
|
@click="tab = 'custom'"
|
||||||
:emojis="
|
|
||||||
emojilist
|
|
||||||
.filter((e) => e.category === category)
|
|
||||||
.map((e) => e.char)
|
|
||||||
"
|
|
||||||
@chosen="chosen"
|
|
||||||
>{{ category }}</XSection
|
|
||||||
>
|
>
|
||||||
|
<i class="ph-smiley ph-bold ph-lg ph-fw ph-lg"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="_button tab"
|
||||||
|
:class="{ active: tab === 'unicode' }"
|
||||||
|
@click="tab = 'unicode'"
|
||||||
|
>
|
||||||
|
<i class="ph-leaf ph-bold ph-lg ph-fw ph-lg"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="_button tab"
|
||||||
|
:class="{ active: tab === 'tags' }"
|
||||||
|
@click="tab = 'tags'"
|
||||||
|
>
|
||||||
|
<i class="ph-hash ph-bold ph-lg ph-fw ph-lg"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
</FocusTrap>
|
||||||
<button
|
|
||||||
class="_button tab"
|
|
||||||
:class="{ active: tab === 'index' }"
|
|
||||||
@click="tab = 'index'"
|
|
||||||
>
|
|
||||||
<i class="ph-asterisk ph-bold ph-lg ph-fw ph-lg"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="_button tab"
|
|
||||||
:class="{ active: tab === 'custom' }"
|
|
||||||
@click="tab = 'custom'"
|
|
||||||
>
|
|
||||||
<i class="ph-smiley ph-bold ph-lg ph-fw ph-lg"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="_button tab"
|
|
||||||
:class="{ active: tab === 'unicode' }"
|
|
||||||
@click="tab = 'unicode'"
|
|
||||||
>
|
|
||||||
<i class="ph-leaf ph-bold ph-lg ph-fw ph-lg"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="_button tab"
|
|
||||||
:class="{ active: tab === 'tags' }"
|
|
||||||
@click="tab = 'tags'"
|
|
||||||
>
|
|
||||||
<i class="ph-hash ph-bold ph-lg ph-fw ph-lg"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -171,6 +173,7 @@ import { deviceKind } from "@/scripts/device-kind";
|
|||||||
import { emojiCategories, instance } from "@/instance";
|
import { emojiCategories, instance } from "@/instance";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
|
import { FocusTrap } from 'focus-trap-vue';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -1,191 +1,185 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FocusTrap v-bind:active="isActive">
|
||||||
<div
|
<div tabindex="-1" v-focus>
|
||||||
ref="itemsEl"
|
<div
|
||||||
v-hotkey="keymap"
|
ref="itemsEl"
|
||||||
class="rrevdjwt _popup _shadow"
|
class="rrevdjwt _popup _shadow"
|
||||||
:class="{ center: align === 'center', asDrawer }"
|
:class="{ center: align === 'center', asDrawer }"
|
||||||
:style="{
|
:style="{
|
||||||
width: width && !asDrawer ? width + 'px' : '',
|
width: width && !asDrawer ? width + 'px' : '',
|
||||||
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
||||||
}"
|
}"
|
||||||
@contextmenu.self="(e) => e.preventDefault()"
|
@contextmenu.self="(e) => e.preventDefault()"
|
||||||
>
|
>
|
||||||
<template v-for="(item, i) in items2">
|
<template v-for="(item, i) in items2">
|
||||||
<div v-if="item === null" class="divider"></div>
|
<div v-if="item === null" class="divider"></div>
|
||||||
<span v-else-if="item.type === 'label'" class="label item">
|
<span v-else-if="item.type === 'label'" class="label item">
|
||||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-else-if="item.type === 'pending'"
|
|
||||||
:tabindex="i"
|
|
||||||
class="pending item"
|
|
||||||
>
|
|
||||||
<span><MkEllipsis /></span>
|
|
||||||
</span>
|
|
||||||
<MkA
|
|
||||||
v-else-if="item.type === 'link'"
|
|
||||||
:to="item.to"
|
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
|
||||||
@click.passive="close(true)"
|
|
||||||
@mouseenter.passive="onItemMouseEnter(item)"
|
|
||||||
@mouseleave.passive="onItemMouseLeave(item)"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
v-if="item.icon"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="item.icon"
|
|
||||||
></i>
|
|
||||||
<span v-else-if="item.icons">
|
|
||||||
<i
|
|
||||||
v-for="icon in item.icons"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="icon"
|
|
||||||
></i>
|
|
||||||
</span>
|
</span>
|
||||||
<MkAvatar
|
<span
|
||||||
v-if="item.avatar"
|
v-else-if="item.type === 'pending'"
|
||||||
:user="item.avatar"
|
class="pending item"
|
||||||
class="avatar"
|
|
||||||
/>
|
|
||||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
|
||||||
<span v-if="item.indicate" class="indicator"
|
|
||||||
><i class="ph-circle ph-fill"></i
|
|
||||||
></span>
|
|
||||||
</MkA>
|
|
||||||
<a
|
|
||||||
v-else-if="item.type === 'a'"
|
|
||||||
:href="item.href"
|
|
||||||
:target="item.target"
|
|
||||||
:download="item.download"
|
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
|
||||||
@click="close(true)"
|
|
||||||
@mouseenter.passive="onItemMouseEnter(item)"
|
|
||||||
@mouseleave.passive="onItemMouseLeave(item)"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
v-if="item.icon"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="item.icon"
|
|
||||||
></i>
|
|
||||||
<span v-else-if="item.icons">
|
|
||||||
<i
|
|
||||||
v-for="icon in item.icons"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="icon"
|
|
||||||
></i>
|
|
||||||
</span>
|
|
||||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
|
||||||
<span v-if="item.indicate" class="indicator"
|
|
||||||
><i class="ph-circle ph-fill"></i
|
|
||||||
></span>
|
|
||||||
</a>
|
|
||||||
<button
|
|
||||||
v-else-if="item.type === 'user' && !items.hidden"
|
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
|
||||||
:class="{ active: item.active }"
|
|
||||||
:disabled="item.active"
|
|
||||||
@click="clicked(item.action, $event)"
|
|
||||||
@mouseenter.passive="onItemMouseEnter(item)"
|
|
||||||
@mouseleave.passive="onItemMouseLeave(item)"
|
|
||||||
>
|
|
||||||
<MkAvatar :user="item.user" class="avatar" /><MkUserName
|
|
||||||
:user="item.user"
|
|
||||||
/>
|
|
||||||
<span v-if="item.indicate" class="indicator"
|
|
||||||
><i class="ph-circle ph-fill"></i
|
|
||||||
></span>
|
|
||||||
</button>
|
|
||||||
<span
|
|
||||||
v-else-if="item.type === 'switch'"
|
|
||||||
:tabindex="i"
|
|
||||||
class="item"
|
|
||||||
@mouseenter.passive="onItemMouseEnter(item)"
|
|
||||||
@mouseleave.passive="onItemMouseLeave(item)"
|
|
||||||
>
|
|
||||||
<FormSwitch
|
|
||||||
v-model="item.ref"
|
|
||||||
:disabled="item.disabled"
|
|
||||||
class="form-switch"
|
|
||||||
:style="item.textStyle || ''"
|
|
||||||
>{{ item.text }}</FormSwitch
|
|
||||||
>
|
>
|
||||||
|
<span><MkEllipsis /></span>
|
||||||
|
</span>
|
||||||
|
<MkA
|
||||||
|
v-else-if="item.type === 'link'"
|
||||||
|
:to="item.to"
|
||||||
|
class="_button item"
|
||||||
|
@click.passive="close(true)"
|
||||||
|
@mouseenter.passive="onItemMouseEnter(item)"
|
||||||
|
@mouseleave.passive="onItemMouseLeave(item)"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="item.icon"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="item.icon"
|
||||||
|
></i>
|
||||||
|
<span v-else-if="item.icons">
|
||||||
|
<i
|
||||||
|
v-for="icon in item.icons"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="icon"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<MkAvatar
|
||||||
|
v-if="item.avatar"
|
||||||
|
:user="item.avatar"
|
||||||
|
class="avatar"
|
||||||
|
/>
|
||||||
|
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||||
|
<span v-if="item.indicate" class="indicator"
|
||||||
|
><i class="ph-circle ph-fill"></i
|
||||||
|
></span>
|
||||||
|
</MkA>
|
||||||
|
<a
|
||||||
|
v-else-if="item.type === 'a'"
|
||||||
|
:href="item.href"
|
||||||
|
:target="item.target"
|
||||||
|
:download="item.download"
|
||||||
|
class="_button item"
|
||||||
|
@click="close(true)"
|
||||||
|
@mouseenter.passive="onItemMouseEnter(item)"
|
||||||
|
@mouseleave.passive="onItemMouseLeave(item)"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="item.icon"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="item.icon"
|
||||||
|
></i>
|
||||||
|
<span v-else-if="item.icons">
|
||||||
|
<i
|
||||||
|
v-for="icon in item.icons"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="icon"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||||
|
<span v-if="item.indicate" class="indicator"
|
||||||
|
><i class="ph-circle ph-fill"></i
|
||||||
|
></span>
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
v-else-if="item.type === 'user' && !items.hidden"
|
||||||
|
class="_button item"
|
||||||
|
:class="{ active: item.active }"
|
||||||
|
:disabled="item.active"
|
||||||
|
@click="clicked(item.action, $event)"
|
||||||
|
@mouseenter.passive="onItemMouseEnter(item)"
|
||||||
|
@mouseleave.passive="onItemMouseLeave(item)"
|
||||||
|
>
|
||||||
|
<MkAvatar :user="item.user" class="avatar" /><MkUserName
|
||||||
|
:user="item.user"
|
||||||
|
/>
|
||||||
|
<span v-if="item.indicate" class="indicator"
|
||||||
|
><i class="ph-circle ph-fill"></i
|
||||||
|
></span>
|
||||||
|
</button>
|
||||||
|
<span
|
||||||
|
v-else-if="item.type === 'switch'"
|
||||||
|
class="item"
|
||||||
|
@mouseenter.passive="onItemMouseEnter(item)"
|
||||||
|
@mouseleave.passive="onItemMouseLeave(item)"
|
||||||
|
>
|
||||||
|
<FormSwitch
|
||||||
|
v-model="item.ref"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
class="form-switch"
|
||||||
|
:style="item.textStyle || ''"
|
||||||
|
>{{ item.text }}</FormSwitch
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
v-else-if="item.type === 'parent'"
|
||||||
|
class="_button item parent"
|
||||||
|
:class="{ childShowing: childShowingItem === item }"
|
||||||
|
@mouseenter="showChildren(item, $event)"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="item.icon"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="item.icon"
|
||||||
|
></i>
|
||||||
|
<span v-else-if="item.icons">
|
||||||
|
<i
|
||||||
|
v-for="icon in item.icons"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="icon"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||||
|
<span class="caret"
|
||||||
|
><i class="ph-caret-right ph-bold ph-lg ph-fw ph-lg"></i
|
||||||
|
></span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="!item.hidden"
|
||||||
|
class="_button item"
|
||||||
|
:class="{ danger: item.danger, active: item.active }"
|
||||||
|
:disabled="item.active"
|
||||||
|
@click="clicked(item.action, $event)"
|
||||||
|
@mouseenter.passive="onItemMouseEnter(item)"
|
||||||
|
@mouseleave.passive="onItemMouseLeave(item)"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="item.icon"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="item.icon"
|
||||||
|
></i>
|
||||||
|
<span v-else-if="item.icons">
|
||||||
|
<i
|
||||||
|
v-for="icon in item.icons"
|
||||||
|
class="ph-fw ph-lg"
|
||||||
|
:class="icon"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<MkAvatar
|
||||||
|
v-if="item.avatar"
|
||||||
|
:user="item.avatar"
|
||||||
|
class="avatar"
|
||||||
|
/>
|
||||||
|
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||||
|
<span v-if="item.indicate" class="indicator"
|
||||||
|
><i class="ph-circle ph-fill"></i
|
||||||
|
></span>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<span v-if="items2.length === 0" class="none item">
|
||||||
|
<span>{{ i18n.ts.none }}</span>
|
||||||
</span>
|
</span>
|
||||||
<button
|
</div>
|
||||||
v-else-if="item.type === 'parent'"
|
<div v-if="childMenu" class="child">
|
||||||
:tabindex="i"
|
<XChild
|
||||||
class="_button item parent"
|
ref="child"
|
||||||
:class="{ childShowing: childShowingItem === item }"
|
:items="childMenu"
|
||||||
@mouseenter="showChildren(item, $event)"
|
:target-element="childTarget"
|
||||||
>
|
:root-element="itemsEl"
|
||||||
<i
|
showing
|
||||||
v-if="item.icon"
|
@actioned="childActioned"
|
||||||
class="ph-fw ph-lg"
|
/>
|
||||||
:class="item.icon"
|
</div>
|
||||||
></i>
|
|
||||||
<span v-else-if="item.icons">
|
|
||||||
<i
|
|
||||||
v-for="icon in item.icons"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="icon"
|
|
||||||
></i>
|
|
||||||
</span>
|
|
||||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
|
||||||
<span class="caret"
|
|
||||||
><i class="ph-caret-right ph-bold ph-lg ph-fw ph-lg"></i
|
|
||||||
></span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-else-if="!item.hidden"
|
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
|
||||||
:class="{ danger: item.danger, active: item.active }"
|
|
||||||
:disabled="item.active"
|
|
||||||
@click="clicked(item.action, $event)"
|
|
||||||
@mouseenter.passive="onItemMouseEnter(item)"
|
|
||||||
@mouseleave.passive="onItemMouseLeave(item)"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
v-if="item.icon"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="item.icon"
|
|
||||||
></i>
|
|
||||||
<span v-else-if="item.icons">
|
|
||||||
<i
|
|
||||||
v-for="icon in item.icons"
|
|
||||||
class="ph-fw ph-lg"
|
|
||||||
:class="icon"
|
|
||||||
></i>
|
|
||||||
</span>
|
|
||||||
<MkAvatar
|
|
||||||
v-if="item.avatar"
|
|
||||||
:user="item.avatar"
|
|
||||||
class="avatar"
|
|
||||||
/>
|
|
||||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
|
||||||
<span v-if="item.indicate" class="indicator"
|
|
||||||
><i class="ph-circle ph-fill"></i
|
|
||||||
></span>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
<span v-if="items2.length === 0" class="none item">
|
|
||||||
<span>{{ i18n.ts.none }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="childMenu" class="child">
|
</FocusTrap>
|
||||||
<XChild
|
|
||||||
ref="child"
|
|
||||||
:items="childMenu"
|
|
||||||
:target-element="childTarget"
|
|
||||||
:root-element="itemsEl"
|
|
||||||
showing
|
|
||||||
@actioned="childActioned"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -229,12 +223,6 @@ let items2: InnerMenuItem[] = $ref([]);
|
|||||||
|
|
||||||
let child = $ref<InstanceType<typeof XChild>>();
|
let child = $ref<InstanceType<typeof XChild>>();
|
||||||
|
|
||||||
let keymap = computed(() => ({
|
|
||||||
"up|k|shift+tab": focusUp,
|
|
||||||
"down|j|tab": focusDown,
|
|
||||||
esc: close,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let childShowingItem = $ref<MenuItem | null>();
|
let childShowingItem = $ref<MenuItem | null>();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
: 'none',
|
: 'none',
|
||||||
'--transformOrigin': transformOrigin,
|
'--transformOrigin': transformOrigin,
|
||||||
}"
|
}"
|
||||||
|
tabindex="-1"
|
||||||
|
v-focus
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="_modalBg data-cy-bg"
|
class="_modalBg data-cy-bg"
|
||||||
@ -50,17 +52,19 @@
|
|||||||
@mousedown="onBgClick"
|
@mousedown="onBgClick"
|
||||||
@contextmenu.prevent.stop="() => {}"
|
@contextmenu.prevent.stop="() => {}"
|
||||||
></div>
|
></div>
|
||||||
<div
|
<focus-trap v-model:active="isActive">
|
||||||
ref="content"
|
<div
|
||||||
:class="[
|
ref="content"
|
||||||
$style.content,
|
:class="[
|
||||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
$style.content,
|
||||||
]"
|
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
||||||
:style="{ zIndex }"
|
]"
|
||||||
@click.self="onBgClick"
|
:style="{ zIndex }"
|
||||||
>
|
@click.self="onBgClick"
|
||||||
<slot :max-height="maxHeight" :type="type"></slot>
|
>
|
||||||
</div>
|
<slot :max-height="maxHeight" :type="type"></slot>
|
||||||
|
</div>
|
||||||
|
</focus-trap>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</template>
|
</template>
|
||||||
|
@ -3,54 +3,57 @@
|
|||||||
ref="modal"
|
ref="modal"
|
||||||
:prefer-type="'dialog'"
|
:prefer-type="'dialog'"
|
||||||
@click="onBgClick"
|
@click="onBgClick"
|
||||||
|
@keyup.esc="$emit('close')"
|
||||||
@closed="$emit('closed')"
|
@closed="$emit('closed')"
|
||||||
>
|
>
|
||||||
<div
|
<focus-trap v-model:active="isActive">
|
||||||
ref="rootEl"
|
<div
|
||||||
class="ebkgoccj"
|
ref="rootEl"
|
||||||
:style="{
|
class="ebkgoccj"
|
||||||
width: `${width}px`,
|
:style="{
|
||||||
height: scroll
|
width: `${width}px`,
|
||||||
? height
|
height: scroll
|
||||||
? `${height}px`
|
? height
|
||||||
: null
|
? `${height}px`
|
||||||
: height
|
: null
|
||||||
? `min(${height}px, 100%)`
|
: height
|
||||||
: '100%',
|
? `min(${height}px, 100%)`
|
||||||
}"
|
: '100%',
|
||||||
@keydown="onKeydown"
|
}"
|
||||||
>
|
@keydown="onKeydown"
|
||||||
<div ref="headerEl" class="header">
|
>
|
||||||
<button
|
<div ref="headerEl" class="header">
|
||||||
v-if="withOkButton"
|
<button
|
||||||
class="_button"
|
v-if="withOkButton"
|
||||||
@click="$emit('close')"
|
class="_button"
|
||||||
>
|
@click="$emit('close')"
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
>
|
||||||
</button>
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
<span class="title">
|
</button>
|
||||||
<slot name="header"></slot>
|
<span class="title">
|
||||||
</span>
|
<slot name="header"></slot>
|
||||||
<button
|
</span>
|
||||||
v-if="!withOkButton"
|
<button
|
||||||
class="_button"
|
v-if="!withOkButton"
|
||||||
@click="$emit('close')"
|
class="_button"
|
||||||
>
|
@click="$emit('close')"
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
>
|
||||||
</button>
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
<button
|
</button>
|
||||||
v-if="withOkButton"
|
<button
|
||||||
class="_button"
|
v-if="withOkButton"
|
||||||
:disabled="okButtonDisabled"
|
class="_button"
|
||||||
@click="$emit('ok')"
|
:disabled="okButtonDisabled"
|
||||||
>
|
@click="$emit('ok')"
|
||||||
<i class="ph-check ph-bold ph-lg"></i>
|
>
|
||||||
</button>
|
<i class="ph-check ph-bold ph-lg"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
</focus-trap>
|
||||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MkModal>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user