refactor: rewrite MkContainer using composition api
This commit is contained in:
parent
124b2244d6
commit
909125e519
1 changed files with 92 additions and 109 deletions
|
@ -9,6 +9,7 @@
|
||||||
scrollable,
|
scrollable,
|
||||||
closed: !showBody,
|
closed: !showBody,
|
||||||
}"
|
}"
|
||||||
|
ref="el"
|
||||||
>
|
>
|
||||||
<header v-if="showHeader" ref="header">
|
<header v-if="showHeader" ref="header">
|
||||||
<div class="title"><slot name="header"></slot></div>
|
<div class="title"><slot name="header"></slot></div>
|
||||||
|
@ -59,123 +60,105 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
import icon from "@/scripts/icon";
|
import icon from "@/scripts/icon";
|
||||||
|
|
||||||
export default defineComponent({
|
const props = withDefaults(
|
||||||
props: {
|
defineProps<{
|
||||||
showHeader: {
|
showHeader?: boolean,
|
||||||
type: Boolean,
|
thin?: boolean,
|
||||||
required: false,
|
naked?: boolean,
|
||||||
default: true,
|
foldable?: boolean,
|
||||||
},
|
expanded?: boolean,
|
||||||
thin: {
|
scrollable?: boolean,
|
||||||
type: Boolean,
|
maxHeight?: number | null,
|
||||||
required: false,
|
}>(),
|
||||||
default: false,
|
{
|
||||||
},
|
showHeader: true,
|
||||||
naked: {
|
thin: false,
|
||||||
type: Boolean,
|
naked: false,
|
||||||
required: false,
|
foldable: false,
|
||||||
default: false,
|
expanded: true,
|
||||||
},
|
scrollable: false,
|
||||||
foldable: {
|
maxHeight: null,
|
||||||
type: Boolean,
|
}
|
||||||
required: false,
|
);
|
||||||
default: false,
|
|
||||||
},
|
const showBody = ref(props.expanded);
|
||||||
expanded: {
|
const omitted = ref<boolean | null>(null);
|
||||||
type: Boolean,
|
const ignoreOmit = ref(false);
|
||||||
required: false,
|
const el = ref<HTMLElement | null>(null);
|
||||||
default: true,
|
const header = ref<HTMLElement | null>(null);
|
||||||
},
|
const content = ref<HTMLElement | null>(null);
|
||||||
scrollable: {
|
|
||||||
type: Boolean,
|
// FIXME: This function is not used, why?
|
||||||
required: false,
|
function toggleContent(show: boolean) {
|
||||||
default: false,
|
if (!props.foldable) return;
|
||||||
},
|
showBody.value = show;
|
||||||
maxHeight: {
|
}
|
||||||
type: Number,
|
|
||||||
required: false,
|
function enter(el) {
|
||||||
default: null,
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
},
|
el.style.height = 0;
|
||||||
},
|
el.offsetHeight; // reflow
|
||||||
data() {
|
el.style.height = `${elementHeight}px`;
|
||||||
return {
|
}
|
||||||
showBody: this.expanded,
|
function afterEnter(el) {
|
||||||
omitted: null,
|
el.style.height = null;
|
||||||
ignoreOmit: false,
|
}
|
||||||
i18n,
|
function leave(el) {
|
||||||
icon,
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
defaultStore,
|
el.style.height = `${elementHeight}px`;
|
||||||
};
|
el.offsetHeight; // reflow
|
||||||
},
|
el.style.height = 0;
|
||||||
mounted() {
|
}
|
||||||
this.$watch(
|
function afterLeave(el) {
|
||||||
"showBody",
|
el.style.height = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
watch(
|
||||||
|
showBody,
|
||||||
(showBody) => {
|
(showBody) => {
|
||||||
const headerHeight = this.showHeader
|
const headerHeight = props.showHeader
|
||||||
? this.$refs.header.offsetHeight
|
? header.value!.offsetHeight
|
||||||
: 0;
|
: 0;
|
||||||
this.$el.style.minHeight = `${headerHeight}px`;
|
el.value!.style.minHeight = `${headerHeight}px`;
|
||||||
if (showBody) {
|
if (showBody) {
|
||||||
this.$el.style.flexBasis = "auto";
|
el.value!.style.flexBasis = "auto";
|
||||||
} else {
|
} else {
|
||||||
this.$el.style.flexBasis = `${headerHeight}px`;
|
el.value!.style.flexBasis = `${headerHeight}px`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$el.style.setProperty("--maxHeight", this.maxHeight + "px");
|
if (props.maxHeight != null) {
|
||||||
|
el.value!.style.setProperty("--maxHeight", `${props.maxHeight}px`);
|
||||||
|
}
|
||||||
|
|
||||||
const calcOmit = () => {
|
const calcOmit = () => {
|
||||||
if (
|
if (
|
||||||
this.omitted ||
|
omitted.value ||
|
||||||
this.ignoreOmit ||
|
ignoreOmit.value ||
|
||||||
this.maxHeight == null ||
|
props.maxHeight == null ||
|
||||||
this.$refs.content == null
|
content.value == null
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
const height = this.$refs.content.offsetHeight;
|
const height = content.value.offsetHeight;
|
||||||
this.omitted = height > this.maxHeight;
|
omitted.value = height > props.maxHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
calcOmit();
|
calcOmit();
|
||||||
new ResizeObserver((entries, observer) => {
|
|
||||||
calcOmit();
|
|
||||||
}).observe(this.$refs.content);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleContent(show: boolean) {
|
|
||||||
if (!this.foldable) return;
|
|
||||||
this.showBody = show;
|
|
||||||
},
|
|
||||||
|
|
||||||
enter(el) {
|
new ResizeObserver((_entries, _observer) => {
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
calcOmit();
|
||||||
el.style.height = 0;
|
}).observe(content.value!);
|
||||||
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;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue