diff --git a/packages/redux-devtools-inspector-monitor/src/ActionList.tsx b/packages/redux-devtools-inspector-monitor/src/ActionList.tsx index 1a7e7978..c0cf6aff 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionList.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionList.tsx @@ -1,7 +1,32 @@ -import React, { useCallback, useLayoutEffect, useRef } from 'react'; +import React, { + forwardRef, + ReactNode, + useCallback, + useLayoutEffect, + useRef, + useState, +} from 'react'; import { Action } from 'redux'; import { PerformAction } from '@redux-devtools/core'; import { StylingFunction } from 'react-base16-styling'; +import { + closestCenter, + DndContext, + DragEndEvent, + DragOverlay, + DragStartEvent, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { + SortableContext, + sortableKeyboardCoordinates, + useSortable, + verticalListSortingStrategy, +} from '@dnd-kit/sortable'; +import { CSS } from '@dnd-kit/utilities'; import ActionListRow from './ActionListRow'; import ActionListHeader from './ActionListHeader'; @@ -65,9 +90,13 @@ export default function ActionListFunction>({ onSweep, onJumpToState, lastActionId, + onReorderAction, }: Props) { const nodeRef = useRef(null); const prevLastActionId = useRef(); + const [activeDragActionId, setActiveDragActionId] = useState( + null, + ); useLayoutEffect(() => { if (nodeRef.current && prevLastActionId.current !== lastActionId) { @@ -88,6 +117,28 @@ export default function ActionListFunction>({ nodeRef.current = node; }, []); + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }), + ); + + const handleDragStart = useCallback(({ active }: DragStartEvent) => { + setActiveDragActionId(active.id as number); + }, []); + + const handleDragEnd = useCallback( + ({ active, over }: DragEndEvent) => { + if (over && active.id !== over.id) { + onReorderAction(active.id as number, over.id as number); + } + + setActiveDragActionId(null); + }, + [onReorderAction], + ); + const lowerSearchValue = searchValue && searchValue.toLowerCase(); const filteredActionIds = searchValue ? actionIds.filter( @@ -98,6 +149,35 @@ export default function ActionListFunction>({ ) : actionIds; + function renderActionListRow(actionId: number) { + return ( + = startActionId && + actionId <= (selectedActionId as number)) || + actionId === selectedActionId + } + isInFuture={ + actionIds.indexOf(actionId) > actionIds.indexOf(currentActionId) + } + onSelect={(e: React.MouseEvent) => + onSelect(e, actionId) + } + timestamps={getTimestamps(actions, actionIds, actionId)} + action={actions[actionId].action} + onToggleClick={() => onToggleAction(actionId)} + onJumpClick={() => onJumpToState(actionId)} + onCommitClick={() => onCommit()} + hideActionButtons={hideActionButtons} + isSkipped={skippedActionIds.indexOf(actionId) !== -1} + /> + ); + } + return (
>({ {...styling('actionListRows')} ref={setNodeRef} > - {filteredActionIds.map((actionId) => ( - = startActionId && - actionId <= (selectedActionId as number)) || - actionId === selectedActionId - } - isInFuture={ - actionIds.indexOf(actionId) > actionIds.indexOf(currentActionId) - } - onSelect={(e: React.MouseEvent) => - onSelect(e, actionId) - } - timestamps={getTimestamps(actions, actionIds, actionId)} - action={actions[actionId].action} - onToggleClick={() => onToggleAction(actionId)} - onJumpClick={() => onJumpToState(actionId)} - onCommitClick={() => onCommit()} - hideActionButtons={hideActionButtons} - isSkipped={skippedActionIds.indexOf(actionId) !== -1} - /> - ))} + + + {filteredActionIds.map((actionId) => ( + + {renderActionListRow(actionId)} + + ))} + + + {activeDragActionId ? ( + {renderActionListRow(activeDragActionId)} + ) : null} + +
); } + +interface SortableItemProps { + readonly children: ReactNode; + readonly actionId: number; +} + +function SortableItem({ children, actionId }: SortableItemProps) { + const { attributes, listeners, setNodeRef, transform, transition } = + useSortable({ id: actionId }); + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + + return ( + + {children} + + ); +} + +const Item = forwardRef< + HTMLDivElement, + React.DetailedHTMLProps, HTMLDivElement> +>(function Item({ ...props }, ref) { + return
; +});