Skip to content

Commit

Permalink
Nick:
Browse files Browse the repository at this point in the history
  • Loading branch information
nickscamara committed May 26, 2024
1 parent 8e10c1c commit 375a882
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 43 deletions.
20 changes: 20 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
"lucide": "^0.379.0",
"lucide-react": "^0.379.0",
"next": "14.2.3",
"next-themes": "^0.3.0",
"react": "^18",
"react-dom": "^18",
"sonner": "^1.4.41",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7"
},
Expand Down
3 changes: 2 additions & 1 deletion src/app/embed/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { allThemes, Theme } from '@/lib/theme';
export default function EmbedPage() {
const searchParams = useSearchParams();
const padding = searchParams?.get('padding') || '64';
const theme = searchParams?.get('theme') || JSON.stringify(allThemes['sunset']);
const theme = searchParams?.get('theme') || JSON.stringify(allThemes['firecrawl']);
const background = searchParams?.get('background') || 'false';

const [parsedPadding, setParsedPadding] = useState(0);
Expand Down Expand Up @@ -41,6 +41,7 @@ export default function EmbedPage() {
padding={parsedPadding}
theme={parsedTheme}
background={parsedBackground}
darkMode={false}
chartRef={chartRef}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { Toaster } from "sonner";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -17,6 +18,7 @@ export default function RootLayout({
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Toaster />
</html>
);
}
27 changes: 22 additions & 5 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import { Theme, allThemes } from "@/lib/theme";
import html2canvas from "html2canvas";

/**
* The issue in the original code is that the `allThemes["sunset"]` object does not match the expected `Theme` type.
* To fix this, we need to ensure that the `allThemes["sunset"]` object conforms to the `Theme` type.
* The issue in the original code is that the `allThemes["firecrawl"]` object does not match the expected `Theme` type.
* To fix this, we need to ensure that the `allThemes["firecrawl"]` object conforms to the `Theme` type.
*/

export default function Home() {
const [padding, setPadding] = useState(64);
const [theme, setTheme] = useState<Theme>(() => allThemes["sunset"] as Theme);
const [theme, setTheme] = useState<Theme>(() => allThemes["firecrawl"] as Theme);

const [background, setBackground] = useState(true);
const [darkMode, setDarkMode] = useState(false);
const [copyAsImage, setCopyAsImage] = useState(false);

const chartRef = useRef<HTMLDivElement>(null);

const handleExport = async () => {
const handleExport = async (copyAsImage: boolean = false) => {
if (chartRef.current) {
const canvas = await html2canvas(chartRef.current, {
useCORS: true,
Expand All @@ -41,10 +43,22 @@ export default function Home() {
});
},
});
console.log("coco");
const link = document.createElement("a");
link.href = canvas.toDataURL("image/png");
link.download = "chart.png";
document.body.appendChild(link); // Append the link to the body
link.click();
document.body.removeChild(link); // Remove the link after download
if (copyAsImage) {
console.log("copying as image");
canvas.toBlob((blob) => {
if (blob) {
const item = new ClipboardItem({ "image/png": blob });
navigator.clipboard.write([item]);
}
});
}
}
};

Expand All @@ -58,7 +72,7 @@ export default function Home() {
}}
>
<main className="relative flex h-[95vh] flex-col items-center justify-center bg-transparent bg-opacity-80">
<Graph padding={padding} theme={theme} background={background} chartRef={chartRef} />
<Graph padding={padding} theme={theme} background={background} darkMode={darkMode} chartRef={chartRef} />

<Menu
padding={padding}
Expand All @@ -68,6 +82,9 @@ export default function Home() {
handleExport={handleExport}
background={background}
setBackground={setBackground}
darkMode={darkMode}
setDarkMode={setDarkMode}
handleExportCopyAsImage={() => handleExport(true)}
/>
<div className="absolute bottom-0 left-0 right-0 p-4 text-white text-center font-light">
Made by{" "}
Expand Down
37 changes: 29 additions & 8 deletions src/components/graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

import { Theme } from "@/lib/theme";
import { AreaChart, Color } from "@tremor/react";
import { useState, useRef } from "react";
import { useState, useRef, useEffect } from "react";
import html2canvas from "html2canvas";

export default function Graph({
padding,
theme,
background,
darkMode,
chartRef,
}: {
padding: number;
theme: Theme;
background: boolean;
darkMode: boolean;
chartRef: React.RefObject<HTMLDivElement>;
}) {
const mockchartdata = [
Expand Down Expand Up @@ -87,8 +89,6 @@ export default function Graph({
const maxStars = Math.max(...mockchartdata.map((data) => data.Stars));
const [maxValue, setMaxValue] = useState(maxStars);



return (
<div
className={`${!background ? "border border-gray-300/25" : ""} rounded-lg`}
Expand All @@ -101,11 +101,32 @@ export default function Graph({
ref={chartRef}
>
<div style={{ padding: `${padding}px` }} className="transition-all">
<div className="bg-white bg-opacity-90 rounded-lg p-4">
<div className="flex space-x-2">
<div className="w-3 h-3 bg-gray-300 rounded-full"></div>
<div className="w-3 h-3 bg-gray-300 rounded-full"></div>
<div className="w-3 h-3 bg-gray-300 rounded-full"></div>
<div
className={`rounded-lg p-4 ${
darkMode ? "bg-black bg-opacity-90" : "bg-white bg-opacity-90"
}`}
>
<div className="w-full flex flex-col items-center mb-4">
<div className="w-full flex space-x-2 mb-2">
<div
className={`w-3 h-3 ${
darkMode ? "bg-gray-700" : "bg-gray-300"
} rounded-full dark-mode-circle`}
></div>
<div
className={`w-3 h-3 ${
darkMode ? "bg-gray-700" : "bg-gray-300"
} rounded-full dark-mode-circle`}
></div>
<div
className={`w-3 h-3 ${
darkMode ? "bg-gray-700" : "bg-gray-300"
} rounded-full dark-mode-circle`}
></div>
</div>
<div className="w-full text-center">
<div contentEditable className="focus:outline-none text-sm text-zinc-500 focus:ring-2 mx-2 rounded-md focus:ring-zinc-300">Your awesome graph</div>
</div>
</div>
<div className="pt-6 text-xs">
<AreaChart
Expand Down
81 changes: 64 additions & 17 deletions src/components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ import {
import { Theme, allThemes } from "@/lib/theme";
import { Button } from "./ui/button";
import { Switch } from "./ui/switch";
import { Code, Download, Plus } from "lucide-react";
import {
ArrowUp,
ArrowUp01,
ChevronUp,
Code,
Copy,
Download,
Image,
MoveUpIcon,
Plus,
} from "lucide-react";
import { SelectIcon } from "@radix-ui/react-select";
import { toast } from "sonner";

export default function Menu({
padding,
Expand All @@ -18,6 +30,9 @@ export default function Menu({
setTheme,
background,
setBackground,
darkMode,
setDarkMode,
handleExportCopyAsImage,
handleExport,
}: {
padding: number;
Expand All @@ -26,18 +41,25 @@ export default function Menu({
setTheme: (theme: Theme) => void;
background: boolean;
setBackground: (background: boolean) => void;
darkMode: boolean;
setDarkMode: (darkMode: boolean) => void;
handleExportCopyAsImage: () => void;
handleExport: () => void;
}) {
const generateEmbedCode = () => {
const embedCode = `
<iframe
src="${window.location.origin}/embed?padding=${padding}&theme=${encodeURIComponent(JSON.stringify(theme))}&background=${background}"
src="${
window.location.origin
}/embed?padding=${padding}&theme=${encodeURIComponent(
JSON.stringify(theme)
)}&background=${background}"
style="border:none;width:100%;height:400px;"
allowfullscreen
></iframe>
`;
navigator.clipboard.writeText(embedCode).then(() => {
alert("Embed code copied to clipboard!");
toast("Embed code copied to clipboard!");
});
};
return (
Expand Down Expand Up @@ -93,6 +115,14 @@ export default function Menu({
onCheckedChange={(checked) => setBackground(checked)}
/>
</div>
{/* <div className="flex h-full flex-col items-start justify-start pb-2">
<span className="text-zinc-700 text-sm">Dark Mode</span>
<Switch
className="mt-2 scale-90 -ml-[2px]"
checked={darkMode}
onCheckedChange={(checked) => setDarkMode(checked)}
/>
</div> */}
<div className="flex flex-col items-start justify-start">
<span className="text-zinc-700 text-sm">Padding</span>
<Select
Expand All @@ -110,20 +140,37 @@ export default function Menu({
</SelectContent>
</Select>
</div>
<Button
onClick={handleExport}
className="bg-orange-400/25 text-orange-400 px-3 py-2 rounded hover:bg-red-400/10"
>
<Download size={16} className="mr-1" />
Export
</Button>
<Button
onClick={generateEmbedCode}
className="bg-orange-400/25 text-orange-400 px-3 py-2 rounded hover:bg-red-400/10"
>
<Code size={16} className="mr-1" />
Embed
</Button>
<div className="flex items-center gap-2">
<Button
onClick={handleExport}
className="bg-orange-400/25 text-orange-400 px-3 py-2 rounded hover:bg-red-400/10"
>
<Download size={16} className="mr-1" />
Export
</Button>
<Select >
<SelectTrigger
noIcon={true}
className="border-0 w-[32px] p-0 bg-orange-400/25 text-orange-400"
>
<ChevronUp size={18} className=" mx-auto" />
</SelectTrigger>
<SelectContent className="w-fit" side="top">
<SelectItem onClick={generateEmbedCode} value="embed">
<div className="flex items-center justify-start gap-2">
<Code size={16} className="-ml-4 mr-1" />
Embed
</div>
</SelectItem>
<SelectItem onClick={handleExportCopyAsImage} value="copy">
<div className="flex items-center justify-start gap-2">
<Image size={16} className="-ml-4 mr-1" />
Copy PNG
</div>
</SelectItem>
</SelectContent>
</Select>
</div>
</div>

{/* <div className="flex items-center rounded-lg bg-white border border-zinc-500/25 shadow-xl px-4 py-[26px] gap-4">
Expand Down
6 changes: 3 additions & 3 deletions src/components/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const SelectValue = SelectPrimitive.Value

const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>, 'noIcon'> & { noIcon?: boolean }
>(({ className, children, noIcon, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
Expand All @@ -26,7 +26,7 @@ const SelectTrigger = React.forwardRef<
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
{noIcon ? <></> : <ChevronDown className="h-4 w-4 opacity-50" />}
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
Expand Down
Loading

0 comments on commit 375a882

Please sign in to comment.