mirror of
https://github.com/neosubhamoy/neodlp-website.git
synced 2026-02-04 10:02:22 +05:30
(chore): initial MVP release
This commit is contained in:
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# build output
|
||||
dist/
|
||||
.netlify/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Subhamoy Biswas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# NeoDLP Website
|
||||
|
||||
Official Website of NeoDLP (Neo Downloader Plus)
|
||||
|
||||
[](https://github.com/neosubhamoy/neodlp-website)
|
||||
[](https://github.com/neosubhamoy/neodlp-website)
|
||||
[](https://github.com/neosubhamoy/neodlp-website)
|
||||
|
||||
> **🥰 Liked this project? Please consider giving it a Star (🌟) on github to show us your appreciation and help the algorythm recommend this project to even more awesome people like you!**
|
||||
|
||||
### ⚡ Technologies Used
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 🛠️ Contributing / Building from Source
|
||||
|
||||
Want to be part of this? Feel free to contribute...!! Pull Requests are always welcome...!! (^_^) Follow these simple steps to start building:
|
||||
|
||||
* Make sure to install Node.js, Git before proceeding.
|
||||
1. Fork this repo in your github account.
|
||||
2. Git clone the forked repo in your local machine.
|
||||
3. Install Node.js dependencies: `npm install`
|
||||
4. Run development / build process
|
||||
```code
|
||||
npm run dev # for development
|
||||
npm run build # for production build
|
||||
```
|
||||
5. Do the changes, Send a Pull Request with proper Description (NOTE: Pull Requests Without Proper Description will be Rejected)
|
||||
|
||||
**⭕ Noticed any Bugs or Want to give us some suggetions? Always feel free to open a GitHub Issue. We would love to hear from you...!!**
|
||||
|
||||
### 📝 License
|
||||
|
||||
NeoDLP Website is Licensed under the [MIT license](https://github.com/neosubhamoy/neodlp-website/blob/main/LICENSE). Anyone can view, modify, use (personal and commercial) or distribute it's sources without any attribution and extra permissions.
|
||||
17
astro.config.mjs
Normal file
17
astro.config.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import react from '@astrojs/react';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
import netlify from '@astrojs/netlify';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
plugins: [tailwindcss()]
|
||||
},
|
||||
integrations: [react(), sitemap()],
|
||||
adapter: netlify(),
|
||||
site: 'https://neodlp.neosubhamoy.com',
|
||||
output: 'server',
|
||||
});
|
||||
21
components.json
Normal file
21
components.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "src/styles/global.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
12050
package-lock.json
generated
Normal file
12050
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
package.json
Normal file
40
package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "neodlp-website",
|
||||
"type": "module",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^4.2.6",
|
||||
"@astrojs/netlify": "^6.3.2",
|
||||
"@astrojs/react": "^4.2.7",
|
||||
"@astrojs/sitemap": "^3.4.0",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.12",
|
||||
"@radix-ui/react-separator": "^1.1.4",
|
||||
"@radix-ui/react-slot": "^1.2.0",
|
||||
"@tailwindcss/vite": "^4.1.3",
|
||||
"@types/canvas-confetti": "^1.9.0",
|
||||
"@types/react": "^19.1.2",
|
||||
"@types/react-dom": "^19.1.3",
|
||||
"astro": "^5.7.10",
|
||||
"astro-loading-indicator": "^0.7.0",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.506.0",
|
||||
"motion": "^12.9.4",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"sonner": "^2.0.3",
|
||||
"tailwind-merge": "^3.2.0",
|
||||
"tailwindcss": "^4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tw-animate-css": "^1.2.8"
|
||||
}
|
||||
}
|
||||
BIN
public/neodlp-extension.webp
Normal file
BIN
public/neodlp-extension.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
BIN
public/neodlp-library.webp
Normal file
BIN
public/neodlp-library.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
public/neodlp-mockup.webp
Normal file
BIN
public/neodlp-mockup.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
11
public/neodlp.svg
Normal file
11
public/neodlp.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1024" height="1024" rx="200" fill="url(#paint0_linear_10_2)"/>
|
||||
<path d="M529.252 811.098C519.472 820.96 503.528 820.96 493.748 811.098L256.265 571.603C240.619 555.824 251.796 529 274.017 529H748.983C771.204 529 782.381 555.824 766.735 571.603L529.252 811.098Z" fill="#FAFAFA"/>
|
||||
<rect x="355" y="222" width="313" height="346" rx="25" fill="#FAFAFA"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_10_2" x1="129.5" y1="148.5" x2="921" y2="863" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4444FF"/>
|
||||
<stop offset="1" stop-color="#FF43D0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 688 B |
4
public/robots.txt
Normal file
4
public/robots.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://neodlp.neosubhamoy.com/sitemap-index.xml
|
||||
204
src/components/AllDowloadsSection.tsx
Normal file
204
src/components/AllDowloadsSection.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import { type LatestRelease } from "@/types/release";
|
||||
import { SlidingButton } from "@/components/ui/sliding-button";
|
||||
import { Download } from "lucide-react";
|
||||
import { CommandSnippet } from "@/components/ui/command-snippet";
|
||||
|
||||
export default function AllDownloadsSection({ release }: { release: LatestRelease }) {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 pt-14 pb-4">
|
||||
<h1 className="text-4xl font-bold">Download NeoDLP</h1>
|
||||
<p className="lg:text-lg text-muted-foreground">Choose your platform to download the latest version of NeoDLP</p>
|
||||
<p className="mt-4 text-xl font-semibold">Latest version (v{release.version})</p>
|
||||
<p className="text-sm text-muted-foreground">Released at: {new Date(release.pub_date).toLocaleString()} - <a className="hover:underline" href="https://github.com/neosubhamoy/neodlp/releases/latest" target="_blank">✨ Read Changelog</a></p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 justify-center items-center gap-4 mt-10">
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["windows-x86_64"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z"/>
|
||||
</svg>
|
||||
Download for Windows
|
||||
</span>
|
||||
<span className="text-xs">(x64) EXE Installer</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["windows-x86_64-msi"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z"/>
|
||||
</svg>
|
||||
Download for Windows
|
||||
</span>
|
||||
<span className="text-xs">(x64) MSI Installer</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-x86_64-dmg"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(x64) DMG Installer</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-x86_64"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(x64) APP Bundle</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-aarch64-dmg"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(ARM64) DMG Installer</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-aarch64"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(ARM64) APP Bundle</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["linux-x86_64-deb"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"/>
|
||||
</svg>
|
||||
Download for Linux
|
||||
</span>
|
||||
<span className="text-xs">(x64) DEB Package</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["linux-x86_64-rpm"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"/>
|
||||
</svg>
|
||||
Download for Linux
|
||||
</span>
|
||||
<span className="text-xs">(x64) RPM Package</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["linux-x86_64-aur"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"/>
|
||||
</svg>
|
||||
Download for Linux
|
||||
</span>
|
||||
<span className="text-xs">(x64) AUR Snapshot</span>
|
||||
</SlidingButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 mt-10">
|
||||
<p className="mt-4 text-xl font-semibold">Install via Command Line</p>
|
||||
<p className="text-sm text-muted-foreground">Install NeoDLP directly via command line by running the command below based on your platform</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center gap-4 mt-12">
|
||||
<CommandSnippet title="Windows (WinGet)">
|
||||
winget install neodlp
|
||||
</CommandSnippet>
|
||||
<CommandSnippet title="Arch Linux (AUR)">
|
||||
yay -S neodlp
|
||||
</CommandSnippet>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
46
src/components/DmcaNoticeSection.tsx
Normal file
46
src/components/DmcaNoticeSection.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
export default function DmcaNoticeSection() {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 pt-14 pb-4">
|
||||
<h1 className="text-4xl font-bold">DMCA Notice</h1>
|
||||
<p className="lg:text-lg text-muted-foreground">Updated: 5/12/2025</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-5 mt-10">
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<p>If you require any more information or have any questions regarding this site's disclaimer, please feel free to contact us by email at <a href="mailto:support@neodlp.neosubhamoy.com">support@neodlp.neosubhamoy.com</a>.</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Disclaimers for NeoDLP Website</h2>
|
||||
<p>All the information on this website - https://neodlp.neosubhamoy.com - is published in good faith and for general information purpose only. NeoDLP Website does not make any warranties about the completeness, reliability and accuracy of this information. Any action you take upon the information you find on this website (NeoDLP Website), is strictly at your own risk. NeoDLP Website will not be liable for any losses and/or damages in connection with the use of our website.</p>
|
||||
<p>From our website, you can visit other websites by following hyperlinks to such external sites. While we strive to provide only quality links to useful and ethical websites, we have no control over the content and nature of these sites. These links to other websites do not imply a recommendation for all the content found on these sites. Site owners and content may change without notice and may occur before we have the opportunity to remove a link which may have gone 'bad'.</p>
|
||||
<p>Please be also aware that when you leave our website, other sites may have different privacy policies and terms which are beyond our control. Please be sure to check the Privacy Policies of these sites as well as their "Terms of Service" before engaging in any business or uploading any information.</p>
|
||||
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">DMCA Policy</h2>
|
||||
<p>This Digital Millennium Copyright Act policy (“Policy”) applies to the <a href="https://neodlp.neosubhamoy.com">neodlp.neosubhamoy.com</a> website (“Website” or “Service”) and any of its related products and services (collectively, “Services”) and outlines how this Website operator (“Operator”, “we”, “us” or “our”) addresses copyright infringement notifications and how you (“you” or “your”) may submit a copyright infringement complaint.</p>
|
||||
<p>Protection of intellectual property is of utmost importance to us and we ask our users and their authorized agents to do the same. It is our policy to expeditiously respond to clear notifications of alleged copyright infringement that comply with the United States Digital Millennium Copyright Act (“DMCA”) of 1998, the text of which can be found at the U.S. Copyright Office <a href="https://www.copyright.gov">website</a>.</p>
|
||||
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">What to consider before submitting a copyright complaint</h2>
|
||||
<p>Please note that if you are unsure whether the material you are reporting is in fact infringing, you may wish to contact an attorney before filing a notification with us.</p>
|
||||
<p>The DMCA requires you to provide your personal information in the copyright infringement notification. If you are concerned about the privacy of your personal information, you may wish to <a href="https://www.copyrighted.com/professional-takedowns">hire an agent</a> to report infringing material for you.</p>
|
||||
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Notifications of infringement</h2>
|
||||
<p>If you are a copyright owner or an agent thereof, and you believe that any material available on our Services infringes your copyrights, then you may submit a written copyright infringement notification (“Notification”) using the contact details below pursuant to the DMCA. All such Notifications must comply with the DMCA requirements.</p>
|
||||
<p>Filing a DMCA complaint is the start of a pre-defined legal process. Your complaint will be reviewed for accuracy, validity, and completeness. If your complaint has satisfied these requirements, our response may include the removal or restriction of access to allegedly infringing material.</p>
|
||||
<p>If we remove or restrict access to materials or terminate an account in response to a Notification of alleged infringement, we will make a good faith effort to contact the affected user with information concerning the removal or restriction of access.</p>
|
||||
<p>Notwithstanding anything to the contrary contained in any portion of this Policy, the Operator reserves the right to take no action upon receipt of a DMCA copyright infringement notification if it fails to comply with all the requirements of the DMCA for such notifications.</p>
|
||||
<p>The process described in this Policy does not limit our ability to pursue any other remedies we may have to address suspected infringement.</p>
|
||||
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Changes and amendments</h2>
|
||||
<p>We reserve the right to modify this Policy or its terms related to the Website and Services at any time at our discretion. When we do, we will revise the updated date at the top of this page. We may also provide notice to you in other ways at our discretion, such as through the contact information you have provided.</p>
|
||||
<p>An updated version of this Policy will be effective immediately upon the posting of the revised Policy unless otherwise specified. Your continued use of the Website and Services after the effective date of the revised Policy (or such other act specified at that time) will constitute your consent to those changes.</p>
|
||||
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Reporting copyright infringement</h2>
|
||||
<p>If you would like to notify us of the infringing material or activity, we encourage you to contact us using the details below:</p>
|
||||
<p><a href="mailto:support@neodlp.neosubhamoy.com">support@neodlp.neosubhamoy.com</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
85
src/components/FeaturesSection.tsx
Normal file
85
src/components/FeaturesSection.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { GlowingEffect } from "@/components/ui/glowing-effect";
|
||||
import { Box, Globe, HeartHandshake, Lock, Search, Settings, Sparkles, Video } from "lucide-react";
|
||||
|
||||
interface GridItemProps {
|
||||
area: string;
|
||||
icon: React.ReactNode;
|
||||
title: string;
|
||||
description: React.ReactNode;
|
||||
}
|
||||
|
||||
const GridItem = ({ area, icon, title, description }: GridItemProps) => {
|
||||
return (
|
||||
<li className={`min-h-[14rem] list-none ${area}`}>
|
||||
<div className="relative h-full rounded-2xl border p-2 md:rounded-3xl md:p-3">
|
||||
<GlowingEffect
|
||||
spread={40}
|
||||
glow={true}
|
||||
disabled={false}
|
||||
proximity={64}
|
||||
inactiveZone={0.01}
|
||||
/>
|
||||
<div className="border-0.75 relative flex h-full flex-col justify-between gap-6 overflow-hidden rounded-xl p-6 md:p-6 dark:shadow-[0px_0px_27px_0px_#2D2D2D]">
|
||||
<div className="relative flex flex-1 flex-col justify-between gap-3">
|
||||
<div className="w-fit rounded-lg border border-gray-600 p-2">
|
||||
{icon}
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<h3 className="-tracking-4 pt-0.5 font-sans text-xl/[1.375rem] font-semibold text-balance text-black md:text-2xl/[1.875rem] dark:text-white">
|
||||
{title}
|
||||
</h3>
|
||||
<h2 className="font-sans text-sm/[1.125rem] text-black md:text-base/[1.375rem] dark:text-neutral-400 [&_b]:md:font-semibold [&_strong]:md:font-semibold">
|
||||
{description}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default function FeaturesSection() {
|
||||
return (
|
||||
<section className="flex flex-col w-full" id="features">
|
||||
<div className="flex flex-col relative items-center">
|
||||
<div className="flex flex-col items-center justify-center gap-2 pt-40 pb-16">
|
||||
<h3 className="text-3xl lg:text-4xl font-bold">Features</h3>
|
||||
<p className="text-sm lg:text-lg font-semibold text-muted-foreground">Take a look on NeoDLP's features and offerings</p>
|
||||
</div>
|
||||
<ul className="grid grid-cols-1 grid-rows-none gap-4 md:grid-cols-12 md:grid-rows-3 lg:gap-4 xl:max-h-[34rem] xl:grid-rows-2 px-4 max-w-7xl">
|
||||
<GridItem
|
||||
area="md:[grid-area:1/1/2/7] xl:[grid-area:1/1/2/5]"
|
||||
icon={<Video className="h-4 w-4 text-black dark:text-neutral-400" />}
|
||||
title="Video and Playlist Download"
|
||||
description="Download videos and playlists from mostly any site exists in the planet."
|
||||
/>
|
||||
<GridItem
|
||||
area="md:[grid-area:1/7/2/13] xl:[grid-area:2/1/3/5]"
|
||||
icon={<Settings className="h-4 w-4 text-black dark:text-neutral-400" />}
|
||||
title="Highly Customizable"
|
||||
description="Customize NeoDLP to your liking with a wide range of options and settings."
|
||||
/>
|
||||
<GridItem
|
||||
area="md:[grid-area:2/1/3/7] xl:[grid-area:1/5/3/8]"
|
||||
icon={<HeartHandshake className="h-4 w-4 text-black dark:text-neutral-400" />}
|
||||
title="Fully Free and Open Sourced"
|
||||
description="NeoDLP is built on top of 100% Free and Open Source software components. No strings attached."
|
||||
/>
|
||||
<GridItem
|
||||
area="md:[grid-area:2/7/3/13] xl:[grid-area:1/8/2/13]"
|
||||
icon={<Sparkles className="h-4 w-4 text-black dark:text-neutral-400" />}
|
||||
title="Lightweight, Fast and Flexible"
|
||||
description="NeoDLP is built with performance in mind. It's lightweight, fast and works on any platform. Built with Tauri."
|
||||
/>
|
||||
<GridItem
|
||||
area="md:[grid-area:3/1/4/13] xl:[grid-area:2/8/3/13]"
|
||||
icon={<Globe className="h-4 w-4 text-black dark:text-neutral-400" />}
|
||||
title="Browser Integration"
|
||||
description="Integrate NeoDLP with your favourite browsers like Chrome, Firefox to download videos from any website with ease."
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
97
src/components/GetExtensionSection.tsx
Normal file
97
src/components/GetExtensionSection.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import type { LatestExtensionRelease } from "@/types/release";
|
||||
import { SlidingButton } from "@/components/ui/sliding-button";
|
||||
import { ArrowRight, Download } from "lucide-react";
|
||||
|
||||
|
||||
export default function GetExtensionSection({ release }: { release: LatestExtensionRelease }) {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 pt-14 pb-4">
|
||||
<h1 className="text-4xl font-bold">Get NeoDLP Extension</h1>
|
||||
<p className="lg:text-lg text-muted-foreground">Choose your browser to get the latest version of NeoDLP Extension</p>
|
||||
<p className="mt-4 text-xl font-semibold">Latest version (v{release.version})</p>
|
||||
<p className="text-sm text-muted-foreground"><a className="hover:underline" href="https://github.com/neosubhamoy/neodlp-extension/releases/latest" target="_blank">✨ Read Changelog</a></p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 justify-center items-center gap-4 mt-10">
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<ArrowRight className="size-4" />
|
||||
<span>Get Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={`#`}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M0 256C0 209.4 12.5 165.6 34.3 127.1L144.1 318.3C166 357.5 207.9 384 256 384C270.3 384 283.1 381.7 296.8 377.4L220.5 509.6C95.9 492.3 0 385.3 0 256zM365.1 321.6C377.4 302.4 384 279.1 384 256C384 217.8 367.2 183.5 340.7 160H493.4C505.4 189.6 512 222.1 512 256C512 397.4 397.4 511.1 256 512L365.1 321.6zM477.8 128H256C193.1 128 142.3 172.1 130.5 230.7L54.2 98.5C101 38.5 174 0 256 0C350.8 0 433.5 51.5 477.8 128V128zM168 256C168 207.4 207.4 168 256 168C304.6 168 344 207.4 344 256C344 304.6 304.6 344 256 344C207.4 344 168 304.6 168 256z"/>
|
||||
</svg>
|
||||
Get Chrome Extension
|
||||
</span>
|
||||
<span className="text-xs">(CRX) Chrome Web Store</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<ArrowRight className="size-4" />
|
||||
<span>Get Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={`#`}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M130.2 127.5C130.4 127.6 130.3 127.6 130.2 127.5V127.5zM481.6 172.9C471 147.4 449.6 119.9 432.7 111.2C446.4 138.1 454.4 165 457.4 185.2C457.4 185.3 457.4 185.4 457.5 185.6C429.9 116.8 383.1 89.1 344.9 28.7C329.9 5.1 334 3.5 331.8 4.1L331.7 4.2C285 30.1 256.4 82.5 249.1 126.9C232.5 127.8 216.2 131.9 201.2 139C199.8 139.6 198.7 140.7 198.1 142C197.4 143.4 197.2 144.9 197.5 146.3C197.7 147.2 198.1 148 198.6 148.6C199.1 149.3 199.8 149.9 200.5 150.3C201.3 150.7 202.1 151 203 151.1C203.8 151.1 204.7 151 205.5 150.8L206 150.6C221.5 143.3 238.4 139.4 255.5 139.2C318.4 138.7 352.7 183.3 363.2 201.5C350.2 192.4 326.8 183.3 304.3 187.2C392.1 231.1 368.5 381.8 247 376.4C187.5 373.8 149.9 325.5 146.4 285.6C146.4 285.6 157.7 243.7 227 243.7C234.5 243.7 256 222.8 256.4 216.7C256.3 214.7 213.8 197.8 197.3 181.5C188.4 172.8 184.2 168.6 180.5 165.5C178.5 163.8 176.4 162.2 174.2 160.7C168.6 141.2 168.4 120.6 173.5 101.1C148.5 112.5 129 130.5 114.8 146.4H114.7C105 134.2 105.7 93.8 106.3 85.3C106.1 84.8 99 89 98.1 89.7C89.5 95.7 81.6 102.6 74.3 110.1C58 126.7 30.1 160.2 18.8 211.3C14.2 231.7 12 255.7 12 263.6C12 398.3 121.2 507.5 255.9 507.5C376.6 507.5 478.9 420.3 496.4 304.9C507.9 228.2 481.6 173.8 481.6 172.9z"/>
|
||||
</svg>
|
||||
Get Firefox Addon
|
||||
</span>
|
||||
<span className="text-xs">(XPI) Mozilla Addons Store</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.browsers["chrome"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M0 256C0 209.4 12.5 165.6 34.3 127.1L144.1 318.3C166 357.5 207.9 384 256 384C270.3 384 283.1 381.7 296.8 377.4L220.5 509.6C95.9 492.3 0 385.3 0 256zM365.1 321.6C377.4 302.4 384 279.1 384 256C384 217.8 367.2 183.5 340.7 160H493.4C505.4 189.6 512 222.1 512 256C512 397.4 397.4 511.1 256 512L365.1 321.6zM477.8 128H256C193.1 128 142.3 172.1 130.5 230.7L54.2 98.5C101 38.5 174 0 256 0C350.8 0 433.5 51.5 477.8 128V128zM168 256C168 207.4 207.4 168 256 168C304.6 168 344 207.4 344 256C344 304.6 304.6 344 256 344C207.4 344 168 304.6 168 256z"/>
|
||||
</svg>
|
||||
Download for Chrome
|
||||
</span>
|
||||
<span className="text-xs">(ZIP) Unpackable Archive</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.browsers["firefox"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M130.2 127.5C130.4 127.6 130.3 127.6 130.2 127.5V127.5zM481.6 172.9C471 147.4 449.6 119.9 432.7 111.2C446.4 138.1 454.4 165 457.4 185.2C457.4 185.3 457.4 185.4 457.5 185.6C429.9 116.8 383.1 89.1 344.9 28.7C329.9 5.1 334 3.5 331.8 4.1L331.7 4.2C285 30.1 256.4 82.5 249.1 126.9C232.5 127.8 216.2 131.9 201.2 139C199.8 139.6 198.7 140.7 198.1 142C197.4 143.4 197.2 144.9 197.5 146.3C197.7 147.2 198.1 148 198.6 148.6C199.1 149.3 199.8 149.9 200.5 150.3C201.3 150.7 202.1 151 203 151.1C203.8 151.1 204.7 151 205.5 150.8L206 150.6C221.5 143.3 238.4 139.4 255.5 139.2C318.4 138.7 352.7 183.3 363.2 201.5C350.2 192.4 326.8 183.3 304.3 187.2C392.1 231.1 368.5 381.8 247 376.4C187.5 373.8 149.9 325.5 146.4 285.6C146.4 285.6 157.7 243.7 227 243.7C234.5 243.7 256 222.8 256.4 216.7C256.3 214.7 213.8 197.8 197.3 181.5C188.4 172.8 184.2 168.6 180.5 165.5C178.5 163.8 176.4 162.2 174.2 160.7C168.6 141.2 168.4 120.6 173.5 101.1C148.5 112.5 129 130.5 114.8 146.4H114.7C105 134.2 105.7 93.8 106.3 85.3C106.1 84.8 99 89 98.1 89.7C89.5 95.7 81.6 102.6 74.3 110.1C58 126.7 30.1 160.2 18.8 211.3C14.2 231.7 12 255.7 12 263.6C12 398.3 121.2 507.5 255.9 507.5C376.6 507.5 478.9 420.3 496.4 304.9C507.9 228.2 481.6 173.8 481.6 172.9z"/>
|
||||
</svg>
|
||||
Download for Firefox
|
||||
</span>
|
||||
<span className="text-xs">(ZIP) Unpackable Archive</span>
|
||||
</SlidingButton>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
44
src/components/HeroSection.tsx
Normal file
44
src/components/HeroSection.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ContainerScroll } from "@/components/ui/container-scroll-animation";
|
||||
import { type LatestRelease } from "@/types/release";
|
||||
|
||||
export default function HeroSection({ release }: { release: LatestRelease }) {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen relative">
|
||||
<div
|
||||
className={cn(
|
||||
"absolute inset-0",
|
||||
"[background-size:20px_20px]",
|
||||
"[background-image:linear-gradient(to_right,#e4e4e7_1px,transparent_1px),linear-gradient(to_bottom,#e4e4e7_1px,transparent_1px)]",
|
||||
"dark:[background-image:linear-gradient(to_right,#262626_1px,transparent_1px),linear-gradient(to_bottom,#262626_1px,transparent_1px)]",
|
||||
)}
|
||||
/>
|
||||
{/* Radial gradient for the container to give a faded look */}
|
||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-white [mask-image:radial-gradient(ellipse_at_center,transparent_20%,black)] dark:bg-black"></div>
|
||||
<div className="flex flex-col relative">
|
||||
<ContainerScroll
|
||||
titleComponent={
|
||||
<>
|
||||
<h1 className="text-4xl font-semibold text-black dark:text-white">
|
||||
The next-gen truely cross-platform <br />
|
||||
<span className="text-4xl md:text-[6rem] font-bold mt-1 leading-none">
|
||||
Video Downloader
|
||||
</span>
|
||||
</h1>
|
||||
</>
|
||||
}
|
||||
release={release}
|
||||
>
|
||||
<img
|
||||
src="/neodlp-mockup.webp"
|
||||
alt="neodlp-mockup"
|
||||
height={744}
|
||||
width={1323}
|
||||
className="mx-auto rounded-2xl h-full object-left-top"
|
||||
draggable={false}
|
||||
/>
|
||||
</ContainerScroll>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
58
src/components/HighlightSection.tsx
Normal file
58
src/components/HighlightSection.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { WobbleCard } from "@/components/ui/wobble-card";
|
||||
|
||||
|
||||
export default function HighlightSection() {
|
||||
return (
|
||||
<section className="flex flex-col w-full">
|
||||
<div className="flex flex-col relative">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 max-w-7xl mx-auto w-full px-4">
|
||||
<WobbleCard
|
||||
containerClassName="col-span-1 lg:col-span-2 h-full bg-pink-800 min-h-[500px] lg:min-h-[300px]"
|
||||
className=""
|
||||
>
|
||||
<div className="max-w-xs">
|
||||
<h2 className="text-left text-balance text-base md:text-xl lg:text-3xl font-semibold tracking-[-0.015em] text-white">
|
||||
Mange all your downloads in one place
|
||||
</h2>
|
||||
<p className="mt-4 text-left text-base/6 text-neutral-200">
|
||||
NeoDLP Library helps you manage and organize all your downloads in one place for better productivity.
|
||||
</p>
|
||||
</div>
|
||||
<img
|
||||
src="/neodlp-library.webp"
|
||||
width={500}
|
||||
height={500}
|
||||
alt="neodlp-library"
|
||||
className="absolute -right-4 lg:-right-[30%] -bottom-10 object-contain rounded-2xl"
|
||||
/>
|
||||
</WobbleCard>
|
||||
<WobbleCard containerClassName="col-span-1 min-h-[300px]">
|
||||
<h2 className="max-w-80 text-left text-balance text-base md:text-xl lg:text-3xl font-semibold tracking-[-0.015em] text-white">
|
||||
Download from thousands of sites
|
||||
</h2>
|
||||
<p className="mt-4 max-w-[26rem] text-left text-base/6 text-neutral-200">
|
||||
NeoDLP supports downloading from thousands of sites like YouTube, Facebook, Instagram, X and many more! Download videos from any site on the fly.
|
||||
</p>
|
||||
</WobbleCard>
|
||||
<WobbleCard containerClassName="col-span-1 lg:col-span-3 bg-blue-900 min-h-[500px] lg:min-h-[600px] xl:min-h-[300px]">
|
||||
<div className="max-w-sm">
|
||||
<h2 className="max-w-sm md:max-w-lg text-left text-balance text-base md:text-xl lg:text-3xl font-semibold tracking-[-0.015em] text-white">
|
||||
Seamlessly Integrate with your favourite browsers
|
||||
</h2>
|
||||
<p className="mt-4 max-w-[26rem] text-left text-base/6 text-neutral-200">
|
||||
Integrate NeoDLP with your favourite browsers like Chrome, Firefox to download videos from any website with ease! Add NeoDLP Extension to get started.
|
||||
</p>
|
||||
</div>
|
||||
<img
|
||||
src="/neodlp-extension.webp"
|
||||
width={500}
|
||||
height={500}
|
||||
alt="neodlp-extension"
|
||||
className="absolute -right-10 md:-right-[30%] lg:-right-[10%] -bottom-10 object-contain rounded-2xl"
|
||||
/>
|
||||
</WobbleCard>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
52
src/components/ModeToggle.tsx
Normal file
52
src/components/ModeToggle.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as React from "react"
|
||||
import { Moon, Sun } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
|
||||
export function ModeToggle() {
|
||||
const [theme, setThemeState] = React.useState<
|
||||
"theme-light" | "dark" | "system"
|
||||
>("theme-light")
|
||||
|
||||
React.useEffect(() => {
|
||||
const isDarkMode = document.documentElement.classList.contains("dark")
|
||||
setThemeState(isDarkMode ? "dark" : "theme-light")
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
const isDark =
|
||||
theme === "dark" ||
|
||||
(theme === "system" &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
document.documentElement.classList[isDark ? "add" : "remove"]("dark")
|
||||
}, [theme])
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="icon">
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="z-60">
|
||||
<DropdownMenuItem onClick={() => setThemeState("theme-light")}>
|
||||
Light
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setThemeState("dark")}>
|
||||
Dark
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setThemeState("system")}>
|
||||
System
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
230
src/components/PrivacyPolicySection.tsx
Normal file
230
src/components/PrivacyPolicySection.tsx
Normal file
@@ -0,0 +1,230 @@
|
||||
|
||||
|
||||
export default function PrivacyPolicySection() {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 pt-14 pb-4">
|
||||
<h1 className="text-4xl font-bold">Privacy Policy</h1>
|
||||
<p className="lg:text-lg text-muted-foreground">Updated: 5/12/2025</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-5 mt-10">
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<p>
|
||||
At NeoDLP Website, accessible from https://neodlp.neosubhamoy.com,
|
||||
one of our main priorities is the privacy of our visitors. This Privacy
|
||||
Policy document contains types of information that is collected and
|
||||
recorded by NeoDLP Website and how we use it.
|
||||
</p>
|
||||
<p>
|
||||
If you have additional questions or require more information about our
|
||||
Privacy Policy, do not hesitate to contact us at support@neodlp.neosubhamoy.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Consent</h2>
|
||||
<p>
|
||||
By using our website, you hereby consent to our Privacy Policy and agree
|
||||
to its terms.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Information we collect</h2>
|
||||
<p>
|
||||
The personal information that you are asked to provide, and the reasons
|
||||
why you are asked to provide it, will be made clear to you at the point
|
||||
we ask you to provide your personal information.
|
||||
</p>
|
||||
<p>
|
||||
If you contact us directly, we may receive additional information about
|
||||
you such as your name, email address, phone number, the contents of the
|
||||
message and/or attachments you may send us, and any other information
|
||||
you may choose to provide.
|
||||
</p>
|
||||
<p>
|
||||
When you register for an Account, we may ask for your contact
|
||||
information, including items such as name, company name, address, email
|
||||
address, and telephone number.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">How we use your information</h2>
|
||||
<p>We use the information we collect in various ways, including to:</p>
|
||||
<ul className="">
|
||||
<li>• Provide, operate, and maintain our website</li>
|
||||
<li>• Improve, personalize, and expand our website</li>
|
||||
<li>• Understand and analyze how you use our website</li>
|
||||
<li>• Develop new products, services, features, and functionality</li>
|
||||
<li>
|
||||
• Communicate with you, either directly or through one of our partners,
|
||||
including for customer service, to provide you with updates and other
|
||||
information relating to the website, and for marketing and promotional
|
||||
purposes
|
||||
</li>
|
||||
<li>• Send you emails</li>
|
||||
<li>• Find and prevent fraud</li>
|
||||
</ul>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Log Files</h2>
|
||||
<p>
|
||||
NeoDLP Website follows a standard procedure of using log
|
||||
files. These files log visitors when they visit websites. All hosting
|
||||
companies do this and a part of hosting services' analytics. The
|
||||
information collected by log files include internet protocol (IP)
|
||||
addresses, browser type, Internet Service Provider (ISP), date and time
|
||||
stamp, referring/exit pages, and possibly the number of clicks. These
|
||||
are not linked to any information that is personally identifiable. The
|
||||
purpose of the information is for analyzing trends, administering the
|
||||
site, tracking users' movement on the website, and gathering demographic
|
||||
information.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Cookies and Web Beacons</h2>
|
||||
<p>
|
||||
Like any other website, NeoDLP Website uses 'cookies'. These
|
||||
cookies are used to store information including visitors' preferences,
|
||||
and the pages on the website that the visitor accessed or visited. The
|
||||
information is used to optimize the users' experience by customizing our
|
||||
web page content based on visitors' browser type and/or other
|
||||
information.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Google DoubleClick DART Cookie</h2>
|
||||
<p>
|
||||
Google is one of a third-party vendor on our site. It also uses cookies,
|
||||
known as DART cookies, to serve ads to our site visitors based upon
|
||||
their visit to www.website.com and other sites on the internet. However,
|
||||
visitors may choose to decline the use of DART cookies by visiting the
|
||||
Google ad and content network Privacy Policy at the following URL –
|
||||
<a target="_blank" href="https://policies.google.com/technologies/ads"
|
||||
>https://policies.google.com/technologies/ads</a
|
||||
>
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Our Advertising Partners</h2>
|
||||
<p>
|
||||
Some of advertisers on our site may use cookies and web beacons. Our
|
||||
advertising partners are listed below. Each of our advertising partners
|
||||
has their own Privacy Policy for their policies on user data. For easier
|
||||
access, we hyperlinked to their Privacy Policies below.
|
||||
</p>
|
||||
<ul className="">
|
||||
<li>
|
||||
<p>• Google</p>
|
||||
<p>
|
||||
<a target="_blank" href="https://policies.google.com/technologies/ads"
|
||||
>https://policies.google.com/technologies/ads</a
|
||||
>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Advertising Partners Privacy Policies</h2>
|
||||
<p>
|
||||
You may consult this list to find the Privacy Policy for each of the
|
||||
advertising partners of NeoDLP Website.
|
||||
</p>
|
||||
<p>
|
||||
Third-party ad servers or ad networks uses technologies like cookies,
|
||||
JavaScript, or Web Beacons that are used in their respective
|
||||
advertisements and links that appear on NeoDLP Website, which
|
||||
are sent directly to users' browser. They automatically receive your IP
|
||||
address when this occurs. These technologies are used to measure the
|
||||
effectiveness of their advertising campaigns and/or to personalize the
|
||||
advertising content that you see on websites that you visit.
|
||||
</p>
|
||||
<p>
|
||||
Note that NeoDLP Website has no access to or control over
|
||||
these cookies that are used by third-party advertisers.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Third Party Privacy Policies</h2>
|
||||
<p>
|
||||
NeoDLP Website's Privacy Policy does not apply to other
|
||||
advertisers or websites. Thus, we are advising you to consult the
|
||||
respective Privacy Policies of these third-party ad servers for more
|
||||
detailed information. It may include their practices and instructions
|
||||
about how to opt-out of certain options.
|
||||
</p>
|
||||
<p>
|
||||
You can choose to disable cookies through your individual browser
|
||||
options. To know more detailed information about cookie management with
|
||||
specific web browsers, it can be found at the browsers' respective
|
||||
websites.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">CCPA Privacy Rights (Do Not Sell My Personal Information)</h2>
|
||||
<p>
|
||||
Under the CCPA, among other rights, California consumers have the right
|
||||
to:
|
||||
</p>
|
||||
<p>
|
||||
Request that a business that collects a consumer's personal data
|
||||
disclose the categories and specific pieces of personal data that a
|
||||
business has collected about consumers.
|
||||
</p>
|
||||
<p>
|
||||
Request that a business delete any personal data about the consumer that
|
||||
a business has collected.
|
||||
</p>
|
||||
<p>
|
||||
Request that a business that sells a consumer's personal data, not sell
|
||||
the consumer's personal data.
|
||||
</p>
|
||||
<p>
|
||||
If you make a request, we have one month to respond to you. If you would
|
||||
like to exercise any of these rights, please contact us.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">GDPR Data Protection Rights</h2>
|
||||
<p>
|
||||
We would like to make sure you are fully aware of all of your data
|
||||
protection rights. Every user is entitled to the following:
|
||||
</p>
|
||||
<p>
|
||||
The right to access – You have the right to request copies of your
|
||||
personal data. We may charge you a small fee for this service.
|
||||
</p>
|
||||
<p>
|
||||
The right to rectification – You have the right to request that we
|
||||
correct any information you believe is inaccurate. You also have the
|
||||
right to request that we complete the information you believe is
|
||||
incomplete.
|
||||
</p>
|
||||
<p>
|
||||
The right to erasure – You have the right to request that we erase your
|
||||
personal data, under certain conditions.
|
||||
</p>
|
||||
<p>
|
||||
The right to restrict processing – You have the right to request that we
|
||||
restrict the processing of your personal data, under certain conditions.
|
||||
</p>
|
||||
<p>
|
||||
The right to object to processing – You have the right to object to our
|
||||
processing of your personal data, under certain conditions.
|
||||
</p>
|
||||
<p>
|
||||
The right to data portability – You have the right to request that we
|
||||
transfer the data that we have collected to another organization, or
|
||||
directly to you, under certain conditions.
|
||||
</p>
|
||||
<p>
|
||||
If you make a request, we have one month to respond to you. If you would
|
||||
like to exercise any of these rights, please contact us.
|
||||
</p>
|
||||
<br></br>
|
||||
<h2 className="text-2xl text-foreground font-semibold mb-2">Children's Information</h2>
|
||||
<p>
|
||||
Another part of our priority is adding protection for children while
|
||||
using the internet. We encourage parents and guardians to observe,
|
||||
participate in, and/or monitor and guide their online activity.
|
||||
</p>
|
||||
<p>
|
||||
NeoDLP Website does not knowingly collect any Personal
|
||||
Identifiable Information from children under the age of 13. If you think
|
||||
that your child provided this kind of information on our website, we
|
||||
strongly encourage you to contact us immediately and we will do our best
|
||||
efforts to promptly remove such information from our records.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
26
src/components/SimpleModeToggle.tsx
Normal file
26
src/components/SimpleModeToggle.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as React from "react"
|
||||
import { Moon, Sun } from "lucide-react"
|
||||
import { NavbarButton } from "@/components/ui/resizable-navbar"
|
||||
|
||||
export function SimpleModeToggle() {
|
||||
const [isDark, setIsDark] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
setIsDark(document.documentElement.classList.contains("dark"))
|
||||
}, [])
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newIsDark = !isDark
|
||||
setIsDark(newIsDark)
|
||||
document.documentElement.classList[newIsDark ? 'add' : 'remove']('dark')
|
||||
localStorage.setItem('theme', newIsDark ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
return (
|
||||
<NavbarButton variant="secondary" as="button" className="flex justify-center items-center" onClick={toggleTheme}>
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</NavbarButton>
|
||||
)
|
||||
}
|
||||
97
src/components/TermsOfUseSection.tsx
Normal file
97
src/components/TermsOfUseSection.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
|
||||
export default function TermsOfUseSection() {
|
||||
return (
|
||||
<section className="flex flex-col w-full min-h-screen">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-2 pt-14 pb-4">
|
||||
<h1 className="text-4xl font-bold">Terms Of Use</h1>
|
||||
<p className="lg:text-lg text-muted-foreground">Updated: 5/12/2025</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center gap-5 mt-10">
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<p className="text-xl font-semibold text-foreground mb-5">Version 1.0</p>
|
||||
<p>The NeoDLP Website located at https://neodlp.neosubhamoy.com is a copyrighted work belonging to Subhamoy Biswas. Certain features of the Site may be subject to additional guidelines, terms, or rules, which will be posted on the Site in connection with such features.</p>
|
||||
<p>All such additional terms, guidelines, and rules are incorporated by reference into these Terms.</p>
|
||||
<p>These Terms of Use described the legally binding terms and conditions that oversee your use of the Site. BY LOGGING INTO THE SITE, YOU ARE BEING COMPLIANT THAT THESE TERMS and you represent that you have the authority and capacity to enter into these Terms. YOU SHOULD BE AT LEAST 18 YEARS OF AGE TO ACCESS THE SITE. IF YOU DISAGREE WITH ALL OF THE PROVISION OF THESE TERMS, DO NOT LOG INTO AND/OR USE THE SITE.</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center text-muted-foreground max-w-7xl px-4">
|
||||
<p>These terms require the use of arbitration Section 10.2 on an individual basis to resolve disputes and also limit the remedies available to you in the event of a dispute.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Access to the Site</h2>
|
||||
<p><span className="text-foreground">Subject to these Terms:</span> Company grants you a non-transferable, non-exclusive, revocable, limited license to access the Site solely for your own personal, noncommercial use.</p>
|
||||
<p><span className="text-foreground">Certain Restrictions:</span> The rights approved to you in these Terms are subject to the following restrictions: (a) you shall not sell, rent, lease, transfer, assign, distribute, host, or otherwise commercially exploit the Site; (b) you shall not change, make derivative works of, disassemble, reverse compile or reverse engineer any part of the Site; (c) you shall not access the Site in order to build a similar or competitive website; and (d) except as expressly stated herein, no part of the Site may be copied, reproduced, distributed, republished, downloaded, displayed, posted or transmitted in any form or by any means unless otherwise indicated, any future release, update, or other addition to functionality of the Site shall be subject to these Terms. All copyright and other proprietary notices on the Site must be retained on all copies thereof.</p>
|
||||
<p>Company reserves the right to change, suspend, or cease the Site with or without notice to you. You approved that Company will not be held liable to you or any third-party for any change, interruption, or termination of the Site or any part.</p>
|
||||
<p><span className="text-foreground">No Support or Maintenance:</span> You agree that Company will have no obligation to provide you with any support in connection with the Site.</p>
|
||||
<p>Excluding any User Content that you may provide, you are aware that all the intellectual property rights, including copyrights, patents, trademarks, and trade secrets, in the Site and its content are owned by Company or Company’s suppliers. Note that these Terms and access to the Site do not give you any rights, title or interest in or to any intellectual property rights, except for the limited access rights expressed in Section 2.1. Company and its suppliers reserve all rights not granted in these Terms.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">User Content</h2>
|
||||
<p><span className="text-foreground">User Content:</span> "User Content" means any and all information and content that a user submits to the Site. You are exclusively responsible for your User Content. You bear all risks associated with use of your User Content. You hereby certify that your User Content does not violate our Acceptable Use Policy. You may not represent or imply to others that your User Content is in any way provided, sponsored or endorsed by Company. Because you alone are responsible for your User Content, you may expose yourself to liability. Company is not obliged to backup any User Content that you post; also, your User Content may be deleted at any time without prior notice to you. You are solely responsible for making your own backup copies of your User Content if you desire.</p>
|
||||
<p>You hereby grant to Company an irreversible, nonexclusive, royalty-free and fully paid, worldwide license to reproduce, distribute, publicly display and perform, prepare derivative works of, incorporate into other works, and otherwise use and exploit your User Content, and to grant sublicenses of the foregoing rights, solely for the purposes of including your User Content in the Site. You hereby irreversibly waive any claims and assertions of moral rights or attribution with respect to your User Content.</p>
|
||||
<p><span className="text-foreground">Acceptable Use Policy:</span> The following terms constitute our "Acceptable Use Policy": You agree not to use the Site to collect, upload, transmit, display, or distribute any User Content (i) that violates any third-party right or any intellectual property or proprietary right; (ii) that is unlawful, harassing, abusive, tortious, threatening, harmful, invasive of another’s privacy, vulgar, defamatory, false, intentionally misleading, trade libelous, pornographic, obscene, patently offensive, promotes racism, bigotry, hatred, or physical harm of any kind against any group or individual; (iii) that is harmful to minors in any way; or (iv) that is in violation of any law, regulation, or obligations or restrictions imposed by any third party.</p>
|
||||
<p>In addition, you agree not to: (i) upload, transmit, or distribute to or through the Site any software intended to damage or alter a computer system or data; (ii) send through the Site unsolicited or unauthorized advertising, promotional materials, junk mail, spam, chain letters, pyramid schemes, or any other form of duplicative or unsolicited messages; (iii) use the Site to harvest, collect, gather or assemble information or data regarding other users without their consent; (iv) interfere with, disrupt, or create an undue burden on servers or networks connected to the Site, or violate the regulations, policies or procedures of such networks; (v) attempt to gain unauthorized access to the Site, whether through password mining or any other means; (vi) harass or interfere with any other user’s use and enjoyment of the Site; or (vi) use software or automated agents or scripts to produce multiple accounts on the Site, or to generate automated searches, requests, or queries to the Site.</p>
|
||||
<p>We reserve the right to review any User Content, and to investigate and/or take appropriate action against you in our sole discretion if you violate the Acceptable Use Policy or any other provision of these Terms or otherwise create liability for us or any other person. Such action may include removing or modifying your User Content, terminating your Account in accordance with Section 8, and/or reporting you to law enforcement authorities.</p>
|
||||
<p>If you provide Company with any feedback or suggestions regarding the Site, you hereby assign to Company all rights in such Feedback and agree that Company shall have the right to use and fully exploit such Feedback and related information in any manner it believes appropriate. Company will treat any Feedback you provide to Company as non-confidential and non-proprietary.</p>
|
||||
<p>You agree to indemnify and hold Company and its officers, employees, and agents harmless, including costs and attorneys’ fees, from any claim or demand made by any third-party due to or arising out of (a) your use of the Site, (b) your violation of these Terms, (c) your violation of applicable laws or regulations or (d) your User Content. Company reserves the right to assume the exclusive defense and control of any matter for which you are required to indemnify us, and you agree to cooperate with our defense of these claims. You agree not to settle any matter without the prior written consent of Company. Company will use reasonable efforts to notify you of any such claim, action or proceeding upon becoming aware of it.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Third-Party Links & Ads; Other Users</h2>
|
||||
<p><span className="text-foreground">Third-Party Links & Ads:</span> The Site may contain links to third-party websites and services, and/or display advertisements for third-parties. Such Third-Party Links & Ads are not under the control of Company, and Company is not responsible for any Third-Party Links & Ads. Company provides access to these Third-Party Links & Ads only as a convenience to you, and does not review, approve, monitor, endorse, warrant, or make any representations with respect to Third-Party Links & Ads. You use all Third-Party Links & Ads at your own risk, and should apply a suitable level of caution and discretion in doing so. When you click on any of the Third-Party Links & Ads, the applicable third party’s terms and policies apply, including the third party’s privacy and data gathering practices.</p>
|
||||
<p><span className="text-foreground">Other Users:</span> Each Site user is solely responsible for any and all of its own User Content. Because we do not control User Content, you acknowledge and agree that we are not responsible for any User Content, whether provided by you or by others. You agree that Company will not be responsible for any loss or damage incurred as the result of any such interactions. If there is a dispute between you and any Site user, we are under no obligation to become involved.</p>
|
||||
<p>You hereby release and forever discharge the Company and our officers, employees, agents, successors, and assigns from, and hereby waive and relinquish, each and every past, present and future dispute, claim, controversy, demand, right, obligation, liability, action and cause of action of every kind and nature, that has arisen or arises directly or indirectly out of, or that relates directly or indirectly to, the Site. If you are a California resident, you hereby waive California civil code section 1542 in connection with the foregoing, which states: "a general release does not extend to claims which the creditor does not know or suspect to exist in his or her favor at the time of executing the release, which if known by him or her must have materially affected his or her settlement with the debtor."</p>
|
||||
<p><span className="text-foreground">Cookies and Web Beacons:</span> Like any other website, NeoDLP Website uses ‘cookies’. These cookies are used to store information including visitors’ preferences, and the pages on the website that the visitor accessed or visited. The information is used to optimize the users’ experience by customizing our web page content based on visitors’ browser type and/or other information.</p>
|
||||
<p><span className="text-foreground">Google DoubleClick DART Cookie:</span> Google is one of a third-party vendor on our site. It also uses cookies, known as DART cookies, to serve ads to our site visitors based upon their visit to www.website.com and other sites on the internet. However, visitors may choose to decline the use of DART cookies by visiting the Google ad and content network Privacy Policy at the following URL – <a href="https://policies.google.com/technologies/ads">https://policies.google.com/technologies/ads</a></p>
|
||||
<p><span className="text-foreground">Our Advertising Partners:</span> Some of advertisers on our site may use cookies and web beacons. Our advertising partners are listed below. Each of our advertising partners has their own Privacy Policy for their policies on user data. For easier access, we hyperlinked to their Privacy Policies below.</p>
|
||||
<ul className="">
|
||||
<li>
|
||||
<p>• Google</p>
|
||||
<p><a href="https://policies.google.com/technologies/ads">https://policies.google.com/technologies/ads</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Disclaimers</h2>
|
||||
<p>The site is provided on an "as-is" and "as available" basis, and company and our suppliers expressly disclaim any and all warranties and conditions of any kind, whether express, implied, or statutory, including all warranties or conditions of merchantability, fitness for a particular purpose, title, quiet enjoyment, accuracy, or non-infringement. We and our suppliers make not guarantee that the site will meet your requirements, will be available on an uninterrupted, timely, secure, or error-free basis, or will be accurate, reliable, free of viruses or other harmful code, complete, legal, or safe. If applicable law requires any warranties with respect to the site, all such warranties are limited in duration to ninety (90) days from the date of first use.</p>
|
||||
<p>Some jurisdictions do not allow the exclusion of implied warranties, so the above exclusion may not apply to you. Some jurisdictions do not allow limitations on how long an implied warranty lasts, so the above limitation may not apply to you.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Limitation on Liability</h2>
|
||||
<p>To the maximum extent permitted by law, in no event shall company or our suppliers be liable to you or any third-party for any lost profits, lost data, costs of procurement of substitute products, or any indirect, consequential, exemplary, incidental, special or punitive damages arising from or relating to these terms or your use of, or incapability to use the site even if company has been advised of the possibility of such damages. Access to and use of the site is at your own discretion and risk, and you will be solely responsible for any damage to your device or computer system, or loss of data resulting therefrom.</p>
|
||||
<p>To the maximum extent permitted by law, notwithstanding anything to the contrary contained herein, our liability to you for any damages arising from or related to this agreement, will at all times be limited to a maximum of fifty U.S. dollars (u.s. $50). The existence of more than one claim will not enlarge this limit. You agree that our suppliers will have no liability of any kind arising from or relating to this agreement.</p>
|
||||
<p>Some jurisdictions do not allow the limitation or exclusion of liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you.</p>
|
||||
<p><span className="text-foreground">Term and Termination:</span> Subject to this Section, these Terms will remain in full force and effect while you use the Site. We may suspend or terminate your rights to use the Site at any time for any reason at our sole discretion, including for any use of the Site in violation of these Terms. Upon termination of your rights under these Terms, your Account and right to access and use the Site will terminate immediately. You understand that any termination of your Account may involve deletion of your User Content associated with your Account from our live databases. Company will not have any liability whatsoever to you for any termination of your rights under these Terms. Even after your rights under these Terms are terminated, the following provisions of these Terms will remain in effect: Sections 2 through 2.5, Section 3 and Sections 4 through 10.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Copyright Policy</h2>
|
||||
<p>Company respects the intellectual property of others and asks that users of our Site do the same. In connection with our Site, we have adopted and implemented a policy respecting copyright law that provides for the removal of any infringing materials and for the termination of users of our online Site who are repeated infringers of intellectual property rights, including copyrights. If you believe that one of our users is, through the use of our Site, unlawfully infringing the copyright(s) in a work, and wish to have the allegedly infringing material removed, the following information in the form of a written notification (pursuant to 17 U.S.C. § 512(c)) must be provided to our designated Copyright Agent:</p>
|
||||
<ul className="">
|
||||
<li>• your physical or electronic signature;</li>
|
||||
<li>• identification of the copyrighted work(s) that you claim to have been infringed;</li>
|
||||
<li>• identification of the material on our services that you claim is infringing and that you request us to remove;</li>
|
||||
<li>• sufficient information to permit us to locate such material;</li>
|
||||
<li>• your address, telephone number, and e-mail address;</li>
|
||||
<li>• a statement that you have a good faith belief that use of the objectionable material is not authorized by the copyright owner, its agent, or under the law; and</li>
|
||||
<li>• a statement that the information in the notification is accurate, and under penalty of perjury, that you are either the owner of the copyright that has allegedly been infringed or that you are authorized to act on behalf of the copyright owner.</li>
|
||||
</ul>
|
||||
<p>Please note that, pursuant to 17 U.S.C. § 512(f), any misrepresentation of material fact in a written notification automatically subjects the complaining party to liability for any damages, costs and attorney’s fees incurred by us in connection with the written notification and allegation of copyright infringement.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">General</h2>
|
||||
<p>These Terms are subject to occasional revision, and if we make any substantial changes, we may notify you by sending you an e-mail to the last e-mail address you provided to us and/or by prominently posting notice of the changes on our Site. You are responsible for providing us with your most current e-mail address. In the event that the last e-mail address that you have provided us is not valid our dispatch of the e-mail containing such notice will nonetheless constitute effective notice of the changes described in the notice. Any changes to these Terms will be effective upon the earliest of thirty (30) calendar days following our dispatch of an e-mail notice to you or thirty (30) calendar days following our posting of notice of the changes on our Site. These changes will be effective immediately for new users of our Site. Continued use of our Site following notice of such changes shall indicate your acknowledgement of such changes and agreement to be bound by the terms and conditions of such changes. Dispute Resolution. Please read this Arbitration Agreement carefully. It is part of your contract with Company and affects your rights. It contains procedures for MANDATORY BINDING ARBITRATION AND A CLASS ACTION WAIVER.</p>
|
||||
<p><span className="text-foreground">Applicability of Arbitration Agreement:</span> All claims and disputes in connection with the Terms or the use of any product or service provided by the Company that cannot be resolved informally or in small claims court shall be resolved by binding arbitration on an individual basis under the terms of this Arbitration Agreement. Unless otherwise agreed to, all arbitration proceedings shall be held in English. This Arbitration Agreement applies to you and the Company, and to any subsidiaries, affiliates, agents, employees, predecessors in interest, successors, and assigns, as well as all authorized or unauthorized users or beneficiaries of services or goods provided under the Terms.</p>
|
||||
<p><span className="text-foreground">Notice Requirement and Informal Dispute Resolution:</span> Before either party may seek arbitration, the party must first send to the other party a written Notice of Dispute describing the nature and basis of the claim or dispute, and the requested relief. A Notice to the Company should be sent to: Kolkata, West Bengal, India. After the Notice is received, you and the Company may attempt to resolve the claim or dispute informally. If you and the Company do not resolve the claim or dispute within thirty (30) days after the Notice is received, either party may begin an arbitration proceeding. The amount of any settlement offer made by any party may not be disclosed to the arbitrator until after the arbitrator has determined the amount of the award to which either party is entitled.</p>
|
||||
<p><span className="text-foreground">Arbitration Rules:</span> Arbitration shall be initiated through the American Arbitration Association, an established alternative dispute resolution provider that offers arbitration as set forth in this section. If AAA is not available to arbitrate, the parties shall agree to select an alternative ADR Provider. The rules of the ADR Provider shall govern all aspects of the arbitration except to the extent such rules are in conflict with the Terms. The AAA Consumer Arbitration Rules governing the arbitration are available online at adr.org or by calling the AAA at 1-800-778-7879. The arbitration shall be conducted by a single, neutral arbitrator. Any claims or disputes where the total amount of the award sought is less than Ten Thousand U.S. Dollars (US $10,000.00) may be resolved through binding non-appearance-based arbitration, at the option of the party seeking relief. For claims or disputes where the total amount of the award sought is Ten Thousand U.S. Dollars (US $10,000.00) or more, the right to a hearing will be determined by the Arbitration Rules. Any hearing will be held in a location within 100 miles of your residence, unless you reside outside of the United States, and unless the parties agree otherwise. If you reside outside of the U.S., the arbitrator shall give the parties reasonable notice of the date, time and place of any oral hearings. Any judgment on the award rendered by the arbitrator may be entered in any court of competent jurisdiction. If the arbitrator grants you an award that is greater than the last settlement offer that the Company made to you prior to the initiation of arbitration, the Company will pay you the greater of the award or $2,500.00. Each party shall bear its own costs and disbursements arising out of the arbitration and shall pay an equal share of the fees and costs of the ADR Provider.</p>
|
||||
<p><span className="text-foreground">Additional Rules for Non-Appearance Based Arbitration:</span> If non-appearance based arbitration is elected, the arbitration shall be conducted by telephone, online and/or based solely on written submissions; the specific manner shall be chosen by the party initiating the arbitration. The arbitration shall not involve any personal appearance by the parties or witnesses unless otherwise agreed by the parties.</p>
|
||||
<p><span className="text-foreground">Time Limits:</span> If you or the Company pursues arbitration, the arbitration action must be initiated and/or demanded within the statute of limitations and within any deadline imposed under the AAA Rules for the pertinent claim.</p>
|
||||
<p><span className="text-foreground">Authority of Arbitrator:</span> If arbitration is initiated, the arbitrator will decide the rights and liabilities of you and the Company, and the dispute will not be consolidated with any other matters or joined with any other cases or parties. The arbitrator shall have the authority to grant motions dispositive of all or part of any claim. The arbitrator shall have the authority to award monetary damages, and to grant any non-monetary remedy or relief available to an individual under applicable law, the AAA Rules, and the Terms. The arbitrator shall issue a written award and statement of decision describing the essential findings and conclusions on which the award is based. The arbitrator has the same authority to award relief on an individual basis that a judge in a court of law would have. The award of the arbitrator is final and binding upon you and the Company.</p>
|
||||
<p><span className="text-foreground">Waiver of Jury Trial:</span> THE PARTIES HEREBY WAIVE THEIR CONSTITUTIONAL AND STATUTORY RIGHTS TO GO TO COURT AND HAVE A TRIAL IN FRONT OF A JUDGE OR A JURY, instead electing that all claims and disputes shall be resolved by arbitration under this Arbitration Agreement. Arbitration procedures are typically more limited, more efficient and less expensive than rules applicable in a court and are subject to very limited review by a court. In the event any litigation should arise between you and the Company in any state or federal court in a suit to vacate or enforce an arbitration award or otherwise, YOU AND THE COMPANY WAIVE ALL RIGHTS TO A JURY TRIAL, instead electing that the dispute be resolved by a judge.</p>
|
||||
<p><span className="text-foreground">Waiver of Class or Consolidated Actions:</span> All claims and disputes within the scope of this arbitration agreement must be arbitrated or litigated on an individual basis and not on a class basis, and claims of more than one customer or user cannot be arbitrated or litigated jointly or consolidated with those of any other customer or user.</p>
|
||||
<p><span className="text-foreground">Confidentiality:</span> All aspects of the arbitration proceeding shall be strictly confidential. The parties agree to maintain confidentiality unless otherwise required by law. This paragraph shall not prevent a party from submitting to a court of law any information necessary to enforce this Agreement, to enforce an arbitration award, or to seek injunctive or equitable relief.</p>
|
||||
<p><span className="text-foreground">Severability:</span> If any part or parts of this Arbitration Agreement are found under the law to be invalid or unenforceable by a court of competent jurisdiction, then such specific part or parts shall be of no force and effect and shall be severed and the remainder of the Agreement shall continue in full force and effect.</p>
|
||||
<p><span className="text-foreground">Right to Waive:</span> Any or all of the rights and limitations set forth in this Arbitration Agreement may be waived by the party against whom the claim is asserted. Such waiver shall not waive or affect any other portion of this Arbitration Agreement.</p>
|
||||
<p><span className="text-foreground">Survival of Agreement:</span> This Arbitration Agreement will survive the termination of your relationship with Company.</p>
|
||||
<p><span className="text-foreground">Small Claims Court:</span> Nonetheless the foregoing, either you or the Company may bring an individual action in small claims court.</p>
|
||||
<p><span className="text-foreground">Emergency Equitable Relief:</span> Anyhow the foregoing, either party may seek emergency equitable relief before a state or federal court in order to maintain the status quo pending arbitration. A request for interim measures shall not be deemed a waiver of any other rights or obligations under this Arbitration Agreement.</p>
|
||||
<p><span className="text-foreground">Claims Not Subject to Arbitration:</span> Notwithstanding the foregoing, claims of defamation, violation of the Computer Fraud and Abuse Act, and infringement or misappropriation of the other party’s patent, copyright, trademark or trade secrets shall not be subject to this Arbitration Agreement.</p>
|
||||
<p>In any circumstances where the foregoing Arbitration Agreement permits the parties to litigate in court, the parties hereby agree to submit to the personal jurisdiction of the courts located within Netherlands County, California, for such purposes.</p>
|
||||
<p>The Site may be subject to U.S. export control laws and may be subject to export or import regulations in other countries. You agree not to export, re-export, or transfer, directly or indirectly, any U.S. technical data acquired from Company, or any products utilizing such data, in violation of the United States export laws or regulations.</p>
|
||||
<p>Company is located at the address in Section 10.8. If you are a California resident, you may report complaints to the Complaint Assistance Unit of the Division of Consumer Product of the California Department of Consumer Affairs by contacting them in writing at 400 R Street, Sacramento, CA 95814, or by telephone at (800) 952-5210.</p>
|
||||
<p><span className="text-foreground">Electronic Communications:</span> The communications between you and Company use electronic means, whether you use the Site or send us emails, or whether Company posts notices on the Site or communicates with you via email. For contractual purposes, you (a) consent to receive communications from Company in an electronic form; and (b) agree that all terms and conditions, agreements, notices, disclosures, and other communications that Company provides to you electronically satisfy any legal obligation that such communications would satisfy if it were be in a hard copy writing.</p>
|
||||
<p><span className="text-foreground">Entire Terms:</span> These Terms constitute the entire agreement between you and us regarding the use of the Site. Our failure to exercise or enforce any right or provision of these Terms shall not operate as a waiver of such right or provision. The section titles in these Terms are for convenience only and have no legal or contractual effect. The word "including" means "including without limitation". If any provision of these Terms is held to be invalid or unenforceable, the other provisions of these Terms will be unimpaired and the invalid or unenforceable provision will be deemed modified so that it is valid and enforceable to the maximum extent permitted by law. Your relationship to Company is that of an independent contractor, and neither party is an agent or partner of the other. These Terms, and your rights and obligations herein, may not be assigned, subcontracted, delegated, or otherwise transferred by you without Company’s prior written consent, and any attempted assignment, subcontract, delegation, or transfer in violation of the foregoing will be null and void. Company may freely assign these Terms. The terms and conditions set forth in these Terms shall be binding upon assignees.</p>
|
||||
<p><span className="text-foreground">Your Privacy:</span> Please read our Privacy Policy.</p>
|
||||
<p><span className="text-foreground">Copyright/Trademark Information:</span> Copyright ©. All rights reserved. All trademarks, logos and service marks displayed on the Site are our property or the property of other third-parties. You are not permitted to use these Marks without our prior written consent or the consent of such third party which may own the Marks.</p>
|
||||
<h2 className="text-2xl text-foreground font-semibold my-3">Contact Information</h2>
|
||||
<p>Address: Basirhat, North 24 Parganas, West Bengal, India</p>
|
||||
<p>Email: <a href="mailto:support@neodlp.neosubhamoy.com">support@neodlp.neosubhamoy.com</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
43
src/components/footer.tsx
Normal file
43
src/components/footer.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Mail } from "lucide-react";
|
||||
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="flex justify-center items-center relative z-40 mt-30">
|
||||
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4 max-w-7xl w-full px-4 py-10 border-t border-border">
|
||||
<div className="flex flex-col gap-2 col-span-2 mb-8 lg:mb-0">
|
||||
<div className="flex flex-col gap-2">
|
||||
<a className="flex items-center gap-4" href="/">
|
||||
<img className="size-8" src="/neodlp.svg" alt="neodlp" />
|
||||
<h5 className="text-2xl font-bold">NeoDLP</h5>
|
||||
</a>
|
||||
<p className="text-sm text-muted-foreground">The Next-Gen Cross-Platform Video Downloader</p>
|
||||
<p className="text-sm mt-1">NeoDLP © {new Date().getFullYear()} - All Rights Reserved • <a className="hover:underline" href="https://github.com/neosubhamoy/neodlp/blob/main/LICENSE" target="_blank">MIT License</a></p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<a className="flex items-center text-xs text-muted-foreground hover:underline" href="mailto:support@neodlp.neosubhamoy.com">
|
||||
<Mail className="size-4" />
|
||||
<span className="ml-2 pb-[0.15rem]">support@neodlp.neosubhamoy.com</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h5 className="font-semibold mb-2">Terms</h5>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="/privacy-policy">Privacy Policy</a>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="/terms-of-use">Terms Of Use</a>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="/dmca">DMCA</a>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h5 className="font-semibold mb-2">Sources</h5>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="https://github.com/neosubhamoy/neodlp" target="_blank">NeoDLP</a>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="https://github.com/neosubhamoy/neodlp-extension" target="_blank">NeoDLP Extension</a>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h5 className="font-semibold mb-2">More Products from Us</h5>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="https://github.com/neosubhamoy/pytubepp" target="_blank">PytubePP</a>
|
||||
<a className="text-sm text-muted-foreground hover:underline" href="https://prourl.eu.org" target="_blank">ProURL</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
117
src/components/navbar.tsx
Normal file
117
src/components/navbar.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ModeToggle } from "@/components/ModeToggle";
|
||||
import { Github } from "lucide-react";
|
||||
import {
|
||||
Navbar as ResizableNavbar,
|
||||
NavBody,
|
||||
NavItems,
|
||||
MobileNav,
|
||||
NavbarLogo,
|
||||
NavbarButton,
|
||||
MobileNavHeader,
|
||||
MobileNavToggle,
|
||||
MobileNavMenu,
|
||||
} from "@/components/ui/resizable-navbar";
|
||||
import { useState } from "react";
|
||||
import { SimpleModeToggle } from "@/components/SimpleModeToggle";
|
||||
|
||||
export default function Navbar() {
|
||||
const navItems = [
|
||||
{
|
||||
name: "Features",
|
||||
link: "/#features",
|
||||
},
|
||||
{
|
||||
name: "Extension",
|
||||
link: "/extension",
|
||||
},
|
||||
];
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<ResizableNavbar>
|
||||
{/* Desktop Navigation */}
|
||||
<NavBody>
|
||||
<NavbarLogo />
|
||||
<NavItems items={navItems} />
|
||||
<div className="flex items-center gap-4">
|
||||
<NavbarButton variant="secondary" as="a" href="https://github.com/neosubhamoy/neodlp" target="_blank" aria-label="GitHub">
|
||||
<Github className="h-4 w-4" />
|
||||
</NavbarButton>
|
||||
<SimpleModeToggle />
|
||||
<NavbarButton variant="primary" as="a" href="/download">
|
||||
Download
|
||||
</NavbarButton>
|
||||
</div>
|
||||
</NavBody>
|
||||
|
||||
{/* Mobile Navigation */}
|
||||
<MobileNav>
|
||||
<MobileNavHeader>
|
||||
<NavbarLogo />
|
||||
<MobileNavToggle
|
||||
isOpen={isMobileMenuOpen}
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
/>
|
||||
</MobileNavHeader>
|
||||
<MobileNavMenu
|
||||
isOpen={isMobileMenuOpen}
|
||||
onClose={() => setIsMobileMenuOpen(false)}
|
||||
>
|
||||
{navItems.map((item, idx) => (
|
||||
<a
|
||||
key={`mobile-link-${idx}`}
|
||||
href={item.link}
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
className="relative text-neutral-600 dark:text-neutral-300"
|
||||
>
|
||||
<span className="block">{item.name}</span>
|
||||
</a>
|
||||
))}
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<NavbarButton
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
variant="primary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
as="a"
|
||||
href="https://github.com/neosubhamoy/neodlp"
|
||||
target="_blank"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
View in GitHub
|
||||
</NavbarButton>
|
||||
<NavbarButton
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
variant="primary"
|
||||
className="w-full"
|
||||
as="a"
|
||||
href="/download"
|
||||
>
|
||||
Download
|
||||
</NavbarButton>
|
||||
</div>
|
||||
</MobileNavMenu>
|
||||
</MobileNav>
|
||||
</ResizableNavbar>
|
||||
// <nav className="flex justify-between items-center border-b border-border sticky top-0 backdrop-blur supports-[backdrop-filter]:bg-background/60 z-50 py-4 px-4 lg:px-12 xl:px-24">
|
||||
// <a className="flex items-center gap-4" href="/">
|
||||
// <div className="w-8">
|
||||
// <img src="/neodlp.svg" alt="logo" />
|
||||
// </div>
|
||||
// <h1 className="text-2xl font-bold">NeoDLP</h1>
|
||||
// </a>
|
||||
// <div className="flex items-center gap-4">
|
||||
// <Button variant="ghost" asChild>
|
||||
// <a href="https://github.com/neosubhamoy/neodlp" target="_blank" aria-label="GitHub">
|
||||
// <Github className="h-4 w-4" />
|
||||
// </a>
|
||||
// </Button>
|
||||
// <ModeToggle />
|
||||
// <Button asChild>
|
||||
// <a href="/download">Download</a>
|
||||
// </Button>
|
||||
// </div>
|
||||
// </nav>
|
||||
);
|
||||
}
|
||||
59
src/components/ui/button.tsx
Normal file
59
src/components/ui/button.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
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"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
outline:
|
||||
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||
icon: "size-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"button"> &
|
||||
VariantProps<typeof buttonVariants> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
|
||||
return (
|
||||
<Comp
|
||||
data-slot="button"
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Button, buttonVariants }
|
||||
41
src/components/ui/command-snippet.tsx
Normal file
41
src/components/ui/command-snippet.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { Copy, Terminal } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export const CommandSnippet = ({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const handleCopy = () => {
|
||||
const command = children?.toString();
|
||||
if (command) {
|
||||
navigator.clipboard.writeText(command).then(() => {
|
||||
toast("Copied to clipboard!");
|
||||
}).catch((err) => {
|
||||
toast("Failed to copy to clipboard!");
|
||||
console.error("Failed to copy command:", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col rounded-lg border border-border overflow-hidden min-w-[20rem] md:min-w-[25rem]">
|
||||
<div className="flex items-center justify-between px-4 py-1 gap-2 bg-muted">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="size-4" />
|
||||
<span className="text-xs text-muted-foreground">{title}</span>
|
||||
</div>
|
||||
<button className="flex items-center gap-2 cursor-pointer text-muted-foreground hover:text-primary" onClick={handleCopy}>
|
||||
<Copy className="size-4" />
|
||||
<span className="text-xs">Copy</span>
|
||||
</button>
|
||||
</div>
|
||||
<code className="flex px-4 py-2">
|
||||
<p className="">{children}</p>
|
||||
</code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
282
src/components/ui/container-scroll-animation.tsx
Normal file
282
src/components/ui/container-scroll-animation.tsx
Normal file
@@ -0,0 +1,282 @@
|
||||
"use client";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useScroll, useTransform, motion, MotionValue } from "motion/react";
|
||||
import { ArrowRight, CircleArrowDown, Download, Puzzle } from "lucide-react";
|
||||
import { type LatestRelease } from "@/types/release";
|
||||
import { SlidingButton } from "@/components/ui/sliding-button";
|
||||
import { getOS } from "@/lib/utils";
|
||||
import type { OS } from "@/types/os";
|
||||
|
||||
export const ContainerScroll = ({
|
||||
titleComponent,
|
||||
children,
|
||||
release,
|
||||
}: {
|
||||
titleComponent: string | React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
release: LatestRelease;
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: containerRef,
|
||||
});
|
||||
const [isMobile, setIsMobile] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth <= 768);
|
||||
};
|
||||
checkMobile();
|
||||
window.addEventListener("resize", checkMobile);
|
||||
return () => {
|
||||
window.removeEventListener("resize", checkMobile);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const scaleDimensions = () => {
|
||||
return isMobile ? [0.7, 0.9] : [1.05, 1];
|
||||
};
|
||||
|
||||
const rotate = useTransform(scrollYProgress, [0, 1], [20, 0]);
|
||||
const scale = useTransform(scrollYProgress, [0, 1], scaleDimensions());
|
||||
const translate = useTransform(scrollYProgress, [0, 1], [0, -100]);
|
||||
|
||||
const [os, setOS] = useState<OS>('unknown');
|
||||
useEffect(() => {
|
||||
const detectedOS = getOS();
|
||||
setOS(detectedOS);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="h-[60rem] md:h-[80rem] flex items-center justify-center relative p-2 md:p-20"
|
||||
ref={containerRef}
|
||||
>
|
||||
<div className="absolute top-20 left-0 inset-x-auto w-full z-20 flex flex-col items-center justify-center">
|
||||
<button
|
||||
className="bg-slate-800 no-underline group cursor-pointer relative shadow-2xl shadow-zinc-900 rounded-full p-px text-xs font-semibold leading-6 text-white inline-block"
|
||||
onClick={() => {
|
||||
window.open("https://github.com/neosubhamoy/neodlp/releases/latest", "_blank");
|
||||
}}
|
||||
>
|
||||
<span className="absolute inset-0 overflow-hidden rounded-full">
|
||||
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100"></span>
|
||||
</span>
|
||||
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-white dark:bg-zinc-950 text-black dark:text-white py-0.5 px-4 ring-1 ring-white/10 ">
|
||||
<span>{`✨ v${release?.version ?? 'Unknown'} released. explore what's new`}</span>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M10.75 8.75L14.25 12L10.75 15.25"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover:opacity-40"></span>
|
||||
</button>
|
||||
<div className="flex justify-center items-center gap-4 mt-10">
|
||||
{/* <button className="px-4 py-2 rounded-md text-center relative overflow-hidden cursor-pointer bg-black dark:bg-white dark:text-black text-white flex justify-center group/windows-download-btn">
|
||||
<span className="group-hover/windows-download-btn:translate-x-60 text-center transition duration-500 flex flex-col justify-center items-center">
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z"/>
|
||||
</svg>
|
||||
Download for Windows
|
||||
</span>
|
||||
<span className="text-xs">(x64) EXE Installer</span>
|
||||
</span>
|
||||
<div className="-translate-x-60 group-hover/windows-download-btn:translate-x-0 flex items-center justify-center absolute inset-0 transition duration-500 text-white z-20">
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
</div>
|
||||
</button> */}
|
||||
{os === "windows" && (
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["windows-x86_64"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z"/>
|
||||
</svg>
|
||||
Download for Windows
|
||||
</span>
|
||||
<span className="text-xs">(x64) EXE Installer</span>
|
||||
</SlidingButton>
|
||||
)}
|
||||
{os === "macos" && (
|
||||
<>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-x86_64-dmg"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(x64) DMG Installer</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["darwin-aarch64-dmg"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
Download for MacOS
|
||||
</span>
|
||||
<span className="text-xs">(ARM64) DMG Installer</span>
|
||||
</SlidingButton>
|
||||
</>
|
||||
)}
|
||||
{os === "linux" && (
|
||||
<>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["linux-x86_64-deb"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"/>
|
||||
</svg>
|
||||
Download for Linux
|
||||
</span>
|
||||
<span className="text-xs">(x64) DEB Package</span>
|
||||
</SlidingButton>
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<Download className="size-4" />
|
||||
<span>Download Now</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href={release.platforms["linux-x86_64-rpm"].url}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<svg className="size-4 fill-white dark:fill-black" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"/>
|
||||
</svg>
|
||||
Download for Linux
|
||||
</span>
|
||||
<span className="text-xs">(x64) RPM Package</span>
|
||||
</SlidingButton>
|
||||
</>
|
||||
)}
|
||||
<SlidingButton
|
||||
slidingContent={
|
||||
<div className="flex items-center justify-center gap-2 text-white dark:text-black">
|
||||
<ArrowRight className="size-4" />
|
||||
<span>Goto All Downloads</span>
|
||||
</div>
|
||||
}
|
||||
as="a"
|
||||
href="/download"
|
||||
>
|
||||
<span className="font-semibold flex items-center gap-2">
|
||||
<CircleArrowDown className="size-4" />
|
||||
All Downloads
|
||||
</span>
|
||||
<span className="text-xs">Choose from all download options</span>
|
||||
</SlidingButton>
|
||||
</div>
|
||||
<div className="flex justify-center items-center gap-2 mt-5 text-sm text-muted-foreground">
|
||||
<Puzzle className=" size-4 text-emerald-500" /> Looking for browser integration? <a className="font-semibold underline transition-all duration-500 hover:text-white" href="/extension">Get Here</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="py-10 md:py-40 w-full relative"
|
||||
style={{
|
||||
perspective: "1000px",
|
||||
}}
|
||||
>
|
||||
<Header translate={translate} titleComponent={titleComponent} />
|
||||
<Card rotate={rotate} translate={translate} scale={scale}>
|
||||
{children}
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Header = ({ translate, titleComponent }: any) => {
|
||||
return (
|
||||
<motion.div
|
||||
style={{
|
||||
translateY: translate,
|
||||
}}
|
||||
className="div max-w-5xl mx-auto text-center"
|
||||
>
|
||||
{titleComponent}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Card = ({
|
||||
rotate,
|
||||
scale,
|
||||
children,
|
||||
}: {
|
||||
rotate: MotionValue<number>;
|
||||
scale: MotionValue<number>;
|
||||
translate: MotionValue<number>;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<motion.div
|
||||
style={{
|
||||
rotateX: rotate,
|
||||
scale,
|
||||
boxShadow:
|
||||
"0 0 #0000004d, 0 9px 20px #0000004a, 0 37px 37px #00000042, 0 84px 50px #00000026, 0 149px 60px #0000000a, 0 233px 65px #00000003",
|
||||
}}
|
||||
className="max-w-5xl -mt-12 mx-auto aspect-video w-full border-4 border-[#6C6C6C] p-2 md:p-6 bg-[#222222] rounded-[30px] shadow-2xl"
|
||||
>
|
||||
<div className="w-full aspect-video overflow-hidden rounded-2xl bg-gray-100 dark:bg-zinc-900 md:rounded-2xl md:p-4 ">
|
||||
{children}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
255
src/components/ui/dropdown-menu.tsx
Normal file
255
src/components/ui/dropdown-menu.tsx
Normal file
@@ -0,0 +1,255 @@
|
||||
import * as React from "react"
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function DropdownMenu({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
|
||||
}
|
||||
|
||||
function DropdownMenuPortal({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Trigger
|
||||
data-slot="dropdown-menu-trigger"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuContent({
|
||||
className,
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Portal>
|
||||
<DropdownMenuPrimitive.Content
|
||||
data-slot="dropdown-menu-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground 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 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuGroup({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuItem({
|
||||
className,
|
||||
inset,
|
||||
variant = "default",
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean
|
||||
variant?: "default" | "destructive"
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Item
|
||||
data-slot="dropdown-menu-item"
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuCheckboxItem({
|
||||
className,
|
||||
children,
|
||||
checked,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
data-slot="dropdown-menu-checkbox-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuRadioGroup({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.RadioGroup
|
||||
data-slot="dropdown-menu-radio-group"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuRadioItem({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
data-slot="dropdown-menu-radio-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CircleIcon className="size-2 fill-current" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuLabel({
|
||||
className,
|
||||
inset,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Label
|
||||
data-slot="dropdown-menu-label"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
data-slot="dropdown-menu-separator"
|
||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuShortcut({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"span">) {
|
||||
return (
|
||||
<span
|
||||
data-slot="dropdown-menu-shortcut"
|
||||
className={cn(
|
||||
"text-muted-foreground ml-auto text-xs tracking-widest",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuSub({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
||||
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
|
||||
}
|
||||
|
||||
function DropdownMenuSubTrigger({
|
||||
className,
|
||||
inset,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
data-slot="dropdown-menu-sub-trigger"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRightIcon className="ml-auto size-4" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
function DropdownMenuSubContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
data-slot="dropdown-menu-sub-content"
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground 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] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuSubContent,
|
||||
}
|
||||
190
src/components/ui/glowing-effect.tsx
Normal file
190
src/components/ui/glowing-effect.tsx
Normal file
@@ -0,0 +1,190 @@
|
||||
"use client";
|
||||
|
||||
import { memo, useCallback, useEffect, useRef } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { animate } from "motion/react";
|
||||
|
||||
interface GlowingEffectProps {
|
||||
blur?: number;
|
||||
inactiveZone?: number;
|
||||
proximity?: number;
|
||||
spread?: number;
|
||||
variant?: "default" | "white";
|
||||
glow?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
movementDuration?: number;
|
||||
borderWidth?: number;
|
||||
}
|
||||
const GlowingEffect = memo(
|
||||
({
|
||||
blur = 0,
|
||||
inactiveZone = 0.7,
|
||||
proximity = 0,
|
||||
spread = 20,
|
||||
variant = "default",
|
||||
glow = false,
|
||||
className,
|
||||
movementDuration = 2,
|
||||
borderWidth = 1,
|
||||
disabled = true,
|
||||
}: GlowingEffectProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const lastPosition = useRef({ x: 0, y: 0 });
|
||||
const animationFrameRef = useRef<number>(0);
|
||||
|
||||
const handleMove = useCallback(
|
||||
(e?: MouseEvent | { x: number; y: number }) => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
if (animationFrameRef.current) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
}
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(() => {
|
||||
const element = containerRef.current;
|
||||
if (!element) return;
|
||||
|
||||
const { left, top, width, height } = element.getBoundingClientRect();
|
||||
const mouseX = e?.x ?? lastPosition.current.x;
|
||||
const mouseY = e?.y ?? lastPosition.current.y;
|
||||
|
||||
if (e) {
|
||||
lastPosition.current = { x: mouseX, y: mouseY };
|
||||
}
|
||||
|
||||
const center = [left + width * 0.5, top + height * 0.5];
|
||||
const distanceFromCenter = Math.hypot(
|
||||
mouseX - center[0],
|
||||
mouseY - center[1]
|
||||
);
|
||||
const inactiveRadius = 0.5 * Math.min(width, height) * inactiveZone;
|
||||
|
||||
if (distanceFromCenter < inactiveRadius) {
|
||||
element.style.setProperty("--active", "0");
|
||||
return;
|
||||
}
|
||||
|
||||
const isActive =
|
||||
mouseX > left - proximity &&
|
||||
mouseX < left + width + proximity &&
|
||||
mouseY > top - proximity &&
|
||||
mouseY < top + height + proximity;
|
||||
|
||||
element.style.setProperty("--active", isActive ? "1" : "0");
|
||||
|
||||
if (!isActive) return;
|
||||
|
||||
const currentAngle =
|
||||
parseFloat(element.style.getPropertyValue("--start")) || 0;
|
||||
let targetAngle =
|
||||
(180 * Math.atan2(mouseY - center[1], mouseX - center[0])) /
|
||||
Math.PI +
|
||||
90;
|
||||
|
||||
const angleDiff = ((targetAngle - currentAngle + 180) % 360) - 180;
|
||||
const newAngle = currentAngle + angleDiff;
|
||||
|
||||
animate(currentAngle, newAngle, {
|
||||
duration: movementDuration,
|
||||
ease: [0.16, 1, 0.3, 1],
|
||||
onUpdate: (value) => {
|
||||
element.style.setProperty("--start", String(value));
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
[inactiveZone, proximity, movementDuration]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (disabled) return;
|
||||
|
||||
const handleScroll = () => handleMove();
|
||||
const handlePointerMove = (e: PointerEvent) => handleMove(e);
|
||||
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
document.body.addEventListener("pointermove", handlePointerMove, {
|
||||
passive: true,
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (animationFrameRef.current) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
}
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
document.body.removeEventListener("pointermove", handlePointerMove);
|
||||
};
|
||||
}, [handleMove, disabled]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
"pointer-events-none absolute -inset-px hidden rounded-[inherit] border opacity-0 transition-opacity",
|
||||
glow && "opacity-100",
|
||||
variant === "white" && "border-white",
|
||||
disabled && "!block"
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
ref={containerRef}
|
||||
style={
|
||||
{
|
||||
"--blur": `${blur}px`,
|
||||
"--spread": spread,
|
||||
"--start": "0",
|
||||
"--active": "0",
|
||||
"--glowingeffect-border-width": `${borderWidth}px`,
|
||||
"--repeating-conic-gradient-times": "5",
|
||||
"--gradient":
|
||||
variant === "white"
|
||||
? `repeating-conic-gradient(
|
||||
from 236.84deg at 50% 50%,
|
||||
var(--black),
|
||||
var(--black) calc(25% / var(--repeating-conic-gradient-times))
|
||||
)`
|
||||
: `radial-gradient(circle, #dd7bbb 10%, #dd7bbb00 20%),
|
||||
radial-gradient(circle at 40% 40%, #d79f1e 5%, #d79f1e00 15%),
|
||||
radial-gradient(circle at 60% 60%, #5a922c 10%, #5a922c00 20%),
|
||||
radial-gradient(circle at 40% 60%, #4c7894 10%, #4c789400 20%),
|
||||
repeating-conic-gradient(
|
||||
from 236.84deg at 50% 50%,
|
||||
#dd7bbb 0%,
|
||||
#d79f1e calc(25% / var(--repeating-conic-gradient-times)),
|
||||
#5a922c calc(50% / var(--repeating-conic-gradient-times)),
|
||||
#4c7894 calc(75% / var(--repeating-conic-gradient-times)),
|
||||
#dd7bbb calc(100% / var(--repeating-conic-gradient-times))
|
||||
)`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
"pointer-events-none absolute inset-0 rounded-[inherit] opacity-100 transition-opacity",
|
||||
glow && "opacity-100",
|
||||
blur > 0 && "blur-[var(--blur)] ",
|
||||
className,
|
||||
disabled && "!hidden"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"glow",
|
||||
"rounded-[inherit]",
|
||||
'after:content-[""] after:rounded-[inherit] after:absolute after:inset-[calc(-1*var(--glowingeffect-border-width))]',
|
||||
"after:[border:var(--glowingeffect-border-width)_solid_transparent]",
|
||||
"after:[background:var(--gradient)] after:[background-attachment:fixed]",
|
||||
"after:opacity-[var(--active)] after:transition-opacity after:duration-300",
|
||||
"after:[mask-clip:padding-box,border-box]",
|
||||
"after:[mask-composite:intersect]",
|
||||
"after:[mask-image:linear-gradient(#0000,#0000),conic-gradient(from_calc((var(--start)-var(--spread))*1deg),#00000000_0deg,#fff,#00000000_calc(var(--spread)*2deg))]"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
GlowingEffect.displayName = "GlowingEffect";
|
||||
|
||||
export { GlowingEffect };
|
||||
288
src/components/ui/resizable-navbar.tsx
Normal file
288
src/components/ui/resizable-navbar.tsx
Normal file
@@ -0,0 +1,288 @@
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Menu as IconMenu, X as IconX } from "lucide-react";
|
||||
import {
|
||||
motion,
|
||||
AnimatePresence,
|
||||
useScroll,
|
||||
useMotionValueEvent,
|
||||
} from "motion/react";
|
||||
|
||||
import React, { useRef, useState } from "react";
|
||||
|
||||
|
||||
interface NavbarProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface NavBodyProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
interface NavItemsProps {
|
||||
items: {
|
||||
name: string;
|
||||
link: string;
|
||||
}[];
|
||||
className?: string;
|
||||
onItemClick?: () => void;
|
||||
}
|
||||
|
||||
interface MobileNavProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
interface MobileNavHeaderProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface MobileNavMenuProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export const Navbar = ({ children, className }: NavbarProps) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const { scrollY } = useScroll({
|
||||
target: ref,
|
||||
offset: ["start start", "end start"],
|
||||
});
|
||||
const [visible, setVisible] = useState<boolean>(false);
|
||||
|
||||
useMotionValueEvent(scrollY, "change", (latest) => {
|
||||
if (latest > 100) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
// IMPORTANT: Change this to class of `fixed` if you want the navbar to be fixed
|
||||
className={cn("sticky inset-x-0 top-4 lg:top-6 xl:top-8 z-40 w-full", className)}
|
||||
>
|
||||
{React.Children.map(children, (child) =>
|
||||
React.isValidElement(child)
|
||||
? React.cloneElement(
|
||||
child as React.ReactElement<{ visible?: boolean }>,
|
||||
{ visible },
|
||||
)
|
||||
: child,
|
||||
)}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const NavBody = ({ children, className, visible }: NavBodyProps) => {
|
||||
return (
|
||||
<motion.div
|
||||
animate={{
|
||||
backdropFilter: visible ? "blur(10px)" : "none",
|
||||
boxShadow: visible
|
||||
? "0 0 24px rgba(34, 42, 53, 0.06), 0 1px 1px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(34, 42, 53, 0.04), 0 0 4px rgba(34, 42, 53, 0.08), 0 16px 68px rgba(47, 48, 55, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1) inset"
|
||||
: "none",
|
||||
width: visible ? "40%" : "100%",
|
||||
y: visible ? 20 : 0,
|
||||
}}
|
||||
transition={{
|
||||
type: "spring",
|
||||
stiffness: 200,
|
||||
damping: 50,
|
||||
}}
|
||||
style={{
|
||||
minWidth: "800px",
|
||||
}}
|
||||
className={cn(
|
||||
"relative z-[60] mx-auto hidden w-full max-w-7xl flex-row items-center justify-between self-start rounded-full bg-transparent px-4 py-2 lg:flex dark:bg-transparent",
|
||||
visible && "bg-white/80 dark:bg-neutral-950/80",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const NavItems = ({ items, className, onItemClick }: NavItemsProps) => {
|
||||
const [hovered, setHovered] = useState<number | null>(null);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
onMouseLeave={() => setHovered(null)}
|
||||
className={cn(
|
||||
"absolute inset-0 hidden flex-1 flex-row items-center justify-center space-x-2 text-sm font-medium text-zinc-600 transition duration-200 hover:text-zinc-800 lg:flex lg:space-x-2",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{items.map((item, idx) => (
|
||||
<a
|
||||
onMouseEnter={() => setHovered(idx)}
|
||||
onClick={onItemClick}
|
||||
className="relative px-4 py-2 text-neutral-600 dark:text-neutral-300"
|
||||
key={`link-${idx}`}
|
||||
href={item.link}
|
||||
>
|
||||
{hovered === idx && (
|
||||
<motion.div
|
||||
layoutId="hovered"
|
||||
className="absolute inset-0 h-full w-full rounded-full bg-gray-100 dark:bg-neutral-800"
|
||||
/>
|
||||
)}
|
||||
<span className="relative z-20">{item.name}</span>
|
||||
</a>
|
||||
))}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileNav = ({ children, className, visible }: MobileNavProps) => {
|
||||
return (
|
||||
<motion.div
|
||||
animate={{
|
||||
backdropFilter: visible ? "blur(10px)" : "none",
|
||||
boxShadow: visible
|
||||
? "0 0 24px rgba(34, 42, 53, 0.06), 0 1px 1px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(34, 42, 53, 0.04), 0 0 4px rgba(34, 42, 53, 0.08), 0 16px 68px rgba(47, 48, 55, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1) inset"
|
||||
: "none",
|
||||
width: visible ? "90%" : "100%",
|
||||
paddingRight: visible ? "12px" : "0px",
|
||||
paddingLeft: visible ? "12px" : "0px",
|
||||
borderRadius: visible ? "4px" : "2rem",
|
||||
y: visible ? 20 : 0,
|
||||
}}
|
||||
transition={{
|
||||
type: "spring",
|
||||
stiffness: 200,
|
||||
damping: 50,
|
||||
}}
|
||||
className={cn(
|
||||
"relative z-50 mx-auto flex w-full max-w-[calc(100vw-2rem)] flex-col items-center justify-between bg-transparent px-0 py-2 lg:hidden",
|
||||
visible && "bg-white/80 dark:bg-neutral-950/80",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileNavHeader = ({
|
||||
children,
|
||||
className,
|
||||
}: MobileNavHeaderProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-full flex-row items-center justify-between",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileNavMenu = ({
|
||||
children,
|
||||
className,
|
||||
isOpen,
|
||||
onClose,
|
||||
}: MobileNavMenuProps) => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className={cn(
|
||||
"absolute inset-x-0 top-16 z-50 flex w-full flex-col items-start justify-start gap-4 rounded-lg bg-white px-4 py-8 shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] dark:bg-neutral-950",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileNavToggle = ({
|
||||
isOpen,
|
||||
onClick,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onClick: () => void;
|
||||
}) => {
|
||||
return isOpen ? (
|
||||
<IconX className="text-black dark:text-white" onClick={onClick} />
|
||||
) : (
|
||||
<IconMenu className="text-black dark:text-white" onClick={onClick} />
|
||||
);
|
||||
};
|
||||
|
||||
export const NavbarLogo = () => {
|
||||
return (
|
||||
<a
|
||||
href="/"
|
||||
className="relative z-20 mr-4 flex items-center space-x-4 px-2 py-1 text-sm font-normal text-black"
|
||||
>
|
||||
<img
|
||||
src="/neodlp.svg"
|
||||
alt="logo"
|
||||
width={30}
|
||||
height={30}
|
||||
/>
|
||||
<span className="font-bold text-2xl text-black dark:text-white">NeoDLP</span>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export const NavbarButton = ({
|
||||
href,
|
||||
as: Tag = "a",
|
||||
children,
|
||||
className,
|
||||
variant = "primary",
|
||||
...props
|
||||
}: {
|
||||
href?: string;
|
||||
as?: React.ElementType;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
variant?: "primary" | "secondary" | "dark" | "gradient";
|
||||
} & (
|
||||
| React.ComponentPropsWithoutRef<"a">
|
||||
| React.ComponentPropsWithoutRef<"button">
|
||||
)) => {
|
||||
const baseStyles =
|
||||
"px-4 py-2 rounded-md bg-white button bg-white text-black text-sm font-bold relative cursor-pointer hover:-translate-y-0.5 transition duration-200 inline-block text-center";
|
||||
|
||||
const variantStyles = {
|
||||
primary:
|
||||
"shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]",
|
||||
secondary: "bg-transparent shadow-none dark:text-white",
|
||||
dark: "bg-black text-white shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset]",
|
||||
gradient:
|
||||
"bg-gradient-to-b from-blue-500 to-blue-700 text-white shadow-[0px_2px_0px_0px_rgba(255,255,255,0.3)_inset]",
|
||||
};
|
||||
|
||||
return (
|
||||
<Tag
|
||||
href={href || undefined}
|
||||
className={cn(baseStyles, variantStyles[variant], className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
26
src/components/ui/separator.tsx
Normal file
26
src/components/ui/separator.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Separator({
|
||||
className,
|
||||
orientation = "horizontal",
|
||||
decorative = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
||||
return (
|
||||
<SeparatorPrimitive.Root
|
||||
data-slot="separator-root"
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Separator }
|
||||
52
src/components/ui/sliding-button.tsx
Normal file
52
src/components/ui/sliding-button.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import React, { type ReactNode } from "react";
|
||||
|
||||
export const SlidingButton = ({
|
||||
children,
|
||||
slidingContent,
|
||||
as: Tag = "button",
|
||||
href,
|
||||
target,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
children: ReactNode;
|
||||
slidingContent: ReactNode;
|
||||
as?: React.ElementType;
|
||||
href?: string;
|
||||
target?: string;
|
||||
className?: string;
|
||||
} & (
|
||||
| React.ComponentPropsWithoutRef<"a">
|
||||
| React.ComponentPropsWithoutRef<"button">
|
||||
)) => {
|
||||
return (
|
||||
<Tag
|
||||
className={cn(
|
||||
"px-4 py-2 rounded-md bg-black dark:bg-white dark:text-black text-white text-center relative overflow-hidden cursor-pointer flex justify-center",
|
||||
`group/sliding-button`,
|
||||
className
|
||||
)}
|
||||
href={href}
|
||||
target={target}
|
||||
{...props}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'text-center transition duration-500 flex flex-col justify-center items-center',
|
||||
`group-hover/sliding-button:translate-x-60`
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center justify-center absolute inset-0 transition duration-500 text-white z-20',
|
||||
`-translate-x-60 group-hover/sliding-button:translate-x-0`
|
||||
)}
|
||||
>
|
||||
{slidingContent}
|
||||
</div>
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
23
src/components/ui/sonner.tsx
Normal file
23
src/components/ui/sonner.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme()
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Toaster }
|
||||
78
src/components/ui/wobble-card.tsx
Normal file
78
src/components/ui/wobble-card.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import { motion } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const WobbleCard = ({
|
||||
children,
|
||||
containerClassName,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
containerClassName?: string;
|
||||
className?: string;
|
||||
}) => {
|
||||
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
|
||||
const handleMouseMove = (event: React.MouseEvent<HTMLElement>) => {
|
||||
const { clientX, clientY } = event;
|
||||
const rect = event.currentTarget.getBoundingClientRect();
|
||||
const x = (clientX - (rect.left + rect.width / 2)) / 20;
|
||||
const y = (clientY - (rect.top + rect.height / 2)) / 20;
|
||||
setMousePosition({ x, y });
|
||||
};
|
||||
return (
|
||||
<motion.section
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
onMouseLeave={() => {
|
||||
setIsHovering(false);
|
||||
setMousePosition({ x: 0, y: 0 });
|
||||
}}
|
||||
style={{
|
||||
transform: isHovering
|
||||
? `translate3d(${mousePosition.x}px, ${mousePosition.y}px, 0) scale3d(1, 1, 1)`
|
||||
: "translate3d(0px, 0px, 0) scale3d(1, 1, 1)",
|
||||
transition: "transform 0.1s ease-out",
|
||||
}}
|
||||
className={cn(
|
||||
"mx-auto w-full bg-indigo-800 relative rounded-2xl overflow-hidden",
|
||||
containerClassName
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="relative h-full [background-image:radial-gradient(88%_100%_at_top,rgba(255,255,255,0.5),rgba(255,255,255,0))] sm:mx-0 sm:rounded-2xl overflow-hidden"
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 10px 32px rgba(34, 42, 53, 0.12), 0 1px 1px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(34, 42, 53, 0.05), 0 4px 6px rgba(34, 42, 53, 0.08), 0 24px 108px rgba(47, 48, 55, 0.10)",
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
style={{
|
||||
transform: isHovering
|
||||
? `translate3d(${-mousePosition.x}px, ${-mousePosition.y}px, 0) scale3d(1.03, 1.03, 1)`
|
||||
: "translate3d(0px, 0px, 0) scale3d(1, 1, 1)",
|
||||
transition: "transform 0.1s ease-out",
|
||||
}}
|
||||
className={cn("h-full px-4 py-20 sm:px-10", className)}
|
||||
>
|
||||
<Noise />
|
||||
{children}
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
const Noise = () => {
|
||||
return (
|
||||
<div
|
||||
className="absolute inset-0 w-full h-full scale-[1.2] transform opacity-10 [mask-image:radial-gradient(#fff,transparent,75%)]"
|
||||
style={{
|
||||
backgroundImage: "url(/noise.webp)",
|
||||
backgroundSize: "30%",
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
};
|
||||
58
src/layouts/main.astro
Normal file
58
src/layouts/main.astro
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
import '@/styles/global.css';
|
||||
import NavBar from '@/components/navbar';
|
||||
import Footer from '@/components/footer';
|
||||
import { ClientRouter } from 'astro:transitions';
|
||||
import LoadingIndicator from 'astro-loading-indicator/component';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<meta name="description" content={description ?? 'no description'} />
|
||||
<link rel="icon" type="image/svg+xml" href="/neodlp.svg" />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
<title>{title ?? 'untitled'}</title>
|
||||
<ClientRouter />
|
||||
<LoadingIndicator color='var(--foreground)' />
|
||||
</head>
|
||||
<body class="relative min-h-screen bg-white dark:bg-black">
|
||||
<NavBar client:load />
|
||||
<main class="pb-10 pt-20">
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
<Toaster client:load />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script is:inline>
|
||||
function setDarkMode(document) {
|
||||
const getThemePreference = () => {
|
||||
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
|
||||
return localStorage.getItem('theme');
|
||||
}
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'theme-light';
|
||||
};
|
||||
const isDark = getThemePreference() === 'dark';
|
||||
document.documentElement.classList[isDark ? 'add' : 'remove']('dark');
|
||||
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const observer = new MutationObserver(() => {
|
||||
const isDark = document.documentElement.classList.contains('dark');
|
||||
localStorage.setItem('theme', isDark ? 'dark' : 'theme-light');
|
||||
});
|
||||
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
||||
}
|
||||
}
|
||||
|
||||
setDarkMode(document);
|
||||
|
||||
document.addEventListener('astro:before-swap', (ev) => {
|
||||
setDarkMode(ev.newDocument);
|
||||
});
|
||||
</script>
|
||||
30
src/lib/utils.ts
Normal file
30
src/lib/utils.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { OS } from "@/types/os";
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export function getOS(): OS {
|
||||
const userAgent = window.navigator.userAgent;
|
||||
const platform = (window.navigator as any)?.userAgentData?.platform || window.navigator.platform;
|
||||
|
||||
const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K', 'macOS'];
|
||||
const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
|
||||
const iosPlatforms = ['iPhone', 'iPad', 'iPod'];
|
||||
|
||||
if (macosPlatforms.includes(platform)) {
|
||||
return 'macos';
|
||||
} else if (iosPlatforms.includes(platform)) {
|
||||
return 'ios';
|
||||
} else if (windowsPlatforms.includes(platform)) {
|
||||
return 'windows';
|
||||
} else if (/Android/.test(userAgent)) {
|
||||
return 'android';
|
||||
} else if (/Linux/.test(platform)) {
|
||||
return 'linux';
|
||||
} else {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
9
src/pages/dmca.astro
Normal file
9
src/pages/dmca.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
export const prerender = true;
|
||||
import DmcaNoticeSection from '@/components/DmcaNoticeSection';
|
||||
import Main from '@/layouts/main.astro';
|
||||
---
|
||||
|
||||
<Main title="DMCA Notice - NeoDLP">
|
||||
<DmcaNoticeSection client:load />
|
||||
</Main>
|
||||
68
src/pages/download.astro
Normal file
68
src/pages/download.astro
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
import AllDownloadsSection from '@/components/AllDowloadsSection';
|
||||
import Main from '@/layouts/main.astro';
|
||||
|
||||
// Default fallback data in case fetch fails
|
||||
let data = {
|
||||
version: "0.0.0",
|
||||
notes: "### Unable to fetch latest release information\n\nPlease check back later or visit our [GitHub repository](https://github.com/neosubhamoy/neodlp) for the latest releases.",
|
||||
pub_date: new Date().toISOString(),
|
||||
platforms: {
|
||||
"darwin-x86_64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_x64.app.tar.gz"
|
||||
},
|
||||
"darwin-aarch64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_aarch64.app.tar.gz"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_0.0.0_x64-setup.exe"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch("https://github.com/neosubhamoy/neodlp/releases/latest/download/latest.json");
|
||||
data = await response.json();
|
||||
|
||||
// Add additional custom platform objects
|
||||
const baseUrl = "https://github.com/neosubhamoy/neodlp/releases/download/v" + data.version + "/";
|
||||
const additionalPlatforms = {
|
||||
"darwin-x86_64-dmg": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_x64.dmg`
|
||||
},
|
||||
"darwin-aarch64-dmg": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_aarch64.dmg`
|
||||
},
|
||||
"windows-x86_64-msi": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_x64_en-US.msi`
|
||||
},
|
||||
"linux-x86_64-deb": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_amd64.deb`
|
||||
},
|
||||
"linux-x86_64-rpm": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP-${data.version}-1.x86_64.rpm`
|
||||
},
|
||||
"linux-x86_64-aur": {
|
||||
signature: "",
|
||||
url: `https://aur.archlinux.org/cgit/aur.git/snapshot/neodlp.tar.gz`
|
||||
}
|
||||
};
|
||||
|
||||
// Merge additional custom platforms with the original data
|
||||
data.platforms = { ...data.platforms, ...additionalPlatforms };
|
||||
} catch (error) {
|
||||
console.error("Error fetching the latest release information:", error);
|
||||
}
|
||||
---
|
||||
|
||||
<Main title="All Downloads - NeoDLP">
|
||||
<AllDownloadsSection release={data} client:load />
|
||||
</Main>
|
||||
28
src/pages/extension.astro
Normal file
28
src/pages/extension.astro
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
import Main from '@/layouts/main.astro';
|
||||
import GetExtensionSection from '@/components/GetExtensionSection';
|
||||
|
||||
let data = {
|
||||
version: "0.0.0",
|
||||
notes: "### Unable to fetch latest release information\n\nPlease check back later or visit our [GitHub repository](https://github.com/neosubhamoy/neodlp-extension) for the latest releases.",
|
||||
browsers: {
|
||||
chrome: {
|
||||
url: "https://github.com/neosubhamoy/neodlp-extension/releases/download/v0.0.0/neodlp-extension-0.0.0-chrome.zip"
|
||||
},
|
||||
firefox: {
|
||||
url: "https://github.com/neosubhamoy/neodlp-extension/releases/download/v0.0.0/neodlp-extension-0.0.0-firefox.zip"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch("https://github.com/neosubhamoy/neodlp-extension/releases/latest/download/latest.json");
|
||||
data = await response.json();
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
---
|
||||
|
||||
<Main title="Get NeoDLP Extension - NeoDLP">
|
||||
<GetExtensionSection release={data} />
|
||||
</Main>
|
||||
72
src/pages/index.astro
Normal file
72
src/pages/index.astro
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
import FeaturesSection from '@/components/FeaturesSection';
|
||||
import HeroSection from '@/components/HeroSection';
|
||||
import HighlightSection from '@/components/HighlightSection';
|
||||
import Main from '@/layouts/main.astro';
|
||||
|
||||
// Default fallback data in case fetch fails
|
||||
let data = {
|
||||
version: "0.0.0",
|
||||
notes: "### Unable to fetch latest release information\n\nPlease check back later or visit our [GitHub repository](https://github.com/neosubhamoy/neodlp) for the latest releases.",
|
||||
pub_date: new Date().toISOString(),
|
||||
platforms: {
|
||||
"darwin-x86_64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_x64.app.tar.gz"
|
||||
},
|
||||
"darwin-aarch64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_aarch64.app.tar.gz"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
signature: "",
|
||||
url: "https://github.com/neosubhamoy/neodlp/releases/download/v0.0.0/NeoDLP_0.0.0_x64-setup.exe"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch("https://github.com/neosubhamoy/neodlp/releases/latest/download/latest.json");
|
||||
data = await response.json();
|
||||
|
||||
// Add additional custom platform objects
|
||||
const baseUrl = "https://github.com/neosubhamoy/neodlp/releases/download/v" + data.version + "/";
|
||||
const additionalPlatforms = {
|
||||
"darwin-x86_64-dmg": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_x64.dmg`
|
||||
},
|
||||
"darwin-aarch64-dmg": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_aarch64.dmg`
|
||||
},
|
||||
"windows-x86_64-msi": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_x64_en-US.msi`
|
||||
},
|
||||
"linux-x86_64-deb": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP_${data.version}_amd64.deb`
|
||||
},
|
||||
"linux-x86_64-rpm": {
|
||||
signature: "",
|
||||
url: baseUrl + `NeoDLP-${data.version}-1.x86_64.rpm`
|
||||
},
|
||||
"linux-x86_64-aur": {
|
||||
signature: "",
|
||||
url: `https://aur.archlinux.org/cgit/aur.git/snapshot/neodlp.tar.gz`
|
||||
}
|
||||
};
|
||||
|
||||
// Merge additional custom platforms with the original data
|
||||
data.platforms = { ...data.platforms, ...additionalPlatforms };
|
||||
} catch (error) {
|
||||
console.error("Error fetching the latest release information:", error);
|
||||
}
|
||||
---
|
||||
|
||||
<Main title="NeoDLP - Neo Downloader Plus | Official Website" description="NeoDLP (Neo Downloader Plus) is a fully Cross-Platform Video/Audio Downloader Desktop Application with Modern UI and Browser Integration.">
|
||||
<HeroSection release={data} client:load />
|
||||
<HighlightSection client:load />
|
||||
<FeaturesSection client:load />
|
||||
</Main>
|
||||
9
src/pages/privacy-policy.astro
Normal file
9
src/pages/privacy-policy.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
export const prerender = true;
|
||||
import PrivacyPolicySection from '@/components/PrivacyPolicySection';
|
||||
import Main from '@/layouts/main.astro';
|
||||
---
|
||||
|
||||
<Main title="Privacy Policy - NeoDLP">
|
||||
<PrivacyPolicySection client:load />
|
||||
</Main>
|
||||
9
src/pages/terms-of-use.astro
Normal file
9
src/pages/terms-of-use.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
export const prerender = true;
|
||||
import TermsOfUseSection from '@/components/TermsOfUseSection';
|
||||
import Main from '@/layouts/main.astro';
|
||||
---
|
||||
|
||||
<Main title="Terms Of Use - NeoDLP">
|
||||
<TermsOfUseSection client:load />
|
||||
</Main>
|
||||
120
src/styles/global.css
Normal file
120
src/styles/global.css
Normal file
@@ -0,0 +1,120 @@
|
||||
@import 'tailwindcss';
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.141 0.005 285.823);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||
--primary: oklch(0.21 0.006 285.885);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.967 0.001 286.375);
|
||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||
--muted: oklch(0.967 0.001 286.375);
|
||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||
--accent: oklch(0.967 0.001 286.375);
|
||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.92 0.004 286.32);
|
||||
--input: oklch(0.92 0.004 286.32);
|
||||
--ring: oklch(0.705 0.015 286.067);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||
--sidebar-primary: oklch(0.21 0.006 285.885);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.705 0.015 286.067);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.92 0.004 286.32);
|
||||
--primary-foreground: oklch(0.21 0.006 285.885);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.552 0.016 285.938);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.21 0.006 285.885);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.552 0.016 285.938);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
1
src/types/os.ts
Normal file
1
src/types/os.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type OS = 'windows' | 'macos' | 'linux' | 'android' | 'ios' | 'unknown';
|
||||
21
src/types/release.ts
Normal file
21
src/types/release.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface LatestRelease {
|
||||
version: string;
|
||||
notes: string;
|
||||
pub_date: string;
|
||||
platforms: {
|
||||
[key: string]: {
|
||||
signature: string;
|
||||
url: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface LatestExtensionRelease {
|
||||
version: string;
|
||||
notes: string;
|
||||
browsers: {
|
||||
[key: string]: {
|
||||
url: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [
|
||||
".astro/types.d.ts",
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"dist"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user