Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { useCallback, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { StyleSheet, View } from 'react-native';
import Animated, {
LinearTransition,
useAnimatedRef
} from 'react-native-reanimated';
import type { OverDrag, SortableGridRenderItem } from 'react-native-sortables';
import Sortable from 'react-native-sortables';

import { OptionGroup, SimpleDropdown, Spacer, TabSelector } from '@/components';
import {
CheckBox,
OptionGroup,
SimpleDropdown,
Spacer,
TabSelector
} from '@/components';
import { IS_WEB } from '@/constants';
import { useBottomNavBarHeight } from '@/providers';
import { colors, flex, radius, sizes, spacing, style, text } from '@/theme';
Expand All @@ -24,20 +30,27 @@ export default function DragHandleExample() {
const bottomNavBarHeight = useBottomNavBarHeight();
const [columns, setColumns] = useState(1);
const [overDrag, setOverDrag] = useState<OverDrag>('both');
const [changeHeight, setChangeHeight] = useState(false);
const scrollableRef = useAnimatedRef<Animated.ScrollView>();

const cardHeight = changeHeight ? columns * sizes.md : sizes.lg;

const renderItem = useCallback<SortableGridRenderItem<string>>(
({ item }) => (
<Animated.View layout={LinearTransition} style={styles.card}>
<Text style={styles.text}>{item}</Text>
<Animated.View
layout={LinearTransition}
style={[styles.card, { height: cardHeight }]}>
<Animated.Text layout={LinearTransition} style={styles.text}>
{item}
</Animated.Text>
<Animated.View layout={LinearTransition}>
<Sortable.Handle>
<FontAwesomeIcon color={colors.white} icon={faGripVertical} />
</Sortable.Handle>
</Animated.View>
</Animated.View>
),
[]
[cardHeight]
);

return (
Expand All @@ -57,6 +70,9 @@ export default function DragHandleExample() {
onSelect={setOverDrag}
/>
</OptionGroup>
<OptionGroup label='change height with columns'>
<CheckBox selected={changeHeight} onChange={setChangeHeight} />
</OptionGroup>
</View>
<Animated.ScrollView
contentContainerStyle={[IS_WEB && style.webContent, styles.container]}
Expand All @@ -70,6 +86,7 @@ export default function DragHandleExample() {
dimensionsAnimationType='layout'
dragActivationDelay={0}
overDrag={overDrag}
overflow='visible'
renderItem={renderItem}
rowGap={10}
scrollableRef={scrollableRef}
Expand All @@ -87,7 +104,6 @@ const styles = StyleSheet.create({
backgroundColor: '#36877F',
borderRadius: radius.md,
flexDirection: 'row',
height: sizes.lg,
justifyContent: 'space-between',
padding: spacing.md
},
Expand Down
6 changes: 3 additions & 3 deletions example/fabric/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2710,7 +2710,7 @@ DEPENDENCIES:
- "RNFlashList (from `../../../node_modules/@shopify/flash-list`)"
- RNGestureHandler (from `../../../node_modules/react-native-gesture-handler`)
- RNReactNativeHapticFeedback (from `../../../node_modules/react-native-haptic-feedback`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNReanimated (from `../../../node_modules/react-native-reanimated`)
- RNScreens (from `../../../node_modules/react-native-screens`)
- RNSVG (from `../../../node_modules/react-native-svg`)
- RNWorklets (from `../../../node_modules/react-native-worklets`)
Expand Down Expand Up @@ -2876,7 +2876,7 @@ EXTERNAL SOURCES:
RNReactNativeHapticFeedback:
:path: "../../../node_modules/react-native-haptic-feedback"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
:path: "../../../node_modules/react-native-reanimated"
RNScreens:
:path: "../../../node_modules/react-native-screens"
RNSVG:
Expand Down Expand Up @@ -2963,7 +2963,7 @@ SPEC CHECKSUMS:
RNFlashList: e8ac986e5bebc2e9e5576d1f0bd8a93fac1c8a0d
RNGestureHandler: 9d04ec6e1379b595222c2467f5e8d1c44157fcc9
RNReactNativeHapticFeedback: 7ab0232cc103ac7d928635410fa0df7b11c53ada
RNReanimated: b34ad297b2707c197bbf7c9af27ebd0169331e56
RNReanimated: 7d12e875bfa54f41b8a7f99ca6e935d0b2be08f4
RNScreens: 45a4564413205e2a1695d40bbc0297f6eefc9b74
RNSVG: c73af7848d94ca3e8136a5191d055e3c1d6fedab
RNWorklets: fda18a05fb63c0254b4866242b00857dd74b2f65
Expand Down
4 changes: 1 addition & 3 deletions example/fabric/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ const { createMetroConfig } = require('../app/scripts/metro');

const defaultConfig = getDefaultConfig(__dirname);

module.exports = createMetroConfig(defaultConfig, __dirname, {
excludeFromRoot: ['react-native-reanimated']
});
module.exports = createMetroConfig(defaultConfig, __dirname);
6 changes: 3 additions & 3 deletions example/paper/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2475,7 +2475,7 @@ DEPENDENCIES:
- "RNFlashList (from `../../../node_modules/@shopify/flash-list`)"
- RNGestureHandler (from `../../../node_modules/react-native-gesture-handler`)
- RNReactNativeHapticFeedback (from `../../../node_modules/react-native-haptic-feedback`)
- RNReanimated (from `../../../node_modules/react-native-reanimated`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../../../node_modules/react-native-screens`)
- RNSVG (from `../../../node_modules/react-native-svg`)
- SocketRocket (~> 0.7.1)
Expand Down Expand Up @@ -2640,7 +2640,7 @@ EXTERNAL SOURCES:
RNReactNativeHapticFeedback:
:path: "../../../node_modules/react-native-haptic-feedback"
RNReanimated:
:path: "../../../node_modules/react-native-reanimated"
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../../../node_modules/react-native-screens"
RNSVG:
Expand Down Expand Up @@ -2725,7 +2725,7 @@ SPEC CHECKSUMS:
RNFlashList: aad5ccddcbcdfe34dcca3524fdef1416abb32a55
RNGestureHandler: 4babc0b2fdcf63e8ddcd86f3c1c3639972922f6b
RNReactNativeHapticFeedback: eed9dfa61c409807a2c95860b45aaad085ccbbc9
RNReanimated: 4d57827f1d1619f662d1d94176fda2c11a2c7aa0
RNReanimated: ecffc26eddb9f122cd03f762f8ad93aefb37dd36
RNScreens: f75a433d5966ab2b0570fa5e5e487f1c46488972
RNSVG: 3446469442ca54ddf210d2a1b7c2b6eaecaca2c3
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Expand Down
4 changes: 3 additions & 1 deletion example/paper/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ const { createMetroConfig } = require('../app/scripts/metro');

const defaultConfig = getDefaultConfig(__dirname);

module.exports = createMetroConfig(defaultConfig, __dirname);
module.exports = createMetroConfig(defaultConfig, __dirname, {
excludeFromRoot: ['react-native-reanimated']
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import type { DimensionValue } from 'react-native';
import { StyleSheet } from 'react-native';
import type { SharedValue } from 'react-native-reanimated';
Expand Down Expand Up @@ -175,7 +175,10 @@ function SortableGridInner<I>({
rowHeight,
...containerProps
}: SortableGridInnerProps<I>) {
const { handleContainerMeasurement } = useMeasurementsContext();
const { handleContainerMeasurement, resetMeasurements } =
useMeasurementsContext();

useEffect(resetMeasurements, [groups, resetMeasurements]);

const animatedInnerStyle = useAnimatedStyle(() =>
isVertical
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ const { GridLayoutProvider, useGridLayoutContext } = createProvider(
}

mainGroupSize.value = value;

if (isVertical) {
itemWidths.value = value;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const { MeasurementsProvider, useMeasurementsContext } = createProvider(
useMultiZoneContext() ?? {};

const measuredItemsCount = useMutableValue(0);
const queuedMeasurements = useMutableValue<null | Set<string>>(null);
const previousItemDimensionsRef = useRef<Record<string, Dimensions>>({});
const debounce = useAnimatedDebounce();

Expand Down Expand Up @@ -95,6 +96,7 @@ const { MeasurementsProvider, useMeasurementsContext } = createProvider(
// measured to reduce the number of times animated reactions are triggered
if (measuredItemsCount.value === itemsCount) {
const updateDimensions = () => {
queuedMeasurements.value = null;
if (!isWidthControlled) itemWidths.modify();
if (!isHeightControlled) itemHeights.modify();
};
Expand All @@ -105,10 +107,20 @@ const { MeasurementsProvider, useMeasurementsContext } = createProvider(
// 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);
// If all sortable container items' dimensions have changed, we can
// update dimensions immediately to avoid unnecessary delays (e.g. when
// someone creates collapsible items which change their height when the user
// starts dragging them)
queuedMeasurements.value ??= new Set();
queuedMeasurements.value.add(key);
if (queuedMeasurements.value.size === itemsCount) {
updateDimensions();
} else {
// In all other cases, debounce the update to reduce the number of
// updates if dimensions of items are changed many times within a
// short period of time
debounce(updateDimensions, 100);
}
}
}
})();
Expand Down Expand Up @@ -182,12 +194,27 @@ const { MeasurementsProvider, useMeasurementsContext } = createProvider(
]
);

const resetMeasurements = useCallback(() => {
previousItemDimensionsRef.current = {};
runOnUI(() => {
measuredItemsCount.value = 0;
queuedMeasurements.value = null;
if (typeof itemWidths.value === 'object') {
itemWidths.value = {};
}
if (typeof itemHeights.value === 'object') {
itemHeights.value = {};
}
})();
}, [itemHeights, itemWidths, measuredItemsCount, queuedMeasurements]);

return {
value: {
applyControlledContainerDimensions,
handleContainerMeasurement,
handleItemMeasurement,
removeItemMeasurements
removeItemMeasurements,
resetMeasurements
}
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { HIDDEN_X_OFFSET, IS_WEB, isFabric } from '../../../constants';
import {
type AnimatedStyleProp,
useAnimatedDebounce,
useMutableValue
} from '../../../integrations/reanimated';
import type { Vector } from '../../../types';
Expand Down Expand Up @@ -86,30 +87,20 @@ function useItemLayoutStylePaper(
*/
function useItemLayoutStyleFabric(
position: SharedValue<null | Vector>,
layoutPosition: SharedValue<null | Vector>,
zIndex: SharedValue<number>
) {
const { activeItemDropped, usesAbsoluteLayout } = useCommonValuesContext();
const transformStartPosition = useMutableValue<null | Vector>(null);
const debounce = useAnimatedDebounce();

useAnimatedReaction(
() => ({
current: position.value,
dropped: activeItemDropped.value,
layout: layoutPosition.value
}),
({ current, dropped, layout }) => {
if (
!transformStartPosition.value &&
layout &&
current &&
areVectorsDifferent(layout, current)
) {
// Switch to positioning via transform for every item which position
// is being changed while one of the items is being dragged
transformStartPosition.value = current;
} else if (dropped) {
transformStartPosition.value = null;
() => ({ current: position.value, dropped: activeItemDropped.value }),
({ current, dropped }) => {
transformStartPosition.value ??= current;
if (dropped) {
debounce(() => {
transformStartPosition.value = null;
}, 50);
}
}
);
Expand Down Expand Up @@ -259,7 +250,7 @@ export default function useItemLayoutStyle(

return isFabric() || IS_WEB
? // eslint-disable-next-line react-hooks/rules-of-hooks
useItemLayoutStyleFabric(position, layoutPosition, zIndex)
useItemLayoutStyleFabric(position, zIndex)
: // eslint-disable-next-line react-hooks/rules-of-hooks
useItemLayoutStylePaper(position, zIndex);
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export type MeasurementsContextType = {
removeItemMeasurements: (key: string) => void;
handleContainerMeasurement: (width: number, height: number) => void;
applyControlledContainerDimensions: (dimensions: Partial<Dimensions>) => void;
resetMeasurements: () => void;
};

// AUTO SCROLL
Expand Down
Loading