1
0
Code Issues Pull Requests Packages Projects Releases Wiki Activity GitHub Gitee

release 0.3.4

This commit is contained in:
songjunxi
2023-11-10 14:59:47 +08:00
parent 2b456637e9
commit 602f2059fd
161 changed files with 9921 additions and 347 deletions

View File

@@ -0,0 +1,40 @@
"use client";
import { useEffect, useState } from "react";
export default function CountingNumbers({
value,
className,
start = 0,
duration = 800,
}: {
value: number;
className: string;
start?: number;
duration?: number;
}) {
const [count, setCount] = useState(start);
useEffect(() => {
let startTime: number | undefined;
const animateCount = (timestamp: number) => {
if (!startTime) startTime = timestamp;
const timePassed = timestamp - startTime;
const progress = timePassed / duration;
const currentCount = easeOutQuad(progress, 0, value, 1);
if (currentCount >= value) {
setCount(value);
return;
}
setCount(currentCount);
requestAnimationFrame(animateCount);
};
requestAnimationFrame(animateCount);
}, [value, duration]);
return <p className={className}>{Intl.NumberFormat().format(count)}</p>;
}
const easeOutQuad = (t: number, b: number, c: number, d: number) => {
t = t > d ? d : t / d;
return Math.round(-c * t * (t - 2) + b);
};

View File

@@ -0,0 +1,18 @@
export default function Box({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className={className}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21 7.5l-2.25-1.313M21 7.5v2.25m0-2.25l-2.25 1.313M3 7.5l2.25-1.313M3 7.5l2.25 1.313M3 7.5v2.25m9 3l2.25-1.313M12 12.75l-2.25-1.313M12 12.75V15m0 6.75l2.25-1.313M12 21.75V19.5m0 2.25l-2.25-1.313m0-16.875L12 2.25l2.25 1.313M21 14.25v2.25l-2.25 1.313m-13.5 0L3 16.5v-2.25"
/>
</svg>
);
}

View File

@@ -0,0 +1,18 @@
export default function Checked() {
return (
<svg
className="text-2xs mr-2 rounded-full bg-green-500 p-1 text-white"
fill="none"
width="19"
height="19"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<polyline points="20 6 9 17 4 12" />
</svg>
);
}

View File

@@ -0,0 +1,20 @@
export default function Color({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={className}
>
<circle cx="13.5" cy="6.5" r=".5" />
<circle cx="17.5" cy="10.5" r=".5" />
<circle cx="8.5" cy="7.5" r=".5" />
<circle cx="6.5" cy="12.5" r=".5" />
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" />
</svg>
);
}

View File

@@ -0,0 +1,36 @@
export default function ExpandingArrow({ className }: { className?: string }) {
return (
<div className="group relative flex items-center">
<svg
className={`${
className ? className : "h-4 w-4"
} absolute transition-all group-hover:translate-x-1 group-hover:opacity-0`}
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 16 16"
width="16"
height="16"
>
<path
fillRule="evenodd"
d="M6.22 3.22a.75.75 0 011.06 0l4.25 4.25a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06-1.06L9.94 8 6.22 4.28a.75.75 0 010-1.06z"
></path>
</svg>
<svg
className={`${
className ? className : "h-4 w-4"
} absolute opacity-0 transition-all group-hover:translate-x-1 group-hover:opacity-100`}
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 16 16"
width="16"
height="16"
>
<path
fillRule="evenodd"
d="M8.22 2.97a.75.75 0 011.06 0l4.25 4.25a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06-1.06l2.97-2.97H3.75a.75.75 0 010-1.5h7.44L8.22 4.03a.75.75 0 010-1.06z"
></path>
</svg>
</div>
);
}

View File

