aboutsummaryrefslogtreecommitdiff
path: root/apps/web/components/canvas/sidepanelcard.tsx
blob: 36014e4c77d68acf7f7bf84ad5ec904326a4b9c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { GlobeAltIcon } from "@heroicons/react/16/solid";
import { TwitterIcon, TypeIcon } from "lucide-react";
import { useState } from "react";
import { motion } from "framer-motion";
import useMeasure from "react-use-measure";

type CardType = string;

export default function Card({
	type,
	title,
	content,
	source,
}: {
	type: CardType;
	title: string;
	content: string;
	source?: string;
}) {
	const [ref, bounds] = useMeasure();
	const [isDragging, setIsDragging] = useState(false);

	const handleDragStart = (
		event: React.DragEvent<HTMLAnchorElement | HTMLDivElement>,
		dragSource: "icon" | "link" | "parent",
	) => {
		setIsDragging(true);

		switch (dragSource) {
			case "icon":
				event.dataTransfer.setData(
					"application/json",
					JSON.stringify({
						type,
						title,
						content,
						text: true,
					}),
				);
				break;
			case "link":
				event.dataTransfer.setData("text/plain", source || "");
				break;
			case "parent":
				event.dataTransfer.setData(
					"application/json",
					JSON.stringify({
						type,
						title,
						content,
						text: false,
					}),
				);
				break;
		}
	};

	const handleDragEnd = () => {
		setIsDragging(false);
	};

	return (
		<motion.div animate={{ height: bounds.height }}>
			<div
				draggable
				onDragEnd={handleDragEnd}
				onDragStart={(e) => handleDragStart(e, "parent")}
				className={`rounded-lg hover:scale-[1.02] group cursor-grab scale-[0.98] select-none transition-all border-[#232c2f] hover:bg-[#232c32] ${
					isDragging ? "border-blue-600 border-dashed border-2" : ""
				}`}
			>
				<div ref={ref} className="flex gap-4 px-3 py-2 items-center">
					<a
						href={source}
						className={`${source && "cursor-pointer"}`}
						draggable
						onDragStart={(e) => {
							e.stopPropagation();
							handleDragStart(e, "icon");
						}}
					>
						<Icon type={type} />
					</a>
					<div>
						<h2>{title}</h2>
						<p className="group-hover:line-clamp-[12] transition-all line-clamp-3 text-gray-200">
							{content}
						</p>
						<a
							draggable
							href={source}
							className="line-clamp-[1] text-blue-500"
							onDragStart={(e) => {
								e.stopPropagation();
								handleDragStart(e, "link");
							}}
						>
							{source}
						</a>
					</div>
				</div>
			</div>
		</motion.div>
	);
}

function Icon({ type }: { type: CardType }) {
	return type === "note" ? (
		<TypeIcon />
	) : type === "page" ? (
		<GlobeAltIcon className="h-9 w-5" />
	) : (
		<TwitterIcon />
	);
}