84 lines
2.4 KiB
TypeScript
84 lines
2.4 KiB
TypeScript
import fractionalIndex from "fractional-index";
|
|
import * as React from "react";
|
|
import { ConnectDragSource, useDrag, useDrop } from "react-dnd";
|
|
import { getEmptyImage } from "react-dnd-html5-backend";
|
|
import Star from "~/models/Star";
|
|
import useStores from "~/hooks/useStores";
|
|
import { DragObject } from "./SidebarLink";
|
|
import { useStarLabelAndIcon } from "./useStarLabelAndIcon";
|
|
|
|
/**
|
|
* Hook for shared logic that allows dragging a Starred item
|
|
*
|
|
* @param star The related Star model.
|
|
*/
|
|
export function useDragStar(
|
|
star: Star
|
|
): [{ isDragging: boolean }, ConnectDragSource] {
|
|
const id = star.id;
|
|
const { label: title, icon } = useStarLabelAndIcon(star);
|
|
const [{ isDragging }, draggableRef, preview] = useDrag({
|
|
type: "star",
|
|
item: () => ({ id, title, icon }),
|
|
collect: (monitor) => ({
|
|
isDragging: !!monitor.isDragging(),
|
|
}),
|
|
canDrag: () => true,
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
preview(getEmptyImage(), { captureDraggingState: true });
|
|
}, [preview]);
|
|
|
|
return [{ isDragging }, draggableRef];
|
|
}
|
|
|
|
/**
|
|
* Hook for shared logic that allows dropping documents and collections to create a star
|
|
*
|
|
* @param getIndex A function to get the index of the current item where the star should be inserted.
|
|
*/
|
|
export function useDropToCreateStar(getIndex?: () => string) {
|
|
const { documents, stars, collections } = useStores();
|
|
|
|
return useDrop({
|
|
accept: ["document", "collection"],
|
|
drop: async (item: DragObject) => {
|
|
const model = documents.get(item.id) ?? collections?.get(item.id);
|
|
await model?.star(
|
|
getIndex?.() ?? fractionalIndex(null, stars.orderedData[0].index)
|
|
);
|
|
},
|
|
collect: (monitor) => ({
|
|
isOverCursor: !!monitor.isOver(),
|
|
isDragging: ["document", "collection"].includes(
|
|
String(monitor.getItemType())
|
|
),
|
|
}),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Hook for shared logic that allows dropping stars to reorder
|
|
*
|
|
* @param getIndex A function to get the index of the current item where the star should be inserted.
|
|
*/
|
|
export function useDropToReorderStar(getIndex?: () => string) {
|
|
const { stars } = useStores();
|
|
|
|
return useDrop({
|
|
accept: "star",
|
|
drop: async (item: DragObject) => {
|
|
const star = stars.get(item.id);
|
|
void star?.save({
|
|
index:
|
|
getIndex?.() ?? fractionalIndex(null, stars.orderedData[0].index),
|
|
});
|
|
},
|
|
collect: (monitor) => ({
|
|
isOverCursor: !!monitor.isOver(),
|
|
isDragging: monitor.getItemType() === "star",
|
|
}),
|
|
});
|
|
}
|