Skip to content

Commit 89eb24d

Browse files
authored
chore: Sortable grid and flex providers refactor (#445)
## Description This PR adds `FlexProvider` and `GridProvider` components to clean up implementation of the `SortableFlex` and `SortableGrid` components and for easier implementation of the grid or flex specific providers.
1 parent e410842 commit 89eb24d

34 files changed

Lines changed: 275 additions & 192 deletions

packages/react-native-sortables/src/components/SortableFlex.tsx

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ import {
99
} from '../constants';
1010
import { useDragEndHandler } from '../hooks';
1111
import {
12-
FLEX_STRATEGIES,
13-
FlexLayoutProvider,
14-
OrderUpdaterComponent,
15-
SharedProvider,
12+
FlexProvider,
1613
useCommonValuesContext,
17-
useMeasurementsContext,
18-
useStrategyKey
14+
useMeasurementsContext
1915
} from '../providers';
2016
import type { DropIndicatorSettings, SortableFlexProps } from '../types';
2117
import { getPropsWithDefaults, orderItems, validateChildren } from '../utils';
@@ -28,14 +24,7 @@ const CONTROLLED_ITEM_DIMENSIONS = {
2824

2925
function SortableFlex(props: SortableFlexProps) {
3026
const {
31-
rest: {
32-
children,
33-
height,
34-
onDragEnd: _onDragEnd,
35-
strategy,
36-
width,
37-
...styleProps
38-
},
27+
rest: { children, onDragEnd: _onDragEnd, strategy, ...styleProps },
3928
sharedProps: {
4029
debug,
4130
dimensionsAnimationType,
@@ -44,7 +33,6 @@ function SortableFlex(props: SortableFlexProps) {
4433
itemEntering,
4534
itemExiting,
4635
overflow,
47-
reorderTriggerOrigin,
4836
showDropIndicator,
4937
...sharedProps
5038
}
@@ -53,7 +41,7 @@ function SortableFlex(props: SortableFlexProps) {
5341
const childrenArray = validateChildren(children);
5442
const itemKeys = childrenArray.map(([key]) => key);
5543

56-
const { flexDirection, flexWrap } = styleProps;
44+
const { flexDirection, flexWrap, height, width, ...restStyle } = styleProps;
5745
const isColumn = flexDirection.startsWith('column');
5846

5947
const controlledContainerDimensions = useMemo(() => {
@@ -73,41 +61,39 @@ function SortableFlex(props: SortableFlexProps) {
7361
}
7462
});
7563

64+
const containerStyle = [
65+
restStyle,
66+
{
67+
flexDirection,
68+
flexWrap,
69+
height: height === 'fill' ? undefined : height,
70+
width: width === 'fill' ? undefined : width
71+
}
72+
];
73+
7674
return (
77-
<SharedProvider
75+
<FlexProvider
7876
{...sharedProps}
7977
controlledContainerDimensions={controlledContainerDimensions}
8078
controlledItemDimensions={CONTROLLED_ITEM_DIMENSIONS}
8179
debug={debug}
8280
itemKeys={itemKeys}
81+
strategy={strategy}
82+
styleProps={styleProps}
8383
onDragEnd={onDragEnd}>
84-
<FlexLayoutProvider {...styleProps} itemsCount={itemKeys.length}>
85-
<OrderUpdaterComponent
86-
key={useStrategyKey(strategy)}
87-
predefinedStrategies={FLEX_STRATEGIES}
88-
strategy={strategy}
89-
triggerOrigin={reorderTriggerOrigin}
90-
/>
91-
<SortableFlexInner
92-
childrenArray={childrenArray}
93-
debug={debug}
94-
dimensionsAnimationType={dimensionsAnimationType}
95-
DropIndicatorComponent={DropIndicatorComponent}
96-
dropIndicatorStyle={dropIndicatorStyle}
97-
itemEntering={itemEntering}
98-
itemExiting={itemExiting}
99-
overflow={overflow}
100-
showDropIndicator={showDropIndicator}
101-
style={[
102-
styleProps,
103-
{
104-
height: height === 'fill' ? undefined : height,
105-
width: width === 'fill' ? undefined : width
106-
}
107-
]}
108-
/>
109-
</FlexLayoutProvider>
110-
</SharedProvider>
84+
<SortableFlexInner
85+
childrenArray={childrenArray}
86+
debug={debug}
87+
dimensionsAnimationType={dimensionsAnimationType}
88+
DropIndicatorComponent={DropIndicatorComponent}
89+
dropIndicatorStyle={dropIndicatorStyle}
90+
itemEntering={itemEntering}
91+
itemExiting={itemExiting}
92+
overflow={overflow}
93+
showDropIndicator={showDropIndicator}
94+
style={containerStyle}
95+
/>
96+
</FlexProvider>
11197
);
11298
}
11399

@@ -184,8 +170,8 @@ function SortableFlexInner({
184170
})}>
185171
{childrenArray.map(([key, child]) => (
186172
<DraggableView
187-
entering={itemEntering ?? undefined}
188-
exiting={itemExiting ?? undefined}
173+
itemEntering={itemEntering}
174+
itemExiting={itemExiting}
189175
itemKey={key}
190176
key={key}
191177
style={styles.styleOverride}>

packages/react-native-sortables/src/components/SortableGrid.tsx

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,7 @@ import { runOnUI, useAnimatedStyle } from 'react-native-reanimated';
77
import { DEFAULT_SORTABLE_GRID_PROPS, IS_WEB } from '../constants';
88
import { useDragEndHandler } from '../hooks';
99
import { useAnimatableValue } from '../integrations/reanimated';
10-
import {
11-
GRID_STRATEGIES,
12-
GridLayoutProvider,
13-
OrderUpdaterComponent,
14-
SharedProvider,
15-
useMeasurementsContext,
16-
useStrategyKey
17-
} from '../providers';
10+
import { GridProvider, useMeasurementsContext } from '../providers';
1811
import type {
1912
DropIndicatorSettings,
2013
SortableGridProps,
@@ -97,47 +90,40 @@ function SortableGrid<I>(props: SortableGridProps<I>) {
9790
});
9891

9992
return (
100-
<SharedProvider
93+
<GridProvider
10194
{...sharedProps}
95+
columnGap={columnGapValue}
10296
controlledContainerDimensions={controlledContainerDimensions}
10397
controlledItemDimensions={controlledItemDimensions}
10498
debug={debug}
99+
isVertical={isVertical}
105100
itemKeys={itemKeys}
101+
numGroups={groups}
102+
numItems={data.length}
103+
reorderTriggerOrigin={reorderTriggerOrigin}
104+
rowGap={rowGapValue}
105+
rowHeight={rowHeight} // must be specified for horizontal grids
106+
strategy={strategy}
106107
onDragEnd={onDragEnd}>
107-
<GridLayoutProvider
108+
<SortableGridInner
108109
columnGap={columnGapValue}
110+
data={data}
111+
debug={debug}
112+
dimensionsAnimationType={dimensionsAnimationType}
113+
DropIndicatorComponent={DropIndicatorComponent}
114+
dropIndicatorStyle={dropIndicatorStyle}
115+
groups={groups}
109116
isVertical={isVertical}
110-
numGroups={groups}
111-
numItems={data.length}
117+
itemEntering={itemEntering}
118+
itemExiting={itemExiting}
119+
itemKeys={itemKeys}
120+
overflow={overflow}
121+
renderItem={renderItem}
112122
rowGap={rowGapValue}
113-
rowHeight={rowHeight} // horizontal grid only
114-
>
115-
<OrderUpdaterComponent
116-
key={useStrategyKey(strategy)}
117-
predefinedStrategies={GRID_STRATEGIES}
118-
strategy={strategy}
119-
triggerOrigin={reorderTriggerOrigin}
120-
/>
121-
<SortableGridInner
122-
columnGap={columnGapValue}
123-
data={data}
124-
debug={debug}
125-
dimensionsAnimationType={dimensionsAnimationType}
126-
DropIndicatorComponent={DropIndicatorComponent}
127-
dropIndicatorStyle={dropIndicatorStyle}
128-
groups={groups}
129-
isVertical={isVertical}
130-
itemEntering={itemEntering}
131-
itemExiting={itemExiting}
132-
itemKeys={itemKeys}
133-
overflow={overflow}
134-
renderItem={renderItem}
135-
rowGap={rowGapValue}
136-
rowHeight={rowHeight!} // must be specified for horizontal grids
137-
showDropIndicator={showDropIndicator}
138-
/>
139-
</GridLayoutProvider>
140-
</SharedProvider>
123+
rowHeight={rowHeight!} // must be specified for horizontal grids
124+
showDropIndicator={showDropIndicator}
125+
/>
126+
</GridProvider>
141127
);
142128
}
143129

@@ -210,6 +196,19 @@ function SortableGridInner<I>({
210196
: { height: rowHeight }
211197
);
212198

199+
const itemStyle = useMemo(
200+
() => [animatedItemStyle, !isVertical && styles.horizontalStyleOverride],
201+
[animatedItemStyle, isVertical]
202+
);
203+
204+
const sharedItemProps = {
205+
itemEntering,
206+
itemExiting,
207+
itemKeys,
208+
renderItem,
209+
style: itemStyle
210+
};
211+
213212
return (
214213
<SortableContainer
215214
{...containerProps}
@@ -222,17 +221,11 @@ function SortableGridInner<I>({
222221
})}>
223222
{zipArrays(data, itemKeys).map(([item, key], index) => (
224223
<SortableGridItem
225-
entering={itemEntering ?? undefined}
226-
exiting={itemExiting ?? undefined}
224+
{...sharedItemProps}
227225
index={index}
228226
item={item}
229227
itemKey={key}
230228
key={key}
231-
renderItem={renderItem}
232-
style={[
233-
animatedItemStyle,
234-
!isVertical && styles.horizontalStyleOverride
235-
]}
236229
/>
237230
))}
238231
</SortableContainer>

packages/react-native-sortables/src/components/shared/DraggableView/DraggableView.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,17 @@ const CommonValuesContextProvider = getContextProvider(CommonValuesContext);
3232

3333
export type DraggableViewProps = PropsWithChildren<{
3434
itemKey: string;
35-
entering: LayoutAnimation | undefined;
36-
exiting: LayoutAnimation | undefined;
35+
itemEntering: LayoutAnimation | null;
36+
itemExiting: LayoutAnimation | null;
3737
style?: AnimatedStyleProp;
3838
}>;
3939

4040
function DraggableView({
4141
children,
42+
itemEntering,
43+
itemExiting,
4244
itemKey: key,
43-
style,
44-
...layoutAnimations
45+
style
4546
}: DraggableViewProps) {
4647
const portalContext = usePortalContext();
4748
const commonValuesContext = useCommonValuesContext();
@@ -112,9 +113,10 @@ function DraggableView({
112113
const renderItemCell = (hidden = false) => {
113114
const innerComponent = (
114115
<ItemCell
115-
{...layoutAnimations}
116116
{...sharedCellProps}
117117
cellStyle={[style, itemStyles]}
118+
entering={itemEntering ?? undefined}
119+
exiting={itemExiting ?? undefined}
118120
hidden={hidden}>
119121
<LayoutAnimationConfig skipEntering={false} skipExiting={false}>
120122
{children}

packages/react-native-sortables/src/components/shared/SortableContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type {
1717
import AnimatedOnLayoutView from './AnimatedOnLayoutView';
1818
import DropIndicator from './DropIndicator';
1919

20-
type AnimatedHeightContainerProps = PropsWithChildren<
20+
export type SortableContainerProps = PropsWithChildren<
2121
DropIndicatorSettings & {
2222
dimensionsAnimationType: DimensionsAnimation;
2323
overflow: Overflow;
@@ -37,7 +37,7 @@ export default function SortableContainer({
3737
overflow,
3838
showDropIndicator,
3939
style
40-
}: AnimatedHeightContainerProps) {
40+
}: SortableContainerProps) {
4141
const {
4242
activeItemDropped,
4343
activeItemKey,

packages/react-native-sortables/src/components/shared/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ export {
33
type CustomHandleProps
44
} from './CustomHandle';
55
export * from './DraggableView';
6-
export { default as SortableContainer } from './SortableContainer';
6+
export {
7+
default as SortableContainer,
8+
type SortableContainerProps
9+
} from './SortableContainer';
710
export {
811
default as SortableLayer,
912
type SortableLayerProps

0 commit comments

Comments
 (0)