<script
    setup
    lang="ts"
>
    defineProps({
        show: { type: Boolean, required: true }
    })

    const beforeEnter = (element: Element) => {
        const html_element = element as HTMLElement;

        html_element.style.width = '0'
        html_element.style.opacity = '0'
    }

    const enter = (element: Element) => {
        const html_element = element as HTMLElement;

        const w = html_element.scrollWidth
        html_element.style.transition = 'width 0.25s ease, opacity 0.25s ease'

        requestAnimationFrame(() => {
            html_element.style.width = w + 'px'
            html_element.style.opacity = '1'
        })
    }

    const afterEnter = (element: Element) => {
        const html_element = element as HTMLElement;

        html_element.style.width = 'auto' // restore natural width
    }

    const beforeLeave = (element: Element) => {
        const html_element = element as HTMLElement;
        html_element.style.width = element.scrollWidth + 'px'
        html_element.style.opacity = '1'
    }

    const leave = (element: Element) => {
        const html_element = element as HTMLElement;

        // force reflow
        void html_element.offsetWidth

        html_element.style.transition = 'width 0.25s ease, opacity 0.25s ease'
        html_element.style.width = '0'
        html_element.style.opacity = '0'
    }
</script>

<template>
    <transition
        @before-enter="beforeEnter"
        @enter="enter"
        @after-enter="afterEnter"
        @before-leave="beforeLeave"
        @leave="leave"
    >
        <div
            v-show="show"
            class="h-slide"
        >
            <slot />
        </div>
    </transition>
</template>



<style scoped>
.h-slide {
    overflow: hidden;
    /* required for width transitions */
    display: inline-block;
    /* ensures width applies correctly */
}
</style>
