refactor(client): refactor and performance improve of MkSpacer
This commit is contained in:
parent
2184240ef1
commit
6c10588e77
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dwzlatin" :class="{ opened }" ref="root">
|
<div class="dwzlatin" :class="{ opened }">
|
||||||
<div class="header _button" @click="toggle">
|
<div 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>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
>
|
>
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<div v-show="opened">
|
<div v-show="opened">
|
||||||
<MkSpacer :margin-min="14" :margin-max="22" :container="root">
|
<MkSpacer :margin-min="14" :margin-max="22">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,7 +40,6 @@ const props = withDefaults(defineProps<{
|
||||||
|
|
||||||
let opened = $ref(props.defaultOpen);
|
let opened = $ref(props.defaultOpen);
|
||||||
let openedAtLeastOnce = $ref(props.defaultOpen);
|
let openedAtLeastOnce = $ref(props.defaultOpen);
|
||||||
let root = $shallowRef<HTMLElement>();
|
|
||||||
|
|
||||||
function enter(el) {
|
function enter(el) {
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
|
@ -142,6 +141,7 @@ function toggle() {
|
||||||
> .body {
|
> .body {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border-radius: 0 0 6px 6px;
|
border-radius: 0 0 6px 6px;
|
||||||
|
container-type: inline-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.opened {
|
&.opened {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="root" :class="$style.root" :style="{ padding: margin + 'px' }">
|
<div :class="[$style.root, { [$style.rootMin]: forceSpacerMin }]">
|
||||||
<div ref="content" :class="$style.content">
|
<div :class="$style.content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,84 +14,13 @@ const props = withDefaults(defineProps<{
|
||||||
contentMax?: number | null;
|
contentMax?: number | null;
|
||||||
marginMin?: number;
|
marginMin?: number;
|
||||||
marginMax?: number;
|
marginMax?: number;
|
||||||
|
|
||||||
// MkFolderとかで開閉アニメーションの際にheightを正しく伝えるため
|
|
||||||
container?: HTMLElement,
|
|
||||||
}>(), {
|
}>(), {
|
||||||
contentMax: null,
|
contentMax: null,
|
||||||
marginMin: 12,
|
marginMin: 12,
|
||||||
marginMax: 24,
|
marginMax: 24,
|
||||||
});
|
});
|
||||||
|
|
||||||
let ro: ResizeObserver;
|
const forceSpacerMin = inject('forceSpacerMin', false) || deviceKind === 'smartphone';
|
||||||
let root = $shallowRef<HTMLElement>();
|
|
||||||
let content = $shallowRef<HTMLElement>();
|
|
||||||
let margin = $ref(props.marginMin);
|
|
||||||
const widthHistory = [null, null] as [number | null, number | null];
|
|
||||||
const heightHistory = [null, null] as [number | null, number | null];
|
|
||||||
const shouldSpacerMin = inject('shouldSpacerMin', false);
|
|
||||||
|
|
||||||
const adjust = (rect: { width: number; height: number; }) => {
|
|
||||||
if (shouldSpacerMin || deviceKind === 'smartphone') {
|
|
||||||
margin = props.marginMin;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rect.width > (props.contentMax ?? 0) || (rect.width > 360 && window.innerWidth > 400)) {
|
|
||||||
margin = props.marginMax;
|
|
||||||
} else {
|
|
||||||
margin = props.marginMin;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (props.container) {
|
|
||||||
const width = props.container.offsetWidth;
|
|
||||||
const height = props.container.offsetHeight;
|
|
||||||
adjust({
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
ro = new ResizeObserver((entries) => {
|
|
||||||
/* iOSが対応していない
|
|
||||||
adjust({
|
|
||||||
width: entries[0].borderBoxSize[0].inlineSize,
|
|
||||||
height: entries[0].borderBoxSize[0].blockSize,
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
const width = props.container ? props.container.offsetWidth : root!.offsetWidth;
|
|
||||||
const height = props.container ? props.container.offsetHeight : root!.offsetHeight;
|
|
||||||
|
|
||||||
//#region Prevent infinite resizing
|
|
||||||
// https://github.com/misskey-dev/misskey/issues/9076
|
|
||||||
const pastWidth = widthHistory.pop();
|
|
||||||
widthHistory.unshift(width);
|
|
||||||
const pastHeight = heightHistory.pop();
|
|
||||||
heightHistory.unshift(height);
|
|
||||||
|
|
||||||
if (pastWidth === width && pastHeight === height) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
adjust({
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ro.observe(root!);
|
|
||||||
|
|
||||||
if (props.contentMax) {
|
|
||||||
content!.style.maxWidth = `${props.contentMax}px`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
ro.disconnect();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
@ -99,9 +28,25 @@ onUnmounted(() => {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.rootMin {
|
||||||
|
padding: v-bind('props.marginMin + "px"') !important;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
max-width: v-bind('props.contentMax + "px"');
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@container (max-width: 360px) {
|
||||||
|
.root {
|
||||||
|
padding: v-bind('props.marginMin + "px"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (min-width: 361px) {
|
||||||
|
.root {
|
||||||
|
padding: v-bind('props.marginMax + "px"');
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -76,7 +76,7 @@ provideMetadataReceiver((info) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
provide('shouldHeaderThin', showMenuOnTop);
|
provide('shouldHeaderThin', showMenuOnTop);
|
||||||
provide('shouldSpacerMin', true);
|
provide('forceSpacerMin', true);
|
||||||
|
|
||||||
function attachSticky(el) {
|
function attachSticky(el) {
|
||||||
const sticky = new StickySidebar(el, defaultStore.state.menuDisplay === 'top' ? 0 : 16, defaultStore.state.menuDisplay === 'top' ? 60 : 0); // TODO: ヘッダーの高さを60pxと決め打ちしているのを直す
|
const sticky = new StickySidebar(el, defaultStore.state.menuDisplay === 'top' ? 0 : 16, defaultStore.state.menuDisplay === 'top' ? 60 : 0); // TODO: ヘッダーの高さを60pxと決め打ちしているのを直す
|
||||||
|
|
|
@ -40,7 +40,7 @@ import { MenuItem } from '@/types/menu';
|
||||||
|
|
||||||
provide('shouldHeaderThin', true);
|
provide('shouldHeaderThin', true);
|
||||||
provide('shouldOmitHeaderTitle', true);
|
provide('shouldOmitHeaderTitle', true);
|
||||||
provide('shouldSpacerMin', true);
|
provide('forceSpacerMin', true);
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
column: Column;
|
column: Column;
|
||||||
|
|
Loading…
Reference in New Issue