rc-virtual-list
Advanced tools
Comparing version 0.0.0-alpha.1 to 0.0.0-alpha.2
@@ -14,3 +14,3 @@ import * as React from 'react'; | ||
children: RenderFunc<T>; | ||
dataSource: T[]; | ||
data: T[]; | ||
height?: number; | ||
@@ -33,3 +33,3 @@ itemHeight?: number; | ||
* Calculated by `scrollTop`. | ||
* We cache in the state since if `dataSource` length change, | ||
* We cache in the state since if `data` length change, | ||
* we need revert back to the located item index. | ||
@@ -63,3 +63,3 @@ */ | ||
itemHeight: number; | ||
dataSource: any[]; | ||
data: any[]; | ||
}; | ||
@@ -80,5 +80,6 @@ state: ListState<T>; | ||
* Lock scroll process with `onScroll` event. | ||
* This is used for `dataSource` length change and `scrollTop` restore | ||
* This is used for `data` length change and `scrollTop` restore | ||
*/ | ||
lockScroll: boolean; | ||
constructor(props: ListProps<T>); | ||
/** | ||
@@ -103,3 +104,4 @@ * Phase 1: Initial should sync with default scroll top | ||
collectItemHeights: () => void; | ||
scrollTo(arg: number | RelativeScroll): void; | ||
scrollTo(scrollTop: number): void; | ||
internalScrollTo(relativeScroll: RelativeScroll): void; | ||
/** | ||
@@ -106,0 +108,0 @@ * Phase 4: Render item and get all the visible items height |
240
es/List.js
@@ -0,1 +1,3 @@ | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
@@ -11,4 +13,2 @@ | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -62,3 +62,3 @@ | ||
function List() { | ||
function List(props) { | ||
var _this; | ||
@@ -68,3 +68,3 @@ | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(List).apply(this, arguments)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(List).call(this, props)); | ||
_this.state = { | ||
@@ -83,9 +83,4 @@ status: 'NONE', | ||
/** | ||
* Always point to the latest props if `disabled` is `false` | ||
*/ | ||
_this.cachedProps = {}; | ||
/** | ||
* Lock scroll process with `onScroll` event. | ||
* This is used for `dataSource` length change and `scrollTop` restore | ||
* This is used for `data` length change and `scrollTop` restore | ||
*/ | ||
@@ -100,3 +95,3 @@ | ||
var _this$props = _this.props, | ||
dataSource = _this$props.dataSource, | ||
data = _this$props.data, | ||
height = _this$props.height, | ||
@@ -118,3 +113,3 @@ itemHeight = _this$props.itemHeight, | ||
var _getRangeIndex = getRangeIndex(scrollPtg, dataSource.length, visibleCount), | ||
var _getRangeIndex = getRangeIndex(scrollPtg, data.length, visibleCount), | ||
itemIndex = _getRangeIndex.itemIndex, | ||
@@ -137,12 +132,13 @@ itemOffsetPtg = _getRangeIndex.itemOffsetPtg, | ||
var mergedProps = props || _this.props; | ||
var _mergedProps$dataSour = mergedProps.dataSource, | ||
dataSource = _mergedProps$dataSour === void 0 ? [] : _mergedProps$dataSour; // Return ghost key as latest index item | ||
var _mergedProps$data = mergedProps.data, | ||
data = _mergedProps$data === void 0 ? [] : _mergedProps$data; // Return ghost key as latest index item | ||
if (index === dataSource.length) { | ||
if (index === data.length) { | ||
return GHOST_ITEM_KEY; | ||
} | ||
var item = dataSource[index]; | ||
var item = data[index]; | ||
if (!item) { | ||
/* istanbul ignore next */ | ||
console.error('Not find index item. Please report this since it is a bug.'); | ||
@@ -200,2 +196,3 @@ } | ||
_this.cachedProps = props; | ||
return _this; | ||
@@ -211,4 +208,6 @@ } | ||
value: function componentDidMount() { | ||
this.listRef.current.scrollTop = 0; | ||
this.onScroll(); | ||
if (this.listRef.current) { | ||
this.listRef.current.scrollTop = 0; | ||
this.onScroll(); | ||
} | ||
} | ||
@@ -227,9 +226,9 @@ /** | ||
var _this$props2 = this.props, | ||
dataSource = _this$props2.dataSource, | ||
data = _this$props2.data, | ||
height = _this$props2.height, | ||
itemHeight = _this$props2.itemHeight, | ||
disabled = _this$props2.disabled; | ||
var prevDataSource = this.cachedProps.dataSource || []; | ||
var prevData = this.cachedProps.data || []; | ||
if (disabled) { | ||
if (disabled || !this.listRef.current) { | ||
return; | ||
@@ -268,3 +267,3 @@ } | ||
/** | ||
* Re-calculate the item position since `dataSource` length changed. | ||
* Re-calculate the item position since `data` length changed. | ||
* [IMPORTANT] We use relative position calculate here. | ||
@@ -274,3 +273,3 @@ */ | ||
if (prevDataSource.length !== dataSource.length && height) { | ||
if (prevData.length !== data.length && height) { | ||
var _this$state3 = this.state, | ||
@@ -291,3 +290,3 @@ originItemIndex = _this$state3.itemIndex, | ||
scrollTop: originScrollTop, | ||
scrollHeight: prevDataSource.length * itemHeight, | ||
scrollHeight: prevData.length * itemHeight, | ||
clientHeight: this.listRef.current.clientHeight | ||
@@ -301,3 +300,3 @@ }), | ||
var changedItemIndex = findListDiffIndex(prevDataSource, dataSource, this.getItemKey); | ||
var changedItemIndex = findListDiffIndex(prevData, data, this.getItemKey); | ||
var originCompareItemIndex = changedItemIndex - 1; // Use next one since there are not more item before removed | ||
@@ -321,3 +320,3 @@ | ||
}); | ||
this.scrollTo({ | ||
this.internalScrollTo({ | ||
itemIndex: originCompareItemIndex, | ||
@@ -332,104 +331,105 @@ relativeTop: originCompareItemTop | ||
key: "scrollTo", | ||
value: function scrollTo(arg) { | ||
value: function scrollTo(scrollTop) { | ||
this.listRef.current.scrollTop = scrollTop; | ||
} | ||
}, { | ||
key: "internalScrollTo", | ||
value: function internalScrollTo(relativeScroll) { | ||
var _this3 = this; | ||
if (typeof arg === 'number') { | ||
this.listRef.current.scrollTop = arg; | ||
} else if (_typeof(arg) === 'object') { | ||
var compareItemIndex = arg.itemIndex, | ||
compareItemRelativeTop = arg.relativeTop; | ||
var originScrollTop = this.state.scrollTop; | ||
var _this$props3 = this.props, | ||
dataSource = _this$props3.dataSource, | ||
itemHeight = _this$props3.itemHeight, | ||
height = _this$props3.height; // 1. Find the best match compare item top | ||
var compareItemIndex = relativeScroll.itemIndex, | ||
compareItemRelativeTop = relativeScroll.relativeTop; | ||
var originScrollTop = this.state.scrollTop; | ||
var _this$props3 = this.props, | ||
data = _this$props3.data, | ||
itemHeight = _this$props3.itemHeight, | ||
height = _this$props3.height; // 1. Find the best match compare item top | ||
var bestSimilarity = Number.MAX_VALUE; | ||
var bestScrollTop = null; | ||
var bestItemIndex = null; | ||
var bestItemOffsetPtg = null; | ||
var bestStartIndex = null; | ||
var bestEndIndex = null; | ||
var missSimilarity = 0; | ||
var scrollHeight = dataSource.length * itemHeight; | ||
var clientHeight = this.listRef.current.clientHeight; | ||
var maxScrollTop = scrollHeight - clientHeight; | ||
var bestSimilarity = Number.MAX_VALUE; | ||
var bestScrollTop = null; | ||
var bestItemIndex = null; | ||
var bestItemOffsetPtg = null; | ||
var bestStartIndex = null; | ||
var bestEndIndex = null; | ||
var missSimilarity = 0; | ||
var scrollHeight = data.length * itemHeight; | ||
var clientHeight = this.listRef.current.clientHeight; | ||
var maxScrollTop = scrollHeight - clientHeight; | ||
for (var i = 0; i < maxScrollTop; i += 1) { | ||
var scrollTop = getIndexByStartLoc(0, maxScrollTop, originScrollTop, i); | ||
var scrollPtg = getScrollPercentage({ | ||
scrollTop: scrollTop, | ||
scrollHeight: scrollHeight, | ||
clientHeight: clientHeight | ||
}); | ||
var visibleCount = Math.ceil(height / itemHeight); | ||
for (var i = 0; i < maxScrollTop; i += 1) { | ||
var scrollTop = getIndexByStartLoc(0, maxScrollTop, originScrollTop, i); | ||
var scrollPtg = getScrollPercentage({ | ||
scrollTop: scrollTop, | ||
scrollHeight: scrollHeight, | ||
clientHeight: clientHeight | ||
}); | ||
var visibleCount = Math.ceil(height / itemHeight); | ||
var _getRangeIndex2 = getRangeIndex(scrollPtg, dataSource.length, visibleCount), | ||
itemIndex = _getRangeIndex2.itemIndex, | ||
itemOffsetPtg = _getRangeIndex2.itemOffsetPtg, | ||
startIndex = _getRangeIndex2.startIndex, | ||
endIndex = _getRangeIndex2.endIndex; // No need to check if compare item out of the index to save performance | ||
var _getRangeIndex2 = getRangeIndex(scrollPtg, data.length, visibleCount), | ||
itemIndex = _getRangeIndex2.itemIndex, | ||
itemOffsetPtg = _getRangeIndex2.itemOffsetPtg, | ||
startIndex = _getRangeIndex2.startIndex, | ||
endIndex = _getRangeIndex2.endIndex; // No need to check if compare item out of the index to save performance | ||
if (startIndex <= compareItemIndex && compareItemIndex <= endIndex) { | ||
// 1.1 Get measure located item relative top | ||
var locatedItemRelativeTop = getItemRelativeTop({ | ||
itemIndex: itemIndex, | ||
itemOffsetPtg: itemOffsetPtg, | ||
itemElementHeights: this.itemElementHeights, | ||
scrollPtg: scrollPtg, | ||
clientHeight: clientHeight, | ||
getItemKey: this.getIndexKey | ||
}); | ||
var compareItemTop = getCompareItemRelativeTop({ | ||
locatedItemRelativeTop: locatedItemRelativeTop, | ||
locatedItemIndex: itemIndex, | ||
compareItemIndex: compareItemIndex, | ||
startIndex: startIndex, | ||
endIndex: endIndex, | ||
getItemKey: this.getIndexKey, | ||
itemElementHeights: this.itemElementHeights | ||
}); // 1.2 Find best match compare item top | ||
if (startIndex <= compareItemIndex && compareItemIndex <= endIndex) { | ||
// 1.1 Get measure located item relative top | ||
var locatedItemRelativeTop = getItemRelativeTop({ | ||
itemIndex: itemIndex, | ||
itemOffsetPtg: itemOffsetPtg, | ||
itemElementHeights: this.itemElementHeights, | ||
scrollPtg: scrollPtg, | ||
clientHeight: clientHeight, | ||
getItemKey: this.getIndexKey | ||
}); | ||
var compareItemTop = getCompareItemRelativeTop({ | ||
locatedItemRelativeTop: locatedItemRelativeTop, | ||
locatedItemIndex: itemIndex, | ||
compareItemIndex: compareItemIndex, | ||
startIndex: startIndex, | ||
endIndex: endIndex, | ||
getItemKey: this.getIndexKey, | ||
itemElementHeights: this.itemElementHeights | ||
}); // 1.2 Find best match compare item top | ||
var similarity = Math.abs(compareItemTop - compareItemRelativeTop); | ||
var similarity = Math.abs(compareItemTop - compareItemRelativeTop); | ||
if (similarity < bestSimilarity) { | ||
bestSimilarity = similarity; | ||
bestScrollTop = scrollTop; | ||
bestItemIndex = itemIndex; | ||
bestItemOffsetPtg = itemOffsetPtg; | ||
bestStartIndex = startIndex; | ||
bestEndIndex = endIndex; | ||
missSimilarity = 0; | ||
} else { | ||
missSimilarity += 1; | ||
} | ||
} // If keeping 10 times not match similarity, | ||
// check more scrollTop is meaningless. | ||
// Here boundary is set to 10. | ||
if (similarity < bestSimilarity) { | ||
bestSimilarity = similarity; | ||
bestScrollTop = scrollTop; | ||
bestItemIndex = itemIndex; | ||
bestItemOffsetPtg = itemOffsetPtg; | ||
bestStartIndex = startIndex; | ||
bestEndIndex = endIndex; | ||
missSimilarity = 0; | ||
} else { | ||
missSimilarity += 1; | ||
} | ||
} // If keeping 10 times not match similarity, | ||
// check more scrollTop is meaningless. | ||
// Here boundary is set to 10. | ||
if (missSimilarity > 10) { | ||
break; | ||
} | ||
} // 2. Re-scroll if has best scroll match | ||
if (missSimilarity > 10) { | ||
break; | ||
} | ||
} // 2. Re-scroll if has best scroll match | ||
if (bestScrollTop !== null) { | ||
this.lockScroll = true; | ||
this.listRef.current.scrollTop = bestScrollTop; | ||
this.setState({ | ||
status: 'MEASURE_START', | ||
scrollTop: bestScrollTop, | ||
itemIndex: bestItemIndex, | ||
itemOffsetPtg: bestItemOffsetPtg, | ||
startIndex: bestStartIndex, | ||
endIndex: bestEndIndex | ||
}); | ||
if (bestScrollTop !== null) { | ||
this.lockScroll = true; | ||
this.listRef.current.scrollTop = bestScrollTop; | ||
this.setState({ | ||
status: 'MEASURE_START', | ||
scrollTop: bestScrollTop, | ||
itemIndex: bestItemIndex, | ||
itemOffsetPtg: bestItemOffsetPtg, | ||
startIndex: bestStartIndex, | ||
endIndex: bestEndIndex | ||
}); | ||
requestAnimationFrame(function () { | ||
requestAnimationFrame(function () { | ||
requestAnimationFrame(function () { | ||
_this3.lockScroll = false; | ||
}); | ||
_this3.lockScroll = false; | ||
}); | ||
} | ||
}); | ||
} | ||
@@ -446,6 +446,6 @@ } | ||
itemHeight = _this$props4.itemHeight, | ||
dataSource = _this$props4.dataSource, | ||
data = _this$props4.data, | ||
children = _this$props4.children, | ||
itemKey = _this$props4.itemKey, | ||
restProps = _objectWithoutProperties(_this$props4, ["style", "component", "height", "itemHeight", "dataSource", "children", "itemKey"]); | ||
restProps = _objectWithoutProperties(_this$props4, ["style", "component", "height", "itemHeight", "data", "children", "itemKey"]); | ||
@@ -459,3 +459,3 @@ var mergedStyle = _objectSpread({}, style, { | ||
if (height === undefined || dataSource.length * itemHeight <= height) { | ||
if (height === undefined || data.length * itemHeight <= height) { | ||
return React.createElement(Component, Object.assign({ | ||
@@ -465,3 +465,3 @@ style: mergedStyle | ||
height: height | ||
}, this.renderChildren(dataSource, 0, children))); | ||
}, this.renderChildren(data, 0, children))); | ||
} | ||
@@ -474,3 +474,3 @@ | ||
startItemTop = _this$state4.startItemTop; | ||
var contentHeight = dataSource.length * itemHeight * ITEM_SCALE_RATE; | ||
var contentHeight = data.length * itemHeight * ITEM_SCALE_RATE; | ||
return React.createElement(Component, Object.assign({ | ||
@@ -484,3 +484,3 @@ style: mergedStyle | ||
offset: status === 'MEASURE_DONE' ? startItemTop : 0 | ||
}, this.renderChildren(dataSource.slice(startIndex, endIndex + 1), startIndex, children))); | ||
}, this.renderChildren(data.slice(startIndex, endIndex + 1), startIndex, children))); | ||
} | ||
@@ -494,4 +494,4 @@ }]); | ||
itemHeight: 15, | ||
dataSource: [] | ||
data: [] | ||
}; | ||
export default List; |
@@ -47,3 +47,3 @@ /** | ||
var startIndex = 0; | ||
var endIndex = originList.length - 1; | ||
var endIndex = Math.max(originList.length, targetList.length) - 1; | ||
var midIndex = Math.floor((startIndex + endIndex) / 2); | ||
@@ -50,0 +50,0 @@ var keyCache = new Map(); |
/** | ||
* Our algorithm have additional one ghost item | ||
* whose index as `dataSource.length` to simplify the calculation | ||
* whose index as `data.length` to simplify the calculation | ||
*/ | ||
@@ -5,0 +5,0 @@ export declare const GHOST_ITEM_KEY = "__rc_ghost_item__"; |
@@ -8,3 +8,3 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } | ||
* Our algorithm have additional one ghost item | ||
* whose index as `dataSource.length` to simplify the calculation | ||
* whose index as `data.length` to simplify the calculation | ||
*/ | ||
@@ -11,0 +11,0 @@ |
@@ -14,3 +14,3 @@ import * as React from 'react'; | ||
children: RenderFunc<T>; | ||
dataSource: T[]; | ||
data: T[]; | ||
height?: number; | ||
@@ -33,3 +33,3 @@ itemHeight?: number; | ||
* Calculated by `scrollTop`. | ||
* We cache in the state since if `dataSource` length change, | ||
* We cache in the state since if `data` length change, | ||
* we need revert back to the located item index. | ||
@@ -63,3 +63,3 @@ */ | ||
itemHeight: number; | ||
dataSource: any[]; | ||
data: any[]; | ||
}; | ||
@@ -80,5 +80,6 @@ state: ListState<T>; | ||
* Lock scroll process with `onScroll` event. | ||
* This is used for `dataSource` length change and `scrollTop` restore | ||
* This is used for `data` length change and `scrollTop` restore | ||
*/ | ||
lockScroll: boolean; | ||
constructor(props: ListProps<T>); | ||
/** | ||
@@ -103,3 +104,4 @@ * Phase 1: Initial should sync with default scroll top | ||
collectItemHeights: () => void; | ||
scrollTo(arg: number | RelativeScroll): void; | ||
scrollTo(scrollTop: number): void; | ||
internalScrollTo(relativeScroll: RelativeScroll): void; | ||
/** | ||
@@ -106,0 +108,0 @@ * Phase 4: Render item and get all the visible items height |
240
lib/List.js
@@ -20,2 +20,4 @@ "use strict"; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
@@ -31,4 +33,2 @@ | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -78,3 +78,3 @@ | ||
function List() { | ||
function List(props) { | ||
var _this; | ||
@@ -84,3 +84,3 @@ | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(List).apply(this, arguments)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(List).call(this, props)); | ||
_this.state = { | ||
@@ -99,9 +99,4 @@ status: 'NONE', | ||
/** | ||
* Always point to the latest props if `disabled` is `false` | ||
*/ | ||
_this.cachedProps = {}; | ||
/** | ||
* Lock scroll process with `onScroll` event. | ||
* This is used for `dataSource` length change and `scrollTop` restore | ||
* This is used for `data` length change and `scrollTop` restore | ||
*/ | ||
@@ -116,3 +111,3 @@ | ||
var _this$props = _this.props, | ||
dataSource = _this$props.dataSource, | ||
data = _this$props.data, | ||
height = _this$props.height, | ||
@@ -134,3 +129,3 @@ itemHeight = _this$props.itemHeight, | ||
var _getRangeIndex = (0, _itemUtil.getRangeIndex)(scrollPtg, dataSource.length, visibleCount), | ||
var _getRangeIndex = (0, _itemUtil.getRangeIndex)(scrollPtg, data.length, visibleCount), | ||
itemIndex = _getRangeIndex.itemIndex, | ||
@@ -153,12 +148,13 @@ itemOffsetPtg = _getRangeIndex.itemOffsetPtg, | ||
var mergedProps = props || _this.props; | ||
var _mergedProps$dataSour = mergedProps.dataSource, | ||
dataSource = _mergedProps$dataSour === void 0 ? [] : _mergedProps$dataSour; // Return ghost key as latest index item | ||
var _mergedProps$data = mergedProps.data, | ||
data = _mergedProps$data === void 0 ? [] : _mergedProps$data; // Return ghost key as latest index item | ||
if (index === dataSource.length) { | ||
if (index === data.length) { | ||
return _itemUtil.GHOST_ITEM_KEY; | ||
} | ||
var item = dataSource[index]; | ||
var item = data[index]; | ||
if (!item) { | ||
/* istanbul ignore next */ | ||
console.error('Not find index item. Please report this since it is a bug.'); | ||
@@ -216,2 +212,3 @@ } | ||
_this.cachedProps = props; | ||
return _this; | ||
@@ -227,4 +224,6 @@ } | ||
value: function componentDidMount() { | ||
this.listRef.current.scrollTop = 0; | ||
this.onScroll(); | ||
if (this.listRef.current) { | ||
this.listRef.current.scrollTop = 0; | ||
this.onScroll(); | ||
} | ||
} | ||
@@ -243,9 +242,9 @@ /** | ||
var _this$props2 = this.props, | ||
dataSource = _this$props2.dataSource, | ||
data = _this$props2.data, | ||
height = _this$props2.height, | ||
itemHeight = _this$props2.itemHeight, | ||
disabled = _this$props2.disabled; | ||
var prevDataSource = this.cachedProps.dataSource || []; | ||
var prevData = this.cachedProps.data || []; | ||
if (disabled) { | ||
if (disabled || !this.listRef.current) { | ||
return; | ||
@@ -284,3 +283,3 @@ } | ||
/** | ||
* Re-calculate the item position since `dataSource` length changed. | ||
* Re-calculate the item position since `data` length changed. | ||
* [IMPORTANT] We use relative position calculate here. | ||
@@ -290,3 +289,3 @@ */ | ||
if (prevDataSource.length !== dataSource.length && height) { | ||
if (prevData.length !== data.length && height) { | ||
var _this$state3 = this.state, | ||
@@ -307,3 +306,3 @@ originItemIndex = _this$state3.itemIndex, | ||
scrollTop: originScrollTop, | ||
scrollHeight: prevDataSource.length * itemHeight, | ||
scrollHeight: prevData.length * itemHeight, | ||
clientHeight: this.listRef.current.clientHeight | ||
@@ -317,3 +316,3 @@ }), | ||
var changedItemIndex = (0, _algorithmUtil.findListDiffIndex)(prevDataSource, dataSource, this.getItemKey); | ||
var changedItemIndex = (0, _algorithmUtil.findListDiffIndex)(prevData, data, this.getItemKey); | ||
var originCompareItemIndex = changedItemIndex - 1; // Use next one since there are not more item before removed | ||
@@ -337,3 +336,3 @@ | ||
}); | ||
this.scrollTo({ | ||
this.internalScrollTo({ | ||
itemIndex: originCompareItemIndex, | ||
@@ -348,104 +347,105 @@ relativeTop: originCompareItemTop | ||
key: "scrollTo", | ||
value: function scrollTo(arg) { | ||
value: function scrollTo(scrollTop) { | ||
this.listRef.current.scrollTop = scrollTop; | ||
} | ||
}, { | ||
key: "internalScrollTo", | ||
value: function internalScrollTo(relativeScroll) { | ||
var _this3 = this; | ||
if (typeof arg === 'number') { | ||
this.listRef.current.scrollTop = arg; | ||
} else if (_typeof(arg) === 'object') { | ||
var compareItemIndex = arg.itemIndex, | ||
compareItemRelativeTop = arg.relativeTop; | ||
var originScrollTop = this.state.scrollTop; | ||
var _this$props3 = this.props, | ||
dataSource = _this$props3.dataSource, | ||
itemHeight = _this$props3.itemHeight, | ||
height = _this$props3.height; // 1. Find the best match compare item top | ||
var compareItemIndex = relativeScroll.itemIndex, | ||
compareItemRelativeTop = relativeScroll.relativeTop; | ||
var originScrollTop = this.state.scrollTop; | ||
var _this$props3 = this.props, | ||
data = _this$props3.data, | ||
itemHeight = _this$props3.itemHeight, | ||
height = _this$props3.height; // 1. Find the best match compare item top | ||
var bestSimilarity = Number.MAX_VALUE; | ||
var bestScrollTop = null; | ||
var bestItemIndex = null; | ||
var bestItemOffsetPtg = null; | ||
var bestStartIndex = null; | ||
var bestEndIndex = null; | ||
var missSimilarity = 0; | ||
var scrollHeight = dataSource.length * itemHeight; | ||
var clientHeight = this.listRef.current.clientHeight; | ||
var maxScrollTop = scrollHeight - clientHeight; | ||
var bestSimilarity = Number.MAX_VALUE; | ||
var bestScrollTop = null; | ||
var bestItemIndex = null; | ||
var bestItemOffsetPtg = null; | ||
var bestStartIndex = null; | ||
var bestEndIndex = null; | ||
var missSimilarity = 0; | ||
var scrollHeight = data.length * itemHeight; | ||
var clientHeight = this.listRef.current.clientHeight; | ||
var maxScrollTop = scrollHeight - clientHeight; | ||
for (var i = 0; i < maxScrollTop; i += 1) { | ||
var scrollTop = (0, _algorithmUtil.getIndexByStartLoc)(0, maxScrollTop, originScrollTop, i); | ||
var scrollPtg = (0, _itemUtil.getScrollPercentage)({ | ||
scrollTop: scrollTop, | ||
scrollHeight: scrollHeight, | ||
clientHeight: clientHeight | ||
}); | ||
var visibleCount = Math.ceil(height / itemHeight); | ||
for (var i = 0; i < maxScrollTop; i += 1) { | ||
var scrollTop = (0, _algorithmUtil.getIndexByStartLoc)(0, maxScrollTop, originScrollTop, i); | ||
var scrollPtg = (0, _itemUtil.getScrollPercentage)({ | ||
scrollTop: scrollTop, | ||
scrollHeight: scrollHeight, | ||
clientHeight: clientHeight | ||
}); | ||
var visibleCount = Math.ceil(height / itemHeight); | ||
var _getRangeIndex2 = (0, _itemUtil.getRangeIndex)(scrollPtg, dataSource.length, visibleCount), | ||
itemIndex = _getRangeIndex2.itemIndex, | ||
itemOffsetPtg = _getRangeIndex2.itemOffsetPtg, | ||
startIndex = _getRangeIndex2.startIndex, | ||
endIndex = _getRangeIndex2.endIndex; // No need to check if compare item out of the index to save performance | ||
var _getRangeIndex2 = (0, _itemUtil.getRangeIndex)(scrollPtg, data.length, visibleCount), | ||
itemIndex = _getRangeIndex2.itemIndex, | ||
itemOffsetPtg = _getRangeIndex2.itemOffsetPtg, | ||
startIndex = _getRangeIndex2.startIndex, | ||
endIndex = _getRangeIndex2.endIndex; // No need to check if compare item out of the index to save performance | ||
if (startIndex <= compareItemIndex && compareItemIndex <= endIndex) { | ||
// 1.1 Get measure located item relative top | ||
var locatedItemRelativeTop = (0, _itemUtil.getItemRelativeTop)({ | ||
itemIndex: itemIndex, | ||
itemOffsetPtg: itemOffsetPtg, | ||
itemElementHeights: this.itemElementHeights, | ||
scrollPtg: scrollPtg, | ||
clientHeight: clientHeight, | ||
getItemKey: this.getIndexKey | ||
}); | ||
var compareItemTop = (0, _itemUtil.getCompareItemRelativeTop)({ | ||
locatedItemRelativeTop: locatedItemRelativeTop, | ||
locatedItemIndex: itemIndex, | ||
compareItemIndex: compareItemIndex, | ||
startIndex: startIndex, | ||
endIndex: endIndex, | ||
getItemKey: this.getIndexKey, | ||
itemElementHeights: this.itemElementHeights | ||
}); // 1.2 Find best match compare item top | ||
if (startIndex <= compareItemIndex && compareItemIndex <= endIndex) { | ||
// 1.1 Get measure located item relative top | ||
var locatedItemRelativeTop = (0, _itemUtil.getItemRelativeTop)({ | ||
itemIndex: itemIndex, | ||
itemOffsetPtg: itemOffsetPtg, | ||
itemElementHeights: this.itemElementHeights, | ||
scrollPtg: scrollPtg, | ||
clientHeight: clientHeight, | ||
getItemKey: this.getIndexKey | ||
}); | ||
var compareItemTop = (0, _itemUtil.getCompareItemRelativeTop)({ | ||
locatedItemRelativeTop: locatedItemRelativeTop, | ||
locatedItemIndex: itemIndex, | ||
compareItemIndex: compareItemIndex, | ||
startIndex: startIndex, | ||
endIndex: endIndex, | ||
getItemKey: this.getIndexKey, | ||
itemElementHeights: this.itemElementHeights | ||
}); // 1.2 Find best match compare item top | ||
var similarity = Math.abs(compareItemTop - compareItemRelativeTop); | ||
var similarity = Math.abs(compareItemTop - compareItemRelativeTop); | ||
if (similarity < bestSimilarity) { | ||
bestSimilarity = similarity; | ||
bestScrollTop = scrollTop; | ||
bestItemIndex = itemIndex; | ||
bestItemOffsetPtg = itemOffsetPtg; | ||
bestStartIndex = startIndex; | ||
bestEndIndex = endIndex; | ||
missSimilarity = 0; | ||
} else { | ||
missSimilarity += 1; | ||
} | ||
} // If keeping 10 times not match similarity, | ||
// check more scrollTop is meaningless. | ||
// Here boundary is set to 10. | ||
if (similarity < bestSimilarity) { | ||
bestSimilarity = similarity; | ||
bestScrollTop = scrollTop; | ||
bestItemIndex = itemIndex; | ||
bestItemOffsetPtg = itemOffsetPtg; | ||
bestStartIndex = startIndex; | ||
bestEndIndex = endIndex; | ||
missSimilarity = 0; | ||
} else { | ||
missSimilarity += 1; | ||
} | ||
} // If keeping 10 times not match similarity, | ||
// check more scrollTop is meaningless. | ||
// Here boundary is set to 10. | ||
if (missSimilarity > 10) { | ||
break; | ||
} | ||
} // 2. Re-scroll if has best scroll match | ||
if (missSimilarity > 10) { | ||
break; | ||
} | ||
} // 2. Re-scroll if has best scroll match | ||
if (bestScrollTop !== null) { | ||
this.lockScroll = true; | ||
this.listRef.current.scrollTop = bestScrollTop; | ||
this.setState({ | ||
status: 'MEASURE_START', | ||
scrollTop: bestScrollTop, | ||
itemIndex: bestItemIndex, | ||
itemOffsetPtg: bestItemOffsetPtg, | ||
startIndex: bestStartIndex, | ||
endIndex: bestEndIndex | ||
}); | ||
if (bestScrollTop !== null) { | ||
this.lockScroll = true; | ||
this.listRef.current.scrollTop = bestScrollTop; | ||
this.setState({ | ||
status: 'MEASURE_START', | ||
scrollTop: bestScrollTop, | ||
itemIndex: bestItemIndex, | ||
itemOffsetPtg: bestItemOffsetPtg, | ||
startIndex: bestStartIndex, | ||
endIndex: bestEndIndex | ||
}); | ||
requestAnimationFrame(function () { | ||
requestAnimationFrame(function () { | ||
requestAnimationFrame(function () { | ||
_this3.lockScroll = false; | ||
}); | ||
_this3.lockScroll = false; | ||
}); | ||
} | ||
}); | ||
} | ||
@@ -462,6 +462,6 @@ } | ||
itemHeight = _this$props4.itemHeight, | ||
dataSource = _this$props4.dataSource, | ||
data = _this$props4.data, | ||
children = _this$props4.children, | ||
itemKey = _this$props4.itemKey, | ||
restProps = _objectWithoutProperties(_this$props4, ["style", "component", "height", "itemHeight", "dataSource", "children", "itemKey"]); | ||
restProps = _objectWithoutProperties(_this$props4, ["style", "component", "height", "itemHeight", "data", "children", "itemKey"]); | ||
@@ -475,3 +475,3 @@ var mergedStyle = _objectSpread({}, style, { | ||
if (height === undefined || dataSource.length * itemHeight <= height) { | ||
if (height === undefined || data.length * itemHeight <= height) { | ||
return React.createElement(Component, Object.assign({ | ||
@@ -481,3 +481,3 @@ style: mergedStyle | ||
height: height | ||
}, this.renderChildren(dataSource, 0, children))); | ||
}, this.renderChildren(data, 0, children))); | ||
} | ||
@@ -490,3 +490,3 @@ | ||
startItemTop = _this$state4.startItemTop; | ||
var contentHeight = dataSource.length * itemHeight * ITEM_SCALE_RATE; | ||
var contentHeight = data.length * itemHeight * ITEM_SCALE_RATE; | ||
return React.createElement(Component, Object.assign({ | ||
@@ -500,3 +500,3 @@ style: mergedStyle | ||
offset: status === 'MEASURE_DONE' ? startItemTop : 0 | ||
}, this.renderChildren(dataSource.slice(startIndex, endIndex + 1), startIndex, children))); | ||
}, this.renderChildren(data.slice(startIndex, endIndex + 1), startIndex, children))); | ||
} | ||
@@ -510,5 +510,5 @@ }]); | ||
itemHeight: 15, | ||
dataSource: [] | ||
data: [] | ||
}; | ||
var _default = List; | ||
exports.default = _default; |
@@ -56,3 +56,3 @@ "use strict"; | ||
var startIndex = 0; | ||
var endIndex = originList.length - 1; | ||
var endIndex = Math.max(originList.length, targetList.length) - 1; | ||
var midIndex = Math.floor((startIndex + endIndex) / 2); | ||
@@ -59,0 +59,0 @@ var keyCache = new Map(); |
/** | ||
* Our algorithm have additional one ghost item | ||
* whose index as `dataSource.length` to simplify the calculation | ||
* whose index as `data.length` to simplify the calculation | ||
*/ | ||
@@ -5,0 +5,0 @@ export declare const GHOST_ITEM_KEY = "__rc_ghost_item__"; |
@@ -26,3 +26,3 @@ "use strict"; | ||
* Our algorithm have additional one ghost item | ||
* whose index as `dataSource.length` to simplify the calculation | ||
* whose index as `data.length` to simplify the calculation | ||
*/ | ||
@@ -29,0 +29,0 @@ var GHOST_ITEM_KEY = '__rc_ghost_item__'; |
{ | ||
"name": "rc-virtual-list", | ||
"version": "0.0.0-alpha.1", | ||
"version": "0.0.0-alpha.2", | ||
"description": "React Virtual List Component", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
# rc-virtual-list | ||
React Virtual List Component which worked with `rc-animation`. | ||
React Virtual List Component which worked with animation. | ||
[![NPM version][npm-image]][npm-url] [![build status][circleci-image]][circleci-url] [![Test coverage][coveralls-image]][coveralls-url] [![node version][node-image]][node-url] [![npm download][download-image]][download-url] | ||
[npm-image]: http://img.shields.io/npm/v/rc-virtual-list.svg?style=flat-square | ||
[npm-url]: http://npmjs.org/package/rc-virtual-list | ||
[circleci-image]: https://img.shields.io/circleci/build/github/react-component/virtual-list/master.svg?style=flat-square | ||
[circleci-url]: https://circleci.com/gh/react-component/virtual-list/tree/master | ||
[coveralls-image]: https://img.shields.io/codecov/c/github/react-component/virtual-list/master.svg?style=flat-square | ||
[coveralls-url]: https://codecov.io/gh/react-component/virtual-list | ||
[node-image]: https://img.shields.io/badge/node.js-%3E=_6.0-green.svg?style=flat-square | ||
[node-url]: http://nodejs.org/download/ | ||
[download-image]: https://img.shields.io/npm/dm/rc-virtual-list.svg?style=flat-square | ||
[download-url]: https://npmjs.org/package/rc-virtual-list | ||
## Development | ||
```bash | ||
npm install | ||
npm start | ||
open http://localhost:9001/ | ||
``` | ||
## Feature | ||
- Support react.js | ||
- Support animation | ||
- Support IE11+ | ||
## Install | ||
[![rc-virtual-list](https://nodei.co/npm/rc-virtual-list.png)](https://npmjs.org/package/rc-virtual-list) | ||
## Usage | ||
```js | ||
import List from 'rc-virtual-list'; | ||
<List data={[0, 1, 2]} height={200} itemHeight={30} itemKey="id"> | ||
{index => <div>{index}</div>} | ||
</List>; | ||
``` | ||
# API | ||
## List | ||
| Prop | Description | Type | Default | | ||
| ---------- | ------------------------------------------------------- | -------------------- | ------- | | ||
| children | Render props of item | item => ReactElement | - | | ||
| component | Customize List dom element | string \| Component | div | | ||
| data | Data list | Array | - | | ||
| disabled | Disable scroll check. Usually used on animation control | boolean | false | | ||
| height | List height | number | - | | ||
| itemHeight | Item minium height | number | - | | ||
| itemKey | Match key with item | string | - | |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
77997
1735
59
0