From f4f42c4f5c306a6bb6161a4fe23e4fee0b6a4bc7 Mon Sep 17 00:00:00 2001 From: Clauderic Demers Date: Mon, 22 Mar 2021 22:37:18 -0400 Subject: [PATCH] Clean up refactor --- .../src/components/DndContext/DndContext.tsx | 90 ++-------- .../core/src/components/DndContext/index.ts | 8 +- packages/core/src/components/index.ts | 7 +- packages/core/src/hooks/index.ts | 2 + packages/core/src/hooks/utilities/index.ts | 7 +- .../src/hooks/utilities/useLayoutMeasuring.ts | 154 ++++++++++++++++++ .../src/hooks/utilities/useLayoutRectMap.ts | 83 ---------- packages/core/src/index.ts | 47 +++--- 8 files changed, 198 insertions(+), 200 deletions(-) create mode 100644 packages/core/src/hooks/utilities/useLayoutMeasuring.ts delete mode 100644 packages/core/src/hooks/utilities/useLayoutRectMap.ts diff --git a/packages/core/src/components/DndContext/DndContext.tsx b/packages/core/src/components/DndContext/DndContext.tsx index f04dd4a02..7364b23b2 100644 --- a/packages/core/src/components/DndContext/DndContext.tsx +++ b/packages/core/src/components/DndContext/DndContext.tsx @@ -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, @@ -147,32 +148,13 @@ export const ActiveDraggableContext = createContext({ 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 @@ -188,21 +170,16 @@ export const DndContext = memo(function DndContext({ const [activatorEvent, setActivatorEvent] = useState(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 @@ -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; @@ -507,32 +474,6 @@ export const DndContext = memo(function DndContext({ }); }, [scrollAdjustedTransalte.x, scrollAdjustedTransalte.y]); - const recomputeLayoutsTimeoutId = useRef(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; @@ -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; -} diff --git a/packages/core/src/components/DndContext/index.ts b/packages/core/src/components/DndContext/index.ts index 534cbab7d..5e67b2290 100644 --- a/packages/core/src/components/DndContext/index.ts +++ b/packages/core/src/components/DndContext/index.ts @@ -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'; diff --git a/packages/core/src/components/index.ts b/packages/core/src/components/index.ts index edfbd0df5..003d7291d 100644 --- a/packages/core/src/components/index.ts +++ b/packages/core/src/components/index.ts @@ -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, diff --git a/packages/core/src/hooks/index.ts b/packages/core/src/hooks/index.ts index 425281d37..d98ae32a2 100644 --- a/packages/core/src/hooks/index.ts +++ b/packages/core/src/hooks/index.ts @@ -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'; diff --git a/packages/core/src/hooks/utilities/index.ts b/packages/core/src/hooks/utilities/index.ts index d0610a33c..4291a8018 100644 --- a/packages/core/src/hooks/utilities/index.ts +++ b/packages/core/src/hooks/utilities/index.ts @@ -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 { diff --git a/packages/core/src/hooks/utilities/useLayoutMeasuring.ts b/packages/core/src/hooks/utilities/useLayoutMeasuring.ts new file mode 100644 index 000000000..17033dab2 --- /dev/null +++ b/packages/core/src/hooks/utilities/useLayoutMeasuring.ts @@ -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 | 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(null); + const disabled = + strategy === LayoutMeasuringStrategy.Always ? false : dragging; + const layoutRectMap = useLazyMemo( + (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; +} diff --git a/packages/core/src/hooks/utilities/useLayoutRectMap.ts b/packages/core/src/hooks/utilities/useLayoutRectMap.ts deleted file mode 100644 index b230d42e8..000000000 --- a/packages/core/src/hooks/utilities/useLayoutRectMap.ts +++ /dev/null @@ -1,83 +0,0 @@ -import {useCallback, useEffect, useRef, useState} from 'react'; -import {useLazyMemo} from '@dnd-kit/utilities'; - -import {getElementLayout} from '../../utilities'; -import {DroppableContainers, LayoutRectMap} from '../../store/types'; - -const defaultValue: LayoutRectMap = new Map(); - -export function useLayoutRectMap( - containers: DroppableContainers, - disabled: boolean -) { - const [willRecomputeLayouts, setWillRecomputeLayouts] = useState(false); - const containersRef = useRef(containers); - const recomputeLayouts = useCallback(() => { - setWillRecomputeLayouts(true); - }, []); - const layoutRectMap = useLazyMemo( - (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]); - - 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; -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 27b1e496b..b9ed92fbf 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,10 +1,4 @@ -export { - DndContext, - DragOverlay, - defaultAnnouncements, - LayoutMeasuringFrequency, - LayoutMeasuringStrategy, -} from './components'; +export {DndContext, DragOverlay, defaultAnnouncements} from './components'; export type { Announcements, CancelDrop, @@ -13,39 +7,50 @@ export type { DragOverEvent, DragStartEvent, DropAnimation, - LayoutMeasuring, ScreenReaderInstructions, } from './components'; export { + LayoutMeasuringFrequency, + LayoutMeasuringStrategy, useDraggable, - UseDraggableArguments, useDndContext, - UseDndContextReturnValue, useDroppable, - UseDroppableArguments, +} from './hooks'; +export type { DraggableSyntheticListeners, + LayoutMeasuring, + UseDndContextReturnValue, + UseDraggableArguments, + UseDroppableArguments, } from './hooks'; -export {applyModifiers, Modifier, Modifiers} from './modifiers'; +export {applyModifiers} from './modifiers'; +export type {Modifier, Modifiers} from './modifiers'; export { + KeyboardSensor, + KeyboardCode, + MouseSensor, + PointerSensor, + Sensor, + Sensors, + TouchSensor, + useSensors, + useSensor, +} from './sensors'; +export type { Activator, Activators, PointerActivationConstraint, + KeyboardCodes, KeyboardCoordinateGetter, - KeyboardSensor, KeyboardSensorOptions, KeyboardSensorProps, - KeyboardCode, - KeyboardCodes, - MouseSensor, MouseSensorOptions, - PointerSensor, PointerEventHandlers, PointerSensorOptions, PointerSensorProps, - Sensor, SensorContext, SensorDescriptor, SensorHandler, @@ -53,11 +58,7 @@ export { SensorOptions, SensorProps, SensorResponse, - Sensors, - TouchSensor, TouchSensorOptions, - useSensors, - useSensor, } from './sensors'; export type {DndContextDescriptor} from './store'; @@ -77,5 +78,5 @@ export { closestCenter, closestCorners, rectIntersection, - CollisionDetection, } from './utilities'; +export type {CollisionDetection} from './utilities';