react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
88 lines (87 loc) • 3.52 kB
JavaScript
;
import React from "react";
import { useCallback, useEffect, useRef } from 'react';
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
import { useStableCallback } from '../../../hooks';
import { useMutableValue } from '../../../integrations/reanimated';
import { CommonValuesContext, ItemContextProvider, useItemNode, usePortalContext } from '../../../providers';
import { getContextProvider } from '../../../utils';
import TeleportedItemCell from './TeleportedItemCell';
import { jsx as _jsx } from "react/jsx-runtime";
const CommonValuesContextProvider = getContextProvider(CommonValuesContext);
export default function ActiveItemPortal({
activationAnimationProgress,
baseStyle,
commonValuesContext,
gesture,
isActive,
itemKey,
onTeleport
}) {
const node = useItemNode(itemKey);
const {
isTeleported,
measurePortalOutlet,
teleport
} = usePortalContext() ?? {};
const teleportEnabled = useMutableValue(false);
const isFirstUpdateRef = useRef(true);
const renderTeleportedItemCell = useCallback(() =>
/*#__PURE__*/
// We have to wrap the TeleportedItemCell in context providers as they won't
// be accessible otherwise, when the item is rendered in the portal outlet
_jsx(CommonValuesContextProvider, {
value: commonValuesContext,
children: /*#__PURE__*/_jsx(ItemContextProvider, {
activationAnimationProgress: activationAnimationProgress,
gesture: gesture,
isActive: isActive,
itemKey: itemKey,
children: /*#__PURE__*/_jsx(TeleportedItemCell, {
activationAnimationProgress: activationAnimationProgress,
baseStyle: baseStyle,
isActive: isActive,
itemKey: itemKey,
children: node
})
})
}), [activationAnimationProgress, baseStyle, commonValuesContext, gesture, isActive, node, itemKey]);
const teleportedItemId = `${commonValuesContext.containerId}-${itemKey}`;
const enableTeleport = useStableCallback(() => {
isFirstUpdateRef.current = true;
teleport?.(teleportedItemId, renderTeleportedItemCell());
onTeleport(true);
});
const disableTeleport = useCallback(() => {
teleport?.(teleportedItemId, null);
onTeleport(false);
}, [teleport, teleportedItemId, onTeleport]);
useEffect(() => disableTeleport, [disableTeleport]);
useEffect(() => {
const checkTeleported = () => isTeleported?.(teleportedItemId);
if (!checkTeleported()) return;
const update = () => checkTeleported() && teleport?.(teleportedItemId, renderTeleportedItemCell());
if (isFirstUpdateRef.current) {
isFirstUpdateRef.current = false;
// Needed for proper collapsible items behavior
setTimeout(update);
} else {
update();
}
}, [isTeleported, renderTeleportedItemCell, teleport, teleportedItemId]);
useAnimatedReaction(() => activationAnimationProgress.value, (progress, prevProgress) => {
if (prevProgress !== null && progress > prevProgress && !teleportEnabled.value) {
// We have to ensure that the portal outlet ref is measured before the
// teleported item is rendered within it because portal outlet position
// must be known to calculate the teleported item position
measurePortalOutlet?.();
teleportEnabled.value = true;
runOnJS(enableTeleport)();
} else if (progress === 0 && teleportEnabled.value) {
teleportEnabled.value = false;
runOnJS(disableTeleport)();
}
});
return null;
}
//# sourceMappingURL=ActiveItemPortal.js.map