collapse-transition.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <script lang="ts" setup>
  2. import type { RendererElement } from 'vue';
  3. defineOptions({
  4. name: 'CollapseTransition',
  5. });
  6. const reset = (el: RendererElement) => {
  7. el.style.maxHeight = '';
  8. el.style.overflow = el.dataset.oldOverflow;
  9. el.style.paddingTop = el.dataset.oldPaddingTop;
  10. el.style.paddingBottom = el.dataset.oldPaddingBottom;
  11. };
  12. const on = {
  13. afterEnter(el: RendererElement) {
  14. el.style.maxHeight = '';
  15. el.style.overflow = el.dataset.oldOverflow;
  16. },
  17. afterLeave(el: RendererElement) {
  18. reset(el);
  19. },
  20. beforeEnter(el: RendererElement) {
  21. if (!el.dataset) el.dataset = {};
  22. el.dataset.oldPaddingTop = el.style.paddingTop;
  23. el.dataset.oldMarginTop = el.style.marginTop;
  24. el.dataset.oldPaddingBottom = el.style.paddingBottom;
  25. el.dataset.oldMarginBottom = el.style.marginBottom;
  26. if (el.style.height) el.dataset.elExistsHeight = el.style.height;
  27. el.style.maxHeight = 0;
  28. el.style.paddingTop = 0;
  29. el.style.marginTop = 0;
  30. el.style.paddingBottom = 0;
  31. el.style.marginBottom = 0;
  32. },
  33. beforeLeave(el: RendererElement) {
  34. if (!el.dataset) el.dataset = {};
  35. el.dataset.oldPaddingTop = el.style.paddingTop;
  36. el.dataset.oldMarginTop = el.style.marginTop;
  37. el.dataset.oldPaddingBottom = el.style.paddingBottom;
  38. el.dataset.oldMarginBottom = el.style.marginBottom;
  39. el.dataset.oldOverflow = el.style.overflow;
  40. el.style.maxHeight = `${el.scrollHeight}px`;
  41. el.style.overflow = 'hidden';
  42. },
  43. enter(el: RendererElement) {
  44. requestAnimationFrame(() => {
  45. el.dataset.oldOverflow = el.style.overflow;
  46. if (el.dataset.elExistsHeight) {
  47. el.style.maxHeight = el.dataset.elExistsHeight;
  48. } else if (el.scrollHeight === 0) {
  49. el.style.maxHeight = 0;
  50. } else {
  51. el.style.maxHeight = `${el.scrollHeight}px`;
  52. }
  53. el.style.paddingTop = el.dataset.oldPaddingTop;
  54. el.style.paddingBottom = el.dataset.oldPaddingBottom;
  55. el.style.marginTop = el.dataset.oldMarginTop;
  56. el.style.marginBottom = el.dataset.oldMarginBottom;
  57. el.style.overflow = 'hidden';
  58. });
  59. },
  60. enterCancelled(el: RendererElement) {
  61. reset(el);
  62. },
  63. leave(el: RendererElement) {
  64. if (el.scrollHeight !== 0) {
  65. el.style.maxHeight = 0;
  66. el.style.paddingTop = 0;
  67. el.style.paddingBottom = 0;
  68. el.style.marginTop = 0;
  69. el.style.marginBottom = 0;
  70. }
  71. },
  72. leaveCancelled(el: RendererElement) {
  73. reset(el);
  74. },
  75. };
  76. </script>
  77. <template>
  78. <transition name="collapse-transition" v-on="on">
  79. <slot></slot>
  80. </transition>
  81. </template>