| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 | import BaseFoundation, { DefaultAdapter } from '../base/foundation';import { strings } from './constants';import { noop, get, cloneDeep } from 'lodash';const Boundary = strings.BOUNDARY_MAP;const OverflowDirection = strings.OVERFLOW_DIR;export interface OverflowListAdapter extends DefaultAdapter {    updateStates: (state: any) => void;    updateVisibleState: (visible: Map<string, boolean>) => void;    notifyIntersect: (res: any) => void;    getItemSizeMap: ()=>Map<string, number>}class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {    constructor(adapter: OverflowListAdapter) {        super({ ...adapter });    }    previousY = undefined;    isScrollMode = (): boolean => {        const { renderMode } = this.getProps();        return renderMode === 'scroll';    };    getOverflowItem(): Array<Array<Record<string, any>>> {        const { items } = this.getProps();        const { visibleState, overflow } = this.getStates();        if (!this.isScrollMode()) {            return overflow;        }        const visibleStateArr = items.map(({ key }: { key: string }) => Boolean(visibleState.get(key)));        const visibleStart = visibleStateArr.indexOf(true);        const visibleEnd = visibleStateArr.lastIndexOf(true);        const overflowList = [];        overflowList[0] = visibleStart >= 0 ? items.slice(0, visibleStart) : [];        overflowList[1] = visibleEnd >= 0 ? items.slice(visibleEnd + 1, items.length) : items;        return overflowList;    }    handleIntersect(entries: Array<IntersectionObserverEntry>): void {        const visibleState = cloneDeep(this.getState('visibleState'));        const res = {};        entries.forEach(entry => {            const itemKey = get(entry, 'target.dataset.scrollkey');            const visible = entry.isIntersecting;            res[itemKey] = entry;            visibleState.set(itemKey, visible);        });        let someItemVisible = false;        for (const value of visibleState.values()) {            if (value) {                someItemVisible = true;                break;            }        }        // Any item is visible, indicating that the List is visible        const wholeListVisible = someItemVisible;        // If scrolling in the vertical direction makes the List invisible, no processing is required.         // If this.previousY is undefined, it means that the List is mounted for the first time and will not be processed.        const [entry1] = entries;        const currentY = entry1.boundingClientRect.y;        if (!wholeListVisible && this.previousY !== undefined && currentY !== this.previousY) {            this.previousY = currentY;            return;        }        this.previousY = currentY;        this._adapter.updateVisibleState(visibleState);        this._adapter.notifyIntersect(res);    }    getReversedItems = ()=>{        const { items } = this.getProps();        return cloneDeep(items).reverse();    }    handleCollapseOverflow(){        const { minVisibleItems, collapseFrom } = this.getProps();        const { overflowWidth, containerWidth, pivot: statePivot, overflowStatus } = this.getStates();        const { items, onOverflow } = this.getProps();        let itemWidths = overflowWidth, _pivot = 0;        let overflowed = false;        for (const size of this._adapter.getItemSizeMap().values()) {            itemWidths += size;            // 触发overflow            if (itemWidths > containerWidth) {                overflowed = true;                break;            }            // 顺利遍历完整个列表,说明不存在overflow,直接渲染全部            if (_pivot === items.length - 1) {                this._adapter.updateStates({                    overflowStatus: "normal",                    pivot: items.length - 1,                    visible: items,                    overflow: []                });                break;            }            _pivot++;        }        if (overflowed) {            const pivot = Math.max(minVisibleItems, _pivot);            const isCollapseFromStart = collapseFrom === Boundary.START;            const visible = isCollapseFromStart ? this.getReversedItems().slice(0, pivot).reverse() : items.slice(0, pivot);            const overflow = isCollapseFromStart ? this.getReversedItems().slice(pivot).reverse() : items.slice(pivot);            this._adapter.updateStates({                overflowStatus: "overflowed",                pivot: pivot,                visible,                overflow,            });            // trigger onOverflow            if (statePivot !== pivot){                onOverflow(overflow);            }            return;        }    }}export default OverflowListFoundation;
 |