@@ -12,19 +12,50 @@ export interface OffsetConfig {
12
12
offsetRight ?: number
13
13
}
14
14
15
+ export interface Options {
16
+ animateOptions ?: AnimateOptions
17
+ boundary ?: Element
18
+ centerIfNeeded ?: boolean
19
+ offsetConfig ?: OffsetConfig
20
+ }
21
+
22
+ function isBoolean ( options : boolean | Options ) : options is boolean {
23
+ return typeof options === 'boolean'
24
+ }
25
+
15
26
export default function scrollIntoViewIfNeeded (
16
27
elem : Element ,
17
- centerIfNeeded ? : boolean ,
18
- options ?: AnimateOptions ,
28
+ options : boolean | Options ,
29
+ animateOptions ?: AnimateOptions ,
19
30
finalElement ?: Element ,
20
- config : OffsetConfig = { }
31
+ offsetOptions : OffsetConfig = { }
21
32
) {
22
33
if ( ! elem || ! ( elem instanceof HTMLElement ) )
23
34
throw new Error ( 'Element is required in scrollIntoViewIfNeeded' )
24
35
36
+ let config : Options = { }
37
+
38
+ if ( isBoolean ( options ) ) {
39
+ config . centerIfNeeded = options
40
+ } else {
41
+ config = options
42
+ }
43
+
44
+ if ( animateOptions ) {
45
+ config . animateOptions = animateOptions
46
+ }
47
+
48
+ if ( finalElement ) {
49
+ config . boundary = finalElement
50
+ }
51
+
52
+ if ( offsetOptions ) {
53
+ config . offsetConfig = offsetOptions
54
+ }
55
+
25
56
function withinBounds ( value , min , max , extent ) {
26
57
if (
27
- false === centerIfNeeded ||
58
+ config . centerIfNeeded === false ||
28
59
( max <= value + extent && value <= min + extent )
29
60
) {
30
61
return Math . min ( max , Math . max ( min , value ) )
@@ -33,10 +64,12 @@ export default function scrollIntoViewIfNeeded(
33
64
}
34
65
}
35
66
36
- const offsetTop = config . offsetTop || 0
37
- const offsetLeft = config . offsetLeft || 0
38
- const offsetBottom = config . offsetBottom || 0
39
- const offsetRight = config . offsetRight || 0
67
+ const { offsetConfig = { } } = config
68
+
69
+ const offsetTop = offsetConfig . offsetTop || 0
70
+ const offsetLeft = offsetConfig . offsetLeft || 0
71
+ const offsetBottom = offsetConfig . offsetBottom || 0
72
+ const offsetRight = offsetConfig . offsetRight || 0
40
73
41
74
function makeArea ( left , top , width , height ) {
42
75
return {
@@ -55,7 +88,7 @@ export default function scrollIntoViewIfNeeded(
55
88
)
56
89
} ,
57
90
relativeFromTo : function ( lhs , rhs ) {
58
- var newLeft = left + offsetLeft ,
91
+ let newLeft = left + offsetLeft ,
59
92
newTop = top + offsetTop
60
93
lhs = lhs . offsetParent
61
94
rhs = rhs . offsetParent
@@ -75,7 +108,7 @@ export default function scrollIntoViewIfNeeded(
75
108
}
76
109
}
77
110
78
- var parent ,
111
+ let parent ,
79
112
area = makeArea (
80
113
elem . offsetLeft ,
81
114
elem . offsetTop ,
@@ -84,34 +117,34 @@ export default function scrollIntoViewIfNeeded(
84
117
)
85
118
while (
86
119
( parent = elem . parentNode ) instanceof HTMLElement &&
87
- elem !== finalElement
120
+ elem !== config . boundary
88
121
) {
89
- var clientLeft = parent . offsetLeft + parent . clientLeft
90
- var clientTop = parent . offsetTop + parent . clientTop
122
+ const clientLeft = parent . offsetLeft + parent . clientLeft
123
+ const clientTop = parent . offsetTop + parent . clientTop
91
124
92
125
// Make area relative to parent's client area.
93
126
area = area . relativeFromTo ( elem , parent ) . translate ( - clientLeft , - clientTop )
94
127
95
- var scrollLeft = withinBounds (
128
+ const scrollLeft = withinBounds (
96
129
parent . scrollLeft ,
97
130
area . right - parent . clientWidth ,
98
131
area . left ,
99
132
parent . clientWidth
100
133
)
101
- var scrollTop = withinBounds (
134
+ const scrollTop = withinBounds (
102
135
parent . scrollTop ,
103
136
area . bottom - parent . clientHeight ,
104
137
area . top ,
105
138
parent . clientHeight
106
139
)
107
- if ( options ) {
140
+ if ( config . animateOptions ) {
108
141
animate (
109
142
parent ,
110
143
{
111
144
scrollLeft : scrollLeft ,
112
145
scrollTop : scrollTop ,
113
146
} ,
114
- options
147
+ config . animateOptions
115
148
)
116
149
} else {
117
150
parent . scrollLeft = scrollLeft
0 commit comments