upgrade the project

This commit is contained in:
PrinOrange
2024-04-03 22:08:27 +08:00
parent a615511139
commit ea3597d62f
313 changed files with 10677 additions and 7069 deletions

View File

@@ -1,33 +1,34 @@
import { SocialIcons } from "@/components/utils/SocialIcons";
import { Config } from "@/data/config";
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
export const HomeCover = () => {
return (
<>
<div
className="mb-20 mt-5 flex w-full justify-center rounded-xl"
style={{
aspectRatio: "4/1",
background: `url(${Config.PageCovers.websiteCoverURL})`,
backgroundSize: "cover",
}}
>
<img
className="relative top-1/2 my-auto h-24 w-24 rounded-full shadow-2xl md:h-32 md:w-32"
alt={Config.Nickname}
src={Config.AvatarURL}
/>
<div className="w-full">
<div
className="mb-20 mt-5 flex w-full justify-center rounded-xl"
style={{
aspectRatio: "4/1",
background: `url(${Config.PageCovers.websiteCoverURL})`,
backgroundSize: "cover",
}}
>
<img
alt={Config.Nickname}
className="relative top-1/2 my-auto h-24 w-24 rounded-full shadow-2xl md:h-32 md:w-32"
src={Config.AvatarURL}
/>
</div>
</div>
<div className={`${fontFangZhengXiaoBiaoSongCN.className} my-8 text-center text-4xl font-bold`}>
{Config.Nickname}
</div>
<SocialIcons />
<div className={`font-fang-zheng-xiao-biao-song my-8 text-center text-4xl font-bold`}>{Config.Nickname}</div>
{Config.Sentence && (
<div className="my-8 flex justify-center">
<p className={`${fontSourceSerifScreenCN.className} text-lg`}>{Config.Sentence}</p>
<div className="my-5 flex justify-center">
<p className={`font-source-serif-screen text-lg`}>{Config.Sentence}</p>
</div>
)}
<div className="my-8">
<SocialIcons />
</div>
</>
);
};

View File

@@ -0,0 +1,13 @@
const Blockquote = (props: JSX.IntrinsicElements["blockquote"]) => {
return (
<blockquote
className={
"not-prose scroll-mt-20 my-5 px-5 py-4 bg-gray-100 dark:bg-gray-800 dark:border-gray-700 border-gray-300 border-l-4"
}
>
{props.children}
</blockquote>
);
};
export default Blockquote;

View File

