"use client";
import React, { useEffect } from "react";
import {
useMotionValue,
Reorder,
useDragControls,
motion,
animate,
DragControls,
} from "framer-motion";
import { GripVertical } from "lucide-react";
export interface DragItem {
id: number;
title: string;
subtitle: string;
date: string;
link?: string;
}
interface DragOrderListProps {
items: DragItem[];
onReorder?: (items: DragItem[]) => void;
}
export function DragOrderList({ items, onReorder }: DragOrderListProps) {
const [list, setList] = React.useState(items);
useEffect(() => {
if (onReorder) onReorder(list);
}, [list]);
return (
{list.map((item) => (
))}
);
}
function DragOrderItem({ item }: { item: DragItem }) {
const y = useMotionValue(0);
const boxShadow = useRaisedShadow(y);
const dragControls = useDragControls();
return (
{item.title}
{item.subtitle}
{item.date}
{item.link && (
More Info
)}
);
}
function ReorderHandle({ dragControls }: { dragControls: DragControls }) {
return (
{
e.preventDefault();
dragControls.start(e);
}}
className="cursor-grab active:cursor-grabbing p-2 text-muted-foreground"
>
);
}
const inactiveShadow = "0px 0px 0px rgba(0,0,0,0.8)";
function useRaisedShadow(value: ReturnType) {
const boxShadow = useMotionValue(inactiveShadow);
useEffect(() => {
let isActive = false;
value.onChange((latest) => {
const wasActive = isActive;
if (latest !== 0) {
isActive = true;
if (isActive !== wasActive) {
animate(boxShadow, "5px 5px 15px rgba(0,0,0,0.15)");
}
} else {
isActive = false;
if (isActive !== wasActive) {
animate(boxShadow, inactiveShadow);
}
}
});
}, [value]);
return boxShadow;
}