Fresh start
43
.gitignore
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
.vercel
|
||||
36
README.md
Normal file
@ -0,0 +1,36 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
114
app/Approach.js
Normal file
@ -0,0 +1,114 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import { CanvasRevealEffect } from "./components/canvas-reveal-effect";
|
||||
import { Button } from "./components/Button";
|
||||
|
||||
export function CanvasRevealEffectDemo() {
|
||||
return (
|
||||
<div className="bg-[#010217]">
|
||||
<h1 className="font-bold text-3xl text-center text-white">
|
||||
My <span className="text-fuchsia-300">approach</span>
|
||||
</h1>
|
||||
<div className="py-20 flex flex-col lg:flex-row items-center justify-center gap-6 px-8">
|
||||
<Card
|
||||
title="Development & Progress"
|
||||
description="Once we agree on the plan, I cue my lofi playlist and dive into coding. From selection to polished code, I keep you updated every step."
|
||||
buttonText="Phase 1"
|
||||
>
|
||||
<CanvasRevealEffect
|
||||
animationSpeed={5.1}
|
||||
containerClassName="bg-emerald-900"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Launch & Delivery"
|
||||
description="After polishing the code and final checks, I ensure smooth delivery and deployment, keeping everything transparent and simple."
|
||||
buttonText="Phase 2"
|
||||
>
|
||||
<CanvasRevealEffect
|
||||
animationSpeed={3}
|
||||
containerClassName="bg-black"
|
||||
colors={[
|
||||
[236, 72, 153],
|
||||
[232, 121, 249],
|
||||
]}
|
||||
dotSize={2}
|
||||
/>
|
||||
<div className="absolute inset-0 [mask-image:radial-gradient(400px_at_center,white,transparent)] bg-black/50 dark:bg-black/90" />
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Post-Launch Support"
|
||||
description="I'm available for maintenance, updates, and improvements even after launch. Long-term support is part of the deal."
|
||||
buttonText="Phase 3"
|
||||
>
|
||||
<CanvasRevealEffect
|
||||
animationSpeed={3}
|
||||
containerClassName="bg-sky-600"
|
||||
colors={[[125, 211, 252]]}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Card = ({ title, description, children, buttonText }) => {
|
||||
const [hovered, setHovered] = React.useState(false);
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
className="max-w-xs w-full mx-auto p-4 relative h-[30rem] rounded-xl flex flex-col justify-between bg-[linear-gradient(103.4deg,_#04071D_16.66%,_#0C0E23_81.61%)]"
|
||||
>
|
||||
{/* الزوائد في الزوايا */}
|
||||
<span className="absolute -top-4 -left-2 text-gray-600 text-5xl font-thin z-20">
|
||||
+
|
||||
</span>
|
||||
<span className="absolute -top-4 -right-1 text-gray-600 text-5xl font-thin z-20">
|
||||
+
|
||||
</span>
|
||||
<span className="absolute -bottom-1 -left-1 text-gray-600 text-5xl font-thin z-20">
|
||||
+
|
||||
</span>
|
||||
<span className="absolute -bottom-1 right-1 text-gray-600 text-5xl font-thin z-20">
|
||||
+
|
||||
</span>
|
||||
|
||||
{/* خلفية تأثير الحركة */}
|
||||
<AnimatePresence>
|
||||
{hovered && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
className="absolute inset-0 z-0"
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* محتوى الكارت */}
|
||||
<div className="relative z-10 flex flex-col justify-between h-full text-center">
|
||||
{hovered && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.4 }}
|
||||
>
|
||||
<h2 className="text-white font-bold text-lg mb-2">{title}</h2>
|
||||
<p className="text-gray-300 text-sm">{description}</p>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{/* زر مخصص لكل كارت */}
|
||||
<div className="flex justify-center mt-auto relative bottom-48">
|
||||
<Button className="w-36 text-sm">{buttonText}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
39
app/Col2.js
Normal file
@ -0,0 +1,39 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import SimpleGlobe from "./components/Moon"; // عدل المسار حسب مكان الملف
|
||||
|
||||
export default function Col2() {
|
||||
return (
|
||||
<div className="col flex flex-col gap-10 px-4 sm:px-6 lg:px-8">
|
||||
{/* القسم الأول */}
|
||||
<div className="bg-[#010217] border border-gray-500 p-5 relative min-h-[200px] overflow-hidden rounded-md">
|
||||
<h1 className="text-white text-xl sm:text-2xl lg:text-3xl font-bold relative top-5 left-5 max-w-full">
|
||||
I'm very flexible with time <br /> zone communications
|
||||
</h1>
|
||||
<div className="relative top-4 flex justify-center">
|
||||
<img src={"/mo.png"} alt="Moon Image" className="max-w-full h-auto" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* القسم الثاني */}
|
||||
<div className="bg-[#010217] border border-gray-500 grid grid-cols-1 md:grid-cols-2 items-center rounded-md">
|
||||
<div className="text-white p-5">
|
||||
<p className="font-thin text-gray-400 mb-3">
|
||||
I constantly try to improve <br />
|
||||
<span className="font-bold text-4xl text-white whitespace-nowrap">
|
||||
My tech stack
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-5 flex justify-center">
|
||||
<img
|
||||
src={"/group.png"}
|
||||
alt="Group Image"
|
||||
className="max-w-full h-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
72
app/Footer.js
Normal file
@ -0,0 +1,72 @@
|
||||
import { GridBackgroundDemo } from "./components/Line";
|
||||
import { FaFacebookF, FaTwitter, FaInstagram } from "react-icons/fa";
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className="relative w-full overflow-hidden">
|
||||
{/* الجريد جوه الفوتر نفسه */}
|
||||
<div className="absolute inset-0 -z-10">
|
||||
<GridBackgroundDemo />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-16 px-6 w-full min-h-[16rem]">
|
||||
<p className="font-bold text-white sm:text-lg md:text-3xl text-center z-10 max-w-3xl">
|
||||
Ready to take <span className="text-fuchsia-300">your</span> digital
|
||||
<br />
|
||||
presence to the next level
|
||||
</p>
|
||||
|
||||
<p className="text-gray-300 mt-4 text-xs z-10 max-w-3xl text-center">
|
||||
Reach out to me today and let's discuss how I can help you achieve
|
||||
your goal
|
||||
</p>
|
||||
|
||||
<button
|
||||
className="mt-10 z-10 px-6 py-3 rounded-md font-semibold text-white
|
||||
backdrop-blur-md bg-gradient-to-r from-white/10 to-white/5 border border-white/10
|
||||
hover:text-white transition-all duration-300"
|
||||
>
|
||||
Contact Me Now
|
||||
</button>
|
||||
|
||||
{/* السطر السفلي */}
|
||||
<div className="grid sm:grid-cols-1 sm:items-center md:flex justify-between items-center w-full max-w-screen-xl relative top-10 text-xs px-4 text-white gap-6">
|
||||
<p className="whitespace-nowrap ">
|
||||
© 2024 Admin Khadeja. All rights reserved.
|
||||
</p>
|
||||
<div className="flex space-x-3 ">
|
||||
<a
|
||||
href="https://facebook.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Facebook"
|
||||
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
|
||||
>
|
||||
<FaFacebookF className="w-4 h-4" />
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Twitter"
|
||||
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
|
||||
>
|
||||
<FaTwitter className="w-4 h-4" />
|
||||
</a>
|
||||
<a
|
||||
href="https://instagram.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Instagram"
|
||||
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
|
||||
>
|
||||
<FaInstagram className="w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
56
app/Hero.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
import { Spotlight } from "./components/SpotLight";
|
||||
import { GridBackgroundDemo } from "./components/Line";
|
||||
import { Button } from "./components/Button";
|
||||
import { TextGenerateEffect } from "./components/text-generate-effect";
|
||||
|
||||
import { FloatingNav } from "./components/Navbar";
|
||||
|
||||
function Hero() {
|
||||
return (
|
||||
<div className="relative bg-[#010217] overflow-hidden p-4 h-screen flex flex-col justify-center items-center">
|
||||
<FloatingNav />
|
||||
|
||||
{/* خلفية الخطوط */}
|
||||
<GridBackgroundDemo />
|
||||
|
||||
{/* Spotlights */}
|
||||
<Spotlight
|
||||
className="absolute top-[20%] left-[80px] opacity-70 z-10 pointer-events-none"
|
||||
fill="white"
|
||||
/>
|
||||
<Spotlight
|
||||
className="absolute top-[20%] left-[240px] opacity-20 z-10 pointer-events-none"
|
||||
fill="purple"
|
||||
/>
|
||||
<Spotlight
|
||||
className="absolute top-[10%] left-[90%] opacity-100 z-30 pointer-events-none"
|
||||
fill="white"
|
||||
/>
|
||||
|
||||
{/* المحتوى النصي */}
|
||||
<div className="absolute top-50 left-1/2 transform -translate-x-1/2 z-40 text-white text-center px-4">
|
||||
<h1 className="capitalize">dynamic web magic with next.js</h1>
|
||||
<TextGenerateEffect className="text-[#caccdc] text-center font-bold sm:text-xl md:text-4xl capitalize">
|
||||
<>
|
||||
<p className="text-[#caccdc] ">
|
||||
{" "}
|
||||
transforming concepts into seamless
|
||||
</p>{" "}
|
||||
<span className="text-fuchsia-300 text-5xl">user experiences</span>
|
||||
<h1 className="text-sm font-normal mt-3 text-[#caccdc] ">
|
||||
Hi, I'm Adrian, a Next.js developer based in Croatia.
|
||||
</h1>
|
||||
</>
|
||||
</TextGenerateEffect>
|
||||
</div>
|
||||
|
||||
{/* زرار Show my Work */}
|
||||
<div className="flex relative bottom-10 z-40">
|
||||
<Button className={"w-52"}>Show my Work</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Hero;
|
||||
32
app/Main.js
Normal file
@ -0,0 +1,32 @@
|
||||
import React from "react";
|
||||
import Col2 from "./Col2";
|
||||
|
||||
function Main() {
|
||||
return (
|
||||
<div className="bg-[#010217] flex flex-col lg:flex-row w-full p-4 sm:p-6 lg:p-20 gap-6 relative">
|
||||
{/* القسم الأيسر */}
|
||||
<div className="relative border border-gray-500 bg-[#050511a2] w-full lg:w-1/2 p-4 flex flex-col items-center justify-center">
|
||||
{/* الصورة */}
|
||||
<div className="w-full max-w-[400px]">
|
||||
<img
|
||||
src="/eaarth.png"
|
||||
alt="img4"
|
||||
className="w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* النص */}
|
||||
<p className="text-white font-bold text-xl sm:text-2xl lg:text-3xl text-center max-w-[400px] absolute bottom-16 left-6">
|
||||
I prioritize client collaboration, fostering open communication
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* القسم الأيمن */}
|
||||
<div className="w-full lg:w-1/2">
|
||||
<Col2 />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Main;
|
||||
22
app/Work.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import Work2 from "./Work2";
|
||||
|
||||
function Work() {
|
||||
return (
|
||||
<div className="bg-red ">
|
||||
<h1 className="font-bold text-3xl text-white text-center">
|
||||
My <span className="text-fuchsia-300">work experience</span>
|
||||
</h1>
|
||||
<div className="w-full px-4 mt-5 mb-5">
|
||||
<div className=" sm:grid-col-1 md:grid grid-cols-2 gap-10 items-center justify-center mt-16 max-w-4xl mx-auto p-2 ">
|
||||
<Work2 src="/st.png" />
|
||||
<Work2 src="/st.png" />
|
||||
<Work2 src="/sss.png" />
|
||||
<Work2 src="/ss.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Work;
|
||||
23
app/Work2.js
Normal file
@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
|
||||
function Work2(props) {
|
||||
return (
|
||||
<div className="relative flex justify-center">
|
||||
<div className="animated-corner-card">
|
||||
<div className="flex items-center justify-center w-full h-full z-10 relative">
|
||||
<Image
|
||||
src={props.src}
|
||||
alt="img"
|
||||
width={400}
|
||||
height={100}
|
||||
className="object-contain"
|
||||
/>
|
||||
</div>
|
||||
<span className="corner-glow" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Work2;
|
||||
91
app/components/3d-pin.js
Normal file
@ -0,0 +1,91 @@
|
||||
'use client';
|
||||
import React, { useState } from 'react';
|
||||
import { motion } from 'framer-motion'; // صححنا الاستيراد من 'motion/react'
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export const PinContainer = ({
|
||||
children,
|
||||
title,
|
||||
href,
|
||||
className,
|
||||
containerClassName
|
||||
}) => {
|
||||
const [transform, setTransform] = useState('translate(-50%,-50%) rotateX(0deg)');
|
||||
|
||||
const onMouseEnter = () => {
|
||||
setTransform('translate(-50%,-50%) rotateX(40deg) scale(0.8)');
|
||||
};
|
||||
const onMouseLeave = () => {
|
||||
setTransform('translate(-50%,-50%) rotateX(0deg) scale(1)');
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
role="link"
|
||||
onClick={() => window.open(href || '/', '_blank')}
|
||||
className={cn('relative group/pin z-50 cursor-pointer', containerClassName)}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
perspective: '1000px',
|
||||
transform: 'rotateX(70deg) translateZ(0deg)',
|
||||
}}
|
||||
className="absolute left-1/2 top-1/2 ml-[0.09375rem] mt-4 -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<div
|
||||
style={{ transform }}
|
||||
className="absolute left-1/2 p-4 top-1/2 flex justify-start items-start rounded-2xl shadow-[0_8px_16px_rgb(0_0_0/0.4)] bg-black border border-white/[0.1] group-hover/pin:border-white/[0.2] transition duration-700 overflow-hidden"
|
||||
>
|
||||
<div className={cn('relative z-50', className)}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
<PinPerspective title={title} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const PinPerspective = ({ title }) => {
|
||||
return (
|
||||
<motion.div className="pointer-events-none w-96 h-80 flex items-center justify-center opacity-0 group-hover/pin:opacity-100 z-[60] transition duration-500">
|
||||
<div className="w-full h-full -mt-7 flex-none inset-0">
|
||||
<div className="absolute top-0 inset-x-0 flex justify-center">
|
||||
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-zinc-950 py-0.5 px-4 ring-1 ring-white/10">
|
||||
<span className="relative z-20 text-white text-xs font-bold inline-block py-0.5">
|
||||
{title}
|
||||
</span>
|
||||
<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/btn:opacity-40" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
perspective: '1000px',
|
||||
transform: 'rotateX(70deg) translateZ(0)',
|
||||
}}
|
||||
className="absolute left-1/2 top-1/2 ml-[0.09375rem] mt-4 -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<>
|
||||
{[0, 2, 4].map((delay) => (
|
||||
<motion.div
|
||||
key={delay}
|
||||
initial={{ opacity: 0, scale: 0, x: '-50%', y: '-50%' }}
|
||||
animate={{ opacity: [0, 1, 0.5, 0], scale: 1, z: 0 }}
|
||||
transition={{ duration: 6, repeat: Infinity, delay }}
|
||||
className="absolute left-1/2 top-1/2 h-[11.25rem] w-[11.25rem] rounded-full bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)]"
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
</div>
|
||||
|
||||
<>
|
||||
<motion.div className="absolute right-1/2 bottom-1/2 bg-gradient-to-b from-transparent to-cyan-500 translate-y-[14px] w-px h-20 group-hover/pin:h-40 blur-[2px]" />
|
||||
<motion.div className="absolute right-1/2 bottom-1/2 bg-gradient-to-b from-transparent to-cyan-500 translate-y-[14px] w-px h-20 group-hover/pin:h-40" />
|
||||
<motion.div className="absolute right-1/2 translate-x-[1.5px] bottom-1/2 bg-cyan-600 translate-y-[14px] w-[4px] h-[4px] rounded-full z-40 blur-[3px]" />
|
||||
<motion.div className="absolute right-1/2 translate-x-[0.5px] bottom-1/2 bg-cyan-300 translate-y-[14px] w-[2px] h-[2px] rounded-full z-40" />
|
||||
</>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
145
app/components/BackgroundGradientAnimation.js
Normal file
@ -0,0 +1,145 @@
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
export const BackgroundGradientAnimation = ({
|
||||
gradientBackgroundStart = "rgb(108, 0, 162)",
|
||||
gradientBackgroundEnd = "rgb(0, 17, 82)",
|
||||
firstColor = "18, 113, 255",
|
||||
secondColor = "221, 74, 255",
|
||||
thirdColor = "100, 220, 255",
|
||||
fourthColor = "200, 50, 50",
|
||||
fifthColor = "180, 180, 50",
|
||||
pointerColor = "140, 100, 255",
|
||||
size = "80%",
|
||||
blendingValue = "hard-light",
|
||||
children,
|
||||
className,
|
||||
interactive = true,
|
||||
containerClassName
|
||||
}) => {
|
||||
const interactiveRef = useRef(null);
|
||||
|
||||
const [curX, setCurX] = useState(0);
|
||||
const [curY, setCurY] = useState(0);
|
||||
const [tgX, setTgX] = useState(0);
|
||||
const [tgY, setTgY] = useState(0);
|
||||
useEffect(() => {
|
||||
document.body.style.setProperty("--gradient-background-start", gradientBackgroundStart);
|
||||
document.body.style.setProperty("--gradient-background-end", gradientBackgroundEnd);
|
||||
document.body.style.setProperty("--first-color", firstColor);
|
||||
document.body.style.setProperty("--second-color", secondColor);
|
||||
document.body.style.setProperty("--third-color", thirdColor);
|
||||
document.body.style.setProperty("--fourth-color", fourthColor);
|
||||
document.body.style.setProperty("--fifth-color", fifthColor);
|
||||
document.body.style.setProperty("--pointer-color", pointerColor);
|
||||
document.body.style.setProperty("--size", size);
|
||||
document.body.style.setProperty("--blending-value", blendingValue);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
function move() {
|
||||
if (!interactiveRef.current) {
|
||||
return;
|
||||
}
|
||||
setCurX(curX + (tgX - curX) / 20);
|
||||
setCurY(curY + (tgY - curY) / 20);
|
||||
interactiveRef.current.style.transform = `translate(${Math.round(curX)}px, ${Math.round(curY)}px)`;
|
||||
}
|
||||
|
||||
move();
|
||||
}, [tgX, tgY]);
|
||||
|
||||
const handleMouseMove = (event) => {
|
||||
if (interactiveRef.current) {
|
||||
const rect = interactiveRef.current.getBoundingClientRect();
|
||||
setTgX(event.clientX - rect.left);
|
||||
setTgY(event.clientY - rect.top);
|
||||
}
|
||||
};
|
||||
|
||||
const [isSafari, setIsSafari] = useState(false);
|
||||
useEffect(() => {
|
||||
setIsSafari(/^((?!chrome|android).)*safari/i.test(navigator.userAgent));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"h-screen w-screen relative overflow-hidden top-0 left-0 bg-[linear-gradient(40deg,var(--gradient-background-start),var(--gradient-background-end))]",
|
||||
containerClassName
|
||||
)}>
|
||||
<svg className="hidden">
|
||||
<defs>
|
||||
<filter id="blurMe">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
|
||||
<feColorMatrix
|
||||
in="blur"
|
||||
mode="matrix"
|
||||
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -8"
|
||||
result="goo" />
|
||||
<feBlend in="SourceGraphic" in2="goo" />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<div className={cn("", className)}>{children}</div>
|
||||
<div
|
||||
className={cn(
|
||||
"gradients-container h-full w-full blur-lg",
|
||||
isSafari ? "blur-2xl" : "[filter:url(#blurMe)_blur(40px)]"
|
||||
)}>
|
||||
<div
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_var(--first-color)_0,_var(--first-color)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
|
||||
`[transform-origin:center_center]`,
|
||||
`animate-first`,
|
||||
`opacity-100`
|
||||
)}></div>
|
||||
<div
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--second-color),_0.8)_0,_rgba(var(--second-color),_0)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
|
||||
`[transform-origin:calc(50%-400px)]`,
|
||||
`animate-second`,
|
||||
`opacity-100`
|
||||
)}></div>
|
||||
<div
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--third-color),_0.8)_0,_rgba(var(--third-color),_0)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
|
||||
`[transform-origin:calc(50%+400px)]`,
|
||||
`animate-third`,
|
||||
`opacity-100`
|
||||
)}></div>
|
||||
<div
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--fourth-color),_0.8)_0,_rgba(var(--fourth-color),_0)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
|
||||
`[transform-origin:calc(50%-200px)]`,
|
||||
`animate-fourth`,
|
||||
`opacity-70`
|
||||
)}></div>
|
||||
<div
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--fifth-color),_0.8)_0,_rgba(var(--fifth-color),_0)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
|
||||
`[transform-origin:calc(50%-800px)_calc(50%+800px)]`,
|
||||
`animate-fifth`,
|
||||
`opacity-100`
|
||||
)}></div>
|
||||
|
||||
{interactive && (
|
||||
<div
|
||||
ref={interactiveRef}
|
||||
onMouseMove={handleMouseMove}
|
||||
className={cn(
|
||||
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--pointer-color),_0.8)_0,_rgba(var(--pointer-color),_0)_50%)_no-repeat]`,
|
||||
`[mix-blend-mode:var(--blending-value)] w-full h-full -top-1/2 -left-1/2`,
|
||||
`opacity-70`
|
||||
)}></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
89
app/components/Button.js
Normal file
@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { motion } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function Button({
|
||||
children,
|
||||
containerClassName,
|
||||
className,
|
||||
as: Tag = "button",
|
||||
duration = 1,
|
||||
clockwise = true,
|
||||
...props
|
||||
}) {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const [direction, setDirection] = useState("TOP");
|
||||
|
||||
const rotateDirection = (currentDirection) => {
|
||||
const directions = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
|
||||
const currentIndex = directions.indexOf(currentDirection);
|
||||
const nextIndex = clockwise
|
||||
? (currentIndex - 1 + directions.length) % directions.length
|
||||
: (currentIndex + 1) % directions.length;
|
||||
return directions[nextIndex];
|
||||
};
|
||||
|
||||
const movingMap = {
|
||||
TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
BOTTOM:
|
||||
"radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
RIGHT:
|
||||
"radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
};
|
||||
|
||||
const highlight =
|
||||
"radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
|
||||
|
||||
useEffect(() => {
|
||||
if (!hovered) {
|
||||
const interval = setInterval(() => {
|
||||
setDirection((prevState) => rotateDirection(prevState));
|
||||
}, duration * 1000);
|
||||
return () => clearInterval(interval);
|
||||
}
|
||||
}, [hovered]);
|
||||
return (
|
||||
<Tag
|
||||
onMouseEnter={(event) => {
|
||||
setHovered(true);
|
||||
}}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
className={cn(
|
||||
"relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap gap-10 h-min justify-center overflow-visible p-px decoration-clone w-fit",
|
||||
containerClassName
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"w-auto text-white z-10 bg-black px-4 py-2 rounded-[inherit]",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<motion.div
|
||||
className={cn(
|
||||
"flex-none inset-0 overflow-hidden absolute z-0 rounded-[inherit]"
|
||||
)}
|
||||
style={{
|
||||
filter: "blur(2px)",
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
initial={{ background: movingMap[direction] }}
|
||||
animate={{
|
||||
background: hovered
|
||||
? [movingMap[direction], highlight]
|
||||
: movingMap[direction],
|
||||
}}
|
||||
transition={{ ease: "linear", duration: duration ?? 1 }}
|
||||
/>
|
||||
<div className="bg-black absolute z-1 flex-none inset-[2px] rounded-[100px]" />
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
21
app/components/Line.js
Normal file
@ -0,0 +1,21 @@
|
||||
export function GridBackgroundDemo({ children }) {
|
||||
return (
|
||||
<div className="relative flex h-[50rem] w-full items-center justify-center bg-[#010217]">
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
backgroundSize: "40px 40px",
|
||||
backgroundImage:
|
||||
"linear-gradient(to right, #2b2b3d 1px, transparent 1px), linear-gradient(to bottom, #2b2b3d 1px, transparent 1px)",
|
||||
// شيل الـ mask عشان لا يخفي النص
|
||||
// maskImage: "radial-gradient(ellipse at center, transparent 20%, black 80%)",
|
||||
// WebkitMaskImage: "radial-gradient(ellipse at center, transparent 20%, black 80%)",
|
||||
opacity: 0.3, // خفف من وضوح الشبكة عشان النص يبان
|
||||
}}
|
||||
/>
|
||||
<div className="relative z-10 w-full flex justify-center px-4">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
594
app/components/MackBookcroll.js
Normal file
@ -0,0 +1,594 @@
|
||||
"use client";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { motion, useScroll, useTransform } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
IconBrightnessDown,
|
||||
IconBrightnessUp,
|
||||
IconCaretRightFilled,
|
||||
IconCaretUpFilled,
|
||||
IconChevronUp,
|
||||
IconMicrophone,
|
||||
IconMoon,
|
||||
IconPlayerSkipForward,
|
||||
IconPlayerTrackNext,
|
||||
IconPlayerTrackPrev,
|
||||
IconTable,
|
||||
IconVolume,
|
||||
IconVolume2,
|
||||
IconVolume3,
|
||||
} from "@tabler/icons-react";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
import { IconWorld } from "@tabler/icons-react";
|
||||
import { IconCommand } from "@tabler/icons-react";
|
||||
import { IconCaretLeftFilled } from "@tabler/icons-react";
|
||||
import { IconCaretDownFilled } from "@tabler/icons-react";
|
||||
|
||||
|
||||
export const MacbookScroll = ({
|
||||
src,
|
||||
showGradient,
|
||||
title,
|
||||
badge
|
||||
}) => {
|
||||
const ref = useRef(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: ref,
|
||||
offset: ["start start", "end start"],
|
||||
});
|
||||
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (window && window.innerWidth < 768) {
|
||||
setIsMobile(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const scaleX = useTransform(scrollYProgress, [0, 0.3], [1.2, isMobile ? 1 : 1.5]);
|
||||
const scaleY = useTransform(scrollYProgress, [0, 0.3], [0.6, isMobile ? 1 : 1.5]);
|
||||
const translate = useTransform(scrollYProgress, [0, 1], [0, 1500]);
|
||||
const rotate = useTransform(scrollYProgress, [0.1, 0.12, 0.3], [-28, -28, 0]);
|
||||
const textTransform = useTransform(scrollYProgress, [0, 0.3], [0, 100]);
|
||||
const textOpacity = useTransform(scrollYProgress, [0, 0.2], [1, 0]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="flex min-h-[200vh] shrink-0 scale-75 transform -translate-x-36 -translate-y-32 flex-col items-center justify-start py-0 [perspective:800px] sm:w-[500px] md:w-full md:py-80">
|
||||
|
||||
<motion.h2
|
||||
style={{
|
||||
translateY: textTransform,
|
||||
opacity: textOpacity,
|
||||
}}
|
||||
className="mb-20 text-center text-3xl font-bold text-neutral-800 dark:text-white">
|
||||
|
||||
</motion.h2>
|
||||
{/* Lid */}
|
||||
<Lid
|
||||
src={'/2.jpg'}
|
||||
scaleX={scaleX}
|
||||
scaleY={scaleY}
|
||||
rotate={rotate}
|
||||
translate={translate} />
|
||||
{/* Base area */}
|
||||
<div
|
||||
className="relative -z-10 h-[22rem] w-[32rem] overflow-hidden rounded-2xl bg-gray-200 dark:bg-[#272729]">
|
||||
{/* above keyboard bar */}
|
||||
<div className="relative h-10 w-full">
|
||||
<div className="absolute inset-x-0 mx-auto h-4 w-[80%] bg-[#050505]" />
|
||||
</div>
|
||||
<div className="relative flex">
|
||||
<div className="mx-auto h-full w-[10%] overflow-hidden">
|
||||
<SpeakerGrid />
|
||||
</div>
|
||||
<div className="mx-auto h-full w-[80%]">
|
||||
<Keypad />
|
||||
</div>
|
||||
<div className="mx-auto h-full w-[10%] overflow-hidden">
|
||||
<SpeakerGrid />
|
||||
</div>
|
||||
</div>
|
||||
<Trackpad />
|
||||
<div
|
||||
className="absolute inset-x-0 bottom-0 mx-auto h-2 w-20 rounded-tl-3xl rounded-tr-3xl bg-gradient-to-t from-[#272729] to-[#050505]" />
|
||||
{showGradient && (
|
||||
<div
|
||||
className="absolute inset-x-0 bottom-0 z-50 h-40 w-full bg-gradient-to-t from-white via-white to-transparent dark:from-black dark:via-black"></div>
|
||||
)}
|
||||
{badge && <div className="absolute bottom-4 left-4">{badge}</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Lid = ({
|
||||
scaleX,
|
||||
scaleY,
|
||||
rotate,
|
||||
translate,
|
||||
src
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative [perspective:800px]">
|
||||
<div
|
||||
style={{
|
||||
transform: "perspective(800px) rotateX(-25deg) translateZ(0px)",
|
||||
transformOrigin: "bottom",
|
||||
transformStyle: "preserve-3d",
|
||||
}}
|
||||
className="relative h-[12rem] w-[32rem] rounded-2xl bg-[#010101] p-2">
|
||||
<div
|
||||
style={{
|
||||
boxShadow: "0px 2px 0px 2px #171717 inset",
|
||||
}}
|
||||
className="absolute inset-0 flex items-center justify-center rounded-lg bg-[#010101]">
|
||||
<span className="text-white">
|
||||
<AceternityLogo />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<motion.div
|
||||
style={{
|
||||
scaleX: scaleX,
|
||||
scaleY: scaleY,
|
||||
rotateX: rotate,
|
||||
translateY: translate,
|
||||
transformStyle: "preserve-3d",
|
||||
transformOrigin: "top",
|
||||
}}
|
||||
className="fixed inset-0 h-80 w-[32rem] rounded-2xl bg-[#010101] p-2">
|
||||
<div className="absolute inset-0 rounded-lg bg-[#272729]" />
|
||||
<img
|
||||
src={"/22.jpg"}
|
||||
alt="aceternity logo"
|
||||
className="fixed inset-0 h-full w-full rounded-lg object-cover object-left-top" />
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Trackpad = () => {
|
||||
return (
|
||||
<div
|
||||
className="mx-auto my-1 h-32 w-[40%] rounded-xl"
|
||||
style={{
|
||||
boxShadow: "0px 0px 1px 1px #00000020 inset",
|
||||
}}></div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Keypad = () => {
|
||||
return (
|
||||
<div
|
||||
className="mx-1 h-full [transform:translateZ(0)] rounded-md bg-[#050505] p-1 [will-change:transform]">
|
||||
{/* First Row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn
|
||||
className="w-10 items-end justify-start pb-[2px] pl-[4px]"
|
||||
childrenClassName="items-start">
|
||||
esc
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconBrightnessDown className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F1</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconBrightnessUp className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F2</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconTable className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F3</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconSearch className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F4</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconMicrophone className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F5</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconMoon className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F6</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconPlayerTrackPrev className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F7</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconPlayerSkipForward className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F8</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconPlayerTrackNext className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F8</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconVolume3 className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F10</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconVolume2 className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F11</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<IconVolume className="h-[6px] w-[6px]" />
|
||||
<span className="mt-1 inline-block">F12</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<div
|
||||
className="h-4 w-4 rounded-full bg-gradient-to-b from-neutral-900 from-20% via-black via-50% to-neutral-900 to-95% p-px">
|
||||
<div className="h-full w-full rounded-full bg-black" />
|
||||
</div>
|
||||
</KBtn>
|
||||
</div>
|
||||
{/* Second row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn>
|
||||
<span className="block">~</span>
|
||||
<span className="mt-1 block">`</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">!</span>
|
||||
<span className="block">1</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">@</span>
|
||||
<span className="block">2</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">#</span>
|
||||
<span className="block">3</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">$</span>
|
||||
<span className="block">4</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">%</span>
|
||||
<span className="block">5</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">^</span>
|
||||
<span className="block">6</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">&</span>
|
||||
<span className="block">7</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">*</span>
|
||||
<span className="block">8</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">(</span>
|
||||
<span className="block">9</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">)</span>
|
||||
<span className="block">0</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">—</span>
|
||||
<span className="block">_</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">+</span>
|
||||
<span className="block"> = </span>
|
||||
</KBtn>
|
||||
<KBtn
|
||||
className="w-10 items-end justify-end pr-[4px] pb-[2px]"
|
||||
childrenClassName="items-end">
|
||||
delete
|
||||
</KBtn>
|
||||
</div>
|
||||
{/* Third row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn
|
||||
className="w-10 items-end justify-start pb-[2px] pl-[4px]"
|
||||
childrenClassName="items-start">
|
||||
tab
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">Q</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">W</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">E</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">R</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">T</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">Y</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">U</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">I</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">O</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">P</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`{`}</span>
|
||||
<span className="block">{`[`}</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`}`}</span>
|
||||
<span className="block">{`]`}</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`|`}</span>
|
||||
<span className="block">{`\\`}</span>
|
||||
</KBtn>
|
||||
</div>
|
||||
{/* Fourth Row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn
|
||||
className="w-[2.8rem] items-end justify-start pb-[2px] pl-[4px]"
|
||||
childrenClassName="items-start">
|
||||
caps lock
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">A</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">S</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">D</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">F</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">G</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">H</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">J</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">K</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">L</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`:`}</span>
|
||||
<span className="block">{`;`}</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`"`}</span>
|
||||
<span className="block">{`'`}</span>
|
||||
</KBtn>
|
||||
<KBtn
|
||||
className="w-[2.85rem] items-end justify-end pr-[4px] pb-[2px]"
|
||||
childrenClassName="items-end">
|
||||
return
|
||||
</KBtn>
|
||||
</div>
|
||||
{/* Fifth Row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn
|
||||
className="w-[3.65rem] items-end justify-start pb-[2px] pl-[4px]"
|
||||
childrenClassName="items-start">
|
||||
shift
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">Z</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">X</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">C</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">V</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">B</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">N</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">M</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`<`}</span>
|
||||
<span className="block">{`,`}</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`>`}</span>
|
||||
<span className="block">{`.`}</span>
|
||||
</KBtn>
|
||||
<KBtn>
|
||||
<span className="block">{`?`}</span>
|
||||
<span className="block">{`/`}</span>
|
||||
</KBtn>
|
||||
<KBtn
|
||||
className="w-[3.65rem] items-end justify-end pr-[4px] pb-[2px]"
|
||||
childrenClassName="items-end">
|
||||
shift
|
||||
</KBtn>
|
||||
</div>
|
||||
{/* sixth Row */}
|
||||
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
|
||||
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-end pr-1">
|
||||
<span className="block">fn</span>
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<IconWorld className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
</KBtn>
|
||||
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-end pr-1">
|
||||
<IconChevronUp className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<span className="block">control</span>
|
||||
</div>
|
||||
</KBtn>
|
||||
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-end pr-1">
|
||||
<OptionKey className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<span className="block">option</span>
|
||||
</div>
|
||||
</KBtn>
|
||||
<KBtn className="w-8" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-end pr-1">
|
||||
<IconCommand className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<span className="block">command</span>
|
||||
</div>
|
||||
</KBtn>
|
||||
<KBtn className="w-[8.2rem]"></KBtn>
|
||||
<KBtn className="w-8" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<IconCommand className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<span className="block">command</span>
|
||||
</div>
|
||||
</KBtn>
|
||||
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<OptionKey className="h-[6px] w-[6px]" />
|
||||
</div>
|
||||
<div className="flex w-full justify-start pl-1">
|
||||
<span className="block">option</span>
|
||||
</div>
|
||||
</KBtn>
|
||||
<div
|
||||
className="mt-[2px] flex h-6 w-[4.9rem] flex-col items-center justify-end rounded-[4px] p-[0.5px]">
|
||||
<KBtn className="h-3 w-6">
|
||||
<IconCaretUpFilled className="h-[6px] w-[6px]" />
|
||||
</KBtn>
|
||||
<div className="flex">
|
||||
<KBtn className="h-3 w-6">
|
||||
<IconCaretLeftFilled className="h-[6px] w-[6px]" />
|
||||
</KBtn>
|
||||
<KBtn className="h-3 w-6">
|
||||
<IconCaretDownFilled className="h-[6px] w-[6px]" />
|
||||
</KBtn>
|
||||
<KBtn className="h-3 w-6">
|
||||
<IconCaretRightFilled className="h-[6px] w-[6px]" />
|
||||
</KBtn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const KBtn = ({
|
||||
className,
|
||||
children,
|
||||
childrenClassName,
|
||||
backlit = true
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"[transform:translateZ(0)] rounded-[4px] p-[0.5px] [will-change:transform]",
|
||||
backlit && "bg-white/[0.2] shadow-xl shadow-white"
|
||||
)}>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-6 w-6 items-center justify-center rounded-[3.5px] bg-[#0A090D]",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
boxShadow:
|
||||
"0px -0.5px 2px 0 #0D0D0F inset, -0.5px 0px 2px 0 #0D0D0F inset",
|
||||
}}>
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-full flex-col items-center justify-center text-[5px] text-neutral-200",
|
||||
childrenClassName,
|
||||
backlit && "text-white"
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const SpeakerGrid = () => {
|
||||
return (
|
||||
<div
|
||||
className="mt-2 flex h-40 gap-[2px] px-[0.5px]"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"radial-gradient(circle, #08080A 0.5px, transparent 0.5px)",
|
||||
backgroundSize: "3px 3px",
|
||||
}}></div>
|
||||
);
|
||||
};
|
||||
|
||||
export const OptionKey = ({
|
||||
className
|
||||
}) => {
|
||||
return (
|
||||
<svg
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="icon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 32 32"
|
||||
className={className}>
|
||||
<rect stroke="currentColor" strokeWidth={2} x="18" y="5" width="10" height="2" />
|
||||
<polygon
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
points="10.6,5 4,5 4,7 9.4,7 18.4,27 28,27 28,25 19.6,25 " />
|
||||
<rect
|
||||
id="_Transparent_Rectangle_"
|
||||
className="st0"
|
||||
width="32"
|
||||
height="32"
|
||||
stroke="none" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const AceternityLogo = () => {
|
||||
return (
|
||||
<svg
|
||||
width="66"
|
||||
height="65"
|
||||
viewBox="0 0 66 65"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-3 w-3 text-white">
|
||||
<path
|
||||
d="M8 8.05571C8 8.05571 54.9009 18.1782 57.8687 30.062C60.8365 41.9458 9.05432 57.4696 9.05432 57.4696"
|
||||
stroke="currentColor"
|
||||
strokeWidth="15"
|
||||
strokeMiterlimit="3.86874"
|
||||
strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
77
app/components/Moon.js
Normal file
@ -0,0 +1,77 @@
|
||||
"use client";
|
||||
|
||||
import React, { useRef, useEffect } from "react";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
|
||||
|
||||
export default function SimpleGlobe() {
|
||||
const mountRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const width = 400;
|
||||
const height = 400;
|
||||
|
||||
// إنشاء المشهد
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
// الكاميرا
|
||||
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
|
||||
camera.position.z = 3;
|
||||
|
||||
// الرندرر
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
renderer.setSize(width, height);
|
||||
mountRef.current.appendChild(renderer.domElement);
|
||||
|
||||
// الكرة الزرقاء
|
||||
const geometry = new THREE.SphereGeometry(1, 32, 32);
|
||||
const material = new THREE.MeshStandardMaterial({
|
||||
color: "#007bff",
|
||||
metalness: 0.3,
|
||||
roughness: 0.7,
|
||||
});
|
||||
const sphere = new THREE.Mesh(geometry, material);
|
||||
scene.add(sphere);
|
||||
|
||||
// إضاءة
|
||||
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// تحكم الماوس
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true; // يجعل الحركة سلسة
|
||||
controls.dampingFactor = 0.05;
|
||||
|
||||
// دالة التحديث والرسوم
|
||||
const animate = () => {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
sphere.rotation.y += 0.005; // دوران تلقائي بسيط
|
||||
|
||||
controls.update(); // تحديث تحكمات الماوس
|
||||
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
|
||||
animate();
|
||||
|
||||
// تنظيف عند إزالة المكون
|
||||
return () => {
|
||||
controls.dispose();
|
||||
mountRef.current.removeChild(renderer.domElement);
|
||||
renderer.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={mountRef}
|
||||
style={{
|
||||
width: "400px",
|
||||
height: "400px",
|
||||
margin: "0 auto",
|
||||
backgroundColor: "#010217",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
99
app/components/Navbar.js
Normal file
@ -0,0 +1,99 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
motion,
|
||||
AnimatePresence,
|
||||
useScroll,
|
||||
useMotionValueEvent,
|
||||
} from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const HomeIcon = () => <span>🏠</span>;
|
||||
const ServicesIcon = () => <span>🛠️</span>;
|
||||
const ProductsIcon = () => <span>📦</span>;
|
||||
const ContactIcon = () => <span>📞</span>;
|
||||
|
||||
export const FloatingNav = ({
|
||||
navItems = [],
|
||||
className,
|
||||
}) => {
|
||||
const { scrollYProgress } = useScroll();
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
useMotionValueEvent(scrollYProgress, "change", (current) => {
|
||||
if (typeof current === "number") {
|
||||
let direction = current - scrollYProgress.getPrevious();
|
||||
if (scrollYProgress.get() < 0.05) {
|
||||
setVisible(false);
|
||||
} else {
|
||||
if (direction < 0) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.nav
|
||||
initial={{ opacity: 1, y: -100 }}
|
||||
animate={{ y: visible ? 0 : -100, opacity: visible ? 1 : 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className={cn(
|
||||
"flex max-w-fit fixed top-10 inset-x-0 mx-auto rounded-full shadow-lg z-[5000] pr-8 pl-8 py-2 items-center justify-center space-x-12", // space-x-12 لمسافة واسعة بين الروابط
|
||||
"bg-[rgba(23,18,40,0.74)] text-white backdrop-blur-sm", // لون كحلي بنفسجي غامق مع شفافية وخلفية ضبابية
|
||||
className
|
||||
)}
|
||||
>
|
||||
{navItems.map((navItem, idx) => (
|
||||
<a
|
||||
key={`link=${idx}`}
|
||||
href={navItem.link}
|
||||
className={cn(
|
||||
"relative flex items-center space-x-2 hover:text-[rgba(221,74,255,0.9)] transition-colors duration-300 ease-in-out font-semibold text-sm"
|
||||
)}
|
||||
>
|
||||
<span className="block sm:hidden">{navItem.icon}</span>
|
||||
<span className="hidden sm:block">{navItem.name}</span>
|
||||
</a>
|
||||
))}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" text-white px-5 py-2 rounded-full font-semibold relative "
|
||||
>
|
||||
<div className="flex gap-6">
|
||||
<span>Home</span>
|
||||
<span>service</span>
|
||||
<span>Products</span>
|
||||
<span>Contact</span>
|
||||
</div>
|
||||
<span className="absolute inset-x-0 w-1/2 mx-auto -bottom-px bg-gradient-to-r from-transparent via-purple-400 to-transparent h-px" />
|
||||
</button>
|
||||
</motion.nav>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
// مثال الاستخدام مع 4 روابط
|
||||
export default function App() {
|
||||
const navItems = [
|
||||
{ name: "Home", link: "/", icon: <HomeIcon /> },
|
||||
{ name: "Services", link: "/services", icon: <ServicesIcon /> },
|
||||
{ name: "Products", link: "/products", icon: <ProductsIcon /> },
|
||||
{ name: "Contact", link: "/contact", icon: <ContactIcon /> },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<FloatingNav navItems={navItems} />
|
||||
<div style={{ height: "200vh", paddingTop: 150 }}>
|
||||
<h1 className="text-white text-center">
|
||||
Scroll down and up to see the navbar appear/disappear
|
||||
</h1>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
43
app/components/SpotLight.js
Normal file
@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const Spotlight = ({
|
||||
className,
|
||||
fill
|
||||
}) => {
|
||||
return (
|
||||
<svg
|
||||
className={cn(
|
||||
"animate-spotlight pointer-events-none absolute z-[1] h-[169%] w-[138%] lg:w-[84%] opacity-0",
|
||||
className
|
||||
)}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 3787 2842"
|
||||
fill="none">
|
||||
<g filter="url(#filter)">
|
||||
<ellipse
|
||||
cx="1924.71"
|
||||
cy="273.501"
|
||||
rx="1924.71"
|
||||
ry="273.501"
|
||||
transform="matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)"
|
||||
fill={fill || "white"}
|
||||
fillOpacity="0.21"></ellipse>
|
||||
</g>
|
||||
<defs>
|
||||
<filter
|
||||
id="filter"
|
||||
x="0.860352"
|
||||
y="0.838989"
|
||||
width="3785.16"
|
||||
height="2840.26"
|
||||
filterUnits="userSpaceOnUse"
|
||||
colorInterpolationFilters="sRGB">
|
||||
<feFlood floodOpacity="0" result="BackgroundImageFix"></feFlood>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend>
|
||||
<feGaussianBlur stdDeviation="151" result="effect1_foregroundBlur_1065_8"></feGaussianBlur>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
264
app/components/canvas-reveal-effect.js
Normal file
@ -0,0 +1,264 @@
|
||||
"use client";;
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Canvas, useFrame, useThree } from "@react-three/fiber";
|
||||
import React, { useMemo, useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
|
||||
export const CanvasRevealEffect = ({
|
||||
animationSpeed = 0.4,
|
||||
opacities = [0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 1],
|
||||
colors = [[0, 255, 255]],
|
||||
containerClassName,
|
||||
dotSize,
|
||||
showGradient = true
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn("h-full relative bg-white w-full", containerClassName)}>
|
||||
<div className="h-full w-full">
|
||||
<DotMatrix
|
||||
colors={colors ?? [[0, 255, 255]]}
|
||||
dotSize={dotSize ?? 3}
|
||||
opacities={
|
||||
opacities ?? [0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 1]
|
||||
}
|
||||
shader={`
|
||||
float animation_speed_factor = ${animationSpeed.toFixed(1)};
|
||||
float intro_offset = distance(u_resolution / 2.0 / u_total_size, st2) * 0.01 + (random(st2) * 0.15);
|
||||
opacity *= step(intro_offset, u_time * animation_speed_factor);
|
||||
opacity *= clamp((1.0 - step(intro_offset + 0.1, u_time * animation_speed_factor)) * 1.25, 1.0, 1.25);
|
||||
`}
|
||||
center={["x", "y"]} />
|
||||
</div>
|
||||
{showGradient && (
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-gray-950 to-[84%]" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DotMatrix = ({
|
||||
colors = [[0, 0, 0]],
|
||||
opacities = [0.04, 0.04, 0.04, 0.04, 0.04, 0.08, 0.08, 0.08, 0.08, 0.14],
|
||||
totalSize = 4,
|
||||
dotSize = 2,
|
||||
shader = "",
|
||||
center = ["x", "y"],
|
||||
}) => {
|
||||
const uniforms = React.useMemo(() => {
|
||||
let colorsArray = [
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[0],
|
||||
];
|
||||
if (colors.length === 2) {
|
||||
colorsArray = [
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[1],
|
||||
colors[1],
|
||||
colors[1],
|
||||
];
|
||||
} else if (colors.length === 3) {
|
||||
colorsArray = [
|
||||
colors[0],
|
||||
colors[0],
|
||||
colors[1],
|
||||
colors[1],
|
||||
colors[2],
|
||||
colors[2],
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
u_colors: {
|
||||
value: colorsArray.map((color) => [
|
||||
color[0] / 255,
|
||||
color[1] / 255,
|
||||
color[2] / 255,
|
||||
]),
|
||||
type: "uniform3fv",
|
||||
},
|
||||
u_opacities: {
|
||||
value: opacities,
|
||||
type: "uniform1fv",
|
||||
},
|
||||
u_total_size: {
|
||||
value: totalSize,
|
||||
type: "uniform1f",
|
||||
},
|
||||
u_dot_size: {
|
||||
value: dotSize,
|
||||
type: "uniform1f",
|
||||
},
|
||||
};
|
||||
}, [colors, opacities, totalSize, dotSize]);
|
||||
|
||||
return (
|
||||
<Shader
|
||||
source={`
|
||||
precision mediump float;
|
||||
in vec2 fragCoord;
|
||||
|
||||
uniform float u_time;
|
||||
uniform float u_opacities[10];
|
||||
uniform vec3 u_colors[6];
|
||||
uniform float u_total_size;
|
||||
uniform float u_dot_size;
|
||||
uniform vec2 u_resolution;
|
||||
out vec4 fragColor;
|
||||
float PHI = 1.61803398874989484820459;
|
||||
float random(vec2 xy) {
|
||||
return fract(tan(distance(xy * PHI, xy) * 0.5) * xy.x);
|
||||
}
|
||||
float map(float value, float min1, float max1, float min2, float max2) {
|
||||
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
||||
}
|
||||
void main() {
|
||||
vec2 st = fragCoord.xy;
|
||||
${
|
||||
center.includes("x")
|
||||
? "st.x -= abs(floor((mod(u_resolution.x, u_total_size) - u_dot_size) * 0.5));"
|
||||
: ""
|
||||
}
|
||||
${
|
||||
center.includes("y")
|
||||
? "st.y -= abs(floor((mod(u_resolution.y, u_total_size) - u_dot_size) * 0.5));"
|
||||
: ""
|
||||
}
|
||||
float opacity = step(0.0, st.x);
|
||||
opacity *= step(0.0, st.y);
|
||||
|
||||
vec2 st2 = vec2(int(st.x / u_total_size), int(st.y / u_total_size));
|
||||
|
||||
float frequency = 5.0;
|
||||
float show_offset = random(st2);
|
||||
float rand = random(st2 * floor((u_time / frequency) + show_offset + frequency) + 1.0);
|
||||
opacity *= u_opacities[int(rand * 10.0)];
|
||||
opacity *= 1.0 - step(u_dot_size / u_total_size, fract(st.x / u_total_size));
|
||||
opacity *= 1.0 - step(u_dot_size / u_total_size, fract(st.y / u_total_size));
|
||||
|
||||
vec3 color = u_colors[int(show_offset * 6.0)];
|
||||
|
||||
${shader}
|
||||
|
||||
fragColor = vec4(color, opacity);
|
||||
fragColor.rgb *= fragColor.a;
|
||||
}`}
|
||||
uniforms={uniforms}
|
||||
maxFps={60} />
|
||||
);
|
||||
};
|
||||
|
||||
const ShaderMaterial = ({
|
||||
source,
|
||||
uniforms,
|
||||
maxFps = 60
|
||||
}) => {
|
||||
const { size } = useThree();
|
||||
const ref = useRef();
|
||||
let lastFrameTime = 0;
|
||||
|
||||
useFrame(({ clock }) => {
|
||||
if (!ref.current) return;
|
||||
const timestamp = clock.getElapsedTime();
|
||||
if (timestamp - lastFrameTime < 1 / maxFps) {
|
||||
return;
|
||||
}
|
||||
lastFrameTime = timestamp;
|
||||
|
||||
const material = ref.current.material;
|
||||
const timeLocation = material.uniforms.u_time;
|
||||
timeLocation.value = timestamp;
|
||||
});
|
||||
|
||||
const getUniforms = () => {
|
||||
const preparedUniforms = {};
|
||||
|
||||
for (const uniformName in uniforms) {
|
||||
const uniform = uniforms[uniformName];
|
||||
|
||||
switch (uniform.type) {
|
||||
case "uniform1f":
|
||||
preparedUniforms[uniformName] = { value: uniform.value, type: "1f" };
|
||||
break;
|
||||
case "uniform3f":
|
||||
preparedUniforms[uniformName] = {
|
||||
value: new THREE.Vector3().fromArray(uniform.value),
|
||||
type: "3f",
|
||||
};
|
||||
break;
|
||||
case "uniform1fv":
|
||||
preparedUniforms[uniformName] = { value: uniform.value, type: "1fv" };
|
||||
break;
|
||||
case "uniform3fv":
|
||||
preparedUniforms[uniformName] = {
|
||||
value: uniform.value.map((v) =>
|
||||
new THREE.Vector3().fromArray(v)),
|
||||
type: "3fv",
|
||||
};
|
||||
break;
|
||||
case "uniform2f":
|
||||
preparedUniforms[uniformName] = {
|
||||
value: new THREE.Vector2().fromArray(uniform.value),
|
||||
type: "2f",
|
||||
};
|
||||
break;
|
||||
default:
|
||||
console.error(`Invalid uniform type for '${uniformName}'.`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
preparedUniforms["u_time"] = { value: 0, type: "1f" };
|
||||
preparedUniforms["u_resolution"] = {
|
||||
value: new THREE.Vector2(size.width * 2, size.height * 2),
|
||||
}; // Initialize u_resolution
|
||||
return preparedUniforms;
|
||||
};
|
||||
|
||||
// Shader material
|
||||
const material = useMemo(() => {
|
||||
const materialObject = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
precision mediump float;
|
||||
in vec2 coordinates;
|
||||
uniform vec2 u_resolution;
|
||||
out vec2 fragCoord;
|
||||
void main(){
|
||||
float x = position.x;
|
||||
float y = position.y;
|
||||
gl_Position = vec4(x, y, 0.0, 1.0);
|
||||
fragCoord = (position.xy + vec2(1.0)) * 0.5 * u_resolution;
|
||||
fragCoord.y = u_resolution.y - fragCoord.y;
|
||||
}
|
||||
`,
|
||||
fragmentShader: source,
|
||||
uniforms: getUniforms(),
|
||||
glslVersion: THREE.GLSL3,
|
||||
blending: THREE.CustomBlending,
|
||||
blendSrc: THREE.SrcAlphaFactor,
|
||||
blendDst: THREE.OneFactor,
|
||||
});
|
||||
|
||||
return materialObject;
|
||||
}, [size.width, size.height, source]);
|
||||
|
||||
return (
|
||||
<mesh ref={ref}>
|
||||
<planeGeometry args={[2, 2]} />
|
||||
<primitive object={material} attach="material" />
|
||||
</mesh>
|
||||
);
|
||||
};
|
||||
|
||||
const Shader = ({ source, uniforms, maxFps = 60 }) => {
|
||||
return (
|
||||
<Canvas className="absolute inset-0 h-full w-full">
|
||||
<ShaderMaterial source={source} uniforms={uniforms} maxFps={maxFps} />
|
||||
</Canvas>
|
||||
);
|
||||
};
|
||||
89
app/components/hover-border-gradient.js
Normal file
@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { motion } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function HoverBorderGradient({
|
||||
children,
|
||||
containerClassName,
|
||||
className,
|
||||
as: Tag = "button",
|
||||
duration = 1,
|
||||
clockwise = true,
|
||||
...props
|
||||
}) {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const [direction, setDirection] = useState("TOP");
|
||||
|
||||
const rotateDirection = (currentDirection) => {
|
||||
const directions = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
|
||||
const currentIndex = directions.indexOf(currentDirection);
|
||||
const nextIndex = clockwise
|
||||
? (currentIndex - 1 + directions.length) % directions.length
|
||||
: (currentIndex + 1) % directions.length;
|
||||
return directions[nextIndex];
|
||||
};
|
||||
|
||||
const movingMap = {
|
||||
TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
BOTTOM:
|
||||
"radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
RIGHT:
|
||||
"radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
|
||||
};
|
||||
|
||||
const highlight =
|
||||
"radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
|
||||
|
||||
useEffect(() => {
|
||||
if (!hovered) {
|
||||
const interval = setInterval(() => {
|
||||
setDirection((prevState) => rotateDirection(prevState));
|
||||
}, duration * 1000);
|
||||
return () => clearInterval(interval);
|
||||
}
|
||||
}, [hovered]);
|
||||
return (
|
||||
<Tag
|
||||
onMouseEnter={(event) => {
|
||||
setHovered(true);
|
||||
}}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
className={cn(
|
||||
"relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap gap-10 h-min justify-center overflow-visible p-px decoration-clone w-fit",
|
||||
containerClassName
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"w-auto text-white z-10 bg-black px-4 py-2 rounded-[inherit]",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<motion.div
|
||||
className={cn(
|
||||
"flex-none inset-0 overflow-hidden absolute z-0 rounded-[inherit]"
|
||||
)}
|
||||
style={{
|
||||
filter: "blur(2px)",
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
initial={{ background: movingMap[direction] }}
|
||||
animate={{
|
||||
background: hovered
|
||||
? [movingMap[direction], highlight]
|
||||
: movingMap[direction],
|
||||
}}
|
||||
transition={{ ease: "linear", duration: duration ?? 1 }}
|
||||
/>
|
||||
<div className="bg-black absolute z-1 flex-none inset-[2px] rounded-[100px]" />
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
104
app/components/infinitemovingcards.js
Normal file
@ -0,0 +1,104 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
export const InfiniteMovingCards = ({
|
||||
items,
|
||||
direction = "left",
|
||||
speed = "fast",
|
||||
pauseOnHover = true,
|
||||
className,
|
||||
}) => {
|
||||
const containerRef = React.useRef(null);
|
||||
const scrollerRef = React.useRef(null);
|
||||
const [start, setStart] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
addAnimation();
|
||||
}, []);
|
||||
|
||||
function addAnimation() {
|
||||
if (containerRef.current && scrollerRef.current) {
|
||||
const scrollerContent = Array.from(scrollerRef.current.children);
|
||||
|
||||
scrollerContent.forEach((item) => {
|
||||
const duplicatedItem = item.cloneNode(true);
|
||||
if (scrollerRef.current) {
|
||||
scrollerRef.current.appendChild(duplicatedItem);
|
||||
}
|
||||
});
|
||||
|
||||
getDirection();
|
||||
getSpeed();
|
||||
setStart(true);
|
||||
}
|
||||
}
|
||||
|
||||
const getDirection = () => {
|
||||
if (containerRef.current) {
|
||||
containerRef.current.style.setProperty(
|
||||
"--animation-direction",
|
||||
direction === "left" ? "forwards" : "reverse"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const getSpeed = () => {
|
||||
if (containerRef.current) {
|
||||
const duration =
|
||||
speed === "fast" ? "20s" : speed === "normal" ? "40s" : "80s";
|
||||
containerRef.current.style.setProperty("--animation-duration", duration);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cn(
|
||||
"scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<ul
|
||||
ref={scrollerRef}
|
||||
className={cn(
|
||||
"flex w-max min-w-full shrink-0 flex-nowrap gap-4 py-4",
|
||||
start && "animate-scroll",
|
||||
pauseOnHover && "hover:[animation-play-state:paused]"
|
||||
)}
|
||||
>
|
||||
{items.map((item) => (
|
||||
<li
|
||||
key={item.name}
|
||||
className="relative w-[350px] max-w-full shrink-0 rounded-2xl border border-b-0 border-zinc-200 px-8 py-6 md:w-[450px] dark:border-zinc-700"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
|
||||
}}
|
||||
>
|
||||
<blockquote>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute -top-0.5 -left-0.5 -z-1 h-[calc(100%_+_4px)] w-[calc(100%_+_4px)] user-select-none"
|
||||
></div>
|
||||
<span className="relative z-20 text-sm leading-[1.6] font-normal text-white">
|
||||
{item.quote}
|
||||
</span>
|
||||
<div className="relative z-20 mt-6 flex flex-row items-center">
|
||||
<span className="flex flex-col gap-1">
|
||||
<span className="text-sm leading-[1.6] font-normal text-white/70">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-sm leading-[1.6] font-normal text-white/70">
|
||||
{item.title}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</blockquote>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
55
app/components/text-generate-effect.js
Normal file
@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import { useAnimate, stagger } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const TextGenerateEffect = ({
|
||||
children,
|
||||
className,
|
||||
filter = true,
|
||||
duration = 0.5
|
||||
}) => {
|
||||
const [scope, animate] = useAnimate();
|
||||
|
||||
useEffect(() => {
|
||||
animate("span", {
|
||||
opacity: 1,
|
||||
filter: filter ? "blur(0px)" : "none",
|
||||
}, {
|
||||
duration: duration,
|
||||
delay: stagger(0.2),
|
||||
});
|
||||
}, [scope, animate, filter, duration]);
|
||||
|
||||
// هنا نحول كل طفل (child) لعنصر <motion.span> لعمل تأثير الحركة
|
||||
const renderWords = () => {
|
||||
return (
|
||||
<div ref={scope}>
|
||||
{React.Children.map(children, (child, idx) => {
|
||||
return (
|
||||
<span
|
||||
key={idx}
|
||||
className="dark:text-white text-black opacity-0"
|
||||
style={{
|
||||
filter: filter ? "blur(10px)" : "none",
|
||||
}}
|
||||
>
|
||||
{child}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn("font-bold", className)}>
|
||||
<div className="mt-4">
|
||||
<div className="dark:text-white text-black text-5xl leading-snug tracking-wide">
|
||||
{renderWords()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
12942
app/data/globe.json
Normal file
BIN
app/favicon.ico
Normal file
|
After Width: | Height: | Size: 25 KiB |
271
app/globals.css
Normal file
@ -0,0 +1,271 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* ------------------------------
|
||||
Root Variables + Animations
|
||||
------------------------------- */
|
||||
@layer base {
|
||||
:root {
|
||||
--animate-spotlight: spotlight 2s ease 0.75s 1 forwards;
|
||||
|
||||
/* Animation Variables for gradients */
|
||||
--animate-first: moveVertical 30s ease infinite;
|
||||
--animate-second: moveInCircle 20s reverse infinite;
|
||||
--animate-third: moveInCircle 40s linear infinite;
|
||||
--animate-fourth: moveHorizontal 40s ease infinite;
|
||||
--animate-fifth: moveInCircle 20s ease infinite;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #000319;
|
||||
}
|
||||
|
||||
/* Spotlight animation */
|
||||
@keyframes spotlight {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(-72%, -62%) scale(0.5);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -40%) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gradient animation: horizontal movement */
|
||||
@keyframes moveHorizontal {
|
||||
0% {
|
||||
transform: translateX(-50%) translateY(-10%);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(50%) translateY(10%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-50%) translateY(-10%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gradient animation: vertical movement */
|
||||
@keyframes moveVertical {
|
||||
0% {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(50%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gradient animation: circular rotation */
|
||||
@keyframes moveInCircle {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll animation for InfiniteMovingCards */
|
||||
@keyframes scroll {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------
|
||||
Utility Classes
|
||||
------------------------------- */
|
||||
@layer utilities {
|
||||
.animate-spotlight {
|
||||
animation: var(--animate-spotlight);
|
||||
}
|
||||
|
||||
.animate-first {
|
||||
animation: var(--animate-first);
|
||||
}
|
||||
.animate-second {
|
||||
animation: var(--animate-second);
|
||||
}
|
||||
.animate-third {
|
||||
animation: var(--animate-third);
|
||||
}
|
||||
.animate-fourth {
|
||||
animation: var(--animate-fourth);
|
||||
}
|
||||
.animate-fifth {
|
||||
animation: var(--animate-fifth);
|
||||
}
|
||||
|
||||
/* Utility class for infinite horizontal scroll */
|
||||
.animate-scroll {
|
||||
animation: scroll var(--animation-duration, 40s) linear infinite;
|
||||
animation-direction: var(--animation-direction, forwards);
|
||||
}
|
||||
}
|
||||
|
||||
.work-card-with-border {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: 150px;
|
||||
background: linear-gradient(103.4deg, #04071d 16.66%, #0c0e23 81.61%);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* الطبقة المتحركة */
|
||||
.work-card-with-border::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
width: calc(100% + 4px);
|
||||
height: calc(100% + 4px);
|
||||
background: conic-gradient(
|
||||
from 0deg,
|
||||
#ffffff 0deg,
|
||||
transparent 90deg,
|
||||
#ffffff 180deg,
|
||||
transparent 270deg,
|
||||
#ffffff 360deg
|
||||
);
|
||||
border-radius: 12px;
|
||||
animation: rotate-border 4s linear infinite;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
||||
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
||||
mask-composite: exclude;
|
||||
-webkit-mask-composite: destination-out;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.animated-corner-card {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: 150px;
|
||||
background: linear-gradient(103.4deg, #04071d 16.66%, #0c0e23 81.61%);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* الخط الرفيع الأبيض مع اللمعة */
|
||||
.corner-line {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.8) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.8));
|
||||
animation: shine 2s linear infinite;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* الخط الأفقي */
|
||||
.corner-line-horizontal {
|
||||
height: 2px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
/* الخط العمودي */
|
||||
.corner-line-vertical {
|
||||
width: 2px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
/* تحريك اللمعة */
|
||||
@keyframes shine {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* زوايا وتحديد أماكن الخطوط */
|
||||
|
||||
/* أعلى يسار */
|
||||
.corner-top-left .corner-line-horizontal {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.corner-top-left .corner-line-vertical {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* أعلى يمين */
|
||||
.corner-top-right .corner-line-horizontal {
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(
|
||||
270deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.8) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
animation: shine 2s linear infinite;
|
||||
}
|
||||
|
||||
.corner-top-right .corner-line-vertical {
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* أسفل يمين */
|
||||
.corner-bottom-right .corner-line-horizontal {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(
|
||||
270deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.8) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
animation: shine 2s linear infinite;
|
||||
}
|
||||
|
||||
.corner-bottom-right .corner-line-vertical {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.8) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
animation: shine 2s linear infinite;
|
||||
}
|
||||
|
||||
/* أسفل يسار */
|
||||
.corner-bottom-left .corner-line-horizontal {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.corner-bottom-left .corner-line-vertical {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.8) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
animation: shine 2s linear infinite;
|
||||
}
|
||||
42
app/infinte.js
Normal file
@ -0,0 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { InfiniteMovingCards } from "./components/infinitemovingcards";
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
quote:
|
||||
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
|
||||
name: "Michel joen",
|
||||
title: "Marketing Director",
|
||||
img: "/gf.png",
|
||||
},
|
||||
{
|
||||
quote:
|
||||
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
|
||||
name: "joenista michkel",
|
||||
title: "Product Manager",
|
||||
img: "/gf.png",
|
||||
},
|
||||
{
|
||||
quote:
|
||||
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
|
||||
name: "jomana adel",
|
||||
title: "Marketing Director",
|
||||
img: "/gf.png",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<main className="mt-20 mb-20">
|
||||
<p className="text-white text-center font-bold sm:text-xl md:text-2xl mb-5">
|
||||
Kind words from{" "}
|
||||
<span className="text-fuchsia-400">satisfied clients</span>
|
||||
</p>
|
||||
<InfiniteMovingCards items={testimonials} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
29
app/layout.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
6
app/lib/utils.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
22
app/page.js
Normal file
@ -0,0 +1,22 @@
|
||||
import Approach from "./Approach";
|
||||
import Hero from "./Hero";
|
||||
import Main from "./Main";
|
||||
import { CanvasRevealEffectDemo } from "./Approach";
|
||||
import X from "./x";
|
||||
import Infinte from "./infinte";
|
||||
import Work from "./Work";
|
||||
import Footer from "./Footer";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<Hero />
|
||||
<Main />
|
||||
<CanvasRevealEffectDemo />
|
||||
<X />
|
||||
<Infinte />
|
||||
<Work />
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
298
app/x.js
Normal file
@ -0,0 +1,298 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { PinContainer } from "./components/3d-pin";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div>
|
||||
<p className="font-bold mb-5 text-white sm:text-2xl md:text-3xl text-center z-[1000] mt-5">
|
||||
A small selection of
|
||||
<span className="text-[#CBACF9]"> recent project</span>
|
||||
</p>
|
||||
<main className="min-h-screen w-[80%] mx-auto grid grid-cols-1 md:grid md:grid-cols-2 gap-x-0 gap-y-52 place-items-center bg-[#010217] py-20">
|
||||
<PinContainer>
|
||||
<div
|
||||
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
|
||||
}}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="relative w-[500px] h-[200px]">
|
||||
{/* الصورة الخلفية */}
|
||||
<img
|
||||
src="/f.png"
|
||||
alt="bg image"
|
||||
className=" w-full h-full object-cover "
|
||||
/>
|
||||
|
||||
{/* الصورة الأمامية */}
|
||||
<img
|
||||
src="/1.png"
|
||||
alt="ai content image"
|
||||
className="absolute bottom-0 left-20 w-[230px] h-[180px] z-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="font-bold">AI Image SaaS - Canva Application</p>
|
||||
<p className="font-normal text-sm text-[#BEC1DD]">
|
||||
A REAL Software-as-a-Service app with AI features and a payments
|
||||
and credits system using the latest tech stack.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
|
||||
alt="TypeScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
|
||||
alt="Next.js"
|
||||
className="w-5 h-5 invert"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
|
||||
alt="JavaScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
|
||||
alt="Vue.js"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
|
||||
alt="HTML5"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
|
||||
alt="CSS3"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[#CBACF9] font-thin">check live site</p>
|
||||
</div>
|
||||
</div>
|
||||
</PinContainer>
|
||||
|
||||
<PinContainer>
|
||||
<div
|
||||
className="w-[400px] h-[400px] text-white text-lg font-bold flex flex-col justify-between p-5 rounded-xl bg-cover bg-center"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
|
||||
}}
|
||||
>
|
||||
<div className="space-y-4 flex flex-col items-center">
|
||||
<div className="relative w-[500px] h-[200px]">
|
||||
{/* الصورة الخلفية */}
|
||||
<img
|
||||
src="/f.png"
|
||||
alt="bg image"
|
||||
className="absolute inset-0 w-full h-full object-cover "
|
||||
/>
|
||||
|
||||
{/* الصورة الأمامية */}
|
||||
<img
|
||||
src="/99.png"
|
||||
alt="ai content image"
|
||||
className="absolute bottom-0 left-32 w-[250px] h-[180px] z-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="font-bold relative z-10 -left-10">
|
||||
Yoom - Video Conferencing App
|
||||
</p>
|
||||
<p className="font-normal text-sm relative z-10 text-[#BEC1DD] ">
|
||||
Simplify your video conferencing experience with Yoom.
|
||||
Seamlessly connect with colleagues and friends.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
|
||||
alt="TypeScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
|
||||
alt="Next.js"
|
||||
className="w-5 h-5 invert"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
|
||||
alt="JavaScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
|
||||
alt="Vue.js"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
|
||||
alt="HTML5"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
|
||||
alt="CSS3"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[#CBACF9] font-thin">check live site</p>
|
||||
</div>
|
||||
</div>
|
||||
</PinContainer>
|
||||
|
||||
<PinContainer>
|
||||
<div
|
||||
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
|
||||
}}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="relative w-[500px] h-[200px]">
|
||||
{/* الصورة الخلفية */}
|
||||
<img
|
||||
src="/f.png"
|
||||
alt="bg image"
|
||||
className="absolute inset-0 w-full h-full object-cover "
|
||||
/>
|
||||
|
||||
{/* الصورة الأمامية */}
|
||||
<img
|
||||
src="/234.png"
|
||||
alt="ai content image"
|
||||
className="absolute bottom-0 left-16 w-[250px] h-[180px] z-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="font-bold">3D Solar System Planets to Explore</p>
|
||||
<p className="font-normal text-sm text-[#BEC1DD]">
|
||||
Explore the wonders of our solar system with this captivating 3D
|
||||
simulation of the planets using Three.js.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
|
||||
alt="TypeScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
|
||||
alt="Next.js"
|
||||
className="w-5 h-5 invert"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
|
||||
alt="JavaScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
|
||||
alt="Vue.js"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
|
||||
alt="HTML5"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
|
||||
alt="CSS3"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[#CBACF9] font-thin">check live site</p>
|
||||
</div>
|
||||
</div>
|
||||
</PinContainer>
|
||||
|
||||
<PinContainer>
|
||||
<div
|
||||
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
|
||||
}}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="relative w-[500px] h-[200px]">
|
||||
{/* الصورة الخلفية */}
|
||||
<img
|
||||
src="/f.png"
|
||||
alt="bg image"
|
||||
className="absolute inset-0 w-full h-full object-cover "
|
||||
/>
|
||||
|
||||
{/* الصورة الأمامية */}
|
||||
<img
|
||||
src="/66.png"
|
||||
alt="ai content image"
|
||||
className="absolute bottom-0 left-16 w-[250px] h-[180px] z-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="font-bold">Animated Apple Iphone 3D Website</p>
|
||||
<p className="font-normal text-sm text-[#BEC1DD]">
|
||||
Recreated the Apple iPhone 15 Pro website, combining GSAP
|
||||
animations and Three.js 3D effects.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
|
||||
alt="TypeScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
|
||||
alt="Next.js"
|
||||
className="w-5 h-5 invert"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
|
||||
alt="JavaScript"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
|
||||
alt="Vue.js"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
|
||||
alt="HTML5"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
<img
|
||||
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
|
||||
alt="CSS3"
|
||||
className="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[#CBACF9] font-thin">check live site</p>
|
||||
</div>
|
||||
</div>
|
||||
</PinContainer>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
8
jsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
6
lib/utils.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
4
next.config.mjs
Normal file
@ -0,0 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
|
||||
export default nextConfig;
|
||||
3487
package-lock.json
generated
Normal file
35
package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "my-next-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^10.1.2",
|
||||
"@react-three/fiber": "^9.0.0-alpha.8",
|
||||
"clsx": "^2.1.1",
|
||||
"motion": "^12.12.2",
|
||||
"next": "15.1.8",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"tailwind-merge": "^3.3.0",
|
||||
"three": "^0.177.0",
|
||||
"three-globe": "^2.42.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1"
|
||||
},
|
||||
"description": "This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
8
postcss.config.mjs
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
BIN
public/1.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
public/2.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/22.jpg
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
public/234.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
public/66.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
BIN
public/99.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
7
public/Frame.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg width="212" height="40" viewBox="0 0 212 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M65.8897 30.6819C69.0056 30.6819 70.5779 29.0729 71.2631 27.9772H71.5718C71.7074 29.1409 72.5297 30.2366 74.1381 30.2366H77.1833V26.812H76.3971C75.8489 26.812 75.5748 26.5041 75.5748 26.0256V12.2954H71.5358V14.487H71.2285C70.4423 13.3912 68.7993 11.8502 65.7873 11.8502C60.9966 11.8502 57.4365 15.8212 57.4365 21.2653C57.4365 26.7094 61.0644 30.6819 65.8897 30.6819ZM66.6081 26.7788C63.7677 26.7788 61.5448 24.6899 61.5448 21.3C61.5448 17.978 63.6999 15.72 66.5749 15.72C69.3128 15.72 71.605 17.7395 71.605 21.3C71.605 24.3473 69.6533 26.7788 66.6081 26.7788ZM79.5692 37.1942H83.6068V27.9772H83.9141C84.6671 29.0729 86.2755 30.6819 89.4592 30.6819C94.2498 30.6819 97.7408 26.6414 97.7408 21.2653C97.7408 15.8559 94.0104 11.8502 89.1851 11.8502C86.1053 11.8502 84.5979 13.5271 83.8795 14.4523H83.5722V12.2954H79.5678L79.5692 37.1942ZM88.6038 26.8814C85.8312 26.8814 83.5376 24.8272 83.5376 21.2653C83.5376 18.218 85.4893 15.6507 88.5345 15.6507C91.3763 15.6507 93.5993 17.8769 93.5993 21.2653C93.5993 24.5873 91.4441 26.8814 88.6038 26.8814ZM99.8252 37.1942H103.864V27.9772H104.172C104.925 29.0729 106.533 30.6819 109.715 30.6819C114.506 30.6819 117.664 26.6414 117.664 21.2653C117.664 15.8559 114.266 11.8502 109.441 11.8502C106.361 11.8502 104.855 13.5271 104.137 14.4523H103.828V12.2954H99.8252V37.1942ZM108.86 26.8814C106.087 26.8814 103.795 24.8272 103.795 21.2653C103.795 18.218 105.745 15.6507 108.791 15.6507C111.632 15.6507 113.857 17.8769 113.857 21.2653C113.857 24.5873 111.7 26.8814 108.86 26.8814ZM123.004 30.653H128.718L131.969 16.5802H132.175L135.425 30.653H141.108L145.656 12.7118H141.586L138.335 26.8193H138.026L134.776 12.7103H129.403L126.117 26.8193H125.81L122.593 12.7103H118.28L123.004 30.653ZM147.703 30.653H151.742V21.7857C151.742 18.3958 153.314 16.307 156.258 16.307H158.037V12.2665H156.703C154.409 12.2665 152.664 13.8422 151.98 15.3485H151.706V12.7118H147.703V30.653ZM178.078 30.653H181.227V27.0578H178.113C176.881 27.0578 176.367 26.5099 176.367 25.2436V16.2723H181.432V12.7118H176.367V7.67825H172.535V12.7118H169.181V16.2723H172.295V25.2783C172.295 29.0787 174.587 30.653 178.078 30.653ZM192.061 30.6819C195.791 30.6819 199.077 28.8315 200.24 25.1019L196.544 24.21C195.893 26.1962 194.012 27.224 192.027 27.224C189.083 27.224 187.133 25.3057 187.098 22.2931H200.685V21.1627C200.685 15.8212 197.366 11.8502 191.89 11.8502C187.064 11.8502 182.924 15.6507 182.924 21.3C182.924 26.7788 186.585 30.6819 192.061 30.6819ZM187.133 19.3485C187.372 17.1916 189.323 15.376 191.89 15.376C194.354 15.376 196.374 16.917 196.579 19.3485H187.133Z" fill="#EDEDF0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M167.384 30.6528H163.345V16.2721H160.198V12.7116H167.384V30.6528Z" fill="#EDEDF0"/>
|
||||
<path d="M165.066 10.2207C166.538 10.2207 167.633 9.12493 167.633 7.68658C167.633 6.28436 166.538 5.18716 165.066 5.18716C163.594 5.18716 162.499 6.28291 162.499 7.68802C162.499 9.12493 163.594 10.2207 165.066 10.2207Z" fill="#EDEDF0"/>
|
||||
<path d="M45.5297 26.254V34.1729H25.78C20.0258 34.1729 15.0015 30.9883 12.314 26.254C11.1249 24.1556 10.426 21.8143 10.27 19.4063L10.27 17.2668C10.3401 16.1679 10.5243 15.0792 10.8196 14.0186C12.666 7.36887 18.6655 2.50013 25.7786 2.50013C32.896 2.50013 38.8941 7.37176 40.7391 14.0171H32.2945C30.9097 11.8502 28.5093 10.4176 25.78 10.4176C23.0508 10.4176 20.6518 11.8502 19.2656 14.0171C18.8371 14.6844 18.5113 15.4124 18.2991 16.1768C18.1046 16.8801 18.0066 17.6067 18.0077 18.3365C18.0045 19.4116 18.2189 20.4761 18.6379 21.4657C19.0569 22.4554 19.6719 23.3496 20.4456 24.0943C21.877 25.4802 23.7897 26.2546 25.78 26.254H45.5297Z" fill="#FD366E"/>
|
||||
<path d="M45.5297 16.1753V24.0942H31.113C31.887 23.3496 32.5022 22.4555 32.9215 21.4658C33.3407 20.4762 33.5554 19.4116 33.5524 18.3365C33.5531 17.6066 33.4545 16.88 33.2595 16.1768L45.5297 16.1753Z" fill="#FD366E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/cld-main-logo.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/creative.jpg
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
public/eaarth.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
public/f.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
1
public/file.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 391 B |
BIN
public/gf.png
Normal file
|
After Width: | Height: | Size: 822 KiB |
BIN
public/gggggg.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
1
public/globe.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
public/group.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
public/mmm.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/mo.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
1
public/next.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/s.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
public/ss.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/sss.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/st.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/sy.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/tit.jpg
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
1
public/vercel.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 128 B |
1
public/window.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
||||
|
After Width: | Height: | Size: 385 B |
17
tailwind.config.mjs
Normal file
@ -0,0 +1,17 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
background: "var(--background)",
|
||||
foreground: "var(--foreground)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||