@@ -1,9 +1,9 @@
import { fontFangZhengXiaoBiaoSongCN } from "@/styles/font";
export const H2 = (props: JSX.IntrinsicElements["h2"]) => {
const H2 = (props: JSX.IntrinsicElements["h2"]) => {
return (
<h2 className={`${fontFangZhengXiaoBiaoSongCN.className} mt-4 mb-2 scroll-mt-20`} id={props.id}>
<h2 className={`font-fang-zheng-xiao-biao-song scroll-mt-20`} id={props.id}>
{props.children}
</h2>
);
};
export default H2;

View File

@@ -1,4 +1,7 @@
import { useRef, useState } from "react";
import { FaCheck } from "react-icons/fa";
import { IoCopyOutline } from "react-icons/io5";
import { Button } from "../ui/button";
const PreWrapper = ({ children }: { children: JSX.Element }) => {
const textInput = useRef(null);
@@ -16,51 +19,23 @@ const PreWrapper = ({ children }: { children: JSX.Element }) => {
setCopied(true);
//@ts-ignore
textInput.current && navigator.clipboard.writeText(textInput.current.textContent);
setTimeout(() => {
setCopied(false);
}, 2000);
};
return (
<div ref={textInput} onMouseEnter={onEnter} onMouseLeave={onExit} className="relative flat-scrollbar-normal">
<div className="relative flat-scrollbar-normal" onMouseLeave={onExit} onMouseMove={onEnter} ref={textInput}>
{hovered && (
<button
<Button
aria-label="Copy code"
className={`absolute right-2 top-2 h-8 w-8 rounded border-2 bg-gray-700 p-1 dark:bg-gray-800 ${
copied ? "border-green-400 focus:border-green-400 focus:outline-none" : "border-gray-300"
}`}
className={`absolute right-2 top-2 h-8 w-8 rounded p-1 ${copied ? "hover:text-green-500 text-green-500" : ""}`}
onClick={onCopy}
variant={"outline"}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
fill="none"
className={copied ? "text-green-400" : "text-gray-300"}
>
{copied ? (
<>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
/>
</>
) : (
<>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
/>
</>
)}
</svg>
</button>
{copied ? <FaCheck /> : <IoCopyOutline />}
</Button>
)}
<pre className="flat-scrollbar-normal">{children}</pre>
<pre className="p-2 dark:bg-[#0d1117] bg-[#F6F8FA] rounded-md flat-scrollbar-normal not-prose text-sm dark:selection:bg-gray-700 selection:bg-gray-300 selection:text-inherit">
{children}
</pre>
</div>
);
};

View File

@@ -1,4 +1,5 @@
import { H2 } from "./H2";
import Blockquote from "./Blockquote";
import H2 from "./H2";
import ImageWrapper from "./ImageWrapper";
import PreWrapper from "./PreWrapper";
import TableWrapper from "./TableWrapper";
@@ -8,4 +9,5 @@ export const MDXComponentsSet = {
table: TableWrapper,
img: ImageWrapper,
h2: H2,
blockquote: Blockquote,
};

View File

@@ -0,0 +1,10 @@
import { Config } from "@/data/config";
export const BottomCard = () => {
return (
<div className="p-8 w-full flex flex-col justify-center">
<img alt={Config.AuthorName} className="h-24 w-24 rounded-full mx-auto" src={Config.AvatarURL} />
<p className="mx-auto mt-5 font-source-serif-screen">{Config.Sentence}</p>
</div>
);
};

View File

@@ -11,12 +11,12 @@ export const DrawerTOC = (props: { data: TTOCItem[] }) => {
const setIsTOCOpen = useDrawerTOCState((state) => state.changeDrawerTOCOpen);
const activeId = useActiveHeading(props.data.map((item) => `#${item.anchorId}`));
return (
<Sheet open={isTOCOpen} onOpenChange={setIsTOCOpen}>
<Sheet onOpenChange={setIsTOCOpen} open={isTOCOpen}>
<SheetTrigger
title="Open the table of contents"
className="bottom-16 right-5 fixed bg-white dark:bg-black border-gray-700 border dark:border-gray-500 shadow-xl"
title="Open the table of contents"
>
<div title="Open the table of contents" onClick={() => setIsTOCOpen(!isTOCOpen)} className="p-1 font-bold">
<div className="p-1 font-bold" onClick={() => setIsTOCOpen(!isTOCOpen)} title="Open the table of contents">
<MdMenuBook className="text-3xl" />
</div>
</SheetTrigger>
@@ -31,11 +31,11 @@ export const DrawerTOC = (props: { data: TTOCItem[] }) => {
"border-t border-b py-1 px-2 border-dashed hover:bg-gray-100 hover:dark:bg-gray-900",
activeId === `#${item.anchorId}` ? "bg-gray-100 dark:bg-gray-900 text-sky-700 dark:text-sky-500" : "",
)}
href={`#${item.anchorId}`}
key={`drawer-toc-${item.anchorId}`}
onClick={() => {
setIsTOCOpen(false);
}}
key={`drawer-toc-${item.anchorId}`}
href={`#${item.anchorId}`}
>
<li className={"p-2"} style={{ paddingLeft: `${item.level - 2}em` }}>{`${item.title}`}</li>
</Link>

View File

@@ -8,19 +8,19 @@ export const PostComments = (props: { postId: string }) => {
Config.Giscus && (
<div className="mt-10 mb-5">
<Giscus
id={props.postId}
repo={Config.Giscus.repo as `${string}/${string}`}
repoId={Config.Giscus.repoId}
category={Config.Giscus.category}
categoryId={Config.Giscus.categoryId}
mapping="pathname"
term={props.postId}
reactionsEnabled="1"
emitMetadata="0"
theme={theme === "light" ? "light_tritanopia" : "dark_tritanopia"}
id={props.postId}
inputPosition="top"
loading="eager"
lang="en"
loading="eager"
mapping="pathname"
reactionsEnabled="1"
repo={Config.Giscus.repo as `${string}/${string}`}
repoId={Config.Giscus.repoId}
term={props.postId}
theme={theme === "light" ? "light_tritanopia" : "dark_tritanopia"}
/>
</div>
)

View File

@@ -1,7 +1,7 @@
export const PostCover = (props: { coverURL: string }) => {
return (
<div
className="mb-8 mt-0 flex w-full justify-center rounded-xl"
className="mb-8 mt-0 flex w-full justify-center rounded-md"
style={{
aspectRatio: "5/2",
background: `url(${props.coverURL})`,

View File

@@ -11,27 +11,26 @@ export const ShareButtons = (props: {
title: string;
quote?: string | null;
}) => {
const postURL = `https://${Config.SiteDomain}/blog/${props.postId}`;
const postURL = encodeURI(`https://${Config.SiteDomain}/blog/${props.postId}`);
const copyShareText = `${props.title} ${props.subtitle ? `- ${props.subtitle}` : ""} - ${
Config.Nickname
}'s Blog ${postURL}`;
const { toast } = useToast();
return (
<div className="my-3 flex space-x-4 text-2xl">
<div className="py-3 flex justify-center space-x-4 text-2xl">
{props.allowShare != false ? (
<>
<div className="my-auto text-sm font-bold">{"SHARE :"}</div>
<FacebookShareButton className="mx-2" url={postURL} quote={props.quote ?? props.title}>
<FaFacebook title="Share to Facebook" className="hover:text-blue-500" />
<FacebookShareButton className="mx-2" quote={props.quote ?? props.title} url={postURL}>
<FaFacebook className="hover:text-blue-500" title="Share to Facebook" />
</FacebookShareButton>
<TwitterShareButton className="mx-2" url={postURL} title={props.title}>
<FaTwitter title="Share to Twitter" className="hover:text-sky-500" />
<TwitterShareButton className="mx-2" title={props.title} url={postURL}>
<FaTwitter className="hover:text-sky-500" title="Share to Twitter" />
</TwitterShareButton>
<LinkedinShareButton className="mx-2" url={postURL} title={props.title}>
<FaLinkedin title="Share to Linkedin" className="hover:text-blue-500" />
<LinkedinShareButton className="mx-2" title={props.title} url={postURL}>
<FaLinkedin className="hover:text-blue-500" title="Share to Linkedin" />
</LinkedinShareButton>
<RedditShareButton className="mx-2" url={postURL} title={props.title}>
<FaReddit title="Share to Reddit" className="hover:text-orange-500" />
<RedditShareButton className="mx-2" title={props.title} url={postURL}>
<FaReddit className="hover:text-orange-500" title="Share to Reddit" />
</RedditShareButton>
<CopyToClipboard
onCopy={() => {
@@ -40,8 +39,8 @@ export const ShareButtons = (props: {
text={copyShareText}
>
<FaLink
title="Share with the post url and description"
className="hover:text-gray-500 mx-2 cursor-pointer"
title="Share with the post url and description"
/>
</CopyToClipboard>
</>

View File

@@ -1,34 +1,31 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { useActiveHeading } from "@/hooks/useActiveHeading";
import { TTOCItem } from "@/types/toc.type";
import Link from "next/link";
import { twMerge } from "tailwind-merge";
import { Separator } from "../ui/separator";
export const TOC = (props: { data: TTOCItem[] }) => {
const activeId = useActiveHeading(props.data.map((item) => `#${item.anchorId}`));
return (
<Card className="sticky top-[5em] mx-5">
<CardHeader className="p-3">
<CardTitle className="text-lg text-center">{"TABLE OF CONTENTS"}</CardTitle>
</CardHeader>
<Separator />
<CardContent className="px-2 py-2 h-[60vh] overflow-y-auto flat-scrollbar-normal">
<ul>
<div className="mx-5">
<div className="text-lg text-center p-2 font-bold border-t-2 border-b-2 border-gray-500">
{"TABLE OF CONTENTS"}
</div>
<div className="px-2 py-2 h-[60vh] overflow-y-auto flat-scrollbar-normal">
<div>
{props.data?.map((item) => (
<Link className={""} href={`#${item.anchorId}`} key={`toc-${item.anchorId}`}>
<li
<Link href={`#${item.anchorId}`} key={`toc-${item.anchorId}`}>
<div
className={twMerge(
`py-2 text-sm rounded-lg hover:bg-gray-100 hover:dark:bg-gray-900`,
activeId === `#${item.anchorId}` ? "bg-gray-100 dark:bg-gray-900 text-sky-700 dark:text-sky-500" : "",
`py-2 text-sm rounded-lg hover:text-sky-700 dark:hover:text-sky-400`,
activeId === `#${item.anchorId}` ? "text-sky-700 dark:text-sky-400" : "",
)}
style={{ paddingLeft: `${item.level - 1}em` }}
>{`${item.title}`}</li>
>{`${item.title}`}</div>
</Link>
))}
</ul>
</CardContent>
</Card>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,167 @@
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator";
import { Config } from "@/data/config";
import { isEmptyString } from "@/lib/utils";
import { DialogTrigger } from "@radix-ui/react-dialog";
import { nanoid } from "nanoid";
import Link from "next/link";
import { QRCodeSVG } from "qrcode.react";
import { useState } from "react";
import CopyToClipboard from "react-copy-to-clipboard";
import { FaCheck, FaCopy } from "react-icons/fa";
import { FaGithub, FaPatreon, FaPaypal } from "react-icons/fa6";
import { SiAlipay, SiWechat } from "react-icons/si";
import { Input } from "../ui/input";
export const SponsorBoard = () => {
const [isCopiedList, setIsCopiedList] = useState(Config.Sponsor?.Crypto?.map(() => false) ?? []);
return (
<Dialog
onOpenChange={() => {
setIsCopiedList(Config.Sponsor?.Crypto?.map(() => false) ?? []);
}}
>
<div className="mx-2 my-10 flex flex-col justify-around space-y-5">
{Config.Sponsor?.Crypto && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<div className="mx-3 my-auto">
<h3 className="mx-auto text-sm font-bold">{"Crypto"}</h3>
<div className="text-xs">{"Supports BTC, USDT and ETH."}</div>
</div>
</div>
<div className="my-auto">
<DialogTrigger>
<Button className="my-auto font-bold">{"DONATE"}</Button>
</DialogTrigger>
</div>
</div>
)}
{Config.Sponsor?.Github && Config.SocialLinks.github && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<FaGithub className="mx-3 my-auto text-4xl text-gray-900 dark:text-gray-500" />
<div className="my-auto">
<h3 className="mx-auto text-sm font-bold">{"Github Sponsor"}</h3>
</div>
</div>
<div className="my-auto">
<Button asChild className="my-auto font-bold">
<Link href={`https://github.com/sponsors/${Config.SocialLinks.github}`} target="_blank">
{"DONATE"}
</Link>
</Button>
</div>
</div>
)}
{!isEmptyString(Config.Sponsor?.WechatPayQRCodeContent) && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<SiWechat className="mx-3 my-auto text-4xl text-green-500" />
<div className="my-auto">
<h3 className="mx-auto text-sm font-bold">{"Wechat Pay"}</h3>
</div>
</div>
<div className="my-auto bg-white p-1">
<QRCodeSVG height={100} value={Config.Sponsor?.WechatPayQRCodeContent!} width={100} />
</div>
</div>
)}
{!isEmptyString(Config.Sponsor?.AlipayLink) && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<SiAlipay className="mx-3 my-auto text-4xl text-blue-500" />
<div className="my-auto">
<h3 className="mx-auto text-sm font-bold">{"Alipay"}</h3>
</div>
</div>
<div className="my-auto">
<Button asChild className="my-auto font-bold">
<Link href={Config.Sponsor?.AlipayLink!} target="_blank">
{"DONATE"}
</Link>
</Button>
</div>
</div>
)}
{!isEmptyString(Config.Sponsor?.PaypalId) && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<FaPaypal className="mx-3 my-auto text-4xl text-blue-600" />
<div className="my-auto">
<h3 className="mx-auto text-sm font-bold">{"Paypal"}</h3>
</div>
</div>
<div className="my-auto">
<Button asChild className="my-auto font-bold">
<Link href={`https://paypal.me/${Config.Sponsor?.PaypalId}`} target="_blank">
{"DONATE"}
</Link>
</Button>
</div>
</div>
)}
{!isEmptyString(Config.Sponsor?.PatreonId) && (
<div className="py-3 flex justify-between border-b">
<div className="my-auto flex">
<FaPatreon className="mx-3 my-auto text-4xl text-gray-500" />
<div className="my-auto">
<h3 className="mx-auto text-sm font-bold">{"Patreon"}</h3>
</div>
</div>
<div className="my-2">
<Button asChild className="my-auto font-bold">
<Link href={`https://patreon.com/${Config.Sponsor?.PatreonId}`} target="_blank">
{"DONATE"}
</Link>
</Button>
</div>
</div>
)}
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex">{"CRYPTO"}</DialogTitle>
</DialogHeader>
<div>
<div className="w-full text-sm my-2">
<div>
<b>NOTE: </b> Please confirm the corresponding block network and address before transferring money to
avoid loss.
</div>
</div>
<Separator />
{Config.Sponsor?.Crypto?.map((cryptoItem, cryptoItemIndex) => (
<div className="w-full py-3 border-b" key={nanoid()}>
<div className="my-2 flex space-x-2">
<div className="font-bold my-auto text-sm">{`${cryptoItem.Name} - ${cryptoItem.Blockchain}`}</div>
</div>
<div className="flex">
<Input autoFocus={false} defaultValue={cryptoItem.Address} readOnly />
<CopyToClipboard
onCopy={() => {
const newIsCopiedList = Config.Sponsor?.Crypto?.map(() => false) ?? [];
newIsCopiedList[cryptoItemIndex] = true;
setIsCopiedList(newIsCopiedList);
}}
text={cryptoItem.Address}
>
<Button
className={`ml-3 my-auto ${isCopiedList[cryptoItemIndex] && "bg-green-500 hover:bg-green-500"}`}
size="sm"
type="submit"
>
<span className="sr-only">{"Copy"}</span>
{isCopiedList[cryptoItemIndex] ? <FaCheck className="h-4 w-4" /> : <FaCopy className="h-4 w-4" />}
</Button>
</CopyToClipboard>
</div>
</div>
))}
</div>
</DialogContent>
</div>
</Dialog>
);
};

View File

@@ -0,0 +1,28 @@
import { Config } from "@/data/config";
export const SponsorDescription = () => {
return (
<div className="h-full">
{!Config.Sponsor ? (
<p className={`font-source-serif-screen break-words text-lg`}>
{"Thank you, for data and personal private security, every sponsor method was paused."}
</p>
) : (
<p className={`font-source-serif-screen break-words text-lg`}>
{
"If you like my works, I would deeply appreciate your support as a patron. Your contribution not only fuels my creative journey but also allows me to delve deeper into my passion. Your support plays a vital role in making this vision a reality. Thank you for considering becoming a patron and being an integral part of this work endeavor."
}
<br />
{
"If you have donated me please note your name and contact information, or contact me with the transfer record, and I will add you to the sponsor list."
}
<br />
{"Here are the ways you can become a patron. Thank you for your support!"}
<br />
<br />
{`Yours, ${Config.AuthorName}`}
</p>
)}
</div>
);
};

View File

@@ -0,0 +1,54 @@
"use client";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDown } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const Accordion = AccordionPrimitive.Root;
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item className={cn("border-b", className)} ref={ref} {...props} />
));
AccordionItem.displayName = "AccordionItem";
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className,
)}
ref={ref}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
ref={ref}
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };

View File

@@ -3,39 +3,39 @@ import * as React from "react";
import { cn } from "@/lib/utils";
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} {...props} />
<div className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} ref={ref} {...props} />
));
Card.displayName = "Card";
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
<div className={cn("flex flex-col space-y-1.5 p-6", className)} ref={ref} {...props} />
),
);
CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
({ className, ...props }, ref) => (
<h3 ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} />
<h3 className={cn("text-2xl font-semibold leading-none tracking-tight", className)} ref={ref} {...props} />
),
);
CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
({ className, ...props }, ref) => (
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
<p className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
),
);
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} />,
({ className, ...props }, ref) => <div className={cn("p-6 pt-0", className)} ref={ref} {...props} />,
);
CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
<div className={cn("flex items-center p-6 pt-0", className)} ref={ref} {...props} />
),
);
CardFooter.displayName = "CardFooter";

