ant-design-vue
Version:
An enterprise-class UI design language and Vue-based implementation
103 lines (81 loc) • 3.35 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; 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); }
import raf from '../../_util/raf';
export default function useScrollTo(containerRef, state, heights, props, getKey, collectHeight, syncScrollTop, triggerFlash) {
var scroll = null;
return function (arg) {
// When not argument provided, we think dev may want to show the scrollbar
if (arg === null || arg === undefined) {
triggerFlash();
return;
} // Normal scroll logic
raf.cancel(scroll);
var data = state.mergedData;
var itemHeight = props.itemHeight;
if (typeof arg === 'number') {
syncScrollTop(arg);
} else if (arg && _typeof(arg) === 'object') {
var index;
var align = arg.align;
if ('index' in arg) {
index = arg.index;
} else {
index = data.findIndex(function (item) {
return getKey(item) === arg.key;
});
}
var _arg$offset = arg.offset,
offset = _arg$offset === void 0 ? 0 : _arg$offset; // We will retry 3 times in case dynamic height shaking
var syncScroll = function syncScroll(times, targetAlign) {
if (times < 0 || !containerRef.value) return;
var height = containerRef.value.clientHeight;
var needCollectHeight = false;
var newTargetAlign = targetAlign; // Go to next frame if height not exist
if (height) {
var mergedAlign = targetAlign || align; // Get top & bottom
var stackTop = 0;
var itemTop = 0;
var itemBottom = 0;
for (var i = 0; i <= index; i += 1) {
var key = getKey(data[i]);
itemTop = stackTop;
var cacheHeight = heights[key];
itemBottom = itemTop + (cacheHeight === undefined ? itemHeight : cacheHeight);
stackTop = itemBottom;
if (i === index && cacheHeight === undefined) {
needCollectHeight = true;
}
} // Scroll to
var targetTop = null;
switch (mergedAlign) {
case 'top':
targetTop = itemTop - offset;
break;
case 'bottom':
targetTop = itemBottom - height + offset;
break;
default:
{
var scrollTop = containerRef.value.scrollTop;
var scrollBottom = scrollTop + height;
if (itemTop < scrollTop) {
newTargetAlign = 'top';
} else if (itemBottom > scrollBottom) {
newTargetAlign = 'bottom';
}
}
}
if (targetTop !== null && targetTop !== containerRef.value.scrollTop) {
syncScrollTop(targetTop);
}
} // We will retry since element may not sync height as it described
scroll = raf(function () {
if (needCollectHeight) {
collectHeight();
}
syncScroll(times - 1, newTargetAlign);
});
};
syncScroll(3);
}
};
}