mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-02 17:55:52 +02:00
refactor(frontend): src -> anchorElement
This commit is contained in:
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
:hasInteractionWithOtherFocusTrappedEls="true"
|
||||
:transparentBg="true"
|
||||
:manualShowing="manualShowing"
|
||||
:src="src"
|
||||
:anchorElement="anchorElement"
|
||||
@click="modal?.close()"
|
||||
@esc="modal?.close()"
|
||||
@opening="opening"
|
||||
@@ -44,7 +44,7 @@ import { prefer } from '@/preferences.js';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
manualShowing?: boolean | null;
|
||||
src?: HTMLElement;
|
||||
anchorElement?: HTMLElement;
|
||||
showPinned?: boolean;
|
||||
pinnedEmojis?: string[],
|
||||
asReactionPicker?: boolean;
|
||||
|
||||
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<MkModal ref="modal" v-slot="{ type, maxHeight }" :preferType="preferedModalType" :anchor="anchor" :transparentBg="true" :src="src" @click="modal?.close()" @closed="emit('closed')" @esc="modal?.close()">
|
||||
<MkModal ref="modal" v-slot="{ type, maxHeight }" :preferType="preferedModalType" :anchor="anchor" :transparentBg="true" :anchorElement="anchorElement" @click="modal?.close()" @closed="emit('closed')" @esc="modal?.close()">
|
||||
<div class="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
|
||||
<div class="main">
|
||||
<template v-for="item in items" :key="item.text">
|
||||
@@ -34,7 +34,7 @@ import { deviceKind } from '@/utility/device-kind.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
src?: HTMLElement;
|
||||
anchorElement?: HTMLElement;
|
||||
anchor?: { x: string; y: string; };
|
||||
}>(), {
|
||||
anchor: () => ({ x: 'right', y: 'center' }),
|
||||
@@ -44,7 +44,7 @@ const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
|
||||
const preferedModalType = (deviceKind === 'desktop' && props.anchorElement != null) ? 'popup' :
|
||||
deviceKind === 'smartphone' ? 'drawer' :
|
||||
'dialog';
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ type ModalTypes = 'popup' | 'dialog' | 'drawer';
|
||||
const props = withDefaults(defineProps<{
|
||||
manualShowing?: boolean | null;
|
||||
anchor?: { x: string; y: string; };
|
||||
src?: HTMLElement | null;
|
||||
anchorElement?: HTMLElement | null;
|
||||
preferType?: ModalTypes | 'auto';
|
||||
zPriority?: 'low' | 'middle' | 'high';
|
||||
noOverlap?: boolean;
|
||||
@@ -76,7 +76,7 @@ const props = withDefaults(defineProps<{
|
||||
returnFocusTo?: HTMLElement | null;
|
||||
}>(), {
|
||||
manualShowing: null,
|
||||
src: null,
|
||||
anchorElement: null,
|
||||
anchor: () => ({ x: 'center', y: 'bottom' }),
|
||||
preferType: 'auto',
|
||||
zPriority: 'low',
|
||||
@@ -110,7 +110,7 @@ const type = computed<ModalTypes>(() => {
|
||||
if ((prefer.s.menuStyle === 'drawer') || (prefer.s.menuStyle === 'auto' && isTouchUsing && deviceKind === 'smartphone')) {
|
||||
return 'drawer';
|
||||
} else {
|
||||
return props.src != null ? 'popup' : 'dialog';
|
||||
return props.anchorElement != null ? 'popup' : 'dialog';
|
||||
}
|
||||
} else {
|
||||
return props.preferType!;
|
||||
@@ -149,7 +149,7 @@ function close(opts: { useSendAnimation?: boolean } = {}) {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
if (props.src) props.src.style.pointerEvents = 'auto';
|
||||
if (props.anchorElement) props.anchorElement.style.pointerEvents = 'auto';
|
||||
showing.value = false;
|
||||
emit('close');
|
||||
}
|
||||
@@ -174,13 +174,13 @@ const MARGIN = 16;
|
||||
const SCROLLBAR_THICKNESS = 16;
|
||||
|
||||
const align = () => {
|
||||
if (props.src == null) return;
|
||||
if (props.anchorElement == null) return;
|
||||
if (type.value === 'drawer') return;
|
||||
if (type.value === 'dialog') return;
|
||||
|
||||
if (content.value == null) return;
|
||||
|
||||
const srcRect = props.src.getBoundingClientRect();
|
||||
const anchorRect = props.anchorElement.getBoundingClientRect();
|
||||
|
||||
const width = content.value!.offsetWidth;
|
||||
const height = content.value!.offsetHeight;
|
||||
@@ -188,15 +188,15 @@ const align = () => {
|
||||
let left;
|
||||
let top;
|
||||
|
||||
const x = srcRect.left + (fixed.value ? 0 : window.scrollX);
|
||||
const y = srcRect.top + (fixed.value ? 0 : window.scrollY);
|
||||
const x = anchorRect.left + (fixed.value ? 0 : window.scrollX);
|
||||
const y = anchorRect.top + (fixed.value ? 0 : window.scrollY);
|
||||
|
||||
if (props.anchor.x === 'center') {
|
||||
left = x + (props.src.offsetWidth / 2) - (width / 2);
|
||||
left = x + (props.anchorElement.offsetWidth / 2) - (width / 2);
|
||||
} else if (props.anchor.x === 'left') {
|
||||
// TODO
|
||||
} else if (props.anchor.x === 'right') {
|
||||
left = x + props.src.offsetWidth;
|
||||
left = x + props.anchorElement.offsetWidth;
|
||||
}
|
||||
|
||||
if (props.anchor.y === 'center') {
|
||||
@@ -204,7 +204,7 @@ const align = () => {
|
||||
} else if (props.anchor.y === 'top') {
|
||||
// TODO
|
||||
} else if (props.anchor.y === 'bottom') {
|
||||
top = y + props.src.offsetHeight;
|
||||
top = y + props.anchorElement.offsetHeight;
|
||||
}
|
||||
|
||||
if (fixed.value) {
|
||||
@@ -214,7 +214,7 @@ const align = () => {
|
||||
}
|
||||
|
||||
const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top;
|
||||
const upperSpace = (srcRect.top - MARGIN);
|
||||
const upperSpace = (anchorRect.top - MARGIN);
|
||||
|
||||
// 画面から縦にはみ出る場合
|
||||
if (top + height > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
|
||||
@@ -238,7 +238,7 @@ const align = () => {
|
||||
}
|
||||
|
||||
const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.scrollY);
|
||||
const upperSpace = (srcRect.top - MARGIN);
|
||||
const upperSpace = (anchorRect.top - MARGIN);
|
||||
|
||||
// 画面から縦にはみ出る場合
|
||||
if (top + height - window.scrollY > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
|
||||
@@ -268,15 +268,15 @@ const align = () => {
|
||||
let transformOriginX = 'center';
|
||||
let transformOriginY = 'center';
|
||||
|
||||
if (top >= srcRect.top + props.src.offsetHeight + (fixed.value ? 0 : window.scrollY)) {
|
||||
if (top >= anchorRect.top + props.anchorElement.offsetHeight + (fixed.value ? 0 : window.scrollY)) {
|
||||
transformOriginY = 'top';
|
||||
} else if ((top + height) <= srcRect.top + (fixed.value ? 0 : window.scrollY)) {
|
||||
} else if ((top + height) <= anchorRect.top + (fixed.value ? 0 : window.scrollY)) {
|
||||
transformOriginY = 'bottom';
|
||||
}
|
||||
|
||||
if (left >= srcRect.left + props.src.offsetWidth + (fixed.value ? 0 : window.scrollX)) {
|
||||
if (left >= anchorRect.left + props.anchorElement.offsetWidth + (fixed.value ? 0 : window.scrollX)) {
|
||||
transformOriginX = 'left';
|
||||
} else if ((left + width) <= srcRect.left + (fixed.value ? 0 : window.scrollX)) {
|
||||
} else if ((left + width) <= anchorRect.left + (fixed.value ? 0 : window.scrollX)) {
|
||||
transformOriginX = 'right';
|
||||
}
|
||||
|
||||
@@ -317,12 +317,12 @@ const alignObserver = new ResizeObserver((entries, observer) => {
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watch(() => props.src, async () => {
|
||||
if (props.src) {
|
||||
watch(() => props.anchorElement, async () => {
|
||||
if (props.anchorElement) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.src.style.pointerEvents = 'none';
|
||||
props.anchorElement.style.pointerEvents = 'none';
|
||||
}
|
||||
fixed.value = (type.value === 'drawer') || (getFixedContainer(props.src) != null);
|
||||
fixed.value = (type.value === 'drawer') || (getFixedContainer(props.anchorElement) != null);
|
||||
|
||||
await nextTick();
|
||||
|
||||
@@ -339,7 +339,7 @@ onMounted(() => {
|
||||
}
|
||||
} else {
|
||||
releaseFocusTrap?.();
|
||||
focusParent(props.returnFocusTo ?? props.src, true, false);
|
||||
focusParent(props.returnFocusTo ?? props.anchorElement, true, false);
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<MkModal ref="modal" v-slot="{ type, maxHeight }" :manualShowing="manualShowing" :zPriority="'high'" :src="src" :transparentBg="true" :returnFocusTo="returnFocusTo" @click="click" @close="onModalClose" @closed="onModalClosed">
|
||||
<MkModal ref="modal" v-slot="{ type, maxHeight }" :manualShowing="manualShowing" :zPriority="'high'" :anchorElement="anchorElement" :transparentBg="true" :returnFocusTo="returnFocusTo" @click="click" @close="onModalClose" @closed="onModalClosed">
|
||||
<MkMenu :items="items" :align="align" :width="width" :max-height="maxHeight" :asDrawer="type === 'drawer'" :returnFocusTo="returnFocusTo" :class="{ [$style.drawer]: type === 'drawer' }" @close="onMenuClose" @hide="hide"/>
|
||||
</MkModal>
|
||||
</template>
|
||||
@@ -19,7 +19,7 @@ defineProps<{
|
||||
items: MenuItem[];
|
||||
align?: 'center' | string;
|
||||
width?: number;
|
||||
src?: HTMLElement | null;
|
||||
anchorElement?: HTMLElement | null;
|
||||
returnFocusTo?: HTMLElement | null;
|
||||
}>();
|
||||
|
||||
|
||||
@@ -470,7 +470,7 @@ function setVisibility() {
|
||||
currentVisibility: visibility.value,
|
||||
isSilenced: $i.isSilenced,
|
||||
localOnly: localOnly.value,
|
||||
src: visibilityButton.value,
|
||||
anchorElement: visibilityButton.value,
|
||||
...(props.reply ? { isReplyVisibilitySpecified: props.reply.visibility === 'specified' } : {}),
|
||||
}, {
|
||||
changeVisibility: v => {
|
||||
|
||||
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<MkModal ref="modal" v-slot="{ type }" :zPriority="'high'" :src="src" @click="modal?.close()" @closed="emit('closed')" @esc="modal?.close()">
|
||||
<MkModal ref="modal" v-slot="{ type }" :zPriority="'high'" :anchorElement="anchorElement" @click="modal?.close()" @closed="emit('closed')" @esc="modal?.close()">
|
||||
<div class="_popup" :class="{ [$style.root]: true, [$style.asDrawer]: type === 'drawer' }">
|
||||
<div :class="[$style.label, $style.item]">
|
||||
{{ i18n.ts.visibility }}
|
||||
@@ -53,7 +53,7 @@ const props = withDefaults(defineProps<{
|
||||
currentVisibility: typeof Misskey.noteVisibilities[number];
|
||||
isSilenced: boolean;
|
||||
localOnly: boolean;
|
||||
src?: HTMLElement;
|
||||
anchorElement?: HTMLElement;
|
||||
isReplyVisibilitySpecified?: boolean;
|
||||
}>(), {
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user