react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
84 lines (81 loc) • 2.9 kB
JavaScript
;
import React from "react";
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { measure, useAnimatedRef } from 'react-native-reanimated';
import { EMPTY_OBJECT } from '../../constants';
import { useMutableValue } from '../../integrations/reanimated';
import { createProvider } from '../utils';
import { PortalOutletProvider } from './PortalOutletProvider';
/** Props for the PortalProvider component */
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const {
PortalProvider,
usePortalContext
} = createProvider('Portal', {
guarded: false
})(({
children,
enabled,
propagateToOuterPortal = false
}) => {
// I need to cast the type because TS goes crazy when I am trying to use it
// directly. I am casting it to the same type as the return type of usePortalContext
const outerPortalContext = usePortalContext();
const [teleportedNodes, setTeleportedNodes] = useState(EMPTY_OBJECT);
const teleportedNodeIdsRef = useRef(new Set());
const portalOutletRef = useAnimatedRef();
const activeItemAbsolutePosition = useMutableValue(null);
const portalOutletMeasurements = useMutableValue(null);
const shouldPropagate = !!outerPortalContext && propagateToOuterPortal;
useEffect(() => {
if (!enabled || shouldPropagate) {
setTeleportedNodes(EMPTY_OBJECT);
}
}, [enabled, shouldPropagate]);
const teleport = useCallback((id, node) => {
if (node) {
teleportedNodeIdsRef.current.add(id);
setTeleportedNodes(prev => ({
...prev,
[id]: node
}));
} else if (teleportedNodeIdsRef.current.has(id)) {
teleportedNodeIdsRef.current.delete(id);
setTeleportedNodes(prev => {
const {
[id]: _,
...rest
} = prev;
return rest;
});
}
}, []);
const isTeleported = useCallback(id => teleportedNodeIdsRef.current.has(id), []);
const measurePortalOutlet = useCallback(() => {
'worklet';
portalOutletMeasurements.value = measure(portalOutletRef);
}, [portalOutletRef, portalOutletMeasurements]);
const outlet = useMemo(() => !shouldPropagate && /*#__PURE__*/_jsx(PortalOutletProvider, {
measurePortalOutlet: measurePortalOutlet,
portalOutletRef: portalOutletRef,
children: Object.entries(teleportedNodes).map(([id, node]) => /*#__PURE__*/_jsx(Fragment, {
children: node
}, id))
}), [measurePortalOutlet, portalOutletRef, shouldPropagate, teleportedNodes]);
const value = shouldPropagate ? outerPortalContext : {
activeItemAbsolutePosition,
isTeleported,
measurePortalOutlet,
portalOutletMeasurements,
teleport
};
return {
children: /*#__PURE__*/_jsxs(Fragment, {
children: [children, outlet]
}),
enabled,
value: value
};
});
export { PortalProvider, usePortalContext };
//# sourceMappingURL=PortalProvider.js.map