fix types of component
This commit is contained in:
parent
f3b189a70c
commit
5da03666b2
12 changed files with 68 additions and 45 deletions
|
@ -21,7 +21,8 @@
|
||||||
"useImportType": "warn",
|
"useImportType": "warn",
|
||||||
"useShorthandFunctionType": "warn",
|
"useShorthandFunctionType": "warn",
|
||||||
"useTemplate": "warn",
|
"useTemplate": "warn",
|
||||||
"noNonNullAssertion": "off"
|
"noNonNullAssertion": "off",
|
||||||
|
"useNodejsImportProtocol": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,12 +181,15 @@ function describe() {
|
||||||
image: props.file,
|
image: props.file,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
done: (result) => {
|
done: (result: {
|
||||||
|
canceled: boolean,
|
||||||
|
result?: string | null,
|
||||||
|
}) => {
|
||||||
if (!result || result.canceled) return;
|
if (!result || result.canceled) return;
|
||||||
const comment = result.result;
|
const comment = result.result;
|
||||||
os.api("drive/files/update", {
|
os.api("drive/files/update", {
|
||||||
fileId: props.file.id,
|
fileId: props.file.id,
|
||||||
comment: comment.length === 0 ? null : comment,
|
comment: comment || null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,7 +73,10 @@ import { deviceKind } from "@/scripts/device-kind";
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
src?: HTMLElement;
|
src?: HTMLElement;
|
||||||
anchor?: { x: string; y: string };
|
anchor?: {
|
||||||
|
x: "left" | "center" | "right";
|
||||||
|
y: "top" | "center" | "bottom";
|
||||||
|
};
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
anchor: () => ({ x: "right", y: "center" }),
|
anchor: () => ({ x: "right", y: "center" }),
|
||||||
|
|
|
@ -100,7 +100,7 @@ const props = withDefaults(
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
done: [v: { canceled: boolean; result?: string | null }];
|
done: [result: { canceled: boolean; result?: string | null }];
|
||||||
closed: [];
|
closed: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
media.type.startsWith('video') ||
|
media.type.startsWith('video') ||
|
||||||
media.type.startsWith('image')
|
media.type.startsWith('image')
|
||||||
"
|
"
|
||||||
:key="media.id"
|
:key="`m-${media.id}`"
|
||||||
:class="{ image: media.type.startsWith('image') }"
|
:class="{ image: media.type.startsWith('image') }"
|
||||||
:data-id="media.id"
|
:data-id="media.id"
|
||||||
:media="media"
|
:media="media"
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
/>
|
/>
|
||||||
<XModPlayer
|
<XModPlayer
|
||||||
v-else-if="isModule(media)"
|
v-else-if="isModule(media)"
|
||||||
:key="media.id"
|
:key="`p-${media.id}`"
|
||||||
:module="media"
|
:module="media"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -48,7 +48,7 @@ import "photoswipe/style.css";
|
||||||
import XBanner from "@/components/MkMediaBanner.vue";
|
import XBanner from "@/components/MkMediaBanner.vue";
|
||||||
import XMedia from "@/components/MkMedia.vue";
|
import XMedia from "@/components/MkMedia.vue";
|
||||||
import XModPlayer from "@/components/MkModPlayer.vue";
|
import XModPlayer from "@/components/MkModPlayer.vue";
|
||||||
import * as os from "@/os";
|
// import * as os from "@/os";
|
||||||
import {
|
import {
|
||||||
FILE_EXT_TRACKER_MODULES,
|
FILE_EXT_TRACKER_MODULES,
|
||||||
FILE_TYPE_BROWSERSAFE,
|
FILE_TYPE_BROWSERSAFE,
|
||||||
|
@ -61,8 +61,8 @@ const props = defineProps<{
|
||||||
inDm?: boolean;
|
inDm?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const gallery = ref(null);
|
const gallery = ref<HTMLElement | null>(null);
|
||||||
const pswpZIndex = os.claimZIndex("middle");
|
// const pswpZIndex = os.claimZIndex("middle");
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const lightbox = new PhotoSwipeLightbox({
|
const lightbox = new PhotoSwipeLightbox({
|
||||||
|
@ -79,7 +79,7 @@ onMounted(() => {
|
||||||
src: media.url,
|
src: media.url,
|
||||||
w: media.properties.width,
|
w: media.properties.width,
|
||||||
h: media.properties.height,
|
h: media.properties.height,
|
||||||
alt: media.comment,
|
alt: media.comment || undefined,
|
||||||
};
|
};
|
||||||
if (
|
if (
|
||||||
media.properties.orientation != null &&
|
media.properties.orientation != null &&
|
||||||
|
@ -89,7 +89,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}),
|
}),
|
||||||
gallery: gallery.value,
|
gallery: gallery.value || undefined,
|
||||||
children: ".image",
|
children: ".image",
|
||||||
thumbSelector: ".image img",
|
thumbSelector: ".image img",
|
||||||
loop: false,
|
loop: false,
|
||||||
|
@ -119,9 +119,13 @@ onMounted(() => {
|
||||||
// element is children
|
// element is children
|
||||||
const { element } = itemData;
|
const { element } = itemData;
|
||||||
|
|
||||||
|
if (element == null) return;
|
||||||
|
|
||||||
const id = element.dataset.id;
|
const id = element.dataset.id;
|
||||||
const file = props.mediaList.find((media) => media.id === id);
|
const file = props.mediaList.find((media) => media.id === id);
|
||||||
|
|
||||||
|
if (file == null) return;
|
||||||
|
|
||||||
itemData.src = file.url;
|
itemData.src = file.url;
|
||||||
itemData.w = Number(file.properties.width);
|
itemData.w = Number(file.properties.width);
|
||||||
itemData.h = Number(file.properties.height);
|
itemData.h = Number(file.properties.height);
|
||||||
|
@ -132,12 +136,12 @@ onMounted(() => {
|
||||||
[itemData.w, itemData.h] = [itemData.h, itemData.w];
|
[itemData.w, itemData.h] = [itemData.h, itemData.w];
|
||||||
}
|
}
|
||||||
itemData.msrc = file.thumbnailUrl;
|
itemData.msrc = file.thumbnailUrl;
|
||||||
itemData.alt = file.comment;
|
itemData.alt = file.comment || undefined;
|
||||||
itemData.thumbCropped = true;
|
itemData.thumbCropped = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
lightbox.on("uiRegister", () => {
|
lightbox.on("uiRegister", () => {
|
||||||
lightbox.pswp.ui.registerElement({
|
lightbox.pswp?.ui?.registerElement({
|
||||||
name: "altText",
|
name: "altText",
|
||||||
className: "pwsp__alt-text-container",
|
className: "pwsp__alt-text-container",
|
||||||
appendTo: "wrapper",
|
appendTo: "wrapper",
|
||||||
|
@ -146,7 +150,7 @@ onMounted(() => {
|
||||||
textBox.className = "pwsp__alt-text";
|
textBox.className = "pwsp__alt-text";
|
||||||
el.appendChild(textBox);
|
el.appendChild(textBox);
|
||||||
|
|
||||||
const preventProp = function (ev: Event): void {
|
const preventProp = (ev: Event): void => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,7 +162,7 @@ onMounted(() => {
|
||||||
el.onpointermove = preventProp;
|
el.onpointermove = preventProp;
|
||||||
|
|
||||||
pwsp.on("change", () => {
|
pwsp.on("change", () => {
|
||||||
textBox.textContent = pwsp.currSlide.data.alt?.trim();
|
textBox.textContent = pwsp.currSlide?.data.alt?.trim() ?? null;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -168,7 +172,7 @@ onMounted(() => {
|
||||||
history.pushState(null, "", location.href);
|
history.pushState(null, "", location.href);
|
||||||
addEventListener("popstate", close);
|
addEventListener("popstate", close);
|
||||||
// This is a workaround. Not sure why, but when clicking to open, it doesn't move focus to the photoswipe. Preventing using esc to close. However when using keyboard to open it already focuses the lightbox fine.
|
// This is a workaround. Not sure why, but when clicking to open, it doesn't move focus to the photoswipe. Preventing using esc to close. However when using keyboard to open it already focuses the lightbox fine.
|
||||||
lightbox.pswp.element.focus();
|
lightbox.pswp?.element?.focus();
|
||||||
});
|
});
|
||||||
lightbox.on("close", () => {
|
lightbox.on("close", () => {
|
||||||
removeEventListener("popstate", close);
|
removeEventListener("popstate", close);
|
||||||
|
@ -180,7 +184,7 @@ onMounted(() => {
|
||||||
function close() {
|
function close() {
|
||||||
removeEventListener("popstate", close);
|
removeEventListener("popstate", close);
|
||||||
history.forward();
|
history.forward();
|
||||||
lightbox.pswp.close();
|
lightbox.pswp?.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -198,7 +202,7 @@ const isModule = (file: entities.DriveFile): boolean => {
|
||||||
return (
|
return (
|
||||||
FILE_TYPE_TRACKER_MODULES.includes(file.type) ||
|
FILE_TYPE_TRACKER_MODULES.includes(file.type) ||
|
||||||
FILE_EXT_TRACKER_MODULES.some((ext) => {
|
FILE_EXT_TRACKER_MODULES.some((ext) => {
|
||||||
return file.name.toLowerCase().endsWith("." + ext);
|
return file.name.toLowerCase().endsWith(`.${ext}`);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
:href="url"
|
:href="url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
:style="{ background: bgCss }"
|
|
||||||
@click.stop
|
@click.stop
|
||||||
>
|
>
|
||||||
<span class="main">
|
<span class="main">
|
||||||
|
@ -54,7 +53,7 @@ const url = `/${canonical}`;
|
||||||
const isMe =
|
const isMe =
|
||||||
isSignedIn &&
|
isSignedIn &&
|
||||||
`@${props.username}@${toUnicode(props.host)}`.toLowerCase() ===
|
`@${props.username}@${toUnicode(props.host)}`.toLowerCase() ===
|
||||||
`@${me.username}@${toUnicode(localHost)}`.toLowerCase();
|
`@${me!.username}@${toUnicode(localHost)}`.toLowerCase();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -37,8 +37,8 @@ function setPosition() {
|
||||||
const rect = props.targetElement.getBoundingClientRect();
|
const rect = props.targetElement.getBoundingClientRect();
|
||||||
const left = props.targetElement.offsetWidth;
|
const left = props.targetElement.offsetWidth;
|
||||||
const top = rect.top - rootRect.top - 8;
|
const top = rect.top - rootRect.top - 8;
|
||||||
el.value.style.left = left + "px";
|
el.value!.style.left = `${left}px`;
|
||||||
el.value.style.top = top + "px";
|
el.value!.style.top = `${top}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChildClosed(actioned?: boolean) {
|
function onChildClosed(actioned?: boolean) {
|
||||||
|
@ -58,7 +58,7 @@ onMounted(() => {
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
checkHit: (ev: MouseEvent) => {
|
checkHit: (ev: MouseEvent) => {
|
||||||
return ev.target === el.value || el.value.contains(ev.target);
|
return ev.target === el.value || el.value?.contains(ev.target as Node);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -89,7 +89,8 @@
|
||||||
></span>
|
></span>
|
||||||
</a>
|
</a>
|
||||||
<button
|
<button
|
||||||
v-else-if="item.type === 'user' && !items.hidden"
|
v-else-if="item.type === 'user'"
|
||||||
|
v-show="!item.hidden"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
:class="{ active: item.active }"
|
:class="{ active: item.active }"
|
||||||
:disabled="item.active"
|
:disabled="item.active"
|
||||||
|
@ -206,6 +207,7 @@ import {
|
||||||
onMounted,
|
onMounted,
|
||||||
ref,
|
ref,
|
||||||
watch,
|
watch,
|
||||||
|
shallowRef,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { FocusTrap } from "focus-trap-vue";
|
import { FocusTrap } from "focus-trap-vue";
|
||||||
import FormSwitch from "@/components/form/switch.vue";
|
import FormSwitch from "@/components/form/switch.vue";
|
||||||
|
@ -213,6 +215,7 @@ import type {
|
||||||
InnerMenuItem,
|
InnerMenuItem,
|
||||||
MenuAction,
|
MenuAction,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
|
MenuParent,
|
||||||
MenuPending,
|
MenuPending,
|
||||||
} from "@/types/menu";
|
} from "@/types/menu";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
|
@ -234,20 +237,24 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: "close", actioned?: boolean): void;
|
close: [actioned?: boolean];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const itemsEl = ref<HTMLDivElement>();
|
const itemsEl = ref<HTMLDivElement>();
|
||||||
|
|
||||||
const items2: InnerMenuItem[] = ref([]);
|
const items2 = shallowRef<InnerMenuItem[]>([]);
|
||||||
|
|
||||||
const child = ref<InstanceType<typeof XChild>>();
|
const child = ref<InstanceType<typeof XChild>>();
|
||||||
|
|
||||||
const childShowingItem = ref<MenuItem | null>();
|
const childShowingItem = ref<MenuItem | null>();
|
||||||
|
|
||||||
|
// FIXME: this is not used
|
||||||
|
const isActive = ref();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.items,
|
() => props.items,
|
||||||
() => {
|
() => {
|
||||||
|
// FIXME: what's this?
|
||||||
const items: (MenuItem | MenuPending)[] = [...props.items].filter(
|
const items: (MenuItem | MenuPending)[] = [...props.items].filter(
|
||||||
(item) => item !== undefined,
|
(item) => item !== undefined,
|
||||||
);
|
);
|
||||||
|
@ -288,29 +295,29 @@ function onGlobalMousedown(event: MouseEvent) {
|
||||||
if (
|
if (
|
||||||
childTarget.value &&
|
childTarget.value &&
|
||||||
(event.target === childTarget.value ||
|
(event.target === childTarget.value ||
|
||||||
childTarget.value.contains(event.target))
|
childTarget.value.contains(event.target as Node))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
if (child.value && child.value.checkHit(event)) return;
|
if (child.value?.checkHit(event)) return;
|
||||||
closeChild();
|
closeChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
let childCloseTimer: null | number = null;
|
let childCloseTimer: null | number = null;
|
||||||
function onItemMouseEnter(item) {
|
function onItemMouseEnter(_item) {
|
||||||
childCloseTimer = window.setTimeout(() => {
|
childCloseTimer = window.setTimeout(() => {
|
||||||
closeChild();
|
closeChild();
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
function onItemMouseLeave(item) {
|
function onItemMouseLeave(_item) {
|
||||||
if (childCloseTimer) window.clearTimeout(childCloseTimer);
|
if (childCloseTimer) window.clearTimeout(childCloseTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showChildren(item: MenuItem, ev: MouseEvent) {
|
async function showChildren(item: MenuParent, ev: MouseEvent) {
|
||||||
if (props.asDrawer) {
|
if (props.asDrawer) {
|
||||||
os.popupMenu(item.children, ev.currentTarget ?? ev.target);
|
os.popupMenu(item.children, (ev.currentTarget ?? ev.target) as HTMLElement);
|
||||||
close();
|
close();
|
||||||
} else {
|
} else {
|
||||||
childTarget.value = ev.currentTarget ?? ev.target;
|
childTarget.value = (ev.currentTarget ?? ev.target) as HTMLElement;
|
||||||
childMenu.value = item.children;
|
childMenu.value = item.children;
|
||||||
childShowingItem.value = item;
|
childShowingItem.value = item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
:stroke="color"
|
:stroke="color"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
/>
|
/>
|
||||||
<circle :cx="headX" :cy="headY" r="3" :fill="color" />
|
<circle :cx="headX ?? undefined" :cy="headY ?? undefined" r="3" :fill="color" />
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,11 @@ type ModalTypes = "popup" | "dialog" | "dialog:top" | "drawer";
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
manualShowing?: boolean | null;
|
manualShowing?: boolean | null;
|
||||||
anchor?: { x: string; y: string };
|
anchor?: {
|
||||||
src?: HTMLElement;
|
x: "left" | "center" | "right";
|
||||||
|
y: "top" | "center" | "bottom";
|
||||||
|
};
|
||||||
|
src?: HTMLElement | null;
|
||||||
preferType?: ModalTypes | "auto";
|
preferType?: ModalTypes | "auto";
|
||||||
zPriority?: "low" | "middle" | "high";
|
zPriority?: "low" | "middle" | "high";
|
||||||
noOverlap?: boolean;
|
noOverlap?: boolean;
|
||||||
|
@ -118,7 +121,7 @@ const props = withDefaults(
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
manualShowing: null,
|
manualShowing: null,
|
||||||
src: undefined,
|
src: null,
|
||||||
anchor: () => ({ x: "center", y: "bottom" }),
|
anchor: () => ({ x: "center", y: "bottom" }),
|
||||||
preferType: "auto",
|
preferType: "auto",
|
||||||
zPriority: "low",
|
zPriority: "low",
|
||||||
|
@ -139,6 +142,9 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
provide("modal", true);
|
provide("modal", true);
|
||||||
|
|
||||||
|
// FIXME: this may not used
|
||||||
|
const isActive = ref();
|
||||||
|
|
||||||
const maxHeight = ref<number>();
|
const maxHeight = ref<number>();
|
||||||
const fixed = ref(false);
|
const fixed = ref(false);
|
||||||
const transformOrigin = ref("center");
|
const transformOrigin = ref("center");
|
||||||
|
@ -189,7 +195,7 @@ const transitionDuration = computed(() =>
|
||||||
|
|
||||||
let contentClicking = false;
|
let contentClicking = false;
|
||||||
|
|
||||||
const focusedElement = document.activeElement;
|
const focusedElement = document.activeElement as HTMLElement;
|
||||||
function close(_ev?, opts: { useSendAnimation?: boolean } = {}) {
|
function close(_ev?, opts: { useSendAnimation?: boolean } = {}) {
|
||||||
// removeEventListener("popstate", close);
|
// removeEventListener("popstate", close);
|
||||||
// if (props.preferType == "dialog") {
|
// if (props.preferType == "dialog") {
|
||||||
|
@ -204,7 +210,7 @@ function close(_ev?, opts: { useSendAnimation?: boolean } = {}) {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
emit("close");
|
emit("close");
|
||||||
if (!props.noReturnFocus) {
|
if (!props.noReturnFocus) {
|
||||||
focusedElement.focus();
|
focusedElement?.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,8 +241,8 @@ const align = () => {
|
||||||
const width = content.value!.offsetWidth;
|
const width = content.value!.offsetWidth;
|
||||||
const height = content.value!.offsetHeight;
|
const height = content.value!.offsetHeight;
|
||||||
|
|
||||||
let left: number;
|
let left = 0;
|
||||||
let top: number;
|
let top = MARGIN;
|
||||||
|
|
||||||
const x = srcRect.left + (fixed.value ? 0 : window.scrollX);
|
const x = srcRect.left + (fixed.value ? 0 : window.scrollX);
|
||||||
const y = srcRect.top + (fixed.value ? 0 : window.scrollY);
|
const y = srcRect.top + (fixed.value ? 0 : window.scrollY);
|
||||||
|
|
|
@ -35,7 +35,7 @@ defineProps<{
|
||||||
align?: "center" | string;
|
align?: "center" | string;
|
||||||
width?: number;
|
width?: number;
|
||||||
viaKeyboard?: boolean;
|
viaKeyboard?: boolean;
|
||||||
src?: any;
|
src?: HTMLElement | null;
|
||||||
noReturnFocus?;
|
noReturnFocus?;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ interface VueComponentConstructor<P, E> {
|
||||||
export async function popup<Props, Emits>(
|
export async function popup<Props, Emits>(
|
||||||
component: VueComponentConstructor<Props, Emits>,
|
component: VueComponentConstructor<Props, Emits>,
|
||||||
props: Props & Record<string, unknown>,
|
props: Props & Record<string, unknown>,
|
||||||
events: Partial<NonNullable<Emits>> | Record<string, never> = {},
|
events: Partial<Emits> = {},
|
||||||
disposeEvent?: string,
|
disposeEvent?: string,
|
||||||
) {
|
) {
|
||||||
markRaw(component);
|
markRaw(component);
|
||||||
|
@ -858,7 +858,7 @@ export async function openEmojiPicker(
|
||||||
|
|
||||||
export function popupMenu(
|
export function popupMenu(
|
||||||
items: MenuItem[] | Ref<MenuItem[]>,
|
items: MenuItem[] | Ref<MenuItem[]>,
|
||||||
src?: HTMLElement,
|
src?: HTMLElement | null,
|
||||||
options?: {
|
options?: {
|
||||||
align?: string;
|
align?: string;
|
||||||
width?: number;
|
width?: number;
|
||||||
|
|
Loading…
Reference in a new issue