@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
JavaScript
/**
* 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;
}