mirror of
https://github.com/community-scripts/Proxmox.git
synced 2026-04-05 09:04:01 -04:00
run prettier formatter overr whole project
This commit is contained in:
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
@@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/feature_request.md
vendored
7
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
@@ -10,7 +10,7 @@ First, install the dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
# or
|
||||
# or
|
||||
yarn install
|
||||
# or
|
||||
pnpm install
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
--ring: 224.3 76.3% 48%;
|
||||
}
|
||||
}
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
* {
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
@@ -67,4 +67,4 @@
|
||||
.glass {
|
||||
backdrop-filter: blur(15px) saturate(100%);
|
||||
-webkit-backdrop-filter: blur(15px) saturate(100%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,4 +90,4 @@ export default function RootLayout({
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ export default function LandingPage() {
|
||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-background [mask-image:radial-gradient(ellipse_at_center,transparent_0%,black)]"></div>
|
||||
<div className="flex animate-fade-up flex-col items-center justify-center">
|
||||
<Image src="/logo.png" alt="proxmox" width={150} height={150} />
|
||||
<h1 className="relative z-20 bg-gradient-to-b from-[#0080C4] to-[#004c75] bg-clip-text py-4 text-4xl font-bold text-transparent sm:text-5xl text-center sm:text-left">
|
||||
<h1 className="relative z-20 bg-gradient-to-b from-[#0080C4] to-[#004c75] bg-clip-text py-4 text-center text-4xl font-bold text-transparent sm:text-left sm:text-5xl">
|
||||
Proxmox VE Helper-Scripts
|
||||
</h1>
|
||||
<p className="bg-gradient-to-b from-neutral-200 to-neutral-500 bg-clip-text text-xl text-center sm:text-left">
|
||||
<p className="bg-gradient-to-b from-neutral-200 to-neutral-500 bg-clip-text text-center text-xl sm:text-left">
|
||||
Proxmox VE Scripts for{" "}
|
||||
<Typewriter
|
||||
words={[
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use client';
|
||||
"use client";
|
||||
import ScriptItem from "@/components/ScriptItem";
|
||||
import ScriptBrowser from "@/components/ScriptBrowser";
|
||||
import { pb } from "@/lib/pocketbase";
|
||||
@@ -14,73 +14,78 @@ export default function Page() {
|
||||
const [cacheExpiryTime, setCacheExpiryTime] = useState<Date | null>(null);
|
||||
const [isCacheEnabled, setIsCacheEnabled] = useState<boolean>(true);
|
||||
|
||||
const fetchLinks = useCallback(async (forceUpdate: boolean = false) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
let res;
|
||||
const fetchLinks = useCallback(
|
||||
async (forceUpdate: boolean = false) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
let res;
|
||||
|
||||
if (isCacheEnabled) {
|
||||
const cachedLinks = localStorage.getItem("scripts");
|
||||
const cacheTime = localStorage.getItem("cacheTime");
|
||||
if (isCacheEnabled) {
|
||||
const cachedLinks = localStorage.getItem("scripts");
|
||||
const cacheTime = localStorage.getItem("cacheTime");
|
||||
|
||||
if (!forceUpdate && cachedLinks && cacheTime) {
|
||||
const now = new Date().getTime();
|
||||
const timeDiff = Math.abs(now - Number(cacheTime));
|
||||
const diffInMinutes = Math.floor(timeDiff / 1000 / 60);
|
||||
if (!forceUpdate && cachedLinks && cacheTime) {
|
||||
const now = new Date().getTime();
|
||||
const timeDiff = Math.abs(now - Number(cacheTime));
|
||||
const diffInMinutes = Math.floor(timeDiff / 1000 / 60);
|
||||
|
||||
if (diffInMinutes < 30) {
|
||||
setLinks(JSON.parse(cachedLinks));
|
||||
setCacheExpiryTime(new Date(Number(cacheTime) + 1440 * 60 * 1000));
|
||||
setIsLoading(false);
|
||||
return;
|
||||
if (diffInMinutes < 30) {
|
||||
setLinks(JSON.parse(cachedLinks));
|
||||
setCacheExpiryTime(
|
||||
new Date(Number(cacheTime) + 1440 * 60 * 1000),
|
||||
);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
res = await (pb.collection("categories").getFullList({
|
||||
expand: "items",
|
||||
sort: "order",
|
||||
requestKey: "desktop",
|
||||
}) as Promise<Category[]>);
|
||||
if (res.length === 0) {
|
||||
throw new Error("Empty response");
|
||||
try {
|
||||
res = await (pb.collection("categories").getFullList({
|
||||
expand: "items",
|
||||
sort: "order",
|
||||
requestKey: "desktop",
|
||||
}) as Promise<Category[]>);
|
||||
if (res.length === 0) {
|
||||
throw new Error("Empty response");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching links from pb:", error);
|
||||
throw error;
|
||||
}
|
||||
res = res.sort((a: Category, b: Category) => {
|
||||
if (
|
||||
a.catagoryName === "Proxmox VE Tools" &&
|
||||
b.catagoryName !== "Proxmox VE Tools"
|
||||
) {
|
||||
return -1;
|
||||
} else if (
|
||||
a.catagoryName !== "Proxmox VE Tools" &&
|
||||
b.catagoryName === "Proxmox VE Tools"
|
||||
) {
|
||||
return 1;
|
||||
} else {
|
||||
return a.catagoryName.localeCompare(b.catagoryName);
|
||||
}
|
||||
});
|
||||
|
||||
if (isCacheEnabled) {
|
||||
localStorage.setItem("scripts", JSON.stringify(res));
|
||||
const newCacheTime = new Date().getTime();
|
||||
localStorage.setItem("cacheTime", String(newCacheTime));
|
||||
setCacheExpiryTime(new Date(newCacheTime + 1440 * 60 * 1000));
|
||||
}
|
||||
|
||||
setLinks(res as unknown as Category[]);
|
||||
} catch (error) {
|
||||
console.error("Error fetching links from pb:", error);
|
||||
throw error;
|
||||
console.error("Error fetching links:", error);
|
||||
setIsLoading(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
res = res.sort((a: Category, b: Category) => {
|
||||
if (
|
||||
a.catagoryName === "Proxmox VE Tools" &&
|
||||
b.catagoryName !== "Proxmox VE Tools"
|
||||
) {
|
||||
return -1;
|
||||
} else if (
|
||||
a.catagoryName !== "Proxmox VE Tools" &&
|
||||
b.catagoryName === "Proxmox VE Tools"
|
||||
) {
|
||||
return 1;
|
||||
} else {
|
||||
return a.catagoryName.localeCompare(b.catagoryName);
|
||||
}
|
||||
});
|
||||
|
||||
if (isCacheEnabled) {
|
||||
localStorage.setItem("scripts", JSON.stringify(res));
|
||||
const newCacheTime = new Date().getTime();
|
||||
localStorage.setItem("cacheTime", String(newCacheTime));
|
||||
setCacheExpiryTime(new Date(newCacheTime + 1440 * 60 * 1000));
|
||||
}
|
||||
|
||||
setLinks(res as unknown as Category[]);
|
||||
} catch (error) {
|
||||
console.error("Error fetching links:", error);
|
||||
setIsLoading(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [isCacheEnabled]);
|
||||
},
|
||||
[isCacheEnabled],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const cacheEnabled = localStorage.getItem("isCacheEnabled");
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const CacheControls: React.FC<CacheControlsProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<Separator className="w-screen"/>
|
||||
<Separator className="w-screen" />
|
||||
<div className="mt-6 grid animate-fade-up grid-cols-1 gap-4 px-4">
|
||||
<div className="text-center">
|
||||
{isCacheEnabled ? (
|
||||
|
||||
@@ -21,7 +21,9 @@ function LatestScripts({ items }: { items: Category[] }) {
|
||||
const latestScripts = useMemo(() => {
|
||||
if (!items) return [];
|
||||
const scripts = items.flatMap((category) => category.expand.items || []);
|
||||
return scripts.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime());
|
||||
return scripts.sort(
|
||||
(a, b) => new Date(b.created).getTime() - new Date(a.created).getTime(),
|
||||
);
|
||||
}, [items]);
|
||||
|
||||
const goToNextPage = () => {
|
||||
@@ -47,7 +49,7 @@ function LatestScripts({ items }: { items: Category[] }) {
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
{page > 1 && (
|
||||
<div
|
||||
className="cursor-pointer text-sm font-semibold p-2 select-none"
|
||||
className="cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
onClick={goToPreviousPage}
|
||||
>
|
||||
Previous
|
||||
@@ -56,7 +58,7 @@ function LatestScripts({ items }: { items: Category[] }) {
|
||||
{endIndex < latestScripts.length && (
|
||||
<div
|
||||
onClick={goToNextPage}
|
||||
className=" cursor-pointer text-sm font-semibold p-2 select-none"
|
||||
className=" cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
>
|
||||
{page === 1 ? "More.." : "Next"}
|
||||
</div>
|
||||
|
||||
@@ -45,11 +45,10 @@ export default function MostViewedScripts({ items }: { items: Category[] }) {
|
||||
<div className="">
|
||||
{mostViewedScripts.length > 0 && (
|
||||
<>
|
||||
<h2 className="text-lg font-semibold">
|
||||
Most Viewed Scripts
|
||||
</h2>
|
||||
<h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
||||
<p className="mb-2 text-sm text-muted-foreground">
|
||||
This data, unfortunately, is not directly influenced by interacting with the website. (yet)
|
||||
This data, unfortunately, is not directly influenced by interacting
|
||||
with the website. (yet)
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
@@ -93,9 +92,17 @@ export default function MostViewedScripts({ items }: { items: Category[] }) {
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<div className="p-2 flex justify-end gap-1">
|
||||
{page > 1 && <Button onClick={goToPreviousPage} variant="outline">Previous</Button>}
|
||||
{endIndex < mostViewedScripts.length && <Button onClick={goToNextPage} variant="outline">{page === 1 ? "More.." : "Next"}</Button>}
|
||||
<div className="flex justify-end gap-1 p-2">
|
||||
{page > 1 && (
|
||||
<Button onClick={goToPreviousPage} variant="outline">
|
||||
Previous
|
||||
</Button>
|
||||
)}
|
||||
{endIndex < mostViewedScripts.length && (
|
||||
<Button onClick={goToNextPage} variant="outline">
|
||||
{page === 1 ? "More.." : "Next"}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,7 +31,7 @@ import { Category } from "@/lib/types";
|
||||
import { Badge } from "./ui/badge";
|
||||
import { pb } from "@/lib/pocketbase";
|
||||
import clsx from "clsx";
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
function Navbar() {
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
@@ -39,7 +39,7 @@ function Navbar() {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [shouldFocusInput, setShouldFocusInput] = useState(false);
|
||||
const router = useRouter();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
@@ -119,15 +119,16 @@ function Navbar() {
|
||||
}`}
|
||||
>
|
||||
<div className="flex h-20 w-full max-w-7xl flex-row-reverse items-center justify-between sm:flex-row">
|
||||
<h2 className="cursor-pointer font-semibold" onClick={removeCookieAndRedirect}>
|
||||
<h2
|
||||
className="cursor-pointer font-semibold"
|
||||
onClick={removeCookieAndRedirect}
|
||||
>
|
||||
<a
|
||||
href="/"
|
||||
className=" flex flex-row-reverse items-center gap-2 sm:flex-row"
|
||||
>
|
||||
<Image height={18} width={18} alt="logo" src={logo} />
|
||||
<span>
|
||||
Proxmox VE Helper-Scripts
|
||||
</span>
|
||||
<span>Proxmox VE Helper-Scripts</span>
|
||||
</a>
|
||||
</h2>
|
||||
<div className="flex items-center sm:hidden">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { useState, useMemo } from "react";
|
||||
import { Category } from "@/lib/types";
|
||||
@@ -14,98 +14,103 @@ import { Button } from "./ui/button";
|
||||
|
||||
const ITEMS_PER_PAGE = 3;
|
||||
|
||||
export default function RecentlyUpdatedScripts({ items }: { items: Category[] }) {
|
||||
const [page, setPage] = useState(1);
|
||||
export default function RecentlyUpdatedScripts({
|
||||
items,
|
||||
}: {
|
||||
items: Category[];
|
||||
}) {
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
|
||||
const updatedScripts = useMemo(() => {
|
||||
if (!items) return [];
|
||||
const scripts = items.flatMap((category) => category.expand.items || []);
|
||||
const updatedScripts = scripts.map((script) => ({
|
||||
...script,
|
||||
updated: new Date(script.updated),
|
||||
}));
|
||||
return updatedScripts.sort((a, b) => b.updated.getTime() - a.updated.getTime());
|
||||
}, [items]);
|
||||
|
||||
const goToNextPage = () => {
|
||||
setPage((prevPage) => prevPage + 1);
|
||||
};
|
||||
|
||||
const goToPreviousPage = () => {
|
||||
setPage((prevPage) => prevPage - 1);
|
||||
};
|
||||
|
||||
const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
||||
const endIndex = page * ITEMS_PER_PAGE;
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
{updatedScripts.length > 0 && (
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h2 className="mb-2 text-lg font-semibold">
|
||||
Recently Updated Scripts
|
||||
</h2>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
{page > 1 && (
|
||||
<div
|
||||
className="cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
onClick={goToPreviousPage}
|
||||
>
|
||||
Previous
|
||||
</div>
|
||||
)}
|
||||
{endIndex < updatedScripts.length && (
|
||||
<div
|
||||
onClick={goToNextPage}
|
||||
className=" cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
>
|
||||
{page === 1 ? "More.." : "Next"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||
{updatedScripts.slice(startIndex, endIndex).map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
className=" min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-3">
|
||||
<div className="flex max-h-16 min-h-16 min-w-16 max-w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||
<Image src={item.logo} height={40} width={40} alt="" />
|
||||
</div>
|
||||
<h3 className="text-xl">
|
||||
{item.title} {item.item_type}
|
||||
</h3>
|
||||
</CardTitle>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Last updated: {item.updated.toISOString().split("T")[0]}
|
||||
</p>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="line-clamp-3 text-card-foreground">
|
||||
{item.description}
|
||||
</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter className="">
|
||||
<Button asChild variant="secondary">
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: item.title },
|
||||
}}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
View Script
|
||||
</Link>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
const updatedScripts = useMemo(() => {
|
||||
if (!items) return [];
|
||||
const scripts = items.flatMap((category) => category.expand.items || []);
|
||||
const updatedScripts = scripts.map((script) => ({
|
||||
...script,
|
||||
updated: new Date(script.updated),
|
||||
}));
|
||||
return updatedScripts.sort(
|
||||
(a, b) => b.updated.getTime() - a.updated.getTime(),
|
||||
);
|
||||
}, [items]);
|
||||
|
||||
const goToNextPage = () => {
|
||||
setPage((prevPage) => prevPage + 1);
|
||||
};
|
||||
|
||||
const goToPreviousPage = () => {
|
||||
setPage((prevPage) => prevPage - 1);
|
||||
};
|
||||
|
||||
const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
||||
const endIndex = page * ITEMS_PER_PAGE;
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
{updatedScripts.length > 0 && (
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h2 className="mb-2 text-lg font-semibold">
|
||||
Recently Updated Scripts
|
||||
</h2>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
{page > 1 && (
|
||||
<div
|
||||
className="cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
onClick={goToPreviousPage}
|
||||
>
|
||||
Previous
|
||||
</div>
|
||||
)}
|
||||
{endIndex < updatedScripts.length && (
|
||||
<div
|
||||
onClick={goToNextPage}
|
||||
className=" cursor-pointer select-none p-2 text-sm font-semibold"
|
||||
>
|
||||
{page === 1 ? "More.." : "Next"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||
{updatedScripts.slice(startIndex, endIndex).map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
className=" min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-3">
|
||||
<div className="flex max-h-16 min-h-16 min-w-16 max-w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||
<Image src={item.logo} height={40} width={40} alt="" />
|
||||
</div>
|
||||
<h3 className="text-xl">
|
||||
{item.title} {item.item_type}
|
||||
</h3>
|
||||
</CardTitle>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Last updated: {item.updated.toISOString().split("T")[0]}
|
||||
</p>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="line-clamp-3 text-card-foreground">
|
||||
{item.description}
|
||||
</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter className="">
|
||||
<Button asChild variant="secondary">
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: item.title },
|
||||
}}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
View Script
|
||||
</Link>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use client'
|
||||
"use client";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
@@ -9,7 +9,13 @@ import { Input } from "@/components/ui/input";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { X, EyeOff, Eye, Star } from "lucide-react";
|
||||
import React, { useState, useEffect, useRef, useMemo, useCallback } from "react";
|
||||
import React, {
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import { Category } from "@/lib/types";
|
||||
import { Badge } from "./ui/badge";
|
||||
import { Button } from "./ui/button";
|
||||
@@ -29,13 +35,13 @@ const ScriptBrowser = ({
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [expandedItems, setExpandedItems] = useState<string[]>([]);
|
||||
const [showLogos, setShowLogos] = useState<boolean>(() => {
|
||||
const saved = localStorage.getItem('showLogos');
|
||||
const saved = localStorage.getItem("showLogos");
|
||||
return saved ? JSON.parse(saved) : true;
|
||||
});
|
||||
const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({});
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('showLogos', JSON.stringify(showLogos));
|
||||
localStorage.setItem("showLogos", JSON.stringify(showLogos));
|
||||
}, [showLogos]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -84,8 +90,10 @@ const ScriptBrowser = ({
|
||||
|
||||
useEffect(() => {
|
||||
const matchingScripts = links
|
||||
.flatMap(category => category.expand.items)
|
||||
.filter(script => script.title.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
.flatMap((category) => category.expand.items)
|
||||
.filter((script) =>
|
||||
script.title.toLowerCase().includes(searchTerm.toLowerCase()),
|
||||
);
|
||||
|
||||
if (matchingScripts.length === 1) {
|
||||
const scriptTitle = matchingScripts[0].title;
|
||||
@@ -100,17 +108,22 @@ const ScriptBrowser = ({
|
||||
}
|
||||
}, [searchTerm, links, setSelectedScript]);
|
||||
|
||||
const handleSelected = useCallback((title: string) => {
|
||||
setSelectedScript(title);
|
||||
}, [setSelectedScript]);
|
||||
const handleSelected = useCallback(
|
||||
(title: string) => {
|
||||
setSelectedScript(title);
|
||||
},
|
||||
[setSelectedScript],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedScript) {
|
||||
const category = links.find(category =>
|
||||
category.expand.items.some(script => script.title === selectedScript)
|
||||
const category = links.find((category) =>
|
||||
category.expand.items.some((script) => script.title === selectedScript),
|
||||
);
|
||||
if (category) {
|
||||
setExpandedItems(prev => Array.from(new Set([...prev, category.catagoryName])));
|
||||
setExpandedItems((prev) =>
|
||||
Array.from(new Set([...prev, category.catagoryName])),
|
||||
);
|
||||
handleSelected(selectedScript);
|
||||
}
|
||||
}
|
||||
@@ -266,10 +279,8 @@ const ScriptBrowser = ({
|
||||
className={clsx(
|
||||
"ml-auto w-[37.69px] justify-center text-center",
|
||||
{
|
||||
"text-primary/75":
|
||||
script.item_type === "VM",
|
||||
"text-yellow-500/75":
|
||||
script.item_type === "LXC",
|
||||
"text-primary/75": script.item_type === "VM",
|
||||
"text-yellow-500/75": script.item_type === "LXC",
|
||||
"border-none": script.item_type === "",
|
||||
hidden: !["VM", "LXC", ""].includes(
|
||||
script.item_type,
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
'use client'
|
||||
"use client";
|
||||
import Image from "next/image";
|
||||
import { Suspense, useEffect, useState, useMemo } from "react";
|
||||
import { extractDate } from "@/lib/time";
|
||||
import { Button } from "./ui/button";
|
||||
import { toast } from "sonner";
|
||||
import { Clipboard, Info, X, Code, Globe, BookOpenText, ExternalLink, Copy } from "lucide-react";
|
||||
import {
|
||||
Clipboard,
|
||||
Info,
|
||||
X,
|
||||
Code,
|
||||
Globe,
|
||||
BookOpenText,
|
||||
ExternalLink,
|
||||
Copy,
|
||||
} from "lucide-react";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import Link from "next/link";
|
||||
import { Category, Script } from "@/lib/types";
|
||||
@@ -41,15 +50,24 @@ function ScriptItem({
|
||||
}
|
||||
}, [id, items, setSelectedScript, selectedScript]);
|
||||
|
||||
const pattern = useMemo(() => /(https:\/\/github\.com\/tteck\/Proxmox\/raw\/main\/(ct|misc|vm)\/([^\/]+)\.sh)/, []);
|
||||
const pattern = useMemo(
|
||||
() =>
|
||||
/(https:\/\/github\.com\/tteck\/Proxmox\/raw\/main\/(ct|misc|vm)\/([^\/]+)\.sh)/,
|
||||
[],
|
||||
);
|
||||
|
||||
const installCommand = useMemo(() => {
|
||||
if (item) {
|
||||
const keys = Object.keys(item);
|
||||
for (const key of keys) {
|
||||
const value = item[key as keyof Script];
|
||||
if (typeof value === "string" && pattern.test(value) &&
|
||||
!value.includes("alpine") && !value.includes("discussions") && !value.includes("2>/dev/null")) {
|
||||
if (
|
||||
typeof value === "string" &&
|
||||
pattern.test(value) &&
|
||||
!value.includes("alpine") &&
|
||||
!value.includes("discussions") &&
|
||||
!value.includes("2>/dev/null")
|
||||
) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -74,8 +92,6 @@ function ScriptItem({
|
||||
return null;
|
||||
}, [installCommand, pattern]);
|
||||
|
||||
|
||||
|
||||
const handleCopy = (type: string, value: any) => {
|
||||
navigator.clipboard.writeText(value);
|
||||
|
||||
|
||||
@@ -54,30 +54,28 @@ export function InfoToastWithButton({
|
||||
toastDuration,
|
||||
message,
|
||||
amountOfVisits,
|
||||
toastButtonMessage
|
||||
toastButtonMessage,
|
||||
}: WarningToastProps) {
|
||||
const toastShown = useRef(false);
|
||||
|
||||
const showWarningToast = useCallback(() => {
|
||||
toast.info(
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="lg text-black dark:text-white">
|
||||
{message}
|
||||
</p>
|
||||
<div>
|
||||
<Button className="text-white">
|
||||
<Link
|
||||
href="https://insigh.to/b/proxmox-ve-helper-scripts"
|
||||
data-umami-event="Give Feedback"
|
||||
target="_blank"
|
||||
>
|
||||
{toastButtonMessage}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>,
|
||||
{ duration: toastDuration },
|
||||
);
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="lg text-black dark:text-white">{message}</p>
|
||||
<div>
|
||||
<Button className="text-white">
|
||||
<Link
|
||||
href="https://insigh.to/b/proxmox-ve-helper-scripts"
|
||||
data-umami-event="Give Feedback"
|
||||
target="_blank"
|
||||
>
|
||||
{toastButtonMessage}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>,
|
||||
{ duration: toastDuration },
|
||||
);
|
||||
}, [message, toastDuration, toastButtonMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client"
|
||||
import * as React from "react"
|
||||
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
||||
import { ChevronDown } from "lucide-react"
|
||||
"use client";
|
||||
import * as React from "react";
|
||||
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Accordion = AccordionPrimitive.Root
|
||||
const Accordion = AccordionPrimitive.Root;
|
||||
|
||||
const AccordionItem = React.forwardRef<
|
||||
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||
@@ -52,6 +52,6 @@ const AccordionContent = React.forwardRef<
|
||||
</AccordionPrimitive.Content>
|
||||
));
|
||||
|
||||
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
||||
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
||||
|
||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-full border px-1.5 py-0.1 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
@@ -20,8 +20,8 @@ const badgeVariants = cva(
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
@@ -30,7 +30,7 @@ export interface BadgeProps
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
||||
export { Badge, badgeVariants };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import * as React from "react";
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
@@ -24,7 +24,7 @@ const buttonVariants = cva(
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
null: "py-1 px-3 rouded-xs"
|
||||
null: "py-1 px-3 rouded-xs",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
@@ -37,21 +37,21 @@ const buttonVariants = cva(
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
const Comp = asChild ? Slot : "button";
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
);
|
||||
},
|
||||
);
|
||||
Button.displayName = "Button";
|
||||
|
||||
export { Button, buttonVariants }
|
||||
export { Button, buttonVariants };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@@ -10,12 +10,12 @@ const Card = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border text-card-foreground shadow-sm",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
));
|
||||
Card.displayName = "Card";
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
));
|
||||
CardHeader.displayName = "CardHeader";
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
@@ -37,12 +37,12 @@ const CardTitle = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-2xl font-semibold leading-none tracking-tight",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
));
|
||||
CardTitle.displayName = "CardTitle";
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
@@ -50,19 +50,22 @@ const CardDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground sm:min-h-[60px] min-h-[40px]", className)}
|
||||
className={cn(
|
||||
"min-h-[40px] text-sm text-muted-foreground sm:min-h-[60px]",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
));
|
||||
CardDescription.displayName = "CardDescription";
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
));
|
||||
CardContent.displayName = "CardContent";
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@@ -70,10 +73,17 @@ const CardFooter = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("items-center p-6 pt-0 mt-auto", className)}
|
||||
className={cn("mt-auto items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
));
|
||||
CardFooter.displayName = "CardFooter";
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
import { X } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Dialog = DialogPrimitive.Root
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogClose = DialogPrimitive.Close
|
||||
const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
@@ -21,13 +21,13 @@ const DialogOverlay = React.forwardRef<
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
||||
));
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
@@ -38,8 +38,8 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-4xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-4xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -50,8 +50,8 @@ const DialogContent = React.forwardRef<
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
))
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
@@ -60,12 +60,12 @@ const DialogHeader = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogHeader.displayName = "DialogHeader"
|
||||
);
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
@@ -74,12 +74,12 @@ const DialogFooter = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogFooter.displayName = "DialogFooter"
|
||||
);
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
@@ -89,12 +89,12 @@ const DialogTitle = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg font-semibold leading-none tracking-tight",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
||||
));
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
@@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef<
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
@@ -119,4 +119,4 @@ export {
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
||||
import { Check, ChevronRight, Circle } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||
|
||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||
|
||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||
|
||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||
|
||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||
|
||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||
|
||||
const DropdownMenuSubTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
@@ -29,16 +29,16 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
||||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRight className="ml-auto h-4 w-4" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
))
|
||||
));
|
||||
DropdownMenuSubTrigger.displayName =
|
||||
DropdownMenuPrimitive.SubTrigger.displayName
|
||||
DropdownMenuPrimitive.SubTrigger.displayName;
|
||||
|
||||
const DropdownMenuSubContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||
@@ -47,14 +47,14 @@ const DropdownMenuSubContent = React.forwardRef<
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
DropdownMenuSubContent.displayName =
|
||||
DropdownMenuPrimitive.SubContent.displayName
|
||||
DropdownMenuPrimitive.SubContent.displayName;
|
||||
|
||||
const DropdownMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||
@@ -65,19 +65,19 @@ const DropdownMenuContent = React.forwardRef<
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
))
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
||||
));
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||
|
||||
const DropdownMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Item
|
||||
@@ -85,12 +85,12 @@ const DropdownMenuItem = React.forwardRef<
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
||||
));
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
||||
|
||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||
@@ -100,7 +100,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
@@ -112,9 +112,9 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
))
|
||||
));
|
||||
DropdownMenuCheckboxItem.displayName =
|
||||
DropdownMenuPrimitive.CheckboxItem.displayName
|
||||
DropdownMenuPrimitive.CheckboxItem.displayName;
|
||||
|
||||
const DropdownMenuRadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||
@@ -124,7 +124,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -135,13 +135,13 @@ const DropdownMenuRadioItem = React.forwardRef<
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
))
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
||||
));
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
||||
|
||||
const DropdownMenuLabel = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Label
|
||||
@@ -149,12 +149,12 @@ const DropdownMenuLabel = React.forwardRef<
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
||||
));
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
||||
|
||||
const DropdownMenuSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||
@@ -165,8 +165,8 @@ const DropdownMenuSeparator = React.forwardRef<
|
||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
||||
));
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
||||
|
||||
const DropdownMenuShortcut = ({
|
||||
className,
|
||||
@@ -177,9 +177,9 @@ const DropdownMenuShortcut = ({
|
||||
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
||||
);
|
||||
};
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
@@ -197,4 +197,4 @@ export {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuRadioGroup,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
@@ -12,14 +12,14 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Input.displayName = "Input"
|
||||
);
|
||||
},
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
|
||||
export { Input }
|
||||
export { Input };
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as React from "react"
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
||||
import { cva } from "class-variance-authority"
|
||||
import { ChevronDown } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const NavigationMenu = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
|
||||
@@ -13,15 +13,15 @@ const NavigationMenu = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative z-10 flex max-w-max flex-1 items-center justify-center",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<NavigationMenuViewport />
|
||||
</NavigationMenuPrimitive.Root>
|
||||
))
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
|
||||
));
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
|
||||
|
||||
const NavigationMenuList = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.List>,
|
||||
@@ -31,18 +31,18 @@ const NavigationMenuList = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"group flex flex-1 list-none items-center justify-center space-x-1",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
|
||||
));
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
|
||||
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
||||
|
||||
const navigationMenuTriggerStyle = cva(
|
||||
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
|
||||
)
|
||||
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50",
|
||||
);
|
||||
|
||||
const NavigationMenuTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
|
||||
@@ -59,8 +59,8 @@ const NavigationMenuTrigger = React.forwardRef<
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</NavigationMenuPrimitive.Trigger>
|
||||
))
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
|
||||
));
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
|
||||
|
||||
const NavigationMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
|
||||
@@ -69,15 +69,15 @@ const NavigationMenuContent = React.forwardRef<
|
||||
<NavigationMenuPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
|
||||
className
|
||||
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 left-0 top-0 w-full md:absolute md:w-auto ",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
|
||||
));
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
|
||||
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
||||
|
||||
const NavigationMenuViewport = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
||||
@@ -86,16 +86,16 @@ const NavigationMenuViewport = React.forwardRef<
|
||||
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
||||
<NavigationMenuPrimitive.Viewport
|
||||
className={cn(
|
||||
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
||||
className
|
||||
"origin-top-center data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg md:w-[var(--radix-navigation-menu-viewport-width)]",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
));
|
||||
NavigationMenuViewport.displayName =
|
||||
NavigationMenuPrimitive.Viewport.displayName
|
||||
NavigationMenuPrimitive.Viewport.displayName;
|
||||
|
||||
const NavigationMenuIndicator = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
|
||||
@@ -104,16 +104,16 @@ const NavigationMenuIndicator = React.forwardRef<
|
||||
<NavigationMenuPrimitive.Indicator
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
|
||||
className
|
||||
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
||||
</NavigationMenuPrimitive.Indicator>
|
||||
))
|
||||
));
|
||||
NavigationMenuIndicator.displayName =
|
||||
NavigationMenuPrimitive.Indicator.displayName
|
||||
NavigationMenuPrimitive.Indicator.displayName;
|
||||
|
||||
export {
|
||||
navigationMenuTriggerStyle,
|
||||
@@ -125,4 +125,4 @@ export {
|
||||
NavigationMenuLink,
|
||||
NavigationMenuIndicator,
|
||||
NavigationMenuViewport,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
import * as React from "react";
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
@@ -26,6 +26,6 @@ const Separator = React.forwardRef<
|
||||
/>
|
||||
),
|
||||
);
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
export { Separator }
|
||||
export { Separator };
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { X } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Sheet = SheetPrimitive.Root
|
||||
const Sheet = SheetPrimitive.Root;
|
||||
|
||||
const SheetTrigger = SheetPrimitive.Trigger
|
||||
const SheetTrigger = SheetPrimitive.Trigger;
|
||||
|
||||
const SheetClose = SheetPrimitive.Close
|
||||
const SheetClose = SheetPrimitive.Close;
|
||||
|
||||
const SheetPortal = SheetPrimitive.Portal
|
||||
const SheetPortal = SheetPrimitive.Portal;
|
||||
|
||||
const SheetOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||
@@ -21,14 +21,14 @@ const SheetOverlay = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
))
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
||||
));
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
||||
@@ -46,8 +46,8 @@ const sheetVariants = cva(
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
@@ -71,8 +71,8 @@ const SheetContent = React.forwardRef<
|
||||
</SheetPrimitive.Close>
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
))
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName
|
||||
));
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||
|
||||
const SheetHeader = ({
|
||||
className,
|
||||
@@ -81,12 +81,12 @@ const SheetHeader = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
SheetHeader.displayName = "SheetHeader"
|
||||
);
|
||||
SheetHeader.displayName = "SheetHeader";
|
||||
|
||||
const SheetFooter = ({
|
||||
className,
|
||||
@@ -95,12 +95,12 @@ const SheetFooter = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
SheetFooter.displayName = "SheetFooter"
|
||||
);
|
||||
SheetFooter.displayName = "SheetFooter";
|
||||
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
@@ -111,8 +111,8 @@ const SheetTitle = React.forwardRef<
|
||||
className={cn("text-lg font-semibold text-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName
|
||||
));
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||
@@ -123,8 +123,8 @@ const SheetDescription = React.forwardRef<
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName
|
||||
));
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
@@ -137,4 +137,4 @@ export {
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner } from "sonner"
|
||||
import { useTheme } from "next-themes";
|
||||
import { Toaster as Sonner } from "sonner";
|
||||
|
||||
type ToasterProps = React.ComponentProps<typeof Sonner>
|
||||
type ToasterProps = React.ComponentProps<typeof Sonner>;
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme()
|
||||
const { theme = "system" } = useTheme();
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
@@ -25,7 +25,7 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { Toaster }
|
||||
export { Toaster };
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||
import * as React from "react";
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Tabs = TabsPrimitive.Root
|
||||
const Tabs = TabsPrimitive.Root;
|
||||
|
||||
const TabsList = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.List>,
|
||||
@@ -15,12 +15,12 @@ const TabsList = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsList.displayName = TabsPrimitive.List.displayName
|
||||
));
|
||||
TabsList.displayName = TabsPrimitive.List.displayName;
|
||||
|
||||
const TabsTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
||||
@@ -30,12 +30,12 @@ const TabsTrigger = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
||||
));
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
||||
|
||||
const TabsContent = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Content>,
|
||||
@@ -45,11 +45,11 @@ const TabsContent = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsContent.displayName = TabsPrimitive.Content.displayName
|
||||
));
|
||||
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
||||
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import PocketBase from "pocketbase";
|
||||
|
||||
export const pb = new PocketBase(process.env.NEXT_PUBLIC_POCKETBASE_URL);
|
||||
export const pbBackup = new PocketBase(process.env.NEXT_PUBLIC_POCKETBASE_URL_BACKUP);
|
||||
export const pbBackup = new PocketBase(
|
||||
process.env.NEXT_PUBLIC_POCKETBASE_URL_BACKUP,
|
||||
);
|
||||
|
||||
export const getImageURL = (recordId: String, fileName: String) => {
|
||||
return `${process.env.NEXT_PUBLIC_POCKETBASE_URL}/${recordId}/${fileName}`;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,4 +5,3 @@ export function extractDate(dateString: string): string {
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export interface Category {
|
||||
expand: {
|
||||
items: Script[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type Scripts = {
|
||||
page: number;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import type { Config } from "tailwindcss"
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const svgToDataUri = require("mini-svg-data-uri");
|
||||
|
||||
const {
|
||||
default: flattenColorPalette,
|
||||
} = require("tailwindcss/lib/util/flattenColorPalette");
|
||||
|
||||
|
||||
const config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
'./pages/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./app/**/*.{ts,tsx}',
|
||||
'./src/**/*.{ts,tsx}',
|
||||
],
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
"./src/**/*.{ts,tsx}",
|
||||
],
|
||||
prefix: "",
|
||||
theme: {
|
||||
container: {
|
||||
@@ -122,33 +121,37 @@ const config = {
|
||||
{
|
||||
"bg-grid": (value: any) => ({
|
||||
backgroundImage: `url("${svgToDataUri(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="${value}"><path d="M0 .5H31.5V32"/></svg>`
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="${value}"><path d="M0 .5H31.5V32"/></svg>`,
|
||||
)}")`,
|
||||
}),
|
||||
"bg-grid-small": (value: any) => ({
|
||||
backgroundImage: `url("${svgToDataUri(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="8" height="8" fill="none" stroke="${value}"><path d="M0 .5H31.5V32"/></svg>`
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="8" height="8" fill="none" stroke="${value}"><path d="M0 .5H31.5V32"/></svg>`,
|
||||
)}")`,
|
||||
}),
|
||||
"bg-dot": (value: any) => ({
|
||||
backgroundImage: `url("${svgToDataUri(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16" fill="none"><circle fill="${value}" id="pattern-circle" cx="10" cy="10" r="1.6257413380501518"></circle></svg>`
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16" fill="none"><circle fill="${value}" id="pattern-circle" cx="10" cy="10" r="1.6257413380501518"></circle></svg>`,
|
||||
)}")`,
|
||||
}),
|
||||
},
|
||||
{ values: flattenColorPalette(theme("backgroundColor")), type: "color" }
|
||||
{
|
||||
values: flattenColorPalette(theme("backgroundColor")),
|
||||
type: "color",
|
||||
},
|
||||
);
|
||||
},
|
||||
],
|
||||
} satisfies Config
|
||||
} satisfies Config;
|
||||
|
||||
function addVariablesForColors({ addBase, theme }: any) {
|
||||
let allColors = flattenColorPalette(theme("colors"));
|
||||
let newVars = Object.fromEntries(
|
||||
Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
|
||||
Object.entries(allColors).map(([key, val]) => [`--${key}`, val]),
|
||||
);
|
||||
addBase({
|
||||
":root": newVars,
|
||||
});}
|
||||
});
|
||||
}
|
||||
|
||||
export default config
|
||||
export default config;
|
||||
|
||||
Reference in New Issue
Block a user