react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
186 lines (185 loc) • 5.95 kB
JavaScript
"use strict";
import React from "react";
import { useMemo } from 'react';
import { StyleSheet } from 'react-native';
import { runOnUI, useAnimatedStyle } from 'react-native-reanimated';
import { DEFAULT_SORTABLE_GRID_PROPS, IS_WEB } from '../constants';
import { useDragEndHandler } from '../hooks';
import { useAnimatableValue } from '../integrations/reanimated';
import { GRID_STRATEGIES, GridLayoutProvider, OrderUpdaterComponent, SharedProvider, useMeasurementsContext, useStrategyKey } from '../providers';
import { defaultKeyExtractor, error, getPropsWithDefaults, orderItems, typedMemo, zipArrays } from '../utils';
import { DraggableView, SortableContainer } from './shared';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
function SortableGrid(props) {
const {
rest: {
columnGap,
columns,
data,
keyExtractor = defaultKeyExtractor,
onDragEnd: _onDragEnd,
renderItem,
rowGap,
rowHeight,
rows,
strategy
},
sharedProps: {
debug,
dimensionsAnimationType,
DropIndicatorComponent,
dropIndicatorStyle,
itemEntering,
itemExiting,
overflow,
reorderTriggerOrigin,
showDropIndicator,
...sharedProps
}
} = getPropsWithDefaults(props, DEFAULT_SORTABLE_GRID_PROPS);
const isVertical = rows === undefined;
const groups = rows ?? columns;
if (!isVertical && !rowHeight) {
throw error('rowHeight is required for horizontal Sortable.Grid');
}
if (columns !== undefined && columns < 1) {
throw error('columns must be greater than 0');
}
if (rows !== undefined && rows < 1) {
throw error('rows must be greater than 0');
}
const columnGapValue = useAnimatableValue(columnGap);
const rowGapValue = useAnimatableValue(rowGap);
const controlledContainerDimensions = useMemo(() => ({
height: isVertical,
// height is controlled for vertical grids
width: !isVertical // width is controlled for horizontal grids
}), [isVertical]);
const controlledItemDimensions = useMemo(() => ({
height: !isVertical,
// height is controlled for horizontal grids
width: isVertical // width is controlled for vertical grids
}), [isVertical]);
const itemKeys = useMemo(() => data.map(keyExtractor), [data, keyExtractor]);
const onDragEnd = useDragEndHandler(_onDragEnd, {
data: params => orderItems(data, itemKeys, params, true)
});
return /*#__PURE__*/_jsx(SharedProvider, {
...sharedProps,
controlledContainerDimensions: controlledContainerDimensions,
controlledItemDimensions: controlledItemDimensions,
debug: debug,
itemKeys: itemKeys,
onDragEnd: onDragEnd,
children: /*#__PURE__*/_jsxs(GridLayoutProvider, {
columnGap: columnGapValue,
isVertical: isVertical,
numGroups: groups,
numItems: data.length,
rowGap: rowGapValue,
rowHeight: rowHeight // horizontal grid only
,
children: [/*#__PURE__*/_jsx(OrderUpdaterComponent, {
predefinedStrategies: GRID_STRATEGIES,
strategy: strategy,
triggerOrigin: reorderTriggerOrigin
}, useStrategyKey(strategy)), /*#__PURE__*/_jsx(SortableGridInner, {
columnGap: columnGapValue,
data: data,
debug: debug,
dimensionsAnimationType: dimensionsAnimationType,
DropIndicatorComponent: DropIndicatorComponent,
dropIndicatorStyle: dropIndicatorStyle,
groups: groups,
isVertical: isVertical,
itemEntering: itemEntering,
itemExiting: itemExiting,
itemKeys: itemKeys,
overflow: overflow,
renderItem: renderItem,
rowGap: rowGapValue,
rowHeight: rowHeight // must be specified for horizontal grids
,
showDropIndicator: showDropIndicator
})]
})
});
}
function SortableGridInner({
columnGap,
data,
groups,
isVertical,
itemEntering,
itemExiting,
itemKeys,
renderItem,
rowGap,
rowHeight,
...containerProps
}) {
const {
handleContainerMeasurement
} = useMeasurementsContext();
const animatedInnerStyle = useAnimatedStyle(() => isVertical ? {
columnGap: IS_WEB ? columnGap.value : 0,
flexDirection: 'row',
marginHorizontal: IS_WEB ? 0 : -columnGap.value / 2,
rowGap: rowGap.value
} : {
columnGap: columnGap.value,
flexDirection: 'column',
height: groups * (rowHeight + rowGap.value) - rowGap.value,
rowGap: rowGap.value
});
const animatedItemStyle = useAnimatedStyle(() => isVertical ? IS_WEB ? {
width: `calc((100% - ${columnGap.value * (groups - 1)}px) / ${groups})`
} : {
flexBasis: `${100 / groups}%`,
paddingHorizontal: columnGap.value / 2
} : {
height: rowHeight
});
return /*#__PURE__*/_jsx(SortableContainer, {
...containerProps,
style: [styles.gridContainer, animatedInnerStyle],
onLayout: runOnUI((width, height) => {
handleContainerMeasurement(width - (isVertical && !IS_WEB ? columnGap.value : 0), height);
}),
children: zipArrays(data, itemKeys).map(([item, key], index) => /*#__PURE__*/_jsx(SortableGridItem, {
entering: itemEntering ?? undefined,
exiting: itemExiting ?? undefined,
index: index,
item: item,
itemKey: key,
renderItem: renderItem,
style: [animatedItemStyle, !isVertical && styles.horizontalStyleOverride]
}, key))
});
}
function SortableGridItem({
index,
item,
renderItem,
...rest
}) {
const children = useMemo(() => renderItem({
index,
item
}), [renderItem, index, item]);
return /*#__PURE__*/_jsx(DraggableView, {
...rest,
children: children
});
}
const styles = StyleSheet.create({
gridContainer: {
flexWrap: 'wrap'
},
horizontalStyleOverride: {
// This is needed to properly adjust the wrapper size to the item width
alignSelf: 'flex-start'
}
});
export default typedMemo(SortableGrid);
//# sourceMappingURL=SortableGrid.js.map