View File

@@ -13,11 +13,11 @@ const Command = React.forwardRef<
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className,
)}
ref={ref}
{...props}
/>
));
@@ -44,11 +44,11 @@ const CommandInput = React.forwardRef<
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
{...props}
/>
</div>
@@ -61,8 +61,8 @@ const CommandList = React.forwardRef<
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
ref={ref}
{...props}
/>
));
@@ -72,7 +72,7 @@ CommandList.displayName = CommandPrimitive.List.displayName;
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />);
>((props, ref) => <CommandPrimitive.Empty className="py-6 text-center text-sm" ref={ref} {...props} />);
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
@@ -81,11 +81,11 @@ const CommandGroup = React.forwardRef<
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className,
)}
ref={ref}
{...props}
/>
));
@@ -96,7 +96,7 @@ const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
<CommandPrimitive.Separator className={cn("-mx-1 h-px bg-border", className)} ref={ref} {...props} />
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
@@ -105,11 +105,11 @@ const CommandItem = React.forwardRef<
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
ref={ref}
{...props}
/>
));

View File

@@ -19,11 +19,11 @@ const DialogOverlay = React.forwardRef<
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
ref={ref}
{...props}
/>
));
@@ -36,11 +36,11 @@ const DialogContent = React.forwardRef<
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg 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,
)}
ref={ref}
{...props}
>
{children}
@@ -68,8 +68,8 @@ const DialogTitle = React.forwardRef<
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
ref={ref}
{...props}
/>
));
@@ -79,7 +79,7 @@ const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
<DialogPrimitive.Description className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;

