1- import { defineComponent , h , Transition , withDirectives , vShow , RendererElement } from 'vue'
1+ import { defineComponent , h , Transition , ref , RendererElement , withDirectives } from 'vue'
2+ import { vVisible } from '../../directives/v-c-visible'
23
34const CCollapse = defineComponent ( {
45 name : 'CCollapse' ,
56 props : {
7+ /**
8+ * Set horizontal collapsing to transition the width instead of height.
9+ */
10+ horizontal : {
11+ type : Boolean ,
12+ required : false ,
13+ } ,
614 /**
715 * Toggle the visibility of component.
816 */
@@ -22,46 +30,68 @@ const CCollapse = defineComponent({
2230 'show' ,
2331 ] ,
2432 setup ( props , { slots, emit } ) {
25- const handleBeforeEnter = ( el : RendererElement ) => {
26- el . classList . remove ( 'collapse' )
27- el . classList . add ( 'collapsing' )
33+ const collapsing = ref ( false )
34+ const show = ref ( props . visible )
35+
36+ const handleBeforeEnter = ( ) => {
37+ collapsing . value = true
2838 }
39+
2940 const handleEnter = ( el : RendererElement , done : ( ) => void ) => {
3041 emit ( 'show' )
3142 el . addEventListener ( 'transitionend' , ( ) => {
32- el . classList . add ( 'collapse' , 'show' )
3343 done ( )
3444 } )
35- el . style . height = `${ el . scrollHeight } px`
45+ setTimeout ( ( ) => {
46+ if ( props . horizontal ) {
47+ el . style . width = `${ el . scrollWidth } px`
48+ return
49+ }
50+ el . style . height = `${ el . scrollHeight } px`
51+ } , 1 )
3652 }
53+
3754 const handleAfterEnter = ( el : RendererElement ) => {
38- el . classList . remove ( 'collapsing' )
39- el . style . removeProperty ( 'height' )
55+ show . value = true
56+ collapsing . value = false
57+ props . horizontal ? el . style . removeProperty ( 'width' ) : el . style . removeProperty ( 'height' )
4058 }
59+
4160 const handleBeforeLeave = ( el : RendererElement ) => {
42- el . classList . add ( 'show' )
61+ collapsing . value = true
62+ show . value = false
63+ if ( props . horizontal ) {
64+ el . style . width = `${ el . scrollWidth } px`
65+ return
66+ }
4367 el . style . height = `${ el . scrollHeight } px`
4468 }
69+
4570 const handleLeave = ( el : RendererElement , done : ( ) => void ) => {
4671 emit ( 'hide' )
47- el . classList . remove ( 'collapse' , 'show' )
48- el . classList . add ( 'collapsing' )
4972 el . addEventListener ( 'transitionend' , ( ) => {
5073 done ( )
5174 } )
52- el . style . height = '0px'
75+ setTimeout ( ( ) => {
76+ if ( props . horizontal ) {
77+ el . style . width = '0px'
78+ return
79+ }
80+ el . style . height = '0px'
81+ } , 1 )
5382 }
83+
5484 const handleAfterLeave = ( el : RendererElement ) => {
55- el . classList . remove ( ' collapsing' )
56- el . classList . add ( 'collapse ')
85+ collapsing . value = false
86+ props . horizontal ? el . style . removeProperty ( 'width' ) : el . style . removeProperty ( 'height ')
5787 }
5888
5989 return ( ) =>
6090 h (
6191 Transition ,
6292 {
63- name : 'fade' ,
64- onBeforeEnter : ( el ) => handleBeforeEnter ( el ) ,
93+ css : false ,
94+ onBeforeEnter : ( ) => handleBeforeEnter ( ) ,
6595 onEnter : ( el , done ) => handleEnter ( el , done ) ,
6696 onAfterEnter : ( el ) => handleAfterEnter ( el ) ,
6797 onBeforeLeave : ( el ) => handleBeforeLeave ( el ) ,
@@ -74,15 +104,13 @@ const CCollapse = defineComponent({
74104 'div' ,
75105 {
76106 class : [
77- 'collapse' ,
78- {
79- show : props . visible ,
80- } ,
107+ collapsing . value ? 'collapsing' : 'collapse' ,
108+ { 'collapse-horizontal' : props . horizontal , show : show . value } ,
81109 ] ,
82110 } ,
83111 slots . default && slots . default ( ) ,
84112 ) ,
85- [ [ vShow , props . visible ] ] ,
113+ [ [ vVisible , props . visible ] ] ,
86114 ) ,
87115 )
88116 } ,
0 commit comments