@@ -0,0 +1,20 @@
export default function FontDefault({ className }: { className?: string }) {
return (
<svg
width="27"
height="17"
viewBox="0 0 27 17"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M2.67735 16.7224H0L6.01587 0H8.92994L14.9458 16.7224H12.2685L7.54229 3.03746H7.41169L2.67735 16.7224ZM3.12629 10.1739H11.8114V12.2968H3.12629V10.1739Z"
fill="currentColor"
/>
<path
d="M20.8127 17C20.0182 17 19.2999 16.853 18.6578 16.5591C18.0156 16.2597 17.5068 15.8269 17.1314 15.2608C16.7613 14.6947 16.5763 14.0006 16.5763 13.1787C16.5763 12.471 16.7123 11.8886 16.9844 11.4313C17.2565 10.9741 17.6238 10.6121 18.0864 10.3453C18.5489 10.0786 19.0659 9.8772 19.6373 9.74111C20.2087 9.60503 20.7909 9.5016 21.3841 9.43084C22.1351 9.34374 22.7445 9.27298 23.2125 9.21854C23.6805 9.15866 24.0206 9.0634 24.2329 8.93276C24.4451 8.80211 24.5512 8.58982 24.5512 8.29587V8.23871C24.5512 7.52562 24.3499 6.9731 23.9472 6.58117C23.5499 6.18924 22.9568 5.99328 22.1677 5.99328C21.346 5.99328 20.6984 6.17563 20.225 6.54035C19.757 6.89962 19.4332 7.29971 19.2536 7.74063L16.9599 7.21806C17.232 6.45597 17.6293 5.84086 18.1517 5.37272C18.6795 4.89914 19.2863 4.5562 19.972 4.3439C20.6576 4.12616 21.3787 4.01729 22.1351 4.01729C22.6357 4.01729 23.1663 4.07717 23.7268 4.19693C24.2927 4.31124 24.8206 4.52354 25.3103 4.83381C25.8055 5.14409 26.2109 5.58774 26.5266 6.16475C26.8422 6.73631 27 7.47935 27 8.39385V16.7224H24.6165V15.0077H24.5186C24.3607 15.3234 24.124 15.6337 23.8084 15.9385C23.4928 16.2434 23.0874 16.4965 22.5922 16.6979C22.097 16.8993 21.5038 17 20.8127 17ZM21.3433 15.0403C22.0181 15.0403 22.5949 14.907 23.0738 14.6403C23.5581 14.3735 23.9254 14.0251 24.1757 13.5951C24.4315 13.1596 24.5594 12.6942 24.5594 12.1988V10.5821C24.4723 10.6692 24.3036 10.7509 24.0533 10.8271C23.8084 10.8979 23.5282 10.9605 23.2125 11.0149C22.8969 11.0639 22.5894 11.1102 22.2902 11.1537C21.9909 11.1918 21.7405 11.2245 21.5392 11.2517C21.0658 11.3116 20.6331 11.4123 20.2413 11.5538C19.855 11.6953 19.5448 11.8995 19.3108 12.1662C19.0822 12.4275 18.968 12.7759 18.968 13.2113C18.968 13.8156 19.1911 14.2728 19.6373 14.5831C20.0835 14.8879 20.6522 15.0403 21.3433 15.0403Z"
fill="currentColor"
/>
</svg>
);
}

View File

@@ -0,0 +1,21 @@
export default function FontMono({ className }: { className?: string }) {
return (
<svg
width="28"
height="19"
viewBox="0 0 28 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M10.4513 13.9906H3.35401L3.80321 11.8861H9.94225L10.4513 13.9906ZM7.06738 5.72075L2.90481 18.6739H0L6.4984 0H7.66631L14.1647 18.6739H11.1701L7.06738 5.72075Z"
fill="currentColor"
/>
<path
d="M20.6032 19C19.066 19 17.8681 18.6542 17.0096 17.9626C16.1711 17.2512 15.7519 16.3323 15.7519 15.2059C15.7519 14.455 15.9216 13.7832 16.261 13.1903C16.6203 12.5777 17.1194 12.0541 17.7583 11.6193C18.4171 11.1846 19.2057 10.8487 20.1241 10.6115C21.0424 10.3547 22.0806 10.2262 23.2385 10.2262C23.4781 10.2262 23.7276 10.2361 23.9872 10.2559C24.2667 10.2559 24.5562 10.2657 24.8556 10.2855C25.175 10.3053 25.4945 10.325 25.8139 10.3448L25.9037 12.4493C25.6242 12.4098 25.3248 12.3801 25.0053 12.3604C24.7059 12.3406 24.4064 12.3307 24.107 12.3307C23.8075 12.3307 23.528 12.3307 23.2685 12.3307C22.4898 12.3307 21.8111 12.39 21.2321 12.5086C20.6731 12.6074 20.2039 12.7655 19.8246 12.9828C19.4652 13.2002 19.1957 13.467 19.016 13.7832C18.8364 14.0993 18.7465 14.4649 18.7465 14.8799C18.7465 15.2158 18.8064 15.5122 18.9262 15.7691C19.046 16.0062 19.2057 16.194 19.4053 16.3323C19.625 16.4706 19.8745 16.5793 20.154 16.6583C20.4535 16.7176 20.7729 16.7473 21.1123 16.7473C21.7711 16.7473 22.3501 16.6386 22.8492 16.4212C23.3483 16.2038 23.7676 15.8877 24.107 15.4727C24.4663 15.038 24.7358 14.5044 24.9155 13.8721C25.0952 13.22 25.185 12.4592 25.185 11.5897C25.185 10.3843 25.0453 9.44566 24.7658 8.77379C24.5062 8.10192 24.1169 7.63755 23.5979 7.38066C23.0788 7.12376 22.4299 6.99532 21.6513 6.99532C21.0125 6.99532 20.3936 7.104 19.7947 7.32137C19.2157 7.51898 18.6467 7.89444 18.0877 8.44774L16.5005 6.66927C17.2592 5.95788 18.0877 5.4441 18.9861 5.12793C19.9045 4.81175 20.8428 4.65367 21.8011 4.65367C22.6795 4.65367 23.4881 4.76235 24.2267 4.97972C24.9854 5.17733 25.6442 5.51326 26.2032 5.98752C26.7822 6.46178 27.2214 7.104 27.5209 7.9142C27.8403 8.72439 28 9.75195 28 10.9969V18.6739H24.8856V16.9844C24.626 17.3796 24.3365 17.7155 24.0171 17.9922C23.6977 18.2491 23.3483 18.4566 22.969 18.6147C22.6096 18.753 22.2303 18.8518 21.831 18.9111C21.4317 18.9704 21.0225 19 20.6032 19Z"
fill="currentColor"
/>
</svg>
);
}

