import React, { useState, useCallback, ReactElement } from 'react';
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
import { FixedSizeList, areEqual } from 'react-window';
/*
* Ctrl + f dragHandleProps on PopupCourseBlock.tsx for example implementation of drag handle (two lines of code)
*
*/
/**
* Props for the List component.
*/
export interface ListProps {
draggableElements: any[]; // Will later define draggableElements based on what types
// of components are draggable.
itemHeight: number;
listHeight: number;
listWidth: number;
gap: number; // Impacts the spacing between items in the list
}
function initial(draggableElements: any[] = []) {
return draggableElements.map((element, index) => ({
id: `id:${index}`,
content: element as ReactElement,
}));
}
function reorder(list: { id: string, content: ReactElement }[], startIndex: number, endIndex: number) {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
}
function getStyle({ provided, style, isDragging, gap }) {
const combined = {
...style,
...provided.draggableProps.style
};
return combined;
}
function Item({ provided, item, style, isDragging, gap }) {
return (
{React.cloneElement(item.content, {dragHandleProps: provided.dragHandleProps})}
);
}
interface RowProps {
data: any, // DraggableElements[]; Need to define DraggableElements interface once those components are ready
index: number,
style: React.CSSProperties,
}
const Row: React.FC = React.memo(({ data: { items, gap }, index, style }) => {
const item = items[index];
const adjustedStyle = {
...style,
height: `calc(${style.height}px - ${gap}px)`, // Reduce the height by gap to accommodate the margin
marginBottom: `${gap}px` // Add gap as bottom margin
};
return (
{/* @ts-ignore */}
{provided => - }
);
}, areEqual);
/**
* `List` is a functional component that displays a course meeting.
*
* @example
*
*/
const List: React.FC = ( { draggableElements, itemHeight, listHeight, listWidth, gap=8 }: ListProps) => {
const [items, setItems] = useState(() => initial(draggableElements));
const onDragEnd = useCallback((result) => {
if (!result.destination) {
return;
}
if (result.source.index === result.destination.index) {
return;
}
const newItems = reorder(
items,
result.source.index,
result.destination.index
);
setItems(newItems as { id: string, content: React.ReactElement }[]);
}, [items]);
return (
{
let { style } = provided.draggableProps;
const transform = style?.transform;
if (snapshot.isDragging && transform) {
let [, y] = transform
.replace('translate(', '')
.replace(')', '')
.split(',')
.map((v) => parseInt(v, 10));
// const minTranslateY = -1 * rubric.source.index * itemHeight;
// const maxTranslateY = (items.length - rubric.source.index - 1) * itemHeight;
// if (y < minTranslateY) {
// }
// else if (y > maxTranslateY) {
// }
// else {
// }
style.transform = `translate(0px, ${y}px)`; // Apply constrained y value
}
return (
)}
}
>
{provided => (
{Row}
)}
);
};
export default List;