UNPKG

@tarojs/components

Version:

Taro 组件库。

194 lines (170 loc) • 6.53 kB
import createListComponent, { isHorizontalFunc } from './createListComponent' let devWarningsDirection = null let devWarningsTagName = null if (process.env.NODE_ENV !== 'production') { if (typeof window !== 'undefined' && typeof window.WeakSet !== 'undefined') { devWarningsDirection = /* #__PURE__ */ new WeakSet() devWarningsTagName = /* #__PURE__ */ new WeakSet() } } const validateSharedProps = ({ children, direction, height, layout, itemTagName, innerTagName, outerTagName, width }, { instance }) => { if (process.env.NODE_ENV !== 'production') { if (innerTagName != null || outerTagName != null || itemTagName != null) { if (devWarningsTagName && !devWarningsTagName.has(instance)) { devWarningsTagName.add(instance) console.warn('The itemTagName态innerTagName and outerTagName props have been deprecated. ' + 'Please use the itemElementType态innerElementType and outerElementType props instead.') } } // TODO Deprecate direction "horizontal" const isHorizontal = direction === 'horizontal' || layout === 'horizontal' switch (direction) { case 'horizontal': case 'vertical': if (devWarningsDirection && !devWarningsDirection.has(instance)) { devWarningsDirection.add(instance) console.warn('The direction prop should be either "ltr" (default) or "rtl". ' + 'Please use the layout prop to specify "vertical" (default) or "horizontal" orientation.') } break case 'ltr': case 'rtl': // Valid values break default: throw Error('An invalid "direction" prop has been specified. ' + 'Value should be either "ltr" or "rtl". ' + `"${direction}" was specified.`) } switch (layout) { case 'horizontal': case 'vertical': // Valid values break default: throw Error('An invalid "layout" prop has been specified. ' + 'Value should be either "horizontal" or "vertical". ' + `"${layout}" was specified.`) } if (children == null) { throw Error('An invalid "children" prop has been specified. ' + 'Value should be a React component. ' + `"${children === null ? 'null' : typeof children}" was specified.`) } if (isHorizontal && typeof width !== 'number') { throw Error('An invalid "width" prop has been specified. ' + 'Horizontal lists must specify a number for width. ' + `"${width === null ? 'null' : typeof width}" was specified.`) } else if (!isHorizontal && typeof height !== 'number') { throw Error('An invalid "height" prop has been specified. ' + 'Vertical lists must specify a number for height. ' + `"${height === null ? 'null' : typeof height}" was specified.`) } } } const FixedSizeList = /* #__PURE__ */ createListComponent({ getItemOffset (props, index, ref) { if (!props.unlimitedSize) { return index * props.itemSize } return ref._getCountSize(props, index) }, getItemSize (props, index, ref) { if (!props.unlimitedSize) { return props.itemSize } return ref._getSizeUpload(index, isHorizontalFunc(props)) }, getEstimatedTotalSize (props, ref) { return ref._getCountSize(props, props.itemCount) }, getOffsetForIndexAndAlignment: (props, id, index, align, scrollOffset, ref) => { const { height, width } = props const { sizeList } = ref.state // TODO Deprecate direction "horizontal" const size = isHorizontalFunc(props) ? width : height const itemSize = ref._getSize(sizeList[index]) const lastItemOffset = Math.max(0, ref._getCountSize(props, props.itemCount) - size) const maxOffset = Math.min(lastItemOffset, ref._getCountSize(props, index)) const minOffset = Math.max(0, ref._getCountSize(props, index) - size + itemSize) if (align === 'smart') { if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) { align = 'auto' } else { align = 'center' } } switch (align) { case 'start': return maxOffset case 'end': return minOffset case 'center': { // "Centered" offset is usually the average of the min and max. // But near the edges of the list, this doesn't hold true. const middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2) if (middleOffset < Math.ceil(size / 2)) { return 0 // near the beginning } else if (middleOffset > lastItemOffset + Math.floor(size / 2)) { return lastItemOffset // near the end } else { return middleOffset } } case 'auto': default: if (scrollOffset >= minOffset && scrollOffset <= maxOffset) { return scrollOffset } else if (scrollOffset < minOffset) { return minOffset } else { return maxOffset } } }, getStartIndexForOffset (props, scrollOffset, ref) { return Math.max(0, ref._getSizeCount(props, scrollOffset) - 1) }, getStopIndexForStartIndex (props, scrollOffset, startIndex, ref) { const { height, itemCount, itemSize, width } = props const size = isHorizontalFunc(props) ? width : height const offset = ref._getCountSize(props, startIndex) if (!props.unlimitedSize) { // TODO Deprecate direction "horizontal" const numVisibleItems = Math.ceil((size + scrollOffset - offset) / itemSize) /** -1 is because stop index is inclusive */ return Math.max(startIndex, Math.min(itemCount - 1, startIndex + numVisibleItems - 1)) } return Math.max(startIndex, Math.min(itemCount - 1, ref._getSizeCount(props, size + scrollOffset))) }, initInstanceProps () { // Noop }, shouldResetStyleCacheOnItemSizeChange: true, validateProps: (nextProps, prevState) => { const { itemCount, itemSize } = nextProps const { sizeList } = prevState if (itemCount > sizeList.length) { const arr = new Array(itemCount - sizeList.length).fill(-1) sizeList.push(...arr) } else if (itemCount < sizeList.length) { sizeList.length = itemCount } if (process.env.NODE_ENV !== 'production') { if (typeof itemSize !== 'number') { throw Error('An invalid "itemSize" prop has been specified. ' + 'Value should be a number. ' + `"${itemSize === null ? 'null' : typeof itemSize}" was specified.`) } } validateSharedProps(nextProps, prevState) } }) export default FixedSizeList