refactor(frontend): src -> anchorElement
This commit is contained in:
parent
aa55663ef7
commit
74c857e23d
|
@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:hasInteractionWithOtherFocusTrappedEls="true"
|
:hasInteractionWithOtherFocusTrappedEls="true"
|
||||||
:transparentBg="true"
|
:transparentBg="true"
|
||||||
:manualShowing="manualShowing"
|
:manualShowing="manualShowing"
|
||||||
:src="src"
|
:anchorElement="anchorElement"
|
||||||
@click="modal?.close()"
|
@click="modal?.close()"
|
||||||
@esc="modal?.close()"
|
@esc="modal?.close()"
|
||||||
@opening="opening"
|
@opening="opening"
|
||||||
|
@ -44,7 +44,7 @@ import { prefer } from '@/preferences.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
manualShowing?: boolean | null;
|
manualShowing?: boolean | null;
|
||||||
src?: HTMLElement;
|
anchorElement?: HTMLElement;
|
||||||
showPinned?: boolean;
|
showPinned?: boolean;
|
||||||
pinnedEmojis?: string[],
|
pinnedEmojis?: string[],
|
||||||
asReactionPicker?: boolean;
|
asReactionPicker?: boolean;
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<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="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<template v-for="item in items" :key="item.text">
|
<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';
|
import { prefer } from '@/preferences.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
src?: HTMLElement;
|
anchorElement?: HTMLElement;
|
||||||
anchor?: { x: string; y: string; };
|
anchor?: { x: string; y: string; };
|
||||||
}>(), {
|
}>(), {
|
||||||
anchor: () => ({ x: 'right', y: 'center' }),
|
anchor: () => ({ x: 'right', y: 'center' }),
|
||||||
|
@ -44,7 +44,7 @@ const emit = defineEmits<{
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
|
const preferedModalType = (deviceKind === 'desktop' && props.anchorElement != null) ? 'popup' :
|
||||||
deviceKind === 'smartphone' ? 'drawer' :
|
deviceKind === 'smartphone' ? 'drawer' :
|
||||||
'dialog';
|
'dialog';
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ type ModalTypes = 'popup' | 'dialog' | 'drawer';
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
manualShowing?: boolean | null;
|
manualShowing?: boolean | null;
|
||||||
anchor?: { x: string; y: string; };
|
anchor?: { x: string; y: string; };
|
||||||
src?: HTMLElement | null;
|
anchorElement?: HTMLElement | null;
|
||||||
preferType?: ModalTypes | 'auto';
|
preferType?: ModalTypes | 'auto';
|
||||||
zPriority?: 'low' | 'middle' | 'high';
|
zPriority?: 'low' | 'middle' | 'high';
|
||||||
noOverlap?: boolean;
|
noOverlap?: boolean;
|
||||||
|
@ -76,7 +76,7 @@ const props = withDefaults(defineProps<{
|
||||||
returnFocusTo?: HTMLElement | null;
|
returnFocusTo?: HTMLElement | null;
|
||||||
}>(), {
|
}>(), {
|
||||||
manualShowing: null,
|
manualShowing: null,
|
||||||
src: null,
|
anchorElement: null,
|
||||||
anchor: () => ({ x: 'center', y: 'bottom' }),
|
anchor: () => ({ x: 'center', y: 'bottom' }),
|
||||||
preferType: 'auto',
|
preferType: 'auto',
|
||||||
zPriority: 'low',
|
zPriority: 'low',
|
||||||
|
@ -110,7 +110,7 @@ const type = computed<ModalTypes>(() => {
|
||||||
if ((prefer.s.menuStyle === 'drawer') || (prefer.s.menuStyle === 'auto' && isTouchUsing && deviceKind === 'smartphone')) {
|
if ((prefer.s.menuStyle === 'drawer') || (prefer.s.menuStyle === 'auto' && isTouchUsing && deviceKind === 'smartphone')) {
|
||||||
return 'drawer';
|
return 'drawer';
|
||||||
} else {
|
} else {
|
||||||
return props.src != null ? 'popup' : 'dialog';
|
return props.anchorElement != null ? 'popup' : 'dialog';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return props.preferType!;
|
return props.preferType!;
|
||||||
|
@ -149,7 +149,7 @@ function close(opts: { useSendAnimation?: boolean } = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-mutating-props
|
// 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;
|
showing.value = false;
|
||||||
emit('close');
|
emit('close');
|
||||||
}
|
}
|
||||||
|
@ -174,13 +174,13 @@ const MARGIN = 16;
|
||||||
const SCROLLBAR_THICKNESS = 16;
|
const SCROLLBAR_THICKNESS = 16;
|
||||||
|
|
||||||
const align = () => {
|
const align = () => {
|
||||||
if (props.src == null) return;
|
if (props.anchorElement == null) return;
|
||||||
if (type.value === 'drawer') return;
|
if (type.value === 'drawer') return;
|
||||||
if (type.value === 'dialog') return;
|
if (type.value === 'dialog') return;
|
||||||
|
|
||||||
if (content.value == null) return;
|
if (content.value == null) return;
|
||||||
|
|
||||||
const srcRect = props.src.getBoundingClientRect();
|
const anchorRect = props.anchorElement.getBoundingClientRect();
|
||||||
|
|
||||||
const width = content.value!.offsetWidth;
|
const width = content.value!.offsetWidth;
|
||||||
const height = content.value!.offsetHeight;
|
const height = content.value!.offsetHeight;
|
||||||
|
@ -188,15 +188,15 @@ const align = () => {
|
||||||
let left;
|
let left;
|
||||||
let top;
|
let top;
|
||||||
|
|
||||||
const x = srcRect.left + (fixed.value ? 0 : window.scrollX);
|
const x = anchorRect.left + (fixed.value ? 0 : window.scrollX);
|
||||||
const y = srcRect.top + (fixed.value ? 0 : window.scrollY);
|
const y = anchorRect.top + (fixed.value ? 0 : window.scrollY);
|
||||||
|
|
||||||
if (props.anchor.x === 'center') {
|
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') {
|
} else if (props.anchor.x === 'left') {
|
||||||
// TODO
|
// TODO
|
||||||
} else if (props.anchor.x === 'right') {
|
} else if (props.anchor.x === 'right') {
|
||||||
left = x + props.src.offsetWidth;
|
left = x + props.anchorElement.offsetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.anchor.y === 'center') {
|
if (props.anchor.y === 'center') {
|
||||||
|
@ -204,7 +204,7 @@ const align = () => {
|
||||||
} else if (props.anchor.y === 'top') {
|
} else if (props.anchor.y === 'top') {
|
||||||
// TODO
|
// TODO
|
||||||
} else if (props.anchor.y === 'bottom') {
|
} else if (props.anchor.y === 'bottom') {
|
||||||
top = y + props.src.offsetHeight;
|
top = y + props.anchorElement.offsetHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixed.value) {
|
if (fixed.value) {
|
||||||
|
@ -214,7 +214,7 @@ const align = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top;
|
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)) {
|
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 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)) {
|
if (top + height - window.scrollY > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
|
||||||
|
@ -268,15 +268,15 @@ const align = () => {
|
||||||
let transformOriginX = 'center';
|
let transformOriginX = 'center';
|
||||||
let transformOriginY = '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';
|
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';
|
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';
|
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';
|
transformOriginX = 'right';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,12 +317,12 @@ const alignObserver = new ResizeObserver((entries, observer) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
watch(() => props.src, async () => {
|
watch(() => props.anchorElement, async () => {
|
||||||
if (props.src) {
|
if (props.anchorElement) {
|
||||||
// eslint-disable-next-line vue/no-mutating-props
|
// 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();
|
await nextTick();
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
releaseFocusTrap?.();
|
releaseFocusTrap?.();
|
||||||
focusParent(props.returnFocusTo ?? props.src, true, false);
|
focusParent(props.returnFocusTo ?? props.anchorElement, true, false);
|
||||||
}
|
}
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<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"/>
|
<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>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -19,7 +19,7 @@ defineProps<{
|
||||||
items: MenuItem[];
|
items: MenuItem[];
|
||||||
align?: 'center' | string;
|
align?: 'center' | string;
|
||||||
width?: number;
|
width?: number;
|
||||||
src?: HTMLElement | null;
|
anchorElement?: HTMLElement | null;
|
||||||
returnFocusTo?: HTMLElement | null;
|
returnFocusTo?: HTMLElement | null;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
|
@ -470,7 +470,7 @@ function setVisibility() {
|
||||||
currentVisibility: visibility.value,
|
currentVisibility: visibility.value,
|
||||||
isSilenced: $i.isSilenced,
|
isSilenced: $i.isSilenced,
|
||||||
localOnly: localOnly.value,
|
localOnly: localOnly.value,
|
||||||
src: visibilityButton.value,
|
anchorElement: visibilityButton.value,
|
||||||
...(props.reply ? { isReplyVisibilitySpecified: props.reply.visibility === 'specified' } : {}),
|
...(props.reply ? { isReplyVisibilitySpecified: props.reply.visibility === 'specified' } : {}),
|
||||||
}, {
|
}, {
|
||||||
changeVisibility: v => {
|
changeVisibility: v => {
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<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="_popup" :class="{ [$style.root]: true, [$style.asDrawer]: type === 'drawer' }">
|
||||||
<div :class="[$style.label, $style.item]">
|
<div :class="[$style.label, $style.item]">
|
||||||
{{ i18n.ts.visibility }}
|
{{ i18n.ts.visibility }}
|
||||||
|
@ -53,7 +53,7 @@ const props = withDefaults(defineProps<{
|
||||||
currentVisibility: typeof Misskey.noteVisibilities[number];
|
currentVisibility: typeof Misskey.noteVisibilities[number];
|
||||||
isSilenced: boolean;
|
isSilenced: boolean;
|
||||||
localOnly: boolean;
|
localOnly: boolean;
|
||||||
src?: HTMLElement;
|
anchorElement?: HTMLElement;
|
||||||
isReplyVisibilitySpecified?: boolean;
|
isReplyVisibilitySpecified?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
});
|
});
|
||||||
|
|
|
@ -609,10 +609,10 @@ export async function selectRole(params: ComponentProps<typeof MkRoleSelectDialo
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog_TypeReferenceOnly>): Promise<string> {
|
export async function pickEmoji(anchorElement: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog_TypeReferenceOnly>): Promise<string> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
||||||
src,
|
anchorElement,
|
||||||
...opts,
|
...opts,
|
||||||
}, {
|
}, {
|
||||||
done: emoji => {
|
done: emoji => {
|
||||||
|
@ -639,20 +639,20 @@ export async function cropImageFile(imageFile: File | Blob, options: {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | null, options?: {
|
export function popupMenu(items: MenuItem[], anchorElement?: HTMLElement | EventTarget | null, options?: {
|
||||||
align?: string;
|
align?: string;
|
||||||
width?: number;
|
width?: number;
|
||||||
onClosing?: () => void;
|
onClosing?: () => void;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
if (!(src instanceof HTMLElement)) {
|
if (!(anchorElement instanceof HTMLElement)) {
|
||||||
src = null;
|
anchorElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let returnFocusTo = getHTMLElementOrNull(src) ?? getHTMLElementOrNull(window.document.activeElement);
|
let returnFocusTo = getHTMLElementOrNull(anchorElement) ?? getHTMLElementOrNull(window.document.activeElement);
|
||||||
return new Promise(resolve => nextTick(() => {
|
return new Promise(resolve => nextTick(() => {
|
||||||
const { dispose } = popup(MkPopupMenu, {
|
const { dispose } = popup(MkPopupMenu, {
|
||||||
items,
|
items,
|
||||||
src,
|
anchorElement,
|
||||||
width: options?.width,
|
width: options?.width,
|
||||||
align: options?.align,
|
align: options?.align,
|
||||||
returnFocusTo,
|
returnFocusTo,
|
||||||
|
|
|
@ -73,7 +73,7 @@ const otherNavItemIndicated = computed<boolean>(() => {
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
anchorElement: ev.currentTarget ?? ev.target,
|
||||||
anchor: { x: 'center', y: 'bottom' },
|
anchor: { x: 'center', y: 'bottom' },
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -180,7 +180,7 @@ function more(ev: MouseEvent) {
|
||||||
const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target);
|
const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: target,
|
anchorElement: target,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -197,7 +197,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(src: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
function select(anchorElement: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
os.popupMenu([label ? {
|
os.popupMenu([label ? {
|
||||||
text: label,
|
text: label,
|
||||||
|
@ -214,16 +214,16 @@ function select(src: HTMLElement | EventTarget | null, label: string | null, mul
|
||||||
text: i18n.ts.fromUrl,
|
text: i18n.ts.fromUrl,
|
||||||
icon: 'ti ti-link',
|
icon: 'ti ti-link',
|
||||||
action: () => chooseFileFromUrl().then(file => res([file])),
|
action: () => chooseFileFromUrl().then(file => res([file])),
|
||||||
}], src);
|
}], anchorElement);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectFile(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile> {
|
export function selectFile(anchorElement: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile> {
|
||||||
return select(src, label, false).then(files => files[0]);
|
return select(anchorElement, label, false).then(files => files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectFiles(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
|
export function selectFiles(anchorElement: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return select(src, label, true);
|
return select(anchorElement, label, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createCroppedImageDriveFileFromImageDriveFile(imageDriveFile: Misskey.entities.DriveFile, options: {
|
export async function createCroppedImageDriveFileFromImageDriveFile(imageDriveFile: Misskey.entities.DriveFile, options: {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { prefer } from '@/preferences.js';
|
||||||
* 一度表示したダイアログを連続で使用できることが望ましいシーンでの利用が想定される。
|
* 一度表示したダイアログを連続で使用できることが望ましいシーンでの利用が想定される。
|
||||||
*/
|
*/
|
||||||
class EmojiPicker {
|
class EmojiPicker {
|
||||||
private src: Ref<HTMLElement | null> = ref(null);
|
private anchorElement: Ref<HTMLElement | null> = ref(null);
|
||||||
private manualShowing = ref(false);
|
private manualShowing = ref(false);
|
||||||
private onChosen?: (emoji: string) => void;
|
private onChosen?: (emoji: string) => void;
|
||||||
private onClosed?: () => void;
|
private onClosed?: () => void;
|
||||||
|
@ -34,7 +34,7 @@ class EmojiPicker {
|
||||||
});
|
});
|
||||||
|
|
||||||
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
||||||
src: this.src,
|
anchorElement: this.anchorElement,
|
||||||
pinnedEmojis: emojisRef,
|
pinnedEmojis: emojisRef,
|
||||||
asReactionPicker: false,
|
asReactionPicker: false,
|
||||||
manualShowing: this.manualShowing,
|
manualShowing: this.manualShowing,
|
||||||
|
@ -47,18 +47,18 @@ class EmojiPicker {
|
||||||
this.manualShowing.value = false;
|
this.manualShowing.value = false;
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
this.src.value = null;
|
this.anchorElement.value = null;
|
||||||
if (this.onClosed) this.onClosed();
|
if (this.onClosed) this.onClosed();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public show(
|
public show(
|
||||||
src: HTMLElement,
|
anchorElement: HTMLElement,
|
||||||
onChosen?: EmojiPicker['onChosen'],
|
onChosen?: EmojiPicker['onChosen'],
|
||||||
onClosed?: EmojiPicker['onClosed'],
|
onClosed?: EmojiPicker['onClosed'],
|
||||||
) {
|
) {
|
||||||
this.src.value = src;
|
this.anchorElement.value = anchorElement;
|
||||||
this.manualShowing.value = true;
|
this.manualShowing.value = true;
|
||||||
this.onChosen = onChosen;
|
this.onChosen = onChosen;
|
||||||
this.onClosed = onClosed;
|
this.onClosed = onClosed;
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
import { MFM_TAGS } from '@@/js/const.js';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { MFM_TAGS } from '@@/js/const.js';
|
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MFMの装飾のリストを表示する
|
* MFMの装飾のリストを表示する
|
||||||
*/
|
*/
|
||||||
export function mfmFunctionPicker(src: HTMLElement | EventTarget | null, textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>) {
|
export function mfmFunctionPicker(anchorElement: HTMLElement | EventTarget | null, textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
text: i18n.ts.addMfmFunction,
|
text: i18n.ts.addMfmFunction,
|
||||||
type: 'label',
|
type: 'label',
|
||||||
}, ...getFunctionList(textArea, textRef)], src);
|
}, ...getFunctionList(textArea, textRef)], anchorElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFunctionList(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>): MenuItem[] {
|
function getFunctionList(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>): MenuItem[] {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { popup } from '@/os.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
|
||||||
class ReactionPicker {
|
class ReactionPicker {
|
||||||
private src: Ref<HTMLElement | null> = ref(null);
|
private anchorElement: Ref<HTMLElement | null> = ref(null);
|
||||||
private manualShowing = ref(false);
|
private manualShowing = ref(false);
|
||||||
private targetNote: Ref<Misskey.entities.Note | null> = ref(null);
|
private targetNote: Ref<Misskey.entities.Note | null> = ref(null);
|
||||||
private onChosen?: (reaction: string) => void;
|
private onChosen?: (reaction: string) => void;
|
||||||
|
@ -30,7 +30,7 @@ class ReactionPicker {
|
||||||
});
|
});
|
||||||
|
|
||||||
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
|
||||||
src: this.src,
|
anchorElement: this.anchorElement,
|
||||||
pinnedEmojis: reactionsRef,
|
pinnedEmojis: reactionsRef,
|
||||||
asReactionPicker: true,
|
asReactionPicker: true,
|
||||||
targetNote: this.targetNote,
|
targetNote: this.targetNote,
|
||||||
|
@ -43,14 +43,14 @@ class ReactionPicker {
|
||||||
this.manualShowing.value = false;
|
this.manualShowing.value = false;
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
this.src.value = null;
|
this.anchorElement.value = null;
|
||||||
if (this.onClosed) this.onClosed();
|
if (this.onClosed) this.onClosed();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public show(src: HTMLElement | null, targetNote: Misskey.entities.Note | null, onChosen?: ReactionPicker['onChosen'], onClosed?: ReactionPicker['onClosed']) {
|
public show(anchorElement: HTMLElement | null, targetNote: Misskey.entities.Note | null, onChosen?: ReactionPicker['onChosen'], onClosed?: ReactionPicker['onClosed']) {
|
||||||
this.src.value = src;
|
this.anchorElement.value = anchorElement;
|
||||||
this.targetNote.value = targetNote;
|
this.targetNote.value = targetNote;
|
||||||
this.manualShowing.value = true;
|
this.manualShowing.value = true;
|
||||||
this.onChosen = onChosen;
|
this.onChosen = onChosen;
|
||||||
|
|
Loading…
Reference in New Issue