import { ReactNode, ComponentType, SVGProps } from 'react'; /** * Brand icon shape that mirrors a lucide-react icon component. Consumers * pass `Link2` / `Package` / `CreditCard` etc. directly; we render it * with the canonical color + stroke. */ type BrandIcon = ComponentType & { strokeWidth?: number; }>; interface NavLink { href: string; label: string; } interface FooterColumn { title: string; links: NavLink[]; } interface MarketingNavProps { /** * Rendered brand icon element (e.g. ``). * Pre-rendered as ReactNode because MarketingNav is a Client Component * and Next App Router forbids passing function components across the * Server → Client boundary. The consumer (which is a Server Component * layout) renders the icon itself with the canonical classes. * * Canonical classes: `h-6 w-6 text-primary` for the navbar. */ brandIcon: ReactNode; /** Product wordmark (e.g. "LinkSnap"). */ brandName: string; /** Override the default `/features /pricing /docs` set. */ navLinks?: NavLink[]; /** Path to the home page; defaults to "/". */ homeHref?: string; /** Path to the login route; defaults to "/login". Pass null to hide. */ loginHref?: string | null; /** Path to the CTA; defaults to "/signup". */ ctaHref?: string; /** CTA label; defaults to "Get Started". */ ctaLabel?: string; /** * Label on the login link; defaults to "Log in". * * Exists so a product with a translated marketing site can render the * whole navbar in one language. Without it the only escape was * `rightSlot`, which means rebuilding the login + CTA pair by hand and * losing the family chrome this component exists to guarantee. */ loginLabel?: string; /** * Accessible name for the mobile menu toggle; defaults to * "Toggle navigation menu". A screen-reader user on an Indonesian page * should not be read an English control name. */ menuLabel?: string; /** * Small controls rendered immediately BEFORE the login link — the * currency picker, and a language one where a product has it. * * Separate from `rightSlot` because the two answer different questions. * `rightSlot` replaces the login + CTA pair, so using it to hang a * currency toggle off the navbar means every product re-implements the * chrome this component exists to keep identical — and then drifts. * This one is additive: the defaults stay exactly where they are. * * On a phone it renders in a thin bar ABOVE the header, mirroring the * footer's preferences row — not inside the menu panel, because a choice * behind a tap is as buried as one behind a Settings page, and not beside * the hamburger, which crowded the header. Desktop keeps it in the nav * cluster; each placement is hidden where the other applies, so the slot * is never visible twice. */ localeSlot?: ReactNode; /** * What the phone bar shows instead of `localeSlot`. * * The bar was rendering the navbar's compact control cluster, which reads * as two unexplained widgets floating above the header. bang asked for it * to be the footer's preferences row instead — an uppercase label, the * same 12px muted type, the currency pushed to the far edge. * * Pass the row's CHILDREN, not a wrapper: the bar is the flex container * and supplies the typography, so `ms-auto` on the last child reaches the * real right edge. A wrapper div would collapse to its content width and * strand it mid-row. * * Falls back to `localeSlot`, so a product that has not opted in keeps * exactly the 0.7.0 behaviour. */ localeBar?: ReactNode; /** * Replace the right-hand login + CTA pair entirely. Useful for the * portal-style "Open dashboard" single button some products use. */ rightSlot?: ReactNode; } interface MarketingFooterProps { /** * Rendered brand icon element. Canonical classes for the footer: * `h-5 w-5 text-primary`. See MarketingNavProps.brandIcon for the * server/client boundary rationale. */ brandIcon: ReactNode; brandName: string; /** One-line tagline shown under the brand block. */ brandTagline?: string; /** * Override the default three columns (Product / Company / Legal). * If omitted, the locked defaults from the linksnap anchor are used. */ columns?: FooterColumn[]; /** * Bottom-row copyright suffix; defaults to "part of the Forjio family." * The "© YEAR PT Forjio Teknologi Indonesia." part is always rendered. */ copyrightSuffix?: string; /** * Override the locked PT Forjio address block. Most products should * leave this alone — it's the single legal entity for all of them. */ company?: { name: string; address: ReactNode; phoneLabel: string; phoneHref: string; email: string; }; } export type { BrandIcon, FooterColumn, MarketingFooterProps, MarketingNavProps, NavLink };