UNPKG

react-native-sortables

Version:

Powerful Sortable Components for Flexible Content Reordering in React Native

93 lines (90 loc) 3.18 kB
"use strict"; 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 subscribersRef = useRef({}); 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 notifySubscribers = useCallback((id, isTeleported) => { subscribersRef.current?.[id]?.forEach(subscriber => subscriber(isTeleported)); }, []); const teleport = useCallback((id, node) => { if (node) { setTeleportedNodes(prev => ({ ...prev, [id]: node })); notifySubscribers(id, true); } else { setTeleportedNodes(prev => { const { [id]: _, ...rest } = prev; return rest; }); notifySubscribers(id, false); } }, [notifySubscribers]); const subscribe = useCallback((id, subscriber) => { subscribersRef.current[id] = subscribersRef.current[id] ?? new Set(); subscribersRef.current[id].add(subscriber); return () => { subscribersRef.current[id]?.delete(subscriber); }; }, []); const measurePortalOutlet = useCallback(() => { 'worklet'; portalOutletMeasurements.value = measure(portalOutletRef); }, [portalOutletRef, portalOutletMeasurements]); const value = shouldPropagate ? outerPortalContext : { activeItemAbsolutePosition, measurePortalOutlet, portalOutletMeasurements, subscribe, teleport }; 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]); return { children: /*#__PURE__*/_jsxs(Fragment, { children: [children, outlet] }), enabled, value: value }; }); export { PortalProvider, usePortalContext }; //# sourceMappingURL=PortalProvider.js.map