View File

@@ -0,0 +1,21 @@
export default function FontSerif({ className }: { className?: string }) {
return (
<svg
width="31"
height="18"
viewBox="0 0 31 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M0.108486 17.8929C0.0361621 17.8214 0 17.6875 0 17.4911C0 17.1696 0.0180811 17.0089 0.0542432 17.0089C0.198892 17.0089 0.406824 16.9732 0.67804 16.9018C0.967337 16.8304 1.23855 16.7411 1.49169 16.6339C1.7629 16.5089 1.93467 16.3839 2.007 16.2589C2.18781 15.9911 2.35958 15.6875 2.52231 15.3482C2.68504 14.9911 2.85681 14.5982 3.03762 14.1696L8.08224 2.11607C8.51619 1.02679 8.85069 0.383929 9.08574 0.1875C9.21231 0.0625 9.366 0 9.54681 0C9.67337 0 9.78186 0.0446429 9.87227 0.133929L15.5678 14.1696C15.7125 14.5089 15.8481 14.8482 15.9746 15.1875C16.1193 15.5089 16.2549 15.8214 16.3815 16.125C16.4538 16.3036 16.6165 16.4643 16.8696 16.6071C17.1228 16.7321 17.385 16.8304 17.6562 16.9018C17.9274 16.9732 18.1353 17.0089 18.28 17.0089C18.3523 17.0089 18.3885 17.1696 18.3885 17.4911C18.3885 17.6875 18.3704 17.8214 18.3342 17.8929L14.9169 17.7321L11.3911 17.8929C11.3188 17.8214 11.2826 17.6518 11.2826 17.3839C11.2826 17.1339 11.3188 17.0089 11.3911 17.0089C11.608 17.0089 11.9064 16.9554 12.2861 16.8482C12.6658 16.7411 12.8918 16.6161 12.9641 16.4732C13.0184 16.3661 13.0455 16.25 13.0455 16.125C13.0455 15.9464 13.0003 15.7054 12.9099 15.4018C12.8195 15.0982 12.6929 14.7232 12.5302 14.2768L11.5809 11.7857C11.5086 11.7143 11.4453 11.6786 11.3911 11.6786C11.1018 11.6607 10.7582 11.6518 10.3605 11.6518C9.98075 11.6339 9.54681 11.625 9.05862 11.625C8.08224 11.625 7.05162 11.6518 5.96675 11.7054C5.85827 11.7054 5.80402 11.7411 5.80402 11.8125L4.7734 14.3036C4.59259 14.75 4.45698 15.125 4.36658 15.4286C4.29425 15.7143 4.25809 15.9196 4.25809 16.0446C4.25809 16.2589 4.35754 16.4375 4.55643 16.5804C4.66492 16.6518 4.82765 16.7232 5.04462 16.7946C5.27967 16.8482 5.51473 16.9018 5.74978 16.9554C5.98484 16.9911 6.14756 17.0089 6.23797 17.0089C6.29221 17.0268 6.31933 17.1518 6.31933 17.3839C6.31933 17.5089 6.31029 17.6161 6.29221 17.7054C6.29221 17.7768 6.28317 17.8393 6.26509 17.8929C5.59609 17.8571 5.04462 17.8214 4.61067 17.7857C4.19481 17.75 3.80607 17.7321 3.44444 17.7321C3.08282 17.7321 2.64888 17.7411 2.14261 17.7589C1.63634 17.7768 0.958297 17.8214 0.108486 17.8929ZM8.57043 10.1786C9.22135 10.1786 9.96267 10.1518 10.7944 10.0982L10.8486 9.99107L8.7874 4.63393L6.56343 9.99107C6.56343 10.0625 6.58151 10.0982 6.61767 10.0982C7.25051 10.1518 7.90143 10.1786 8.57043 10.1786Z"
fill="currentColor"
/>
<path
d="M23.0534 18C22.1493 18 21.408 17.7589 20.8294 17.2768C20.2689 16.7768 19.9886 16.0982 19.9886 15.2411C19.9886 14.6518 20.1785 14.1161 20.5582 13.6339C20.956 13.1518 21.5074 12.7411 22.2126 12.4018C22.4657 12.2768 22.6917 12.1786 22.8906 12.1071C23.1076 12.0179 23.3065 11.9375 23.4873 11.8661C24.1202 11.6696 24.6445 11.5089 25.0604 11.3839C25.4943 11.2589 25.8017 11.1696 25.9825 11.1161C26.1452 11.0268 26.2266 10.8839 26.2266 10.6875V9.21429C26.2266 8.58929 26.0819 8.09821 25.7927 7.74107C25.5034 7.38393 25.1146 7.20536 24.6264 7.20536C24.084 7.20536 23.6591 7.375 23.3517 7.71429C23.0443 8.03571 22.8906 8.5 22.8906 9.10714C22.8906 9.46429 22.755 9.73214 22.4838 9.91071C22.2126 10.0714 21.9052 10.1518 21.5617 10.1518C20.8927 10.1518 20.4226 9.9375 20.1514 9.50893C20.1514 9.08036 20.3141 8.66071 20.6395 8.25C20.965 7.82143 21.3899 7.4375 21.9143 7.09821C22.4567 6.75893 23.0534 6.49107 23.7043 6.29464C24.3552 6.08036 25.0061 5.97321 25.657 5.97321C26.7781 5.97321 27.6188 6.26786 28.1794 6.85714C28.7399 7.42857 29.0201 8.41964 29.0201 9.83036V15.1071C29.0201 15.8393 29.3185 16.2054 29.9151 16.2054C30.1864 16.2054 30.4937 16.0893 30.8373 15.8571C30.9458 15.875 31 15.9732 31 16.1518C31 16.4911 30.9458 16.7589 30.8373 16.9554C30.5661 17.1696 30.2044 17.3929 29.7524 17.625C29.3004 17.8571 28.8664 17.9732 28.4506 17.9732C28.0347 17.9732 27.6279 17.8214 27.2301 17.5179C26.8323 17.2143 26.5701 16.8839 26.4436 16.5268C26.2989 16.6518 26.1904 16.7411 26.1181 16.7946C26.0458 16.8482 25.9283 16.9375 25.7655 17.0625C25.3858 17.3125 24.97 17.5357 24.5179 17.7321C24.0659 17.9107 23.5777 18 23.0534 18ZM24.4366 16.2589C24.9248 16.2589 25.3406 16.1339 25.6842 15.8839C26.0458 15.6339 26.2266 15.3482 26.2266 15.0268V12.2946L24.4908 12.8839C24.0749 13.0625 23.7043 13.2768 23.3788 13.5268C23.0534 13.7768 22.8906 14.1339 22.8906 14.5982C22.8906 15.1696 23.0353 15.5893 23.3246 15.8571C23.6139 16.125 23.9845 16.2589 24.4366 16.2589Z"
fill="currentColor"
/>
</svg>
);
}