View File

@@ -7,12 +7,12 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => {
return (
<input
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,
)}
ref={ref}
type={type}
{...props}
/>
);

View File

@@ -10,10 +10,10 @@ const Separator = React.forwardRef<
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
<SeparatorPrimitive.Root
ref={ref}
className={cn("shrink-0 bg-border", orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", className)}
decorative={decorative}
orientation={orientation}
className={cn("shrink-0 bg-border", orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", className)}
ref={ref}
{...props}
/>
));

View File

@@ -61,7 +61,7 @@ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Con
({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
<SheetPrimitive.Content className={cn(sheetVariants({ side }), className)} ref={ref} {...props}>
{children}
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
@@ -87,7 +87,7 @@ const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title ref={ref} className={cn("text-lg font-semibold text-foreground", className)} {...props} />
<SheetPrimitive.Title className={cn("text-lg font-semibold text-foreground", className)} ref={ref} {...props} />
));
SheetTitle.displayName = SheetPrimitive.Title.displayName;
@@ -95,7 +95,7 @@ const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
<SheetPrimitive.Description className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
));
SheetDescription.displayName = SheetPrimitive.Description.displayName;

View File

@@ -12,11 +12,11 @@ const ToastViewport = React.forwardRef<
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
className,
)}
ref={ref}
{...props}
/>
));
@@ -41,7 +41,7 @@ const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return <ToastPrimitives.Root ref={ref} className={cn(toastVariants({ variant }), className)} {...props} />;
return <ToastPrimitives.Root className={cn(toastVariants({ variant }), className)} ref={ref} {...props} />;
});
Toast.displayName = ToastPrimitives.Root.displayName;
@@ -50,11 +50,11 @@ const ToastAction = React.forwardRef<
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className,
)}
ref={ref}
{...props}
/>
));
@@ -65,11 +65,11 @@ const ToastClose = React.forwardRef<
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className,
)}
ref={ref}
toast-close=""
{...props}
>
@@ -82,7 +82,7 @@ const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title ref={ref} className={cn("text-sm font-semibold", className)} {...props} />
<ToastPrimitives.Title className={cn("text-sm font-semibold", className)} ref={ref} {...props} />
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;
@@ -90,7 +90,7 @@ const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description ref={ref} className={cn("text-sm opacity-90", className)} {...props} />
<ToastPrimitives.Description className={cn("text-sm opacity-90", className)} ref={ref} {...props} />
));
ToastDescription.displayName = ToastPrimitives.Description.displayName;

