import type { StartRowDragAction, UpdateRowDragAction, ApplyPropsAction, } from '../actions' import type { GridRowId, GridRowDragMode, GridRowDragConfig, GridDragResponse, } from '../../types' import { createReducer } from '../utils' import type { CollisionDetails } from '../../functional/grid-drag-controller/collision' export type GridDragState = CollisionDetails & { active: boolean draggingRowIds: Set recentlyDroppedRowIds: Set moveReceived: boolean allowed: boolean message?: string config: { previewColumnId: string | null enabled: boolean mode: GridRowDragMode enableLeafConversion: boolean multiple: boolean canDrop?: GridRowDragConfig['canDrop'] } } const EMPTY_COLLISION: CollisionDetails = { prevId: null, prevInsertId: null, parentId: null, level: 0, operation: 'between', } const initialState: GridDragState = { active: false, draggingRowIds: new Set(), recentlyDroppedRowIds: new Set(), moveReceived: false, ...EMPTY_COLLISION, allowed: false, config: { previewColumnId: null, enabled: false, mode: 'default', enableLeafConversion: false, multiple: false, }, } export default createReducer({ initialState, reducers: { applyProps(state, action: ApplyPropsAction): GridDragState { const config = action.payload.rowDrag return { ...state, config: { ...state.config, previewColumnId: config.previewColumnId ?? null, enabled: config.enabled, mode: config.mode ?? 'default', enableLeafConversion: config.enableLeafConversion === true, multiple: config.multiple === true, canDrop: config.canDrop, }, } }, startRowDrag(state, action: StartRowDragAction): GridDragState { return { ...state, active: true, draggingRowIds: action.payload.ids, moveReceived: false, ...EMPTY_COLLISION, } }, completeRowDrag(state): GridDragState { return { ...state, active: false, draggingRowIds: new Set(), recentlyDroppedRowIds: state.draggingRowIds, moveReceived: false, ...EMPTY_COLLISION, } }, cancelRowDrag(state): GridDragState { return { ...state, active: false, draggingRowIds: new Set(), moveReceived: false, ...EMPTY_COLLISION, } }, updateRowDrag(state, action: UpdateRowDragAction): GridDragState { return { ...state, moveReceived: true, ...action.payload, } }, removeRecentlyDragged(state) { return { ...state, recentlyDroppedRowIds: new Set(), } }, }, }) export const selectDragNeedsFinalRowOffset = (state: GridDragState) => state.active && state.config.mode === 'default' export const selectDragIsActive = (state: GridDragState) => state.active export const selectDragMoveReceived = (state: GridDragState) => state.moveReceived export const selectIsRowDragging = (state: GridDragState, rowId: GridRowId) => state.active && state.draggingRowIds.has(rowId) export const selectDropIsAllowed = (state: GridDragState) => state.allowed export const selectDragMessage = (state: GridDragState) => state.active ? state.message || '' : '' export const selectDragCollisionDetails = ( state: GridDragState ): CollisionDetails => ({ level: state.level, parentId: state.parentId, prevId: state.prevId, prevInsertId: state.prevInsertId, operation: state.operation, }) export const selectDraggingRowIds = (state: GridDragState) => state.draggingRowIds export const selectRecentlyDroppedRowIds = (state: GridDragState) => state.recentlyDroppedRowIds export const selectIsDraggingEnabled = (state: GridDragState) => state.config.enabled export const selectCanDragMultiple = (state: GridDragState) => state.config.multiple export const selectCanConvertLeaf = (state: GridDragState) => state.config.enableLeafConversion export const selectDragMode = (state: GridDragState) => state.config.mode const alwaysDropTrue: () => GridDragResponse = () => ({ allowed: true }) export const selectDropPredicate = (state: GridDragState) => state.config.canDrop || alwaysDropTrue export const selectConfiguredPreviewColumnId = (state: GridDragState) => state.config.previewColumnId ?? null