UNPKG

react-native-sortables

Version:

Powerful Sortable Components for Flexible Content Reordering in React Native

132 lines (112 loc) 3.42 kB
'worklet'; import type { AutoOffsetAdjustmentProps, Coordinate, GridLayout, GridLayoutProps, Vector } from '../../../../types'; import { resolveDimension } from '../../../../utils'; import { getCrossIndex, getMainIndex } from './helpers'; export const calculateLayout = ({ gaps, indexToKey, isVertical, itemHeights, itemWidths, numGroups, startCrossOffset }: GridLayoutProps): GridLayout | null => { const mainGroupSize = (isVertical ? itemWidths : itemHeights) as | null | number; if (!mainGroupSize) { return null; } const crossAxisOffsets = [startCrossOffset ?? 0]; const itemPositions: Record<string, Vector> = {}; let mainCoordinate: Coordinate; let crossCoordinate: Coordinate; let crossItemSizes; if (isVertical) { // grid with specified number of columns (vertical orientation) mainCoordinate = 'x'; crossCoordinate = 'y'; crossItemSizes = itemHeights; } else { // grid with specified number of rows (horizontal orientation) mainCoordinate = 'y'; crossCoordinate = 'x'; crossItemSizes = itemWidths; } for (const [itemIndex, itemKey] of indexToKey.entries()) { const crossItemSize = resolveDimension(crossItemSizes, itemKey); // Return null if the item is not yet measured or the item main size // is different than the main group size (main size must be always the same) if (crossItemSize === null) { return null; } const mainIndex = getMainIndex(itemIndex, numGroups); const crossIndex = getCrossIndex(itemIndex, numGroups); const crossAxisOffset = crossAxisOffsets[crossIndex] ?? 0; // Update offset of the next group crossAxisOffsets[crossIndex + 1] = Math.max( crossAxisOffsets[crossIndex + 1] ?? 0, crossAxisOffset + crossItemSize + gaps.cross ); // Update item position itemPositions[itemKey] = { [crossCoordinate]: crossAxisOffset, [mainCoordinate]: mainIndex * (mainGroupSize + gaps.main) } as Vector; } let lastCrossOffset = crossAxisOffsets[crossAxisOffsets.length - 1]; lastCrossOffset = lastCrossOffset ? Math.max(lastCrossOffset - gaps.cross, 0) : 0; const mainSize = (mainGroupSize + gaps.main) * numGroups - gaps.main; return { containerCrossSize: lastCrossOffset, contentBounds: [ { [crossCoordinate]: startCrossOffset ?? 0, [mainCoordinate]: 0 } as Vector, { [crossCoordinate]: lastCrossOffset, [mainCoordinate]: mainSize } as Vector ], crossAxisOffsets, itemPositions }; }; export const calculateItemCrossOffset = ({ crossGap, crossItemSizes, indexToKey, itemKey, numGroups }: AutoOffsetAdjustmentProps): number => { let activeItemCrossOffset = 0; let currentGroupCrossSize = 0; let currentGroupCrossIndex = 0; // Find new active item position for (let i = 0; i < indexToKey.length; i++) { const crossIndex = getCrossIndex(i, numGroups); if (crossIndex !== currentGroupCrossIndex) { activeItemCrossOffset += currentGroupCrossSize + crossGap; currentGroupCrossIndex = crossIndex; currentGroupCrossSize = 0; } const key = indexToKey[i]!; currentGroupCrossSize = Math.max( currentGroupCrossSize, resolveDimension(crossItemSizes, key) ?? 0 ); if (key === itemKey) { break; } } return activeItemCrossOffset; };