@@ -9,6 +9,9 @@ type ThumbReact = {
99 left : number ;
1010 right : number ;
1111 width : number ;
12+ top : number ;
13+ bottom : number ;
14+ height : number ;
1215} | null ;
1316
1417export interface MotionThumbInterface {
@@ -20,23 +23,52 @@ export interface MotionThumbInterface {
2023 onMotionStart : VoidFunction ;
2124 onMotionEnd : VoidFunction ;
2225 direction ?: 'ltr' | 'rtl' ;
26+ position ?: 'horizontal' | 'vertical' ;
2327}
2428
2529const calcThumbStyle = (
2630 targetElement : HTMLElement | null | undefined ,
27- ) : ThumbReact =>
28- targetElement
29- ? {
30- left : targetElement . offsetLeft ,
31- right :
32- ( targetElement . parentElement ! . clientWidth as number ) -
33- targetElement . clientWidth -
34- targetElement . offsetLeft ,
35- width : targetElement . clientWidth ,
36- }
37- : null ;
31+ position : 'horizontal' | 'vertical' ,
32+ ) : ThumbReact => {
33+ if ( ! targetElement ) return null ;
34+
35+ const style : ThumbReact = {
36+ left : targetElement . offsetLeft ,
37+ right :
38+ ( targetElement . parentElement ! . clientWidth as number ) -
39+ targetElement . clientWidth -
40+ targetElement . offsetLeft ,
41+ width : targetElement . clientWidth ,
42+ top : targetElement . offsetTop ,
43+ bottom :
44+ ( targetElement . parentElement ! . clientHeight as number ) -
45+ targetElement . clientHeight -
46+ targetElement . offsetTop ,
47+ height : targetElement . clientHeight ,
48+ } ;
3849
39- const toPX = ( value : number ) =>
50+ if ( position === 'vertical' ) {
51+ return {
52+ left : 0 ,
53+ right : 0 ,
54+ width : 0 ,
55+ top : style . top ,
56+ bottom : style . bottom ,
57+ height : style . height ,
58+ } ;
59+ }
60+
61+ return {
62+ left : style . left ,
63+ right : style . right ,
64+ width : style . width ,
65+ top : 0 ,
66+ bottom : 0 ,
67+ height : 0 ,
68+ } ;
69+ } ;
70+
71+ const toPX = ( value : number | undefined ) : string | undefined =>
4072 value !== undefined ? `${ value } px` : undefined ;
4173
4274export default function MotionThumb ( props : MotionThumbInterface ) {
@@ -49,19 +81,17 @@ export default function MotionThumb(props: MotionThumbInterface) {
4981 onMotionStart,
5082 onMotionEnd,
5183 direction,
84+ position = 'horizontal' ,
5285 } = props ;
5386
5487 const thumbRef = React . useRef < HTMLDivElement > ( null ) ;
5588 const [ prevValue , setPrevValue ] = React . useState ( value ) ;
5689
57- // =========================== Effect ===========================
5890 const findValueElement = ( val : SegmentedValue ) => {
5991 const index = getValueIndex ( val ) ;
60-
6192 const ele = containerRef . current ?. querySelectorAll < HTMLDivElement > (
6293 `.${ prefixCls } -item` ,
6394 ) [ index ] ;
64-
6595 return ele ?. offsetParent && ele ;
6696 } ;
6797
@@ -73,8 +103,8 @@ export default function MotionThumb(props: MotionThumbInterface) {
73103 const prev = findValueElement ( prevValue ) ;
74104 const next = findValueElement ( value ) ;
75105
76- const calcPrevStyle = calcThumbStyle ( prev ) ;
77- const calcNextStyle = calcThumbStyle ( next ) ;
106+ const calcPrevStyle = calcThumbStyle ( prev , position ) ;
107+ const calcNextStyle = calcThumbStyle ( next , position ) ;
78108
79109 setPrevValue ( value ) ;
80110 setPrevStyle ( calcPrevStyle ) ;
@@ -90,40 +120,44 @@ export default function MotionThumb(props: MotionThumbInterface) {
90120
91121 const thumbStart = React . useMemo (
92122 ( ) =>
93- direction === 'rtl '
94- ? toPX ( - ( prevStyle ?. right as number ) )
95- : toPX ( prevStyle ?. left as number ) ,
96- [ direction , prevStyle ] ,
123+ position === 'vertical '
124+ ? toPX ( prevStyle ?. top ?? 0 )
125+ : toPX ( prevStyle ?. left ?? 0 ) ,
126+ [ position , prevStyle ] ,
97127 ) ;
128+
98129 const thumbActive = React . useMemo (
99130 ( ) =>
100- direction === 'rtl '
101- ? toPX ( - ( nextStyle ?. right as number ) )
102- : toPX ( nextStyle ?. left as number ) ,
103- [ direction , nextStyle ] ,
131+ position === 'vertical '
132+ ? toPX ( nextStyle ?. top ?? 0 )
133+ : toPX ( nextStyle ?. left ?? 0 ) ,
134+ [ position , nextStyle ] ,
104135 ) ;
105136
106- // =========================== Motion ===========================
107- const onAppearStart = ( ) => {
108- return {
109- transform : `translateX(var(--thumb-start-left))` ,
110- width : `var(--thumb-start-width)` ,
111- } ;
112- } ;
113- const onAppearActive = ( ) => {
114- return {
115- transform : `translateX(var(--thumb-active-left))` ,
116- width : `var(--thumb-active-width)` ,
117- } ;
118- } ;
137+ const onAppearStart = ( ) => ( {
138+ transform : `translate${
139+ position === 'vertical' ? 'Y' : 'X'
140+ } (var(--thumb-start-${ position === 'vertical' ? 'top' : 'left' } ))`,
141+ [ position === 'vertical' ? 'height' : 'width' ] : `var(--thumb-start-${
142+ position === 'vertical' ? 'height' : 'width'
143+ } )`,
144+ } ) ;
145+
146+ const onAppearActive = ( ) => ( {
147+ transform : `translate${
148+ position === 'vertical' ? 'Y' : 'X'
149+ } (var(--thumb-active-${ position === 'vertical' ? 'top' : 'left' } ))`,
150+ [ position === 'vertical' ? 'height' : 'width' ] : `var(--thumb-active-${
151+ position === 'vertical' ? 'height' : 'width'
152+ } )`,
153+ } ) ;
154+
119155 const onVisibleChanged = ( ) => {
120156 setPrevStyle ( null ) ;
121157 setNextStyle ( null ) ;
122158 onMotionEnd ( ) ;
123159 } ;
124160
125- // =========================== Render ===========================
126- // No need motion when nothing exist in queue
127161 if ( ! prevStyle || ! nextStyle ) {
128162 return null ;
129163 }
@@ -144,13 +178,20 @@ export default function MotionThumb(props: MotionThumbInterface) {
144178 '--thumb-start-width' : toPX ( prevStyle ?. width ) ,
145179 '--thumb-active-left' : thumbActive ,
146180 '--thumb-active-width' : toPX ( nextStyle ?. width ) ,
181+ '--thumb-start-top' : thumbStart ,
182+ '--thumb-start-height' : toPX ( prevStyle ?. height ) ,
183+ '--thumb-active-top' : thumbActive ,
184+ '--thumb-active-height' : toPX ( nextStyle ?. height ) ,
147185 } as React . CSSProperties ;
148186
149- // It's little ugly which should be refactor when @umi/test update to latest jsdom
150187 const motionProps = {
151188 ref : composeRef ( thumbRef , ref ) ,
152189 style : mergedStyle ,
153- className : classNames ( `${ prefixCls } -thumb` , motionClassName ) ,
190+ className : classNames (
191+ `${ prefixCls } -thumb` ,
192+ `${ prefixCls } -${ position } -thumb` ,
193+ motionClassName ,
194+ ) ,
154195 } ;
155196
156197 if ( process . env . NODE_ENV === 'test' ) {
0 commit comments