Files
zeekay 6c65e3e941 @hanzo/app 0.2.0: the app SDK, renamed from @hanzo/rooms
Every import, the catalog pin and the docs name @hanzo/app and
github.com/hanzoai/app. lib/rooms.ts is lib/app.ts and
components/rooms.tsx is components/app.tsx.
2026-10-22 19:07:20 -07:00

52 lines
1.8 KiB
TypeScript

'use client'
import { useSyncExternalStore } from 'react'
import { usePathname } from 'next/navigation'
import { ClosingCta } from '@hanzo/ui/marketing'
import { track } from '@hanzo/app/lib/tags'
import { bare, betaRunning, subscribeBeta } from '@/components/shell/mode'
/**
* Where a page ends without this call: the places a person already pays or
* reads, and the pages that state their own. Every focused page (the way in,
* the way to pay, the first run: components/shell/mode `bare`) is quiet too, so
* /forget and /join end at their mark as /login does.
*/
const QUIET = [
'/login', '/signup', '/onboarding', '/pricing', '/enterprise', '/contact', '/contact-sales', '/sms-opt-in', '/status', '/console',
'/account', '/settings', '/billing', '/auth',
'/legal', '/terms', '/privacy', '/cookies', '/pay', '/checkout', '/docs', '/blog',
// The application is the page. '/beta' does not match '/betaa'.
'/beta',
]
export const quiet = (path: string): boolean =>
QUIET.some((route) => path === route || path.startsWith(`${route}/`))
/**
* The one closing call, mounted once between a marketing page and its footer.
* A page outside the (marketing) layout mounts it itself, and may name its own
* headline and second door.
*/
export default function Closing({
title,
primary,
secondary,
}: {
title?: string
primary?: { label: string; href: string }
secondary?: { label: string; href: string } | null
}) {
const path = usePathname() ?? '/'
const applying = useSyncExternalStore(subscribeBeta, betaRunning, () => false)
if (quiet(path) || bare(path) || applying) return null
return (
<ClosingCta
title={title}
primary={primary}
secondary={secondary}
onCta={(cta) => cta === 'try_hanzo' && track('cta_clicked', { page: path, cta })}
/>
)
}