UNPKG

react-native-sortables

Version:

Powerful Sortable Components for Flexible Content Reordering in React Native

169 lines (159 loc) 5.98 kB
"use strict"; import { reorderInsert } from '../../../../../utils'; const getFirstItemIndex = (group, keyToIndex) => { 'worklet'; const firstKey = group[0]; if (firstKey === undefined) return null; return keyToIndex[firstKey] ?? null; }; const getLastItemIndex = (group, keyToIndex) => { 'worklet'; const lastKey = group[group.length - 1]; if (lastKey === undefined) return null; return keyToIndex[lastKey] ?? null; }; export const getTotalGroupSize = (group, itemDimensions, mainDimension, gap) => { 'worklet'; const sizesSum = group.reduce((total, key) => total + (itemDimensions[key]?.[mainDimension] ?? 0), 0); return sizesSum + gap * (group.length - 1); }; const getIndexesWhenSwappedToGroupBefore = ({ activeItemKey, currentGroupIndex, groupSizeLimit, itemDimensions, itemGroups, keyToIndex, mainDimension, mainGap }) => { 'worklet'; if (groupSizeLimit === Infinity || currentGroupIndex < 1) { return null; } const firstInGroupBeforeIndex = getFirstItemIndex(itemGroups[currentGroupIndex - 1], keyToIndex); const lastInGroupBeforeIndex = getLastItemIndex(itemGroups[currentGroupIndex - 1], keyToIndex); if (firstInGroupBeforeIndex === null || lastInGroupBeforeIndex === null) { return null; } const activeMainSize = itemDimensions[activeItemKey]?.[mainDimension] ?? 0; if (currentGroupIndex > 1) { // If there is a group before the group before the active group, // we have to check whether the active item won't wrap to this group const totalGroupBeforeBeforeSize = getTotalGroupSize(itemGroups[currentGroupIndex - 2], itemDimensions, mainDimension, mainGap); if (totalGroupBeforeBeforeSize + activeMainSize <= groupSizeLimit) { if (firstInGroupBeforeIndex < lastInGroupBeforeIndex) { // If the active item fits in the group before the group before // the active group, we want to put it in the second position of // the group before the active group to prevent it from wrapping // to the group before it (we cannot put it as the first one as // it will be wrapped in this case). return { groupIndex: currentGroupIndex - 1, itemIndex: firstInGroupBeforeIndex + 1, itemIndexInGroup: 1 }; } // If the active item fits in the group before the group before, // and it doesn't fit in the group before the active group, // we want to put it in the 2nd group before the active group. return { groupIndex: currentGroupIndex - 2, itemIndex: getFirstItemIndex(itemGroups[currentGroupIndex - 2] ?? [], keyToIndex) ?? 0, itemIndexInGroup: 0 }; } } return { groupIndex: currentGroupIndex - 1, itemIndex: firstInGroupBeforeIndex, itemIndexInGroup: 0 }; }; const getIndexesWhenSwappedToGroupAfter = ({ activeItemKey, currentGroupIndex, groupSizeLimit, indexToKey, itemDimensions, itemGroups, keyToIndex, mainDimension, mainGap }) => { 'worklet'; if (groupSizeLimit === Infinity || currentGroupIndex + 1 >= itemGroups.length) { return null; } const firstInActiveGroupIndex = getFirstItemIndex(itemGroups[currentGroupIndex], keyToIndex); const lastInActiveGroupIndex = getLastItemIndex(itemGroups[currentGroupIndex], keyToIndex); if (firstInActiveGroupIndex === null || lastInActiveGroupIndex === null) { return null; } // We need to remove the active item from the its group, fit all items // in the remaining space between the active item's group and the target group, // and then insert the active item in the target group let targetItemIndex = firstInActiveGroupIndex; let totalGroupSize = 0; let nextGroupFirstItemKey = null; for (let i = firstInActiveGroupIndex; i < indexToKey.length; i++) { const key = indexToKey[i]; if (key === activeItemKey) continue; const itemMainSize = itemDimensions[key]?.[mainDimension] ?? 0; if (totalGroupSize + itemMainSize > groupSizeLimit) { nextGroupFirstItemKey = key; break; } totalGroupSize += itemMainSize + mainGap; targetItemIndex++; } const activeMainSize = itemDimensions[activeItemKey]?.[mainDimension] ?? 0; if (totalGroupSize + activeMainSize > groupSizeLimit) { // If the active item can be the first element of the next group (it won't // wrap to the current group), we put it in the 1st position of the next group return { groupIndex: currentGroupIndex + 1, itemIndex: targetItemIndex, // is the first item of the next group itemIndexInGroup: 0 }; } if (nextGroupFirstItemKey && (itemDimensions[nextGroupFirstItemKey]?.[mainDimension] ?? 0) + mainGap + activeMainSize <= groupSizeLimit) { // Otherwise, if it can be the second item of the next group, we put it there // to prevent wrapping to the current group return { groupIndex: currentGroupIndex + 1, itemIndex: targetItemIndex + 1, // is the second item of the next group itemIndexInGroup: 1 }; } return { groupIndex: currentGroupIndex + 2, // is in a group after the next group itemIndex: targetItemIndex + 1, // is after the item from the next group itemIndexInGroup: 0 }; }; export const getSwappedToGroupBeforeIndices = props => { 'worklet'; const indexes = getIndexesWhenSwappedToGroupBefore(props); if (indexes === null) return null; return { ...indexes, indexToKey: reorderInsert(props.indexToKey, props.activeItemIndex, indexes.itemIndex, undefined // TODO - add fixed items support in flex ) }; }; export const getSwappedToGroupAfterIndices = props => { 'worklet'; const indexes = getIndexesWhenSwappedToGroupAfter(props); if (indexes === null) return null; return { ...indexes, indexToKey: reorderInsert(props.indexToKey, props.activeItemIndex, indexes.itemIndex, undefined // TODO - add fixed items support in flex ) }; }; //# sourceMappingURL=utils.js.map