View File

@@ -61,9 +61,9 @@ export const Footer = () => {
text={RSSFeedURL}
>
<Button
type="submit"
size="sm"
className={`ml-3 my-auto ${isCopied && "bg-green-500 hover:bg-green-500"}`}
size="sm"
type="submit"
>
<span className="sr-only">{"Copy"}</span>
{isCopied ? <FaCheck className="h-4 w-4" /> : <FaCopy className="h-4 w-4" />}

View File

@@ -1,6 +1,5 @@
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { Config } from "@/data/config";
import { fontFangZhengXiaoBiaoSongCN } from "@/styles/font";
import { nanoid } from "nanoid";
import { useTheme } from "next-themes";
import Link from "next/link";
@@ -32,40 +31,43 @@ export const NavBar = () => {
};
return (
<Sheet open={isSideNavOpen} onOpenChange={(open) => setIsSideNavOpen(open)}>
<div className="sticky top-0 z-50 border-gray-200 dark:border-gray-700 border-b flex flex-wrap justify-between py-3 backdrop-blur bg-white/50 dark:bg-gray-950/50 px-5 md:px-10 lg:px-20 xl:px-32 2xl:px-52">
<Link href="/" className="cursor-pointer my-auto text-2xl font-bold">
<h1 className={`${fontFangZhengXiaoBiaoSongCN.className} my-auto`}>{Config.SiteTitle}</h1>
<Sheet onOpenChange={(open) => setIsSideNavOpen(open)} open={isSideNavOpen}>
<div className="sticky top-0 z-50 border-black-200 dark:border-gray-700 border-b bg-white dark:bg-gray-950 flex flex-wrap justify-between py-3 px-5 md:px-10 lg:px-20 xl:px-32 2xl:px-52">
<Link className="cursor-pointer my-auto text-2xl font-bold" href="/">
<h1 className={`font-fang-zheng-xiao-biao-song my-auto`} title="Click to jump to home page.">
{Config.SiteTitle}
</h1>
</Link>
<div className="my-auto hidden sm:flex">
{MenuItems.map((menuItem) => (
<Link
className="font-bold hover:text-sky-700 dark:hover:text-sky-500 mx-2 my-auto px-2"
href={menuItem.href}
key={nanoid()}
className="border-b-sky-600 font-bold hover:text-sky-600 dark:hover:border-b-sky-500 dark:hover:text-sky-500 mx-2 my-auto px-2"
onClick={() => setIsSideNavOpen(false)}
>
{menuItem.title}
</Link>
))}
<Link
href={"/search"}
className="cursor-pointer mx-2 rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
href={"/search"}
title="Search posts by keywords"
>
<MdSearch />
</Link>
<div
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
className="cursor-pointer mx-1 rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
onClick={handleSwitchTheme}
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
>
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
</div>
</div>
<div className="text-3xl sm:hidden my-auto">
<SheetTrigger
title="Spread the navigation menu"
className="text-black rounded-full p-1 hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
title="Spread the navigation menu"
>
<MdMenu
onClick={() => {
@@ -78,19 +80,19 @@ export const NavBar = () => {
<SheetContent className="bg:white border-none py-16 shadow-md dark:bg-black flex flex-col text-end">
{MenuItems.map((menuItem) => (
<Link
className="border-b border-dashed p-3 text-xl hover:text-sky-500"
href={menuItem.href}
key={nanoid()}
className="border-b border-dashed p-3 text-xl hover:text-sky-500"
onClick={() => setIsSideNavOpen(false)}
>
{menuItem.title}
</Link>
))}
<Link
title="Search the posts"
className="border-b border-dashed p-3 text-xl hover:text-sky-500"
href="/search"
onClick={() => setIsSideNavOpen(false)}
title="Search the posts"
>
{"SEARCH"}
</Link>
@@ -99,8 +101,8 @@ export const NavBar = () => {
onClick={handleSwitchTheme}
>
<div
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
className="cursor-pointer mx-1 my-auto rounded-full text-2xl"
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
>
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
</div>

View File

@@ -1,5 +1,4 @@
import { normalizeDate } from "@/lib/date";
import { fontSourceSerifScreenCN } from "@/styles/font";
import { TPostListItem } from "@/types/post-list";
import { nanoid } from "nanoid";
import Link from "next/link";
@@ -13,35 +12,43 @@ export const PostList = (props: { data: TPostListItem[] }) => {
<div
className={`flex flex-col justify-center ${
index !== props.data.length - 1 && "border-b"
} border-gray-200 hover:bg-gray-50 dark:hover:bg-gray-950 dark:border-gray-800 p-3`}
} border-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 dark:border-gray-800 px-3 py-1`}
>
<div className={`${fontSourceSerifScreenCN.className} text-center flex-col py-2`}>
<h3 className="mx-auto text-lg font-extrabold capitalize">{postItem.frontMatter.title}</h3>
{postItem.frontMatter.subtitle && (
<div className="mx-auto text-base font-semibold capitalize text-gray-700 dark:text-gray-300">
{postItem.frontMatter.subtitle}
</div>
)}
</div>
<div className="text-center text-sm italic">{normalizeDate(postItem.frontMatter.time)}</div>
{postItem.frontMatter.tags && (
<div className="my-2 flex justify-center">
{postItem.frontMatter.tags.map((tagName) => (
<Badge
variant={"secondary"}
className="mx-1 text-gray-600 dark:text-gray-300"
key={`tags-${nanoid()}`}
>
{tagName}
</Badge>
))}
<div className={"font-source-serif-screen flex-col py-3"}>
<div className="flex justify-center">
<h3 className="mx-auto text-lg font-extrabold capitalize">{postItem.frontMatter.title}</h3>
</div>
)}
<div className="flex justify-center">
{postItem.frontMatter.subtitle && (
<div className="mx-auto text-sm font-bold capitalize text-gray-700 dark:text-gray-300">
{postItem.frontMatter.subtitle}
</div>
)}
</div>
</div>
{postItem.frontMatter.summary && (
<div className={`${fontSourceSerifScreenCN.className} flex my-1 justify-center`}>
<div className={"font-source-serif-screen flex justify-center"}>
<p>{postItem.frontMatter.summary}</p>
</div>
)}
<div className="flex flex-wrap justify-between my-2">
<div className="text-center flex flex-col justify-center italic text-sm my-auto mr-2 h-6">
<div className="my-auto">{normalizeDate(postItem.frontMatter.time)}</div>
</div>
{postItem.frontMatter.tags && (
<div className="flex flex-wrap my-auto">
{postItem.frontMatter.tags.map((tagName) => (
<Badge
className="mr-1 my-1 text-gray-600 dark:text-gray-300"
key={`tags-${nanoid()}`}
variant={"secondary"}
>
{tagName}
</Badge>
))}
</div>
)}
</div>
</div>
</Link>
))}

View File

@@ -6,9 +6,8 @@ export const SEO = (props: { title: string; description?: string | null; coverUR
return (
<>
<title>{props.title}</title>
<link rel="alternate" type="application/rss+xml" href={RSSFeedURL} />
<link href={RSSFeedURL} rel="alternate" type="application/rss+xml" />
<NextSeo
title={props.title}
description={props.description ?? Config.Sentence}
openGraph={{
title: props.title,
@@ -31,6 +30,7 @@ export const SEO = (props: { title: string; description?: string | null; coverUR
},
],
}}
title={props.title}
twitter={{
handle: `@${Config.SocialLinks.twitter}`,
site: WebsiteURL,

View File

@@ -7,36 +7,36 @@ export const SocialIcons = () => {
return (
<div className="my-5 flex justify-center space-x-4 text-2xl font-bold">
{Config.SocialLinks.twitter && (
<Link target="_blank" href={`https://x.com/${Config.SocialLinks.twitter}`} title="Twitter">
<Link href={`https://x.com/${Config.SocialLinks.twitter}`} target="_blank" title="Twitter">
<FiTwitter className="hover:text-sky-500" />
</Link>
)}
{Config.SocialLinks.mastodon && (
<Link target="_blank" href={Config.SocialLinks.mastodon} title="Mastodon">
<Link href={Config.SocialLinks.mastodon} target="_blank" title="Mastodon">
<TbBrandMastodon className="hover:text-purple-500" />
</Link>
)}
{Config.SocialLinks.instagram && (
<Link target="_blank" href={`https://instagram.com/${Config.SocialLinks.instagram}`} title="Instagram">
<Link href={`https://instagram.com/${Config.SocialLinks.instagram}`} target="_blank" title="Instagram">
<FiInstagram className="hover:text-orange-500" />
</Link>
)}
{Config.SocialLinks.facebook && (
<Link target="_blank" href={`https://instagram.com/${Config.SocialLinks.facebook}`} title="Instagram">
<Link href={`https://instagram.com/${Config.SocialLinks.facebook}`} target="_blank" title="Instagram">
<TbBrandFacebook className="hover:text-blue-500" />
</Link>
)}
{Config.SocialLinks.linkedin && (
<Link target="_blank" href={`https://linkedin.com/in/${Config.SocialLinks.linkedin}`} title="Instagram">
<Link href={`https://linkedin.com/in/${Config.SocialLinks.linkedin}`} target="_blank" title="Instagram">
<TbBrandLinkedin className="hover:text-blue-500" />
</Link>
)}
{Config.SocialLinks.github && (
<Link target="_blank" href={`https://github.com/${Config.SocialLinks.github}`} title="Github">
<Link href={`https://github.com/${Config.SocialLinks.github}`} target="_blank" title="Github">
<FiGithub className="hover:text-gray-500" />
</Link>
)}
<Link target="_blank" href={`mailto:${Config.SocialLinks.email}`} title="EMail Address">
<Link href={`mailto:${Config.SocialLinks.email}`} target="_blank" title="EMail Address">
<FiMail className="hover:text-gray-500" />
</Link>
</div>