<script>
/* eslint-disable no-param-reassign */
/* eslint-disable no-unused-expressions */
/**
 * Toggles with animation the visibility of content by the vue prop `isOpen`.
 */
export default {
  name: 'MCollapsableContent',
  functional: true,
  props: {
    isOpen: {
      type: Boolean,
      default: false,
    },
    classes: {
      type: String,
      default: '',
    },
  },
  render(createElement, context) {
    const wrapper = context.props.isOpen
      ? createElement(
        'div',
        { class: ['collapsable-wrapper', context.props.classes] },
        context.children,
      )
      : '';

    const data = {
      props: {
        name: 'collapsable',
      },
      on: {
        afterEnter(element) {
          element.style.height = 'auto';
        },
        enter(element) {
          const { width } = getComputedStyle(element);

          element.style.width = width;
          element.style.position = 'absolute';
          element.style.visibility = 'hidden';
          element.style.height = 'auto';

          const { height } = getComputedStyle(element);

          element.style.width = null;
          element.style.position = null;
          element.style.visibility = null;
          element.style.height = 0;

          // Force repaint to make sure the
          // animation is triggered correctly.
          getComputedStyle(element).height;
          requestAnimationFrame(() => {
            element.style.height = height;
          });
        },
        leave(element) {
          const { height } = getComputedStyle(element);

          element.style.height = height;
          // Force repaint to make sure the
          // animation is triggered correctly.
          getComputedStyle(element).height;
          requestAnimationFrame(() => {
            element.style.height = 0;
          });
        },
      },
    };

    return createElement('transition', data, [wrapper]);
  },
};
</script>

<style>
.collapsable-wrapper {
  will-change: height;
}

.collapsable-enter-active,
.collapsable-leave-active {
  overflow: hidden;

  transition: height 300ms ease-in-out;
}

.collapsable-enter,
.collapsable-leave-to {
  height: 0;
}
</style>
