mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-22 18:07:31 -07:00
Merge pull request 'keyboard-accessability' (#9974) from Freeplay/calckey:keyboard-accessability into develop
Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9974
This commit is contained in:
commit
ae7311a6a8
41 changed files with 640 additions and 506 deletions
|
@ -40,6 +40,8 @@
|
||||||
"@bull-board/ui": "^4.10.2",
|
"@bull-board/ui": "^4.10.2",
|
||||||
"@napi-rs/cli": "^2.15.0",
|
"@napi-rs/cli": "^2.15.0",
|
||||||
"@tensorflow/tfjs": "^3.21.0",
|
"@tensorflow/tfjs": "^3.21.0",
|
||||||
|
"focus-trap": "^7.2.0",
|
||||||
|
"focus-trap-vue": "^4.0.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"seedrandom": "^3.0.5"
|
"seedrandom": "^3.0.5"
|
||||||
},
|
},
|
||||||
|
|
|
@ -195,8 +195,7 @@ function onMousedown(evt: MouseEvent): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: solid 2px var(--focus);
|
outline: auto;
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.inline {
|
&.inline {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
|
ref="el"
|
||||||
class="_button"
|
class="_button"
|
||||||
:class="{ showLess: modelValue, fade: !modelValue }"
|
:class="{ showLess: modelValue, fade: !modelValue }"
|
||||||
@click.stop="toggle"
|
@click.stop="toggle"
|
||||||
|
@ -12,7 +13,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { length } from "stringz";
|
import { length } from "stringz";
|
||||||
import * as misskey from "calckey-js";
|
import * as misskey from "calckey-js";
|
||||||
import { concat } from "@/scripts/array";
|
import { concat } from "@/scripts/array";
|
||||||
|
@ -27,6 +28,8 @@ const emit = defineEmits<{
|
||||||
(ev: "update:modelValue", v: boolean): void;
|
(ev: "update:modelValue", v: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const el = ref<HTMLElement>();
|
||||||
|
|
||||||
const label = computed(() => {
|
const label = computed(() => {
|
||||||
return concat([
|
return concat([
|
||||||
props.note.text
|
props.note.text
|
||||||
|
@ -43,6 +46,14 @@ const label = computed(() => {
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
emit("update:modelValue", !props.modelValue);
|
emit("update:modelValue", !props.modelValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function focus() {
|
||||||
|
el.value.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
focus
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -62,9 +73,46 @@ const toggle = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover > span {
|
&:hover > span, &:focus > span {
|
||||||
background: var(--cwFg) !important;
|
background: var(--cwFg) !important;
|
||||||
color: var(--cwBg) !important;
|
color: var(--cwBg) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.fade {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--panel);
|
||||||
|
padding: 0.4em 1em;
|
||||||
|
font-size: 0.8em;
|
||||||
|
border-radius: 999px;
|
||||||
|
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
|
||||||
|
}
|
||||||
|
&:hover, &:focus {
|
||||||
|
> span {
|
||||||
|
background: var(--panelHighlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.showLess {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 1em;
|
||||||
|
position: sticky;
|
||||||
|
bottom: var(--stickyBottom);
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--panel);
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
border-radius: 999px;
|
||||||
|
box-shadow: 0 0 7px 7px var(--bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="thumbnail" class="zdjebgpv">
|
<button ref="thumbnail" class="zdjebgpv">
|
||||||
<ImgWithBlurhash
|
<ImgWithBlurhash
|
||||||
v-if="isThumbnailAvailable"
|
v-if="isThumbnailAvailable"
|
||||||
:hash="file.blurhash"
|
:hash="file.blurhash"
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
v-if="isThumbnailAvailable && is === 'video'"
|
v-if="isThumbnailAvailable && is === 'video'"
|
||||||
class="ph-file-video ph-bold ph-lg icon-sub"
|
class="ph-file-video ph-bold ph-lg icon-sub"
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -88,6 +88,9 @@ const isThumbnailAvailable = computed(() => {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
> .icon-sub {
|
> .icon-sub {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -1,157 +1,160 @@
|
||||||
<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
|
tabindex="-1"
|
||||||
ref="search"
|
>
|
||||||
v-model.trim="q"
|
<input
|
||||||
class="search"
|
ref="search"
|
||||||
data-prevent-emoji-insert
|
v-model.trim="q"
|
||||||
:class="{ filled: q != null && q != '' }"
|
class="search"
|
||||||
:placeholder="i18n.ts.search"
|
data-prevent-emoji-insert
|
||||||
type="search"
|
:class="{ filled: q != null && q != '' }"
|
||||||
@paste.stop="paste"
|
:placeholder="i18n.ts.search"
|
||||||
@keyup.enter="done()"
|
type="search"
|
||||||
/>
|
@paste.stop="paste"
|
||||||
<div ref="emojis" class="emojis">
|
@keyup.enter="done()"
|
||||||
<section class="result">
|
/>
|
||||||
<div v-if="searchResultCustom.length > 0" class="body">
|
<div ref="emojis" class="emojis">
|
||||||
<button
|
<section class="result">
|
||||||
v-for="emoji in searchResultCustom"
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
: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 +174,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<{
|
||||||
|
|
|
@ -139,7 +139,7 @@ function close() {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
&:hover {
|
&:hover, &:focus-visible {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
background: var(--accentedBg);
|
background: var(--accentedBg);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
|
@ -138,6 +138,10 @@ watch(
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
box-sizing: border-box;
|
||||||
|
&:focus-visible {
|
||||||
|
border: 2px solid var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
> .gif {
|
> .gif {
|
||||||
background-color: var(--fg);
|
background-color: var(--fg);
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="el" class="sfhdhdhr">
|
<div ref="el" class="sfhdhdhr" tabindex="-1">
|
||||||
<MkMenu
|
<MkMenu
|
||||||
ref="menu"
|
ref="menu"
|
||||||
:items="items"
|
:items="items"
|
||||||
:align="align"
|
:align="align"
|
||||||
:width="width"
|
:width="width"
|
||||||
:as-drawer="false"
|
:as-drawer="false"
|
||||||
@close="onChildClosed"
|
@close="onChildClosed"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -23,7 +23,6 @@ import {
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import MkMenu from "./MkMenu.vue";
|
import MkMenu from "./MkMenu.vue";
|
||||||
import { MenuItem } from "@/types/menu";
|
import { MenuItem } from "@/types/menu";
|
||||||
import * as os from "@/os";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
items: MenuItem[];
|
items: MenuItem[];
|
||||||
|
|
|
@ -1,191 +1,188 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<FocusTrap :active="false" ref="focusTrap">
|
||||||
<div
|
<div tabindex="-1">
|
||||||
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"
|
||||||
|
disableLink
|
||||||
|
/>
|
||||||
|
<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" disableLink /><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)"
|
||||||
|
@click="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"
|
||||||
|
disableLink
|
||||||
|
/>
|
||||||
|
<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>
|
||||||
|
@ -206,8 +203,10 @@ import FormSwitch from "@/components/form/switch.vue";
|
||||||
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from "@/types/menu";
|
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from "@/types/menu";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
import { FocusTrap } from 'focus-trap-vue';
|
||||||
|
|
||||||
const XChild = defineAsyncComponent(() => import("./MkMenu.child.vue"));
|
const XChild = defineAsyncComponent(() => import("./MkMenu.child.vue"));
|
||||||
|
const focusTrap = ref();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
items: MenuItem[];
|
items: MenuItem[];
|
||||||
|
@ -228,12 +227,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(
|
||||||
|
@ -324,6 +317,8 @@ function focusDown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
focusTrap.value.activate();
|
||||||
|
|
||||||
if (props.viaKeyboard) {
|
if (props.viaKeyboard) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
focusNext(itemsEl.children[0], true, false);
|
focusNext(itemsEl.children[0], true, false);
|
||||||
|
@ -364,8 +359,7 @@ onBeforeUnmount(() => {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
overflow: hidden;
|
outline: none;
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: "";
|
||||||
|
@ -389,7 +383,7 @@ onBeforeUnmount(() => {
|
||||||
transform: translateY(0em);
|
transform: translateY(0em);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:disabled):hover {
|
&:not(:disabled):hover, &:focus-visible {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
@ -397,6 +391,9 @@ onBeforeUnmount(() => {
|
||||||
background: var(--accentedBg);
|
background: var(--accentedBg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:focus-visible:before {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
&.danger {
|
&.danger {
|
||||||
color: #eb6f92;
|
color: #eb6f92;
|
||||||
|
|
|
@ -14,54 +14,59 @@
|
||||||
:duration="transitionDuration"
|
:duration="transitionDuration"
|
||||||
appear
|
appear
|
||||||
@after-leave="emit('closed')"
|
@after-leave="emit('closed')"
|
||||||
|
@keyup.esc="emit('click')"
|
||||||
@enter="emit('opening')"
|
@enter="emit('opening')"
|
||||||
@after-enter="onOpened"
|
@after-enter="onOpened"
|
||||||
>
|
>
|
||||||
<div
|
<FocusTrap v-model:active="isActive">
|
||||||
v-show="manualShowing != null ? manualShowing : showing"
|
|
||||||
v-hotkey.global="keymap"
|
|
||||||
:class="[
|
|
||||||
$style.root,
|
|
||||||
{
|
|
||||||
[$style.drawer]: type === 'drawer',
|
|
||||||
[$style.dialog]: type === 'dialog' || type === 'dialog:top',
|
|
||||||
[$style.popup]: type === 'popup',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
:style="{
|
|
||||||
zIndex,
|
|
||||||
pointerEvents: (manualShowing != null ? manualShowing : showing)
|
|
||||||
? 'auto'
|
|
||||||
: 'none',
|
|
||||||
'--transformOrigin': transformOrigin,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="_modalBg data-cy-bg"
|
v-show="manualShowing != null ? manualShowing : showing"
|
||||||
|
v-hotkey.global="keymap"
|
||||||
:class="[
|
:class="[
|
||||||
$style.bg,
|
$style.root,
|
||||||
{
|
{
|
||||||
[$style.bgTransparent]: isEnableBgTransparent,
|
[$style.drawer]: type === 'drawer',
|
||||||
'data-cy-transparent': isEnableBgTransparent,
|
[$style.dialog]: type === 'dialog' || type === 'dialog:top',
|
||||||
|
[$style.popup]: type === 'popup',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
:style="{ zIndex }"
|
:style="{
|
||||||
@click="onBgClick"
|
zIndex,
|
||||||
@mousedown="onBgClick"
|
pointerEvents: (manualShowing != null ? manualShowing : showing)
|
||||||
@contextmenu.prevent.stop="() => {}"
|
? 'auto'
|
||||||
></div>
|
: 'none',
|
||||||
<div
|
'--transformOrigin': transformOrigin,
|
||||||
ref="content"
|
}"
|
||||||
:class="[
|
tabindex="-1"
|
||||||
$style.content,
|
v-focus
|
||||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
|
||||||
]"
|
|
||||||
:style="{ zIndex }"
|
|
||||||
@click.self="onBgClick"
|
|
||||||
>
|
>
|
||||||
<slot :max-height="maxHeight" :type="type"></slot>
|
<div
|
||||||
|
class="_modalBg data-cy-bg"
|
||||||
|
:class="[
|
||||||
|
$style.bg,
|
||||||
|
{
|
||||||
|
[$style.bgTransparent]: isEnableBgTransparent,
|
||||||
|
'data-cy-transparent': isEnableBgTransparent,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:style="{ zIndex }"
|
||||||
|
@click="onBgClick"
|
||||||
|
@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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</FocusTrap>
|
||||||
</Transition>
|
</Transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -71,6 +76,7 @@ import * as os from "@/os";
|
||||||
import { isTouchUsing } from "@/scripts/touch";
|
import { isTouchUsing } from "@/scripts/touch";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
import { deviceKind } from "@/scripts/device-kind";
|
import { deviceKind } from "@/scripts/device-kind";
|
||||||
|
import { FocusTrap } from 'focus-trap-vue';
|
||||||
|
|
||||||
function getFixedContainer(el: Element | null): Element | null {
|
function getFixedContainer(el: Element | null): Element | null {
|
||||||
if (el == null || el.tagName === "BODY") return null;
|
if (el == null || el.tagName === "BODY") return null;
|
||||||
|
@ -166,6 +172,7 @@ let transitionDuration = $computed(() =>
|
||||||
|
|
||||||
let contentClicking = false;
|
let contentClicking = false;
|
||||||
|
|
||||||
|
const focusedElement = document.activeElement;
|
||||||
function close(opts: { useSendAnimation?: boolean } = {}) {
|
function close(opts: { useSendAnimation?: boolean } = {}) {
|
||||||
if (opts.useSendAnimation) {
|
if (opts.useSendAnimation) {
|
||||||
useSendAnime = true;
|
useSendAnime = true;
|
||||||
|
@ -175,10 +182,12 @@ function close(opts: { useSendAnimation?: boolean } = {}) {
|
||||||
if (props.src) props.src.style.pointerEvents = "auto";
|
if (props.src) props.src.style.pointerEvents = "auto";
|
||||||
showing = false;
|
showing = false;
|
||||||
emit("close");
|
emit("close");
|
||||||
|
focusedElement.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBgClick() {
|
function onBgClick() {
|
||||||
if (contentClicking) return;
|
if (contentClicking) return;
|
||||||
|
focusedElement.focus();
|
||||||
emit("click");
|
emit("click");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,6 +490,7 @@ defineExpose({
|
||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
outline: none;
|
||||||
&.dialog {
|
&.dialog {
|
||||||
> .content {
|
> .content {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
|
@ -158,6 +158,7 @@ function onContextmenu(ev: MouseEvent) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
contain: content;
|
contain: content;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
--root-margin: 24px;
|
--root-margin: 24px;
|
||||||
|
|
||||||
|
|
|
@ -3,59 +3,64 @@
|
||||||
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
|
<FocusTrap 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">
|
tabindex="-1"
|
||||||
<button
|
>
|
||||||
v-if="withOkButton"
|
<div ref="headerEl" class="header">
|
||||||
class="_button"
|
<button
|
||||||
@click="$emit('close')"
|
v-if="withOkButton"
|
||||||
>
|
class="_button"
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
@click="$emit('close')"
|
||||||
</button>
|
>
|
||||||
<span class="title">
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
<slot name="header"></slot>
|
</button>
|
||||||
</span>
|
<span class="title">
|
||||||
<button
|
<slot name="header"></slot>
|
||||||
v-if="!withOkButton"
|
</span>
|
||||||
class="_button"
|
<button
|
||||||
@click="$emit('close')"
|
v-if="!withOkButton"
|
||||||
>
|
class="_button"
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
@click="$emit('close')"
|
||||||
</button>
|
>
|
||||||
<button
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
v-if="withOkButton"
|
</button>
|
||||||
class="_button"
|
<button
|
||||||
:disabled="okButtonDisabled"
|
v-if="withOkButton"
|
||||||
@click="$emit('ok')"
|
class="_button"
|
||||||
>
|
:disabled="okButtonDisabled"
|
||||||
<i class="ph-check ph-bold ph-lg"></i>
|
@click="$emit('ok')"
|
||||||
</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">
|
</FocusTrap>
|
||||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MkModal>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted } from "vue";
|
import { onMounted, onUnmounted } from "vue";
|
||||||
|
import { FocusTrap } from 'focus-trap-vue';
|
||||||
import MkModal from "./MkModal.vue";
|
import MkModal from "./MkModal.vue";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
:detailedView="detailedView"
|
:detailedView="detailedView"
|
||||||
:parentId="appearNote.parentId"
|
:parentId="appearNote.parentId"
|
||||||
@push="(e) => router.push(notePage(e))"
|
@push="(e) => router.push(notePage(e))"
|
||||||
|
@focusfooter="footerEl.focus()"
|
||||||
></MkSubNoteContent>
|
></MkSubNoteContent>
|
||||||
<div v-if="translating || translation" class="translation">
|
<div v-if="translating || translation" class="translation">
|
||||||
<MkLoading v-if="translating" mini />
|
<MkLoading v-if="translating" mini />
|
||||||
|
@ -117,7 +118,7 @@
|
||||||
<MkTime :time="appearNote.createdAt" mode="absolute" />
|
<MkTime :time="appearNote.createdAt" mode="absolute" />
|
||||||
</MkA>
|
</MkA>
|
||||||
</div>
|
</div>
|
||||||
<footer ref="el" class="footer" @click.stop>
|
<footer ref="footerEl" class="footer" @click.stop tabindex="-1">
|
||||||
<XReactionsViewer
|
<XReactionsViewer
|
||||||
v-if="enableEmojiReactions"
|
v-if="enableEmojiReactions"
|
||||||
ref="reactionsViewer"
|
ref="reactionsViewer"
|
||||||
|
@ -278,6 +279,7 @@ const isRenote =
|
||||||
note.poll == null;
|
note.poll == null;
|
||||||
|
|
||||||
const el = ref<HTMLElement>();
|
const el = ref<HTMLElement>();
|
||||||
|
const footerEl = ref<HTMLElement>();
|
||||||
const menuButton = ref<HTMLElement>();
|
const menuButton = ref<HTMLElement>();
|
||||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
const starButton = ref<InstanceType<typeof XStarButton>>();
|
||||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||||
|
@ -298,8 +300,8 @@ const keymap = {
|
||||||
r: () => reply(true),
|
r: () => reply(true),
|
||||||
"e|a|plus": () => react(true),
|
"e|a|plus": () => react(true),
|
||||||
q: () => renoteButton.value.renote(true),
|
q: () => renoteButton.value.renote(true),
|
||||||
"up|k|shift+tab": focusBefore,
|
"up|k": focusBefore,
|
||||||
"down|j|tab": focusAfter,
|
"down|j": focusAfter,
|
||||||
esc: blur,
|
esc: blur,
|
||||||
"m|o": () => menu(true),
|
"m|o": () => menu(true),
|
||||||
s: () => showContent.value !== showContent.value,
|
s: () => showContent.value !== showContent.value,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-size="{ min: [350, 500] }" class="fefdfafb">
|
<div v-size="{ min: [350, 500] }" class="fefdfafb">
|
||||||
<MkAvatar class="avatar" :user="$i" />
|
<MkAvatar class="avatar" :user="$i" disableLink />
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<MkUserName :user="$i" />
|
<MkUserName :user="$i" />
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
:note="note"
|
:note="note"
|
||||||
:parentId="appearNote.parentId"
|
:parentId="appearNote.parentId"
|
||||||
:conversation="conversation"
|
:conversation="conversation"
|
||||||
|
@focusfooter="footerEl.focus()"
|
||||||
/>
|
/>
|
||||||
<div v-if="translating || translation" class="translation">
|
<div v-if="translating || translation" class="translation">
|
||||||
<MkLoading v-if="translating" mini />
|
<MkLoading v-if="translating" mini />
|
||||||
|
@ -46,7 +47,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="footer" @click.stop>
|
<footer ref="footerEl" class="footer" @click.stop tabindex="-1">
|
||||||
<XReactionsViewer
|
<XReactionsViewer
|
||||||
v-if="enableEmojiReactions"
|
v-if="enableEmojiReactions"
|
||||||
ref="reactionsViewer"
|
ref="reactionsViewer"
|
||||||
|
@ -212,6 +213,7 @@ const isRenote =
|
||||||
note.poll == null;
|
note.poll == null;
|
||||||
|
|
||||||
const el = ref<HTMLElement>();
|
const el = ref<HTMLElement>();
|
||||||
|
const footerEl = ref<HTMLElement>();
|
||||||
const menuButton = ref<HTMLElement>();
|
const menuButton = ref<HTMLElement>();
|
||||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
const starButton = ref<InstanceType<typeof XStarButton>>();
|
||||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
:transparent-bg="true"
|
:transparent-bg="true"
|
||||||
@click="modal.close()"
|
@click="modal.close()"
|
||||||
@closed="emit('closed')"
|
@closed="emit('closed')"
|
||||||
|
tabindex="-1"
|
||||||
|
v-focus
|
||||||
>
|
>
|
||||||
<MkMenu
|
<MkMenu
|
||||||
:items="items"
|
:items="items"
|
||||||
|
|
|
@ -198,7 +198,6 @@ export default defineComponent({
|
||||||
height: 64px;
|
height: 64px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
|
||||||
cursor: move;
|
cursor: move;
|
||||||
|
|
||||||
&:hover > .remove {
|
&:hover > .remove {
|
||||||
|
|
|
@ -35,7 +35,11 @@
|
||||||
class="content"
|
class="content"
|
||||||
:class="{ collapsed, isLong, showContent: note.cw && !showContent }"
|
:class="{ collapsed, isLong, showContent: note.cw && !showContent }"
|
||||||
>
|
>
|
||||||
<div class="body">
|
<XCwButton ref="cwButton" v-if="note.cw && !showContent" v-model="showContent" :note="note" v-on:keydown="focusFooter" />
|
||||||
|
<div
|
||||||
|
class="body"
|
||||||
|
v-bind="{ 'aria-label': !showContent ? '' : null, 'tabindex': !showContent ? '-1' : null }"
|
||||||
|
>
|
||||||
<span v-if="note.deletedAt" style="opacity: 0.5"
|
<span v-if="note.deletedAt" style="opacity: 0.5"
|
||||||
>({{ i18n.ts.deleted }})</span
|
>({{ i18n.ts.deleted }})</span
|
||||||
>
|
>
|
||||||
|
@ -96,28 +100,20 @@
|
||||||
<XNoteSimple :note="note.renote" />
|
<XNoteSimple :note="note.renote" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<div
|
||||||
|
v-if="note.cw && !showContent"
|
||||||
|
tabindex="0"
|
||||||
|
v-on:focus="cwButton?.focus()"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<XShowMoreButton v-if="isLong" v-model="collapsed"></XShowMoreButton>
|
||||||
v-if="isLong && collapsed"
|
<XCwButton v-if="note.cw && showContent" v-model="showContent" :note="note" />
|
||||||
class="fade _button"
|
|
||||||
@click.stop="collapsed = false"
|
|
||||||
>
|
|
||||||
<span>{{ i18n.ts.showMore }}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-if="isLong && !collapsed"
|
|
||||||
class="showLess _button"
|
|
||||||
@click.stop="collapsed = true"
|
|
||||||
>
|
|
||||||
<span>{{ i18n.ts.showLess }}</span>
|
|
||||||
</button>
|
|
||||||
<XCwButton v-if="note.cw" v-model="showContent" :note="note" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {} from "vue";
|
import { ref } from "vue";
|
||||||
import * as misskey from "calckey-js";
|
import * as misskey from "calckey-js";
|
||||||
import * as mfm from "mfm-js";
|
import * as mfm from "mfm-js";
|
||||||
import XNoteSimple from "@/components/MkNoteSimple.vue";
|
import XNoteSimple from "@/components/MkNoteSimple.vue";
|
||||||
|
@ -138,8 +134,10 @@ const props = defineProps<{
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: "push", v): void;
|
(ev: "push", v): void;
|
||||||
|
(ev: "focusfooter"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const cwButton = ref<HTMLElement>();
|
||||||
const isLong =
|
const isLong =
|
||||||
!props.detailedView &&
|
!props.detailedView &&
|
||||||
props.note.cw == null &&
|
props.note.cw == null &&
|
||||||
|
@ -151,6 +149,13 @@ const urls = props.note.text
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
let showContent = $ref(false);
|
let showContent = $ref(false);
|
||||||
|
|
||||||
|
|
||||||
|
function focusFooter(ev) {
|
||||||
|
if (ev.key == "Tab" && !ev.getModifierState("Shift")) {
|
||||||
|
emit("focusfooter");
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -242,6 +247,9 @@ let showContent = $ref(false);
|
||||||
margin-top: -50px;
|
margin-top: -50px;
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
}
|
}
|
||||||
&.collapsed > .body {
|
&.collapsed > .body {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
v-if="item.type === 'a'"
|
v-if="item.type === 'a'"
|
||||||
:href="item.href"
|
:href="item.href"
|
||||||
:target="item.target"
|
:target="item.target"
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
class="_button item"
|
||||||
:class="{ danger: item.danger, active: item.active }"
|
:class="{ danger: item.danger, active: item.active }"
|
||||||
>
|
>
|
||||||
|
@ -22,7 +21,6 @@
|
||||||
</a>
|
</a>
|
||||||
<button
|
<button
|
||||||
v-else-if="item.type === 'button'"
|
v-else-if="item.type === 'button'"
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
class="_button item"
|
||||||
:class="{ danger: item.danger, active: item.active }"
|
:class="{ danger: item.danger, active: item.active }"
|
||||||
:disabled="item.active"
|
:disabled="item.active"
|
||||||
|
@ -38,7 +36,6 @@
|
||||||
<MkA
|
<MkA
|
||||||
v-else
|
v-else
|
||||||
:to="item.to"
|
:to="item.to"
|
||||||
:tabindex="i"
|
|
||||||
class="_button item"
|
class="_button item"
|
||||||
:class="{ danger: item.danger, active: item.active }"
|
:class="{ danger: item.danger, active: item.active }"
|
||||||
>
|
>
|
||||||
|
@ -99,7 +96,7 @@ export default defineComponent({
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin-bottom: 0.3rem;
|
margin-bottom: 0.3rem;
|
||||||
|
|
||||||
&:hover {
|
&:hover, &:focus-visible {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: var(--panelHighlight);
|
background: var(--panelHighlight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
:user="user"
|
:user="user"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:show-indicator="true"
|
:show-indicator="true"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<MkUserName :user="user" class="name" />
|
<MkUserName :user="user" class="name" />
|
||||||
|
@ -73,6 +74,7 @@
|
||||||
:user="user"
|
:user="user"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:show-indicator="true"
|
:show-indicator="true"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<MkUserName :user="user" class="name" />
|
<MkUserName :user="user" class="name" />
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
>
|
>
|
||||||
<div class="beaffaef">
|
<div class="beaffaef">
|
||||||
<div v-for="u in users" :key="u.id" class="user">
|
<div v-for="u in users" :key="u.id" class="user">
|
||||||
<MkAvatar class="avatar" :user="u" />
|
<MkAvatar class="avatar" :user="u" disableLink />
|
||||||
<MkUserName class="name" :user="u" :nowrap="true" />
|
<MkUserName class="name" :user="u" :nowrap="true" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="users.length < count" class="omitted">
|
<div v-if="users.length < count" class="omitted">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="vjoppmmu">
|
<div class="vjoppmmu">
|
||||||
<template v-if="edit">
|
<template v-if="edit">
|
||||||
<header>
|
<header tabindex="-1" v-focus>
|
||||||
<MkSelect
|
<MkSelect
|
||||||
v-model="widgetAdderSelected"
|
v-model="widgetAdderSelected"
|
||||||
style="margin-bottom: var(--margin)"
|
style="margin-bottom: var(--margin)"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dwzlatin" :class="{ opened }">
|
<div class="dwzlatin" :class="{ opened }">
|
||||||
<div class="header _button" @click="toggle">
|
<button class="header _button" @click="toggle">
|
||||||
<span class="icon"><slot name="icon"></slot></span>
|
<span class="icon"><slot name="icon"></slot></span>
|
||||||
<span class="text"><slot name="label"></slot></span>
|
<span class="text"><slot name="label"></slot></span>
|
||||||
<span class="right">
|
<span class="right">
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
<i v-if="opened" class="ph-caret-up ph-bold ph-lg icon"></i>
|
<i v-if="opened" class="ph-caret-up ph-bold ph-lg icon"></i>
|
||||||
<i v-else class="ph-caret-down ph-bold ph-lg icon"></i>
|
<i v-else class="ph-caret-down ph-bold ph-lg icon"></i>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</button>
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<div v-if="openedAtLeastOnce" v-show="opened" class="body">
|
<div v-if="openedAtLeastOnce" v-show="opened" class="body">
|
||||||
<MkSpacer :margin-min="14" :margin-max="22">
|
<MkSpacer :margin-min="14" :margin-max="22">
|
||||||
|
|
|
@ -66,6 +66,9 @@ function toggle(): void {
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--inputBorderHover) !important;
|
border-color: var(--inputBorderHover) !important;
|
||||||
}
|
}
|
||||||
|
&:focus-within {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
&.checked {
|
&.checked {
|
||||||
background-color: var(--accentedBg) !important;
|
background-color: var(--accentedBg) !important;
|
||||||
|
|
|
@ -99,6 +99,9 @@ const toggle = () => {
|
||||||
border-color: var(--inputBorderHover) !important;
|
border-color: var(--inputBorderHover) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:focus-within > .button {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
> .label {
|
> .label {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:user="$i"
|
:user="$i"
|
||||||
:disable-preview="true"
|
:disable-preview="true"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="metadata">
|
<template v-if="metadata">
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
:user="metadata.avatar"
|
:user="metadata.avatar"
|
||||||
:disable-preview="true"
|
:disable-preview="true"
|
||||||
:show-indicator="true"
|
:show-indicator="true"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
<i
|
<i
|
||||||
v-else-if="metadata.icon && !narrow"
|
v-else-if="metadata.icon && !narrow"
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
:is="currentPageComponent"
|
:is="currentPageComponent"
|
||||||
:key="key"
|
:key="key"
|
||||||
v-bind="Object.fromEntries(currentPageProps)"
|
v-bind="Object.fromEntries(currentPageProps)"
|
||||||
|
tabindex="-1"
|
||||||
|
v-focus
|
||||||
|
style="outline: none;"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<template #fallback>
|
<template #fallback>
|
||||||
|
|
3
packages/client/src/directives/focus.ts
Normal file
3
packages/client/src/directives/focus.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default {
|
||||||
|
mounted: (el) => el.focus()
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import anim from "./anim";
|
||||||
import clickAnime from "./click-anime";
|
import clickAnime from "./click-anime";
|
||||||
import panel from "./panel";
|
import panel from "./panel";
|
||||||
import adaptiveBorder from "./adaptive-border";
|
import adaptiveBorder from "./adaptive-border";
|
||||||
|
import focus from "./focus";
|
||||||
|
|
||||||
export default function (app: App) {
|
export default function (app: App) {
|
||||||
app.directive("userPreview", userPreview);
|
app.directive("userPreview", userPreview);
|
||||||
|
@ -25,4 +26,5 @@ export default function (app: App) {
|
||||||
app.directive("click-anime", clickAnime);
|
app.directive("click-anime", clickAnime);
|
||||||
app.directive("panel", panel);
|
app.directive("panel", panel);
|
||||||
app.directive("adaptive-border", adaptiveBorder);
|
app.directive("adaptive-border", adaptiveBorder);
|
||||||
|
app.directive("focus", focus);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,23 +76,32 @@ export default {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showTooltip() {
|
||||||
|
window.clearTimeout(self.showTimer);
|
||||||
|
window.clearTimeout(self.hideTimer);
|
||||||
|
self.showTimer = window.setTimeout(self.show, delay);
|
||||||
|
}
|
||||||
|
function hideTooltip() {
|
||||||
|
window.clearTimeout(self.showTimer);
|
||||||
|
window.clearTimeout(self.hideTimer);
|
||||||
|
self.hideTimer = window.setTimeout(self.close, delay);
|
||||||
|
}
|
||||||
|
|
||||||
el.addEventListener(
|
el.addEventListener(
|
||||||
start,
|
start, showTooltip,
|
||||||
() => {
|
{ passive: true },
|
||||||
window.clearTimeout(self.showTimer);
|
);
|
||||||
window.clearTimeout(self.hideTimer);
|
el.addEventListener(
|
||||||
self.showTimer = window.setTimeout(self.show, delay);
|
"focusin", showTooltip,
|
||||||
},
|
|
||||||
{ passive: true },
|
{ passive: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
el.addEventListener(
|
el.addEventListener(
|
||||||
end,
|
end, hideTooltip,
|
||||||
() => {
|
{ passive: true },
|
||||||
window.clearTimeout(self.showTimer);
|
);
|
||||||
window.clearTimeout(self.hideTimer);
|
el.addEventListener(
|
||||||
self.hideTimer = window.setTimeout(self.close, delay);
|
"focusout", hideTooltip,
|
||||||
},
|
|
||||||
{ passive: true },
|
{ passive: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -313,11 +313,7 @@ onUnmounted(() => {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
||||||
&:hover {
|
&:hover, &:focus-visible, &.active {
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
class="user"
|
class="user"
|
||||||
:to="`/user-info/${user.id}`"
|
:to="`/user-info/${user.id}`"
|
||||||
>
|
>
|
||||||
<MkAvatar :user="user" class="avatar" indicator />
|
<MkAvatar :user="user" class="avatar" indicator disableLink />
|
||||||
</MkA>
|
</MkA>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:user="req.follower"
|
:user="req.follower"
|
||||||
:show-indicator="true"
|
:show-indicator="true"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
{{ i18n.ts.addAccount }}</FormButton
|
{{ i18n.ts.addAccount }}</FormButton
|
||||||
>
|
>
|
||||||
|
|
||||||
<div
|
<button
|
||||||
v-for="account in accounts"
|
v-for="account in accounts"
|
||||||
:key="account.id"
|
:key="account.id"
|
||||||
class="_panel _button lcjjdxlm"
|
class="_panel _button lcjjdxlm"
|
||||||
@click="menu(account, $event)"
|
@click="menu(account, $event)"
|
||||||
>
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<MkAvatar :user="account" class="avatar" />
|
<MkAvatar :user="account" class="avatar" disableLink />
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<MkAcct :user="account" />
|
<MkAcct :user="account" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
</FormSuspense>
|
</FormSuspense>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -158,6 +158,8 @@ definePageMetadata({
|
||||||
.lcjjdxlm {
|
.lcjjdxlm {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: unset;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -204,10 +204,6 @@ hr {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus-visible {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<MkAvatar
|
<MkAvatar
|
||||||
:user="$i"
|
:user="$i"
|
||||||
class="icon"
|
class="icon"
|
||||||
|
disableLink
|
||||||
/><!-- <MkAcct class="text" :user="$i"/> -->
|
/><!-- <MkAcct class="text" :user="$i"/> -->
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<MkAvatar
|
<MkAvatar
|
||||||
:user="$i"
|
:user="$i"
|
||||||
class="icon"
|
class="icon"
|
||||||
|
disableLink
|
||||||
/><!-- <MkAcct class="text" :user="$i"/> -->
|
/><!-- <MkAcct class="text" :user="$i"/> -->
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -334,6 +335,7 @@ function more(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
&.active {
|
&.active {
|
||||||
&:before {
|
&:before {
|
||||||
background: var(--accentLighten);
|
background: var(--accentLighten);
|
||||||
|
@ -398,8 +400,6 @@ function more(ev: MouseEvent) {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
line-height: 2.85rem;
|
line-height: 2.85rem;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
@ -425,9 +425,12 @@ function more(ev: MouseEvent) {
|
||||||
> .text {
|
> .text {
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--navHoverFg);
|
color: var(--navHoverFg);
|
||||||
transition: all 0.4s ease;
|
transition: all 0.4s ease;
|
||||||
|
@ -437,7 +440,8 @@ function more(ev: MouseEvent) {
|
||||||
color: var(--navActive);
|
color: var(--navActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
&.active {
|
&.active {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
transition: all 0.4s ease;
|
transition: all 0.4s ease;
|
||||||
|
@ -528,6 +532,7 @@ function more(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
&.active {
|
&.active {
|
||||||
&:before {
|
&:before {
|
||||||
background: var(--accentLighten);
|
background: var(--accentLighten);
|
||||||
|
@ -613,6 +618,7 @@ function more(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
&.active {
|
&.active {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
@ -642,5 +648,12 @@ function more(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
outline: none;
|
||||||
|
&:focus-visible:before {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
<MkAvatar :user="$i" class="avatar" /><MkAcct
|
<MkAvatar :user="$i" class="avatar" /><MkAcct
|
||||||
class="acct"
|
class="acct"
|
||||||
:user="$i"
|
:user="$i"
|
||||||
|
disableLink
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<div class="post" @click="post">
|
<div class="post" @click="post">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
class="item _button account"
|
class="item _button account"
|
||||||
@click="openAccountMenu"
|
@click="openAccountMenu"
|
||||||
>
|
>
|
||||||
<MkAvatar :user="$i" class="avatar" /><MkAcct
|
<MkAvatar :user="$i" class="avatar" disableLink /><MkAcct
|
||||||
class="text"
|
class="text"
|
||||||
:user="$i"
|
:user="$i"
|
||||||
/>
|
/>
|
||||||
|
@ -299,6 +299,7 @@ function openInstanceMenu(ev: MouseEvent) {
|
||||||
width: 46px;
|
width: 46px;
|
||||||
height: 46px;
|
height: 46px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin-inline: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,6 +373,7 @@ function openInstanceMenu(ev: MouseEvent) {
|
||||||
|
|
||||||
> i {
|
> i {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
> i,
|
> i,
|
||||||
|
|
|
@ -227,6 +227,8 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.gbhvwtnk {
|
.gbhvwtnk {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
$ui-font-size: 1em;
|
$ui-font-size: 1em;
|
||||||
$widgets-hide-threshold: 1200px;
|
$widgets-hide-threshold: 1200px;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@ importers:
|
||||||
'@tensorflow/tfjs':
|
'@tensorflow/tfjs':
|
||||||
specifier: ^3.21.0
|
specifier: ^3.21.0
|
||||||
version: 3.21.0(seedrandom@3.0.5)
|
version: 3.21.0(seedrandom@3.0.5)
|
||||||
|
focus-trap:
|
||||||
|
specifier: ^7.2.0
|
||||||
|
version: 7.2.0
|
||||||
|
focus-trap-vue:
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1(focus-trap@7.2.0)(vue@3.2.45)
|
||||||
js-yaml:
|
js-yaml:
|
||||||
specifier: 4.1.0
|
specifier: 4.1.0
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
|
@ -3803,14 +3809,12 @@ packages:
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/compiler-dom@3.2.45:
|
/@vue/compiler-dom@3.2.45:
|
||||||
resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==}
|
resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-core': 3.2.45
|
'@vue/compiler-core': 3.2.45
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/compiler-sfc@2.7.14:
|
/@vue/compiler-sfc@2.7.14:
|
||||||
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
|
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
|
||||||
|
@ -3833,14 +3837,12 @@ packages:
|
||||||
magic-string: 0.25.9
|
magic-string: 0.25.9
|
||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/compiler-ssr@3.2.45:
|
/@vue/compiler-ssr@3.2.45:
|
||||||
resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==}
|
resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-dom': 3.2.45
|
'@vue/compiler-dom': 3.2.45
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/reactivity-transform@3.2.45:
|
/@vue/reactivity-transform@3.2.45:
|
||||||
resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==}
|
resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==}
|
||||||
|
@ -3850,20 +3852,17 @@ packages:
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
magic-string: 0.25.9
|
magic-string: 0.25.9
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/reactivity@3.2.45:
|
/@vue/reactivity@3.2.45:
|
||||||
resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==}
|
resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/runtime-core@3.2.45:
|
/@vue/runtime-core@3.2.45:
|
||||||
resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==}
|
resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/reactivity': 3.2.45
|
'@vue/reactivity': 3.2.45
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/runtime-dom@3.2.45:
|
/@vue/runtime-dom@3.2.45:
|
||||||
resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==}
|
resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==}
|
||||||
|
@ -3871,7 +3870,6 @@ packages:
|
||||||
'@vue/runtime-core': 3.2.45
|
'@vue/runtime-core': 3.2.45
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
csstype: 2.6.21
|
csstype: 2.6.21
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/server-renderer@3.2.45(vue@3.2.45):
|
/@vue/server-renderer@3.2.45(vue@3.2.45):
|
||||||
resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==}
|
resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==}
|
||||||
|
@ -3881,11 +3879,9 @@ packages:
|
||||||
'@vue/compiler-ssr': 3.2.45
|
'@vue/compiler-ssr': 3.2.45
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
vue: 3.2.45
|
vue: 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@vue/shared@3.2.45:
|
/@vue/shared@3.2.45:
|
||||||
resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==}
|
resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@webassemblyjs/ast@1.11.1:
|
/@webassemblyjs/ast@1.11.1:
|
||||||
resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==}
|
resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==}
|
||||||
|
@ -6074,7 +6070,6 @@ packages:
|
||||||
|
|
||||||
/csstype@2.6.21:
|
/csstype@2.6.21:
|
||||||
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/csstype@3.1.1:
|
/csstype@3.1.1:
|
||||||
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
||||||
|
@ -6979,7 +6974,6 @@ packages:
|
||||||
|
|
||||||
/estree-walker@2.0.2:
|
/estree-walker@2.0.2:
|
||||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/esutils@2.0.3:
|
/esutils@2.0.3:
|
||||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||||
|
@ -7445,6 +7439,22 @@ packages:
|
||||||
readable-stream: 2.3.7
|
readable-stream: 2.3.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/focus-trap-vue@4.0.1(focus-trap@7.2.0)(vue@3.2.45):
|
||||||
|
resolution: {integrity: sha512-2iqOeoSvgq7Um6aL+255a/wXPskj6waLq2oKCa4gOnMORPo15JX7wN6J5bl1SMhMlTlkHXGSrQ9uJPJLPZDl5w==}
|
||||||
|
peerDependencies:
|
||||||
|
focus-trap: ^7.0.0
|
||||||
|
vue: ^3.0.0
|
||||||
|
dependencies:
|
||||||
|
focus-trap: 7.2.0
|
||||||
|
vue: 3.2.45
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/focus-trap@7.2.0:
|
||||||
|
resolution: {integrity: sha512-v4wY6HDDYvzkBy4735kW5BUEuw6Yz9ABqMYLuTNbzAFPcBOGiGHwwcNVMvUz4G0kgSYh13wa/7TG3XwTeT4O/A==}
|
||||||
|
dependencies:
|
||||||
|
tabbable: 6.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/follow-redirects@1.15.2(debug@4.3.4):
|
/follow-redirects@1.15.2(debug@4.3.4):
|
||||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
@ -10350,7 +10360,6 @@ packages:
|
||||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
sourcemap-codec: 1.4.8
|
sourcemap-codec: 1.4.8
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mailcheck@1.1.1:
|
/mailcheck@1.1.1:
|
||||||
resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==}
|
resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==}
|
||||||
|
@ -13267,7 +13276,6 @@ packages:
|
||||||
/sourcemap-codec@1.4.8:
|
/sourcemap-codec@1.4.8:
|
||||||
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
||||||
deprecated: Please use @jridgewell/sourcemap-codec instead
|
deprecated: Please use @jridgewell/sourcemap-codec instead
|
||||||
dev: true
|
|
||||||
|
|
||||||
/sparkles@1.0.1:
|
/sparkles@1.0.1:
|
||||||
resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==}
|
resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==}
|
||||||
|
@ -13686,6 +13694,10 @@ packages:
|
||||||
resolution: {integrity: sha512-g9rPT3V1Q4WjWFZ/t5BdGC1mT/FpYnsLdBl+M5e6MlRkuE1RSR+R43wcY/3mKI59B9KEr+vxdWCuWNMD3oNHKA==}
|
resolution: {integrity: sha512-g9rPT3V1Q4WjWFZ/t5BdGC1mT/FpYnsLdBl+M5e6MlRkuE1RSR+R43wcY/3mKI59B9KEr+vxdWCuWNMD3oNHKA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tabbable@6.1.1:
|
||||||
|
resolution: {integrity: sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tapable@2.2.1:
|
/tapable@2.2.1:
|
||||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -14776,7 +14788,6 @@ packages:
|
||||||
'@vue/runtime-dom': 3.2.45
|
'@vue/runtime-dom': 3.2.45
|
||||||
'@vue/server-renderer': 3.2.45(vue@3.2.45)
|
'@vue/server-renderer': 3.2.45(vue@3.2.45)
|
||||||
'@vue/shared': 3.2.45
|
'@vue/shared': 3.2.45
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vuedraggable@4.1.0(vue@3.2.45):
|
/vuedraggable@4.1.0(vue@3.2.45):
|
||||||
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
|
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
|
||||||
|
|
Loading…
Reference in a new issue