diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-04-23 08:13:12 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2023-04-23 08:13:12 +0900 |
| commit | 59dc9516d09723e1d9bb5d3783afaf39c8cdd301 (patch) | |
| tree | 9a9095622ca694878502c480376b0170e2c101b5 /packages/frontend/src/components/MkContainer.vue | |
| parent | :art: (diff) | |
| download | misskey-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.vue | 169 |
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> |