@tarojs/components 3.6.0-canary.5 → 3.6.0-canary.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/component-lib/input.js +1 -1
- package/dist/react/component-lib/reactify-wc.js +10 -10
- package/dist/react/helper.js +1 -1
- package/dist/react/react-component-lib/createComponent.js +9 -9
- package/dist/react/react-component-lib/createOverlayComponent.js +10 -10
- package/dist/react/react-component-lib/utils/attachProps.js +1 -1
- package/dist/react/react-component-lib/utils/index.js +1 -1
- package/dist/vue2/component-lib/createComponent.js +1 -1
- package/dist/vue2/component-lib/createFormsComponent.js +2 -2
- package/dist/vue2/component-lib/index.js +1 -1
- package/dist/vue2/component-lib/mixins/listeners.js +1 -1
- package/dist/vue2/component-lib/mixins/refs.js +1 -1
- package/dist/vue2/component-lib/picker.js +1 -1
- package/dist/vue2/component-lib/scroll-view.js +1 -1
- package/dist/vue2/components.js +1 -1
- package/dist/vue2/index.js +2 -2
- package/dist/vue2/vue-component-lib/utils.js +2 -2
- package/dist/vue3/component-lib/createComponent.js +1 -1
- package/dist/vue3/component-lib/createFormsComponent.js +3 -3
- package/dist/vue3/index.js +1 -1
- package/dist/vue3/vue-component-lib/utils.js +3 -3
- package/package.json +5 -4
- package/types/Ad.d.ts +1 -1
- package/types/Audio.d.ts +1 -1
- package/types/Button.d.ts +1 -1
- package/types/Camera.d.ts +1 -1
- package/types/Canvas.d.ts +1 -1
- package/types/Checkbox.d.ts +1 -1
- package/types/CheckboxGroup.d.ts +1 -1
- package/types/CoverImage.d.ts +1 -1
- package/types/CoverView.d.ts +102 -4
- package/types/CustomWrapper.d.ts +1 -1
- package/types/Form.d.ts +1 -1
- package/types/Icon.d.ts +1 -1
- package/types/Image.d.ts +1 -1
- package/types/Input.d.ts +71 -8
- package/types/LivePlayer.d.ts +1 -1
- package/types/LivePusher.d.ts +1 -1
- package/types/Map.d.ts +1 -1
- package/types/MatchMedia.d.ts +1 -1
- package/types/MovableArea.d.ts +2 -2
- package/types/MovableView.d.ts +17 -17
- package/types/Navigator.d.ts +1 -1
- package/types/OpenData.d.ts +1 -1
- package/types/PageContainer.d.ts +28 -18
- package/types/PageMeta.d.ts +1 -1
- package/types/Picker.d.ts +1 -1
- package/types/PickerView.d.ts +1 -1
- package/types/Progress.d.ts +1 -1
- package/types/Radio.d.ts +1 -1
- package/types/RadioGroup.d.ts +1 -1
- package/types/RootPortal.d.ts +11 -2
- package/types/ScrollView.d.ts +1 -1
- package/types/ShareElement.d.ts +20 -10
- package/types/Slider.d.ts +1 -1
- package/types/Swiper.d.ts +1 -1
- package/types/SwiperItem.d.ts +3 -2
- package/types/Switch.d.ts +1 -1
- package/types/Text.d.ts +1 -1
- package/types/Textarea.d.ts +7 -1
- package/types/Video.d.ts +7 -1
- package/types/View.d.ts +1 -1
- package/types/WebView.d.ts +1 -1
- package/types/index.vue3.d.ts +2 -1
- package/virtual-list/index.d.ts +3 -120
- package/virtual-list/index.js +3 -7
- package/virtual-list/domHelpers.js +0 -40
- package/virtual-list/memoize.js +0 -38
- package/virtual-list/react/FixedSizeList.js +0 -193
- package/virtual-list/react/createListComponent.js +0 -654
- package/virtual-list/react/index.d.ts +0 -123
- package/virtual-list/react/index.js +0 -67
- package/virtual-list/timer.js +0 -24
- package/virtual-list/vue/index.js +0 -589
|
@@ -1,654 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-sequences */
|
|
2
|
-
/* eslint-disable no-case-declarations */
|
|
3
|
-
/* eslint-disable no-void */
|
|
4
|
-
/* eslint-disable no-return-assign */
|
|
5
|
-
import { createSelectorQuery } from '@tarojs/taro'
|
|
6
|
-
import { createElement, PureComponent } from 'react'
|
|
7
|
-
|
|
8
|
-
import { getRTLOffsetType } from '../domHelpers'
|
|
9
|
-
import { memoizeOne } from '../memoize'
|
|
10
|
-
import { cancelTimeout, requestTimeout } from '../timer'
|
|
11
|
-
|
|
12
|
-
const IS_SCROLLING_DEBOUNCE_INTERVAL = 200
|
|
13
|
-
|
|
14
|
-
const defaultItemKey = (index) => index // In DEV mode, this Set helps us only log a warning once per component instance.
|
|
15
|
-
// This avoids spamming the console every time a render happens.
|
|
16
|
-
|
|
17
|
-
let INSTANCE_ID = 0
|
|
18
|
-
|
|
19
|
-
export function isHorizontalFunc ({ direction, layout }) {
|
|
20
|
-
return direction === 'horizontal' || layout === 'horizontal'
|
|
21
|
-
}
|
|
22
|
-
export function isRtlFunc ({ direction }) {
|
|
23
|
-
return direction === 'rtl'
|
|
24
|
-
}
|
|
25
|
-
export function getRectSize (id, success = () => {}, fail = () => {}) {
|
|
26
|
-
const query = createSelectorQuery()
|
|
27
|
-
query.select(id).boundingClientRect((res) => {
|
|
28
|
-
if (res) {
|
|
29
|
-
success(res)
|
|
30
|
-
} else {
|
|
31
|
-
fail()
|
|
32
|
-
}
|
|
33
|
-
}).exec()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default function createListComponent ({
|
|
37
|
-
getItemOffset,
|
|
38
|
-
getEstimatedTotalSize,
|
|
39
|
-
getItemSize,
|
|
40
|
-
getOffsetForIndexAndAlignment,
|
|
41
|
-
getStartIndexForOffset,
|
|
42
|
-
getStopIndexForStartIndex,
|
|
43
|
-
initInstanceProps,
|
|
44
|
-
shouldResetStyleCacheOnItemSizeChange,
|
|
45
|
-
validateProps
|
|
46
|
-
}) {
|
|
47
|
-
let _class, _temp
|
|
48
|
-
|
|
49
|
-
return _temp = _class = class List extends PureComponent {
|
|
50
|
-
// Always use explicit constructor for React components.
|
|
51
|
-
// It produces less code after transpilation. (#26)
|
|
52
|
-
// eslint-disable-next-line no-useless-constructor
|
|
53
|
-
constructor (props) {
|
|
54
|
-
super(props)
|
|
55
|
-
this._instanceProps = initInstanceProps(this.props, this)
|
|
56
|
-
this._outerRef = void 0
|
|
57
|
-
this._resetIsScrollingTimeoutId = null
|
|
58
|
-
this.state = {
|
|
59
|
-
id: this.props.id || `virtual-list-${INSTANCE_ID++}`,
|
|
60
|
-
instance: this,
|
|
61
|
-
isScrolling: false,
|
|
62
|
-
scrollDirection: 'forward',
|
|
63
|
-
scrollOffset: typeof this.props.initialScrollOffset === 'number' ? this.props.initialScrollOffset : 0,
|
|
64
|
-
scrollUpdateWasRequested: false,
|
|
65
|
-
sizeList: []
|
|
66
|
-
}
|
|
67
|
-
if (this.props.unlimitedSize) {
|
|
68
|
-
this.state.sizeList = new Array(this.props.itemCount).fill(-1)
|
|
69
|
-
}
|
|
70
|
-
this.field = {
|
|
71
|
-
scrollLeft: 0,
|
|
72
|
-
scrollTop: 0,
|
|
73
|
-
scrollHeight: 0,
|
|
74
|
-
scrollWidth: 0,
|
|
75
|
-
clientHeight: 0,
|
|
76
|
-
clientWidth: 0
|
|
77
|
-
}
|
|
78
|
-
this._callOnItemsRendered = void 0
|
|
79
|
-
this._callOnItemsRendered = memoizeOne((overscanStartIndex, overscanStopIndex, visibleStartIndex, visibleStopIndex) => this.props.onItemsRendered({
|
|
80
|
-
overscanStartIndex,
|
|
81
|
-
overscanStopIndex,
|
|
82
|
-
visibleStartIndex,
|
|
83
|
-
visibleStopIndex
|
|
84
|
-
}))
|
|
85
|
-
this._callOnScroll = void 0
|
|
86
|
-
this._callOnScroll = memoizeOne((scrollDirection, scrollOffset, scrollUpdateWasRequested, detail) => this.props.onScroll({
|
|
87
|
-
scrollDirection,
|
|
88
|
-
scrollOffset,
|
|
89
|
-
scrollUpdateWasRequested,
|
|
90
|
-
detail
|
|
91
|
-
}))
|
|
92
|
-
|
|
93
|
-
this._getSize = void 0
|
|
94
|
-
|
|
95
|
-
this._getSize = (size) => {
|
|
96
|
-
if (typeof size === 'number' && size >= 0) {
|
|
97
|
-
return size
|
|
98
|
-
}
|
|
99
|
-
return this.props.itemSize
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this._getSizeUploadSync = void 0
|
|
103
|
-
|
|
104
|
-
this._getSizeUploadSync = (index, isHorizontal) => {
|
|
105
|
-
const ID = `#${this.state.id}-${index}`
|
|
106
|
-
|
|
107
|
-
return new Promise((resolve) => {
|
|
108
|
-
const success = ({ width, height }) => {
|
|
109
|
-
const { sizeList } = this.state
|
|
110
|
-
const size = isHorizontal ? width : height
|
|
111
|
-
if (size !== sizeList[index]) {
|
|
112
|
-
sizeList[index] = this._getSize(size)
|
|
113
|
-
this.setState({
|
|
114
|
-
sizeList: [...sizeList]
|
|
115
|
-
}, () => {
|
|
116
|
-
resolve(this._getSize(size))
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const fail = () => {
|
|
121
|
-
const [startIndex, stopIndex] = this._getRangeToRender()
|
|
122
|
-
if (index >= startIndex && index <= stopIndex) {
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
getRectSize(ID, success, fail)
|
|
125
|
-
}, 100)
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
getRectSize(ID, success, fail)
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this._getSizeUpload = (index, isHorizontal) => {
|
|
133
|
-
this._getSizeUploadSync(index, isHorizontal)
|
|
134
|
-
const { sizeList } = this.state
|
|
135
|
-
return this._getSize(sizeList[index])
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this._getCountSize = void 0
|
|
139
|
-
|
|
140
|
-
this._getCountSize = (props, count) => {
|
|
141
|
-
if (!props.unlimitedSize) {
|
|
142
|
-
return props.itemSize * count
|
|
143
|
-
}
|
|
144
|
-
const { sizeList } = this.state
|
|
145
|
-
const sizes = sizeList.slice(0, count)
|
|
146
|
-
return sizes.reduce((p, a) => {
|
|
147
|
-
return p + this._getSize(a)
|
|
148
|
-
}, 0)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
this._getSizeCount = void 0
|
|
152
|
-
|
|
153
|
-
this._getSizeCount = (props, offset) => {
|
|
154
|
-
if (offset === 0) {
|
|
155
|
-
return 0
|
|
156
|
-
}
|
|
157
|
-
if (!props.unlimitedSize) {
|
|
158
|
-
return Math.min(props.itemCount - 1, Math.floor(offset / props.itemSize))
|
|
159
|
-
}
|
|
160
|
-
let offsetSize = 0
|
|
161
|
-
const { sizeList } = this.state
|
|
162
|
-
const count = sizeList.reduce((p, a) => {
|
|
163
|
-
a = this._getSize(a)
|
|
164
|
-
if (offsetSize < offset) {
|
|
165
|
-
offsetSize += a
|
|
166
|
-
return ++p
|
|
167
|
-
}
|
|
168
|
-
return p
|
|
169
|
-
}, 0)
|
|
170
|
-
return count - 1
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
this._getStyleValue = value => {
|
|
174
|
-
return typeof value === 'number'
|
|
175
|
-
? value + 'px'
|
|
176
|
-
: value == null
|
|
177
|
-
? ''
|
|
178
|
-
: value
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
this._getItemStyle = void 0
|
|
182
|
-
|
|
183
|
-
this._getItemStyle = index => {
|
|
184
|
-
const {
|
|
185
|
-
direction,
|
|
186
|
-
itemSize,
|
|
187
|
-
layout
|
|
188
|
-
} = this.props
|
|
189
|
-
|
|
190
|
-
const itemStyleCache = this._getItemStyleCache(shouldResetStyleCacheOnItemSizeChange && itemSize, shouldResetStyleCacheOnItemSizeChange && layout, shouldResetStyleCacheOnItemSizeChange && direction)
|
|
191
|
-
|
|
192
|
-
let style
|
|
193
|
-
|
|
194
|
-
const offset = getItemOffset(this.props, index, this)
|
|
195
|
-
const size = getItemSize(this.props, index, this) // TODO Deprecate direction "horizontal"
|
|
196
|
-
const isHorizontal = isHorizontalFunc(this.props)
|
|
197
|
-
const isRtl = isRtlFunc(this.props)
|
|
198
|
-
if (itemStyleCache.hasOwnProperty(index)) {
|
|
199
|
-
style = itemStyleCache[index]
|
|
200
|
-
if (isHorizontal) {
|
|
201
|
-
style.width = size
|
|
202
|
-
if (isRtl) {
|
|
203
|
-
style.right = offset
|
|
204
|
-
} else {
|
|
205
|
-
style.left = offset
|
|
206
|
-
}
|
|
207
|
-
} else {
|
|
208
|
-
style.height = size
|
|
209
|
-
style.top = offset
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
const offsetHorizontal = isHorizontal ? offset : 0
|
|
213
|
-
itemStyleCache[index] = style = {
|
|
214
|
-
position: 'absolute',
|
|
215
|
-
left: !isRtl ? offsetHorizontal : undefined,
|
|
216
|
-
right: isRtl ? offsetHorizontal : undefined,
|
|
217
|
-
top: !isHorizontal ? offset : 0,
|
|
218
|
-
height: !isHorizontal ? size : '100%',
|
|
219
|
-
width: isHorizontal ? size : '100%'
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
for (const k in style) {
|
|
224
|
-
if (style.hasOwnProperty(k)) {
|
|
225
|
-
style[k] = this._getStyleValue(style[k])
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return style
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
this._getItemStyleCache = void 0
|
|
233
|
-
this._getItemStyleCache = memoizeOne(() => ({}))
|
|
234
|
-
|
|
235
|
-
this._onScrollHorizontal = event => {
|
|
236
|
-
const {
|
|
237
|
-
clientWidth,
|
|
238
|
-
scrollTop,
|
|
239
|
-
scrollLeft,
|
|
240
|
-
scrollHeight,
|
|
241
|
-
scrollWidth
|
|
242
|
-
} = event.currentTarget
|
|
243
|
-
this.field.scrollHeight = scrollHeight
|
|
244
|
-
this.field.scrollWidth = getEstimatedTotalSize(this.props, this)
|
|
245
|
-
this.field.scrollTop = scrollTop
|
|
246
|
-
this.field.scrollLeft = scrollLeft
|
|
247
|
-
this.field.clientHeight = scrollHeight
|
|
248
|
-
this.field.clientWidth = clientWidth
|
|
249
|
-
this.setState(prevState => {
|
|
250
|
-
if (prevState.scrollOffset === scrollLeft) {
|
|
251
|
-
// Scroll position may have been updated by cDM/cDU,
|
|
252
|
-
// In which case we don't need to trigger another render,
|
|
253
|
-
// And we don't want to update state.isScrolling.
|
|
254
|
-
return null
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
let scrollOffset = scrollLeft
|
|
258
|
-
|
|
259
|
-
if (isRtlFunc(this.props)) {
|
|
260
|
-
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
261
|
-
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
262
|
-
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
|
263
|
-
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
|
264
|
-
switch (getRTLOffsetType()) {
|
|
265
|
-
case 'negative':
|
|
266
|
-
scrollOffset = -scrollLeft
|
|
267
|
-
break
|
|
268
|
-
|
|
269
|
-
case 'positive-descending':
|
|
270
|
-
scrollOffset = scrollWidth - clientWidth - scrollLeft
|
|
271
|
-
break
|
|
272
|
-
}
|
|
273
|
-
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
|
274
|
-
|
|
275
|
-
scrollOffset = Math.max(0, Math.min(scrollOffset, scrollWidth - clientWidth))
|
|
276
|
-
this.field.scrollWidth = scrollOffset
|
|
277
|
-
return {
|
|
278
|
-
isScrolling: true,
|
|
279
|
-
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
|
280
|
-
scrollOffset,
|
|
281
|
-
scrollUpdateWasRequested: false
|
|
282
|
-
}
|
|
283
|
-
}, this._resetIsScrollingDebounced)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
this._onScrollVertical = event => {
|
|
287
|
-
const {
|
|
288
|
-
clientHeight,
|
|
289
|
-
scrollHeight,
|
|
290
|
-
scrollWidth,
|
|
291
|
-
scrollTop,
|
|
292
|
-
scrollLeft
|
|
293
|
-
} = event.currentTarget
|
|
294
|
-
this.setState(prevState => {
|
|
295
|
-
const diffOffset = this.field.scrollTop - scrollTop
|
|
296
|
-
if (prevState.scrollOffset === scrollTop || this.field.diffOffset === -diffOffset) {
|
|
297
|
-
// Scroll position may have been updated by cDM/cDU,
|
|
298
|
-
// In which case we don't need to trigger another render,
|
|
299
|
-
// And we don't want to update state.isScrolling.
|
|
300
|
-
return null
|
|
301
|
-
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
|
302
|
-
const scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight))
|
|
303
|
-
this.field.scrollHeight = getEstimatedTotalSize(this.props, this)
|
|
304
|
-
this.field.scrollWidth = scrollWidth
|
|
305
|
-
this.field.scrollTop = scrollOffset
|
|
306
|
-
this.field.scrollLeft = scrollLeft
|
|
307
|
-
this.field.clientHeight = clientHeight
|
|
308
|
-
this.field.clientWidth = scrollWidth
|
|
309
|
-
this.field.diffOffset = diffOffset
|
|
310
|
-
return {
|
|
311
|
-
isScrolling: true,
|
|
312
|
-
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
|
313
|
-
scrollOffset,
|
|
314
|
-
scrollUpdateWasRequested: false
|
|
315
|
-
}
|
|
316
|
-
}, this._resetIsScrollingDebounced)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
this._outerRefSetter = ref => {
|
|
320
|
-
const {
|
|
321
|
-
outerRef
|
|
322
|
-
} = this.props
|
|
323
|
-
this._outerRef = ref
|
|
324
|
-
|
|
325
|
-
if (typeof outerRef === 'function') {
|
|
326
|
-
outerRef(ref)
|
|
327
|
-
} else if (outerRef != null && typeof outerRef === 'object' && outerRef.hasOwnProperty('current')) {
|
|
328
|
-
outerRef.current = ref
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
this._resetIsScrollingDebounced = () => {
|
|
333
|
-
if (this._resetIsScrollingTimeoutId !== null) {
|
|
334
|
-
cancelTimeout(this._resetIsScrollingTimeoutId)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
this._resetIsScrollingTimeoutId = requestTimeout(this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
this._resetIsScrolling = () => {
|
|
341
|
-
this._resetIsScrollingTimeoutId = null
|
|
342
|
-
this.setState({
|
|
343
|
-
isScrolling: false
|
|
344
|
-
}, () => {
|
|
345
|
-
// Clear style cache after state update has been committed.
|
|
346
|
-
// This way we don't break pure sCU for items that don't use isScrolling param.
|
|
347
|
-
this._getItemStyleCache(-1, null)
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
static getDerivedStateFromProps (nextProps, prevState) {
|
|
353
|
-
validateProps(nextProps, prevState)
|
|
354
|
-
return null
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
scrollTo (scrollOffset) {
|
|
358
|
-
scrollOffset = Math.max(0, scrollOffset)
|
|
359
|
-
this.setState(prevState => {
|
|
360
|
-
if (prevState.scrollOffset === scrollOffset) {
|
|
361
|
-
return null
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return {
|
|
365
|
-
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
|
366
|
-
scrollOffset: scrollOffset,
|
|
367
|
-
scrollUpdateWasRequested: true
|
|
368
|
-
}
|
|
369
|
-
}, this._resetIsScrollingDebounced)
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
scrollToItem (index, align = 'auto') {
|
|
373
|
-
const {
|
|
374
|
-
itemCount
|
|
375
|
-
} = this.props
|
|
376
|
-
const {
|
|
377
|
-
scrollOffset
|
|
378
|
-
} = this.state
|
|
379
|
-
index = Math.max(0, Math.min(index, itemCount - 1))
|
|
380
|
-
this.scrollTo(getOffsetForIndexAndAlignment(this.props, this.state.id, index, align, scrollOffset, this))
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
componentDidMount () {
|
|
384
|
-
const { initialScrollOffset } = this.props
|
|
385
|
-
|
|
386
|
-
if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
|
|
387
|
-
const outerRef = this._outerRef // TODO Deprecate direction "horizontal"
|
|
388
|
-
|
|
389
|
-
if (isHorizontalFunc(this.props)) {
|
|
390
|
-
outerRef.scrollLeft = initialScrollOffset
|
|
391
|
-
} else {
|
|
392
|
-
outerRef.scrollTop = initialScrollOffset
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
this._callPropsCallbacks()
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
componentDidUpdate (prevProps, prevState) {
|
|
400
|
-
const {
|
|
401
|
-
scrollOffset,
|
|
402
|
-
scrollUpdateWasRequested
|
|
403
|
-
} = this.state
|
|
404
|
-
|
|
405
|
-
if (scrollUpdateWasRequested && this._outerRef != null) {
|
|
406
|
-
const outerRef = this._outerRef // TODO Deprecate direction "horizontal"
|
|
407
|
-
|
|
408
|
-
if (isHorizontalFunc(this.props)) {
|
|
409
|
-
if (isRtlFunc(this.props)) {
|
|
410
|
-
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
411
|
-
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
412
|
-
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
|
413
|
-
switch (getRTLOffsetType()) {
|
|
414
|
-
case 'negative':
|
|
415
|
-
outerRef.scrollLeft = -scrollOffset
|
|
416
|
-
break
|
|
417
|
-
|
|
418
|
-
case 'positive-ascending':
|
|
419
|
-
outerRef.scrollLeft = scrollOffset
|
|
420
|
-
break
|
|
421
|
-
|
|
422
|
-
default:
|
|
423
|
-
const {
|
|
424
|
-
clientWidth,
|
|
425
|
-
scrollWidth
|
|
426
|
-
} = outerRef
|
|
427
|
-
outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset
|
|
428
|
-
break
|
|
429
|
-
}
|
|
430
|
-
} else {
|
|
431
|
-
outerRef.scrollLeft = scrollOffset
|
|
432
|
-
}
|
|
433
|
-
} else {
|
|
434
|
-
outerRef.scrollTop = scrollOffset
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
this._callPropsCallbacks(prevProps, prevState)
|
|
439
|
-
|
|
440
|
-
setTimeout(() => {
|
|
441
|
-
const [startIndex, stopIndex] = this._getRangeToRender()
|
|
442
|
-
const isHorizontal = isHorizontalFunc(this.props)
|
|
443
|
-
for (let index = startIndex; index <= stopIndex; index++) {
|
|
444
|
-
this._getSizeUploadSync(index, isHorizontal)
|
|
445
|
-
}
|
|
446
|
-
}, 0)
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
componentWillUnmount () {
|
|
450
|
-
if (this._resetIsScrollingTimeoutId !== null) {
|
|
451
|
-
cancelTimeout(this._resetIsScrollingTimeoutId)
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
render () {
|
|
456
|
-
const {
|
|
457
|
-
children,
|
|
458
|
-
className,
|
|
459
|
-
direction,
|
|
460
|
-
height,
|
|
461
|
-
innerRef,
|
|
462
|
-
innerElementType,
|
|
463
|
-
innerTagName,
|
|
464
|
-
itemElementType,
|
|
465
|
-
itemTagName,
|
|
466
|
-
itemCount,
|
|
467
|
-
itemData,
|
|
468
|
-
itemKey = defaultItemKey,
|
|
469
|
-
layout,
|
|
470
|
-
outerElementType,
|
|
471
|
-
outerTagName,
|
|
472
|
-
style,
|
|
473
|
-
useIsScrolling,
|
|
474
|
-
width,
|
|
475
|
-
position,
|
|
476
|
-
renderTop,
|
|
477
|
-
renderBottom,
|
|
478
|
-
...rest
|
|
479
|
-
} = this.props
|
|
480
|
-
const {
|
|
481
|
-
id,
|
|
482
|
-
isScrolling,
|
|
483
|
-
scrollOffset,
|
|
484
|
-
scrollUpdateWasRequested
|
|
485
|
-
} = this.state // TODO Deprecate direction "horizontal"
|
|
486
|
-
|
|
487
|
-
const isHorizontal = isHorizontalFunc(this.props)
|
|
488
|
-
const onScroll = isHorizontal ? this._onScrollHorizontal : this._onScrollVertical
|
|
489
|
-
|
|
490
|
-
const [startIndex, stopIndex] = this._getRangeToRender()
|
|
491
|
-
|
|
492
|
-
const items = []
|
|
493
|
-
|
|
494
|
-
if (itemCount > 0) {
|
|
495
|
-
for (let index = startIndex; index <= stopIndex; index++) {
|
|
496
|
-
const key = itemKey(index, itemData)
|
|
497
|
-
let style
|
|
498
|
-
if (position === 'relative') {
|
|
499
|
-
const size = getItemSize(this.props, index, this)
|
|
500
|
-
style = {
|
|
501
|
-
height: this._getStyleValue(!isHorizontal ? size : '100%'),
|
|
502
|
-
width: this._getStyleValue(isHorizontal ? size : '100%')
|
|
503
|
-
}
|
|
504
|
-
} else {
|
|
505
|
-
style = this._getItemStyle(index)
|
|
506
|
-
}
|
|
507
|
-
items.push(createElement(itemElementType || itemTagName || 'div', {
|
|
508
|
-
key, style
|
|
509
|
-
}, createElement(children, {
|
|
510
|
-
id: `${id}-${index}`,
|
|
511
|
-
data: itemData,
|
|
512
|
-
index,
|
|
513
|
-
isScrolling: useIsScrolling ? isScrolling : undefined
|
|
514
|
-
})))
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
// Read this value AFTER items have been created,
|
|
518
|
-
// So their actual sizes (if variable) are taken into consideration.
|
|
519
|
-
|
|
520
|
-
const estimatedTotalSize = getEstimatedTotalSize(this.props, this)
|
|
521
|
-
const outerElementProps = {
|
|
522
|
-
...rest,
|
|
523
|
-
id,
|
|
524
|
-
className,
|
|
525
|
-
onScroll,
|
|
526
|
-
ref: this._outerRefSetter,
|
|
527
|
-
layout,
|
|
528
|
-
style: {
|
|
529
|
-
position: 'relative',
|
|
530
|
-
height: this._getStyleValue(height),
|
|
531
|
-
width: this._getStyleValue(width),
|
|
532
|
-
overflow: 'auto',
|
|
533
|
-
WebkitOverflowScrolling: 'touch',
|
|
534
|
-
willChange: 'transform',
|
|
535
|
-
direction,
|
|
536
|
-
...style
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
if (scrollUpdateWasRequested) {
|
|
540
|
-
if (isHorizontal) {
|
|
541
|
-
outerElementProps.scrollLeft = scrollOffset
|
|
542
|
-
} else {
|
|
543
|
-
outerElementProps.scrollTop = scrollOffset
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
if (position === 'relative') {
|
|
548
|
-
const pre = getItemOffset(this.props, startIndex, this)
|
|
549
|
-
return createElement(outerElementType || outerTagName || 'div', outerElementProps,
|
|
550
|
-
renderTop,
|
|
551
|
-
createElement(itemElementType || itemTagName || 'div', {
|
|
552
|
-
key: `${id}-pre`,
|
|
553
|
-
id: `${id}-pre`,
|
|
554
|
-
style: {
|
|
555
|
-
height: isHorizontal ? '100%' : this._getStyleValue(pre),
|
|
556
|
-
width: !isHorizontal ? '100%' : this._getStyleValue(pre)
|
|
557
|
-
}
|
|
558
|
-
}),
|
|
559
|
-
createElement(innerElementType || innerTagName || 'div', {
|
|
560
|
-
ref: innerRef,
|
|
561
|
-
key: `${id}-inner`,
|
|
562
|
-
id: `${id}-inner`,
|
|
563
|
-
style: {
|
|
564
|
-
pointerEvents: isScrolling ? 'none' : 'auto'
|
|
565
|
-
}
|
|
566
|
-
}, items),
|
|
567
|
-
renderBottom
|
|
568
|
-
)
|
|
569
|
-
} else {
|
|
570
|
-
return createElement(outerElementType || outerTagName || 'div', outerElementProps,
|
|
571
|
-
renderTop,
|
|
572
|
-
createElement(innerElementType || innerTagName || 'div', {
|
|
573
|
-
ref: innerRef,
|
|
574
|
-
key: `${id}-inner`,
|
|
575
|
-
id: `${id}-inner`,
|
|
576
|
-
style: {
|
|
577
|
-
height: this._getStyleValue(isHorizontal ? '100%' : estimatedTotalSize),
|
|
578
|
-
pointerEvents: isScrolling ? 'none' : 'auto',
|
|
579
|
-
width: this._getStyleValue(isHorizontal ? estimatedTotalSize : '100%')
|
|
580
|
-
}
|
|
581
|
-
}, items),
|
|
582
|
-
renderBottom
|
|
583
|
-
)
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
_callPropsCallbacks (prevProps, prevState) {
|
|
588
|
-
if (typeof this.props.onItemsRendered === 'function') {
|
|
589
|
-
if (this.props.itemCount > 0) {
|
|
590
|
-
if (!prevProps && prevProps.itemCount !== this.props.itemCount) {
|
|
591
|
-
const [overscanStartIndex, overscanStopIndex, visibleStartIndex, visibleStopIndex] = this._getRangeToRender()
|
|
592
|
-
|
|
593
|
-
this._callOnItemsRendered(overscanStartIndex, overscanStopIndex, visibleStartIndex, visibleStopIndex)
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
if (typeof this.props.onScroll === 'function') {
|
|
599
|
-
if (!prevState ||
|
|
600
|
-
prevState.scrollDirection !== this.state.scrollDirection ||
|
|
601
|
-
prevState.scrollOffset !== this.state.scrollOffset ||
|
|
602
|
-
prevState.scrollUpdateWasRequested !== this.state.scrollUpdateWasRequested
|
|
603
|
-
) {
|
|
604
|
-
this._callOnScroll(
|
|
605
|
-
this.state.scrollDirection,
|
|
606
|
-
this.state.scrollOffset,
|
|
607
|
-
this.state.scrollUpdateWasRequested,
|
|
608
|
-
this.field
|
|
609
|
-
)
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
// Lazily create and cache item styles while scrolling,
|
|
614
|
-
// So that pure component sCU will prevent re-renders.
|
|
615
|
-
// We maintain this cache, and pass a style prop rather than index,
|
|
616
|
-
// So that List can clear cached styles and force item re-render if necessary.
|
|
617
|
-
|
|
618
|
-
_getRangeToRender () {
|
|
619
|
-
const {
|
|
620
|
-
itemCount,
|
|
621
|
-
overscanCount
|
|
622
|
-
} = this.props
|
|
623
|
-
const {
|
|
624
|
-
isScrolling,
|
|
625
|
-
scrollDirection,
|
|
626
|
-
scrollOffset
|
|
627
|
-
} = this.state
|
|
628
|
-
|
|
629
|
-
if (itemCount === 0) {
|
|
630
|
-
return [0, 0, 0, 0]
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
const startIndex = getStartIndexForOffset(this.props, scrollOffset, this)
|
|
634
|
-
const stopIndex = getStopIndexForStartIndex(this.props, scrollOffset, startIndex, this) // Overscan by one item in each direction so that tab/focus works.
|
|
635
|
-
// If there isn't at least one extra item, tab loops back around.
|
|
636
|
-
|
|
637
|
-
const overscanBackward = !isScrolling || scrollDirection === 'backward' ? Math.max(1, overscanCount) : 1
|
|
638
|
-
const overscanForward = !isScrolling || scrollDirection === 'forward' ? Math.max(1, overscanCount) : 1
|
|
639
|
-
return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(itemCount - 1, stopIndex + overscanForward)), startIndex, stopIndex]
|
|
640
|
-
}
|
|
641
|
-
}, _class.defaultProps = {
|
|
642
|
-
direction: 'ltr',
|
|
643
|
-
itemData: undefined,
|
|
644
|
-
layout: 'vertical',
|
|
645
|
-
overscanCount: 2,
|
|
646
|
-
useIsScrolling: false
|
|
647
|
-
}, _temp
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// NOTE: I considered further wrapping individual items with a pure ListItem component.
|
|
651
|
-
// This would avoid ever calling the render function for the same index more than once,
|
|
652
|
-
// But it would also add the overhead of a lot of components/fibers.
|
|
653
|
-
// I assume people already do this (render function returning a class component),
|
|
654
|
-
// So my doing it would just unnecessarily double the wrappers.
|