View File

@@ -0,0 +1,14 @@
export default function Github({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
viewBox="0 0 24 24"
className={className}
>
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
);
}

View File

@@ -0,0 +1,47 @@
export default function Google({ className }: { className: string }) {
return (
<svg viewBox="0 0 100 100" className={className}>
<linearGradient
id="b"
x1="55.41"
x2="12.11"
y1="96.87"
y2="21.87"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stopColor="#1e8e3e" />
<stop offset="1" stopColor="#34a853" />
</linearGradient>
<linearGradient
id="c"
x1="42.7"
x2="86"
y1="100"
y2="25.13"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stopColor="#fcc934" />
<stop offset="1" stopColor="#fbbc04" />
</linearGradient>
<linearGradient
id="a"
x1="6.7"
x2="93.29"
y1="31.25"
y2="31.25"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stopColor="#d93025" />
<stop offset="1" stopColor="#ea4335" />
</linearGradient>
<path fill="url(#a)" d="M93.29 25a50 50 90 0 0-86.6 0l3 54z" />
<path fill="url(#b)" d="M28.35 62.5 6.7 25A50 50 90 0 0 50 100l49-50z" />
<path fill="url(#c)" d="M71.65 62.5 50 100a50 50 90 0 0 43.29-75H50z" />
<path fill="#fff" d="M50 75a25 25 90 1 0 0-50 25 25 90 0 0 0 50z" />
<path
fill="#1a73e8"
d="M50 69.8a19.8 19.8 90 1 0 0-39.6 19.8 19.8 90 0 0 0 39.6z"
/>{" "}
</svg>
);
}

