import React, { forwardRef, HTMLAttributes, useEffect, useState } from 'react';
import { FiltersMap } from '@wix/bex-core';
import { DragAndDropBulkSubmit, DragAndDropSubmit } from '../DragAndDrop';
import { NestedTableNestedModeState } from '../../state';
import { observer } from 'mobx-react-lite';
import { TableProps } from '@wix/design-system';
import {
DragAndDropContext,
IDragAndDropContext,
} from '@wix/wix-style-react-incubator/drag-and-drop';
import { DragAndDropAnnouncements } from '../DragAndDrop/DragAndDropAnnouncements';
import {
dragHandleTestEvents,
sortableItemTestEvents,
} from '../GridDragAndDropDndKit/dndTestEventHandlers';
import { addEventListener } from '@wix/bex-core/util';
import { NestedTableDragAndDropState } from './NestedTableDragAndDropState';
import { minimalRequiredWdsRuntimeCheck } from '../../minimalRequiredWdsRuntimeCheck';
import { validateNestedTableDragAndDropProps } from './validateNestedTableDragAndDropProps';
import { DragOverlayTestComponent } from '../DragAndDrop/DragOverlayTestComponent';
import { DragOverlayProps } from '@wix/wix-style-react-incubator/dnd-kit/core';
import { NestedTableDragAndDropOverlay } from './NestedTableDragAndDropOverlay';
import { createUseIsDropDisabled } from './createUseIsDropDisabled';
import { usePageContext } from '@wix/bex-core/react';
export interface NestedTableDragAndDropContextProps<
C extends string,
T,
F extends FiltersMap,
> {
state: NestedTableNestedModeState;
onSubmit?: DragAndDropSubmit;
onBulkSubmit?: DragAndDropBulkSubmit;
children: React.ReactElement<
TableProps,
React.ComponentType>
>;
}
function _NestedTableDragAndDropContext<
C extends string,
T,
F extends FiltersMap,
>(props: NestedTableDragAndDropContextProps) {
const { state: nestedState, onSubmit, onBulkSubmit, children } = props;
const { type: Table, props: tableProps } = children;
if (process.env.NODE_ENV !== 'production') {
minimalRequiredWdsRuntimeCheck({
required: '^1.109.2',
requiredBy: 'WixPatterns/NestedTable',
});
validateNestedTableDragAndDropProps(nestedState);
}
const state =
nestedState.nestedTableDragAndDrop as NestedTableDragAndDropState;
const useIsDropDisabled = createUseIsDropDisabled(state);
const dragAndDropState = state.dnd;
const { modalsContainerRef } = usePageContext();
useEffect(() => state.init(), []);
dragAndDropState.onSubmit = onSubmit;
dragAndDropState.onBulkSubmit = onBulkSubmit;
const [dragAndDropContext] = useState(
(): IDragAndDropContext => ({
useIsDropDisabled,
closestCenterOnViewPort: true,
onDragAndDropDisabledRowPointerDown: (id, e) => {
dragAndDropState.attachDisabledDragAttempt(id as string, e, 'y');
},
cancelDrop: async (ev) => {
return dragAndDropState.beforeDrop(ev);
},
dropAnimation: {
duration: dragAndDropState.dropAnimation.duration,
easing: dragAndDropState.dropAnimation.easing,
},
announcements: dragAndDropState.nullAnnouncements,
a11yContainer: modalsContainerRef.current,
onDragOver: ({ over }) => dragAndDropState.onDragOver({ over }),
onDragMove: (event) => dragAndDropState.onDragMove(event),
restoreFocus: false,
onDropAnimationEnd: (id, dragHandleRef) => {
return addEventListener(
dragAndDropState.events,
'dropAnimationEnd',
() => {
dragAndDropState.focusDragHandleIfDropped(
id,
dragHandleRef.current,
);
},
);
},
overlayWrapperElement: forwardRef<
HTMLDivElement,
HTMLAttributes
>((props, ref) => (
)),
...(process.env.NODE_ENV === 'test' && {
DragOverlayComponentType: (props: DragOverlayProps) => (
),
}),
keyboardCodes: dragAndDropState.keyboardCodes,
autoScrollOptions: {
acceleration: 6,
},
hideOverlayBottomShadow: true,
eventHandlers: {
row: ({ id, disabled }) => {
const testEvents =
process.env.NODE_ENV === 'test'
? sortableItemTestEvents({
state: dragAndDropState,
id,
disabled,
})
: undefined;
return {
...testEvents,
onPointerDown: (e) => {
dragAndDropState.containerEvents.onPointerDown?.(e);
testEvents?.onPointerDown?.(e);
},
};
},
handle: ({ id }) => ({
onPointerDown: (e) => {
dragAndDropState.handleEvents.onPointerDown?.(e);
},
onKeyDown: (e) => {
dragAndDropState.handleEvents.onKeyDown?.(e);
},
...(process.env.NODE_ENV === 'test' &&
dragHandleTestEvents({
state: dragAndDropState,
id,
})),
}),
},
}),
);
dragAndDropContext.a11yContainer = modalsContainerRef.current;
return (
dragAndDropState.onDragStart(event)}
onDragEnd={(event) => dragAndDropState.onDragEnd(event)}
onDragCancel={() => dragAndDropState.onDragCancel()}
/>
);
}
export const NestedTableDragAndDropContext = observer(
_NestedTableDragAndDropContext,
);