summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkMenu.vue
diff options
context:
space:
mode:
authorMarie <marie@kaifa.ch>2024-02-03 20:19:44 +0100
committerMarie <marie@kaifa.ch>2024-02-03 20:19:44 +0100
commit11628e4b6a439a8a5f0ed1e1e8997f4edc894ace (patch)
tree865f01b5a5fbaf98bc838451cb7bd39e44bceb66 /packages/frontend/src/components/MkMenu.vue
parentmerge: Fix sfm-js linkage (!399) (diff)
parent2024.2.0-beta.9 (diff)
downloadsharkey-11628e4b6a439a8a5f0ed1e1e8997f4edc894ace.tar.gz
sharkey-11628e4b6a439a8a5f0ed1e1e8997f4edc894ace.tar.bz2
sharkey-11628e4b6a439a8a5f0ed1e1e8997f4edc894ace.zip
merge: upstream
Diffstat (limited to 'packages/frontend/src/components/MkMenu.vue')
-rw-r--r--packages/frontend/src/components/MkMenu.vue28
1 files changed, 16 insertions, 12 deletions
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index eb6e7935ed..ad3162bad5 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:style="{ width: (width && !asDrawer) ? width + 'px' : '', maxHeight: maxHeight ? maxHeight + 'px' : '' }"
@contextmenu.self="e => e.preventDefault()"
>
- <template v-for="(item, i) in items2">
+ <template v-for="(item, i) in (items2 ?? [])">
<div v-if="item.type === 'divider'" role="separator" :class="$style.divider"></div>
<span v-else-if="item.type === 'label'" role="menuitem" :class="[$style.label, $style.item]">
<span style="opacity: 0.7;">{{ item.text }}</span>
@@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span :class="$style.caret" style="pointer-events: none;"><i class="ph-caret-right ph-bold ph-lg ti-fw"></i></span>
</div>
</button>
- <button v-else :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
+ <button v-else :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: getValue(item.active) }]" :disabled="getValue(item.active)" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/>
<div :class="$style.item_content">
@@ -63,18 +63,18 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</button>
</template>
- <span v-if="items2.length === 0" :class="[$style.none, $style.item]">
+ <span v-if="items2 == null || items2.length === 0" :class="[$style.none, $style.item]">
<span>{{ i18n.ts.none }}</span>
</span>
</div>
<div v-if="childMenu">
- <XChild ref="child" :items="childMenu" :targetElement="childTarget" :rootElement="itemsEl" showing @actioned="childActioned" @close="close(false)"/>
+ <XChild ref="child" :items="childMenu" :targetElement="childTarget!" :rootElement="itemsEl!" showing @actioned="childActioned" @close="close(false)"/>
</div>
</div>
</template>
<script lang="ts">
-import { computed, defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
+import { ComputedRef, computed, defineAsyncComponent, isRef, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
import { focusPrev, focusNext } from '@/scripts/focus.js';
import MkSwitchButton from '@/components/MkSwitch.button.vue';
import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu.js';
@@ -104,7 +104,7 @@ const emit = defineEmits<{
const itemsEl = shallowRef<HTMLDivElement>();
-const items2 = ref<InnerMenuItem[]>([]);
+const items2 = ref<InnerMenuItem[]>();
const child = shallowRef<InstanceType<typeof XChild>>();
@@ -119,15 +119,15 @@ const childShowingItem = ref<MenuItem | null>();
let preferClick = isTouchUsing || props.asDrawer;
watch(() => props.items, () => {
- const items: (MenuItem | MenuPending)[] = [...props.items].filter(item => item !== undefined);
+ const items = [...props.items].filter(item => item !== undefined) as (NonNullable<MenuItem> | MenuPending)[];
for (let i = 0; i < items.length; i++) {
const item = items[i];
- if (item && 'then' in item) { // if item is Promise
+ if ('then' in item) { // if item is Promise
items[i] = { type: 'pending' };
item.then(actualItem => {
- items2.value[i] = actualItem;
+ if (items2.value?.[i]) items2.value[i] = actualItem;
});
}
}
@@ -151,7 +151,7 @@ function childActioned() {
}
const onGlobalMousedown = (event: MouseEvent) => {
- if (childTarget.value && (event.target === childTarget.value || childTarget.value.contains(event.target))) return;
+ if (childTarget.value && (event.target === childTarget.value || childTarget.value.contains(event.target as Node))) return;
if (child.value && child.value.checkHit(event)) return;
closeChild();
};
@@ -169,7 +169,7 @@ function onItemMouseLeave(item) {
}
async function showChildren(item: MenuParent, ev: MouseEvent) {
- const children = await (async () => {
+ const children: MenuItem[] = await (async () => {
if (childrenCache.has(item)) {
return childrenCache.get(item)!;
} else {
@@ -189,7 +189,7 @@ async function showChildren(item: MenuParent, ev: MouseEvent) {
});
emit('hide');
} else {
- childTarget.value = ev.currentTarget ?? ev.target;
+ childTarget.value = (ev.currentTarget ?? ev.target) as HTMLElement;
// これでもリアクティビティは保たれる
childMenu.value = children;
childShowingItem.value = item;
@@ -218,6 +218,10 @@ function switchItem(item: MenuSwitch & { ref: any }) {
item.ref = !item.ref;
}
+function getValue<T>(item?: ComputedRef<T> | T) {
+ return isRef(item) ? item.value : item;
+}
+
onMounted(() => {
if (props.viaKeyboard) {
nextTick(() => {