View File

@@ -0,0 +1,22 @@
export default function ImageDown({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={className}
>
<circle cx="9" cy="9" r="2" />
<path d="M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10.8" />
<path d="m21 15-3.1-3.1a2 2 0 0 0-2.814.014L6 21" />
<path d="m14 19.5 3 3v-6" />
<path d="m17 22.5 3-3" />
</svg>
);
}

View File

@@ -0,0 +1,12 @@
export { default as LoadingDots } from "./loading-dots";
export { default as LoadingCircle } from "./loading-circle";
export { default as LoadingSpinner } from "./loading-spinner";
export { default as ExpandingArrow } from "./expanding-arrow";
export { default as Github } from "./github";
export { default as Twitter } from "./twitter";
export { default as Google } from "./google";
export { default as Widgets } from "./widgets";
export { default as Color } from "./color";
export { default as FontDefault } from "./font-default";
export { default as FontSerif } from "./font-serif";
export { default as FontMono } from "./font-mono";

View File

@@ -0,0 +1,22 @@
export default function LoadingCircle({ className }: { className?: string }) {
return (
<svg
aria-hidden="true"
className={
className + " h-4 w-4 animate-spin fill-gray-600 text-gray-200"
}
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
);
}

View File

@@ -0,0 +1,40 @@
.loading {
display: inline-flex;
align-items: center;
}
.loading .spacer {
margin-right: 2px;
}
.loading span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
width: 5px;
height: 5px;
border-radius: 50%;
display: inline-block;
margin: 0 1px;
}
.loading span:nth-of-type(2) {
animation-delay: 0.2s;
}
.loading span:nth-of-type(3) {
animation-delay: 0.4s;
}
@keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}

View File

@@ -0,0 +1,13 @@
import styles from "./loading-dots.module.css";
const LoadingDots = ({ color = "#000" }: { color?: string }) => {
return (
<span className={styles.loading}>
<span style={{ backgroundColor: color }} />
<span style={{ backgroundColor: color }} />
<span style={{ backgroundColor: color }} />
</span>
);
};
export default LoadingDots;

View File

