145 lines
4.8 KiB
TypeScript
145 lines
4.8 KiB
TypeScript
"use client";
|
|
|
|
import { useCopyFeedback } from "./shared";
|
|
import { buildHighlightUrl } from "@/lib/text-highlight";
|
|
import { createPortal } from "react-dom";
|
|
import { X, MessageSquare, ExternalLink } from "lucide-react";
|
|
import {
|
|
Drawer,
|
|
DrawerClose,
|
|
DrawerContent,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
} from "@/components/ui/drawer";
|
|
|
|
export function ShareModal({
|
|
open,
|
|
onClose,
|
|
selectedText,
|
|
isMobile,
|
|
}: {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
selectedText: string;
|
|
isMobile: boolean;
|
|
}) {
|
|
const { copied, copy } = useCopyFeedback();
|
|
|
|
const shareOptions = [
|
|
{
|
|
key: "feed",
|
|
label: "Share to Feed",
|
|
icon: <MessageSquare className="size-4" />,
|
|
description: "Post this quote to your feed",
|
|
onClick: () => {
|
|
// TODO: Implement share to feed
|
|
onClose();
|
|
},
|
|
},
|
|
{
|
|
key: "link",
|
|
label: "Share Link",
|
|
icon: <ExternalLink className="size-4" />,
|
|
description: "Copy a shareable link",
|
|
onClick: () => {
|
|
copy(buildHighlightUrl(selectedText));
|
|
},
|
|
},
|
|
];
|
|
|
|
if (isMobile) {
|
|
return (
|
|
<Drawer open={open} onOpenChange={(o) => !o && onClose()}>
|
|
<DrawerContent className="bg-black dark:bg-[#1a1a1a] border-white/10">
|
|
<DrawerHeader className="text-left border-b border-white/10 pb-4">
|
|
<DrawerTitle className="text-white">Share</DrawerTitle>
|
|
{selectedText && (
|
|
<p className="text-sm text-white/50 mt-1 line-clamp-2">
|
|
“{selectedText.slice(0, 120)}
|
|
{selectedText.length > 120 ? "…" : ""}”
|
|
</p>
|
|
)}
|
|
</DrawerHeader>
|
|
<div className="p-4 space-y-1">
|
|
{shareOptions.map((opt) => (
|
|
<button
|
|
key={opt.key}
|
|
onClick={opt.onClick}
|
|
className="flex items-center gap-3 w-full px-3 py-3 rounded-lg text-left hover:bg-white/10 transition-colors"
|
|
>
|
|
<div className="flex items-center justify-center size-9 rounded-lg bg-amber-400/15 text-amber-400">
|
|
{opt.icon}
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-white/90">
|
|
{opt.key === "link" && copied ? "Link Copied!" : opt.label}
|
|
</p>
|
|
<p className="text-xs text-white/50">{opt.description}</p>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
<div className="p-4 pt-0">
|
|
<DrawerClose asChild>
|
|
<button className="w-full py-2.5 rounded-lg border border-white/15 text-sm font-medium text-white/60 hover:bg-white/10 transition-colors">
|
|
Cancel
|
|
</button>
|
|
</DrawerClose>
|
|
</div>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
}
|
|
|
|
// Desktop modal
|
|
if (!open) return null;
|
|
|
|
return createPortal(
|
|
<>
|
|
<div
|
|
className="fixed inset-0 z-100 bg-black/60 animate-in fade-in-0"
|
|
onClick={onClose}
|
|
/>
|
|
<div className="fixed left-1/2 top-1/2 z-101 w-full max-w-sm -translate-x-1/2 -translate-y-1/2 rounded-xl border border-white/10 bg-black shadow-2xl animate-in fade-in-0 zoom-in-95 dark:bg-[#1a1a1a] dark:border-white/15">
|
|
<div className="flex items-center justify-between px-5 py-4 border-b border-white/10">
|
|
<h2 className="text-lg font-semibold text-white">Share</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="flex items-center justify-center size-8 rounded-lg text-white/50 hover:bg-white/10 hover:text-white transition-colors"
|
|
>
|
|
<X className="size-4" />
|
|
</button>
|
|
</div>
|
|
{selectedText && (
|
|
<div className="px-5 py-3 border-b border-white/10">
|
|
<p className="text-sm text-white/50 line-clamp-2">
|
|
“{selectedText.slice(0, 120)}
|
|
{selectedText.length > 120 ? "…" : ""}”
|
|
</p>
|
|
</div>
|
|
)}
|
|
<div className="p-3 space-y-1">
|
|
{shareOptions.map((opt) => (
|
|
<button
|
|
key={opt.key}
|
|
onClick={opt.onClick}
|
|
className="flex items-center gap-3 w-full px-3 py-3 rounded-lg text-left hover:bg-white/10 transition-colors"
|
|
>
|
|
<div className="flex items-center justify-center size-9 rounded-lg bg-amber-400/15 text-amber-400">
|
|
{opt.icon}
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-white/90">
|
|
{opt.key === "link" && copied ? "Link Copied!" : opt.label}
|
|
</p>
|
|
<p className="text-xs text-white/50">{opt.description}</p>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</>,
|
|
document.body,
|
|
);
|
|
}
|