diff --git a/app/globals.css b/app/globals.css index 4ff7e5c..466cb8b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,27 +3,152 @@ @tailwind utilities; :root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; + --background: #101112; + --foreground: #d9d9d9; + --card: #272829; + --card-foreground: #ffffff; + --card-border: #1a1a1a; + --primary: #7a7fee; + --primary-foreground: #ffffff; + --secondary: #272829; + --secondary-foreground: #ffffff; + --muted: #a1a1aa; + --muted-foreground: #d4d4d8; + --accent: #2a2a2a; + --accent-foreground: #ffffff; + --border: #2a2a2a; + --input: #2a2a2a; + --ring: #7a7fee; + --radius: 0.75rem; + --font-outfit: "Outfit", sans-serif; } -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; +@layer base { + body { + background-color: var(--background); + color: var(--foreground); + font-family: var(--font-outfit); + } + + html { + scroll-behavior: smooth; + } + + h1 { + font-weight: 500; + font-size: 60px; + line-height: 1.2em; + letter-spacing: 0; + } + + h2 { + font-weight: 400; + font-size: 48px; + line-height: 1.2em; + letter-spacing: 0; + } + + @media (max-width: 1440px) { + h1 { + font-size: calc(40px + (60 - 40) * ((100vw - 768px) / (1440 - 768))); + } + h2 { + font-size: calc(36px + (48 - 36) * ((100vw - 768px) / (1440 - 768))); + } + } + + @media (max-width: 768px) { + h1 { + font-size: 40px; + } + h2 { + font-size: 36px; + } } } -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); +@layer components { + .container { + @apply mx-auto px-4 sm:px-6 lg:px-8; + max-width: 1200px; + } + + .card { + background-color: var(--card); + color: var(--card-foreground); + border: 1px solid var(--card-border); + @apply rounded-3xl overflow-hidden shadow-md; + } + + .dark .card { + background-color: var(--card); + background-image: linear-gradient(to bottom, #2d2e2f, #272829); + position: relative; + } + + .dark .card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: url("/noise-texture.png"); + background-size: 200px; + opacity: 0.4; + mix-blend-mode: overlay; + pointer-events: none; + border-radius: inherit; + } + + .btn-primary { + background-color: #7a7fee; + color: #ffffff; + @apply px-6 py-2.5 rounded-md hover:bg-opacity-90 transition-all text-sm font-medium shadow-sm; + } + + .btn-secondary { + color: var(--foreground); + @apply hover:underline transition-all text-sm font-medium py-2.5; + } + + .section-title { + @apply font-medium mb-2; + color: var(--foreground); + } + + .section-subtitle { + color: #7a7fee; + @apply font-medium mb-6; + } + + .accent-text { + color: #7a7fee; + } + + /* Mobile menu styles */ + .mobile-menu-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 100; + } + + .mobile-menu { + position: fixed; + top: 0; + right: 0; + bottom: 0; + width: 85%; + max-width: 320px; + background-color: var(--background); + z-index: 101; + overflow-y: auto; + box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1); + } } @layer utilities { diff --git a/app/layout.tsx b/app/layout.tsx index fbc50a7..9b2eaaf 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,9 +1,11 @@ import type { Metadata } from "next"; import "./globals.css"; -import { Orbitron } from "next/font/google"; +import { Outfit } from "next/font/google"; +import { ThemeProvider } from "@/components/theme-provider"; -const orbitron = Orbitron({ +const outfit = Outfit({ subsets: ["latin"], + variable: "--font-outfit", }); export const metadata: Metadata = { @@ -74,8 +76,12 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - {children} + + + + {children} + + ); } diff --git a/app/page.tsx b/app/page.tsx index f90e95d..eee06f6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,118 +1,5 @@ -import React from "react"; -import Image from "next/image"; -import D from "@/public/logic-gate-or-svgrepo-com.svg"; -import cir from "@/public/8bvaKz01 (1).svg"; -import Link from "next/link"; -import { LoaderButton } from "@/components/LoaderButton"; +import LandingPage from "@/components/landing-page" export default function Home() { - return ( -
-
- {/* Header */} -
-
- Logic Gate -

