UNPKG

@shopify/flash-list

Version:

FlashList is a more performant FlatList replacement

151 lines 6.15 kB
import { RVLayoutManager, } from "./LayoutManager"; /** * LinearLayoutManager implementation that arranges items in a single row or column. * Supports both horizontal and vertical layouts with dynamic item sizing. */ export class RVLinearLayoutManagerImpl extends RVLayoutManager { constructor(params, previousLayoutManager) { super(params, previousLayoutManager); /** Whether the bounded size has been set */ this.hasSize = false; /** Height of the tallest item */ this.tallestItemHeight = 0; this.boundedSize = this.horizontal ? params.windowSize.height : params.windowSize.width; this.hasSize = this.boundedSize > 0; } /** * Updates layout parameters and triggers recomputation if necessary. * @param params New layout parameters */ updateLayoutParams(params) { const prevHorizontal = this.horizontal; super.updateLayoutParams(params); const oldBoundedSize = this.boundedSize; this.boundedSize = this.horizontal ? params.windowSize.height : params.windowSize.width; if (oldBoundedSize !== this.boundedSize || prevHorizontal !== this.horizontal) { if (this.layouts.length > 0) { // console.log("-----> recomputeLayouts", this.horizontal); this.recomputeLayouts(0, this.layouts.length - 1); this.requiresRepaint = true; } } } /** * Processes layout information for items, updating their dimensions. * For horizontal layouts, also normalizes heights of items. * @param layoutInfo Array of layout information for items * @param itemCount Total number of items in the list */ processLayoutInfo(layoutInfo, itemCount) { // Update layout information for (const info of layoutInfo) { const { index, dimensions } = info; const layout = this.layouts[index]; layout.width = this.horizontal ? dimensions.width : this.boundedSize; layout.isHeightMeasured = true; layout.isWidthMeasured = true; layout.height = dimensions.height; } if (this.horizontal && !this.hasSize) { this.normalizeLayoutHeights(layoutInfo); } } /** * Estimates layout dimensions for an item at the given index. * @param index Index of the item to estimate layout for */ estimateLayout(index) { const layout = this.layouts[index]; layout.width = this.horizontal ? this.getEstimatedWidth(index) : this.boundedSize; layout.height = this.getEstimatedHeight(index); layout.isWidthMeasured = !this.horizontal; layout.enforcedWidth = !this.horizontal; } /** * Returns the total size of the layout area. * @returns RVDimension containing width and height of the layout */ getLayoutSize() { var _a, _b; if (this.layouts.length === 0) return { width: 0, height: 0 }; const lastLayout = this.layouts[this.layouts.length - 1]; return { width: this.horizontal ? lastLayout.x + lastLayout.width : this.boundedSize, height: this.horizontal ? (_b = (_a = this.tallestItem) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : this.boundedSize : lastLayout.y + lastLayout.height, }; } /** * Normalizes heights of items in horizontal layout to match the tallest item. * @param layoutInfo Array of layout information for items */ normalizeLayoutHeights(layoutInfo) { var _a, _b; let newTallestItem; for (const info of layoutInfo) { const { index } = info; const layout = this.layouts[index]; if (layout.height > ((_a = layout.minHeight) !== null && _a !== void 0 ? _a : 0) && layout.height > ((_b = newTallestItem === null || newTallestItem === void 0 ? void 0 : newTallestItem.height) !== null && _b !== void 0 ? _b : 0)) { newTallestItem = layout; } } if (newTallestItem && newTallestItem.height !== this.tallestItemHeight) { let targetMinHeight = newTallestItem.height; if (newTallestItem.height < this.tallestItemHeight) { this.requiresRepaint = true; targetMinHeight = 0; } // set minHeight for all layouts for (const layout of this.layouts) { if (targetMinHeight > 0) { layout.height = newTallestItem.height; } layout.minHeight = targetMinHeight; } newTallestItem.minHeight = 0; this.tallestItem = newTallestItem; this.tallestItemHeight = newTallestItem.height; } } /** * Recomputes layouts for items in the given range. * Positions items sequentially based on layout direction. * @param startIndex Starting index of items to recompute * @param endIndex Ending index of items to recompute */ recomputeLayouts(startIndex, endIndex) { for (let i = startIndex; i <= endIndex; i++) { const layout = this.getLayout(i); // Set positions based on whether this is the first item or not if (i === 0) { layout.x = 0; layout.y = 0; } else { const prevLayout = this.getLayout(i - 1); layout.x = this.horizontal ? prevLayout.x + prevLayout.width : 0; layout.y = this.horizontal ? 0 : prevLayout.y + prevLayout.height; } // Set width for vertical layouts if (!this.horizontal) { layout.width = this.boundedSize; } else if (this.hasSize) { layout.minHeight = this.boundedSize; } } } } //# sourceMappingURL=LinearLayoutManager.js.map