### Start Development Server with pnpm Source: https://github.com/ecaronte/cumplefactura-web/blob/master/shadcn-ui/README.md Starts the development server using Vite. This command enables hot module replacement and provides a local development environment for the React application. ```shell pnpm run dev ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/ecaronte/cumplefactura-web/blob/master/shadcn-ui/README.md Installs all project dependencies using the pnpm package manager. This command reads the 'dependencies' and 'devDependencies' from the package.json file. ```shell pnpm i ``` -------------------------------- ### Project Development Commands (Bash) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A collection of essential bash commands for managing the project's development lifecycle. This includes installing dependencies, starting the development server, building for production, previewing the build, and linting the code. ```bash # Install dependencies pnpm install # Start development server pnpm run dev # Build for production pnpm run build # Preview production build pnpm run preview # Lint code pnpm run lint ``` -------------------------------- ### Add New Dependency with pnpm Source: https://github.com/ecaronte/cumplefactura-web/blob/master/shadcn-ui/README.md Adds a new dependency to the project using the pnpm package manager. The specified dependency will be installed and added to the project's package.json. ```shell pnpm add some_new_dependency ``` -------------------------------- ### Build Project for Production with pnpm Source: https://github.com/ecaronte/cumplefactura-web/blob/master/shadcn-ui/README.md Builds the project for production using Vite. This command optimizes the application for deployment, generating static assets. ```shell pnpm run build ``` -------------------------------- ### Mock API Data for Pricing and FAQs (TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Simulates asynchronous API calls for pricing plans and frequently asked questions. Returns Promise-wrapped data structures for 'Plan' and 'FaqItem'. Useful for development and testing. ```typescript import { Plan, FaqItem } from "../types"; export const getPlans = (): Promise => { return Promise.resolve([ { id: "connect", name: "CumpleFactura Connect", price: "4,90€", description: "Quick entry for migrations. Clear compliance without complexity.", features: [ "Plugin and panel access (Connect mode)", "Complete VeriFactu (QR + hash chain)", "Automatic AEAT record submission", "Compliance event logging", "Up to 60 invoices/month included", ], cta: "Start with Connect", }, { id: "pro", name: "CumpleFactura Pro", price: "10,90€", description: "Complete system for long-term operation. Includes WooCommerce plugin.", features: [ "Everything in Connect", "WooCommerce plugin included", "Invoice editor + templates + logo", "Advanced tax validations", "Up to 100 invoices/month included", ], cta: "Choose Pro", highlight: true, }, { id: "partner", name: "CumpleFactura Partner", price: "59€", description: "B2B product: multi-client panel and centralized control.", features: [ "Multi-client panel", "AEAT status and traceability per client", "B2B specialized support", ], cta: "Contact Us", }, ]); }; export const getFaqs = (): Promise => { return Promise.resolve([ { id: "1", question: "How long are promotional prices valid?", answer: "Promotion applies to new signups until July 1, 2027.", }, { id: "2", question: "What plan do I need for WooCommerce?", answer: "CumpleFactura Pro includes the WooCommerce plugin.", }, ]); }; ``` -------------------------------- ### API Client for Lead Submission (TypeScript) Source: https://github.com/ecaronte/cumplefactura-web/blob/master/attached_assets/Pasted-Quiero-que-ajustes-la-homepage-de-CumpleFactura-para-ca_1764723601837.txt Provides a TypeScript function `submitEarlyAccessLead` for handling the submission of early access lead data. This function reads the API base URL from the `VITE_API_BASE` environment variable and makes a POST request to the `/leads/early-access` endpoint. It includes the necessary payload structure and content type. ```typescript import { env } from 'process'; interface EarlyAccessPayload { nombre: string; email: string; tipoUsuario: string; volumenFacturas?: string; comentario?: string; consentimiento: boolean; timestamp: number; originPage: string; } async function submitEarlyAccessLead(payload: EarlyAccessPayload): Promise { const VITE_API_BASE = env.VITE_API_BASE; if (!VITE_API_BASE) { console.warn('VITE_API_BASE is not defined. Skipping API submission.'); return; } try { const response = await fetch(`${VITE_API_BASE}/leads/early-access`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); if (!response.ok) { console.error('Failed to submit early access lead:', response.statusText); } } catch (error) { console.error('Error submitting early access lead:', error); } } export { submitEarlyAccessLead }; ``` -------------------------------- ### Early Access Form Section Structure (HTML) Source: https://github.com/ecaronte/cumplefactura-web/blob/master/attached_assets/Pasted-Quiero-que-ajustes-la-homepage-de-CumpleFactura-para-ca_1764723601837.txt Defines the HTML structure for the 'early-access' section on the homepage. This section includes a title, introductory text, a button for 'gestorias', and the main early access form. It is designed to be a prominent part of the homepage for lead capture. ```html

