Skip to content

Commit

Permalink
Clean up refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Clauderic Demers committed Mar 23, 2021
1 parent 4022411 commit f4f42c4
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 200 deletions.
90 changes: 10 additions & 80 deletions packages/core/src/components/DndContext/DndContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ import {
} from '../../store';
import type {Coordinates, ViewRect, LayoutRect, Translate} from '../../types';
import {
LayoutMeasuring,
SyntheticListener,
useAutoScroller,
useCachedNode,
useCombineActivators,
useLayoutRectMap,
useLayoutMeasuring,
useScrollableAncestors,
useClientRect,
useClientRects,
useScrollOffsets,
useViewRect,
SyntheticListener,
} from '../../hooks/utilities';
import {
KeyboardSensor,
Expand Down Expand Up @@ -147,32 +148,13 @@ export const ActiveDraggableContext = createContext<Transform>({
scaleY: 1,
});

export enum LayoutMeasuringStrategy {
Always = 'always',
WhileDragging = 'while-dragging',
}

export enum LayoutMeasuringFrequency {
Optimized = 'optimized',
}

export interface LayoutMeasuring {
strategy: LayoutMeasuringStrategy;
frequency: LayoutMeasuringFrequency | number;
}

const defaultLayoutMeasuring: LayoutMeasuring = {
strategy: LayoutMeasuringStrategy.WhileDragging,
frequency: LayoutMeasuringFrequency.Optimized,
};

export const DndContext = memo(function DndContext({
autoScroll = true,
announcements,
children,
sensors = defaultSensors,
collisionDetection = rectIntersection,
layoutMeasuring: customLayoutMeasuring,
layoutMeasuring,
modifiers,
screenReaderInstructions = defaultScreenReaderInstructions,
...props
Expand All @@ -188,21 +170,16 @@ export const DndContext = memo(function DndContext({
const [activatorEvent, setActivatorEvent] = useState<Event | null>(null);
const latestProps = useRef(props);
const draggableDescribedById = useUniqueId(`DndDescribedBy`);
const layoutMeasuring = customLayoutMeasuring
? {
...defaultLayoutMeasuring,
...customLayoutMeasuring,
}
: defaultLayoutMeasuring;
const {frequency} = layoutMeasuring;
const layoutMeasuringEnabled = shouldMeasureLayouts(layoutMeasuring, {
active,
});

const {
layoutRectMap: droppableRects,
recomputeLayouts,
willRecomputeLayouts,
} = useLayoutRectMap(droppableContainers, !layoutMeasuringEnabled);
} = useLayoutMeasuring(droppableContainers, {
dragging: active != null,
dependencies: [translate.x, translate.y],
config: layoutMeasuring,
});
const activeNode = useCachedNode(
getDraggableNode(active, draggableNodes),
active
Expand Down Expand Up @@ -451,16 +428,6 @@ export const DndContext = memo(function DndContext({
Object.values(props)
);

useIsomorphicLayoutEffect(
() => {
if (layoutMeasuringEnabled) {
requestAnimationFrame(() => recomputeLayouts());
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[active, layoutMeasuringEnabled, recomputeLayouts]
);

useEffect(() => {
if (!active) {
initialActiveNodeRectRef.current = null;
Expand Down Expand Up @@ -507,32 +474,6 @@ export const DndContext = memo(function DndContext({
});
}, [scrollAdjustedTransalte.x, scrollAdjustedTransalte.y]);

const recomputeLayoutsTimeoutId = useRef<NodeJS.Timeout | null>(null);

useEffect(
function forceRecomputeLayouts() {
if (
!layoutMeasuringEnabled ||
typeof frequency !== 'number' ||
recomputeLayoutsTimeoutId.current !== null
) {
return;
}

recomputeLayoutsTimeoutId.current = setTimeout(() => {
recomputeLayouts();
recomputeLayoutsTimeoutId.current = null;
}, frequency);
},
[
frequency,
layoutMeasuringEnabled,
recomputeLayouts,
scrollAdjustedTransalte.x,
scrollAdjustedTransalte.y,
]
);

useEffect(() => {
if (!activeRef.current) {
return;
Expand Down Expand Up @@ -693,14 +634,3 @@ function getLayoutRect(
): LayoutRect | null {
return id ? layoutRectMap.get(id) ?? null : null;
}

function shouldMeasureLayouts(
{strategy}: LayoutMeasuring,
{active}: {active: UniqueIdentifier | null}
) {
if (strategy === LayoutMeasuringStrategy.Always) {
return true;
}

return active != null;
}
8 changes: 1 addition & 7 deletions packages/core/src/components/DndContext/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
export {
ActiveDraggableContext,
DndContext,
LayoutMeasuringStrategy,
LayoutMeasuringFrequency,
} from './DndContext';
export {ActiveDraggableContext, DndContext} from './DndContext';
export type {
CancelDrop,
DragStartEvent,
DragMoveEvent,
DragOverEvent,
DragEndEvent,
LayoutMeasuring,
} from './DndContext';
7 changes: 1 addition & 6 deletions packages/core/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ export {
defaultAnnouncements,
ScreenReaderInstructions,
} from './Accessibility';
export {
DndContext,
LayoutMeasuringFrequency,
LayoutMeasuringStrategy,
} from './DndContext';
export {DndContext} from './DndContext';
export type {
CancelDrop,
DragEndEvent,
DragOverEvent,
DragMoveEvent,
DragStartEvent,
LayoutMeasuring,
} from './DndContext';
export {
DragOverlay,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export {
} from './useDraggable';
export {useDndContext, UseDndContextReturnValue} from './useDndContext';
export {useDroppable, UseDroppableArguments} from './useDroppable';
export {LayoutMeasuringStrategy, LayoutMeasuringFrequency} from './utilities';
export type {LayoutMeasuring} from './utilities';
7 changes: 6 additions & 1 deletion packages/core/src/hooks/utilities/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
export {useAutoScroller} from './useAutoScroller';
export {useCachedNode} from './useCachedNode';
export {useCombineActivators} from './useCombineActivators';
export {useLayoutRectMap} from './useLayoutRectMap';
export {
useLayoutMeasuring,
LayoutMeasuringFrequency,
LayoutMeasuringStrategy,
} from './useLayoutMeasuring';
export type {LayoutMeasuring} from './useLayoutMeasuring';
export {useScrollOffsets} from './useScrollOffsets';
export {useScrollableAncestors} from './useScrollableAncestors';
export {
Expand Down
154 changes: 154 additions & 0 deletions packages/core/src/hooks/utilities/useLayoutMeasuring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import {useCallback, useEffect, useRef, useState} from 'react';
import {useLazyMemo, useIsomorphicLayoutEffect} from '@dnd-kit/utilities';

import {getElementLayout} from '../../utilities';
import type {DroppableContainers, LayoutRectMap} from '../../store/types';

interface Arguments {
dragging: boolean;
dependencies: any[];
config: Partial<LayoutMeasuring> | undefined;
}

export enum LayoutMeasuringStrategy {
Always = 'always',
WhileDragging = 'while-dragging',
}

export enum LayoutMeasuringFrequency {
Optimized = 'optimized',
}

export interface LayoutMeasuring {
strategy: LayoutMeasuringStrategy;
frequency: LayoutMeasuringFrequency | number;
}

const defaultValue: LayoutRectMap = new Map();

export function useLayoutMeasuring(
containers: DroppableContainers,
{dragging, dependencies, config}: Arguments
) {
const [willRecomputeLayouts, setWillRecomputeLayouts] = useState(false);
const {frequency, strategy} = getLayoutMeasuring(config);
const containersRef = useRef(containers);
const recomputeLayouts = useCallback(() => {
setWillRecomputeLayouts(true);
}, []);
const recomputeLayoutsTimeoutId = useRef<NodeJS.Timeout | null>(null);
const disabled =
strategy === LayoutMeasuringStrategy.Always ? false : dragging;
const layoutRectMap = useLazyMemo<LayoutRectMap>(
(previousValue) => {
if (disabled) {
return defaultValue;
}

if (
!previousValue ||
previousValue === defaultValue ||
containersRef.current !== containers ||
willRecomputeLayouts
) {
for (let container of Object.values(containers)) {
if (!container) {
continue;
}

container.rect.current = container.node.current
? getElementLayout(container.node.current)
: null;
}

return createLayoutRectMap(containers);
}

return previousValue;
},
[containers, disabled, willRecomputeLayouts]
);

useEffect(() => {
containersRef.current = containers;
}, [containers]);

useEffect(() => {
if (willRecomputeLayouts) {
setWillRecomputeLayouts(false);
}
}, [willRecomputeLayouts]);

useIsomorphicLayoutEffect(
function recompute() {
if (disabled) {
return;
}

requestAnimationFrame(() => recomputeLayouts());
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[dragging, disabled]
);

useEffect(
function forceRecomputeLayouts() {
if (
disabled ||
typeof frequency !== 'number' ||
recomputeLayoutsTimeoutId.current !== null
) {
return;
}

recomputeLayoutsTimeoutId.current = setTimeout(() => {
recomputeLayouts();
recomputeLayoutsTimeoutId.current = null;
}, frequency);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[frequency, disabled, recomputeLayouts, ...dependencies]
);

return {layoutRectMap, recomputeLayouts, willRecomputeLayouts};
}

function createLayoutRectMap(
containers: DroppableContainers | null
): LayoutRectMap {
const layoutRectMap: LayoutRectMap = new Map();

if (containers) {
for (const container of Object.values(containers)) {
if (!container) {
continue;
}

const {id, rect, disabled} = container;

if (disabled || rect.current == null) {
continue;
}

layoutRectMap.set(id, rect.current);
}
}

return layoutRectMap;
}

const defaultLayoutMeasuring: LayoutMeasuring = {
strategy: LayoutMeasuringStrategy.WhileDragging,
frequency: LayoutMeasuringFrequency.Optimized,
};

function getLayoutMeasuring(
layoutMeasuring: Arguments['config']
): LayoutMeasuring {
return layoutMeasuring
? {
...defaultLayoutMeasuring,
...layoutMeasuring,
}
: defaultLayoutMeasuring;
}
Loading

0 comments on commit f4f42c4

Please sign in to comment.