mirror of
https://github.com/hanzoai/agency.git
synced 2026-11-02 19:13:28 +00:00
1 line
67 KiB
Plaintext
1 line
67 KiB
Plaintext
{"version":3,"file":"waitlist.js","names":[],"sources":["../src/storage.ts","../src/Join.tsx","../src/Share.tsx","../src/InviteFriends.tsx","../src/Status.tsx","../src/Waitlist.tsx","../src/useCountUp.ts","../src/Leaderboard.tsx","../src/Activity.tsx"],"sourcesContent":["// Single source of truth for the widget's localStorage shape.\n//\n// Both the widget and the host page may need to know \"is this visitor\n// already on the list, and what's their rank/refCode\" — owning that key\n// here keeps the contract in one place and lets consumers swap storage\n// out cleanly (e.g. to a cookie or a server-rendered prop).\n\nimport { useEffect, useState } from 'react'\n\n/** Persisted snapshot. Server is the source of truth; this is just a cache. */\nexport interface PersistedEntry {\n email: string\n rank?: number\n refCode?: string\n}\n\nconst PREFIX = 'hanzo-waitlist:'\nconst REF_KEY = 'hanzo-waitlist:ref'\n\nexport function entryKey(slug: string): string {\n return PREFIX + slug\n}\n\n/** Synchronous read (returns null on miss / parse error / SSR). */\nexport function readPersistedEntry(slug: string): PersistedEntry | null {\n if (typeof localStorage === 'undefined') return null\n try {\n const raw = localStorage.getItem(entryKey(slug))\n if (!raw) return null\n const parsed = JSON.parse(raw) as Partial<PersistedEntry>\n if (!parsed?.email) return null\n return { email: parsed.email, rank: parsed.rank, refCode: parsed.refCode }\n } catch {\n return null\n }\n}\n\nexport function writePersistedEntry(slug: string, entry: PersistedEntry): void {\n if (typeof localStorage === 'undefined') return\n try { localStorage.setItem(entryKey(slug), JSON.stringify(entry)) } catch { /* noop */ }\n // Notify same-tab subscribers — native `storage` event only fires cross-tab.\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('hanzo-waitlist:change', { detail: { slug } }))\n }\n}\n\nexport function clearPersistedEntry(slug: string): void {\n if (typeof localStorage === 'undefined') return\n try { localStorage.removeItem(entryKey(slug)) } catch { /* noop */ }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('hanzo-waitlist:change', { detail: { slug } }))\n }\n}\n\n/** Capture an inbound ?ref=<code> URL param for later submission. */\nexport function captureReferrerFromUrl(): void {\n if (typeof window === 'undefined') return\n try {\n const ref = new URLSearchParams(window.location.search).get('ref')\n if (ref) localStorage.setItem(REF_KEY, ref)\n } catch { /* noop */ }\n}\n\nexport function readPendingReferrer(): string | undefined {\n if (typeof localStorage === 'undefined') return undefined\n try { return localStorage.getItem(REF_KEY) ?? undefined } catch { return undefined }\n}\n\n/**\n * React hook: subscribes to the persisted entry for `slug`. Reactive to\n * same-tab writes (via custom event) and cross-tab writes (via native\n * `storage` event).\n */\nexport function usePersistedEntry(slug: string): PersistedEntry | null {\n const [entry, setEntry] = useState<PersistedEntry | null>(() => readPersistedEntry(slug))\n\n useEffect(() => {\n setEntry(readPersistedEntry(slug))\n const onChange = (e: Event) => {\n const target = (e as CustomEvent<{ slug?: string }>).detail?.slug\n if (target && target !== slug) return\n setEntry(readPersistedEntry(slug))\n }\n const onStorage = (e: StorageEvent) => {\n if (e.key === entryKey(slug)) setEntry(readPersistedEntry(slug))\n }\n window.addEventListener('hanzo-waitlist:change', onChange)\n window.addEventListener('storage', onStorage)\n return () => {\n window.removeEventListener('hanzo-waitlist:change', onChange)\n window.removeEventListener('storage', onStorage)\n }\n }, [slug])\n\n return entry\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport { WaitlistClient, type WaitlistEntry } from './client'\nimport { readPendingReferrer } from './storage'\n\nexport interface WaitlistJoinProps {\n /** Slug or id of the waitlist. */\n waitlist: string\n /** Base server URL. Defaults to current origin. */\n baseUrl?: string\n /** Copy. */\n title?: string\n subtitle?: string\n submitLabel?: string\n /** Cloudflare Turnstile token, if Turnstile is enabled server-side. */\n turnstileToken?: string\n /** Pre-fill the email field. */\n email?: string\n /** Fires with the new entry after a successful POST /join. */\n onSuccess?: (entry: WaitlistEntry) => void\n /** Fires on validation OR server error. */\n onError?: (err: { message: string; status: number }) => void\n}\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/**\n * Pure join form. No localStorage, no success view — that's the composer's\n * job (see <Waitlist>). Drops a single POST /v1/waitlist/join and notifies\n * onSuccess/onError. Pre-fills the referrerCode from storage if present.\n */\nexport function WaitlistJoin(props: WaitlistJoinProps) {\n const {\n waitlist, baseUrl,\n title = 'Join the waitlist',\n subtitle,\n submitLabel = 'Join',\n turnstileToken,\n email: initialEmail,\n onSuccess, onError,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const [email, setEmail] = useState(initialEmail ?? '')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const submit = useCallback(async (e?: React.FormEvent) => {\n e?.preventDefault()\n if (busy) return\n const normalized = email.trim().toLowerCase()\n if (!EMAIL_RE.test(normalized)) {\n const msg = 'Enter a valid email address.'\n setError(msg)\n onError?.({ message: msg, status: 0 })\n return\n }\n\n setBusy(true)\n setError(null)\n const res = await client.join({\n waitlist,\n email: normalized,\n referrerCode: readPendingReferrer(),\n turnstileToken,\n })\n\n if ('ok' in res && res.ok) {\n setBusy(false)\n onSuccess?.(res)\n return\n }\n const message = res.message || 'Something went wrong. Try again.'\n setError(message)\n onError?.({ message, status: res.status })\n setBusy(false)\n }, [busy, client, email, onError, onSuccess, turnstileToken, waitlist])\n\n return (\n <form onSubmit={submit} noValidate>\n <h3 className=\"hanzo-waitlist__title\">{title}</h3>\n {subtitle && <p className=\"hanzo-waitlist__subtitle\">{subtitle}</p>}\n <div className=\"hanzo-waitlist__row\">\n <input\n className=\"hanzo-waitlist__input\"\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n placeholder=\"[email protected]\"\n value={email}\n onChange={(e) => setEmail(e.currentTarget.value)}\n disabled={busy}\n aria-label=\"Email address\"\n required\n />\n <button type=\"submit\" className=\"hanzo-waitlist__button\" disabled={busy || !email}>\n {busy ? '…' : submitLabel}\n </button>\n </div>\n {error && <p className=\"hanzo-waitlist__error\" role=\"alert\">{error}</p>}\n </form>\n )\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport { WaitlistClient, type PointValues } from './client'\n\nexport type SharePlatformId =\n | 'webshare' | 'email' | 'x' | 'linkedin' | 'facebook'\n | 'reddit' | 'telegram' | 'whatsapp' | 'sms' | 'copy'\n\nexport interface ShareTarget {\n id: SharePlatformId | string\n label: string\n /** Points awarded for this action. If undefined, falls back to pointValues.SHARE. */\n points?: number\n /**\n * Returns a URL to open, OR `null` to skip the navigation (e.g. for copy /\n * webshare which do their own thing in `onClick`).\n */\n href: (ctx: ShareContext) => string | null\n /** Optional custom click handler — runs INSTEAD of href navigation. */\n onClick?: (ctx: ShareContext) => void | Promise<void>\n}\n\nexport interface ShareContext {\n url: string\n text: string\n rank: number\n refCode: string\n}\n\nexport interface WaitlistShareProps {\n /** Slug of the waitlist (needed for track-share calls). */\n waitlist: string\n /** The viewer's referral code (server credits points to this code). */\n refCode: string\n /** Full share URL (typically the host page with `?ref=<code>` appended). */\n shareUrl: string\n /** Optional viewer rank — used in default share text. */\n rank?: number\n /** Optional total — used in default share text. */\n total?: number\n\n /**\n * Override the share message. Receives the same ctx as href functions.\n * Default: `I'm #N on the waitlist. Join me:`\n */\n message?: (ctx: ShareContext) => string\n\n /**\n * Restrict / reorder targets. Pass an array of platform IDs from the\n * built-in set, OR a full ShareTarget for custom platforms. Defaults to\n * the full built-in roster.\n */\n shareTargets?: Array<SharePlatformId | ShareTarget>\n\n /**\n * Override the server's published point values for display only. The\n * actual point award still happens server-side per pointValues; this is\n * for showing custom labels.\n */\n pointValues?: Partial<PointValues>\n\n /** Base server URL. Defaults to current origin. */\n baseUrl?: string\n\n /** Callback after a successful track-share (or copy). */\n onShared?: (platform: string, awarded: number, alreadyClaimed: boolean) => void\n}\n\nconst DEFAULT_ORDER: SharePlatformId[] = [\n 'webshare', 'email', 'x', 'linkedin', 'facebook',\n 'reddit', 'telegram', 'whatsapp', 'sms', 'copy',\n]\n\nconst BUILTIN: Record<SharePlatformId, Omit<ShareTarget, 'id'>> = {\n webshare: {\n label: 'Share',\n href: () => null,\n onClick: async ({ url, text }) => {\n if (typeof navigator !== 'undefined' && 'share' in navigator) {\n try { await (navigator as Navigator & { share: (d: ShareData) => Promise<void> }).share({ text, url }) } catch { /* user cancelled */ }\n }\n },\n },\n email: {\n label: 'Email',\n href: ({ url, text }) => `mailto:?subject=${encodeURIComponent('Join the waitlist')}&body=${encodeURIComponent(`${text}\\n\\n${url}`)}`,\n },\n x: {\n label: 'X',\n href: ({ url, text }) => `https://x.com/intent/post?text=${encodeURIComponent(text)}&url=${encodeURIComponent(url)}`,\n },\n linkedin: {\n label: 'LinkedIn',\n href: ({ url }) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`,\n },\n facebook: {\n label: 'Facebook',\n href: ({ url }) => `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,\n },\n reddit: {\n label: 'Reddit',\n href: ({ url, text }) => `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(text)}`,\n },\n telegram: {\n label: 'Telegram',\n href: ({ url, text }) => `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`,\n },\n whatsapp: {\n label: 'WhatsApp',\n href: ({ url, text }) => `https://wa.me/?text=${encodeURIComponent(`${text} ${url}`)}`,\n },\n sms: {\n label: 'SMS',\n href: ({ url, text }) => `sms:?&body=${encodeURIComponent(`${text} ${url}`)}`,\n },\n copy: {\n label: 'Copy link',\n href: () => null,\n onClick: async ({ url }) => {\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try { await navigator.clipboard.writeText(url) } catch { /* noop */ }\n }\n },\n },\n}\n\nfunction resolveTargets(spec: WaitlistShareProps['shareTargets']): ShareTarget[] {\n const list = spec ?? DEFAULT_ORDER\n return list\n .map((entry) => {\n if (typeof entry === 'string') {\n const builtin = BUILTIN[entry as SharePlatformId]\n if (!builtin) return null\n return { id: entry, ...builtin }\n }\n return entry\n })\n .filter((x): x is ShareTarget => Boolean(x))\n}\n\nexport function WaitlistShare(props: WaitlistShareProps) {\n const {\n waitlist, refCode, shareUrl, rank = 0, total: _total,\n message, shareTargets, pointValues, baseUrl, onShared,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const targets = useMemo(() => resolveTargets(shareTargets), [shareTargets])\n const [busy, setBusy] = useState<string | null>(null)\n const [toast, setToast] = useState<string | null>(null)\n\n const sharePoints = pointValues?.SHARE ?? 2\n\n const ctx: ShareContext = useMemo(() => {\n const text = message\n ? message({ url: shareUrl, text: '', rank, refCode })\n : (rank ? `I'm #${rank.toLocaleString()} on the waitlist. Climb with me:` : 'Join me on the waitlist:')\n return { url: shareUrl, text, rank, refCode }\n }, [message, rank, refCode, shareUrl])\n\n // Hide Web Share when the API isn't there.\n const visibleTargets = useMemo(() => {\n if (typeof navigator === 'undefined' || !('share' in navigator)) {\n return targets.filter((t) => t.id !== 'webshare')\n }\n return targets\n }, [targets])\n\n const fire = useCallback(async (t: ShareTarget) => {\n if (busy) return\n setBusy(String(t.id))\n setToast(null)\n\n // Side action (copy / webshare) first so the user gets immediate feedback.\n try {\n if (t.onClick) await t.onClick(ctx)\n } catch { /* swallow — UX over correctness here */ }\n\n // Open the share URL (if any) in a new tab. Mailto/sms use same window.\n const href = t.href(ctx)\n if (href) {\n const sameWindow = href.startsWith('mailto:') || href.startsWith('sms:')\n if (sameWindow) {\n window.location.href = href\n } else {\n window.open(href, '_blank', 'noopener,noreferrer')\n }\n }\n\n // Fire-and-forget point award. Caps and dedup live on the server.\n const result = await client.trackShare({ waitlist, refCode, platform: String(t.id) })\n let awarded = 0\n let alreadyClaimed = false\n if ('ok' in result && result.ok) {\n awarded = result.awarded\n alreadyClaimed = result.alreadyClaimed\n if (awarded > 0) setToast(`+${awarded} from ${t.label}`)\n else if (alreadyClaimed) setToast(`Already counted today`)\n }\n onShared?.(String(t.id), awarded, alreadyClaimed)\n\n setBusy(null)\n // Auto-clear toast.\n setTimeout(() => setToast(null), 2200)\n }, [busy, client, ctx, onShared, refCode, waitlist])\n\n return (\n <div className=\"hanzo-waitlist__share-wrap\">\n <ul className=\"hanzo-waitlist__share\" role=\"list\">\n {visibleTargets.map((t) => {\n const pts = t.points ?? sharePoints\n const isBusy = busy === String(t.id)\n const emphasized = t.id === 'webshare' || t.id === 'copy'\n return (\n <li key={String(t.id)}>\n <button\n type=\"button\"\n className={`hanzo-waitlist__share-btn${emphasized ? '' : ' hanzo-waitlist__button--ghost'}`}\n onClick={() => fire(t)}\n disabled={isBusy}\n aria-label={`${t.label} (+${pts})`}\n >\n <span className=\"hanzo-waitlist__share-label\">{t.label}</span>\n {pts > 0 && (\n <span className=\"hanzo-waitlist__share-pts\" aria-hidden=\"true\">+{pts}</span>\n )}\n </button>\n </li>\n )\n })}\n </ul>\n <div className=\"hanzo-waitlist__toast\" role=\"status\" aria-live=\"polite\">\n {toast}\n </div>\n </div>\n )\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport { WaitlistClient, type InviteResponse } from './client'\n\nexport interface WaitlistInviteFriendsProps {\n /** Waitlist slug. */\n waitlist: string\n /** Viewer's referral code (server credits the points here). */\n refCode: string\n /** Base server URL. */\n baseUrl?: string\n /** Points per invite-sent, for display. Server is the source of truth. */\n pointPerInvite?: number\n /** Points per converted invite (when invited friend joins). */\n pointPerConversion?: number\n /** Max emails per submit (default 50). */\n maxBatch?: number\n /** Initial message body (optional, sent to the server). */\n defaultMessage?: string\n /** Callback after a successful submit. */\n onSent?: (result: InviteResponse) => void\n}\n\nfunction parseEmails(input: string): string[] {\n return input\n .split(/[\\s,;]+/)\n .map((s) => s.trim())\n .filter(Boolean)\n}\n\nexport function WaitlistInviteFriends(props: WaitlistInviteFriendsProps) {\n const {\n waitlist, refCode, baseUrl,\n pointPerInvite = 1,\n pointPerConversion = 5,\n maxBatch = 50,\n defaultMessage = '',\n onSent,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const [open, setOpen] = useState(false)\n const [raw, setRaw] = useState('')\n const [message, setMessage] = useState(defaultMessage)\n const [busy, setBusy] = useState(false)\n const [result, setResult] = useState<InviteResponse | null>(null)\n const [error, setError] = useState<string | null>(null)\n\n const emails = useMemo(() => parseEmails(raw), [raw])\n const count = emails.length\n const over = count > maxBatch\n const potential = count * pointPerInvite\n\n const submit = useCallback(async () => {\n if (count === 0 || over || busy) return\n setBusy(true)\n setError(null)\n setResult(null)\n const res = await client.invite({ waitlist, refCode, emails, message: message || undefined })\n if ('ok' in res && res.ok) {\n setResult(res)\n setRaw('')\n onSent?.(res)\n } else {\n setError(res.message || 'failed to send')\n }\n setBusy(false)\n }, [busy, client, count, emails, message, onSent, over, refCode, waitlist])\n\n return (\n <div className=\"hanzo-waitlist__invite\">\n <button\n type=\"button\"\n className=\"hanzo-waitlist__invite-toggle\"\n onClick={() => setOpen((o) => !o)}\n aria-expanded={open}\n >\n <span>Invite friends</span>\n <span className=\"hanzo-waitlist__invite-toggle-meta\">\n +{pointPerInvite}/sent · +{pointPerConversion}/joined\n </span>\n <span aria-hidden=\"true\" className={`hanzo-waitlist__chev${open ? ' is-open' : ''}`}>›</span>\n </button>\n\n {open && (\n <div className=\"hanzo-waitlist__invite-panel\">\n <label className=\"hanzo-waitlist__invite-label\" htmlFor=\"hw-invite-emails\">\n Emails\n <span className=\"hanzo-waitlist__invite-hint\">\n {count} {count === 1 ? 'address' : 'addresses'}\n {over && ` — max ${maxBatch}`}\n {!over && count > 0 && ` · +${potential} pts pending`}\n </span>\n </label>\n <textarea\n id=\"hw-invite-emails\"\n className=\"hanzo-waitlist__invite-textarea\"\n placeholder={`[email protected]\\[email protected], [email protected]`}\n rows={4}\n value={raw}\n onChange={(e) => setRaw(e.currentTarget.value)}\n disabled={busy}\n />\n <input\n type=\"text\"\n className=\"hanzo-waitlist__input\"\n placeholder=\"Personal note (optional)\"\n value={message}\n maxLength={500}\n onChange={(e) => setMessage(e.currentTarget.value)}\n disabled={busy}\n />\n <button\n type=\"button\"\n className=\"hanzo-waitlist__button\"\n onClick={submit}\n disabled={busy || count === 0 || over}\n >\n {busy ? 'Sending…' : count > 0 ? `Send ${count} ${count === 1 ? 'invite' : 'invites'}` : 'Send invites'}\n </button>\n\n {error && <p className=\"hanzo-waitlist__error\" role=\"alert\">{error}</p>}\n {result && (\n <p className=\"hanzo-waitlist__invite-result\" role=\"status\">\n Sent <strong>{result.sent}</strong>\n {result.skipped > 0 && <>, skipped {result.skipped} <small>(already on list)</small></>}\n {result.invalid > 0 && <>, {result.invalid} invalid</>}\n {result.duplicates > 0 && <>, {result.duplicates} duplicates</>}\n {result.pointsAwarded > 0 && <> · +{result.pointsAwarded} pts</>}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport type { WaitlistEntry } from './client'\nimport { WaitlistShare, type SharePlatformId, type ShareTarget } from './Share'\nimport { WaitlistInviteFriends } from './InviteFriends'\n\nexport interface WaitlistStatusProps {\n /** The entry to render. Server is the source of truth; this is just the view. */\n entry: WaitlistEntry\n /** Waitlist slug — needed for share + invite POSTs. */\n waitlist: string\n /** Base server URL. Defaults to current origin. */\n baseUrl?: string\n\n /** Override the \"You're on the list\" headline. */\n title?: string\n /** Override the subtitle line under the rank. */\n subtitle?: (entry: WaitlistEntry) => string\n\n /** Hide the share grid. */\n hideShare?: boolean\n /** Hide the invite-friends panel. */\n hideInvite?: boolean\n /** Hide the points score block. */\n hidePoints?: boolean\n /** Restrict / reorder share platforms. */\n shareTargets?: Array<SharePlatformId | ShareTarget>\n\n /**\n * Called whenever the user earns points locally (share click, invite send)\n * so consumers can keep external caches in sync. Receives the updated entry.\n */\n onEntryChange?: (next: WaitlistEntry) => void\n}\n\nconst defaultSubtitle = (e: WaitlistEntry) =>\n e.aheadOf && e.aheadOf > 0\n ? `${e.aheadOf.toLocaleString()} ${e.aheadOf === 1 ? 'person is' : 'people are'} behind you. Refer friends to climb.`\n : 'Refer friends to climb the list.'\n\n/**\n * Presentational gamified post-join view: rank, points breakdown, share grid,\n * invite panel. State-light by design — pass it an entry, render the entry,\n * notify the caller on local point gains. No network on mount, no localStorage.\n */\nexport function WaitlistStatus(props: WaitlistStatusProps) {\n const {\n entry, waitlist, baseUrl,\n title = \"You're on the list\",\n subtitle = defaultSubtitle,\n hideShare, hideInvite, hidePoints, shareTargets,\n onEntryChange,\n } = props\n\n // Local mirror so we can optimistically reflect share/invite point gains\n // even when the caller doesn't pass onEntryChange. The server is still the\n // source of truth — caller can blow this away with a fresh entry whenever.\n const [local, setLocal] = useState<WaitlistEntry>(entry)\n // Reset local to upstream whenever a new entry is passed.\n if (entry !== local && entry.email === local.email && entry.points !== local.points) {\n setLocal(entry)\n }\n\n const view = entry === local || entry.points >= local.points ? entry : local\n\n const shareUrl = useMemo(() => {\n if (typeof window === 'undefined') return view.shareUrl\n const u = new URL(window.location.href)\n u.search = ''\n u.searchParams.set('ref', view.refCode)\n return u.toString()\n }, [view.refCode, view.shareUrl])\n\n const bump = useCallback((points: number, breakdown: WaitlistEntry['pointBreakdown']) => {\n const next = { ...view, points, pointBreakdown: breakdown }\n setLocal(next)\n onEntryChange?.(next)\n }, [onEntryChange, view])\n\n const pb = view.pointBreakdown\n const pv = view.pointValues\n\n return (\n <div className=\"hanzo-waitlist__success\">\n <h3 className=\"hanzo-waitlist__title\" style={{ textAlign: 'center' }}>{title}</h3>\n <div className=\"hanzo-waitlist__rank\" aria-label={`Rank ${view.rank} of ${view.total}`}>\n {view.rank.toLocaleString()}\n </div>\n <p className=\"hanzo-waitlist__of\" aria-hidden=\"true\">of {view.total.toLocaleString()}</p>\n <p className=\"hanzo-waitlist__meta\">{subtitle(view)}</p>\n\n {!hidePoints && (\n <div className=\"hanzo-waitlist__score\" aria-label={`${view.points} points`}>\n <div className=\"hanzo-waitlist__score-num\">\n {view.points.toLocaleString()}\n <span className=\"hanzo-waitlist__score-suffix\">pts</span>\n </div>\n <ul className=\"hanzo-waitlist__score-breakdown\" role=\"list\">\n <li><b>{pb.referrals}</b> referrals <small>×{pv.REFERRAL}</small></li>\n <li><b>{pb.shares}</b> shares <small>×{pv.SHARE}</small></li>\n <li><b>{pb.invitesSent}</b> invites <small>×{pv.INVITE_SENT}</small></li>\n <li><b>{pb.invitesConverted}</b> joined <small>×{pv.INVITE_CONVERTED}</small></li>\n </ul>\n </div>\n )}\n\n {!hideShare && (\n <WaitlistShare\n waitlist={waitlist}\n refCode={view.refCode}\n shareUrl={shareUrl}\n rank={view.rank}\n total={view.total}\n baseUrl={baseUrl}\n shareTargets={shareTargets}\n pointValues={view.pointValues}\n onShared={(_platform, awarded) => {\n if (awarded > 0) bump(view.points + awarded, { ...pb, shares: pb.shares + awarded })\n }}\n />\n )}\n\n {!hideInvite && (\n <WaitlistInviteFriends\n waitlist={waitlist}\n refCode={view.refCode}\n baseUrl={baseUrl}\n pointPerInvite={pv.INVITE_SENT}\n pointPerConversion={pv.INVITE_CONVERTED}\n onSent={(r) => bump(view.points + r.pointsAwarded, { ...pb, invitesSent: pb.invitesSent + r.pointsAwarded })}\n />\n )}\n </div>\n )\n}\n","// Top-level convenience component composing the join flow.\n//\n// Composition layout — each piece is independently usable, see ./Join,\n// ./Status, ./Share, ./InviteFriends:\n//\n// <Waitlist>\n// <Card>\n// {entry ? <WaitlistStatus/> : <WaitlistJoin/>}\n// </Card>\n//\n// State management is delegated to storage.usePersistedEntry — the same\n// hook the host page uses to drive its sticky CTA. One source of truth.\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { WaitlistClient, type WaitlistEntry } from './client'\nimport { WaitlistJoin, type WaitlistJoinProps } from './Join'\nimport { WaitlistStatus } from './Status'\nimport { captureReferrerFromUrl, usePersistedEntry, writePersistedEntry } from './storage'\nimport type { SharePlatformId, ShareTarget } from './Share'\n\nexport type WaitlistMode = 'inline' | 'modal'\nexport type WaitlistTheme = 'auto' | 'light' | 'dark'\n\nexport interface WaitlistProps {\n /** Slug or id of the waitlist on the Base server. */\n waitlist: string\n /** Where the Base server lives. Defaults to current origin. */\n baseUrl?: string\n /** Layout: `inline` renders the form in place, `modal` renders a button that opens it. */\n mode?: WaitlistMode\n /** Light / dark / `auto` (follow OS). */\n theme?: WaitlistTheme\n /** Consumer-provided logo (rendered above the title in both Join and Status). */\n logo?: React.ReactNode\n\n /** Join form copy + Turnstile token. */\n title?: WaitlistJoinProps['title']\n subtitle?: WaitlistJoinProps['subtitle']\n submitLabel?: WaitlistJoinProps['submitLabel']\n turnstileToken?: WaitlistJoinProps['turnstileToken']\n\n /** Status view copy. */\n successTitle?: string\n successSubtitle?: (entry: WaitlistEntry) => string\n\n /** Optional CTA before user submits (modal mode). */\n triggerLabel?: string\n\n /** Toggle pieces of the status view. */\n hideShare?: boolean\n hideInvite?: boolean\n hidePoints?: boolean\n shareTargets?: Array<SharePlatformId | ShareTarget>\n\n /** Forward to root container. */\n className?: string\n style?: React.CSSProperties\n\n /** Callbacks. */\n onSuccess?: (entry: WaitlistEntry) => void\n onError?: WaitlistJoinProps['onError']\n}\n\nexport function Waitlist(props: WaitlistProps) {\n const {\n waitlist, baseUrl,\n mode = 'inline',\n theme = 'auto',\n logo,\n title, subtitle, submitLabel, turnstileToken,\n successTitle, successSubtitle,\n triggerLabel = 'Join waitlist',\n hideShare, hideInvite, hidePoints, shareTargets,\n className, style,\n onSuccess, onError,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const cached = usePersistedEntry(waitlist)\n const [entry, setEntry] = useState<WaitlistEntry | null>(null)\n const [modalOpen, setModalOpen] = useState(false)\n\n // On mount: capture inbound ?ref= URL and rehydrate the cached entry.\n useEffect(() => { captureReferrerFromUrl() }, [])\n\n useEffect(() => {\n if (!cached?.email) { setEntry(null); return }\n let cancelled = false\n client.status({ waitlist, email: cached.email }).then((res) => {\n if (cancelled) return\n if ('ok' in res && res.ok) setEntry(res)\n })\n return () => { cancelled = true }\n }, [cached?.email, client, waitlist])\n\n const handleSuccess = useCallback((next: WaitlistEntry) => {\n writePersistedEntry(waitlist, { email: next.email, rank: next.rank, refCode: next.refCode })\n setEntry(next)\n onSuccess?.(next)\n }, [onSuccess, waitlist])\n\n const card = (\n <Card theme={theme} className={className} style={style}>\n {logo && <div className=\"hanzo-waitlist__logo\">{logo}</div>}\n {entry ? (\n <WaitlistStatus\n entry={entry}\n waitlist={waitlist}\n baseUrl={baseUrl}\n title={successTitle}\n subtitle={successSubtitle}\n hideShare={hideShare}\n hideInvite={hideInvite}\n hidePoints={hidePoints}\n shareTargets={shareTargets}\n onEntryChange={setEntry}\n />\n ) : (\n <WaitlistJoin\n waitlist={waitlist}\n baseUrl={baseUrl}\n title={title}\n subtitle={subtitle}\n submitLabel={submitLabel}\n turnstileToken={turnstileToken}\n onSuccess={handleSuccess}\n onError={onError}\n />\n )}\n </Card>\n )\n\n if (mode === 'inline') return card\n\n return (\n <>\n <button\n type=\"button\"\n className=\"hanzo-waitlist__trigger\"\n onClick={() => setModalOpen(true)}\n >\n {entry ? `#${entry.rank.toLocaleString()} — view` : triggerLabel}\n </button>\n {modalOpen && (\n <div\n className=\"hanzo-waitlist__backdrop\"\n role=\"dialog\"\n aria-modal=\"true\"\n onClick={(e) => { if (e.target === e.currentTarget) setModalOpen(false) }}\n >\n <div className=\"hanzo-waitlist__dialog\">{card}</div>\n </div>\n )}\n </>\n )\n}\n\nfunction Card(p: { theme: WaitlistTheme; className?: string; style?: React.CSSProperties; children: React.ReactNode }) {\n const themeAttr = p.theme === 'auto' ? undefined : p.theme\n const className = ['hanzo-waitlist', p.className].filter(Boolean).join(' ')\n return (\n <div className={className} data-theme={themeAttr} style={p.style}>\n <div className=\"hanzo-waitlist__card\">{p.children}</div>\n </div>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\n\nexport interface UseCountUpOptions {\n /** Animation duration in ms. Default 1200. Set 0 to disable. */\n duration?: number\n /** Easing function. Default cubic ease-out. */\n ease?: (t: number) => number\n /** Re-trigger on `target` changes. Default true. */\n retrigger?: boolean\n}\n\nconst easeOutCubic = (t: number) => 1 - Math.pow(1 - t, 3)\n\n/**\n * Smoothly animates from 0 (or the previous value) up to `target`. Honors\n * `prefers-reduced-motion` and a `duration: 0` opt-out.\n */\nexport function useCountUp(target: number | null, opts: UseCountUpOptions = {}): number {\n const {\n duration = 1200,\n ease = easeOutCubic,\n retrigger = true,\n } = opts\n\n const [value, setValue] = useState(0)\n const raf = useRef<number | null>(null)\n const prev = useRef(0)\n\n useEffect(() => {\n if (target === null || target === undefined) return\n if (duration <= 0) { setValue(target); prev.current = target; return }\n\n const reduce = typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n if (reduce) { setValue(target); prev.current = target; return }\n\n const from = retrigger ? prev.current : value\n const to = target\n if (from === to) return\n\n const start = performance.now()\n const step = (now: number) => {\n const t = Math.min(1, (now - start) / duration)\n const v = from + (to - from) * ease(t)\n setValue(Math.round(v))\n if (t < 1) raf.current = requestAnimationFrame(step)\n else { prev.current = to; raf.current = null }\n }\n raf.current = requestAnimationFrame(step)\n return () => { if (raf.current) cancelAnimationFrame(raf.current) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [target, duration])\n\n return value\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport { WaitlistClient, type LeaderboardEntry } from './client'\nimport { useCountUp } from './useCountUp'\n\nexport type LeaderboardMode = 'load-more' | 'paginate'\n\nexport interface WaitlistLeaderboardProps {\n /** Slug or id of the waitlist. */\n waitlist: string\n /** Base server URL. Defaults to current origin. */\n baseUrl?: string\n /** Entries per page. Default 25. */\n pageSize?: number\n /** Theme override ('auto' | 'light' | 'dark'). */\n theme?: 'auto' | 'light' | 'dark'\n /**\n * Highlight the row matching this email (typically the current viewer).\n * The widget's `Waitlist` component stores the joined email in\n * localStorage under `hanzo-waitlist:<slug>` — read it there to wire up.\n */\n highlightEmail?: string\n /**\n * `'load-more'` (default) — single button at the bottom that appends the\n * next chunk; no page counters or arrows.\n * `'paginate'` — classic next/prev with a page count.\n */\n mode?: LeaderboardMode\n /** Override the load-more button text. */\n loadMoreLabel?: string\n /** Text shown after the last page in load-more mode. Set to '' to hide. */\n exhaustedLabel?: string\n /**\n * Animated count-up on the total (\"1,205 on the list\"). Pass `false`\n * to disable, or an object to tune the duration. Default true / 1200ms.\n */\n animateTotal?: boolean | { duration?: number }\n /** Optional className on the root container. */\n className?: string\n style?: React.CSSProperties\n /**\n * Custom renderer for the \"email\" cell. Default shows the masked email.\n * Use this to render avatars, social links, etc.\n */\n renderEmail?: (entry: LeaderboardEntry) => React.ReactNode\n}\n\n/**\n * Paginated leaderboard view of a waitlist. The widget itself stays per-user\n * (Join + your-rank); this is the public list view. Same monochrome surface,\n * same CSS variables, same brand-neutral design — drop in next to <Waitlist>.\n */\nexport function WaitlistLeaderboard(props: WaitlistLeaderboardProps) {\n const {\n waitlist,\n baseUrl,\n pageSize = 25,\n theme = 'auto',\n highlightEmail,\n mode = 'load-more',\n loadMoreLabel = 'Show more',\n exhaustedLabel = \"That's everyone\",\n animateTotal = true,\n className,\n style,\n renderEmail,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const [page, setPage] = useState(1)\n const [entries, setEntries] = useState<LeaderboardEntry[]>([])\n const [meta, setMeta] = useState<{ total: number; totalPages: number } | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n\n // For load-more, accumulate; for paginate, replace.\n const load = useCallback(async (p: number, append: boolean) => {\n setBusy(true)\n setError(null)\n const res = await client.list({ waitlist, page: p, pageSize })\n if ('ok' in res && res.ok) {\n setMeta({ total: res.total, totalPages: res.totalPages })\n setEntries((prev) => {\n if (!append) return res.entries\n // Dedup by rank in case of overlapping fetches.\n const seen = new Set(prev.map((e) => e.rank))\n const fresh = res.entries.filter((e) => !seen.has(e.rank))\n return [...prev, ...fresh]\n })\n } else {\n setError(res.message || 'failed to load')\n }\n setBusy(false)\n }, [client, pageSize, waitlist])\n\n // Initial load and whenever waitlist/pageSize change.\n useEffect(() => {\n setPage(1)\n setEntries([])\n load(1, false)\n }, [load])\n\n const total = meta?.total ?? 0\n const animDuration = animateTotal === false ? 0 : (typeof animateTotal === 'object' ? animateTotal.duration ?? 1200 : 1200)\n const animatedTotal = useCountUp(meta ? total : null, { duration: animDuration })\n const displayedTotal = animateTotal === false ? total : animatedTotal\n const isPaginate = mode === 'paginate'\n const isLastPage = meta ? page >= meta.totalPages : false\n const isExhausted = mode === 'load-more' && meta && entries.length >= meta.total\n\n const onLoadMore = useCallback(() => {\n if (busy) return\n const next = page + 1\n setPage(next)\n load(next, true)\n }, [busy, load, page])\n\n const themeAttr = theme === 'auto' ? undefined : theme\n\n return (\n <div className={['hanzo-waitlist', className].filter(Boolean).join(' ')} data-theme={themeAttr} style={style}>\n <div className=\"hanzo-waitlist__card hanzo-waitlist-lb\">\n <header className=\"hanzo-waitlist-lb__head\">\n <div>\n <h3 className=\"hanzo-waitlist__title\">Leaderboard</h3>\n <p className=\"hanzo-waitlist__subtitle\">\n <span className=\"hanzo-waitlist-lb__total\">{displayedTotal.toLocaleString()}</span> on the list\n </p>\n </div>\n {isPaginate && (\n <Pager\n page={page}\n totalPages={meta?.totalPages ?? 1}\n busy={busy}\n onChange={(p) => { setPage(p); load(p, false) }}\n />\n )}\n </header>\n\n {error && <p className=\"hanzo-waitlist__error\" role=\"alert\">{error}</p>}\n\n <ol className=\"hanzo-waitlist-lb__list\">\n {entries.map((e) => {\n const mine = highlightEmail && e.email.toLowerCase() === highlightEmail.toLowerCase()\n return (\n <li\n key={`${e.rank}-${e.email}`}\n className=\"hanzo-waitlist-lb__row\"\n data-mine={mine ? 'true' : undefined}\n >\n <span className=\"hanzo-waitlist-lb__rank\">#{e.rank.toLocaleString()}</span>\n <span className=\"hanzo-waitlist-lb__email\">\n {renderEmail ? renderEmail(e) : e.email}\n </span>\n <span className=\"hanzo-waitlist-lb__refs\" aria-label={`${e.referralCount} referrals`}>\n {e.referralCount.toLocaleString()}\n </span>\n </li>\n )\n })}\n {!error && entries.length === 0 && (\n <li className=\"hanzo-waitlist-lb__empty\">\n {busy ? 'Loading…' : 'No one yet — be the first.'}\n </li>\n )}\n </ol>\n\n {!isPaginate && meta && !isExhausted && (\n <footer className=\"hanzo-waitlist-lb__foot\">\n <button\n type=\"button\"\n className=\"hanzo-waitlist__button hanzo-waitlist__button--ghost hanzo-waitlist-lb__more\"\n onClick={onLoadMore}\n disabled={busy}\n >\n {busy ? 'Loading…' : loadMoreLabel}\n </button>\n </footer>\n )}\n {!isPaginate && isExhausted && exhaustedLabel && (\n <footer className=\"hanzo-waitlist-lb__foot\">\n <span className=\"hanzo-waitlist-lb__exhausted\">{exhaustedLabel}</span>\n </footer>\n )}\n {isPaginate && (meta?.totalPages ?? 1) > 1 && (\n <footer className=\"hanzo-waitlist-lb__foot\">\n <Pager\n page={page}\n totalPages={meta?.totalPages ?? 1}\n busy={busy}\n onChange={(p) => { setPage(p); load(p, false) }}\n />\n </footer>\n )}\n {!isPaginate && isLastPage && false /* suppress noop */}\n </div>\n </div>\n )\n}\n\nfunction Pager(p: { page: number; totalPages: number; busy: boolean; onChange: (n: number) => void }) {\n const prev = () => p.onChange(Math.max(1, p.page - 1))\n const next = () => p.onChange(Math.min(p.totalPages, p.page + 1))\n return (\n <div className=\"hanzo-waitlist-lb__pager\">\n <button\n type=\"button\"\n className=\"hanzo-waitlist__button hanzo-waitlist__button--ghost\"\n onClick={prev}\n disabled={p.busy || p.page <= 1}\n aria-label=\"Previous page\"\n >←</button>\n <span className=\"hanzo-waitlist-lb__pageinfo\">\n {p.page.toLocaleString()} / {p.totalPages.toLocaleString()}\n </span>\n <button\n type=\"button\"\n className=\"hanzo-waitlist__button hanzo-waitlist__button--ghost\"\n onClick={next}\n disabled={p.busy || p.page >= p.totalPages}\n aria-label=\"Next page\"\n >→</button>\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n WaitlistClient,\n type ActivityEvent,\n type ActivityType,\n} from './client'\n\nexport type ActivityFormatter = (evt: ActivityEvent, ctx: { relative: string }) => React.ReactNode\n\nexport interface WaitlistActivityProps {\n /** Slug or id of the waitlist. */\n waitlist: string\n /** Base server URL. */\n baseUrl?: string\n /** Items to show. Default 8. */\n limit?: number\n /** Restrict to specific event types. Default: all. */\n types?: ActivityType[]\n /** Poll interval in ms. 0 = no polling (one-shot). Default 12000. */\n pollInterval?: number\n /** Theme override. */\n theme?: 'auto' | 'light' | 'dark'\n /** Override each row's content. Receives event + computed relative time. */\n formatEvent?: ActivityFormatter\n /** Custom relative-time formatter. */\n formatRelative?: (deltaMs: number) => string\n /** Show heading. Default true. */\n showHeading?: boolean\n /** Heading text. Default \"Recent activity\". */\n heading?: string\n /** Empty-state message. */\n emptyLabel?: string\n className?: string\n style?: React.CSSProperties\n}\n\nfunction defaultRelative(deltaMs: number): string {\n const s = Math.max(0, Math.floor(deltaMs / 1000))\n if (s < 30) return 'just now'\n if (s < 60) return `${s}s ago`\n const m = Math.floor(s / 60)\n if (m < 60) return `${m}m ago`\n const h = Math.floor(m / 60)\n if (h < 24) return `${h}h ago`\n const d = Math.floor(h / 24)\n if (d < 7) return `${d}d ago`\n const w = Math.floor(d / 7)\n return `${w}w ago`\n}\n\nfunction platformLabel(p?: string): string {\n if (!p) return 'somewhere'\n const m: Record<string, string> = {\n x: 'X', twitter: 'X',\n linkedin: 'LinkedIn',\n facebook: 'Facebook',\n reddit: 'Reddit',\n telegram: 'Telegram',\n whatsapp: 'WhatsApp',\n email: 'email',\n sms: 'SMS',\n copy: 'link',\n webshare: 'a friend',\n mastodon: 'Mastodon',\n bluesky: 'Bluesky',\n threads: 'Threads',\n }\n return m[p.toLowerCase()] ?? p\n}\n\nfunction defaultFormat(evt: ActivityEvent): React.ReactNode {\n switch (evt.type) {\n case 'join':\n return <><b>{evt.who}</b> joined{evt.source === 'referral' ? ' (referred)' : ''}</>\n case 'share': {\n const p = evt.platform?.toLowerCase()\n if (p === 'copy') return <><b>{evt.who}</b> copied their link</>\n if (p === 'webshare') return <><b>{evt.who}</b> shared via system</>\n if (p === 'email') return <><b>{evt.who}</b> shared by email</>\n if (p === 'sms') return <><b>{evt.who}</b> texted their link</>\n return <><b>{evt.who}</b> shared on {platformLabel(evt.platform)}</>\n }\n case 'invite':\n return <><b>{evt.who}</b> invited a friend</>\n case 'referral':\n return <><b>{evt.who}</b> earned a referral</>\n }\n}\n\nexport function WaitlistActivity(props: WaitlistActivityProps) {\n const {\n waitlist, baseUrl,\n limit = 8,\n types,\n pollInterval = 12000,\n theme = 'auto',\n formatEvent,\n formatRelative,\n showHeading = true,\n heading = 'Recent activity',\n emptyLabel = 'Quiet for now.',\n className, style,\n } = props\n\n const client = useMemo(() => new WaitlistClient({ baseUrl }), [baseUrl])\n const [events, setEvents] = useState<ActivityEvent[]>([])\n const [serverNow, setServerNow] = useState<number | null>(null)\n const [, force] = useState(0)\n const mounted = useRef(true)\n\n // Initial + polling fetch.\n useEffect(() => {\n mounted.current = true\n const fetchOnce = async () => {\n const r = await client.activity({ waitlist, limit, types })\n if (!mounted.current) return\n if ('ok' in r && r.ok) {\n setEvents(r.entries)\n setServerNow(r.now)\n }\n }\n fetchOnce()\n if (pollInterval <= 0) return undefined\n const id = window.setInterval(fetchOnce, pollInterval)\n return () => {\n mounted.current = false\n window.clearInterval(id)\n }\n }, [client, waitlist, limit, pollInterval, types])\n\n // Tick relative times even between polls so \"just now\" → \"10s ago\".\n useEffect(() => {\n const id = window.setInterval(() => force((n) => n + 1), 10000)\n return () => window.clearInterval(id)\n }, [])\n\n const themeAttr = theme === 'auto' ? undefined : theme\n\n const rel = useCallback((ts: number) => {\n const fmt = formatRelative ?? defaultRelative\n // Use server-now if we have it; the wall-clock drift is handled by\n // the difference computation.\n const base = serverNow ?? Date.now()\n const wallDrift = Date.now() - (serverNow ?? Date.now())\n return fmt(base - ts + wallDrift)\n }, [formatRelative, serverNow])\n\n return (\n <div className={['hanzo-waitlist', className].filter(Boolean).join(' ')} data-theme={themeAttr} style={style}>\n <div className=\"hanzo-waitlist__card hanzo-waitlist-act\">\n {showHeading && (\n <header className=\"hanzo-waitlist-act__head\">\n <h3 className=\"hanzo-waitlist__title\">{heading}</h3>\n <span className=\"hanzo-waitlist-act__pulse\" aria-hidden=\"true\" />\n </header>\n )}\n {events.length === 0 ? (\n <p className=\"hanzo-waitlist__hint\" style={{ textAlign: 'left' }}>{emptyLabel}</p>\n ) : (\n <ul className=\"hanzo-waitlist-act__list\" role=\"list\">\n {events.map((e, i) => {\n const relative = rel(e.ts)\n return (\n <li key={`${e.ts}-${i}`} className=\"hanzo-waitlist-act__row\">\n <span className={`hanzo-waitlist-act__dot hanzo-waitlist-act__dot--${e.type}`} aria-hidden=\"true\" />\n <span className=\"hanzo-waitlist-act__text\">\n {formatEvent ? formatEvent(e, { relative }) : defaultFormat(e)}\n </span>\n <time className=\"hanzo-waitlist-act__time\" dateTime={new Date(e.ts).toISOString()}>\n {relative}\n </time>\n </li>\n )\n })}\n </ul>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"} |