Sé de los primeros en usar CumpleFactura

Estamos desplegando CumpleFactura para autónomos, pymes y gestorías. Déjanos tus datos y te avisamos cuando esté disponible, con prioridad para los primeros interesados.

[ Botón “Soy una gestoría” ] [ Formulario de early access ]
``` -------------------------------- ### Mock API Service Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Provides mock data for pricing plans and FAQs, simulating asynchronous API calls. ```APIDOC ## GET /plans ### Description Retrieves a list of available pricing plans. ### Method GET ### Endpoint /plans ### Parameters (No parameters) ### Response #### Success Response (200) - **id** (string) - Unique identifier for the plan. - **name** (string) - Name of the pricing plan. - **price** (string) - Price of the plan (e.g., "4,90€"). - **description** (string) - A brief description of the plan. - **features** (array of strings) - List of features included in the plan. - **cta** (string) - Call to action text for the plan. - **highlight** (boolean) - Optional. Indicates if the plan should be highlighted. #### Response Example ```json [ { "id": "connect", "name": "CumpleFactura Connect", "price": "4,90€", "description": "Quick entry for migrations. Clear compliance without complexity.", "features": [ "Plugin and panel access (Connect mode)", "Complete VeriFactu (QR + hash chain)", "Automatic AEAT record submission", "Compliance event logging", "Up to 60 invoices/month included" ], "cta": "Start with Connect" }, { "id": "pro", "name": "CumpleFactura Pro", "price": "10,90€", "description": "Complete system for long-term operation. Includes WooCommerce plugin.", "features": [ "Everything in Connect", "WooCommerce plugin included", "Invoice editor + templates + logo", "Advanced tax validations", "Up to 100 invoices/month included" ], "cta": "Choose Pro", "highlight": true } ] ``` ``` ```APIDOC ## GET /faqs ### Description Retrieves a list of frequently asked questions and their answers. ### Method GET ### Endpoint /faqs ### Parameters (No parameters) ### Response #### Success Response (200) - **id** (string) - Unique identifier for the FAQ item. - **question** (string) - The question asked. - **answer** (string) - The answer to the question. #### Response Example ```json [ { "id": "1", "question": "How long are promotional prices valid?", "answer": "Promotion applies to new signups until July 1, 2027." }, { "id": "2", "question": "What plan do I need for WooCommerce?", "answer": "CumpleFactura Pro includes the WooCommerce plugin." } ] ``` ``` -------------------------------- ### Configure React Router with Lazy Loading Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Sets up the main application router using React Router DOM. It includes lazy-loaded routes for different pages, wrapped in QueryClientProvider for data fetching and Suspense for loading states. Dependencies include react-router-dom and @tanstack/react-query. ```tsx import React, { Suspense } from "react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { BrowserRouter, Routes, Route } from "react-router-dom"; const Home = React.lazy(() => import("./pages/Home")); const Pricing = React.lazy(() => import("./pages/Pricing")); const ContactPage = React.lazy(() => import("./pages/ContactPage")); const queryClient = new QueryClient(); const App = () => ( Loading...}> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); export default App; ``` -------------------------------- ### Lead Capture - Early Access Form Source: https://github.com/ecaronte/cumplefactura-web/blob/master/replit.md This endpoint is used to capture lead information from the early access form on the homepage. ```APIDOC ## POST /leads/early-access ### Description Submits lead information from the early access form on the CumpleFactura homepage. ### Method POST ### Endpoint /leads/early-access ### Parameters #### Request Body - **nombre** (string) - Required - The name of the lead. - **email** (string) - Required - The email address of the lead. - **tipoUsuario** (string) - Required - The type of user (e.g., 'autonomo', 'empresa'). - **consentimiento** (boolean) - Required - Indicates if the user has given consent for communication. - **volumenFacturas** (string) - Optional - The estimated volume of invoices. - **comentario** (string) - Optional - Any additional comments from the lead. ### Request Example ```json { "nombre": "Juan Perez", "email": "juan.perez@example.com", "tipoUsuario": "autonomo", "consentimiento": true, "volumenFacturas": "100-200", "comentario": "Interesado en la solución para autónomos." } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating successful lead submission. ``` -------------------------------- ### Submit Lead Data via API (TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Provides functions to submit 'early access' and 'gestoria' lead data to the backend API. It defines the expected payload structures and handles POST requests with basic error checking. Requires API_BASE environment variable. ```typescript export interface EarlyAccessPayload { nombre: string; email: string; tipoUsuario: string; volumenFacturas?: string; comentario?: string; consentimiento: boolean; timestamp: string; originPage: string; } export interface GestoriaLeadPayload { nombreGestoria: string; personaContacto: string; email: string; telefono: string; codigoPostal: string; direccion?: string; volumen?: string; tipoClientes?: string; comentarios: string; consentimiento: boolean; timestamp: string; originPage: string; } const API_BASE = import.meta.env.VITE_API_BASE; // Submit early access lead export async function submitEarlyAccessLead(payload: EarlyAccessPayload): Promise { const url = `${API_BASE}/leads/early-access`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!response.ok) { throw new Error(`Error HTTP ${response.status}`); } } // Submit gestoria (accounting agency) lead export async function submitGestoriaLead(payload: GestoriaLeadPayload): Promise { const url = `${API_BASE}/leads/gestorias`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!response.ok) { throw new Error(`Error HTTP ${response.status}`); } } ``` -------------------------------- ### Early Access Form Fields (HTML/Form Structure) Source: https://github.com/ecaronte/cumplefactura-web/blob/master/attached_assets/Pasted-Quiero-que-ajustes-la-homepage-de-CumpleFactura-para-ca_1764723601837.txt Details the required and optional fields for the general early access form. It specifies input types, names, labels, validation requirements, and options for fields like 'Nombre', 'Email', 'Tipo de usuario', 'Consentimiento', 'Volumen de facturas', and 'Comentario'. It emphasizes the need for proper label associations and unique IDs. ```html ``` -------------------------------- ### Create Main Layout Component Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A reusable layout component that wraps page content with a consistent structure. It includes a Navbar, Footer, CookieBanner, and AnalyticsLoader, ensuring a uniform user experience across the application. It uses shadcn/ui components and Tailwind CSS for styling. ```tsx import { ReactNode } from 'react'; import Navbar from '@/components/layout/Navbar'; import Footer from '@/components/layout/Footer'; import CookieBanner from '@/components/CookieBanner'; import AnalyticsLoader from '@/components/AnalyticsLoader'; interface MainLayoutProps { children: ReactNode; } export default function MainLayout({ children }: MainLayoutProps) { return (
{children}
); } ``` -------------------------------- ### Gestoria Button Navigation (React/Router) Source: https://github.com/ecaronte/cumplefactura-web/blob/master/attached_assets/Pasted-Quiero-que-ajustes-la-homepage-de-CumpleFactura-para-ca_1764723601837.txt Specifies the implementation for a secondary button labeled 'Soy una gestoría'. This button should navigate users to the specific gestoria form located on the '/gestorias' page, targeting the section with the ID 'gestorias-form'. This can be achieved using a Link component or programmatic navigation with a hash. ```javascript Soy una gestoría ``` -------------------------------- ### Dynamic Pricing Calculation with Billing Cycle Toggle (React/TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt This React component calculates and displays pricing plans based on selected billing cycles (monthly, annual, 2-year, 3-year). It fetches plan data from a mock API and applies discounts for longer billing terms. The component uses React hooks for state management and effects. ```tsx import { useEffect, useState } from "react"; import { getPlans } from "@/services/mockApi"; import type { Plan } from "@/types"; type BillingCycle = "monthly" | "annual" | "2y" | "3y"; const DISCOUNTS: Record = { monthly: 0, annual: 0, "2y": 0.1, "3y": 0.18, }; const PRICING = { connect: { promo: { monthly: 4.9, annual: 55 }, standard: { monthly: 7.9, annual: 79 }, }, pro: { promo: { monthly: 10.9, annual: 119 }, standard: { monthly: 14.9, annual: 149 }, }, }; export default function Pricing() { const [plans, setPlans] = useState([]); const [cycle, setCycle] = useState("monthly"); useEffect(() => { getPlans().then(setPlans); }, []); const calculatePrice = (planId: string) => { const spec = PRICING[planId as keyof typeof PRICING]; if (!spec) return null; if (cycle === "monthly") { return { price: spec.promo.monthly, label: "/month" }; } const years = cycle === "annual" ? 1 : cycle === "2y" ? 2 : 3; const discount = DISCOUNTS[cycle]; const total = spec.promo.annual * years * (1 - discount); return { price: total, label: `/${years} year${years > 1 ? 's' : ''}` }; }; return (
{/* Billing Cycle Toggle */}
{(["monthly", "annual", "2y", "3y"] as BillingCycle[]).map((c) => ( ))}
{/* Plan Cards */} {plans.map((plan) => { const pricing = calculatePrice(plan.id); return (

{plan.name}

{pricing && (
€{pricing.price.toFixed(2)}{pricing.label}
)}
    {plan.features.map((f, i) =>
  • {f}
  • )}
); })}
); } ``` -------------------------------- ### Lead Capture - Gestorías Form Source: https://github.com/ecaronte/cumplefactura-web/blob/master/replit.md This endpoint is used to capture lead information from the gestorías form, typically found on the /gestorias page. ```APIDOC ## POST /leads/gestorias ### Description Submits lead information from the gestorías form, designed for accounting firms. ### Method POST ### Endpoint /leads/gestorias ### Parameters #### Request Body - **nombreGestoria** (string) - Required - The name of the gestoría. - **personaContacto** (string) - Required - The contact person's name. - **email** (string) - Required - The email address for the gestoría. - **telefono** (string) - Required - The phone number for the gestoría. - **codigoPostal** (string) - Required - The postal code of the gestoría. - **comentarios** (string) - Required - Any comments or inquiries from the gestoría. - **consentimiento** (boolean) - Required - Indicates if the gestoría has given consent for communication. - **direccion** (string) - Optional - The address of the gestoría. - **volumen** (string) - Optional - The volume of clients or invoices handled. - **tipoClientes** (string) - Optional - The types of clients the gestoría serves. ### Request Example ```json { "nombreGestoria": "Gestoría ABC", "personaContacto": "Maria Garcia", "email": "maria.garcia@gestoriaabc.es", "telefono": "+34 912 345 678", "codigoPostal": "28001", "comentarios": "Buscamos una solución para nuestros clientes autónomos.", "consentimiento": true, "tipoClientes": "Autónomos y PYMES" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating successful lead submission. ``` -------------------------------- ### Lead Capture API Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Provides endpoints for submitting lead capture forms. Supports early access and gestoria (accounting agency) leads. ```APIDOC ## POST /leads/early-access ### Description Submits an early access lead to the backend. ### Method POST ### Endpoint /leads/early-access ### Parameters #### Request Body - **nombre** (string) - Required - Name of the lead. - **email** (string) - Required - Email address of the lead. - **tipoUsuario** (string) - Required - Type of user. - **volumenFacturas** (string) - Optional - Invoice volume. - **comentario** (string) - Optional - User comment. - **consentimiento** (boolean) - Required - User consent. - **timestamp** (string) - Required - Timestamp of submission. - **originPage** (string) - Required - The page where the lead originated. ### Request Example ```json { "nombre": "John Doe", "email": "john.doe@example.com", "tipoUsuario": "freelancer", "volumenFacturas": "100", "comentario": "Interested in early access.", "consentimiento": true, "timestamp": "2023-10-27T10:00:00Z", "originPage": "/" } ``` ### Response #### Success Response (200) No content is returned on successful submission. #### Response Example (No content) ``` ```APIDOC ## POST /leads/gestorias ### Description Submits a lead for a gestoria (accounting agency) to the backend. ### Method POST ### Endpoint /leads/gestorias ### Parameters #### Request Body - **nombreGestoria** (string) - Required - Name of the gestoria. - **personaContacto** (string) - Required - Contact person's name. - **email** (string) - Required - Email address. - **telefono** (string) - Required - Phone number. - **codigoPostal** (string) - Required - Postal code. - **direccion** (string) - Optional - Address. - **volumen** (string) - Optional - Invoice volume. - **tipoClientes** (string) - Optional - Type of clients. - **comentarios** (string) - Required - Comments. - **consentimiento** (boolean) - Required - User consent. - **timestamp** (string) - Required - Timestamp of submission. - **originPage** (string) - Required - The page where the lead originated. ### Request Example ```json { "nombreGestoria": "ABC Gestoria", "personaContacto": "Jane Smith", "email": "jane.smith@abcgestoria.com", "telefono": "123-456-7890", "codigoPostal": "12345", "direccion": "123 Main St", "volumen": "500", "tipoClientes": "SMEs", "comentarios": "Looking for a solution for our clients.", "consentimiento": true, "timestamp": "2023-10-27T10:05:00Z", "originPage": "/" } ``` ### Response #### Success Response (200) No content is returned on successful submission. #### Response Example (No content) ``` -------------------------------- ### React Lead Capture Form with State Management and Async Submission Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt This React component implements a lead capture form using TypeScript. It manages form state, handles user input, performs asynchronous submission to an API, and displays submission status. Dependencies include React hooks and UI components from '@/components/ui'. ```tsx import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { submitEarlyAccessLead, EarlyAccessPayload } from "@/lib/api"; interface FormData { nombre: string; email: string; tipoUsuario: string; consentimiento: boolean; } export default function EarlyAccessSection() { const [formData, setFormData] = useState({ nombre: "", email: "", tipoUsuario: "", consentimiento: false, }); const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); const payload: EarlyAccessPayload = { ...formData, timestamp: new Date().toISOString(), originPage: "home-early-access", }; try { await submitEarlyAccessLead(payload); setIsSubmitted(true); } catch (error) { console.error("Submission failed:", error); } finally { setIsSubmitting(false); } }; if (isSubmitted) { return
Thank you for your interest!
; } return (
setFormData(prev => ({ ...prev, nombre: e.target.value }))} required />
setFormData(prev => ({ ...prev, email: e.target.value }))} required />
setFormData(prev => ({ ...prev, consentimiento: checked === true })) } />
); } ``` -------------------------------- ### Homepage Hero CTA and Scroll Behavior (JavaScript) Source: https://github.com/ecaronte/cumplefactura-web/blob/master/attached_assets/Pasted-Quiero-que-ajustes-la-homepage-de-CumpleFactura-para-ca_1764723601837.txt Implements the main Call to Action (CTA) button in the homepage hero section. It changes the button text to 'Quiero CumpleFactura' and configures it to smoothly scroll to the 'early-access' form section on the same page. It also ensures any 'Empezar' button in the navbar shares this scrolling behavior. ```javascript document.getElementById("early-access")?.scrollIntoView({ behavior: "smooth" }); ``` -------------------------------- ### useHashScroll Hook Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A custom React hook that enables smooth scrolling to elements identified by URL hash fragments. ```APIDOC ## useHashScroll Hook ### Description This custom hook automatically scrolls the page to an element whose ID matches the URL's hash fragment (e.g., `#section-id`). It's useful for navigation within a single page application. ### Usage Import and call `useHashScroll()` at the top level of your page component. ```javascript import { useHashScroll } from './useHashScroll'; // Adjust path as needed function MyPageComponent() { useHashScroll(); return (
Content for section 1
Content for section 2
); } ``` ### How it works - It listens to changes in the URL's hash. - If a hash is present, it finds the corresponding DOM element by its ID. - It then uses `element.scrollIntoView({ behavior: 'smooth' })` to smoothly scroll the page to that element. - A small timeout is used to ensure the DOM is ready before scrolling. ``` -------------------------------- ### Core TypeScript Interfaces (TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt Defines the fundamental data structures used throughout the application, including 'Plan', 'FaqItem', 'Feature', and 'NavLink'. These interfaces ensure type safety and consistency. ```typescript export interface Plan { id: string; name: string; price: string; description: string; features: string[]; cta: string; highlight?: boolean; } export interface FaqItem { id: string; question: string; answer: string; } export interface Feature { title: string; description: string; icon?: string; } export interface NavLink { label: string; href: string; } ``` -------------------------------- ### Button Component using shadcn/ui and class-variance-authority (React/TSX) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A customizable Button component leveraging shadcn/ui for styling and class-variance-authority for variant management. It supports the `asChild` pattern for composition with other elements and integrates with Radix UI's Slot for flexible rendering. Dependencies include React, class-variance-authority, and Radix UI. ```tsx import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/lib/utils'; const buttonVariants = cva( 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50', { variants: { variant: { default: 'bg-primary text-primary-foreground hover:bg-primary/90', destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', outline: 'border border-input hover:bg-accent hover:text-accent-foreground', secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', ghost: 'hover:bg-accent hover:text-accent-foreground', link: 'text-primary underline-offset-4 hover:underline', }, size: { default: 'h-10 px-4 py-2', sm: 'h-9 rounded-md px-3', lg: 'h-11 rounded-md px-8', icon: 'h-10 w-10', }, }, defaultVariants: { variant: 'default', size: 'default' }, } ); export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean; } const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : 'button'; return ; } ); export { Button, buttonVariants }; // Usage examples: // // // // ``` -------------------------------- ### Smooth Scrolling Hook for Hash URLs (React/TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A custom React hook, `useHashScroll`, that automatically scrolls the page to an element specified by the URL hash. It uses `useEffect` and `useLocation` from `react-router-dom` to detect hash changes and perform smooth scrolling. ```typescript import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; export function useHashScroll() { const { hash } = useLocation(); useEffect(() => { if (hash) { const elementId = hash.replace('#', ''); const element = document.getElementById(elementId); if (element) { setTimeout(() => { element.scrollIntoView({ behavior: 'smooth' }); }, 100); } } }, [hash]); } // Usage in a page component: export default function Home() { useHashScroll(); return (
{/* Content scrolled to when URL has #early-access */}
); } ``` -------------------------------- ### Class Merging Utility Function (TypeScript) Source: https://context7.com/ecaronte/cumplefactura-web/llms.txt A utility function `cn` that merges CSS class names using `clsx` for conditional class application and `tailwind-merge` for resolving Tailwind CSS class conflicts. This function is essential for dynamically applying styles in a Tailwind CSS environment. It takes a variable number of class values as input and returns a single, optimized class string. ```typescript import { clsx, type ClassValue } from 'clsx'; import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } // Usage: // cn('px-4 py-2', 'bg-blue-500', condition && 'text-white') // Returns merged, deduplicated class string ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.