@hello-pangea/dnd
Version:
Beautiful and accessible drag and drop for lists with React
69 lines (60 loc) • 2.1 kB
text/typescript
import { useRef } from 'react';
import { invariant } from '../../invariant';
import type { DraggableId, ContextId } from '../../types';
import type { Props } from './draggable-types';
import checkIsValidInnerRef from '../check-is-valid-inner-ref';
import findDragHandle from '../get-elements/find-drag-handle';
import useDevSetupWarning from '../use-dev-setup-warning';
import useDev from '../use-dev';
export function useValidation(
props: Props,
contextId: ContextId,
getRef: () => HTMLElement | null,
) {
// running after every update in development
useDevSetupWarning(() => {
function prefix(id: DraggableId): string {
return `Draggable[id: ${id}]: `;
}
// wrapping entire block for better minification
const id: DraggableId | null = props.draggableId;
invariant(id, 'Draggable requires a draggableId');
invariant(
typeof id === 'string',
`Draggable requires a [string] draggableId.
Provided: [type: ${typeof id}] (value: ${id})`,
);
invariant(
Number.isInteger(props.index),
`${prefix(id)} requires an integer index prop`,
);
if (props.mapped.type === 'DRAGGING') {
return;
}
// Checking provided ref (only when not dragging as it might be removed)
checkIsValidInnerRef(getRef());
// Checking that drag handle is provided
// Only running check when enabled.
// When not enabled there is no drag handle props
if (props.isEnabled) {
invariant(
findDragHandle(contextId, id),
`${prefix(id)} Unable to find drag handle`,
);
}
});
}
// we expect isClone not to change for entire component's life
export function useClonePropValidation(isClone: boolean) {
useDev(() => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const initialRef = useRef<boolean>(isClone);
// eslint-disable-next-line react-hooks/rules-of-hooks
useDevSetupWarning(() => {
invariant(
isClone === initialRef.current,
'Draggable isClone prop value changed during component life',
);
}, [isClone]);
});
}