UNPKG

react-native-sortables

Version:

Powerful Sortable Components for Flexible Content Reordering in React Native

151 lines (147 loc) 5.63 kB
"use strict"; import { useCallback, useRef } from 'react'; import { runOnUI } from 'react-native-reanimated'; import { useStableCallback } from '../../hooks'; import { setAnimatedTimeout, useAnimatedDebounce, useMutableValue } from '../../integrations/reanimated'; import { areValuesDifferent, resolveDimension } from '../../utils'; import { createProvider } from '../utils'; import { useCommonValuesContext } from './CommonValuesProvider'; import { useMultiZoneContext } from './MultiZoneProvider'; const { MeasurementsProvider, useMeasurementsContext } = createProvider('Measurements')(({ itemsCount }) => { const { activeItemDimensions, activeItemKey, containerHeight, containerWidth, controlledContainerDimensions, controlledItemDimensions, itemHeights, itemWidths, usesAbsoluteLayout } = useCommonValuesContext(); const { activeItemDimensions: multiZoneActiveItemDimensions } = useMultiZoneContext() ?? {}; const measuredItemsCount = useMutableValue(0); const previousItemDimensionsRef = useRef({}); const debounce = useAnimatedDebounce(); const handleItemMeasurement = useStableCallback((key, dimensions) => { const prevDimensions = previousItemDimensionsRef.current[key]; const { height: isHeightControlled, width: isWidthControlled } = controlledItemDimensions; if (isWidthControlled && isHeightControlled) { return; } const changedDimensions = {}; if (!isWidthControlled && areValuesDifferent(prevDimensions?.width, dimensions.width, 1)) { changedDimensions.width = dimensions.width; } if (!isHeightControlled && areValuesDifferent(prevDimensions?.height, dimensions.height, 1)) { changedDimensions.height = dimensions.height; } if (!Object.keys(changedDimensions).length) { return; } previousItemDimensionsRef.current[key] = dimensions; runOnUI(() => { const resolvedWidth = resolveDimension(itemWidths.value, key); const resolvedHeight = resolveDimension(itemHeights.value, key); const isNewItem = resolvedWidth === null || resolvedHeight === null; if (isNewItem) { measuredItemsCount.value += 1; } if (itemWidths.value && typeof itemWidths.value === 'object') { itemWidths.value[key] = dimensions.width; } if (itemHeights.value && typeof itemHeights.value === 'object') { itemHeights.value[key] = dimensions.height; } if (activeItemKey.value === key) { activeItemDimensions.value = dimensions; if (multiZoneActiveItemDimensions) { multiZoneActiveItemDimensions.value = dimensions; } } // Update the array of item dimensions only after all items have been // measured to reduce the number of times animated reactions are triggered if (measuredItemsCount.value === itemsCount) { const updateDimensions = () => { if (!isWidthControlled) itemWidths.modify(); if (!isHeightControlled) itemHeights.modify(); }; if (isNewItem) { // If measurements were triggered because of adding new items and all new // items have been measured, update dimensions immediately to avoid // unnecessary delays updateDimensions(); } else { // Otherwise, debounce the update if the number of items is not changed // to reduce the number of updates if dimensions of items are changed // many times within a short period of time debounce(updateDimensions, 100); } } })(); }); const removeItemMeasurements = useCallback(key => { delete previousItemDimensionsRef.current[key]; const { height: isHeightControlled, width: isWidthControlled } = controlledItemDimensions; if (isWidthControlled && isHeightControlled) { return; } runOnUI(() => { if (itemWidths.value && typeof itemWidths.value === 'object') { delete itemWidths.value[key]; } if (itemHeights.value && typeof itemHeights.value === 'object') { delete itemHeights.value[key]; } measuredItemsCount.value -= 1; })(); }, [controlledItemDimensions, itemHeights, itemWidths, measuredItemsCount]); const handleContainerMeasurement = useCallback((width, height) => { 'worklet'; if (!controlledContainerDimensions.width) { containerWidth.value = width; } if (!controlledContainerDimensions.height) { containerHeight.value = height; } }, [controlledContainerDimensions, containerHeight, containerWidth]); const applyControlledContainerDimensions = useCallback(dimensions => { 'worklet'; if (controlledContainerDimensions.width && dimensions.width !== undefined) { containerWidth.value = dimensions.width; } if (controlledContainerDimensions.height && dimensions.height !== undefined) { containerHeight.value = dimensions.height; } if (!usesAbsoluteLayout.value) { // Add timeout for safety, to prevent too many layout recalculations // in a short period of time (this may cause issues on low end devices) setAnimatedTimeout(() => { usesAbsoluteLayout.value = true; }, 100); } }, [containerHeight, containerWidth, controlledContainerDimensions, usesAbsoluteLayout]); return { value: { applyControlledContainerDimensions, handleContainerMeasurement, handleItemMeasurement, removeItemMeasurements } }; }); export { MeasurementsProvider, useMeasurementsContext }; //# sourceMappingURL=MeasurementsProvider.js.map