@@ -9,6 +9,9 @@ type ThumbReact = {
9
9
left : number ;
10
10
right : number ;
11
11
width : number ;
12
+ top : number ;
13
+ bottom : number ;
14
+ height : number ;
12
15
} | null ;
13
16
14
17
export interface MotionThumbInterface {
@@ -20,23 +23,52 @@ export interface MotionThumbInterface {
20
23
onMotionStart : VoidFunction ;
21
24
onMotionEnd : VoidFunction ;
22
25
direction ?: 'ltr' | 'rtl' ;
26
+ position ?: 'horizontal' | 'vertical' ;
23
27
}
24
28
25
29
const calcThumbStyle = (
26
30
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
+ } ;
38
49
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 =>
40
72
value !== undefined ? `${ value } px` : undefined ;
41
73
42
74
export default function MotionThumb ( props : MotionThumbInterface ) {
@@ -49,19 +81,17 @@ export default function MotionThumb(props: MotionThumbInterface) {
49
81
onMotionStart,
50
82
onMotionEnd,
51
83
direction,
84
+ position = 'horizontal' ,
52
85
} = props ;
53
86
54
87
const thumbRef = React . useRef < HTMLDivElement > ( null ) ;
55
88
const [ prevValue , setPrevValue ] = React . useState ( value ) ;
56
89
57
- // =========================== Effect ===========================
58
90
const findValueElement = ( val : SegmentedValue ) => {
59
91
const index = getValueIndex ( val ) ;
60
-
61
92
const ele = containerRef . current ?. querySelectorAll < HTMLDivElement > (
62
93
`.${ prefixCls } -item` ,
63
94
) [ index ] ;
64
-
65
95
return ele ?. offsetParent && ele ;
66
96
} ;
67
97
@@ -73,8 +103,8 @@ export default function MotionThumb(props: MotionThumbInterface) {
73
103
const prev = findValueElement ( prevValue ) ;
74
104
const next = findValueElement ( value ) ;
75
105
76
- const calcPrevStyle = calcThumbStyle ( prev ) ;
77
- const calcNextStyle = calcThumbStyle ( next ) ;
106
+ const calcPrevStyle = calcThumbStyle ( prev , position ) ;
107
+ const calcNextStyle = calcThumbStyle ( next , position ) ;
78
108
79
109
setPrevValue ( value ) ;
80
110
setPrevStyle ( calcPrevStyle ) ;
@@ -90,40 +120,44 @@ export default function MotionThumb(props: MotionThumbInterface) {
90
120
91
121
const thumbStart = React . useMemo (
92
122
( ) =>
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 ] ,
97
127
) ;
128
+
98
129
const thumbActive = React . useMemo (
99
130
( ) =>
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 ] ,
104
135
) ;
105
136
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
+
119
155
const onVisibleChanged = ( ) => {
120
156
setPrevStyle ( null ) ;
121
157
setNextStyle ( null ) ;
122
158
onMotionEnd ( ) ;
123
159
} ;
124
160
125
- // =========================== Render ===========================
126
- // No need motion when nothing exist in queue
127
161
if ( ! prevStyle || ! nextStyle ) {
128
162
return null ;
129
163
}
@@ -144,13 +178,20 @@ export default function MotionThumb(props: MotionThumbInterface) {
144
178
'--thumb-start-width' : toPX ( prevStyle ?. width ) ,
145
179
'--thumb-active-left' : thumbActive ,
146
180
'--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 ) ,
147
185
} as React . CSSProperties ;
148
186
149
- // It's little ugly which should be refactor when @umi/test update to latest jsdom
150
187
const motionProps = {
151
188
ref : composeRef ( thumbRef , ref ) ,
152
189
style : mergedStyle ,
153
- className : classNames ( `${ prefixCls } -thumb` , motionClassName ) ,
190
+ className : classNames (
191
+ `${ prefixCls } -thumb` ,
192
+ `${ prefixCls } -${ position } -thumb` ,
193
+ motionClassName ,
194
+ ) ,
154
195
} ;
155
196
156
197
if ( process . env . NODE_ENV === 'test' ) {
0 commit comments