You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
59 lines
1.8 KiB
59 lines
1.8 KiB
import {Dispatch, ReactElement, RefObject, SetStateAction, useRef} from "react";
|
|
import Draggable from "react-draggable";
|
|
|
|
export interface RackInput {
|
|
id: string,
|
|
objects: [ReactElement[], Dispatch<SetStateAction<ReactElement[]>>],
|
|
canDetach: (ref: RefObject<HTMLDivElement>) => boolean,
|
|
onElementDetached: (ref: RefObject<HTMLDivElement>, el: ReactElement) => void,
|
|
}
|
|
|
|
interface RackItemInput {
|
|
item: ReactElement,
|
|
onTryDetach: (ref: RefObject<HTMLDivElement>, el: ReactElement) => void
|
|
}
|
|
|
|
/**
|
|
* A container of draggable objects
|
|
* */
|
|
export function Rack({id, objects, canDetach, onElementDetached}: RackInput) {
|
|
|
|
const [rackObjects, setRackObjects] = objects
|
|
|
|
return (
|
|
<div id={id} style={{
|
|
display: "flex"
|
|
}}>
|
|
{rackObjects.map(element => (
|
|
<RackItem key={element.key}
|
|
item={element}
|
|
onTryDetach={(ref, element) => {
|
|
if (!canDetach(ref))
|
|
return
|
|
|
|
setRackObjects(objects => {
|
|
const index = objects.findIndex(o => o.key === element.key)
|
|
return objects.toSpliced(index, 1);
|
|
})
|
|
|
|
onElementDetached(ref, element)
|
|
}}/>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function RackItem({item, onTryDetach}: RackItemInput) {
|
|
const divRef = useRef<HTMLDivElement>(null);
|
|
|
|
return (
|
|
<Draggable
|
|
position={{x: 0, y: 0}}
|
|
nodeRef={divRef}
|
|
onStop={() => onTryDetach(divRef, item)}>
|
|
<div ref={divRef}>
|
|
{item}
|
|
</div>
|
|
</Draggable>
|
|
)
|
|
} |