- igital{" "} -

-
- -

- Circuit Simulator -

-
- -

- Build, test, and analyze your digital circuits virtually — no - breadboard required. -

- -
- Circuit illustration -
- - - - -
- - {/* About Section */} -
-

- About the Project -

-

- The{" "} - - Digital Circuit Simulator{" "} - - is an interactive learning platform designed to make digital - electronics accessible and engaging. Built with modern web - technologies, it offers a seamless drag-and-drop interface that lets - you visualize, connect, and test digital logic components — all within - your browser. -

-
- - {/* Core Features Section */} -
-

- Core Features -

- -
-
-

- Logic Gate Design -

-

- Build circuits visually using AND, OR, NOT, NAND, NOR, XOR, and - XNOR gates. -

-
- -
-

- Interactive Connections -

-

- Connect components with dynamic wires and handles. -

-
- -
-

- Live Testing -

-

- Observe instant changes in output as you toggle input switches and - test your logic. -

-
- -
-

- Browser-Based -

-

- No installations or hardware setup — experiment directly from your - web browser. -

-
-
-
- - {/* Subtle footer glow */} -
-
- ); + return } diff --git a/components/Toolbar.tsx b/components/Toolbar.tsx index f17ea42..e1a5e5d 100644 --- a/components/Toolbar.tsx +++ b/components/Toolbar.tsx @@ -13,24 +13,11 @@ import { Cpu, X, } from "lucide-react"; - -interface GateType { - id: string; - color: string; - name: string; - inputs?: string[]; - outputs: { [key: string]: string }; - circuit?: { gates: GateType[]; wires: Wire[] }; -} - -interface Wire { - source: string; - target: string; -} +import { GateType, PendingNode } from "@/types"; interface ToolbarProps { paletteOpen: boolean; - pendingNode: { type: string; gate?: GateType } | null; + pendingNode: PendingNode | null; nextLabelIndex: number; GateList: GateType[]; onTogglePalette: () => void; diff --git a/components/landing-page/call-to-action.tsx b/components/landing-page/call-to-action.tsx new file mode 100644 index 0000000..1f730fc --- /dev/null +++ b/components/landing-page/call-to-action.tsx @@ -0,0 +1,37 @@ +import Image from "next/image" +import Link from "next/link" + +export default function CallToAction() { + return ( +
+
+
+

+ Ready to Build Your First Circuit? +

+

+ Start creating digital logic circuits today. +

+

+ Drag and drop components, connect them with wires, and test your designs in real-time. No installation required. +

+
+ + Start Building Circuits + +
+
+ +
+ Circuit Illustration +
+
+
+ ) +} diff --git a/components/landing-page/data.ts b/components/landing-page/data.ts new file mode 100644 index 0000000..36924df --- /dev/null +++ b/components/landing-page/data.ts @@ -0,0 +1,64 @@ +import { CircleDot, Layers, Rocket } from "lucide-react" + +export const faqs = [ + { + id: 1, + question: "What is a Digital Circuit Simulator?", + answer: + "A digital circuit simulator is a tool that allows you to design, build, and test digital logic circuits virtually. It helps you understand how logic gates work together to create complex digital systems without needing physical components.", + }, + { + id: 2, + question: "How do I start building circuits?", + answer: + "Simply click 'Start Building' to access our circuit builder. Drag logic gates from the toolbar onto the canvas, connect them with wires, add input switches and output displays, then test your circuit by toggling the inputs.", + }, + { + id: 3, + question: "What types of circuits can I build?", + answer: + "You can build basic logic circuits (AND, OR, NOT gates), arithmetic circuits (adders, subtractors), sequential circuits (flip-flops, counters), and complex systems. The simulator supports all standard digital logic components.", + }, + { + id: 4, + question: "Is the simulator free to use?", + answer: + "Yes! Our digital circuit simulator is completely free to use. No registration required, no hidden fees. Simply open your browser and start building circuits immediately.", + }, + { + id: 5, + question: "Can I save and share my circuits?", + answer: + "Currently, circuits are saved in your browser's local storage. You can export circuit designs and share them with others. Future updates will include cloud saving and sharing features.", + }, + { + id: 6, + question: "Is this suitable for educational use?", + answer: + "Absolutely! Our simulator is perfect for students learning digital logic, computer science courses, and electronics education. Teachers can use it to demonstrate concepts and students can experiment hands-on.", + }, +] + +export const services = [ + { + id: 1, + title: "Visual Circuit Design", + description: "Build circuits with drag-and-drop logic gates, inputs, and outputs using our intuitive interface.", + icon: CircleDot, + color: "bg-[#7A7FEE]", + }, + { + id: 2, + title: "Real-time Simulation", + description: "Test your circuits instantly with live input toggles and see outputs change in real-time.", + icon: Layers, + color: "bg-[#7A7FEE]", + }, + { + id: 3, + title: "Interactive Learning", + description: "Learn digital logic through hands-on experimentation with guided examples and tutorials.", + icon: Rocket, + color: "bg-[#7A7FEE]", + }, +] \ No newline at end of file diff --git a/components/landing-page/faq.tsx b/components/landing-page/faq.tsx new file mode 100644 index 0000000..941e33d --- /dev/null +++ b/components/landing-page/faq.tsx @@ -0,0 +1,51 @@ +"use client" + +import { useState } from "react" +import { ChevronDown } from "lucide-react" +import { faqs } from "./data" + +export default function Faq() { + const [openItem, setOpenItem] = useState(null) + + const toggleItem = (id: number) => { + setOpenItem(openItem === id ? null : id) + } + + return ( +
+
+

+ Frequently Asked + Questions +

+

+ Have questions about digital circuits and how our simulator works? Find answers to the most common questions and learn how to + get started with digital logic design. +

+ +
+ {faqs.map((faq) => ( +
+ + {openItem === faq.id && ( +
+ {faq.answer} +
+ )} +
+ ))} +
+
+
+ ) +} diff --git a/components/landing-page/footer.tsx b/components/landing-page/footer.tsx new file mode 100644 index 0000000..e3396b0 --- /dev/null +++ b/components/landing-page/footer.tsx @@ -0,0 +1,46 @@ +"use client" + +import Link from "next/link" +import Image from "next/image" +import { useTheme } from "@/components/theme-provider" +import { useState, useEffect } from "react" + +export default function Footer() { + const { resolvedTheme } = useTheme() + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + }, []) + + return ( +
+
+ + {mounted ? ( +
+ Digital Circuit Logo + Digital Circuit Simulator +
+ ) : ( +
+ )} + +

+ Interactive Digital Logic Circuit Simulator +

+ +

+ © {new Date().getFullYear()} Digital Circuit Simulator. All rights reserved. +

+
+
+ ) +} diff --git a/components/landing-page/header.tsx b/components/landing-page/header.tsx new file mode 100644 index 0000000..6cd8765 --- /dev/null +++ b/components/landing-page/header.tsx @@ -0,0 +1,180 @@ +"use client"; + +import type React from "react"; +import { useState, useEffect } from "react"; +import Image from "next/image"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { Menu, X } from "lucide-react"; + +export default function Header() { + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const [isScrolled, setIsScrolled] = useState(false); + const [mounted, setMounted] = useState(false); + const router = useRouter(); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + const handleScroll = () => { + if (window.scrollY > 10) { + setIsScrolled(true); + } else { + setIsScrolled(false); + } + }; + + window.addEventListener("scroll", handleScroll); + handleScroll(); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, []); + + const handleLogoClick = (e: React.MouseEvent) => { + e.preventDefault(); + router.push("/"); + }; + + + + return ( + <> +
+
+
+
+ + {mounted ? ( + <> +
+ Digital Circuit Logo + Digital Circuit Simulator +
+ + ) : ( +
+ )} + + + + +
+ +
+ + Log in + + + Register + +
+ + +
+
+
+
+
+ + {mobileMenuOpen && ( +
+
setMobileMenuOpen(false)} + /> +
+
+
+
+
+ Digital Circuit Logo +
+ + Digital Circuit + +
+ +
+ + + +
+ setMobileMenuOpen(false)} + > + Log in + + setMobileMenuOpen(false)} + > + Register + +
+
+
+
+ )} + + ); +} diff --git a/components/landing-page/hero.tsx b/components/landing-page/hero.tsx new file mode 100644 index 0000000..1fe3c3b --- /dev/null +++ b/components/landing-page/hero.tsx @@ -0,0 +1,39 @@ +import Image from "next/image" +import Link from "next/link" + +export default function Hero() { + return ( +
+
+
+

+ Design & Test + Digital Circuits +

+

+ Build digital logic circuits visually with drag-and-drop components. + Test your designs in real-time with our interactive simulator. +

+
+ + Start Building + + + Learn More + +
+
+ +
+ Circuit Illustration +
+
+
+ ) +} diff --git a/components/landing-page/index.tsx b/components/landing-page/index.tsx new file mode 100644 index 0000000..9720d16 --- /dev/null +++ b/components/landing-page/index.tsx @@ -0,0 +1,27 @@ +import Header from "./header" +import Hero from "./hero" +import Services from "./services" +import Faq from "./faq" +import CallToAction from "./call-to-action" +import Footer from "./footer" + +interface LandingPageProps { + showHeader?: boolean + showFooter?: boolean +} +export { Header, Hero, Services, Faq, CallToAction, Footer } + +export default function LandingPage({ showHeader = true, showFooter = true }: LandingPageProps) { + return ( +
+ {showHeader &&
} +
+ + + + +
+ {showFooter &&
} +
+ ) +} diff --git a/components/landing-page/services.tsx b/components/landing-page/services.tsx new file mode 100644 index 0000000..1941dda --- /dev/null +++ b/components/landing-page/services.tsx @@ -0,0 +1,28 @@ +import { services } from "./data" + +export default function Services() { + return ( +
+

+ Your Circuit + Learning Journey +

+

+ From basic gates to complex circuits, our simulator provides everything you need to master digital logic. + Start your journey with our interactive platform. +

+ +
+ {services.map((service) => ( +
+
+ +
+

{service.title}

+

{service.description}

+
+ ))} +
+
+ ) +} diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx new file mode 100644 index 0000000..e13ef34 --- /dev/null +++ b/components/theme-provider.tsx @@ -0,0 +1,54 @@ +"use client" + +import { createContext, useContext, useEffect, useState } from "react" + +type ThemeProviderProps = { + children: React.ReactNode +} + +type ThemeProviderState = { + theme: "dark" + resolvedTheme: "dark" +} + +const initialState: ThemeProviderState = { + theme: "dark", + resolvedTheme: "dark", +} + +const ThemeProviderContext = createContext(initialState) + +export function ThemeProvider({ + children, + ...props +}: ThemeProviderProps) { + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + // Always set dark mode + const root = window.document.documentElement + root.classList.remove("light") + root.classList.add("dark") + }, []) + + const value = { + theme: "dark" as const, + resolvedTheme: "dark" as const, + } + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext) + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider") + + return context +} diff --git a/constants/gates.ts b/constants/gates.ts new file mode 100644 index 0000000..5e5f1f2 --- /dev/null +++ b/constants/gates.ts @@ -0,0 +1,55 @@ +import { GateType } from "@/types"; + +export const GateList: GateType[] = [ + { + id: "1", + name: "AND", + color: "#267AB2", + inputs: ["a", "b"], + outputs: { out: "a && b" }, + }, + { + id: "2", + name: "OR", + color: "#0D6E52", + inputs: ["x", "y"], + outputs: { out: "x || y" }, + }, + { + id: "3", + name: "NOT", + color: "#8C1F1A", + inputs: ["a"], + outputs: { out: "!a" }, + }, + { + id: "4", + name: "NAND", + color: "#5C2D91", + inputs: ["a", "b"], + outputs: { out: "!(a && b)" }, + }, + { + id: "5", + name: "NOR", + color: "#1F5B70", + inputs: ["a", "b"], + outputs: { out: "!(a || b)" }, + }, + { + id: "6", + name: "XOR", + color: "#A65B1F", + inputs: ["a", "b"], + outputs: { out: "(a && !b) || (!a && b)" }, + }, + { + id: "7", + name: "XNOR", + color: "#3F6B2F", + inputs: ["a", "b"], + outputs: { out: "!((a && !b) || (!a && b))" }, + }, +]; + +export const proOptions = { hideAttribution: true }; diff --git a/package-lock.json b/package-lock.json index 9e48af1..14dd2b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "clsx": "^2.1.1", "framer-motion": "^12.23.24", "lucide-react": "^0.546.0", + "motion": "^12.23.24", "next": "^14.2.33", "next-auth": "^5.0.0-beta.16", "react": "^18", @@ -1278,6 +1279,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", "devOptional": true, + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1288,6 +1290,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz", "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==", "devOptional": true, + "peer": true, "dependencies": { "@types/react": "*" } @@ -1436,6 +1439,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2038,6 +2042,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "peer": true, "engines": { "node": ">=12" } @@ -2438,6 +2443,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2590,6 +2596,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, + "peer": true, "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -4016,6 +4023,32 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/motion": { + "version": "12.23.24", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.23.24.tgz", + "integrity": "sha512-Rc5E7oe2YZ72N//S3QXGzbnXgqNrTESv8KKxABR20q2FLch9gHLo0JLyYo2hZ238bZ9Gx6cWhj9VO0IgwbMjCw==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.23.24", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/motion-dom": { "version": "12.23.23", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", @@ -4506,6 +4539,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -4634,6 +4668,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -4700,6 +4735,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -4711,6 +4747,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -5336,6 +5373,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -5558,6 +5596,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 3387e1c..d01dd4b 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "clsx": "^2.1.1", "framer-motion": "^12.23.24", "lucide-react": "^0.546.0", + "motion": "^12.23.24", "next": "^14.2.33", "next-auth": "^5.0.0-beta.16", "react": "^18", diff --git a/tailwind.config.ts b/tailwind.config.ts index 7e4bd91..a3aad17 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -6,6 +6,7 @@ const config: Config = { "./components/**/*.{js,ts,jsx,tsx,mdx}", "./app/**/*.{js,ts,jsx,tsx,mdx}", ], + darkMode: 'class', theme: { extend: { backgroundImage: { diff --git a/types/index.ts b/types/index.ts new file mode 100644 index 0000000..8cc63c4 --- /dev/null +++ b/types/index.ts @@ -0,0 +1,33 @@ +export interface GateType { + id: string; + color: string; + name: string; + inputs?: string[]; + outputs: { [key: string]: string }; + circuit?: { gates: GateType[]; wires: Wire[] }; +} + +export interface Wire { + source: string; + target: string; +} + +export interface PendingNode { + type: string; + gate?: GateType; +} + +export interface MousePosition { + x: number; + y: number; +} + +export interface CircuitState { + nodes: any[]; + edges: any[]; + inputValues: { [key: string]: boolean }; + outputValues: { [key: string]: boolean }; + paletteOpen: boolean; + pendingNode: PendingNode | null; + nextLabelIndex: number; +}