react-beautiful-dnd
Version:
Beautiful, accessible drag and drop for lists with React.js
77 lines (67 loc) • 2.22 kB
JavaScript
// @flow
import { type Position, type Spacing, type Rect } from 'css-box-model';
import isPartiallyVisibleThroughFrame from './is-partially-visible-through-frame';
import isTotallyVisibleThroughFrame from './is-totally-visible-through-frame';
import { offsetByPosition } from '../spacing';
import { origin } from '../position';
import type { DroppableDimension } from '../../types';
type Args = {|
target: Spacing,
destination: DroppableDimension,
viewport: Rect,
|};
type HelperArgs = {|
...Args,
isVisibleThroughFrameFn: (frame: Spacing) => (subject: Spacing) => boolean,
|};
const isVisible = ({
target,
destination,
viewport,
isVisibleThroughFrameFn,
}: HelperArgs): boolean => {
const displacement: Position = destination.viewport.closestScrollable
? destination.viewport.closestScrollable.scroll.diff.displacement
: origin;
const withDisplacement: Spacing = offsetByPosition(target, displacement);
// destination subject is totally hidden by frame
// this should never happen - but just guarding against it
if (!destination.viewport.clippedPageMarginBox) {
return false;
}
// When considering if the target is visible in the droppable we need
// to consider the change in scroll of the droppable. We need to
// adjust for the scroll as the clipped viewport takes into account
// the scroll of the droppable.
const isVisibleInDroppable: boolean = isVisibleThroughFrameFn(
destination.viewport.clippedPageMarginBox,
)(withDisplacement);
// We also need to consider whether the destination scroll when detecting
// if we are visible in the viewport.
const isVisibleInViewport: boolean = isVisibleThroughFrameFn(viewport)(
withDisplacement,
);
return isVisibleInDroppable && isVisibleInViewport;
};
export const isPartiallyVisible = ({
target,
destination,
viewport,
}: Args): boolean =>
isVisible({
target,
destination,
viewport,
isVisibleThroughFrameFn: isPartiallyVisibleThroughFrame,
});
export const isTotallyVisible = ({
target,
destination,
viewport,
}: Args): boolean =>
isVisible({
target,
destination,
viewport,
isVisibleThroughFrameFn: isTotallyVisibleThroughFrame,
});