UNPKG

@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-migration

Version:

An optional Pragmatic drag and drop package that enables rapid migration from react-beautiful-dnd to Pragmatic drag and drop

86 lines (80 loc) 2.58 kB
/** * The lifecycle methods owned by this provided are used to align internal * timings with those of the rbd lifecycle. * * The events are intentionally distinct to those exposed by rbd to avoid * any confusion around whether events are fired internally or externally * first. */ import React, { createContext, useCallback, useContext, useState } from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'; import { batchUpdatesForReact16 } from '../utils/batch-updates-for-react-16'; import { rbdInvariant } from './rbd-invariant'; /** * The data associated with each type of lifecycle event. */ function createRegistry() { return { onPendingDragStart: [], onPrePendingDragUpdate: [], onPendingDragUpdate: [], onBeforeDragEnd: [] }; } function createLifecycleManager() { const registry = createRegistry(); const addResponder = (event, responder) => { registry[event].push(responder); return () => { // @ts-expect-error - type narrowing issues registry[event] = registry[event].filter(value => value !== responder); }; }; const dispatch = (event, data) => { batchUpdatesForReact16(() => { for (const responder of registry[event]) { responder(data); } }); }; return { addResponder, dispatch }; } /** * Creates a new lifecycle manager, returning methods for interfacing with it. */ export function useLifecycle() { const [lifecycleManager] = useState(createLifecycleManager); return lifecycleManager; } const LifecycleContext = /*#__PURE__*/createContext(null); export function LifecycleContextProvider({ children, lifecycle }) { /** * Allows for `<Draggable>` and `<Droppable>` instances to know about the * lifecycle timings. * * Designed to have a similar API to the pdnd monitors. */ const monitorForLifecycle = useCallback(responders => { const cleanupFns = []; for (const entry of Object.entries(responders)) { const [event, responder] = entry; cleanupFns.push(lifecycle.addResponder(event, responder)); } return combine(...cleanupFns); }, [lifecycle]); return /*#__PURE__*/React.createElement(LifecycleContext.Provider, { value: monitorForLifecycle }, children); } export function useMonitorForLifecycle() { const monitorForLifecycle = useContext(LifecycleContext); rbdInvariant(monitorForLifecycle !== null, 'useLifecycle() should only be called inside of a <DragDropContext />'); return monitorForLifecycle; }