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.
Application-Web/front/components/Rack.tsx

58 lines
1.7 KiB

import {ReactElement, useRef} from "react";
import Draggable from "react-draggable";
export interface RackProps<E> {
id: string,
objects: E[],
onChange: (objects: E[]) => void,
canDetach: (ref: HTMLDivElement) => boolean,
onElementDetached: (ref: HTMLDivElement, el: E) => void,
render: (e: E) => ReactElement,
}
interface RackItemProps<E> {
item: E,
onTryDetach: (ref: HTMLDivElement, el: E) => void,
render: (e: E) => ReactElement,
}
/**
* A container of draggable objects
* */
export function Rack<E>({id, objects, onChange, canDetach, onElementDetached, render}: RackProps<E>) {
return (
<div id={id} style={{
display: "flex"
}}>
{objects.map(element => (
<RackItem key={element.key}
item={element}
render={render}
onTryDetach={(ref, element) => {
if (!canDetach(ref))
return
const index = objects.findIndex(o => o.key === element.key)
onChange(objects.toSpliced(index, 1))
onElementDetached(ref, element)
}}/>
))}
</div>
)
}
function RackItem<E>({item, onTryDetach, render}: RackItemProps<E>) {
const divRef = useRef<HTMLDivElement>(null);
return (
<Draggable
position={{x: 0, y: 0}}
nodeRef={divRef}
onStop={() => onTryDetach(divRef.current!, item)}>
<div ref={divRef}>
{render(item)}
</div>
</Draggable>
)
}