mirror of
https://iceshrimp.dev/iceshrimp/iceshrimp
synced 2024-11-28 23:08:12 +09:00
add the focus trap thingies again
This commit is contained in:
parent
10b3079658
commit
14ec973c70
@ -1,157 +1,159 @@
|
||||
<template>
|
||||
<div
|
||||
class="omfetrab"
|
||||
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
||||
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
||||
>
|
||||
<input
|
||||
ref="search"
|
||||
v-model.trim="q"
|
||||
class="search"
|
||||
data-prevent-emoji-insert
|
||||
:class="{ filled: q != null && q != '' }"
|
||||
:placeholder="i18n.ts.search"
|
||||
type="search"
|
||||
@paste.stop="paste"
|
||||
@keyup.enter="done()"
|
||||
/>
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0" class="body">
|
||||
<button
|
||||
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">
|
||||
<FocusTrap v-bind:active="isActive">
|
||||
<div
|
||||
class="omfetrab"
|
||||
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
||||
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
||||
>
|
||||
<input
|
||||
ref="search"
|
||||
v-model.trim="q"
|
||||
class="search"
|
||||
data-prevent-emoji-insert
|
||||
:class="{ filled: q != null && q != '' }"
|
||||
:placeholder="i18n.ts.search"
|
||||
type="search"
|
||||
@paste.stop="paste"
|
||||
@keyup.enter="done()"
|
||||
/>
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in pinned"
|
||||
:key="emoji"
|
||||
v-for="emoji in searchResultCustom"
|
||||
:key="emoji.id"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji
|
||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||
<img
|
||||
class="emoji"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
: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>
|
||||
|
||||
<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 v-if="tab === 'index'" class="group index">
|
||||
<section v-if="showPinned">
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in pinned"
|
||||
:key="emoji"
|
||||
class="_button item"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji
|
||||
class="emoji"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
/>
|
||||
</button>
|
||||
</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 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 class="tabs">
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'index' }"
|
||||
@click="tab = 'index'"
|
||||
>
|
||||
</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
|
||||
<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>
|
||||
<div class="tabs">
|
||||
<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>
|
||||
</FocusTrap>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -171,6 +173,7 @@ import { deviceKind } from "@/scripts/device-kind";
|
||||
import { emojiCategories, instance } from "@/instance";
|
||||
import { i18n } from "@/i18n";
|
||||
import { defaultStore } from "@/store";
|
||||
import { FocusTrap } from 'focus-trap-vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -1,191 +1,185 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
ref="itemsEl"
|
||||
v-hotkey="keymap"
|
||||
class="rrevdjwt _popup _shadow"
|
||||
:class="{ center: align === 'center', asDrawer }"
|
||||
:style="{
|
||||
width: width && !asDrawer ? width + 'px' : '',
|
||||
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
||||
}"
|
||||
@contextmenu.self="(e) => e.preventDefault()"
|
||||
>
|
||||
<template v-for="(item, i) in items2">
|
||||
<div v-if="item === null" class="divider"></div>
|
||||
<span v-else-if="item.type === 'label'" class="label item">
|
||||
<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>
|
||||
<FocusTrap v-bind:active="isActive">
|
||||
<div tabindex="-1" v-focus>
|
||||
<div
|
||||
ref="itemsEl"
|
||||
class="rrevdjwt _popup _shadow"
|
||||
:class="{ center: align === 'center', asDrawer }"
|
||||
:style="{
|
||||
width: width && !asDrawer ? width + 'px' : '',
|
||||
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
||||
}"
|
||||
@contextmenu.self="(e) => e.preventDefault()"
|
||||
>
|
||||
<template v-for="(item, i) in items2">
|
||||
<div v-if="item === null" class="divider"></div>
|
||||
<span v-else-if="item.type === 'label'" class="label item">
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
</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"
|
||||
: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
|
||||
v-else-if="item.type === 'pending'"
|
||||
class="pending item"
|
||||
>
|
||||
<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>
|
||||
<button
|
||||
v-else-if="item.type === 'parent'"
|
||||
:tabindex="i"
|
||||
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"
|
||||
: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 v-if="childMenu" class="child">
|
||||
<XChild
|
||||
ref="child"
|
||||
:items="childMenu"
|
||||
:target-element="childTarget"
|
||||
:root-element="itemsEl"
|
||||
showing
|
||||
@actioned="childActioned"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="childMenu" class="child">
|
||||
<XChild
|
||||
ref="child"
|
||||
:items="childMenu"
|
||||
:target-element="childTarget"
|
||||
:root-element="itemsEl"
|
||||
showing
|
||||
@actioned="childActioned"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -229,12 +223,6 @@ let items2: InnerMenuItem[] = $ref([]);
|
||||
|
||||
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>();
|
||||
|
||||
watch(
|
||||
|
@ -35,6 +35,8 @@
|
||||
: 'none',
|
||||
'--transformOrigin': transformOrigin,
|
||||
}"
|
||||
tabindex="-1"
|
||||
v-focus
|
||||
>
|
||||
<div
|
||||
class="_modalBg data-cy-bg"
|
||||
@ -50,17 +52,19 @@
|
||||
@mousedown="onBgClick"
|
||||
@contextmenu.prevent.stop="() => {}"
|
||||
></div>
|
||||
<div
|
||||
ref="content"
|
||||
:class="[
|
||||
$style.content,
|
||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
||||
]"
|
||||
:style="{ zIndex }"
|
||||
@click.self="onBgClick"
|
||||
>
|
||||
<slot :max-height="maxHeight" :type="type"></slot>
|
||||
</div>
|
||||
<focus-trap v-model:active="isActive">
|
||||
<div
|
||||
ref="content"
|
||||
:class="[
|
||||
$style.content,
|
||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
||||
]"
|
||||
:style="{ zIndex }"
|
||||
@click.self="onBgClick"
|
||||
>
|
||||
<slot :max-height="maxHeight" :type="type"></slot>
|
||||
</div>
|
||||
</focus-trap>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
@ -3,54 +3,57 @@
|
||||
ref="modal"
|
||||
:prefer-type="'dialog'"
|
||||
@click="onBgClick"
|
||||
@keyup.esc="$emit('close')"
|
||||
@closed="$emit('closed')"
|
||||
>
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="ebkgoccj"
|
||||
:style="{
|
||||
width: `${width}px`,
|
||||
height: scroll
|
||||
? height
|
||||
? `${height}px`
|
||||
: null
|
||||
: height
|
||||
? `min(${height}px, 100%)`
|
||||
: '100%',
|
||||
}"
|
||||
@keydown="onKeydown"
|
||||
>
|
||||
<div ref="headerEl" class="header">
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<span class="title">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<button
|
||||
v-if="!withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
:disabled="okButtonDisabled"
|
||||
@click="$emit('ok')"
|
||||
>
|
||||
<i class="ph-check ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<focus-trap v-model:active="isActive">
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="ebkgoccj"
|
||||
:style="{
|
||||
width: `${width}px`,
|
||||
height: scroll
|
||||
? height
|
||||
? `${height}px`
|
||||
: null
|
||||
: height
|
||||
? `min(${height}px, 100%)`
|
||||
: '100%',
|
||||
}"
|
||||
@keydown="onKeydown"
|
||||
>
|
||||
<div ref="headerEl" class="header">
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<span class="title">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<button
|
||||
v-if="!withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
:disabled="okButtonDisabled"
|
||||
@click="$emit('ok')"
|
||||
>
|
||||
<i class="ph-check ph-bold ph-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="body">
|
||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</focus-trap>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user