@@ -0,0 +1,79 @@
.spinner {
color: gray;
display: inline-block;
position: relative;
width: 80px;
height: 80px;
transform: scale(0.3) translateX(-95px);
}
.spinner div {
transform-origin: 40px 40px;
animation: spinner 1.2s linear infinite;
}
.spinner div:after {
content: " ";
display: block;
position: absolute;
top: 3px;
left: 37px;
width: 6px;
height: 20px;
border-radius: 20%;
background: black;
}
.spinner div:nth-child(1) {
transform: rotate(0deg);
animation-delay: -1.1s;
}
.spinner div:nth-child(2) {
transform: rotate(30deg);
animation-delay: -1s;
}
.spinner div:nth-child(3) {
transform: rotate(60deg);
animation-delay: -0.9s;
}
.spinner div:nth-child(4) {
transform: rotate(90deg);
animation-delay: -0.8s;
}
.spinner div:nth-child(5) {
transform: rotate(120deg);
animation-delay: -0.7s;
}
.spinner div:nth-child(6) {
transform: rotate(150deg);
animation-delay: -0.6s;
}
.spinner div:nth-child(7) {
transform: rotate(180deg);
animation-delay: -0.5s;
}
.spinner div:nth-child(8) {
transform: rotate(210deg);
animation-delay: -0.4s;
}
.spinner div:nth-child(9) {
transform: rotate(240deg);
animation-delay: -0.3s;
}
.spinner div:nth-child(10) {
transform: rotate(270deg);
animation-delay: -0.2s;
}
.spinner div:nth-child(11) {
transform: rotate(300deg);
animation-delay: -0.1s;
}
.spinner div:nth-child(12) {
transform: rotate(330deg);
animation-delay: 0s;
}
@keyframes spinner {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View File

@@ -0,0 +1,20 @@
import styles from "./loading-spinner.module.css";
export default function LoadingSpinner() {
return (
<div className={styles.spinner}>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
);
}

View File

@@ -0,0 +1,16 @@
export default function Pill({ className }: { className?: string }) {
return (
<svg
className={className}
width="512"
height="512"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="currentColor"
d="M262.97 19.438a221.3 221.3 0 0 0-10.595.375c37.426 5.91 74.12 23.423 102.188 49.624c-55.762-26.124-129.46-27.253-186.875-3.5c10.37-9.73 21.777-17.51 33.875-23.343C48.768 80.06-6.44 197.116 56.72 343.938c-16.45-26.78-29.106-55.588-35.626-84.688c-5.23 74.055 32.02 134.952 102.47 197.406c.06.063.124.126.186.188c12.107 12.125 24.238 22.045 32.875 27.03c64.588 37.292 121.345-63.365 57.78-100.062c-11.465-6.62-33.518-14.218-56.56-18.875c-76.657-36.295-93.91-155.886-20.282-240.687c-6.654 16.82-11.594 34.836-14.844 53.375c76.21-134.99 312.3-129.124 324.124 72.063c-10.722-61.622-53.708-113.837-121.03-135.344c56.69 23.942 96.28 79.752 96.28 145.25c0 94.252-72.826 148.403-154.594 165.625c42.582 2.34 94.684-13.826 125.438-36.314c-23.357 39.58-72.146 67.082-123.25 81.594c72.736-2.804 136.515-41.146 175.406-97.375c-10.316 11.652-22.718 22.04-36.78 30.97c46.54-55.267 70.795-137.97 61.31-210.25c8.428 16.284 13.583 33.51 15.782 51.374C485.26 97.63 372.46 18.3 262.97 19.437z"
/>
</svg>
);
}

View File

@@ -0,0 +1,75 @@
export default function ProductHunt() {
return (
<svg
width="250"
height="54"
viewBox="0 0 250 54"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g transform="translate(-130.000000, -73.000000)">
<g transform="translate(130.000000, 73.000000)">
<rect
stroke="#FF6154"
strokeWidth="1"
fill="#FFFFFF"
x="0.5"
y="0.5"
width="249"
height="53"
rx="10"
></rect>
<text
fontFamily="Helvetica-Bold, Helvetica"
fontSize="9"
fontWeight="bold"
fill="#FF6154"
>
<tspan x="53" y="20">
FEATURED ON
</tspan>
</text>
<text
fontFamily="Helvetica-Bold, Helvetica"
fontSize="21"
fontWeight="bold"
fill="#FF6154"
>
<tspan x="52" y="40">
Product Hunt
</tspan>
</text>
<g transform="translate(201.000000, 13.000000)" fill="#FF6154">
<g>
<polygon points="26.0024997 10 15 10 20.5012498 0"></polygon>
<text
fontFamily="Helvetica-Bold, Helvetica"
fontSize="13"
fontWeight="bold"
line-spacing="20"
>
<tspan x="12.4" y="27">
70
</tspan>
</text>
</g>
</g>
<g transform="translate(11.000000, 12.000000)">
<path
d="M31,15.5 C31,24.0603917 24.0603917,31 15.5,31 C6.93960833,31 0,24.0603917 0,15.5 C0,6.93960833 6.93960833,0 15.5,0 C24.0603917,0 31,6.93960833 31,15.5"
fill="#FF6154"
></path>
<path
d="M17.4329412,15.9558824 L17.4329412,15.9560115 L13.0929412,15.9560115 L13.0929412,11.3060115 L17.4329412,11.3060115 L17.4329412,11.3058824 C18.7018806,11.3058824 19.7305882,12.3468365 19.7305882,13.6308824 C19.7305882,14.9149282 18.7018806,15.9558824 17.4329412,15.9558824 M17.4329412,8.20588235 L17.4329412,8.20601152 L10.0294118,8.20588235 L10.0294118,23.7058824 L13.0929412,23.7058824 L13.0929412,19.0560115 L17.4329412,19.0560115 L17.4329412,19.0558824 C20.3938424,19.0558824 22.7941176,16.6270324 22.7941176,13.6308824 C22.7941176,10.6347324 20.3938424,8.20588235 17.4329412,8.20588235"
fill="#FFFFFF"
></path>
</g>
</g>
</g>
</g>
</svg>
);
}

View File

@@ -0,0 +1,14 @@
export default function Twitter({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 248 204"
className={className}
>
<path
fill="currentColor"
d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z"
/>
</svg>
);
}

View File

@@ -0,0 +1,16 @@
export default function Widgets({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={className}
>
<path d="M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.077.877.528 1.073 1.01a2.5 2.5 0 1 0 3.259-3.259c-.482-.196-.933-.558-1.01-1.073-.05-.336.062-.676.303-.917l1.525-1.525A2.402 2.402 0 0 1 12 1.998c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.237 3.237c-.464.18-.894.527-.967 1.02Z" />
</svg>
);
}

View File

@@ -0,0 +1,73 @@
import { useEffect, useRef, ReactNode, Dispatch, SetStateAction } from "react";
import { AnimatePresence, motion, useAnimation } from "framer-motion";
export default function Leaflet({
setShow,
showBlur,
children,
}: {
setShow: Dispatch<SetStateAction<boolean>>;
showBlur: boolean;
children: ReactNode;
}) {
const leafletRef = useRef<HTMLDivElement>(null);
const controls = useAnimation();
const transitionProps = { type: "spring", stiffness: 500, damping: 30 };
useEffect(() => {
controls.start({
y: 20,
transition: transitionProps,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function handleDragEnd(_: any, info: any) {
const offset = info.offset.y;
const velocity = info.velocity.y;
const height = leafletRef.current?.getBoundingClientRect().height || 0;
if (offset > height / 2 || velocity > 800) {
await controls.start({ y: "100%", transition: transitionProps });
setShow(false);
} else {
controls.start({ y: 0, transition: transitionProps });
}
}
return (
<AnimatePresence>
<motion.div
ref={leafletRef}
key="leaflet"
className="group fixed inset-x-0 bottom-0 z-40 w-screen cursor-grab overflow-y-scroll bg-white pb-5 active:cursor-grabbing sm:hidden"
style={{ maxHeight: "65%" }}
initial={{ y: "100%" }}
animate={controls}
exit={{ y: "100%" }}
transition={transitionProps}
drag="y"
dragDirectionLock
onDragEnd={handleDragEnd}
dragElastic={{ top: 0, bottom: 1 }}
dragConstraints={{ top: 0, bottom: 0 }}
>
<div
className={`rounded-t-4xl -mb-1 flex h-7 w-full items-center justify-center border-t border-gray-200`}
>
<div className="-mr-1 h-1 w-6 rounded-full bg-gray-300 transition-all group-active:rotate-12" />
<div className="h-1 w-6 rounded-full bg-gray-300 transition-all group-active:-rotate-12" />
</div>
{children}
</motion.div>
{showBlur && (
<motion.div
key="leaflet-backdrop"
className="fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setShow(false)}
/>
)}
</AnimatePresence>
);
}

View File

@@ -0,0 +1,84 @@
"use client";
import {
Dispatch,
SetStateAction,
useCallback,
useEffect,
useRef,
} from "react";
import FocusTrap from "focus-trap-react";
import { AnimatePresence, motion } from "framer-motion";
import Leaflet from "./leaflet";
import useWindowSize from "@/lib/hooks/use-window-size";
export default function Modal({
children,
showModal,
setShowModal,
showBlur = true,
}: {
children: React.ReactNode;
showModal: boolean;
setShowModal: Dispatch<SetStateAction<boolean>>;
showBlur?: boolean;
}) {
const desktopModalRef = useRef(null);
const onKeyDown = useCallback(
(e: KeyboardEvent) => {
if (e.key === "Escape") {
setShowModal(false);
}
},
[setShowModal],
);
useEffect(() => {
document.addEventListener("keydown", onKeyDown);
return () => document.removeEventListener("keydown", onKeyDown);
}, [onKeyDown]);
const { isMobile, isDesktop } = useWindowSize();
return (
<AnimatePresence>
{showModal && (
<>
{isMobile && (
<Leaflet setShow={setShowModal} showBlur={showBlur}>
{children}
</Leaflet>
)}
{isDesktop && showBlur && (
<>
<motion.div
ref={desktopModalRef}
key="desktop-modal"
className="fixed inset-0 z-[1000] min-h-screen flex-col items-center justify-center md:flex"
initial={{ scale: 0.95 }}
animate={{ scale: 1 }}
exit={{ scale: 0.95 }}
onMouseDown={(e) => {
if (desktopModalRef.current === e.target) {
setShowModal(false);
}
}}
>
{children}
</motion.div>
<motion.div
key="desktop-backdrop"
className="fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setShowModal(false)}
/>
</>
)}
</>
)}
</AnimatePresence>
);
}

View File

@@ -0,0 +1,15 @@
import "@/styles/placeholder.css";
export default function PlaceHolder() {
return (
<div className="placeholder">
<label className="avatar"></label>
<label className="info">
<span className="info-1"></span>
<span className="info-2"></span>
</label>
<div className="content-1"></div>
<div className="content-2"></div>
</div>
);
}

View File

@@ -0,0 +1,50 @@
"use client";
import { Dispatch, SetStateAction, ReactNode, useRef } from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover";
import useWindowSize from "@/lib/hooks/use-window-size";
import Leaflet from "./leaflet";
export default function Popover({
children,
content,
align = "center",
openPopover,
setOpenPopover,
}: {
children: ReactNode;
content: ReactNode | string;
align?: "center" | "start" | "end";
openPopover: boolean;
setOpenPopover: Dispatch<SetStateAction<boolean>>;
}) {
const { isMobile, isDesktop } = useWindowSize();
if (!isMobile && !isDesktop) return <>{children}</>;
return (
<>
{isMobile && children}
{openPopover && isMobile && (
<Leaflet setShow={setOpenPopover} showBlur={true}>
{content}
</Leaflet>
)}
{isDesktop && (
<PopoverPrimitive.Root
open={openPopover}
onOpenChange={(isOpen) => setOpenPopover(isOpen)}
>
<PopoverPrimitive.Trigger className="inline-flex" asChild>
{children}
</PopoverPrimitive.Trigger>
<PopoverPrimitive.Content
sideOffset={4}
align={align}
className="z-20 animate-slide-up-fade items-center rounded-md border border-gray-200 bg-white drop-shadow-lg"
>
{content}
</PopoverPrimitive.Content>
</PopoverPrimitive.Root>
)}
</>
);
}

View File

@@ -0,0 +1,71 @@
"use client";
import { ReactNode, useState } from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import useWindowSize from "@/lib/hooks/use-window-size";
import Leaflet from "./leaflet";
export default function Tooltip({
children,
content,
fullWidth,
}: {
children: ReactNode;
content: ReactNode | string;
fullWidth?: boolean;
}) {
const [openTooltip, setOpenTooltip] = useState(false);
const { isMobile, isDesktop } = useWindowSize();
return (
<>
{/* {isMobile && (
<button
type="button"
className={`${fullWidth ? "w-full" : "inline-flex"}`}
onClick={() => setOpenTooltip(true)}
>
{children}
</button>
)} */}
{/* {openTooltip && isMobile && (
<Leaflet setShow={setOpenTooltip} showBlur={true}>
{typeof content === "string" ? (
<span className="flex min-h-[150px] w-full items-center justify-center bg-white px-10 text-center text-sm text-gray-700">
{content}
</span>
) : (
content
)}
</Leaflet>
)} */}
{
<TooltipPrimitive.Provider delayDuration={100}>
<TooltipPrimitive.Root>
<TooltipPrimitive.Trigger className="" asChild>
{children}
</TooltipPrimitive.Trigger>
<TooltipPrimitive.Content
sideOffset={4}
side="top"
className="animate-slide-up-fade z-30 items-center overflow-hidden rounded-md border border-gray-200 bg-white drop-shadow-lg"
>
<TooltipPrimitive.Arrow className="fill-current text-white" />
{typeof content === "string" ? (
<div className="p-5">
<span className="block max-w-xs text-center text-sm text-gray-700">
{content}
</span>
</div>
) : (
content
)}
<TooltipPrimitive.Arrow className="fill-current text-white" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Root>
</TooltipPrimitive.Provider>
}
</>
);
}