summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkContainer.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-04-23 08:13:12 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-04-23 08:13:12 +0900
commit59dc9516d09723e1d9bb5d3783afaf39c8cdd301 (patch)
tree9a9095622ca694878502c480376b0170e2c101b5 /packages/frontend/src/components/MkContainer.vue
parent:art: (diff)
downloadmisskey-59dc9516d09723e1d9bb5d3783afaf39c8cdd301.tar.gz
misskey-59dc9516d09723e1d9bb5d3783afaf39c8cdd301.tar.bz2
misskey-59dc9516d09723e1d9bb5d3783afaf39c8cdd301.zip
refactor(frontend): use composition aoi
Diffstat (limited to 'packages/frontend/src/components/MkContainer.vue')
-rw-r--r--packages/frontend/src/components/MkContainer.vue169
1 files changed, 70 insertions, 99 deletions
diff --git a/packages/frontend/src/components/MkContainer.vue b/packages/frontend/src/components/MkContainer.vue
index a6372b7b6f..d03331a6eb 100644
--- a/packages/frontend/src/components/MkContainer.vue
+++ b/packages/frontend/src/components/MkContainer.vue
@@ -1,6 +1,6 @@
<template>
-<div class="_panel" :class="[$style.root, { [$style.naked]: naked, [$style.thin]: thin, [$style.hideHeader]: !showHeader, [$style.scrollable]: scrollable, [$style.closed]: !showBody }]">
- <header v-if="showHeader" ref="header" :class="$style.header">
+<div ref="rootEl" class="_panel" :class="[$style.root, { [$style.naked]: naked, [$style.thin]: thin, [$style.hideHeader]: !showHeader, [$style.scrollable]: scrollable, [$style.closed]: !showBody }]">
+ <header v-if="showHeader" ref="headerEl" :class="$style.header">
<div :class="$style.title">
<span :class="$style.titleIcon"><slot name="icon"></slot></span>
<slot name="header"></slot>
@@ -23,7 +23,7 @@
@leave="leave"
@after-leave="afterLeave"
>
- <div v-show="showBody" ref="content" :class="[$style.content, { [$style.omitted]: omitted }]">
+ <div v-show="showBody" ref="contentEl" :class="[$style.content, { [$style.omitted]: omitted }]">
<slot></slot>
<button v-if="omitted" :class="$style.fade" class="_button" @click="() => { ignoreOmit = true; omitted = false; }">
<span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span>
@@ -33,109 +33,80 @@
</div>
</template>
-<script lang="ts">
-import { defineComponent } from 'vue';
+<script lang="ts" setup>
+import { onMounted, ref, shallowRef, watch } from 'vue';
import { defaultStore } from '@/store';
import { i18n } from '@/i18n';
-export default defineComponent({
- props: {
- showHeader: {
- type: Boolean,
- required: false,
- default: true,
- },
- thin: {
- type: Boolean,
- required: false,
- default: false,
- },
- naked: {
- type: Boolean,
- required: false,
- default: false,
- },
- foldable: {
- type: Boolean,
- required: false,
- default: false,
- },
- expanded: {
- type: Boolean,
- required: false,
- default: true,
- },
- scrollable: {
- type: Boolean,
- required: false,
- default: false,
- },
- maxHeight: {
- type: Number,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- showBody: this.expanded,
- omitted: null,
- ignoreOmit: false,
- defaultStore,
- i18n,
- };
- },
- mounted() {
- this.$watch('showBody', showBody => {
- const headerHeight = this.showHeader ? this.$refs.header.offsetHeight : 0;
- this.$el.style.minHeight = `${headerHeight}px`;
- if (showBody) {
- this.$el.style.flexBasis = 'auto';
- } else {
- this.$el.style.flexBasis = `${headerHeight}px`;
- }
- }, {
- immediate: true,
- });
+const props = withDefaults(defineProps<{
+ showHeader?: boolean;
+ thin?: boolean;
+ naked?: boolean;
+ foldable?: boolean;
+ scrollable?: boolean;
+ expanded?: boolean;
+ maxHeight?: number | null;
+}>(), {
+ expanded: true,
+ showHeader: true,
+ maxHeight: null,
+});
- this.$el.style.setProperty('--maxHeight', this.maxHeight + 'px');
+const rootEl = shallowRef<HTMLElement>();
+const contentEl = shallowRef<HTMLElement>();
+const headerEl = shallowRef<HTMLElement>();
+const showBody = ref(props.expanded);
+const ignoreOmit = ref(false);
+const omitted = ref(false);
- const calcOmit = () => {
- if (this.omitted || this.ignoreOmit || this.maxHeight == null) return;
- const height = this.$refs.content.offsetHeight;
- this.omitted = height > this.maxHeight;
- };
+function enter(el) {
+ const elementHeight = el.getBoundingClientRect().height;
+ el.style.height = 0;
+ el.offsetHeight; // reflow
+ el.style.height = Math.min(elementHeight, props.maxHeight ?? Infinity) + 'px';
+}
- calcOmit();
- new ResizeObserver((entries, observer) => {
- calcOmit();
- }).observe(this.$refs.content);
- },
- methods: {
- toggleContent(show: boolean) {
- if (!this.foldable) return;
- this.showBody = show;
- },
+function afterEnter(el) {
+ el.style.height = null;
+}
+
+function leave(el) {
+ const elementHeight = el.getBoundingClientRect().height;
+ el.style.height = elementHeight + 'px';
+ el.offsetHeight; // reflow
+ el.style.height = 0;
+}
- enter(el) {
- const elementHeight = el.getBoundingClientRect().height;
- el.style.height = 0;
- el.offsetHeight; // reflow
- el.style.height = elementHeight + 'px';
- },
- afterEnter(el) {
- el.style.height = null;
- },
- leave(el) {
- const elementHeight = el.getBoundingClientRect().height;
- el.style.height = elementHeight + 'px';
- el.offsetHeight; // reflow
- el.style.height = 0;
- },
- afterLeave(el) {
- el.style.height = null;
- },
- },
+function afterLeave(el) {
+ el.style.height = null;
+}
+
+const calcOmit = () => {
+ if (omitted.value || ignoreOmit.value || props.maxHeight == null) return;
+ const height = contentEl.value.offsetHeight;
+ omitted.value = height > props.maxHeight;
+};
+
+onMounted(() => {
+ watch(showBody, v => {
+ const headerHeight = props.showHeader ? headerEl.value.offsetHeight : 0;
+ rootEl.value.style.minHeight = `${headerHeight}px`;
+ if (v) {
+ rootEl.value.style.flexBasis = 'auto';
+ } else {
+ rootEl.value.style.flexBasis = `${headerHeight}px`;
+ }
+ }, {
+ immediate: true,
+ });
+
+ rootEl.value.style.setProperty('--maxHeight', props.maxHeight + 'px');
+
+ calcOmit();
+
+ new ResizeObserver((entries, observer) => {
+ calcOmit();
+ }).observe(contentEl.value);
});
</script>