diff --git a/app/page.tsx b/app/page.tsx
index af3a694..5fc4d73 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useState } from "react"
+import { useState, useEffect } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
@@ -8,6 +8,43 @@ import { ScrollArea } from "@/components/ui/scroll-area"
import { Separator } from "@/components/ui/separator"
import { BookOpen, Code, FileText, Hash, Info, Settings, Tag, Users, ChevronRight } from "lucide-react"
+const SyntaxHighlighter = ({ code, language = "javascript" }: { code: string; language?: string }) => {
+ const [highlightedCode, setHighlightedCode] = useState(code)
+
+ useEffect(() => {
+ // Simple syntax highlighting for JavaScript/JSDoc
+ const highlight = (text: string) => {
+ return (
+ text
+ // JSDoc tags
+ .replace(/(@\w+)/g, '$1')
+ // Comments
+ .replace(/(\/\*\*[\s\S]*?\*\/)/g, '$1')
+ .replace(/(\/\/.*$)/gm, '$1')
+ // Strings
+ .replace(/(['"`])((?:(?!\1)[^\\]|\\.)*)(\1)/g, '$1$2$3')
+ // Keywords
+ .replace(
+ /\b(function|class|const|let|var|if|else|for|while|return|new|this|typeof|instanceof)\b/g,
+ '$1',
+ )
+ // Types in curly braces
+ .replace(/\{([^}]+)\}/g, '{$1}')
+ // Numbers
+ .replace(/\b(\d+\.?\d*)\b/g, '$1')
+ )
+ }
+
+ setHighlightedCode(highlight(code))
+ }, [code])
+
+ return (
+
+
+
+ )
+}
+
const sections = [
{
id: "basic",
@@ -499,6 +536,7 @@ module.exports = {
export default function JSDocCheatsheet() {
const [activeSection, setActiveSection] = useState("basic")
const [expandedSections, setExpandedSections] = useState(["basic"])
+ const [isScrolling, setIsScrolling] = useState(false)
const toggleSection = (sectionId: string) => {
setExpandedSections((prev) =>
@@ -509,10 +547,43 @@ export default function JSDocCheatsheet() {
const scrollToTag = (tag: string) => {
const element = document.getElementById(tag.replace("@", "").replace(/[^a-zA-Z0-9]/g, "-"))
if (element) {
+ setIsScrolling(true)
element.scrollIntoView({ behavior: "smooth", block: "start" })
+
+ // Reset scrolling state after animation
+ setTimeout(() => setIsScrolling(false), 1000)
+
+ // Highlight the element briefly
+ element.classList.add("ring-2", "ring-primary", "ring-opacity-50")
+ setTimeout(() => {
+ element.classList.remove("ring-2", "ring-primary", "ring-opacity-50")
+ }, 2000)
}
}
+ useEffect(() => {
+ const handleScroll = () => {
+ if (isScrolling) return // Don't update during programmatic scrolling
+
+ const sections = Object.keys(jsdocData)
+ const scrollPosition = window.scrollY + 200
+
+ for (const sectionId of sections) {
+ const element = document.getElementById(`section-${sectionId}`)
+ if (element) {
+ const { offsetTop, offsetHeight } = element
+ if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) {
+ setActiveSection(sectionId)
+ break
+ }
+ }
+ }
+ }
+
+ window.addEventListener("scroll", handleScroll)
+ return () => window.removeEventListener("scroll", handleScroll)
+ }, [isScrolling])
+
return (
{/* Header */}
@@ -530,7 +601,7 @@ export default function JSDocCheatsheet() {
{/* Sidebar Navigation */}