@appfunnel-dev/sdk 2.0.0-canary.0 → 2.0.0-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/state/variableStore.ts","../src/state/store.ts","../src/state/context.ts","../src/tracking/tracking.ts","../src/tracking/bus.ts","../src/i18n/translation.ts","../src/commerce/catalog.ts","../src/flow/spine.ts","../src/flow/experiments.ts","../src/flow/flow.tsx","../src/modals/registry.tsx","../src/modals/sheet.tsx","../src/commerce/checkout.tsx","../src/toast/toast.tsx","../src/state/namespaces.ts","../src/flow/components.tsx","../src/tracking/catalog.ts","../src/embed/script.tsx","../src/manifest/manifest.ts"],"names":["base","createContext","createElement","useContext","useCallback","useState","useMemo","lazy","page","useRef","useEffect","Suspense","useReducer","createPortal","isValidElement","cloneElement","Toaster","Fragment","useSyncExternalStore"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { VariableValue } from '../types'\n\n/**\n * External variable store for funnel variables — the flat, reactive key/value\n * store under the v2 namespaces. Components subscribe selectively via\n * `useSyncExternalStore`, so only components depending on changed keys re-render.\n * (Seeding lives in {@link ./store}.`createFunnelStore`.)\n */\ninterface ScopedListener {\n listener: () => void\n /** Exact keys to watch, or null for all changes */\n keys: string[] | null\n /** Prefix to watch (e.g. 'answers.'), or null for all */\n prefix: string | null\n}\n\nexport class VariableStore {\n private state: Record<string, VariableValue>\n private listeners = new Set<ScopedListener>()\n /** Tracks which keys changed in the last mutation — used by scoped notify */\n private changedKeys: string[] = []\n\n constructor(initial: Record<string, VariableValue>) {\n this.state = { ...initial }\n }\n\n getState(): Record<string, VariableValue> {\n return this.state\n }\n\n get(key: string): VariableValue {\n return this.state[key]\n }\n\n set(key: string, value: VariableValue): void {\n if (this.state[key] === value) return\n this.state = { ...this.state, [key]: value }\n this.changedKeys = [key]\n this.notify()\n }\n\n setState(updater: (prev: Record<string, VariableValue>) => Record<string, VariableValue>): void {\n const prev = this.state\n const next = updater(prev)\n if (next === prev) return\n this.state = next\n // Compute changed keys\n this.changedKeys = []\n for (const key of Object.keys(next)) {\n if (next[key] !== prev[key]) this.changedKeys.push(key)\n }\n for (const key of Object.keys(prev)) {\n if (!(key in next) && prev[key] !== undefined) this.changedKeys.push(key)\n }\n this.notify()\n }\n\n /** Batch set multiple variables at once */\n setMany(updates: Record<string, VariableValue>): void {\n const changed: string[] = []\n const next = { ...this.state }\n for (const [key, value] of Object.entries(updates)) {\n if (next[key] !== value) {\n next[key] = value\n changed.push(key)\n }\n }\n if (changed.length === 0) return\n this.state = next\n this.changedKeys = changed\n this.notify()\n }\n\n /**\n * Subscribe to store changes.\n *\n * @param listener - callback fired when relevant keys change\n * @param scope - optional scope to limit notifications:\n * - `{ keys: ['data.x', 'user.email'] }` — only fire when these exact keys change\n * - `{ prefix: 'answers.' }` — only fire when any key starting with this prefix changes\n * - omit or `{}` — fire on every change (global listener)\n */\n subscribe(\n listener: () => void,\n scope?: { keys?: string[]; prefix?: string },\n ): () => void {\n const entry: ScopedListener = {\n listener,\n keys: scope?.keys || null,\n prefix: scope?.prefix || null,\n }\n this.listeners.add(entry)\n return () => this.listeners.delete(entry)\n }\n\n private notify(): void {\n const changed = this.changedKeys\n for (const entry of this.listeners) {\n // Global listener — no scope\n if (!entry.keys && !entry.prefix) {\n entry.listener()\n continue\n }\n // Key-scoped listener\n if (entry.keys) {\n if (changed.some((k) => entry.keys!.includes(k))) {\n entry.listener()\n }\n continue\n }\n // Prefix-scoped listener\n if (entry.prefix) {\n if (changed.some((k) => k.startsWith(entry.prefix!))) {\n entry.listener()\n }\n }\n }\n }\n}\n","/**\n * v2 store seeding — builds a {@link VariableStore} holding only the **writable**\n * namespaces (`user` / `responses` / `data`), each persisted to the backend.\n *\n * Seeds the {@link VariableStore} with v2 prefixes (no legacy `answers.`/`query.`\n * aliasing). Read-only computed values do NOT live\n * here — see {@link ./context}. Three deliberate namespaces:\n *\n * - `user.*` persistent identity attributes (cross-session)\n * - `responses.*` the clean, aggregated funnel answers\n * - `data.*` working/scratch state — persisted (so reload + return survive)\n * but kept separate from responses so analytics aggregates only\n * real answers and `data` can hold intermediate garbage\n */\n\nimport type { VariableValue, VariableConfig } from '../types'\nimport { VariableStore } from './variableStore'\n\n/** v2 namespace → store-key prefix (sans trailing dot). 1:1, no legacy aliasing. */\nexport const NAMESPACE_PREFIX = {\n user: 'user',\n responses: 'responses',\n data: 'data',\n} as const\n\nexport type WritableNamespace = keyof typeof NAMESPACE_PREFIX\n\n/** Built-in user attributes — always present so reads never `undefined`. */\nconst BUILTIN_USER: Record<string, VariableValue> = {\n 'user.email': '',\n 'user.name': '',\n}\n\nexport interface FunnelStoreConfig {\n responses?: Record<string, VariableConfig>\n data?: Record<string, VariableConfig>\n}\n\nfunction defaultFor(type: string): VariableValue {\n switch (type) {\n case 'string': return ''\n case 'number': return 0\n case 'boolean': return false\n case 'stringArray': return []\n default: return ''\n }\n}\n\n/**\n * Seed a store from a funnel's declared `responses`/`data` defaults, then layer\n * server / session-restored values on top (highest priority).\n */\nexport function createFunnelStore(\n config: FunnelStoreConfig = {},\n sessionValues?: Record<string, VariableValue>,\n): VariableStore {\n const initial: Record<string, VariableValue> = { ...BUILTIN_USER }\n\n for (const [key, cfg] of Object.entries(config.responses ?? {})) {\n initial[`responses.${key}`] = cfg.default ?? defaultFor(cfg.type)\n }\n for (const [key, cfg] of Object.entries(config.data ?? {})) {\n initial[`data.${key}`] = cfg.default ?? defaultFor(cfg.type)\n }\n\n if (sessionValues) {\n for (const [key, value] of Object.entries(sessionValues)) {\n if (value !== undefined) initial[key] = value\n }\n }\n\n return new VariableStore(initial)\n}\n","/**\n * v2 `context` — the **read-only, computed** namespace.\n *\n * Everything the funnel can *read* but never *write*: the device, the visitor's\n * locale, the current page, acquisition params (UTM), the session, and system\n * facts (funnel id, test/live mode, clock). It supersedes the v0 flat\n * `page.*`/`device.*`/`browser.*`/`os.*`/`query.*`/`metadata.*` system variables\n * (see {@link ./systemVariables}) by folding them into one nested object.\n *\n * Why it's *not* in the {@link ./variableStore}: the store holds **writable**\n * state (`user`/`responses`/`data`) that persists + re-renders per key. Context\n * is derived and read-only, so it lives as a plain object on a React context —\n * no subscriptions, no churn. The one moving part (`page`) is merged into the\n * snapshot from navigation state at read time.\n *\n * Authors read it through hooks (`useDevice()`, `useLocale()`, `usePage()`,\n * `useUtm()`) or inside routing/condition predicates as `s.context.*`.\n */\n\n// ── Shape ────────────────────────────────────────────────\n\nexport interface DeviceContext {\n type: 'mobile' | 'tablet' | 'desktop'\n isMobile: boolean\n isTablet: boolean\n screenWidth: number\n screenHeight: number\n viewportWidth: number\n viewportHeight: number\n colorDepth: number\n pixelRatio: number\n}\n\nexport interface BrowserContext {\n name: string\n version: string\n userAgent: string\n language: string\n cookieEnabled: boolean\n online: boolean\n}\n\nexport interface OsContext {\n name: string\n timezone: string\n}\n\nexport interface LocaleContext {\n /** Full locale, e.g. `en-US`. */\n locale: string\n /** Language subtag, e.g. `en`. */\n language: string\n /** Region subtag, e.g. `US` (may be empty). */\n region: string\n /** IANA timezone, e.g. `America/New_York`. */\n timeZone: string\n}\n\nexport interface PageContext {\n /** Current page key. */\n key: string\n /** Current page URL slug (`meta.slug`, defaults to the key) — what the renderer puts in the path. */\n slug: string\n /** 0-based position in the visited history. */\n index: number\n /** Total pages in the (expected) flow. */\n total: number\n /** 0–100. */\n progressPercentage: number\n /** Epoch ms the current page was entered. */\n startedAt: number\n}\n\n/** Acquisition / ad params captured on entry (the old `query.*` utm slice). */\nexport interface UtmContext {\n source?: string\n medium?: string\n campaign?: string\n content?: string\n term?: string\n [key: string]: string | undefined\n}\n\n/**\n * Per-network ad **click-ids** captured from the entry URL — the matching signals\n * the server CAPI needs. Named per network (not a generic bag) so the platform +\n * each integration map them precisely; `[key]` catches any others.\n */\nexport interface ClickIdContext {\n /** Meta / Facebook */\n fbclid?: string\n /** Google Ads (+ gbraid/wbraid for app↔web) */\n gclid?: string\n gbraid?: string\n wbraid?: string\n /** Microsoft / Bing */\n msclkid?: string\n /** TikTok */\n ttclid?: string\n /** Twitter / X */\n twclid?: string\n /** Snapchat */\n sccid?: string\n /** LinkedIn */\n li_fat_id?: string\n /** Pinterest */\n epik?: string\n /** Reddit */\n rdt_cid?: string\n [key: string]: string | undefined\n}\n\n/**\n * The full acquisition snapshot captured once on entry — the funnel reads `utm` /\n * `clickIds` off {@link FunnelContext}; the SDK forwards this whole thing to the\n * tracker (`setAcquisition`) so the platform persists it **first-class**: per-visit\n * on the session + **first-touch (write-once) on the Customer**, and the click-ids /\n * `_fbp`/`_fbc` cookies feed CAPI. Not stored as a generic attribute/answer.\n */\nexport interface Acquisition {\n utm: UtmContext\n clickIds: ClickIdContext\n /** CAPI cookies (`_fbp`/`_fbc`) read from `document.cookie` (not funnel-readable). */\n cookies: { fbp?: string; fbc?: string }\n /** `document.referrer` at entry. */\n referrer: string\n /** Entry URL path (the landing page). */\n landingPath: string\n}\n\nexport interface SessionContext {\n /** Server session id; null until resolved. */\n id: string | null\n /** Epoch ms the session began. */\n startedAt: number\n /** `document.referrer` at entry. */\n referrer: string\n}\n\n/**\n * Durable identity for **stable experiment bucketing** (phase-4 §4.2). The\n * preferred seed is `customerId` once known; before identification it's the\n * signed anonymous `visitorId` (P1). It is deliberately **not** the session id or\n * fingerprint — a returning visitor (e.g. via winback) must keep their variant\n * across sessions/devices (landmine #4). Both null = unidentifiable traffic, and\n * the experiment layer falls back to control rather than bucket on nothing.\n */\nexport interface IdentityContext {\n /** Known customer id (post-identification). The preferred bucketing seed. */\n customerId: string | null\n /** Signed anonymous visitor id. The fallback bucketing seed. */\n visitorId: string | null\n}\n\nexport interface SystemContext {\n funnelId: string\n campaignId: string\n /** Render mode — `test` for preview/QA, `live` for public traffic. */\n mode: 'test' | 'live'\n /** Epoch ms captured at build time (stable per render, not a live clock). */\n now: number\n}\n\n/** The whole read-only computed namespace, as read in predicates: `s.context.*`. */\nexport interface FunnelContext {\n device: DeviceContext\n browser: BrowserContext\n os: OsContext\n locale: LocaleContext\n page: PageContext\n utm: UtmContext\n /** Per-network ad click-ids captured on entry (funnel-readable; also forwarded for CAPI). */\n clickIds: ClickIdContext\n session: SessionContext\n identity: IdentityContext\n system: SystemContext\n}\n\n// ── Detection ────────────────────────────────────────────\n\ninterface RawBrowser {\n device: DeviceContext\n browser: BrowserContext\n os: OsContext\n locale: LocaleContext\n}\n\nlet cached: RawBrowser | null = null\n\nfunction extractVersion(ua: string, regex: RegExp): string {\n return ua.match(regex)?.[1] ?? '0'\n}\n\n/**\n * Sniff device/browser/os/locale from the environment, once. SSR-safe: returns\n * neutral defaults when `window` is absent. (Self-contained v2 detector — the v0\n * {@link ./systemVariables} equivalent emits flat store keys; this returns the\n * nested shape.)\n */\nfunction detect(): RawBrowser {\n if (cached) return cached\n\n if (typeof window === 'undefined') {\n cached = {\n device: {\n type: 'desktop', isMobile: false, isTablet: false,\n screenWidth: 0, screenHeight: 0, viewportWidth: 0, viewportHeight: 0,\n colorDepth: 24, pixelRatio: 1,\n },\n browser: {\n name: 'Unknown', version: '0', userAgent: 'unknown',\n language: 'en', cookieEnabled: true, online: true,\n },\n os: { name: 'Unknown', timezone: 'UTC' },\n locale: { locale: 'en', language: 'en', region: '', timeZone: 'UTC' },\n }\n return cached\n }\n\n const ua = navigator.userAgent\n const l = ua.toLowerCase()\n\n let name = 'Unknown'\n let version = '0'\n if (l.includes('firefox')) { name = 'Firefox'; version = extractVersion(ua, /Firefox\\/(\\d+[\\d.]*)/) }\n else if (l.includes('edg')) { name = 'Edge'; version = extractVersion(ua, /Edg\\/(\\d+[\\d.]*)/) }\n else if (l.includes('chrome') && !l.includes('edg')) { name = 'Chrome'; version = extractVersion(ua, /Chrome\\/(\\d+[\\d.]*)/) }\n else if (l.includes('safari') && !l.includes('chrome')) { name = 'Safari'; version = extractVersion(ua, /Version\\/(\\d+[\\d.]*)/) }\n\n let osName = 'Unknown'\n if (l.includes('win')) osName = 'Windows'\n else if (l.includes('mac')) osName = 'macOS'\n else if (l.includes('linux') && !l.includes('android')) osName = 'Linux'\n else if (l.includes('android')) osName = 'Android'\n else if (/iphone|ipad|ipod/.test(l)) osName = 'iOS'\n\n let type: DeviceContext['type'] = 'desktop'\n if (/mobile|android(?!.*tablet)|iphone|ipod/.test(l)) type = 'mobile'\n else if (/tablet|ipad/.test(l)) type = 'tablet'\n\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n const fullLocale = navigator.language || 'en'\n const [language = 'en', region = ''] = fullLocale.split('-')\n\n cached = {\n device: {\n type, isMobile: type === 'mobile', isTablet: type === 'tablet',\n screenWidth: window.screen?.width || 0,\n screenHeight: window.screen?.height || 0,\n viewportWidth: window.innerWidth || 0,\n viewportHeight: window.innerHeight || 0,\n colorDepth: window.screen?.colorDepth || 24,\n pixelRatio: window.devicePixelRatio || 1,\n },\n browser: {\n name, version, userAgent: ua,\n language: fullLocale,\n cookieEnabled: navigator.cookieEnabled ?? true,\n online: navigator.onLine ?? true,\n },\n os: { name: osName, timezone: timeZone },\n locale: { locale: fullLocale, language, region, timeZone },\n }\n return cached\n}\n\n/** Collect `utm_*` params (and any extras) from the URL. SSR-safe. */\nfunction collectUtm(): UtmContext {\n if (typeof window === 'undefined') return {}\n const out: UtmContext = {}\n const params = new URLSearchParams(window.location.search)\n params.forEach((value, key) => {\n if (key.startsWith('utm_')) out[key.slice(4)] = value\n })\n return out\n}\n\n/** Known ad-network click-id params. Any present in the URL is captured. */\nconst CLICK_ID_PARAMS = [\n 'fbclid', 'gclid', 'gbraid', 'wbraid', 'msclkid', 'ttclid',\n 'twclid', 'sccid', 'li_fat_id', 'epik', 'rdt_cid', 'dclid', 'irclickid',\n]\n\n/** Collect ad-network click-ids from the entry URL. SSR-safe. */\nfunction collectClickIds(): ClickIdContext {\n if (typeof window === 'undefined') return {}\n const out: ClickIdContext = {}\n const params = new URLSearchParams(window.location.search)\n for (const key of CLICK_ID_PARAMS) {\n const v = params.get(key)\n if (v) out[key] = v\n }\n return out\n}\n\n/** Read a cookie value by name. SSR-safe. */\nfunction readCookie(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined\n const m = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'))\n return m ? decodeURIComponent(m[1]) : undefined\n}\n\n/**\n * Assemble the full {@link Acquisition} snapshot from the context + `document`\n * (cookies, referrer, path) — captured once on entry, forwarded to the tracker for\n * first-class persistence (session + first-touch Customer) + CAPI.\n */\nexport function buildAcquisition(context: FunnelContext): Acquisition {\n return {\n utm: context.utm,\n clickIds: context.clickIds,\n cookies: { fbp: readCookie('_fbp'), fbc: readCookie('_fbc') },\n referrer: context.session.referrer,\n landingPath: typeof window !== 'undefined' ? window.location.pathname : '',\n }\n}\n\nexport interface BuildContextOptions {\n funnelId?: string\n campaignId?: string\n mode?: 'test' | 'live'\n /** Stable build-time clock (avoids `Date.now()` churn in renders/tests). */\n now?: number\n sessionId?: string | null\n /** Known customer id — the preferred stable bucketing seed (phase-4 §4.2). */\n customerId?: string | null\n /** Signed anonymous visitor id — the fallback bucketing seed. */\n visitorId?: string | null\n /** Overrides for any slice — used by the server to hydrate `utm`/`session`. */\n overrides?: Partial<FunnelContext>\n}\n\n/**\n * Build the read-only {@link FunnelContext} once, at mount. `page` starts at the\n * first page and is replaced per navigation when assembling a snapshot.\n */\nexport function buildContext(opts: BuildContextOptions = {}): FunnelContext {\n const raw = detect()\n const now = opts.now ?? 0\n const referrer = typeof document !== 'undefined' ? document.referrer : ''\n\n const base: FunnelContext = {\n device: raw.device,\n browser: raw.browser,\n os: raw.os,\n locale: raw.locale,\n utm: collectUtm(),\n clickIds: collectClickIds(),\n page: { key: '', slug: '', index: 0, total: 0, progressPercentage: 0, startedAt: now },\n session: { id: opts.sessionId ?? null, startedAt: now, referrer },\n identity: { customerId: opts.customerId ?? null, visitorId: opts.visitorId ?? null },\n system: {\n funnelId: opts.funnelId ?? '',\n campaignId: opts.campaignId ?? '',\n mode: opts.mode ?? 'live',\n now,\n },\n }\n\n if (!opts.overrides) return base\n return {\n ...base,\n ...opts.overrides,\n device: { ...base.device, ...opts.overrides.device },\n browser: { ...base.browser, ...opts.overrides.browser },\n os: { ...base.os, ...opts.overrides.os },\n locale: { ...base.locale, ...opts.overrides.locale },\n utm: { ...base.utm, ...opts.overrides.utm },\n clickIds: { ...base.clickIds, ...opts.overrides.clickIds },\n page: { ...base.page, ...opts.overrides.page },\n session: { ...base.session, ...opts.overrides.session },\n identity: { ...base.identity, ...opts.overrides.identity },\n system: { ...base.system, ...opts.overrides.system },\n }\n}\n\n/** Internal: reset the detection cache (tests only). */\nexport function __resetContextCache(): void {\n cached = null\n}\n","/**\n * v2 tracking seam — the funnel runtime emits a **fixed event taxonomy**, but\n * never talks to the network itself. It calls a {@link Tracker} the platform/CLI\n * injects via {@link FunnelProvider}. The real implementation is the existing\n * {@link ./tracker}.`FunnelTracker` (session id, ad attribution, debounced\n * persistence, CAPI fan-out); tests and local dev use {@link createConsoleTracker}.\n *\n * The taxonomy is preserved verbatim from v0 so analytics keep working:\n * funnel.start · page.view · page.exit · user.registered · experiment.exposure ·\n * checkout.start · checkout.payment_added · checkout.failed · purchase.complete\n *\n * Where each fires (all from the SDK runtime):\n * - `funnel.start` / `page.view` / `page.exit` / `experiment.exposure` — navigation\n * ({@link ../flow/flow}.`FunnelView`); `page.exit` carries duration + active (visible) time.\n * - `user.registered` — `identify()`, the first time `user.email` is written.\n * - `checkout.*` / `purchase.complete` — the commerce primitives ({@link ../commerce/checkout}).\n * `checkout.payment_added` is reported by an inline driver via `onPaymentAdded` (optional).\n *\n * A `responses.set(...)` does **not** emit a discrete event — values are batched into\n * `userData` and persisted (debounced). Only the events above fire.\n */\n\nimport {\n createContext,\n createElement,\n useCallback,\n useContext,\n type ReactNode,\n} from 'react'\nimport type { Acquisition } from '../state/context'\n\n// ── Event taxonomy (typed, preserved from v0) ────────────\n\nexport interface FunnelEventDataMap {\n 'funnel.start': Record<string, never>\n 'page.view': { pageId: string; pageKey?: string; pageName?: string; isInitial?: boolean; eventId?: string }\n 'page.exit': { pageId: string; durationMs: number; activeMs: number }\n 'user.registered': { email: string; eventId?: string }\n 'checkout.start': { productId?: string; priceId?: string; productName?: string }\n 'checkout.payment_added': Record<string, never>\n 'checkout.failed': { category: string; declineCode?: string; productId?: string; intent?: string }\n 'purchase.complete': { amount?: number; currency?: string; email?: string; eventId?: string }\n 'experiment.exposure': { experimentId: string; variant: string }\n}\n\n/**\n * A unique id for an analytics event, used as the **dedup key** between the\n * browser pixel (`fbq(..., { eventID })`) and the server CAPI call. Browser-\n * originated events (page.view, registration) mint one with this; **purchase /\n * subscription events carry the id the *server* minted** (the charge is the source\n * of truth) — see `CheckoutResult.eventId`.\n */\nlet _eventIdCounter = 0\nexport function newEventId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `af_${Date.now().toString(36)}_${(_eventIdCounter++).toString(36)}`\n}\n\nexport type KnownFunnelEvent = keyof FunnelEventDataMap\n\n/**\n * The surface the runtime needs from a tracker. A subset of `FunnelTracker`, so\n * the real one satisfies it directly; the console tracker is a trivial stub.\n */\nexport interface Tracker {\n /** Emit a known event (typed) or any custom event name. */\n track<E extends KnownFunnelEvent>(event: E, data?: FunnelEventDataMap[E], userData?: Record<string, unknown>): void\n track(event: string, data?: Record<string, unknown>, userData?: Record<string, unknown>): void\n /**\n * Identify by email — fires `user.registered` (idempotent in the impl). The\n * optional `eventId` is the browser↔CAPI dedup key for the registration event.\n */\n identify(email: string, eventId?: string): void\n /** Push the latest variable snapshot for batched/debounced persistence. */\n setVariables?(variables: Record<string, unknown>): void\n /**\n * The acquisition snapshot (utm + click-ids + `_fbp`/`_fbc` + referrer), pushed\n * once on entry. The platform persists it first-class — per-visit on the session +\n * **first-touch (write-once) on the Customer** — and feeds it to CAPI. Optional;\n * the console/test trackers ignore it.\n */\n setAcquisition?(acquisition: Acquisition): void\n}\n\n/** A no-op-ish tracker that logs to the console — for tests, preview, local dev. */\nexport function createConsoleTracker(opts: { silent?: boolean } = {}): Tracker {\n const log = (label: string, ...args: unknown[]) => {\n if (!opts.silent) console.info(`[appfunnel] ${label}`, ...args)\n }\n return {\n track: (event: string, data?: unknown) => log(`track ${event}`, data ?? {}),\n identify: (email: string, eventId?: string) => log('identify', email, eventId),\n setVariables: (vars) => log('vars', vars),\n setAcquisition: (acq) => log('acquisition', acq),\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\nconst TrackerContext = createContext<Tracker | null>(null)\n\nexport function TrackerProvider({\n tracker,\n children,\n}: {\n tracker: Tracker\n children: ReactNode\n}): ReactNode {\n return createElement(TrackerContext.Provider, { value: tracker }, children)\n}\n\n/** Internal: the raw tracker, or a silent console fallback if none provided. */\nexport function useTrackerRef(): Tracker {\n return useContext(TrackerContext) ?? FALLBACK\n}\n\nconst FALLBACK = createConsoleTracker({ silent: true })\n\n/**\n * `const { track } = useTracker()` — emit a custom event. Auto events\n * (page.view, identify, purchase, …) fire on their own; this is the escape\n * hatch for funnel-specific events (`track('quiz_skipped', { step: 3 })`).\n */\nexport function useTracker(): { track: Tracker['track'] } {\n const tracker = useTrackerRef()\n const track = useCallback(\n (event: string, data?: Record<string, unknown>, userData?: Record<string, unknown>) =>\n tracker.track(event, data as never, userData),\n [tracker],\n )\n return { track }\n}\n","/**\n * The **`window.appfunnel` event bus** — the client-side integration surface\n * (port of v0 `admin/lib/funnel/utils/appfunnelRuntime.ts`).\n *\n * Every taxonomy event the runtime emits is mirrored here, so on-page pixels and\n * custom scripts integrate by **subscribing** — `window.appfunnel.on('purchase.complete', …)`\n * — instead of the funnel hand-injecting pixel config per page. The pre-built pixel\n * loaders (Meta/TikTok/GTM/Clarity) are just subscribers; CAPI stays the server-side\n * default (this is the *client* sink of the same events). See doc 08 §3.\n *\n * Two deliberate properties vs. v0:\n * - **Replay history** (`events`): async pixels load *after* `funnel.start`/`page.view`\n * fire, so a late subscriber would miss them. The bus keeps a bounded history a\n * subscriber can replay (the GTM `dataLayer` trick) — no lost events.\n * - **Subscribe + read only.** The window surface exposes `on`/`off`/`events` + read\n * getters; it has **no `emit`** (third-party code can't forge events) and **no\n * mutating actions** (`setVariable`/navigation) — the funnel can't be driven through\n * it. (v0's full-control Custom-JS API is deferred pending the bus-control-scope\n * decision; doc 08 §3 + §4.)\n */\n\nimport { newEventId, type Tracker } from './tracking'\n\n/** Read accessors the bus exposes — wired to the funnel's store + context. */\nexport interface BusAccessors {\n getVariable: (key: string) => unknown\n getVariables: () => Record<string, unknown>\n getCurrentPageId: () => string | null\n getCustomerId: () => string | null\n getVisitorId: () => string | null\n}\n\nexport interface BusEvent {\n event: string\n data: unknown\n /** Epoch ms the event was emitted (for ordering / replay). */\n ts: number\n}\n\ntype Listener = (data: unknown) => void\n\n/** The public `window.appfunnel` surface — subscribe + read, never emit or mutate. */\nexport interface AppFunnelBusApi extends BusAccessors {\n /** Subscribe to an event (or `'*'` for all). Returns an unsubscribe fn. */\n on(event: string, cb: Listener): () => void\n off(event: string, cb: Listener): void\n /** Bounded replay history — read past events, then `on()` for future ones. */\n readonly events: BusEvent[]\n}\n\nconst MAX_HISTORY = 250\n\n/**\n * The internal bus: the public {@link AppFunnelBusApi} plus `emit` (SDK-only) and\n * `now` injection. The SDK holds this; only {@link AppFunnelBusApi} reaches `window`.\n */\nexport interface FunnelBus extends AppFunnelBusApi {\n emit(event: string, data?: unknown): void\n}\n\n/** Create a bus over the given read accessors. `now` is injectable for tests. */\nexport function createBus(accessors: BusAccessors, now: () => number = () => Date.now()): FunnelBus {\n const listeners = new Map<string, Set<Listener>>()\n const events: BusEvent[] = []\n\n const on: AppFunnelBusApi['on'] = (event, cb) => {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(cb)\n return () => off(event, cb)\n }\n const off: AppFunnelBusApi['off'] = (event, cb) => {\n listeners.get(event)?.delete(cb)\n }\n\n const emit = (event: string, data?: unknown) => {\n events.push({ event, data, ts: now() })\n if (events.length > MAX_HISTORY) events.shift()\n // Exact-event listeners, then wildcard. A throwing subscriber never breaks the rest.\n for (const cb of listeners.get(event) ?? []) {\n try { cb(data) } catch { /* a pixel error must not break the funnel */ }\n }\n for (const cb of listeners.get('*') ?? []) {\n try { cb({ event, data }) } catch { /* ignore */ }\n }\n }\n\n return { on, off, events, emit, ...accessors }\n}\n\n/**\n * Wrap a {@link Tracker} so every emitted taxonomy event is mirrored to the bus\n * (the client sink). `identify()` also surfaces a `user.registered` to the bus, so\n * pixels see registration. The server sink (the inner tracker → CAPI) is untouched.\n */\nexport function withBus(tracker: Tracker, bus: FunnelBus): Tracker {\n return {\n // Spread preserves the original call arity (don't append an undefined userData).\n track: ((...args: [string, unknown?, Record<string, unknown>?]) => {\n ;(tracker.track as (...a: unknown[]) => void)(...args)\n bus.emit(args[0], args[1])\n }) as Tracker['track'],\n identify: (email: string, eventId?: string) => {\n // One id shared by the server (inner.identify → CAPI) and the bus (pixel) so\n // CompleteRegistration dedupes across browser + server.\n const id = eventId ?? newEventId()\n tracker.identify(email, id)\n bus.emit('user.registered', { email, eventId: id })\n },\n setVariables: tracker.setVariables ? (v) => tracker.setVariables!(v) : undefined,\n // Acquisition is persistence (session + first-touch Customer), not a bus event.\n setAcquisition: tracker.setAcquisition ? (a) => tracker.setAcquisition!(a) : undefined,\n }\n}\n\ndeclare global {\n interface Window {\n appfunnel?: AppFunnelBusApi\n }\n}\n\n/**\n * Attach the bus's public surface to `window.appfunnel` (client-side only).\n * Returns a detach fn for unmount. No-op under SSR.\n */\nexport function attachBus(bus: FunnelBus): () => void {\n if (typeof window === 'undefined') return () => {}\n const { on, off, getVariable, getVariables, getCurrentPageId, getCustomerId, getVisitorId } = bus\n const api: AppFunnelBusApi = {\n on, off, getVariable, getVariables, getCurrentPageId, getCustomerId, getVisitorId,\n get events() { return bus.events },\n }\n window.appfunnel = api\n return () => {\n if (window.appfunnel === api) delete window.appfunnel\n }\n}\n","/**\n * v2 localization — translated **text** (prices already localize via `Intl` in\n * {@link ./catalog}). Per doc 05: locales live in the funnel source — supported\n * locales + default + fallback are funnel config ({@link FunnelLocales}), and\n * each locale is a flat `key → string` **catalog** (`messages/en.json`, …),\n * versioned + published with the funnel. The dashboard's manual translation\n * table edits exactly these catalogs.\n *\n * Lookup walks a **fallback chain** (active → fallback → default) so a missing\n * string never blanks — it falls through, and only as a last resort returns the\n * key (flagged in dev). Interpolation is simple `{{var}}`; plurals use the\n * built-in `Intl.PluralRules`; numbers/dates/percent use `Intl`. No ICU, no rich\n * markup (markup stays in TSX).\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react'\nimport type { FunnelLocales } from '../flow/spine'\n\n/** locale → (message key → string). The shape of `messages/<locale>.json`. */\nexport type MessageCatalog = Record<string, Record<string, string>>\n\nexport type PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'\nexport type Direction = 'ltr' | 'rtl'\n\nconst RTL_LANGS = new Set(['ar', 'he', 'fa', 'ur', 'ps', 'sd', 'dv', 'yi'])\n\n/** Whether a locale is right-to-left (by language subtag). */\nexport function isRtl(locale: string): boolean {\n return RTL_LANGS.has(locale.split('-')[0])\n}\n\nconst base = (l: string | undefined): string | undefined => l?.split('-')[0]\n\n/**\n * Resolve the active locale: `override` (URL/param) → `detected` (device) →\n * funnel default, each only if supported (matched by exact tag or language\n * subtag). Mirrors doc 05's resolution chain (the geo/header steps happen\n * server-side and arrive via `override`/`detected`).\n */\nexport function resolveLocale(\n config: FunnelLocales | undefined,\n detected: string,\n override?: string,\n): string {\n const supported = config?.supported ?? (config?.default ? [config.default] : ['en'])\n const def = config?.default ?? supported[0] ?? 'en'\n const pick = (l?: string): string | undefined => {\n if (!l) return undefined\n if (supported.includes(l)) return l\n return supported.find((s) => base(s) === base(l))\n }\n return pick(override) ?? pick(detected) ?? def\n}\n\n/** Replace `{{name}}` placeholders; leaves unknown ones intact. */\nfunction interpolate(str: string, params?: Record<string, string | number>): string {\n if (!params) return str\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, k: string) => (k in params ? String(params[k]) : `{{${k}}}`))\n}\n\n/** Walk the fallback chain for a key; undefined if absent everywhere. */\nfunction lookup(catalog: MessageCatalog, chain: string[], key: string): string | undefined {\n for (const loc of chain) {\n const v = catalog[loc]?.[key]\n if (v !== undefined) return v\n }\n return undefined\n}\n\nfunction devWarn(message: string): void {\n const env = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV\n if (env === 'production') return\n try {\n console.warn(message)\n } catch {\n /* no-op */\n }\n}\n\n// ── Public types ─────────────────────────────────────────\n\nexport interface TFunction {\n /** Translate a key, with optional `{{var}}` params. Missing → fallback → key. */\n (key: string, params?: Record<string, string | number>): string\n /** Locale-correct plural: `t.plural(n, { one: '# day', other: '# days' })` (`#` → n). */\n plural: (\n n: number,\n forms: Partial<Record<PluralCategory, string>>,\n params?: Record<string, string | number>,\n ) => string\n}\n\nexport interface Formatters {\n number: (n: number, opts?: Intl.NumberFormatOptions) => string\n date: (d: Date | number, opts?: Intl.DateTimeFormatOptions) => string\n percent: (n: number, opts?: Intl.NumberFormatOptions) => string\n}\n\nexport interface Translation {\n t: TFunction\n fmt: Formatters\n /** The active (resolved) locale. */\n locale: string\n /** Switch locale at runtime (preview / language picker). */\n setLocale: (locale: string) => void\n /** Text direction for the active locale. */\n dir: Direction\n /** The funnel's supported locales. */\n locales: string[]\n}\n\n// ── React wiring ─────────────────────────────────────────\n\ninterface LocaleContextValue {\n locale: string\n setLocale: (locale: string) => void\n config?: FunnelLocales\n catalog: MessageCatalog\n}\n\nconst LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport interface LocaleProviderProps {\n config?: FunnelLocales\n catalog?: MessageCatalog\n /** Device/browser locale (from computed context) — the resolution input. */\n detected: string\n /** Explicit override (URL/param/geo), highest priority. */\n override?: string\n children: ReactNode\n}\n\n/** Resolves + holds the active locale and the message catalog. */\nexport function LocaleProvider({\n config,\n catalog = {},\n detected,\n override,\n children,\n}: LocaleProviderProps): ReactNode {\n const [locale, setLocale] = useState(() => resolveLocale(config, detected, override))\n const value = useMemo<LocaleContextValue>(\n () => ({ locale, setLocale, config, catalog }),\n [locale, config, catalog],\n )\n return createElement(LocaleContext.Provider, { value }, children)\n}\n\n/** The active (resolved) funnel locale, or `'en'` if no provider — for display\n * formatting (e.g. {@link ./catalog} prices) without building the full handle. */\nexport function useActiveLocale(): string {\n return useContext(LocaleContext)?.locale ?? 'en'\n}\n\n/**\n * `const { t, fmt, locale, dir } = useTranslation()` — translated text +\n * locale-aware `Intl` formatters for the active funnel locale.\n */\nexport function useTranslation(): Translation {\n const ctx = useContext(LocaleContext)\n if (!ctx) throw new Error('useTranslation must be used inside <FunnelProvider>')\n const { locale, setLocale, config, catalog } = ctx\n\n const chain = useMemo(() => {\n const def = config?.default\n const fb = config?.fallback\n return Array.from(new Set([locale, fb, def].filter(Boolean) as string[]))\n }, [locale, config])\n\n const t = useMemo<TFunction>(() => {\n const fn = ((key: string, params?: Record<string, string | number>) => {\n const raw = lookup(catalog, chain, key)\n if (raw === undefined) {\n devWarn(`[appfunnel] missing translation: \"${key}\" (${locale})`)\n return key\n }\n return interpolate(raw, params)\n }) as TFunction\n fn.plural = (n, forms, params) => {\n const rule = new Intl.PluralRules(locale).select(n) as PluralCategory\n const form = forms[rule] ?? forms.other ?? ''\n return interpolate(form.replace(/#/g, String(n)), params)\n }\n return fn\n }, [catalog, chain, locale])\n\n const fmt = useMemo<Formatters>(\n () => ({\n number: (n, opts) => new Intl.NumberFormat(locale, opts).format(n),\n date: (d, opts) => new Intl.DateTimeFormat(locale, opts).format(d),\n percent: (n, opts) => new Intl.NumberFormat(locale, { style: 'percent', ...opts }).format(n),\n }),\n [locale],\n )\n\n return {\n t,\n fmt,\n locale,\n setLocale,\n dir: isRtl(locale) ? 'rtl' : 'ltr',\n locales: config?.supported ?? [locale],\n }\n}\n","/**\n * v2 `products` — the **read-only** product catalog.\n *\n * **AppFunnel does not manage currency.** Multi-currency is entirely the payment\n * provider's job: the provider (or its preview API) resolves the visitor's price,\n * and we receive a single resolved `{ amount, currency }` per product. No FX, no\n * currency selection, no conversion on our side. (FX appears only for frozen-USD\n * *reporting*, never display — phase-3 §3.6b.) A provider that doesn't localize\n * simply gives one currency.\n *\n * Our only job is **display**: pick the product by logical id and **format** its\n * amount. Formatting happens at read time in the funnel's **active locale** (so\n * switching language reformats `kr 79,00` ⇄ `$9.99`), while the **currency** is\n * whatever the provider resolved. Currency selection is the platform's; the\n * authoring funnel only ever names a product id.\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n useMemo,\n type ReactNode,\n} from 'react'\nimport { useActiveLocale } from '../i18n/translation'\n\n// ── Shape ────────────────────────────────────────────────\n\nexport type Interval = 'day' | 'week' | 'month' | 'year' | 'one_time'\n\n/** What the platform hands the funnel per product (a single provider-resolved price). */\nexport interface ProductInput {\n id: string\n name?: string\n displayName?: string\n /** Provider-resolved price in **minor units** (the provider chose the currency). */\n amount: number\n /** Currency of `amount`, as the provider resolved it (e.g. `DKK`). */\n currency: string\n interval?: Interval\n intervalCount?: number\n trialDays?: number\n /** Trial price in minor units (omit/0 = free trial). */\n trialAmount?: number\n /** Settlement provider — opaque to the author, used by the checkout driver. */\n provider?: string\n}\n\n/** A money value with a locale-formatted string. */\nexport interface Money {\n /** Major units, e.g. `79`. */\n amount: number\n /** Minor units, e.g. `7900`. */\n minor: number\n currency: string\n /** Locale-formatted, e.g. `kr 79,00` / `€9,99` / `$9.99`. */\n formatted: string\n}\n\n/**\n * The product with its amounts resolved (currency + period math), **before**\n * locale formatting — what the catalog stores. {@link useProduct} formats it.\n */\nexport interface ResolvedProduct {\n id: string\n name: string\n displayName: string\n provider: string\n currency: string\n priceMinor: number\n perDayMinor: number\n perWeekMinor: number\n perMonthMinor: number\n perYearMinor: number\n period: string\n periodly: string\n hasTrial: boolean\n trialDays: number\n trialMinor: number\n}\n\n/** Display-ready product the author reads (every amount locale-formatted). */\nexport interface Product {\n id: string\n name: string\n displayName: string\n provider: string\n price: Money\n /** e.g. `month`, `quarter`, `one-time`. */\n period: string\n /** e.g. `monthly`, `quarterly`, `one-time`. */\n periodly: string\n /** Period-normalized prices (for \"just $0.27/day\" style copy). */\n perDay: Money\n perWeek: Money\n perMonth: Money\n perYear: Money\n hasTrial: boolean\n trialDays: number\n trialPrice: Money | null\n}\n\n// ── Resolve (currency-agnostic) ──────────────────────────\n\nconst PERIOD_DAYS: Record<Interval, number> = {\n day: 1, week: 7, month: 30, year: 365, one_time: 0,\n}\n\nfunction periodDays(interval: Interval, count: number): number {\n return PERIOD_DAYS[interval] * count\n}\n\nfunction intervalLabel(interval: Interval, count: number): { period: string; periodly: string } {\n if (interval === 'one_time') return { period: 'one-time', periodly: 'one-time' }\n if (interval === 'month' && count === 3) return { period: 'quarter', periodly: 'quarterly' }\n if (interval === 'month' && count === 6) return { period: '6 months', periodly: 'semiannually' }\n if (interval === 'week' && count === 2) return { period: '2 weeks', periodly: 'biweekly' }\n if (count === 1) {\n const periodly = { day: 'daily', week: 'weekly', month: 'monthly', year: 'yearly' }[interval]\n return { period: interval, periodly }\n }\n return { period: `${count} ${interval}s`, periodly: `every ${count} ${interval}s` }\n}\n\n/** Resolve a {@link ProductInput} into amounts + period math (no formatting yet). */\nexport function resolveProduct(input: ProductInput): ResolvedProduct {\n const interval = input.interval ?? 'one_time'\n const count = input.intervalCount ?? 1\n const days = periodDays(interval, count)\n const perDayMinor = days > 0 ? input.amount / days : input.amount\n const label = intervalLabel(interval, count)\n\n return {\n id: input.id,\n name: input.name ?? input.id,\n displayName: input.displayName ?? input.name ?? input.id,\n provider: input.provider ?? 'stripe',\n currency: input.currency,\n priceMinor: input.amount,\n perDayMinor,\n perWeekMinor: perDayMinor * 7,\n perMonthMinor: perDayMinor * 30,\n perYearMinor: perDayMinor * 365,\n period: label.period,\n periodly: label.periodly,\n hasTrial: (input.trialDays ?? 0) > 0,\n trialDays: input.trialDays ?? 0,\n trialMinor: input.trialAmount ?? 0,\n }\n}\n\n/** Build the id → {@link ResolvedProduct} catalog. Formatting happens at read time. */\nexport function buildCatalog(inputs: ProductInput[]): Map<string, ResolvedProduct> {\n return new Map(inputs.map((i) => [i.id, resolveProduct(i)]))\n}\n\n// ── Format (locale-dependent) ────────────────────────────\n\nfunction formatMoney(minor: number, currency: string, locale: string): Money {\n const amount = minor / 100\n const code = currency.toUpperCase()\n let formatted: string\n try {\n formatted = new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n } catch {\n formatted = `${code} ${amount.toFixed(2)}`\n }\n return { amount, minor, currency: code, formatted }\n}\n\n/** Format a {@link ResolvedProduct} into a display {@link Product} in `locale`. */\nexport function formatProduct(r: ResolvedProduct, locale: string): Product {\n const m = (minor: number): Money => formatMoney(minor, r.currency, locale)\n return {\n id: r.id,\n name: r.name,\n displayName: r.displayName,\n provider: r.provider,\n price: m(r.priceMinor),\n period: r.period,\n periodly: r.periodly,\n perDay: m(r.perDayMinor),\n perWeek: m(r.perWeekMinor),\n perMonth: m(r.perMonthMinor),\n perYear: m(r.perYearMinor),\n hasTrial: r.hasTrial,\n trialDays: r.trialDays,\n trialPrice: r.hasTrial ? m(r.trialMinor) : null,\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\nconst CatalogContext = createContext<Map<string, ResolvedProduct> | null>(null)\n\nexport function CatalogProvider({\n catalog,\n children,\n}: {\n catalog: Map<string, ResolvedProduct>\n children: ReactNode\n}): ReactNode {\n return createElement(CatalogContext.Provider, { value: catalog }, children)\n}\n\nfunction useCatalog(): Map<string, ResolvedProduct> {\n return useContext(CatalogContext) ?? EMPTY\n}\nconst EMPTY = new Map<string, ResolvedProduct>()\n\n/** `useProduct('monthly')` — one product, formatted in the active locale. */\nexport function useProduct(id: string | undefined): Product | undefined {\n const catalog = useCatalog()\n const locale = useActiveLocale()\n const resolved = id ? catalog.get(id) : undefined\n return useMemo(() => (resolved ? formatProduct(resolved, locale) : undefined), [resolved, locale])\n}\n\n/** `useProducts()` — every product, formatted in the active locale, in order. */\nexport function useProducts(): Product[] {\n const catalog = useCatalog()\n const locale = useActiveLocale()\n return useMemo(\n () => Array.from(catalog.values()).map((r) => formatProduct(r, locale)),\n [catalog, locale],\n )\n}\n","import type { ComponentType } from 'react'\nimport type { VariableConfig, VariableValue } from '../types'\nimport type { FunnelContext } from '../state/context'\n\n/**\n * The funnel **spine** — the constrained, declarative configuration authored as\n * code (`defineFunnel` / `pageMeta` / `definePage`) yet **dashboard-editable**\n * (static AST parse → pretty UI → codegen) and compiled to the manifest IR.\n *\n * Principle: **presentation = code** (the page components), **configuration =\n * data** (this spine). See docs/platform-v2/06-funnel-project-model.md.\n *\n * Routing is **declarative nodes + code predicates** (decided — doc 06): a\n * page's `next` is an ordered list of {@link Route}s, each with a **static `to`\n * page key** (so the dashboard can draw every possible edge without executing\n * anything) and an optional `when` **gate** that returns true/false. The gate is\n * either a declarative {@link Condition} (one field — UI-editable data) or a code\n * {@link Predicate} (`s => boolean` — the escape hatch, opaque body but the edge\n * is still visible). First matching route wins; a route with no `when` is the\n * fallback. Multiple conditions = multiple routes (or boolean logic in one\n * predicate). Omit `next` entirely for the default linear flow.\n */\n\n// ── Snapshot (what a predicate sees) ─────────────────────\n\n/**\n * Read-only view of every namespace a routing/condition predicate can branch\n * on. `user`/`responses`/`data` are the writable namespaces; `context` is the\n * read-only computed one ({@link FunnelContext}).\n */\nexport interface FunnelSnapshot {\n user: Record<string, VariableValue>\n responses: Record<string, VariableValue>\n data: Record<string, VariableValue>\n context: FunnelContext\n}\n\n/** A code-predicate gate — `s => s.responses.goal === 'gain'`. */\nexport type Predicate = (s: FunnelSnapshot) => boolean\n\nexport type ConditionOp =\n | 'eq' | 'neq' | 'in' | 'gt' | 'gte' | 'lt' | 'lte'\n | 'exists' | 'empty' | 'contains'\n\n/**\n * A declarative gate over **one** namespaced field — UI-editable data the\n * dashboard renders as a condition row (`field` `op` `value`). `field` is a\n * dotted path into the snapshot: `responses.goal`, `user.country`,\n * `context.device.isMobile`.\n */\nexport interface Condition {\n field: string\n op: ConditionOp\n value?: VariableValue | VariableValue[]\n}\n\n/** An edge gate: either declarative data ({@link Condition}) or a {@link Predicate}. */\nexport type Gate = Condition | Predicate\n\n/**\n * One routing edge out of a page. `to` is a **static** target key (the dashboard\n * reads these to draw the flow graph); `when` gates the edge (omit = fallback).\n */\nexport interface Route {\n to: string\n when?: Gate\n}\n\n/** Read a dotted path out of the snapshot (flat namespaces + nested `context`). */\nfunction readField(s: FunnelSnapshot, field: string): VariableValue {\n let cur: unknown = s\n for (const part of field.split('.')) {\n if (cur == null) return undefined\n cur = (cur as Record<string, unknown>)[part]\n }\n return cur as VariableValue\n}\n\n/** Evaluate a declarative {@link Condition} against a snapshot. */\nexport function evaluateCondition(cond: Condition, s: FunnelSnapshot): boolean {\n const val = readField(s, cond.field)\n const { op, value } = cond\n switch (op) {\n case 'eq': return val === value\n case 'neq': return val !== value\n case 'in': return Array.isArray(value) && (value as VariableValue[]).includes(val as VariableValue)\n case 'gt': return typeof val === 'number' && typeof value === 'number' && val > value\n case 'gte': return typeof val === 'number' && typeof value === 'number' && val >= value\n case 'lt': return typeof val === 'number' && typeof value === 'number' && val < value\n case 'lte': return typeof val === 'number' && typeof value === 'number' && val <= value\n case 'contains':\n if (typeof val === 'string') return val.includes(String(value))\n if (Array.isArray(val)) return (val as VariableValue[]).includes(value as VariableValue)\n return false\n case 'exists': return val !== undefined && val !== null && val !== ''\n case 'empty':\n return val === undefined || val === null || val === '' ||\n (Array.isArray(val) && val.length === 0)\n default: return false\n }\n}\n\n/** Evaluate either gate kind to a boolean. */\nexport function evaluateGate(gate: Gate, s: FunnelSnapshot): boolean {\n return typeof gate === 'function' ? gate(s) : evaluateCondition(gate, s)\n}\n\n/**\n * Resolve an ordered list of routes to a target page key, or `undefined` to fall\n * through to the linear next. First route whose gate passes (or has no `when`)\n * wins.\n */\nexport function resolveRoute(\n routes: Route[] | undefined,\n s: FunnelSnapshot,\n): string | undefined {\n if (!routes) return undefined\n for (const route of routes) {\n if (!route.when || evaluateGate(route.when, s)) return route.to\n }\n return undefined\n}\n\n// ── Pages ────────────────────────────────────────────────\n\nexport type PageType =\n | 'default' // plain content/step page (the baseline)\n | 'email-capture' // collects user.email — the mandatory identity step (validated)\n | 'paywall' // the offer/pricing page → drives paywall-view + paywall-CR\n | 'upsell' // post-purchase one-click → drives Upsell Rate + off-session charge\n | 'finish' // terminal success/thank-you page → completion analytics, ends the flow\n\nexport interface PageMeta {\n /** Page kind — drives behavior + analytics (e.g. `paywall`, `upsell`). */\n type?: PageType\n /** URL slug; defaults to the page key. */\n slug?: string\n /**\n * Ordered routing edges out of this page (first match wins). Each has a static\n * `to` key + an optional `when` gate. Omit for the default linear flow.\n */\n next?: Route[]\n /**\n * Entry precondition for **deep-link / reload** restoration. When the runtime is\n * asked to start *on this page* (not via in-funnel navigation), it restores there\n * only if `guard` passes against the restored snapshot — otherwise it falls back\n * to the start page. e.g. an upsell page: `guard: s => s.data.purchased === true`.\n * Reaching the page via `next()` is unaffected (routing already gated it). Omit =\n * always restorable. Same gate kind as routing (`Condition` or predicate).\n */\n guard?: Gate\n}\n\n/**\n * Identity helper for a page's co-located metadata.\n * `export const meta = pageMeta({ type: 'paywall', next: s => … })`.\n */\nexport function pageMeta(meta: PageMeta): PageMeta {\n return meta\n}\n\n/**\n * Default entry guard implied by a page **type** — a built-in precondition every\n * funnel inherits. `paywall` and `upsell` require a captured `user.email` (the\n * mandatory identity step), so a deep-link / reload straight into them without\n * email bounces to the start. Authors don't write this; an explicit `meta.guard`\n * **overrides** it (see {@link entryGuard}).\n */\nconst TYPE_GUARDS: Partial<Record<PageType, Gate>> = {\n paywall: { field: 'user.email', op: 'exists' },\n upsell: { field: 'user.email', op: 'exists' },\n}\n\n/**\n * The effective entry guard for a page: an explicit `meta.guard` if the author set\n * one, **otherwise** the page-type default (e.g. paywall/upsell need email). The\n * explicit guard fully **overrides** the default — it's not combined. Returns\n * `undefined` when neither applies.\n */\nexport function entryGuard(meta?: PageMeta): Gate | undefined {\n return meta?.guard ?? (meta?.type ? TYPE_GUARDS[meta.type] : undefined)\n}\n\n/**\n * Identity helper for a page component. The page is plain React that reaches the\n * runtime through hooks (`useResponse`, `useNavigation`, …) — there is no `sdk`\n * prop. `export default definePage(function Welcome() { … })`.\n */\nexport function definePage<P extends object = Record<string, never>>(\n component: ComponentType<P>,\n): ComponentType<P> {\n return component\n}\n\n// ── Flow resolution ──────────────────────────────────────\n\n/** A page in the flow: its key + (optional) co-located meta. */\nexport interface FlowPage {\n key: string\n meta?: PageMeta\n}\n\n/**\n * Decide the next page from `currentKey`:\n * 1. the current page's `next` routes ({@link resolveRoute}), if one matches, else\n * 2. the next page in file order (the default linear flow), else\n * 3. `undefined` (end of funnel / current key not found).\n */\nexport function nextPage(\n pages: FlowPage[],\n currentKey: string,\n s: FunnelSnapshot,\n): string | undefined {\n const idx = pages.findIndex((p) => p.key === currentKey)\n if (idx === -1) return undefined\n const routed = resolveRoute(pages[idx].meta?.next, s)\n if (routed) return routed\n return pages[idx + 1]?.key\n}\n\n/**\n * Every page a visitor *could* go to next from `currentKey` — all route targets\n * (regardless of gate, since we don't know which will pass) plus the linear next.\n * Used to **prefetch** the likely-next page chunks; not for navigation.\n */\nexport function outgoingKeys(pages: FlowPage[], currentKey: string): string[] {\n const idx = pages.findIndex((p) => p.key === currentKey)\n if (idx === -1) return []\n const out = new Set<string>()\n for (const route of pages[idx].meta?.next ?? []) out.add(route.to)\n const linear = pages[idx + 1]?.key\n if (linear) out.add(linear)\n return [...out]\n}\n\n/**\n * The number of pages on the path from `startKey` to a `finish` (or the end of\n * the flow) **given the current state** — the denominator for progress. It walks\n * the actual routing ({@link nextPage}) rather than counting all files, so a\n * branched funnel reaches 100% on whichever path the visitor's answers select.\n * Re-traced per navigation; a visited set guards against routing cycles.\n */\nexport function expectedPathLength(\n pages: FlowPage[],\n startKey: string,\n s: FunnelSnapshot,\n): number {\n const seen = new Set<string>()\n let key: string | undefined = startKey\n let count = 0\n while (key && !seen.has(key)) {\n seen.add(key)\n count++\n if (pages.find((p) => p.key === key)?.meta?.type === 'finish') break\n key = nextPage(pages, key, s)\n }\n return count\n}\n\n// ── Funnel definition ────────────────────────────────────\n\nexport interface FunnelLocales {\n default: string\n supported: string[]\n fallback?: string\n}\n\n/**\n * The funnel-level spine. Flow is mostly inferred from page file order + each\n * page's `next`; this holds the funnel-wide config. Stays **thin** — routing\n * lives co-located on pages (doc 06: \"funnel.ts stays thin\").\n */\nexport interface FunnelDefinition {\n id: string\n /** `responses.*` runtime variables (default values). */\n responses?: Record<string, VariableConfig>\n /** `data.*` working/scratch variables (default values). */\n data?: Record<string, VariableConfig>\n /** Product ids from the platform catalog this funnel uses (prices resolved at render). */\n products?: string[]\n locales?: FunnelLocales\n /**\n * When `true`, the funnel shows the **geo-specific** currency/price the payment\n * provider resolves (Stripe `currency_options`, Paddle preview, Whop, SolidGate,\n * …). When `false` (default), a single fixed currency is used. AppFunnel does no\n * FX — this only toggles whether the platform asks the provider for the geo\n * price; the SDK just displays whatever resolved `{amount, currency}` it's handed.\n * (See docs/platform-v2 phase-3 §3.6.)\n */\n locationAwareCurrency?: boolean\n}\n\n/** Identity helper for a funnel definition. */\nexport function defineFunnel(def: FunnelDefinition): FunnelDefinition {\n return def\n}\n","/**\n * **Runtime page-level experiments** — A/B/n on a *single page inside one funnel*,\n * resolved at render time (phase-4). No funnel duplication: a slot (e.g. the page\n * `welcome`) has alternate versions filed as siblings (`welcome@b.tsx`), and the\n * runtime shows **one** of them per visitor, collapsing the losers out of the\n * linear flow. The flow keeps stable **slot keys** (the control's key); only the\n * rendered component swaps — so routing, the manifest, and analytics all key on the\n * slot, not the variant.\n *\n * **Where the wiring lives:** the *variant pages* are code (compiled into the\n * bundle). The *experiment wiring* — slot, variant→page map, weights, status — is\n * **operational data the platform owns** (a DB record, edited by the dashboard,\n * changed without recompiling the funnel). The SDK is storage-agnostic: the\n * platform hands the runtime experiment records to `FunnelProvider`, the same way\n * it hands in resolved product prices. This module just resolves them.\n *\n * **The only source-side marker** is the `@` in a variant file's key\n * (`welcome@b`): it tells the *build* (manifest, flow graph) that a page is an\n * off-flow variant of its slot, so the structure is correct without the DB. The\n * label/weight/experiment-id are not in source.\n *\n * Bucketing is a deterministic FNV-1a hash, **namespaced by experiment id** so\n * independent experiments bucket orthogonally (the basis for layering 100+ tests,\n * §4.3). The seed is the durable identity ({@link bucketingSeed}) — never the\n * session/fingerprint — so a returning visitor keeps their variant (landmine #4).\n * Stability across an *add-a-variant* edit is the platform's job: an experiment's\n * variant set is immutable while running (reweighting / adding an arm = a new\n * experiment version), so within one record the assignment never moves.\n *\n * This module is pure (no React, no I/O) → it unit-tests trivially and the\n * dashboard/server can reuse the same assignment math.\n */\n\nimport type { FunnelContext } from '../state/context'\n\n// ── Hashing ──────────────────────────────────────────────\n\n/**\n * FNV-1a 32-bit hash → unsigned int. Deterministic and isomorphic (no `crypto`,\n * runs the same in the browser, a worker, and a build). The same math v0 used,\n * kept because it's sound — only the *seed* changes (identity, not session).\n */\nexport function fnv1a(input: string): number {\n let h = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i)\n // h *= 16777619, in uint32, via shift-adds.\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0\n }\n return h >>> 0\n}\n\n/** Map a seed string to a stable float in `[0, 1)`. */\nexport function hashToUnit(seed: string): number {\n return fnv1a(seed) / 0x1_0000_0000\n}\n\n/**\n * Pick a variant key by weight from a stable unit position `u ∈ [0,1)`. Variants\n * are walked in declaration order and the first whose cumulative weight band\n * contains `u` wins, so the same `u` always lands in the same variant.\n */\nexport function pickByWeight(weights: Record<string, number>, u: number): string {\n const entries = Object.entries(weights).filter(([, w]) => w > 0)\n if (entries.length === 0) return Object.keys(weights)[0] ?? ''\n const total = entries.reduce((sum, [, w]) => sum + w, 0)\n const target = u * total\n let acc = 0\n for (const [key, w] of entries) {\n acc += w\n if (target < acc) return key\n }\n return entries[entries.length - 1][0]\n}\n\n/**\n * Deterministically assign a visitor (`seed`) to a variant of one experiment.\n * The hash is **namespaced by `experimentId`** so two experiments on the same\n * traffic don't correlate (orthogonal layering).\n */\nexport function assignVariant(\n experimentId: string,\n seed: string,\n weights: Record<string, number>,\n): string {\n return pickByWeight(weights, hashToUnit(`${experimentId}:${seed}`))\n}\n\n// ── Seed + slot parsing ──────────────────────────────────\n\n/**\n * The stable bucketing seed: the known `customerId`, else the signed `visitorId`.\n * Never the session id or fingerprint (landmine #4). `null` when neither is known\n * — the caller then serves control instead of bucketing on nothing.\n */\nexport function bucketingSeed(context: FunnelContext): string | null {\n return context.identity.customerId ?? context.identity.visitorId ?? null\n}\n\n/** Split a page key into its slot + optional variant: `welcome@b` → `{ slot, variant: 'b' }`. */\nexport function parseSlotKey(key: string): { slot: string; variant?: string } {\n const at = key.indexOf('@')\n return at === -1 ? { slot: key } : { slot: key.slice(0, at), variant: key.slice(at + 1) }\n}\n\n/** True if a page key is an off-flow variant (`welcome@b`), by the source-side `@` marker. */\nexport function isVariantKey(key: string): boolean {\n return parseSlotKey(key).variant !== undefined\n}\n\n// ── Runtime experiment records (platform/DB-sourced) ─────\n\n/** One arm of an experiment: which page renders, at what weight. */\nexport interface ExperimentVariant {\n /** The page key this arm renders (the slot's control, or a `@variant` sibling). */\n page: string\n /** Relative weight in the split (need not sum to 100; zero = paused arm). */\n weight: number\n}\n\n/**\n * A runtime experiment record — the operational wiring the **platform** owns and\n * hands to the SDK (not authored in the funnel source). The variant *pages* are\n * code in the bundle; this is the live config over them.\n */\nexport interface RuntimeExperiment {\n id: string\n /** The page key holding the flow position (the anchor / control). */\n slot: string\n /** label → arm. One arm's `page` is the `slot` (control); others are `@variant` siblings. */\n variants: Record<string, ExperimentVariant>\n /** Lifecycle. Absent = running. */\n status?: 'running' | 'paused' | 'stopped'\n /** When stopped, the variant label everyone sees until promotion bakes it into the slot. */\n winner?: string\n /** Primary metric (analytics only; not used for resolution). */\n metric?: string\n}\n\n// ── Flow resolution ──────────────────────────────────────\n\nexport interface ExperimentResolution {\n /** experiment id → assigned variant label. */\n assignments: Record<string, string>\n /** Page keys forming the effective linear flow (variant siblings removed), in order. */\n activeKeys: string[]\n /** Slot key → the page key whose component should render there. */\n render: Record<string, string>\n /** Variant page key → its slot key. For remapping a route that targets a variant. */\n slotOf: Record<string, string>\n /** Slot key → the experiment id it hosts (drives the exposure event). */\n experimentOf: Record<string, string>\n}\n\n/** Weights map (label → weight) for one experiment's arms. */\nfunction weightsOf(exp: RuntimeExperiment): Record<string, number> {\n const out: Record<string, number> = {}\n for (const [label, v] of Object.entries(exp.variants)) out[label] = v.weight\n return out\n}\n\n/**\n * Resolve which page version each experiment slot shows for this visitor, and\n * which page keys remain in the linear flow.\n *\n * Variant pages are detected structurally by the `@` in their key, so they\n * collapse out of the linear flow even for a slot with no active experiment.\n * For each *running* experiment the visitor is bucketed (stable on `seed`); a\n * *stopped* one serves its `winner`; a *paused* one (or no seed) serves the slot.\n */\nexport function resolveExperiments(\n pages: { key: string }[],\n experiments: RuntimeExperiment[],\n seed: string | null,\n): ExperimentResolution {\n const assignments: Record<string, string> = {}\n const render: Record<string, string> = {}\n const experimentOf: Record<string, string> = {}\n\n for (const exp of experiments) {\n const status = exp.status ?? 'running'\n let label: string\n if (status === 'stopped' && exp.winner) label = exp.winner\n else if (status === 'running' && seed) label = assignVariant(exp.id, seed, weightsOf(exp))\n else continue // paused, or no seed → the slot renders its own (control) page\n\n const arm = exp.variants[label]\n if (!arm) continue\n assignments[exp.id] = label\n experimentOf[exp.slot] = exp.id\n if (arm.page !== exp.slot) render[exp.slot] = arm.page // swap only when a non-control arm won\n }\n\n // Variant siblings (`@`) never stand alone in the linear flow.\n const slotOf: Record<string, string> = {}\n const activeKeys: string[] = []\n for (const p of pages) {\n const { slot, variant } = parseSlotKey(p.key)\n if (variant !== undefined) slotOf[p.key] = slot\n else activeKeys.push(p.key)\n }\n\n return { assignments, activeKeys, render, slotOf, experimentOf }\n}\n\n// ── Validation ───────────────────────────────────────────\n\n/** One referential problem with an experiment record. */\nexport interface ExperimentIssue {\n /** The offending experiment id (`'*'` for a cross-experiment issue). */\n experimentId: string\n code:\n | 'slot_missing' // slot is not a page in the funnel\n | 'slot_is_variant' // slot points at an `@variant`, not a real flow page\n | 'slot_conflict' // two experiments target the same slot\n | 'duplicate_id' // two experiments share an id (bucketing namespace collision)\n | 'variant_page_missing' // a variant references a page that doesn't exist (dangling)\n | 'variant_slot_mismatch' // a variant's `@`-page belongs to a different slot\n | 'no_control' // no arm renders the slot itself (the baseline)\n | 'no_traffic' // every arm has weight ≤ 0\n | 'negative_weight' // an arm has a negative weight\n | 'bad_winner' // a stopped experiment's winner isn't one of its variants\n | 'single_arm' // only one variant — nothing to test (warning)\n | 'orphan_variant' // a `@variant` page no running experiment renders (warning)\n message: string\n}\n\nexport interface ExperimentValidation {\n ok: boolean\n errors: ExperimentIssue[]\n warnings: ExperimentIssue[]\n}\n\n/**\n * Cross-check experiment records against the funnel's pages — the publish-time /\n * experiment-edit gate that catches the dangling references the runtime can't see\n * (the experiment wiring lives in the DB; the pages live in the build, so they can\n * drift). Pure: hand it the runtime experiments + the funnel's page keys (e.g.\n * `manifest.pages`).\n *\n * Errors block; warnings inform. `orphan_variant` is a warning, not an error — a\n * `@variant` file with no running experiment is dead-but-harmless (a paused test, or\n * one not wired yet).\n */\nexport function validateExperiments(\n experiments: RuntimeExperiment[],\n pages: { key: string }[],\n): ExperimentValidation {\n const errors: ExperimentIssue[] = []\n const warnings: ExperimentIssue[] = []\n const pageKeys = new Set(pages.map((p) => p.key))\n\n const seenIds = new Set<string>()\n const slotOwner = new Map<string, string>()\n const renderedVariantPages = new Set<string>() // arm pages that are `@variant`s\n\n for (const exp of experiments) {\n const err = (code: ExperimentIssue['code'], message: string) =>\n errors.push({ experimentId: exp.id, code, message })\n const warn = (code: ExperimentIssue['code'], message: string) =>\n warnings.push({ experimentId: exp.id, code, message })\n\n if (seenIds.has(exp.id)) err('duplicate_id', `Experiment id \"${exp.id}\" is used more than once.`)\n seenIds.add(exp.id)\n\n // Slot must be a real flow page (not missing, not itself a variant).\n if (!pageKeys.has(exp.slot)) err('slot_missing', `Slot \"${exp.slot}\" is not a page in the funnel.`)\n if (isVariantKey(exp.slot)) err('slot_is_variant', `Slot \"${exp.slot}\" is a variant page; a slot must be a real flow page.`)\n if (slotOwner.has(exp.slot)) {\n err('slot_conflict', `Slot \"${exp.slot}\" is already targeted by experiment \"${slotOwner.get(exp.slot)}\".`)\n } else {\n slotOwner.set(exp.slot, exp.id)\n }\n\n const arms = Object.entries(exp.variants)\n if (arms.length < 2) warn('single_arm', `Experiment \"${exp.id}\" has fewer than two variants — nothing to test.`)\n\n let hasControl = false\n let totalWeight = 0\n for (const [label, arm] of arms) {\n if (!pageKeys.has(arm.page)) {\n err('variant_page_missing', `Variant \"${label}\" references page \"${arm.page}\", which doesn't exist.`)\n }\n if (arm.page === exp.slot) hasControl = true\n else if (isVariantKey(arm.page)) {\n renderedVariantPages.add(arm.page)\n if (parseSlotKey(arm.page).slot !== exp.slot) {\n err('variant_slot_mismatch', `Variant \"${label}\" page \"${arm.page}\" belongs to a different slot than \"${exp.slot}\".`)\n }\n }\n if (arm.weight < 0) err('negative_weight', `Variant \"${label}\" has a negative weight (${arm.weight}).`)\n totalWeight += arm.weight\n }\n if (!hasControl) err('no_control', `No variant of \"${exp.id}\" renders the slot \"${exp.slot}\" itself (the control/baseline).`)\n if (totalWeight <= 0) err('no_traffic', `Experiment \"${exp.id}\" has no positive weight — no traffic would enter it.`)\n\n if (exp.status === 'stopped' && exp.winner && !exp.variants[exp.winner]) {\n err('bad_winner', `Stopped experiment \"${exp.id}\" names winner \"${exp.winner}\", which isn't one of its variants.`)\n }\n }\n\n // A `@variant` page that no running experiment renders is dead (but harmless).\n const running = new Set(experiments.filter((e) => (e.status ?? 'running') === 'running').flatMap((e) =>\n Object.values(e.variants).map((v) => v.page),\n ))\n for (const p of pages) {\n if (isVariantKey(p.key) && !running.has(p.key)) {\n warnings.push({ experimentId: '*', code: 'orphan_variant', message: `Variant page \"${p.key}\" is rendered by no running experiment.` })\n }\n }\n\n return { ok: errors.length === 0, errors, warnings }\n}\n","import {\n createContext,\n createElement,\n lazy,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport { useFunnel } from '../state/namespaces'\nimport { newEventId, useTrackerRef } from '../tracking/tracking'\nimport { entryGuard, evaluateGate, expectedPathLength, nextPage, outgoingKeys, type FlowPage, type PageMeta } from './spine'\nimport { bucketingSeed, resolveExperiments } from './experiments'\nimport type { PageContext } from '../state/context'\n\n/** What a page's `load` resolves to — a component, or a module default-exporting one. */\nexport type PageModule = ComponentType | { default: ComponentType }\n\n/**\n * A page wired into the runtime. Provide **either** an eager `Component` (small\n * funnels, tests) **or** a lazy `load` (code-split: the renderer hands a dynamic\n * `import()` so a big funnel ships one chunk per page, not the whole funnel).\n */\nexport interface RuntimePage {\n key: string\n meta?: PageMeta\n /** Eager component. Provide this or `load`. */\n Component?: ComponentType\n /** Lazy loader for a code-split chunk. Provide this or `Component`. */\n load?: () => Promise<PageModule>\n}\n\nexport interface NavigationState {\n /** The current page's read-only context (key, index, total, progress). */\n page: PageContext\n /** Advance via the current page's `next` predicate, else the linear next. */\n next: () => void\n /** Go to the previous page in history. */\n back: () => void\n /** Jump to a specific page key. */\n go: (key: string) => void\n /** Warm a page's code-split chunk ahead of navigation (e.g. on link hover). No-op for eager pages. */\n prefetch: (key: string) => void\n /**\n * The page keys the visitor could go to next, already resolved to the chunk that\n * would render (experiment variant applied). The **renderer** maps these to chunk\n * URLs and emits `<link rel=\"modulepreload\">` (the browser-native, non-executing,\n * SSR-able prefetch — see v0 `HeadlessFunnelRenderer`). The SDK's `load()`-based\n * `prefetch` is the fallback for mounts without a modulepreload manager.\n */\n nextCandidates: string[]\n canGoBack: boolean\n}\n\nconst NavContext = createContext<NavigationState | null>(null)\n\n/** experiment id → the variant this visitor is bucketed into, for the live render. */\nconst ExperimentContext = createContext<Record<string, string>>({})\n\n/**\n * `const variant = useExperiment('welcome-headline')` — the variant key this\n * visitor is assigned in an experiment (`undefined` if not in one). Page-variant\n * swapping is automatic; this is for branching *within* a page or custom logging.\n */\nexport function useExperiment(id: string): string | undefined {\n return useContext(ExperimentContext)[id]\n}\n\n/**\n * Compute the read-only page context for a position in the flow. `total` is the\n * **expected** path length for the visitor's current answers (see\n * {@link expectedPathLength}) — not the raw file count — so progress reaches 100%\n * on whichever branch the funnel actually takes. Clamped so a visitor who jumped\n * past the traced path can't read above 100%.\n */\nfunction pageContextFor(\n currentKey: string,\n slug: string,\n index: number,\n total: number,\n startedAt: number,\n): PageContext {\n const denom = Math.max(total, index + 1)\n return {\n key: currentKey,\n slug,\n index,\n total: denom,\n progressPercentage: denom > 0 ? Math.min(100, Math.round(((index + 1) / denom) * 100)) : 0,\n startedAt,\n }\n}\n\n/**\n * Renders the funnel: shows the current page and drives navigation. `next()`\n * resolves the current page's `next` predicate against the live snapshot\n * (writable namespaces + read-only `context`), falling back to the linear next\n * page in file order (see {@link nextPage}).\n *\n * Auto-emits `funnel.start` on mount and `page.view` on each page change, and\n * keeps `context.page` in sync so predicates and `usePage()` see the live page.\n *\n * Pass a `layout` (a `{ children }` component) for **persistent chrome** — a\n * header, progress bar, background — rendered *inside* the nav context but\n * *outside* the page swap, so it mounts once and never remounts on navigation\n * (and can read `usePage`/`useNavigation`).\n *\n * Must live inside `<FunnelProvider>`.\n */\nexport function FunnelView({\n pages,\n initialKey,\n layout,\n fallback,\n prefetch: prefetchMode = 'auto',\n onNavigate,\n}: {\n pages: RuntimePage[]\n initialKey?: string\n layout?: ComponentType<{ children: ReactNode }>\n /** Shown in the page area while a lazy page's chunk loads (the layout persists around it). */\n fallback?: ReactNode\n /**\n * `'auto'` (default): the SDK warms next-likely chunks by calling `load()`.\n * `'off'`: the **renderer** owns prefetch (via `<link rel=\"modulepreload\">` over\n * `useNavigation().nextCandidates`) — avoids the redundant `load()` execution.\n */\n prefetch?: 'auto' | 'off'\n /**\n * Fires on every page change (incl. the initial page) with the current page key\n * + slug. The **renderer** uses it to sync the URL path (`history.replaceState`,\n * v0-style — funnel back is in-memory, not browser history). Fires for the\n * *resolved* page, so if an entry `guard` bounced a deep-link to the start, the\n * URL gets corrected.\n */\n onNavigate?: (key: string, slug: string) => void\n}): ReactNode {\n const funnel = useFunnel()\n const tracker = useTrackerRef()\n\n // Resolve each page to a renderable component: eager `Component` as-is, or a\n // stable `React.lazy` over `load` (memoized so the lazy element identity is\n // stable across renders → no remount). `loaders` keeps the raw `load` fns for\n // prefetch (dynamic import dedupes, so calling them early just warms the chunk).\n const components = useMemo(() => {\n const map = new Map<string, ComponentType>()\n for (const p of pages) {\n if (p.Component) map.set(p.key, p.Component)\n else if (p.load) {\n const load = p.load\n map.set(p.key, lazy(() => Promise.resolve(load()).then((m) =>\n typeof m === 'function' ? { default: m } : m,\n )))\n }\n }\n return map\n }, [pages])\n const loaders = useMemo(\n () => new Map(pages.filter((p) => p.load).map((p) => [p.key, p.load!])),\n [pages],\n )\n\n // Resolve page-level experiments once for this visitor: which variant of each\n // slot to show, and which variant pages drop out of the linear flow. Stable for\n // the render — the seed is the durable identity, memoized so a later\n // identification can't flip an in-progress visitor's variant.\n const seed = bucketingSeed(funnel.context)\n const experiments = useMemo(\n () => resolveExperiments(pages, funnel.experiments, seed),\n [pages, funnel.experiments, seed],\n )\n const pageByKey = useMemo(() => new Map(pages.map((p) => [p.key, p])), [pages])\n // The effective flow: anchors + standalone pages, in order (losers removed).\n const flowPages = useMemo<RuntimePage[]>(\n () => experiments.activeKeys.map((k) => pageByKey.get(k)!).filter(Boolean),\n [experiments, pageByKey],\n )\n\n // The flow as plain {key, meta} for routing + path-length tracing.\n const flow = useMemo<FlowPage[]>(\n () => flowPages.map((p) => ({ key: p.key, meta: p.meta })),\n [flowPages],\n )\n\n // Resolve the starting page. A deep-link / reload `initialKey` is honored only if\n // the page's entry `guard` passes against the (restored) snapshot — else fall\n // back to the start page. (In-funnel navigation never hits this; routing gated it.)\n const [history, setHistory] = useState<string[]>(() => {\n const start = flowPages[0]?.key\n if (!initialKey || initialKey === start) return [start].filter(Boolean) as string[]\n const target = experiments.slotOf[initialKey] ?? initialKey\n const page = flowPages.find((p) => p.key === target)\n // Effective guard = the page-type default (paywall/upsell need email) AND any\n // explicit meta.guard.\n const guard = entryGuard(page?.meta)\n const ok = page && (!guard || evaluateGate(guard, funnel.snapshot()))\n return [ok ? target : start].filter(Boolean) as string[]\n })\n const currentKey = history[history.length - 1]\n const index = history.length - 1\n const startKey = history[0]\n\n // Expected path length for the visitor's current answers — re-traced per\n // navigation so progress reaches 100% on whichever branch the funnel takes.\n const total = useMemo(\n () => expectedPathLength(flow, startKey, funnel.snapshot()),\n // currentKey in deps: re-trace as each step's answers settle the branch.\n [flow, startKey, currentKey, funnel],\n )\n\n // Keep the read-only context's `page` slice current so predicates + usePage see it.\n const slug = pageByKey.get(currentKey)?.meta?.slug ?? currentKey\n const page = useMemo(\n () => pageContextFor(currentKey, slug, index, total, funnel.context.system.now),\n [currentKey, slug, index, total, funnel.context.system.now],\n )\n // context.page is mutable internal state of the read-only namespace.\n funnel.context.page = page\n\n // funnel.start once, on mount.\n const started = useRef(false)\n useEffect(() => {\n if (started.current) return\n started.current = true\n tracker.track('funnel.start', {})\n }, [tracker])\n\n // page.view on every page change.\n useEffect(() => {\n if (!currentKey) return\n tracker.track('page.view', { pageId: currentKey, pageKey: currentKey, isInitial: index === 0, eventId: newEventId() })\n }, [tracker, currentKey, index])\n\n // Tell the renderer the live page (key + slug) so it can sync the URL path.\n useEffect(() => {\n if (currentKey && onNavigate) onNavigate(currentKey, slug)\n }, [onNavigate, currentKey, slug])\n\n // experiment.exposure the first time the visitor lands on an experiment slot.\n const exposed = useRef<Set<string>>(new Set())\n useEffect(() => {\n const expId = experiments.experimentOf[currentKey]\n if (!expId || exposed.current.has(expId)) return\n exposed.current.add(expId)\n tracker.track('experiment.exposure', { experimentId: expId, variant: experiments.assignments[expId] })\n }, [tracker, currentKey, experiments])\n\n // page.exit timing — wall-clock duration on a page, minus time the tab was\n // hidden (active engagement). Uses a real clock (effects only, never render).\n const timer = useRef<{ key: string; enteredAt: number; hidden: number; hiddenSince: number | null } | null>(null)\n const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now())\n const emitExit = useCallback(() => {\n const t = timer.current\n if (!t) return\n const at = now()\n const hidden = t.hidden + (t.hiddenSince != null ? at - t.hiddenSince : 0)\n const durationMs = Math.round(at - t.enteredAt)\n tracker.track('page.exit', { pageId: t.key, durationMs, activeMs: Math.max(0, Math.round(durationMs - hidden)) })\n }, [tracker])\n\n // Track tab visibility so `activeMs` excludes backgrounded time.\n useEffect(() => {\n if (typeof document === 'undefined') return\n const onVis = () => {\n const t = timer.current\n if (!t) return\n if (document.visibilityState === 'hidden') t.hiddenSince = now()\n else if (t.hiddenSince != null) {\n t.hidden += now() - t.hiddenSince\n t.hiddenSince = null\n }\n }\n document.addEventListener('visibilitychange', onVis)\n return () => document.removeEventListener('visibilitychange', onVis)\n }, [])\n\n // On each page change emit page.exit for the page being left, then start the\n // new page's timer. The final page's exit fires on unmount.\n useEffect(() => {\n if (!currentKey) return\n if (timer.current && timer.current.key !== currentKey) emitExit()\n const hidden = typeof document !== 'undefined' && document.visibilityState === 'hidden'\n timer.current = { key: currentKey, enteredAt: now(), hidden: 0, hiddenSince: hidden ? now() : null }\n }, [currentKey, emitExit])\n\n useEffect(() => () => emitExit(), [emitExit])\n\n const next = useCallback(() => {\n // Route over the effective flow (slots); the slot page's `meta.next` governs\n // routing. Remap any target that points at a collapsed variant key to its slot.\n const target = nextPage(flow, currentKey, funnel.snapshot())\n const resolved = target ? experiments.slotOf[target] ?? target : target\n if (resolved) setHistory((h) => [...h, resolved])\n }, [flow, currentKey, funnel, experiments])\n\n const back = useCallback(\n () => setHistory((h) => (h.length > 1 ? h.slice(0, -1) : h)),\n [],\n )\n const go = useCallback(\n (key: string) => setHistory((h) => [...h, experiments.slotOf[key] ?? key]),\n [experiments],\n )\n\n // Warm a slot's code-split chunk (the variant that would actually render). Idempotent.\n const prefetched = useRef<Set<string>>(new Set())\n const prefetch = useCallback(\n (key: string) => {\n const target = experiments.render[key] ?? key\n const load = loaders.get(target)\n if (!load || prefetched.current.has(target)) return\n prefetched.current.add(target)\n load().catch(() => prefetched.current.delete(target)) // let a failed load retry later\n },\n [loaders, experiments],\n )\n\n // The next-likely pages, resolved to the chunk that would actually render\n // (experiment variant applied) — the renderer modulepreloads these.\n const nextCandidates = useMemo(\n () => [...new Set(outgoingKeys(flow, currentKey).map((k) => experiments.render[k] ?? k))],\n [flow, currentKey, experiments],\n )\n\n // 'auto' mode: warm those chunks by calling load(). 'off': the renderer owns it.\n useEffect(() => {\n if (prefetchMode !== 'auto') return\n for (const key of nextCandidates) prefetch(key)\n }, [prefetchMode, nextCandidates, prefetch])\n\n const value: NavigationState = {\n page,\n next,\n back,\n go,\n prefetch,\n nextCandidates,\n canGoBack: history.length > 1,\n }\n // Render the assigned variant's component at the current slot (the anchor key\n // stays the flow position; only the component swaps). Lazy pages suspend, so the\n // page area shows `fallback` while the chunk loads — inside the layout, so the\n // persistent chrome stays put.\n const renderKey = experiments.render[currentKey] ?? currentKey\n const Current = components.get(renderKey)\n const pageEl = createElement(Suspense, { fallback: fallback ?? null }, Current ? createElement(Current) : null)\n // The layout wraps the page inside NavContext → it persists across navigation\n // (same element type, only the page child swaps) and can use nav/funnel hooks.\n const content = layout ? createElement(layout, null, pageEl) : pageEl\n\n return createElement(\n ExperimentContext.Provider,\n { value: experiments.assignments },\n createElement(NavContext.Provider, { value }, content),\n )\n}\n\n/** `const { next, back, go, page } = useNavigation()`. */\nexport function useNavigation(): NavigationState {\n const ctx = useContext(NavContext)\n if (!ctx) throw new Error('useNavigation must be used inside <FunnelView>')\n return ctx\n}\n\n/** `usePage()` — the current page's read-only context, reactive to navigation. */\nexport function usePage(): PageContext {\n return useNavigation().page\n}\n","/**\n * Imperative, promise-based modal registry — our trimmed adaptation of\n * eBay's `@ebay/nice-modal-react` (MIT). The model: a module-level registry +\n * a reducer-backed store, so any code can `showModal(MyModal)` from anywhere\n * (no prop-drilling, no rendering the modal where you trigger it) and get back a\n * **promise** that resolves when the modal calls `resolve()` — perfect for\n * confirm/upsell/detail flows.\n *\n * Every modal is keyed by a **stable id**, which also makes it natural to bind\n * analytics later (open/close per id, like pages).\n *\n * Pair it with the controlled chrome in {@link ./overlay}: a `defineModal`\n * component renders a `<Sheet open={m.visible} onClose={m.hide}>`/`<Modal>`.\n * The runtime ({@link ./namespaces}.FunnelProvider) mounts {@link ModalRoot} for\n * you, so there's no provider to wire.\n *\n * Trimmed vs upstream: dropped the antd/mui/bootstrap binding adapters and the\n * standalone `<Provider>` (folded into the funnel runtime).\n */\n\nimport {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n type ComponentType,\n type Dispatch,\n type ReactNode,\n} from 'react'\n\n// ── State ────────────────────────────────────────────────\n\nexport interface ModalState {\n id: string\n args?: Record<string, unknown>\n visible?: boolean\n delayVisible?: boolean\n keepMounted?: boolean\n}\nexport interface ModalStore {\n [id: string]: ModalState\n}\ninterface ModalAction {\n type: 'show' | 'hide' | 'remove' | 'set-flags'\n payload: { modalId: string; args?: Record<string, unknown>; flags?: Record<string, unknown> }\n}\ninterface ModalCallbacks {\n [id: string]: { resolve: (v: unknown) => void; reject: (v: unknown) => void; promise: Promise<unknown> }\n}\n\n/** The handle `useModal()` returns to control one modal. */\nexport interface ModalHandler<Props = Record<string, unknown>> {\n id: string\n args?: Record<string, unknown>\n visible: boolean\n keepMounted: boolean\n show: (args?: Props) => Promise<unknown>\n hide: () => Promise<unknown>\n remove: () => void\n /** Resolve the promise returned by `show()` (e.g. a confirm result). */\n resolve: (value?: unknown) => void\n /** Reject the promise returned by `show()`. */\n reject: (value?: unknown) => void\n /** Resolve the promise returned by `hide()` (after a close transition). */\n resolveHide: (value?: unknown) => void\n}\n\n// ── Module-level registry + dispatch ─────────────────────\n\nconst symModalId = Symbol('AppFunnelModalId')\nconst initialState: ModalStore = {}\nconst ModalStateContext = createContext<ModalStore>(initialState)\nconst ModalIdContext = createContext<string | null>(null)\n\nconst REGISTRY: { [id: string]: { comp: ComponentType<any>; props?: Record<string, unknown> } } = {}\nconst ALREADY_MOUNTED: Record<string, boolean> = {}\nconst modalCallbacks: ModalCallbacks = {}\nconst hideCallbacks: ModalCallbacks = {}\n\nlet uid = 0\nconst getUid = () => `_af_modal_${uid++}`\n\nlet dispatch: Dispatch<ModalAction> = () => {\n throw new Error('No modal dispatch — render inside <FunnelProvider> (which mounts the modal runtime).')\n}\n\nexport const modalReducer = (state: ModalStore = initialState, action: ModalAction): ModalStore => {\n const { modalId, args, flags } = action.payload\n switch (action.type) {\n case 'show':\n return {\n ...state,\n [modalId]: {\n ...state[modalId],\n id: modalId,\n args,\n // Mount first, then flip visible on the next effect → enter transition.\n visible: !!ALREADY_MOUNTED[modalId],\n delayVisible: !ALREADY_MOUNTED[modalId],\n },\n }\n case 'hide':\n return state[modalId] ? { ...state, [modalId]: { ...state[modalId], visible: false } } : state\n case 'remove': {\n const next = { ...state }\n delete next[modalId]\n return next\n }\n case 'set-flags':\n return { ...state, [modalId]: { ...state[modalId], ...flags } }\n default:\n return state\n }\n}\n\nfunction idOf(modal: string | ComponentType<any>): string {\n if (typeof modal === 'string') return modal\n const m = modal as ComponentType<any> & { [symModalId]?: string }\n if (!m[symModalId]) m[symModalId] = getUid()\n return m[symModalId] as string\n}\n\n// ── Imperative API (callable from anywhere) ──────────────\n\n/** Register a component as an id-keyed modal so the placeholder can render it. */\nexport function registerModal(id: string, comp: ComponentType<any>, props?: Record<string, unknown>): void {\n if (!REGISTRY[id]) REGISTRY[id] = { comp, props }\n else REGISTRY[id].props = props\n}\n\nexport function unregisterModal(id: string): void {\n delete REGISTRY[id]\n}\n\n/** Show a modal (by component or id). Returns a promise resolved by `resolve()`. */\nexport function showModal<T = unknown>(modal: string | ComponentType<any>, args?: Record<string, unknown>): Promise<T> {\n const id = idOf(modal)\n if (typeof modal !== 'string' && !REGISTRY[id]) registerModal(id, modal)\n dispatch({ type: 'show', payload: { modalId: id, args } })\n if (!modalCallbacks[id]) {\n let res!: (v: unknown) => void\n let rej!: (v: unknown) => void\n const promise = new Promise<unknown>((resolve, reject) => {\n res = resolve\n rej = reject\n })\n modalCallbacks[id] = { resolve: res, reject: rej, promise }\n }\n return modalCallbacks[id].promise as Promise<T>\n}\n\n/** Hide a modal. Returns a promise resolved by `resolveHide()` (post-transition). */\nexport function hideModal<T = unknown>(modal: string | ComponentType<any>): Promise<T> {\n const id = idOf(modal)\n dispatch({ type: 'hide', payload: { modalId: id } })\n delete modalCallbacks[id]\n if (!hideCallbacks[id]) {\n let res!: (v: unknown) => void\n let rej!: (v: unknown) => void\n const promise = new Promise<unknown>((resolve, reject) => {\n res = resolve\n rej = reject\n })\n hideCallbacks[id] = { resolve: res, reject: rej, promise }\n }\n return hideCallbacks[id].promise as Promise<T>\n}\n\n/** Remove a modal from the tree (frees its state; better than just hiding). */\nexport function removeModal(modal: string | ComponentType<any>): void {\n const id = idOf(modal)\n dispatch({ type: 'remove', payload: { modalId: id } })\n delete modalCallbacks[id]\n delete hideCallbacks[id]\n}\n\nfunction setFlags(id: string, flags: Record<string, unknown>): void {\n dispatch({ type: 'set-flags', payload: { modalId: id, flags } })\n}\n\n// ── Hook ─────────────────────────────────────────────────\n\nexport function useModal(): ModalHandler\nexport function useModal(modal: string, args?: Record<string, unknown>): ModalHandler\nexport function useModal<P extends object>(modal: ComponentType<P>, args?: Partial<P>): ModalHandler<P>\nexport function useModal(modal?: string | ComponentType<any>, args?: Record<string, unknown>): ModalHandler {\n const modals = useContext(ModalStateContext)\n const contextId = useContext(ModalIdContext)\n const isComponent = !!modal && typeof modal !== 'string'\n const id = modal ? idOf(modal) : contextId\n if (!id) throw new Error('useModal: no modal id (call inside a defineModal component, or pass an id/component).')\n\n useEffect(() => {\n if (isComponent && !REGISTRY[id]) registerModal(id, modal as ComponentType<any>, args)\n }, [isComponent, id, modal, args])\n\n const info = modals[id]\n const show = useCallback((a?: Record<string, unknown>) => showModal(id, a), [id])\n const hide = useCallback(() => hideModal(id), [id])\n const remove = useCallback(() => removeModal(id), [id])\n const resolve = useCallback((v?: unknown) => {\n modalCallbacks[id]?.resolve(v)\n delete modalCallbacks[id]\n }, [id])\n const reject = useCallback((v?: unknown) => {\n modalCallbacks[id]?.reject(v)\n delete modalCallbacks[id]\n }, [id])\n const resolveHide = useCallback((v?: unknown) => {\n hideCallbacks[id]?.resolve(v)\n delete hideCallbacks[id]\n }, [id])\n\n return useMemo(\n () => ({\n id,\n args: info?.args,\n visible: !!info?.visible,\n keepMounted: !!info?.keepMounted,\n show,\n hide,\n remove,\n resolve,\n reject,\n resolveHide,\n }),\n [id, info?.args, info?.visible, info?.keepMounted, show, hide, remove, resolve, reject, resolveHide],\n )\n}\n\n// ── defineModal (HOC) ────────────────────────────────────\n\nexport interface ModalHocProps {\n id: string\n defaultVisible?: boolean\n keepMounted?: boolean\n}\n\n/**\n * Wrap a component into an id-keyed modal. Inside it, `useModal()` (no args)\n * gives the handle. Render a controlled `<Sheet>`/`<Modal>` with\n * `open={m.visible} onClose={m.hide}`.\n */\nexport function defineModal<P extends object>(Comp: ComponentType<P>): ComponentType<P & ModalHocProps> {\n return function Wrapped({ id, defaultVisible, keepMounted, ...props }: P & ModalHocProps): ReactNode {\n const { args, show } = useModal(id)\n const modals = useContext(ModalStateContext)\n const shouldMount = !!modals[id]\n\n useEffect(() => {\n if (defaultVisible) show()\n ALREADY_MOUNTED[id] = true\n return () => {\n delete ALREADY_MOUNTED[id]\n }\n }, [id, show, defaultVisible])\n\n useEffect(() => {\n if (keepMounted) setFlags(id, { keepMounted: true })\n }, [id, keepMounted])\n\n const delayVisible = modals[id]?.delayVisible\n useEffect(() => {\n if (delayVisible) show(args)\n }, [delayVisible, args, show])\n\n if (!shouldMount) return null\n return createElement(\n ModalIdContext.Provider,\n { value: id },\n createElement(Comp, { ...(props as P), ...args }),\n )\n }\n}\n\n// ── Runtime (mounted by FunnelProvider) ──────────────────\n\n/** Renders every visible registered modal. Mounted once by the funnel runtime. */\nexport function ModalRoot(): ReactNode {\n const modals = useContext(ModalStateContext)\n const toRender = Object.keys(modals)\n .filter((id) => REGISTRY[id])\n .map((id) => ({ id, ...REGISTRY[id] }))\n return createElement(\n 'div',\n { 'data-appfunnel-modal-root': '' },\n ...toRender.map((t) => createElement(t.comp, { key: t.id, id: t.id, ...t.props })),\n )\n}\n\n/**\n * Provides the modal store + sets the module dispatch + renders {@link ModalRoot}.\n * Wrapped around the funnel tree by `FunnelProvider`.\n */\nexport function ModalRuntime({ children }: { children: ReactNode }): ReactNode {\n const [state, localDispatch] = useReducer(modalReducer, initialState)\n dispatch = localDispatch\n return createElement(\n ModalStateContext.Provider,\n { value: state },\n children,\n createElement(ModalRoot, null),\n )\n}\n","/**\n * Raw, **controlled** overlay chrome — `<Sheet>` (a drawer) and `<Modal>` (a\n * centered dialog). Headless and styleable (className/portal/dismiss), the same\n * two-tier contract as `<Choice>`: thin wrappers you restyle or eject.\n *\n * These are the presentation layer. For *imperative*, promise-based modals\n * triggered from anywhere, wrap one in `defineModal` and `showModal(...)`\n * (see {@link ./modals}) — that registry drives these controlled primitives.\n * They're also used directly (no registry) where local state is simpler, e.g.\n * the checkout `sheet` surface.\n *\n * Deliberately minimal: portal to `document.body`, lock body scroll while open,\n * dismiss on Escape / backdrop. No animation engine, no focus-trap dependency.\n */\n\nimport {\n createElement,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { useModal } from './registry'\n\nexport type SheetSide = 'bottom' | 'top' | 'left' | 'right'\n\n/**\n * `<Sheet>`/`<Modal>` bind themselves to the surrounding {@link defineModal} via\n * its context — so inside a modal you write just `<Sheet>…</Sheet>`, with no\n * open/onClose plumbing. They are therefore **only valid inside a `defineModal`**\n * (rendered through `showModal`); used anywhere else `useModal()` throws, which\n * is the correct signal. For an overlay driven by local state, wrap it in a\n * `defineModal` and `showModal` it — that's the one overlay path.\n */\nfunction useModalControl(): { open: boolean; onClose: () => void } {\n const m = useModal()\n return {\n open: m.visible,\n onClose: () => {\n m.hide()\n m.resolveHide()\n if (!m.keepMounted) m.remove()\n },\n }\n}\n\ninterface OverlayCommon {\n className?: string\n backdropClassName?: string\n dismissOnBackdrop?: boolean\n ariaLabel?: string\n children: ReactNode\n}\n\ninterface ShellProps {\n open: boolean\n onClose: () => void\n className?: string\n backdropClassName?: string\n dismissOnBackdrop?: boolean\n ariaLabel?: string\n /** Flexbox alignment of the panel within the viewport. */\n container: Pick<CSSProperties, 'justifyContent' | 'alignItems'>\n /** Panel layout (size + corners per variant). */\n panel: CSSProperties\n children: ReactNode\n}\n\n/** Shared overlay shell: portal, backdrop, scroll-lock, Escape — variant-agnostic. */\nfunction OverlayShell({\n open,\n onClose,\n className,\n backdropClassName,\n dismissOnBackdrop = true,\n ariaLabel,\n container,\n panel,\n children,\n}: ShellProps): ReactNode {\n useEffect(() => {\n if (!open || typeof document === 'undefined') return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n document.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = prev\n document.removeEventListener('keydown', onKey)\n }\n }, [open, onClose])\n\n if (!open || typeof document === 'undefined') return null\n\n const overlay = createElement(\n 'div',\n {\n role: 'dialog',\n 'aria-modal': true,\n 'aria-label': ariaLabel,\n 'data-appfunnel-overlay': '',\n style: { position: 'fixed', inset: 0, zIndex: 1000, display: 'flex', ...container },\n },\n createElement('div', {\n 'data-appfunnel-overlay-backdrop': '',\n className: backdropClassName,\n onClick: dismissOnBackdrop ? onClose : undefined,\n style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)' },\n }),\n createElement(\n 'div',\n { 'data-appfunnel-overlay-panel': '', className, style: { position: 'relative', background: '#fff', ...panel } },\n children,\n ),\n )\n\n return createPortal(overlay, document.body)\n}\n\nexport type SheetProps = OverlayCommon & {\n /** Edge the drawer slides from (default `bottom`). */\n side?: SheetSide\n}\n\nconst SHEET_LAYOUT: Record<SheetSide, { container: ShellProps['container']; panel: CSSProperties }> = {\n bottom: { container: { justifyContent: 'flex-end', alignItems: 'stretch' }, panel: { borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 16, maxHeight: '90vh', overflow: 'auto' } },\n top: { container: { justifyContent: 'flex-start', alignItems: 'stretch' }, panel: { borderBottomLeftRadius: 16, borderBottomRightRadius: 16, padding: 16, maxHeight: '90vh', overflow: 'auto' } },\n left: { container: { justifyContent: 'flex-start', alignItems: 'stretch' }, panel: { height: '100%', width: 'min(420px, 90vw)', padding: 16, overflow: 'auto' } },\n right: { container: { justifyContent: 'flex-end', alignItems: 'stretch' }, panel: { height: '100%', width: 'min(420px, 90vw)', padding: 16, overflow: 'auto' } },\n}\n\n/**\n * An edge-anchored drawer. Inside a `defineModal` it auto-binds — `<Sheet>…`;\n * outside one, control it with `open`/`onClose`.\n */\nexport function Sheet(props: SheetProps): ReactNode {\n const control = useModalControl()\n const layout = SHEET_LAYOUT[props.side ?? 'bottom']\n return createElement(OverlayShell, {\n ...control,\n className: props.className,\n backdropClassName: props.backdropClassName,\n dismissOnBackdrop: props.dismissOnBackdrop,\n ariaLabel: props.ariaLabel,\n container: layout.container,\n panel: layout.panel,\n children: props.children,\n })\n}\n\nexport type ModalProps = OverlayCommon\n\n/** A centered dialog. Auto-binds to its `defineModal` — `<Modal>…`. */\nexport function Modal(props: ModalProps): ReactNode {\n const control = useModalControl()\n return createElement(OverlayShell, {\n ...control,\n className: props.className,\n backdropClassName: props.backdropClassName,\n dismissOnBackdrop: props.dismissOnBackdrop,\n ariaLabel: props.ariaLabel,\n container: { justifyContent: 'center', alignItems: 'center' },\n panel: { borderRadius: 16, padding: 24, width: 'min(480px, 92vw)', maxHeight: '90vh', overflow: 'auto' },\n children: props.children,\n })\n}\n","/**\n * v2 commerce primitives — the two intents from phase-3, made trivial.\n *\n * - `<Checkout product surface>` — the **purchase** primitive. The `surface`\n * prop picks presentation; some surfaces render **inline** (express wallets,\n * inline card, provider iframe), some **open on click** (sheet/popup/redirect).\n * `<Checkout>` covers both: it renders inline surfaces and renders a trigger\n * button for the rest (`asChild` to use your own button).\n * - `<Upsell product>` — the **upsell** primitive. Off-session charge to the\n * saved method, no card re-entry, one tap.\n * - `useCheckout()` — the headless hook under both, always available for a\n * fully-custom CTA.\n *\n * The SDK never talks to a provider. It owns the state machine + the analytics\n * (`checkout.start` / `purchase.complete`) + post-charge navigation, and\n * delegates the actual charge/render to an injected {@link CheckoutDriver}\n * (the real one is platform-side; tests use {@link createMockDriver}).\n *\n * Which product is charged is the author's bound variable, captured at render\n * (inline surfaces) or at `open()` time (trigger surfaces).\n */\n\nimport {\n createContext,\n createElement,\n isValidElement,\n cloneElement,\n useCallback,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { useTrackerRef } from '../tracking/tracking'\nimport { useNavigation } from '../flow/flow'\nimport { Sheet } from '../modals/sheet'\nimport { defineModal, useModal, showModal } from '../modals/registry'\n\n// ── Surfaces, providers, capability matrix ───────────────\n\nexport type CheckoutSurface =\n | 'express' // wallet quick-buttons (Apple/Google Pay) — inline\n | 'element' // inline card form — inline\n | 'embedded' // provider-managed inline checkout — inline\n | 'sheet' // bottom-sheet popup — opens on click\n | 'popup' // provider-hosted overlay — opens on click\n | 'redirect' // provider-hosted page — opens on click\n\nexport type CheckoutProvider = 'stripe' | 'paddle' | 'whop' | 'primer' | 'solidgate'\nexport type CheckoutIntent = 'purchase' | 'upsell'\n\n/** Surfaces that render inline (vs. those that open on click). */\nexport const INLINE_SURFACES: ReadonlySet<CheckoutSurface> = new Set<CheckoutSurface>([\n 'express',\n 'element',\n 'embedded',\n])\n\nexport function isInlineSurface(surface: CheckoutSurface): boolean {\n return INLINE_SURFACES.has(surface)\n}\n\n/**\n * The kind of off-session upsell (researched against Funnelfox's changelog, which\n * ships these as distinct features). The discriminating real-world constraint is\n * **stacking a 2nd concurrent subscription** — Paddle can't, SolidGate/Stripe can.\n */\nexport type UpsellKind =\n | 'subscription' // charge a NEW, 2nd concurrent subscription off-session (stacking)\n | 'one-time' // charge a one-time add-on off-session\n | 'upgrade' // change the existing subscription's plan\n\n/** Reliability of an off-session upsell charge AFTER a purchase on a surface. */\nexport type OffSessionReliability =\n | 'reliable' // we hold the saved method (Stripe Elements / SolidGate / Primer) or the provider charges it (Paddle / Whop API)\n | 'conditional' // possible but may decline — Stripe **managed** checkout: the upsell is a direct off-session charge against Stripe's vaulted card (SCA / setup_future_usage not guaranteed)\n | 'none'\n\nexport interface SurfaceCapability {\n purchase: boolean\n /** Apple/Google Pay available on this surface. */\n wallets: boolean\n /** Reliability of an off-session upsell after a purchase on this surface. */\n offSession: OffSessionReliability\n}\n\nexport interface ProviderProfile {\n /** Merchant-of-Record (handles tax/compliance) vs. a PSP you settle through. */\n isMoR: boolean\n /** Upsell kinds this provider can charge off-session (one-click, no re-entry). */\n offSessionUpsells: UpsellKind[]\n /** Who charges the saved method off-session: you (PSP) or the provider (MoR/managed). */\n tokenModel: 'merchant' | 'provider'\n /** Routes across multiple processors (Primer; SolidGate also offers this) vs. a single acquirer. */\n orchestrator: boolean\n /** Supported surfaces → per-surface capabilities. **Absent = not supported.** */\n surfaces: Partial<Record<CheckoutSurface, SurfaceCapability>>\n}\n\n/** Reliable off-session after this surface (we/the provider hold a chargeable method). */\nconst ON: SurfaceCapability = { purchase: true, wallets: true, offSession: 'reliable' }\n/** Stripe-managed checkout: a purchase works, but the off-session upsell may decline. */\nconst MANAGED: SurfaceCapability = { purchase: true, wallets: true, offSession: 'conditional' }\nconst ALL_UPSELLS: UpsellKind[] = ['subscription', 'one-time', 'upgrade']\n\n/**\n * Provider capabilities (researched 2026-06-23 against provider docs + Funnelfox).\n *\n * Three real-world corrections to the naive model:\n * 1. **Off-session upsell support is per-provider by *kind*** (`offSessionUpsells`):\n * Paddle can't stack a 2nd concurrent subscription (upgrade + one-time only);\n * Stripe/SolidGate/Whop/Primer can do all kinds.\n * 2. **Off-session *reliability* varies by the paywall surface** (`SurfaceCapability.\n * offSession`): Stripe **managed** checkout (`embedded`/`redirect`) upsells as a\n * direct charge against Stripe's vault → `conditional` (may decline); Elements\n * surfaces are `reliable`.\n * 3. **Surface availability is a hard constraint.** MoR/managed providers can't\n * expose a raw card field to your own UI: Paddle has no `express`/`element`/your\n * `sheet`; Whop has no raw `element`/`express`; Primer has no hosted `redirect`;\n * Stripe/SolidGate have no `popup`. A missing entry means \"not possible.\"\n */\nexport const PROVIDER_PROFILES: Record<CheckoutProvider, ProviderProfile> = {\n // PSP; you hold the PaymentMethod and fire your own off-session PaymentIntent on\n // the Elements surfaces (reliable). **Managed** Checkout (`embedded`/`redirect`)\n // upsells too, but as a direct charge against Stripe's vaulted card → conditional.\n // No provider \"popup\" surface.\n stripe: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: false,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: MANAGED, redirect: MANAGED },\n },\n // Merchant-of-Record; card entry is always Paddle's frame → no own element/sheet/\n // express. Off-session via subscription one-time charge / collection_mode, but\n // **no 2nd concurrent subscription** (upgrade + one-time only), provider-initiated.\n paddle: {\n isMoR: true, offSessionUpsells: ['one-time', 'upgrade'], tokenModel: 'provider', orchestrator: false,\n surfaces: { embedded: ON, popup: ON, redirect: ON },\n },\n // Merchant-of-Record; iframe-only (no raw card field). Off-session works\n // (provider-initiated, async via webhooks). `sheet` = our chrome hosting their embed.\n whop: {\n isMoR: true, offSessionUpsells: ALL_UPSELLS, tokenModel: 'provider', orchestrator: false,\n surfaces: { embedded: ON, redirect: ON, sheet: ON },\n },\n // Pure orchestrator (PSP-side); Headless renders express/element/sheet/embedded.\n // No hosted redirect page, no popup checkout. Off-session is PSP-conditional.\n primer: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: true,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: ON },\n },\n // PSP **and** orchestrator (own acquiring + connectors routing across Stripe/Adyen/\n // PayPal). One Payment Form (element/sheet/embedded) + hosted page + wallet button.\n // Strong native off-session (Recurring API). No popup.\n solidgate: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: true,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: ON, redirect: ON },\n },\n}\n\nexport interface ValidationResult {\n ok: boolean\n reason?: string\n /** Non-fatal caveat (e.g. Paddle upgrade-only). */\n note?: string\n}\n\n/** Surfaces a provider supports, for the editor/AI to steer authors. */\nexport function surfacesFor(provider: CheckoutProvider): CheckoutSurface[] {\n return Object.keys(PROVIDER_PROFILES[provider]?.surfaces ?? {}) as CheckoutSurface[]\n}\n\n/** Whether a provider is a Merchant of Record (it owns tax/compliance). */\nexport function isMerchantOfRecord(provider: CheckoutProvider): boolean {\n return PROVIDER_PROFILES[provider]?.isMoR ?? false\n}\n\n/** Whether a provider routes across multiple processors (Primer, SolidGate). */\nexport function isOrchestrator(provider: CheckoutProvider): boolean {\n return PROVIDER_PROFILES[provider]?.orchestrator ?? false\n}\n\n/**\n * Validate a (provider, surface) for a **purchase**: the surface must exist for\n * the provider and accept a payment. Surface availability is the real constraint\n * (e.g. Paddle has no `element`).\n */\nexport function validateCheckout(provider: CheckoutProvider, surface: CheckoutSurface): ValidationResult {\n const cap = PROVIDER_PROFILES[provider]?.surfaces[surface]\n if (!cap) return { ok: false, reason: `${provider} has no '${surface}' surface` }\n return cap.purchase ? { ok: true } : { ok: false, reason: `'${surface}' can't take a purchase on ${provider}` }\n}\n\n/**\n * Validate an **off-session upsell** of `kind` after a purchase made on\n * `paywallSurface`. Combines provider support for the kind (Paddle can't stack a\n * 2nd subscription) with the paywall surface's off-session reliability (Stripe\n * managed checkout is `conditional` — returned as a `note`, not a hard block).\n */\nexport function validateUpsell(\n provider: CheckoutProvider,\n paywallSurface: CheckoutSurface,\n kind: UpsellKind = 'subscription',\n): ValidationResult {\n const profile = PROVIDER_PROFILES[provider]\n if (!profile) return { ok: false, reason: `unknown provider '${provider}'` }\n if (!profile.offSessionUpsells.includes(kind)) {\n const can = profile.offSessionUpsells.length ? ` (it supports: ${profile.offSessionUpsells.join(', ')})` : ''\n return { ok: false, reason: `${provider} can't charge a '${kind}' upsell off-session${can}` }\n }\n const cap = profile.surfaces[paywallSurface]\n if (!cap) return { ok: false, reason: `${provider} has no '${paywallSurface}' surface to upsell after` }\n if (cap.offSession === 'none') {\n return { ok: false, reason: `a purchase on '${paywallSurface}' retains no chargeable method for an upsell` }\n }\n if (cap.offSession === 'conditional') {\n return { ok: true, note: `off-session upsell after ${provider} '${paywallSurface}' (managed checkout) may decline — prefer element/sheet/express` }\n }\n return { ok: true }\n}\n\n// ── Driver seam ──────────────────────────────────────────\n\nexport type CheckoutStatus = 'idle' | 'loading' | 'requires_action' | 'success' | 'error'\n\nexport interface CheckoutRequest {\n product: string\n intent: CheckoutIntent\n surface?: CheckoutSurface\n /** For `upsell` intent — which kind of off-session charge (default `subscription`). */\n kind?: UpsellKind\n}\n\n/**\n * Normalized failure category — the driver/platform maps each provider's decline\n * codes into one of these so funnels can route/recover by reason. `authentication_\n * required` (3DS/SCA) and `requires_payment_method` are the cases an **off-session**\n * upsell can't satisfy → recover on-session (re-collect a card).\n */\nexport type CheckoutErrorCategory =\n | 'card_declined'\n | 'insufficient_funds'\n | 'expired_card'\n | 'authentication_required' // SCA/3DS needed — off-session can't challenge\n | 'requires_payment_method' // no usable saved method\n | 'processing_error'\n | 'canceled'\n | 'unknown'\n\nexport interface CheckoutError {\n category: CheckoutErrorCategory\n message: string\n /** Raw provider decline code, if any (e.g. Stripe `card_declined`/`insufficient_funds`). */\n declineCode?: string\n /** Whether re-attempting (e.g. an on-session re-collection) may succeed. */\n retryable: boolean\n}\n\n/** Build a {@link CheckoutError} (driver/test helper). */\nexport function checkoutError(\n category: CheckoutErrorCategory,\n message: string,\n extra: { declineCode?: string; retryable?: boolean } = {},\n): CheckoutError {\n const retryable = extra.retryable ?? (category === 'authentication_required' || category === 'requires_payment_method' || category === 'processing_error')\n return { category, message, declineCode: extra.declineCode, retryable }\n}\n\nexport interface CheckoutResult {\n ok: boolean\n error?: CheckoutError\n /** Charged amount in minor units (for the purchase event). */\n amountMinor?: number\n currency?: string\n /**\n * The **server-minted** dedup id for the purchase event — the platform creates it\n * when the charge settles and fires CAPI with it; the SDK emits `purchase.complete`\n * with the same id so the browser pixel dedupes against the server. (Server is the\n * source of truth for payment events; the SDK doesn't mint these.)\n */\n eventId?: string\n}\n\nexport interface CheckoutCallbacks {\n onSuccess: (result: CheckoutResult) => void\n onError: (error: CheckoutError) => void\n /**\n * The inline surface reports a valid payment method was entered (e.g. Stripe's\n * Payment Element became `complete`), before the charge. Drives the\n * `checkout.payment_added` analytics step; optional — drivers that can't observe\n * it (or off-session charges) simply never call it.\n */\n onPaymentAdded?: () => void\n}\n\n/**\n * The provider seam. The platform injects the real one (Stripe/Paddle/Whop/…);\n * tests use {@link createMockDriver}.\n *\n * Most providers ship their **own React SDK** (`@stripe/react-stripe-js`,\n * `@paddle/paddle-js`, Primer's React components, …). A driver's `renderInline`\n * returns exactly that: the provider's React element mounted in our chrome (inline,\n * or inside the `<Sheet>`). Those provider SDKs live in the **driver/platform**\n * package, not our core funnel SDK — which is why the driver is injected: the core\n * stays lean and provider-agnostic, and you only pull the SDK for the provider you use.\n */\nexport interface CheckoutDriver {\n provider: CheckoutProvider\n /** Trigger a charge (trigger surfaces + programmatic). Resolves when settled. */\n start(req: CheckoutRequest): Promise<CheckoutResult>\n /** Render an inline surface (e.g. the provider's React payment element); report via callbacks. */\n renderInline?(req: CheckoutRequest, cb: CheckoutCallbacks): ReactNode\n}\n\nexport interface MockDriverOptions {\n /** The result a successful charge resolves with. */\n result?: CheckoutResult\n /** Make **off-session** charges (no surface) fail — to exercise the upsell fallback. */\n failOffSession?: CheckoutError | boolean\n}\n\n/** A console/no-op driver — tests, preview, local dev. Succeeds unless configured to fail. */\nexport function createMockDriver(\n provider: CheckoutProvider = 'stripe',\n options: MockDriverOptions = {},\n): CheckoutDriver {\n const success: CheckoutResult = options.result ?? { ok: true, amountMinor: 0, currency: 'USD' }\n const offError: CheckoutError =\n typeof options.failOffSession === 'object'\n ? options.failOffSession\n : checkoutError('authentication_required', 'off-session charge declined (mock)')\n return {\n provider,\n start: (req) => {\n if (options.failOffSession && !req.surface) return Promise.resolve({ ok: false, error: offError })\n return Promise.resolve(success)\n },\n renderInline: (req, cb) =>\n createElement(\n 'button',\n {\n type: 'button',\n 'data-mock-surface': req.surface,\n onClick: () =>\n success.ok\n ? cb.onSuccess(success)\n : cb.onError(success.error ?? checkoutError('processing_error', 'failed (mock)')),\n },\n `Pay (mock ${req.surface})`,\n ),\n }\n}\n\nconst DriverContext = createContext<CheckoutDriver | null>(null)\n\nexport function CheckoutDriverProvider({\n driver,\n children,\n}: {\n driver: CheckoutDriver\n children: ReactNode\n}): ReactNode {\n return createElement(DriverContext.Provider, { value: driver }, children)\n}\n\nfunction useDriver(): CheckoutDriver {\n return useContext(DriverContext) ?? FALLBACK_DRIVER\n}\nconst FALLBACK_DRIVER = createMockDriver()\n\n// ── The headless hook ────────────────────────────────────\n\nexport interface UseCheckoutOptions {\n intent?: CheckoutIntent\n /** For `upsell` intent — which kind of off-session charge (default `subscription`). */\n kind?: UpsellKind\n /** Advance to the next page after a successful charge (default: true). */\n advanceOnSuccess?: boolean\n onSuccess?: (result: CheckoutResult) => void\n onError?: (error: CheckoutError) => void\n}\n\nexport interface CheckoutHandle {\n /** Start the charge for a product; resolves with the result (no surface = off-session). */\n open: (product: string, surface?: CheckoutSurface) => Promise<CheckoutResult>\n status: CheckoutStatus\n /** The last failure, structured so you can route/recover by `category`. */\n error: CheckoutError | null\n isLoading: boolean\n reset: () => void\n /** Build the callbacks an inline surface reports through (used by `<Checkout>`). */\n callbacksFor: (product: string, surface?: CheckoutSurface) => CheckoutCallbacks & { onStart: () => void }\n}\n\n/**\n * The headless checkout hook. Owns the state machine + analytics + post-charge\n * navigation; delegates the charge to the injected {@link CheckoutDriver}.\n */\nexport function useCheckout(opts: UseCheckoutOptions = {}): CheckoutHandle {\n const driver = useDriver()\n const tracker = useTrackerRef()\n const nav = useNavigation()\n const [status, setStatus] = useState<CheckoutStatus>('idle')\n const [error, setError] = useState<CheckoutError | null>(null)\n\n const intent = opts.intent ?? 'purchase'\n const kind = opts.kind\n const advance = opts.advanceOnSuccess ?? true\n\n const succeed = useCallback(\n (result: CheckoutResult) => {\n setStatus('success')\n tracker.track('purchase.complete', {\n amount: result.amountMinor != null ? result.amountMinor / 100 : undefined,\n currency: result.currency,\n eventId: result.eventId, // server-minted (browser↔CAPI dedup); undefined if none\n })\n opts.onSuccess?.(result)\n if (advance) nav.next()\n },\n [tracker, nav, advance, opts],\n )\n\n const fail = useCallback(\n (err: CheckoutError, product?: string) => {\n // 3DS/SCA that an off-session charge can't satisfy → flag for recovery.\n setStatus(err.category === 'authentication_required' ? 'requires_action' : 'error')\n setError(err)\n tracker.track('checkout.failed', {\n category: err.category,\n declineCode: err.declineCode,\n productId: product,\n intent,\n } as never)\n opts.onError?.(err)\n },\n [tracker, intent, opts],\n )\n\n const begin = useCallback(\n (product: string, surface?: CheckoutSurface) => {\n setStatus('loading')\n setError(null)\n tracker.track('checkout.start', { productId: product, surface } as never)\n },\n [tracker],\n )\n\n const paymentAdded = useCallback(() => tracker.track('checkout.payment_added', {}), [tracker])\n\n const open = useCallback(\n async (product: string, surface?: CheckoutSurface): Promise<CheckoutResult> => {\n begin(product, surface)\n try {\n const result = await driver.start({ product, intent, surface, kind })\n if (result.ok) succeed(result)\n else fail(result.error ?? checkoutError('unknown', 'Checkout failed'), product)\n return result\n } catch (e) {\n const err = checkoutError('processing_error', e instanceof Error ? e.message : 'Checkout failed')\n fail(err, product)\n return { ok: false, error: err }\n }\n },\n [driver, intent, kind, begin, succeed, fail],\n )\n\n const callbacksFor = useCallback(\n (product: string, surface?: CheckoutSurface) => ({\n onStart: () => begin(product, surface),\n onSuccess: (result: CheckoutResult) => succeed(result),\n onError: (err: CheckoutError) => fail(err, product),\n onPaymentAdded: () => paymentAdded(),\n }),\n [begin, succeed, fail, paymentAdded],\n )\n\n const reset = useCallback(() => {\n setStatus('idle')\n setError(null)\n }, [])\n\n return { open, status, error, isLoading: status === 'loading', reset, callbacksFor }\n}\n\n// ── The components ───────────────────────────────────────\n\nexport interface CheckoutProps extends UseCheckoutOptions {\n /** Logical product id (the author's bound selection). */\n product: string\n surface: CheckoutSurface\n /** Render your own trigger element instead of the default button (trigger surfaces). */\n asChild?: boolean\n /** Trigger label / your trigger element. */\n children?: ReactNode\n className?: string\n}\n\n/**\n * The `sheet` surface as a registry modal: our {@link Sheet} hosts the driver's\n * element. It resolves outcomes by invoking the callbacks passed via `showModal`\n * args — closures created in the `<Checkout>` trigger (which lives inside\n * `<FunnelView>`, so they carry navigation). Dismissing the sheet just closes it.\n */\nconst CheckoutSheet = defineModal<{\n product: string\n surface: CheckoutSurface\n intent: CheckoutIntent\n onSuccess: (result: CheckoutResult) => void\n onError: (error: CheckoutError) => void\n}>(({ product, surface, intent, onSuccess, onError }) => {\n const driver = useDriver()\n const modal = useModal()\n if (!driver.renderInline) return null\n return createElement(Sheet, {\n children: driver.renderInline(\n { product, intent, surface },\n {\n onSuccess: (r) => { modal.hide(); onSuccess(r) },\n onError: (e) => { modal.hide(); onError(e) },\n },\n ),\n })\n})\n\n/** Render the default trigger button, or clone the author's `asChild` element. */\nfunction trigger(\n onClick: () => void,\n { asChild, children, className, disabled }: { asChild?: boolean; children?: ReactNode; className?: string; disabled?: boolean },\n): ReactNode {\n if (asChild && isValidElement(children)) {\n const child = children as ReactElement<{ onClick?: () => void }>\n return cloneElement(child, { onClick })\n }\n return createElement('button', { type: 'button', className, disabled, onClick }, children ?? 'Continue')\n}\n\n/**\n * The purchase primitive. Three presentation modes by `surface`:\n * - **inline** (`express`/`element`/`embedded`) — the driver renders the\n * provider UI in place (keyed by product so a selection change remounts it);\n * - **SDK sheet** (`sheet`) — a trigger opens the AppFunnel-owned {@link Sheet}\n * and the driver renders the provider element inside it;\n * - **provider-hosted** (`popup`/`redirect`) — a trigger hands off to the\n * provider's own overlay/page.\n */\nexport function Checkout({\n product,\n surface,\n asChild,\n children,\n className,\n ...options\n}: CheckoutProps): ReactNode {\n const driver = useDriver()\n const checkout = useCheckout(options)\n const intent = options.intent ?? 'purchase'\n\n // Inline: driver renders the mounted UI; keyed by product so changing the\n // selected plan cleanly remounts the surface.\n if (isInlineSurface(surface)) {\n return driver.renderInline\n ? createElement(\n 'div',\n { key: product, className },\n driver.renderInline({ product, intent, surface }, checkout.callbacksFor(product, surface)),\n )\n : null\n }\n\n // SDK sheet: open our overlay (a registry modal) hosting the driver's element.\n if (surface === 'sheet') {\n const cb = checkout.callbacksFor(product, surface)\n const open = () => {\n cb.onStart()\n showModal(CheckoutSheet, { product, surface, intent, onSuccess: cb.onSuccess, onError: cb.onError })\n }\n return trigger(open, { asChild, children, className, disabled: checkout.isLoading })\n }\n\n // Provider-hosted (popup/redirect): trigger hands off to the provider.\n return trigger(() => checkout.open(product, surface), {\n asChild,\n children,\n className,\n disabled: checkout.isLoading,\n })\n}\n\nexport interface UpsellProps extends Omit<UseCheckoutOptions, 'intent'> {\n product: string\n /**\n * If the off-session charge fails, present this surface **on-session** to\n * re-collect a card and charge again — e.g. `fallback=\"sheet\"` opens the\n * payment sheet, `fallback=\"popup\"` the provider overlay. Omit to just report\n * the failure (via `onError` / the `checkout.failed` event).\n */\n fallback?: CheckoutSurface\n asChild?: boolean\n children?: ReactNode\n className?: string\n}\n\n/**\n * The upsell primitive — an off-session, one-tap charge to the saved method (no\n * surface, no card re-entry). On failure, optionally `fallback` to an on-session\n * surface to re-collect and retry.\n */\nexport function Upsell({ product, fallback, asChild, children, className, ...options }: UpsellProps): ReactNode {\n const checkout = useCheckout({ ...options, intent: 'upsell' })\n\n const start = async () => {\n const result = await checkout.open(product) // off-session (no surface)\n if (result.ok || !fallback) return\n // Recover on-session via the fallback surface (re-collect a card).\n const cb = checkout.callbacksFor(product, fallback)\n if (fallback === 'sheet') {\n cb.onStart()\n showModal(CheckoutSheet, { product, surface: 'sheet', intent: 'upsell', onSuccess: cb.onSuccess, onError: cb.onError })\n } else {\n await checkout.open(product, fallback) // hosted on-session re-collect\n }\n }\n\n return trigger(start, {\n asChild,\n children: children ?? 'Add to my plan',\n className,\n disabled: checkout.isLoading,\n })\n}\n","/**\n * Toast — a thin convenience re-export of {@link https://sonner.emilkowal.ski | sonner}.\n *\n * Authors call `toast.success(...)` / `toast.error(...)` anywhere in their funnel.\n * `FunnelProvider` auto-mounts {@link FunnelToaster} (opt out with `toaster={false}`),\n * so toasts work with no setup; render it yourself if you want a custom location.\n *\n * This is the *one* opinionated UI we re-export — kept deliberately thin (just the\n * imperative `toast` + a defaulted `<Toaster>`), because error/info surfacing is a\n * near-universal funnel need and sonner is tiny. Everything else stays headless.\n */\n\nimport { createElement, type ReactNode } from 'react'\nimport { Toaster, type ToasterProps } from 'sonner'\n\nexport { toast } from 'sonner'\nexport type { ToasterProps }\n\n/** Sonner's `<Toaster>` with funnel defaults (top-center); pass any `ToasterProps` to override. */\nexport function FunnelToaster(props: ToasterProps = {}): ReactNode {\n return createElement(Toaster, { position: 'top-center', ...props })\n}\n\n/** Internal: resolve the `FunnelProvider` `toaster` prop to an element (or null). */\nexport function renderToaster(toaster: boolean | ToasterProps): ReactNode {\n if (toaster === false) return null\n return createElement(Toaster, { position: 'top-center', ...(toaster === true ? {} : toaster) })\n}\n","import {\n createContext,\n createElement,\n Fragment,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport type { VariableStore } from './variableStore'\nimport { createFunnelStore, NAMESPACE_PREFIX, type WritableNamespace } from './store'\nimport { buildAcquisition, buildContext, type FunnelContext } from './context'\nimport {\n TrackerProvider,\n createConsoleTracker,\n type Tracker,\n} from '../tracking/tracking'\nimport { attachBus, createBus, withBus, type FunnelBus } from '../tracking/bus'\nimport { CatalogProvider, buildCatalog, type ResolvedProduct, type ProductInput } from '../commerce/catalog'\nimport { CheckoutDriverProvider, createMockDriver, type CheckoutDriver } from '../commerce/checkout'\nimport { ModalRuntime } from '../modals/registry'\nimport { LocaleProvider, type MessageCatalog } from '../i18n/translation'\nimport { renderToaster, type ToasterProps } from '../toast/toast'\nimport type { FunnelDefinition, FunnelSnapshot } from '../flow/spine'\nimport type { RuntimeExperiment } from '../flow/experiments'\nimport type { VariableValue } from '../types'\n\n/**\n * v2 namespace layer over the flat {@link VariableStore}.\n *\n * **The public surface is hooks, not a god object.** Reactive reads use\n * `useState`-shaped tuple hooks (`const [goal, setGoal] = useResponse('goal')`);\n * read-only computed values use `useDevice()`/`useLocale()`/`usePage()`/`useUtm()`.\n * `useFunnel()` returns an **imperative, non-subscribing** handle for use in\n * handlers/effects only — it is not the documented primary API and carries no\n * `sdk` branding.\n *\n * Three writable namespaces (`user`/`responses`/`data`) + the read-only\n * `context`. Entitlements are **not** here — they're the separate app/IdentitySDK.\n *\n * All writes route through {@link Namespace.set}, so persistence + identify fire\n * from one place (the \"magic behind set()\", doc 07 §Layer 1).\n */\n\n// ── Writable namespace view ──────────────────────────────\n\n/** A typed view over one writable namespace's slice of the store. */\nexport class Namespace<\n T extends Record<string, VariableValue> = Record<string, VariableValue>,\n> {\n private readonly dot: string\n\n constructor(\n private readonly store: VariableStore,\n readonly name: WritableNamespace,\n /** Side-effect run after every write (persistence, identify). */\n private readonly onWrite: (ns: WritableNamespace, values: Partial<T>) => void,\n ) {\n this.dot = `${NAMESPACE_PREFIX[name]}.`\n }\n\n /** Fully-qualified store key for a namespace-relative key. */\n storeKey(key: string): string {\n return this.dot + key\n }\n\n /** The store-key prefix this namespace reads/writes (e.g. `user.`). */\n get prefix(): string {\n return this.dot\n }\n\n /** Read the whole namespace as a flat object (prefix stripped). */\n getAll(): T {\n const out: Record<string, VariableValue> = {}\n const all = this.store.getState()\n for (const key in all) {\n if (key.startsWith(this.dot)) out[key.slice(this.dot.length)] = all[key]\n }\n return out as T\n }\n\n /** Read one key, or the whole namespace when called with no argument. */\n get<K extends keyof T & string>(key: K): T[K]\n get(): T\n get(key?: string): VariableValue | T {\n return key === undefined ? this.getAll() : this.store.get(this.storeKey(key))\n }\n\n /** Write one or more keys from a plain object (batched + side-effected). */\n set(values: Partial<T>): void {\n const updates: Record<string, VariableValue> = {}\n for (const key in values) {\n updates[this.storeKey(key)] = values[key] as VariableValue\n }\n this.store.setMany(updates)\n this.onWrite(this.name, values)\n }\n}\n\n// ── The imperative handle ────────────────────────────────\n\n/**\n * The imperative funnel handle (`useFunnel()`). Non-reactive — for event\n * handlers and effects. Reactive render reads go through the hooks instead.\n */\nexport interface Funnel {\n user: Namespace\n responses: Namespace\n data: Namespace\n /** Read-only computed namespace. `page` reflects the latest navigation. */\n readonly context: FunnelContext\n /** Live page-level experiment records (platform/DB-sourced); the runtime buckets visitors into them. */\n readonly experiments: RuntimeExperiment[]\n /** Emit a custom analytics event. */\n track: Tracker['track']\n /** A point-in-time snapshot for predicates (routing/conditions). */\n snapshot(): FunnelSnapshot\n}\n\n/** Build the imperative handle over a store + context + tracker. */\nexport function createFunnel(\n store: VariableStore,\n context: FunnelContext,\n tracker: Tracker,\n experiments: RuntimeExperiment[] = [],\n): Funnel {\n // One write path → one place for the \"magic behind set()\".\n const onWrite = (ns: WritableNamespace, values: Record<string, VariableValue>) => {\n // Identify the moment a non-empty email is written.\n if (ns === 'user' && typeof values.email === 'string' && values.email) {\n tracker.identify(values.email)\n }\n // Push the writable snapshot for debounced persistence.\n tracker.setVariables?.(store.getState())\n }\n\n const user = new Namespace(store, 'user', onWrite)\n const responses = new Namespace(store, 'responses', onWrite)\n const data = new Namespace(store, 'data', onWrite)\n\n return {\n user,\n responses,\n data,\n context,\n experiments,\n track: (event: string, eventData?: never, userData?: Record<string, unknown>) =>\n tracker.track(event, eventData, userData),\n snapshot: () => ({\n user: user.getAll(),\n responses: responses.getAll(),\n data: data.getAll(),\n context,\n }),\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\ninterface FunnelContextValue {\n funnel: Funnel\n store: VariableStore\n context: FunnelContext\n catalog: Map<string, ResolvedProduct>\n driver: CheckoutDriver\n /** Tracker composed with the client bus sink (every track() also hits window.appfunnel). */\n tracker: Tracker\n /** The window.appfunnel event bus (client-side integration surface). */\n bus: FunnelBus\n}\n\nconst FunnelCtx = createContext<FunnelContextValue | null>(null)\n\nexport interface FunnelProviderProps {\n /** Mount from a funnel definition (the normal case). */\n config?: FunnelDefinition\n /** Server / session-restored values overriding declared defaults. */\n sessionValues?: Record<string, VariableValue>\n /** The platform tracker; defaults to a silent console tracker (tests/dev). */\n tracker?: Tracker\n /** Computed-context seed (funnel id, test/live mode, server-hydrated utm/session). */\n context?: Parameters<typeof buildContext>[0]\n /** Products with their provider-resolved price (`{ amount, currency }`). */\n products?: ProductInput[]\n /** Live page-level experiment records, platform/DB-sourced (not authored in funnel code). */\n experiments?: RuntimeExperiment[]\n /** The platform checkout driver; defaults to a mock that resolves successfully. */\n checkout?: CheckoutDriver\n /** Message catalogs per locale (`messages/<locale>.json`) for translation. */\n messages?: MessageCatalog\n /** Explicit locale override (URL/param/geo); wins over the detected device locale. */\n locale?: string\n /** Auto-mount the toast `<Toaster>` (default true). Pass props to customize, or `false` to opt out. */\n toaster?: boolean | ToasterProps\n /** Advanced / testing: supply a pre-built store instead of a `config`. */\n store?: VariableStore\n children: ReactNode\n}\n\n/**\n * Mounts a funnel: builds the writable {@link VariableStore} + the read-only\n * {@link FunnelContext} (once) and provides the runtime to the tree via hooks.\n */\nexport function FunnelProvider({\n config,\n sessionValues,\n tracker,\n context: contextOpts,\n products,\n experiments,\n checkout,\n messages,\n locale: localeOverride,\n toaster = true,\n store,\n children,\n}: FunnelProviderProps): ReactNode {\n const resolvedTracker = tracker ?? FALLBACK_TRACKER\n const [value] = useState<FunnelContextValue>(() => {\n const s =\n store ??\n createFunnelStore(\n { responses: config?.responses, data: config?.data },\n sessionValues,\n )\n const ctx = buildContext({\n funnelId: config?.id,\n ...contextOpts,\n })\n // The client event bus (window.appfunnel), composed into the tracker so every\n // taxonomy event mirrors to it for on-page pixels. Read getters wire to store + context.\n const bus = createBus({\n getVariable: (key) => s.get(key),\n getVariables: () => s.getState(),\n getCurrentPageId: () => ctx.page.key || null,\n getCustomerId: () => ctx.identity.customerId,\n getVisitorId: () => ctx.identity.visitorId,\n })\n const busTracker = withBus(resolvedTracker, bus)\n return {\n funnel: createFunnel(s, ctx, busTracker, experiments ?? []),\n store: s,\n context: ctx,\n catalog: buildCatalog(products ?? []),\n driver: checkout ?? createMockDriver(),\n tracker: busTracker,\n bus,\n }\n })\n // Expose the bus on window.appfunnel for the funnel's lifetime (client-side only).\n useEffect(() => attachBus(value.bus), [value.bus])\n // Forward the acquisition snapshot once on entry → the platform persists it\n // first-class (session + first-touch Customer) + feeds CAPI.\n useEffect(() => {\n value.tracker.setAcquisition?.(buildAcquisition(value.context))\n }, [value])\n const tree = createElement(TrackerProvider, {\n tracker: value.tracker,\n children: createElement(CheckoutDriverProvider, {\n driver: value.driver,\n children: createElement(CatalogProvider, {\n catalog: value.catalog,\n children: createElement(FunnelCtx.Provider, {\n value,\n children: createElement(LocaleProvider, {\n config: config?.locales,\n catalog: messages,\n detected: value.context.locale.locale,\n override: localeOverride,\n children: createElement(ModalRuntime, { children }),\n }),\n }),\n }),\n }),\n })\n return createElement(Fragment, null, tree, renderToaster(toaster))\n}\n\nconst FALLBACK_TRACKER = createConsoleTracker({ silent: true })\n\nfunction useFunnelCtx(): FunnelContextValue {\n const ctx = useContext(FunnelCtx)\n if (!ctx) {\n throw new Error('useFunnel/useResponse/… must be used inside <FunnelProvider>')\n }\n return ctx\n}\n\n/**\n * The imperative handle. Does **not** subscribe — use it in event handlers and\n * effects (`useFunnel().responses.set({...})`). For reactive reads use the hooks.\n */\nexport function useFunnel(): Funnel {\n return useFunnelCtx().funnel\n}\n\n/** Internal: the raw {@link VariableStore} (for reactive condition/field hooks). */\nexport function useFunnelStore(): VariableStore {\n return useFunnelCtx().store\n}\n\n// ── Reactive field hooks ─────────────────────────────────\n\n/** Subscribe to a single flat store key; returns its reactive value. */\nfunction useStoreKey(store: VariableStore, key: string): VariableValue {\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(cb, { keys: [key] }),\n [store, key],\n )\n const getSnapshot = useCallback(() => store.get(key), [store, key])\n // Snapshot is the primitive value → stable by value, no caching needed.\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n\n/** Build a `useState`-shaped tuple hook bound to one writable namespace. */\nfunction makeFieldHook(ns: WritableNamespace) {\n return function useNamespaceField(\n key: string,\n ): [VariableValue, (value: VariableValue) => void] {\n const { funnel, store } = useFunnelCtx()\n const value = useStoreKey(store, `${NAMESPACE_PREFIX[ns]}.${key}`)\n const set = useCallback(\n (v: VariableValue) => funnel[ns].set({ [key]: v }),\n [funnel, key],\n )\n return [value, set]\n }\n}\n\n/**\n * `const [goal, setGoal] = useResponse('goal')` — one funnel answer,\n * `useState`-shaped and per-key reactive. Writing persists + (later) feeds\n * analytics aggregation.\n */\nexport const useResponse = makeFieldHook('responses')\n\n/**\n * `const [height, setHeight] = useUserAttribute('height')` — any field on the\n * user. The platform routes known fields → typed column, custom → attribute;\n * the author doesn't specify which. Writing `email` also identifies the visitor.\n */\nexport const useUserAttribute = makeFieldHook('user')\n\n/**\n * `const [score, setScore] = useData('score')` — working/scratch state. Persisted\n * (survives reload/return) but kept out of `responses` aggregation.\n */\nexport const useData = makeFieldHook('data')\n\n/**\n * The headless field hook — `useField('responses.goal')` — the building block\n * the styleable components (`<Choice>`) wrap. Takes a namespaced path and\n * returns `{ value, set }`. Accepts only writable namespaces.\n */\nexport function useField(path: string): {\n value: VariableValue\n set: (value: VariableValue) => void\n} {\n const dot = path.indexOf('.')\n const ns = path.slice(0, dot) as WritableNamespace\n const key = path.slice(dot + 1)\n const { funnel, store } = useFunnelCtx()\n if (!(ns in NAMESPACE_PREFIX)) {\n throw new Error(`useField: \"${path}\" is not a writable namespace (user/responses/data)`)\n }\n const value = useStoreKey(store, `${NAMESPACE_PREFIX[ns]}.${key}`)\n const set = useCallback(\n (v: VariableValue) => funnel[ns].set({ [key]: v }),\n [funnel, ns, key],\n )\n return { value, set }\n}\n\n// ── Read-only context hooks ──────────────────────────────\n\n/** The whole read-only computed namespace (non-reactive except `page`). */\nfunction useContextObject(): FunnelContext {\n return useFunnelCtx().context\n}\n\n/** `useDevice()` — viewport, device type, pixel ratio (read-only). */\nexport function useDevice(): FunnelContext['device'] {\n return useContextObject().device\n}\n\n/** `useLocale()` — resolved locale/language/region/timezone (read-only). */\nexport function useLocale(): FunnelContext['locale'] {\n return useContextObject().locale\n}\n\n/** `useUtm()` — the 5 utm params captured on entry (read-only). */\nexport function useUtm(): FunnelContext['utm'] {\n return useContextObject().utm\n}\n\n/** `useClickIds()` — per-network ad click-ids captured on entry (read-only). */\nexport function useClickIds(): FunnelContext['clickIds'] {\n return useContextObject().clickIds\n}\n\n/** `useSystem()` — funnel id, test/live mode, build clock (read-only). */\nexport function useSystem(): FunnelContext['system'] {\n return useContextObject().system\n}\n\n/** Read a dotted path out of context, e.g. `useContextValue('device.isMobile')`. */\nexport function useContextValue(path: string): unknown {\n const ctx = useContextObject()\n return useMemo(\n () => path.split('.').reduce<unknown>((acc, k) => (acc as Record<string, unknown>)?.[k], ctx),\n [ctx, path],\n )\n}\n","import {\n createElement,\n type ButtonHTMLAttributes,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react'\nimport { useField } from '../state/namespaces'\nimport { useNavigation } from './flow'\n\n/**\n * The two-tier component model (doc 07 §\"magic ≠ black box\"): the magic lives in\n * headless hooks (`useField`, `useNavigation`); these styleable components are\n * thin, restyle-able wrappers over them. Every `<Choice>` reduces to `useField`\n * + your own JSX — eject any time. They pass `className`/DOM props straight\n * through and never dictate a pixel beyond the minimum.\n */\n\nexport interface ChoiceOption {\n value: string\n label?: ReactNode\n}\n\nexport interface ChoiceProps {\n /** Writable namespaced path to bind, e.g. `responses.goal`. */\n bind: string\n /** The selectable options (a bare string is shorthand for `{value, label}`). */\n options: (string | ChoiceOption)[]\n /** Class applied to each option button. */\n className?: string\n /** Class applied to the selected option button (in addition to `className`). */\n selectedClassName?: string\n /** Advance navigation after a choice (handy for single-tap question pages). */\n advanceOnSelect?: boolean\n}\n\n/**\n * Single-select bound to a writable field. `<Choice bind=\"responses.goal\"\n * options={[\"lose\", \"gain\"]} />` — selecting persists + (later) tracks; pass\n * `advanceOnSelect` to move to the next page on tap.\n */\nexport function Choice({\n bind,\n options,\n className,\n selectedClassName,\n advanceOnSelect,\n}: ChoiceProps): ReactNode {\n const { value, set } = useField(bind)\n const nav = useNavigation()\n\n return options.map((opt) => {\n const o: ChoiceOption = typeof opt === 'string' ? { value: opt } : opt\n const selected = value === o.value\n return createElement(\n 'button',\n {\n key: o.value,\n type: 'button',\n 'aria-pressed': selected,\n 'data-selected': selected || undefined,\n className: selected && selectedClassName ? `${className ?? ''} ${selectedClassName}`.trim() : className,\n onClick: () => {\n set(o.value)\n if (advanceOnSelect) nav.next()\n },\n },\n o.label ?? o.value,\n )\n })\n}\n\nexport interface NextProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n children?: ReactNode\n}\n\n/** A button that advances the funnel (the current page's `next`, else linear). */\nexport function Next({ children, onClick, ...rest }: NextProps): ReactNode {\n const { next } = useNavigation()\n return createElement(\n 'button',\n {\n type: 'button',\n ...rest,\n onClick: (e: ReactMouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (!e.defaultPrevented) next()\n },\n },\n children ?? 'Continue',\n )\n}\n\nexport interface BackProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n children?: ReactNode\n}\n\n/** A button that returns to the previous page; hidden when there's no history. */\nexport function Back({ children, onClick, ...rest }: BackProps): ReactNode {\n const { back, canGoBack } = useNavigation()\n if (!canGoBack) return null\n return createElement(\n 'button',\n {\n type: 'button',\n ...rest,\n onClick: (e: ReactMouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (!e.defaultPrevented) back()\n },\n },\n children ?? 'Back',\n )\n}\n","/**\n * The **event catalog** — the single source of truth for *which* events exist and\n * how each is routed (analytics vs. integrations vs. runtime-only). Pairs with the\n * typed payloads in {@link ./tracking}.`FunnelEventDataMap`.\n *\n * This replaces the duplication the monorepo flags (`shared/events/catalog.ts` is\n * \"documentation, not imported\" — the taxonomy is re-declared in\n * `admin/lib/funnel/tracking.ts`, each `admin/lib/integrations/*` EVENT_MAP, and\n * `api/src/integrations/constants`). In v2 the **SDK owns the taxonomy** (it emits\n * it), so the bus, the pixel loaders, and the platform all import *this*.\n */\n\nexport type EventSource = 'frontend' | 'backend'\n\nexport interface EventMeta {\n /** Where the event originates. `backend` = the server emits it (e.g. a settled charge). */\n sources: EventSource[]\n /** Persisted to analytics. */\n tracking: boolean\n /** Forwarded to ad/integration pixels (Meta/GTM/TikTok/…). */\n integrations: boolean\n /** Runtime-only JS subscription — not persisted, not sent to integrations. */\n runtime?: boolean\n}\n\n/**\n * Every event the system knows, with its routing metadata. Keys are the taxonomy\n * names (a superset of `FunnelEventDataMap`: it also lists the **backend-originated**\n * monetary events the platform pushes to the client bus for pixel firing).\n */\nexport const EVENT_CATALOG = {\n // ── Runtime / navigation (JS subscriptions; not persisted) ──\n 'funnel.start': { sources: ['frontend'], tracking: false, integrations: false, runtime: true },\n 'experiment.exposure': { sources: ['frontend'], tracking: true, integrations: false },\n\n // ── Frontend, tracked; some also go to pixels ──\n 'page.view': { sources: ['frontend'], tracking: true, integrations: true },\n 'page.exit': { sources: ['frontend'], tracking: true, integrations: false },\n 'user.registered': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.start': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.payment_added': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.failed': { sources: ['frontend'], tracking: true, integrations: false },\n\n // ── Backend-originated money events (server mints the eventId; client fires the pixel) ──\n 'purchase.complete': { sources: ['backend'], tracking: true, integrations: true },\n 'customer.first_purchase': { sources: ['backend'], tracking: true, integrations: true },\n 'subscription.created': { sources: ['backend'], tracking: true, integrations: true },\n 'subscription.renewal': { sources: ['backend'], tracking: true, integrations: true },\n} as const satisfies Record<string, EventMeta>\n\n/** A catalog event name. */\nexport type CatalogEvent = keyof typeof EVENT_CATALOG\n\n/** True if the event is persisted to analytics. */\nexport function isTrackableEvent(name: string): boolean {\n return EVENT_CATALOG[name as CatalogEvent]?.tracking ?? false\n}\n\n/** True if the event is forwarded to ad/integration pixels. */\nexport function isIntegrationEvent(name: string): boolean {\n return EVENT_CATALOG[name as CatalogEvent]?.integrations ?? false\n}\n\n/** The events that feed integrations — the set a pixel loader subscribes to. */\nexport function integrationEvents(): CatalogEvent[] {\n return (Object.keys(EVENT_CATALOG) as CatalogEvent[]).filter((e) => EVENT_CATALOG[e].integrations)\n}\n","/**\n * `<Script>` — the **declared third-party embed** primitive (phase-2 §2.3d).\n *\n * The controlled escape hatch for runtime widgets/embeds that genuinely need\n * client code — Intercom, Trustpilot, a calendar embed, an operator pixel. Unlike\n * arbitrary `<script>` injection, it's **declared** (the funnel author writes\n * `<Script src=…/>`), **deduped** (injected at most once per id/src, even across\n * page navigation in the SPA — a chat widget must not reload on every page), and\n * **CSP-friendly** (accepts a `nonce`).\n *\n * CSP enforcement itself is the **renderer's** job: it scans the funnel's declared\n * `<Script src>`s (build-time) into the `script-src` allowlist and supplies the\n * `nonce`. This component just injects the tag at the right time.\n *\n * For *analytics* pixels, prefer subscribing to the `window.appfunnel` bus\n * ({@link ../tracking/bus}) — `<Script>` is for non-analytics third-party widgets\n * (and the pixel loader snippets, which then subscribe to the bus).\n */\n\nimport { useEffect } from 'react'\n\n/** Module-level registry so a given script injects once for the app's lifetime. */\nconst injected = new Set<string>()\n\nexport interface ScriptProps {\n /** The third-party script URL. */\n src: string\n /**\n * When to inject. `afterInteractive` (default) injects on mount (after hydration);\n * `lazyOnload` waits for idle/`load` so it never competes with the funnel's own JS.\n */\n strategy?: 'afterInteractive' | 'lazyOnload'\n /** Dedup key (defaults to `src`) — the script injects at most once per id. */\n id?: string\n /** Defaults to `true`. */\n async?: boolean\n defer?: boolean\n /** CSP nonce — supplied by the renderer. */\n nonce?: string\n /** Extra attributes (e.g. `data-*`). */\n attributes?: Record<string, string>\n onLoad?: () => void\n onError?: () => void\n}\n\n/**\n * Injects a third-party script once. Renders nothing. Persists across navigation\n * (the tag is never removed on unmount — third-party widgets should stay loaded).\n */\nexport function Script({\n src,\n strategy = 'afterInteractive',\n id,\n async = true,\n defer,\n nonce,\n attributes,\n onLoad,\n onError,\n}: ScriptProps): null {\n useEffect(() => {\n if (typeof document === 'undefined') return\n const key = id ?? src\n if (injected.has(key)) {\n onLoad?.() // already present from an earlier mount\n return\n }\n\n const inject = () => {\n if (injected.has(key)) return\n injected.add(key)\n const el = document.createElement('script')\n el.src = src\n if (id) el.id = id\n if (async) el.async = true\n if (defer) el.defer = true\n if (nonce) el.nonce = nonce\n if (attributes) for (const [k, v] of Object.entries(attributes)) el.setAttribute(k, v)\n el.addEventListener('load', () => onLoad?.())\n el.addEventListener('error', () => {\n injected.delete(key) // allow a later retry\n onError?.()\n })\n document.head.appendChild(el)\n }\n\n if (strategy === 'lazyOnload') {\n const ric = (window as unknown as { requestIdleCallback?: (cb: () => void) => number })\n .requestIdleCallback\n if (ric) {\n ric(inject)\n } else {\n const t = setTimeout(inject, 0)\n return () => clearTimeout(t)\n }\n return\n }\n inject()\n // src/id identify the script; injection is idempotent via the registry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [src, id])\n\n return null\n}\n\n/** Internal: clear the injected-script registry (tests only). */\nexport function __resetScriptRegistry(): void {\n injected.clear()\n}\n","/**\n * The **manifest** — the declarative IR a funnel project compiles to (doc 06).\n * It's the machine-readable artifact the platform operates on without executing\n * the funnel: the dashboard draws the flow graph from it, analytics binds to its\n * **stable ids**, validation runs against it, and the renderer reads it to resolve\n * routing.\n *\n * `compileManifest` evaluates the spine (the funnel config + each page's co-located\n * `meta`) into that IR. It's pure — no I/O — so it unit-tests trivially. **It runs\n * server-side**, as the IR step of the publish build over the canonical files in our\n * storage (R2). The client/CLI never produces the authoritative manifest — R2 is the\n * source of truth, the server compiles. (A local dev preview may run it for itself,\n * but that output is never published.)\n *\n * Edge model mirrors the runtime ({@link ../flow/spine}.`nextPage`): a page's\n * `meta.next` routes become **branch** edges (with a serialized condition — a\n * declarative {@link Condition}, or an opaque marker for a code predicate), and the\n * implicit file-order fall-through becomes a **linear** edge (unless an\n * unconditional route already covers it, or the page is a `finish`).\n *\n * Experiments are **not** compiled here. A variant page is recognised structurally\n * by the `@` in its key (`welcome@b`) and tagged `variantOf` + collapsed out of the\n * linear flow; the experiment *wiring* (labels/weights/status) is operational data\n * the platform owns and overlays at render time, not part of the funnel build.\n *\n * Stable ids: the page **key** is the source anchor, so `id === key` here. The\n * durable analytics id is the semantic page name (a slot survives a winner being\n * promoted into it); transient `@variant` pages only ever key analytics by\n * `(experimentId, variant)` in immutable results — a platform concern.\n */\n\nimport type {\n Condition,\n FunnelDefinition,\n FunnelLocales,\n Gate,\n PageMeta,\n PageType,\n} from '../flow/spine'\nimport { isVariantKey, parseSlotKey } from '../flow/experiments'\n\nexport interface ManifestPage {\n id: string\n key: string\n type: PageType\n slug: string\n index: number\n /**\n * Set on a variant page (`welcome@b`) to its **slot** (`welcome`) — a structural\n * marker that this node is an off-flow alternate, not a linear step. The\n * experiment *wiring* (label/weight/id) is operational data the platform owns,\n * not the manifest.\n */\n variantOf?: string\n}\n\nexport type EdgeCondition =\n | { kind: 'declarative'; condition: Condition }\n /** A code predicate — opaque body; `label` may be supplied later by AST parsing. */\n | { kind: 'predicate'; label?: string }\n\nexport interface ManifestEdge {\n from: string\n to: string\n kind: 'branch' | 'linear'\n /** Absent = unconditional (a fallback route, or the linear fall-through). */\n condition?: EdgeCondition\n}\n\nexport interface ManifestValidation {\n ok: boolean\n /** Page ids you can't proceed from (and that aren't a `finish`). */\n deadEnds: string[]\n /** Page ids not reachable from the start. */\n unreachable: string[]\n /** Routes whose target page key doesn't exist. */\n badTargets: { from: string; to: string }[]\n /** True if the funnel never writes `user.email` (the mandatory identity step). */\n missingEmailCapture: boolean\n}\n\nexport interface FunnelManifest {\n id: string\n pages: ManifestPage[]\n flow: { start: string | null; nodes: string[]; edges: ManifestEdge[] }\n products: string[]\n locales?: FunnelLocales\n validation: ManifestValidation\n}\n\nexport interface CompileInput {\n funnel: FunnelDefinition\n /** Pages in file order (the default flow); `meta` holds type/slug/next. */\n pages: { key: string; meta?: PageMeta }[]\n}\n\n/**\n * A **variant** node — a page filed with an `@variant` key (e.g. `welcome@b`).\n * It's an alternate of its slot, not a step in the linear spine, so it gets no\n * linear edge and is excluded from dead-end/reachability checks (the runtime\n * resolves it by bucketing, not by an edge). The `@` is the only source-side\n * signal; the experiment wiring is the platform's operational data. The slot's\n * control (no `@`) stays the flow node. Mirrors {@link resolveExperiments}.\n */\nfunction isVariantNode(page: { key: string }): boolean {\n return isVariantKey(page.key)\n}\n\n/** Serialize a route gate for the manifest (declarative → data; predicate → opaque). */\nfunction serializeGate(when: Gate | undefined): EdgeCondition | undefined {\n if (!when) return undefined\n if (typeof when === 'function') return { kind: 'predicate' }\n return { kind: 'declarative', condition: when }\n}\n\n/** Compile a funnel's spine into its declarative {@link FunnelManifest} IR. */\nexport function compileManifest(input: CompileInput): FunnelManifest {\n const { funnel, pages } = input\n const keys = new Set(pages.map((p) => p.key))\n\n const manifestPages: ManifestPage[] = pages.map((p, index) => ({\n id: p.key,\n key: p.key,\n type: p.meta?.type ?? 'default',\n slug: p.meta?.slug ?? p.key,\n index,\n variantOf: isVariantKey(p.key) ? parseSlotKey(p.key).slot : undefined,\n }))\n\n const edges: ManifestEdge[] = []\n const badTargets: { from: string; to: string }[] = []\n\n // The next page in file order that is a real flow node (skip `@variant` siblings).\n const nextAnchor = (from: number) => {\n for (let j = from + 1; j < pages.length; j++) {\n if (!isVariantNode(pages[j])) return pages[j]\n }\n return undefined\n }\n\n pages.forEach((p, i) => {\n // Variant nodes are alternates of their slot, resolved at runtime by bucketing\n // — they carry no flow edges (routing lives on the slot's control/anchor).\n if (isVariantNode(p)) return\n\n const routes = p.meta?.next ?? []\n let hasUnconditional = false\n for (const route of routes) {\n if (!keys.has(route.to)) {\n badTargets.push({ from: p.key, to: route.to })\n continue\n }\n edges.push({ from: p.key, to: route.to, kind: 'branch', condition: serializeGate(route.when) })\n if (!route.when) hasUnconditional = true\n }\n // Linear fall-through, unless an unconditional route already covers it,\n // this is a `finish` page, or there is no next page.\n const next = nextAnchor(i)\n if (!hasUnconditional && next && p.meta?.type !== 'finish') {\n edges.push({ from: p.key, to: next.key, kind: 'linear' })\n }\n })\n\n // The start is the first real flow node (a leading variant can't be the entry).\n const startPage = pages.find((p) => !isVariantNode(p))\n const start = startPage?.key ?? null\n const variantKeys = new Set(pages.filter(isVariantNode).map((p) => p.key))\n const validation = validate(manifestPages, edges, badTargets, start, variantKeys)\n\n return {\n id: funnel.id,\n pages: manifestPages,\n flow: { start, nodes: manifestPages.map((p) => p.id), edges },\n products: funnel.products ?? [],\n locales: funnel.locales,\n validation,\n }\n}\n\nfunction validate(\n pages: ManifestPage[],\n edges: ManifestEdge[],\n badTargets: { from: string; to: string }[],\n start: string | null,\n variantKeys: Set<string>,\n): ManifestValidation {\n const outgoing = new Map<string, number>()\n for (const e of edges) outgoing.set(e.from, (outgoing.get(e.from) ?? 0) + 1)\n\n // Variant nodes are resolved by bucketing, not edges — they're neither dead\n // ends nor unreachable in the flow-graph sense, so exclude them from both.\n const deadEnds = pages\n .filter((p) => p.type !== 'finish' && !variantKeys.has(p.id) && !(outgoing.get(p.id)! > 0))\n .map((p) => p.id)\n\n // Reachability from the start over the edge set.\n const reachable = new Set<string>()\n if (start) {\n const adj = new Map<string, string[]>()\n for (const e of edges) {\n const list = adj.get(e.from)\n if (list) list.push(e.to)\n else adj.set(e.from, [e.to])\n }\n const stack = [start]\n while (stack.length) {\n const id = stack.pop()!\n if (reachable.has(id)) continue\n reachable.add(id)\n for (const to of adj.get(id) ?? []) stack.push(to)\n }\n }\n const unreachable = pages\n .filter((p) => !variantKeys.has(p.id) && !reachable.has(p.id))\n .map((p) => p.id)\n\n // The funnel must capture user.email somewhere (doc 06). We can see the typed\n // `email-capture` page; deeper detection (any user.email write) is a build-time\n // AST concern. Treat presence of an `email-capture` page as satisfying it.\n const missingEmailCapture = !pages.some((p) => p.type === 'email-capture')\n\n return {\n ok: deadEnds.length === 0 && unreachable.length === 0 && badTargets.length === 0 && !missingEmailCapture,\n deadEnds,\n unreachable,\n badTargets,\n missingEmailCapture,\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/state/variableStore.ts","../src/state/store.ts","../src/state/context.ts","../src/tracking/tracking.ts","../src/tracking/bus.ts","../src/i18n/translation.ts","../src/commerce/catalog.ts","../src/flow/spine.ts","../src/flow/experiments.ts","../src/flow/flow.tsx","../src/modals/registry.tsx","../src/modals/sheet.tsx","../src/commerce/checkout.tsx","../src/toast/toast.tsx","../src/state/namespaces.ts","../src/flow/components.tsx","../src/tracking/catalog.ts","../src/embed/script.tsx","../src/manifest/manifest.ts"],"names":["base","createContext","createElement","useContext","useCallback","useState","useMemo","lazy","page","useRef","useEffect","useTransition","Suspense","useReducer","createPortal","isValidElement","cloneElement","Toaster","Fragment","useSyncExternalStore"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { VariableValue } from '../types'\n\n/**\n * External variable store for funnel variables — the flat, reactive key/value\n * store under the v2 namespaces. Components subscribe selectively via\n * `useSyncExternalStore`, so only components depending on changed keys re-render.\n * (Seeding lives in {@link ./store}.`createFunnelStore`.)\n */\ninterface ScopedListener {\n listener: () => void\n /** Exact keys to watch, or null for all changes */\n keys: string[] | null\n /** Prefix to watch (e.g. 'answers.'), or null for all */\n prefix: string | null\n}\n\nexport class VariableStore {\n private state: Record<string, VariableValue>\n private listeners = new Set<ScopedListener>()\n /** Tracks which keys changed in the last mutation — used by scoped notify */\n private changedKeys: string[] = []\n\n constructor(initial: Record<string, VariableValue>) {\n this.state = { ...initial }\n }\n\n getState(): Record<string, VariableValue> {\n return this.state\n }\n\n get(key: string): VariableValue {\n return this.state[key]\n }\n\n set(key: string, value: VariableValue): void {\n if (this.state[key] === value) return\n this.state = { ...this.state, [key]: value }\n this.changedKeys = [key]\n this.notify()\n }\n\n setState(updater: (prev: Record<string, VariableValue>) => Record<string, VariableValue>): void {\n const prev = this.state\n const next = updater(prev)\n if (next === prev) return\n this.state = next\n // Compute changed keys\n this.changedKeys = []\n for (const key of Object.keys(next)) {\n if (next[key] !== prev[key]) this.changedKeys.push(key)\n }\n for (const key of Object.keys(prev)) {\n if (!(key in next) && prev[key] !== undefined) this.changedKeys.push(key)\n }\n this.notify()\n }\n\n /** Batch set multiple variables at once */\n setMany(updates: Record<string, VariableValue>): void {\n const changed: string[] = []\n const next = { ...this.state }\n for (const [key, value] of Object.entries(updates)) {\n if (next[key] !== value) {\n next[key] = value\n changed.push(key)\n }\n }\n if (changed.length === 0) return\n this.state = next\n this.changedKeys = changed\n this.notify()\n }\n\n /**\n * Subscribe to store changes.\n *\n * @param listener - callback fired when relevant keys change\n * @param scope - optional scope to limit notifications:\n * - `{ keys: ['data.x', 'user.email'] }` — only fire when these exact keys change\n * - `{ prefix: 'answers.' }` — only fire when any key starting with this prefix changes\n * - omit or `{}` — fire on every change (global listener)\n */\n subscribe(\n listener: () => void,\n scope?: { keys?: string[]; prefix?: string },\n ): () => void {\n const entry: ScopedListener = {\n listener,\n keys: scope?.keys || null,\n prefix: scope?.prefix || null,\n }\n this.listeners.add(entry)\n return () => this.listeners.delete(entry)\n }\n\n private notify(): void {\n const changed = this.changedKeys\n for (const entry of this.listeners) {\n // Global listener — no scope\n if (!entry.keys && !entry.prefix) {\n entry.listener()\n continue\n }\n // Key-scoped listener\n if (entry.keys) {\n if (changed.some((k) => entry.keys!.includes(k))) {\n entry.listener()\n }\n continue\n }\n // Prefix-scoped listener\n if (entry.prefix) {\n if (changed.some((k) => k.startsWith(entry.prefix!))) {\n entry.listener()\n }\n }\n }\n }\n}\n","/**\n * v2 store seeding — builds a {@link VariableStore} holding only the **writable**\n * namespaces (`user` / `responses` / `data`), each persisted to the backend.\n *\n * Seeds the {@link VariableStore} with v2 prefixes (no legacy `answers.`/`query.`\n * aliasing). Read-only computed values do NOT live\n * here — see {@link ./context}. Three deliberate namespaces:\n *\n * - `user.*` persistent identity attributes (cross-session)\n * - `responses.*` the clean, aggregated funnel answers\n * - `data.*` working/scratch state — persisted (so reload + return survive)\n * but kept separate from responses so analytics aggregates only\n * real answers and `data` can hold intermediate garbage\n */\n\nimport type { VariableValue, VariableConfig } from '../types'\nimport { VariableStore } from './variableStore'\n\n/** v2 namespace → store-key prefix (sans trailing dot). 1:1, no legacy aliasing. */\nexport const NAMESPACE_PREFIX = {\n user: 'user',\n responses: 'responses',\n data: 'data',\n} as const\n\nexport type WritableNamespace = keyof typeof NAMESPACE_PREFIX\n\n/** Built-in user attributes — always present so reads never `undefined`. */\nconst BUILTIN_USER: Record<string, VariableValue> = {\n 'user.email': '',\n 'user.name': '',\n}\n\nexport interface FunnelStoreConfig {\n responses?: Record<string, VariableConfig>\n data?: Record<string, VariableConfig>\n}\n\nfunction defaultFor(type: string): VariableValue {\n switch (type) {\n case 'string': return ''\n case 'number': return 0\n case 'boolean': return false\n case 'stringArray': return []\n default: return ''\n }\n}\n\n/**\n * Seed a store from a funnel's declared `responses`/`data` defaults, then layer\n * server / session-restored values on top (highest priority).\n */\nexport function createFunnelStore(\n config: FunnelStoreConfig = {},\n sessionValues?: Record<string, VariableValue>,\n): VariableStore {\n const initial: Record<string, VariableValue> = { ...BUILTIN_USER }\n\n for (const [key, cfg] of Object.entries(config.responses ?? {})) {\n initial[`responses.${key}`] = cfg.default ?? defaultFor(cfg.type)\n }\n for (const [key, cfg] of Object.entries(config.data ?? {})) {\n initial[`data.${key}`] = cfg.default ?? defaultFor(cfg.type)\n }\n\n if (sessionValues) {\n for (const [key, value] of Object.entries(sessionValues)) {\n if (value !== undefined) initial[key] = value\n }\n }\n\n return new VariableStore(initial)\n}\n","/**\n * v2 `context` — the **read-only, computed** namespace.\n *\n * Everything the funnel can *read* but never *write*: the device, the visitor's\n * locale, the current page, acquisition params (UTM), the session, and system\n * facts (funnel id, test/live mode, clock). It supersedes the v0 flat\n * `page.*`/`device.*`/`browser.*`/`os.*`/`query.*`/`metadata.*` system variables\n * (see {@link ./systemVariables}) by folding them into one nested object.\n *\n * Why it's *not* in the {@link ./variableStore}: the store holds **writable**\n * state (`user`/`responses`/`data`) that persists + re-renders per key. Context\n * is derived and read-only, so it lives as a plain object on a React context —\n * no subscriptions, no churn. The one moving part (`page`) is merged into the\n * snapshot from navigation state at read time.\n *\n * Authors read it through hooks (`useDevice()`, `useLocale()`, `usePage()`,\n * `useUtm()`) or inside routing/condition predicates as `s.context.*`.\n */\n\n// ── Shape ────────────────────────────────────────────────\n\nexport interface DeviceContext {\n type: 'mobile' | 'tablet' | 'desktop'\n isMobile: boolean\n isTablet: boolean\n screenWidth: number\n screenHeight: number\n viewportWidth: number\n viewportHeight: number\n colorDepth: number\n pixelRatio: number\n}\n\nexport interface BrowserContext {\n name: string\n version: string\n userAgent: string\n language: string\n cookieEnabled: boolean\n online: boolean\n}\n\nexport interface OsContext {\n name: string\n timezone: string\n}\n\nexport interface LocaleContext {\n /** Full locale, e.g. `en-US`. */\n locale: string\n /** Language subtag, e.g. `en`. */\n language: string\n /** Region subtag, e.g. `US` (may be empty). */\n region: string\n /** IANA timezone, e.g. `America/New_York`. */\n timeZone: string\n}\n\nexport interface PageContext {\n /** Current page key. */\n key: string\n /** Current page URL slug (`meta.slug`, defaults to the key) — what the renderer puts in the path. */\n slug: string\n /** 0-based position in the visited history. */\n index: number\n /** Total pages in the (expected) flow. */\n total: number\n /** 0–100. */\n progressPercentage: number\n /** Epoch ms the current page was entered. */\n startedAt: number\n}\n\n/** Acquisition / ad params captured on entry (the old `query.*` utm slice). */\nexport interface UtmContext {\n source?: string\n medium?: string\n campaign?: string\n content?: string\n term?: string\n [key: string]: string | undefined\n}\n\n/**\n * Per-network ad **click-ids** captured from the entry URL — the matching signals\n * the server CAPI needs. Named per network (not a generic bag) so the platform +\n * each integration map them precisely; `[key]` catches any others.\n */\nexport interface ClickIdContext {\n /** Meta / Facebook */\n fbclid?: string\n /** Google Ads (+ gbraid/wbraid for app↔web) */\n gclid?: string\n gbraid?: string\n wbraid?: string\n /** Microsoft / Bing */\n msclkid?: string\n /** TikTok */\n ttclid?: string\n /** Twitter / X */\n twclid?: string\n /** Snapchat */\n sccid?: string\n /** LinkedIn */\n li_fat_id?: string\n /** Pinterest */\n epik?: string\n /** Reddit */\n rdt_cid?: string\n [key: string]: string | undefined\n}\n\n/**\n * The full acquisition snapshot captured once on entry — the funnel reads `utm` /\n * `clickIds` off {@link FunnelContext}; the SDK forwards this whole thing to the\n * tracker (`setAcquisition`) so the platform persists it **first-class**: per-visit\n * on the session + **first-touch (write-once) on the Customer**, and the click-ids /\n * `_fbp`/`_fbc` cookies feed CAPI. Not stored as a generic attribute/answer.\n */\nexport interface Acquisition {\n utm: UtmContext\n clickIds: ClickIdContext\n /** CAPI cookies (`_fbp`/`_fbc`) read from `document.cookie` (not funnel-readable). */\n cookies: { fbp?: string; fbc?: string }\n /** `document.referrer` at entry. */\n referrer: string\n /** Entry URL path (the landing page). */\n landingPath: string\n}\n\nexport interface SessionContext {\n /** Server session id; null until resolved. */\n id: string | null\n /** Epoch ms the session began. */\n startedAt: number\n /** `document.referrer` at entry. */\n referrer: string\n}\n\n/**\n * Durable identity for **stable experiment bucketing** (phase-4 §4.2). The\n * preferred seed is `customerId` once known; before identification it's the\n * signed anonymous `visitorId` (P1). It is deliberately **not** the session id or\n * fingerprint — a returning visitor (e.g. via winback) must keep their variant\n * across sessions/devices (landmine #4). Both null = unidentifiable traffic, and\n * the experiment layer falls back to control rather than bucket on nothing.\n */\nexport interface IdentityContext {\n /** Known customer id (post-identification). The preferred bucketing seed. */\n customerId: string | null\n /** Signed anonymous visitor id. The fallback bucketing seed. */\n visitorId: string | null\n}\n\nexport interface SystemContext {\n funnelId: string\n campaignId: string\n /** Render mode — `test` for preview/QA, `live` for public traffic. */\n mode: 'test' | 'live'\n /** Epoch ms captured at build time (stable per render, not a live clock). */\n now: number\n}\n\n/** The whole read-only computed namespace, as read in predicates: `s.context.*`. */\nexport interface FunnelContext {\n device: DeviceContext\n browser: BrowserContext\n os: OsContext\n locale: LocaleContext\n page: PageContext\n utm: UtmContext\n /** Per-network ad click-ids captured on entry (funnel-readable; also forwarded for CAPI). */\n clickIds: ClickIdContext\n session: SessionContext\n identity: IdentityContext\n system: SystemContext\n}\n\n// ── Detection ────────────────────────────────────────────\n\ninterface RawBrowser {\n device: DeviceContext\n browser: BrowserContext\n os: OsContext\n locale: LocaleContext\n}\n\nlet cached: RawBrowser | null = null\n\nfunction extractVersion(ua: string, regex: RegExp): string {\n return ua.match(regex)?.[1] ?? '0'\n}\n\n/**\n * Sniff device/browser/os/locale from the environment, once. SSR-safe: returns\n * neutral defaults when `window` is absent. (Self-contained v2 detector — the v0\n * {@link ./systemVariables} equivalent emits flat store keys; this returns the\n * nested shape.)\n */\nfunction detect(): RawBrowser {\n if (cached) return cached\n\n if (typeof window === 'undefined') {\n cached = {\n device: {\n type: 'desktop', isMobile: false, isTablet: false,\n screenWidth: 0, screenHeight: 0, viewportWidth: 0, viewportHeight: 0,\n colorDepth: 24, pixelRatio: 1,\n },\n browser: {\n name: 'Unknown', version: '0', userAgent: 'unknown',\n language: 'en', cookieEnabled: true, online: true,\n },\n os: { name: 'Unknown', timezone: 'UTC' },\n locale: { locale: 'en', language: 'en', region: '', timeZone: 'UTC' },\n }\n return cached\n }\n\n const ua = navigator.userAgent\n const l = ua.toLowerCase()\n\n let name = 'Unknown'\n let version = '0'\n if (l.includes('firefox')) { name = 'Firefox'; version = extractVersion(ua, /Firefox\\/(\\d+[\\d.]*)/) }\n else if (l.includes('edg')) { name = 'Edge'; version = extractVersion(ua, /Edg\\/(\\d+[\\d.]*)/) }\n else if (l.includes('chrome') && !l.includes('edg')) { name = 'Chrome'; version = extractVersion(ua, /Chrome\\/(\\d+[\\d.]*)/) }\n else if (l.includes('safari') && !l.includes('chrome')) { name = 'Safari'; version = extractVersion(ua, /Version\\/(\\d+[\\d.]*)/) }\n\n let osName = 'Unknown'\n if (l.includes('win')) osName = 'Windows'\n else if (l.includes('mac')) osName = 'macOS'\n else if (l.includes('linux') && !l.includes('android')) osName = 'Linux'\n else if (l.includes('android')) osName = 'Android'\n else if (/iphone|ipad|ipod/.test(l)) osName = 'iOS'\n\n let type: DeviceContext['type'] = 'desktop'\n if (/mobile|android(?!.*tablet)|iphone|ipod/.test(l)) type = 'mobile'\n else if (/tablet|ipad/.test(l)) type = 'tablet'\n\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n const fullLocale = navigator.language || 'en'\n const [language = 'en', region = ''] = fullLocale.split('-')\n\n cached = {\n device: {\n type, isMobile: type === 'mobile', isTablet: type === 'tablet',\n screenWidth: window.screen?.width || 0,\n screenHeight: window.screen?.height || 0,\n viewportWidth: window.innerWidth || 0,\n viewportHeight: window.innerHeight || 0,\n colorDepth: window.screen?.colorDepth || 24,\n pixelRatio: window.devicePixelRatio || 1,\n },\n browser: {\n name, version, userAgent: ua,\n language: fullLocale,\n cookieEnabled: navigator.cookieEnabled ?? true,\n online: navigator.onLine ?? true,\n },\n os: { name: osName, timezone: timeZone },\n locale: { locale: fullLocale, language, region, timeZone },\n }\n return cached\n}\n\n/** Collect `utm_*` params (and any extras) from the URL. SSR-safe. */\nfunction collectUtm(): UtmContext {\n if (typeof window === 'undefined') return {}\n const out: UtmContext = {}\n const params = new URLSearchParams(window.location.search)\n params.forEach((value, key) => {\n if (key.startsWith('utm_')) out[key.slice(4)] = value\n })\n return out\n}\n\n/** Known ad-network click-id params. Any present in the URL is captured. */\nconst CLICK_ID_PARAMS = [\n 'fbclid', 'gclid', 'gbraid', 'wbraid', 'msclkid', 'ttclid',\n 'twclid', 'sccid', 'li_fat_id', 'epik', 'rdt_cid', 'dclid', 'irclickid',\n]\n\n/** Collect ad-network click-ids from the entry URL. SSR-safe. */\nfunction collectClickIds(): ClickIdContext {\n if (typeof window === 'undefined') return {}\n const out: ClickIdContext = {}\n const params = new URLSearchParams(window.location.search)\n for (const key of CLICK_ID_PARAMS) {\n const v = params.get(key)\n if (v) out[key] = v\n }\n return out\n}\n\n/** Read a cookie value by name. SSR-safe. */\nfunction readCookie(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined\n const m = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'))\n return m ? decodeURIComponent(m[1]) : undefined\n}\n\n/**\n * Assemble the full {@link Acquisition} snapshot from the context + `document`\n * (cookies, referrer, path) — captured once on entry, forwarded to the tracker for\n * first-class persistence (session + first-touch Customer) + CAPI.\n */\nexport function buildAcquisition(context: FunnelContext): Acquisition {\n return {\n utm: context.utm,\n clickIds: context.clickIds,\n cookies: { fbp: readCookie('_fbp'), fbc: readCookie('_fbc') },\n referrer: context.session.referrer,\n landingPath: typeof window !== 'undefined' ? window.location.pathname : '',\n }\n}\n\nexport interface BuildContextOptions {\n funnelId?: string\n campaignId?: string\n mode?: 'test' | 'live'\n /** Stable build-time clock (avoids `Date.now()` churn in renders/tests). */\n now?: number\n sessionId?: string | null\n /** Known customer id — the preferred stable bucketing seed (phase-4 §4.2). */\n customerId?: string | null\n /** Signed anonymous visitor id — the fallback bucketing seed. */\n visitorId?: string | null\n /** Overrides for any slice — used by the server to hydrate `utm`/`session`. */\n overrides?: Partial<FunnelContext>\n}\n\n/**\n * Build the read-only {@link FunnelContext} once, at mount. `page` starts at the\n * first page and is replaced per navigation when assembling a snapshot.\n */\nexport function buildContext(opts: BuildContextOptions = {}): FunnelContext {\n const raw = detect()\n const now = opts.now ?? 0\n const referrer = typeof document !== 'undefined' ? document.referrer : ''\n\n const base: FunnelContext = {\n device: raw.device,\n browser: raw.browser,\n os: raw.os,\n locale: raw.locale,\n utm: collectUtm(),\n clickIds: collectClickIds(),\n page: { key: '', slug: '', index: 0, total: 0, progressPercentage: 0, startedAt: now },\n session: { id: opts.sessionId ?? null, startedAt: now, referrer },\n identity: { customerId: opts.customerId ?? null, visitorId: opts.visitorId ?? null },\n system: {\n funnelId: opts.funnelId ?? '',\n campaignId: opts.campaignId ?? '',\n mode: opts.mode ?? 'live',\n now,\n },\n }\n\n if (!opts.overrides) return base\n return {\n ...base,\n ...opts.overrides,\n device: { ...base.device, ...opts.overrides.device },\n browser: { ...base.browser, ...opts.overrides.browser },\n os: { ...base.os, ...opts.overrides.os },\n locale: { ...base.locale, ...opts.overrides.locale },\n utm: { ...base.utm, ...opts.overrides.utm },\n clickIds: { ...base.clickIds, ...opts.overrides.clickIds },\n page: { ...base.page, ...opts.overrides.page },\n session: { ...base.session, ...opts.overrides.session },\n identity: { ...base.identity, ...opts.overrides.identity },\n system: { ...base.system, ...opts.overrides.system },\n }\n}\n\n/** Internal: reset the detection cache (tests only). */\nexport function __resetContextCache(): void {\n cached = null\n}\n","/**\n * v2 tracking seam — the funnel runtime emits a **fixed event taxonomy**, but\n * never talks to the network itself. It calls a {@link Tracker} the platform/CLI\n * injects via {@link FunnelProvider}. The real implementation is the existing\n * {@link ./tracker}.`FunnelTracker` (session id, ad attribution, debounced\n * persistence, CAPI fan-out); tests and local dev use {@link createConsoleTracker}.\n *\n * The taxonomy is preserved verbatim from v0 so analytics keep working:\n * funnel.start · page.view · page.exit · user.registered · experiment.exposure ·\n * checkout.start · checkout.payment_added · checkout.failed · purchase.complete\n *\n * Where each fires (all from the SDK runtime):\n * - `funnel.start` / `page.view` / `page.exit` / `experiment.exposure` — navigation\n * ({@link ../flow/flow}.`FunnelView`); `page.exit` carries duration + active (visible) time.\n * - `user.registered` — `identify()`, the first time `user.email` is written.\n * - `checkout.*` / `purchase.complete` — the commerce primitives ({@link ../commerce/checkout}).\n * `checkout.payment_added` is reported by an inline driver via `onPaymentAdded` (optional).\n *\n * A `responses.set(...)` does **not** emit a discrete event — values are batched into\n * `userData` and persisted (debounced). Only the events above fire.\n */\n\nimport {\n createContext,\n createElement,\n useCallback,\n useContext,\n type ReactNode,\n} from 'react'\nimport type { Acquisition } from '../state/context'\n\n// ── Event taxonomy (typed, preserved from v0) ────────────\n\nexport interface FunnelEventDataMap {\n 'funnel.start': Record<string, never>\n 'page.view': { pageId: string; pageKey?: string; pageName?: string; isInitial?: boolean; eventId?: string }\n 'page.exit': { pageId: string; durationMs: number; activeMs: number }\n 'user.registered': { email: string; eventId?: string }\n 'checkout.start': { productId?: string; priceId?: string; productName?: string }\n 'checkout.payment_added': Record<string, never>\n 'checkout.failed': { category: string; declineCode?: string; productId?: string; intent?: string }\n 'purchase.complete': { amount?: number; currency?: string; email?: string; eventId?: string }\n 'experiment.exposure': { experimentId: string; variant: string }\n}\n\n/**\n * A unique id for an analytics event, used as the **dedup key** between the\n * browser pixel (`fbq(..., { eventID })`) and the server CAPI call. Browser-\n * originated events (page.view, registration) mint one with this; **purchase /\n * subscription events carry the id the *server* minted** (the charge is the source\n * of truth) — see `CheckoutResult.eventId`.\n */\nlet _eventIdCounter = 0\nexport function newEventId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `af_${Date.now().toString(36)}_${(_eventIdCounter++).toString(36)}`\n}\n\nexport type KnownFunnelEvent = keyof FunnelEventDataMap\n\n/**\n * The surface the runtime needs from a tracker. A subset of `FunnelTracker`, so\n * the real one satisfies it directly; the console tracker is a trivial stub.\n */\nexport interface Tracker {\n /** Emit a known event (typed) or any custom event name. */\n track<E extends KnownFunnelEvent>(event: E, data?: FunnelEventDataMap[E], userData?: Record<string, unknown>): void\n track(event: string, data?: Record<string, unknown>, userData?: Record<string, unknown>): void\n /**\n * Identify by email — fires `user.registered` (idempotent in the impl). The\n * optional `eventId` is the browser↔CAPI dedup key for the registration event.\n */\n identify(email: string, eventId?: string): void\n /** Push the latest variable snapshot for batched/debounced persistence. */\n setVariables?(variables: Record<string, unknown>): void\n /**\n * The acquisition snapshot (utm + click-ids + `_fbp`/`_fbc` + referrer), pushed\n * once on entry. The platform persists it first-class — per-visit on the session +\n * **first-touch (write-once) on the Customer** — and feeds it to CAPI. Optional;\n * the console/test trackers ignore it.\n */\n setAcquisition?(acquisition: Acquisition): void\n}\n\n/** A no-op-ish tracker that logs to the console — for tests, preview, local dev. */\nexport function createConsoleTracker(opts: { silent?: boolean } = {}): Tracker {\n const log = (label: string, ...args: unknown[]) => {\n if (!opts.silent) console.info(`[appfunnel] ${label}`, ...args)\n }\n return {\n track: (event: string, data?: unknown) => log(`track ${event}`, data ?? {}),\n identify: (email: string, eventId?: string) => log('identify', email, eventId),\n setVariables: (vars) => log('vars', vars),\n setAcquisition: (acq) => log('acquisition', acq),\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\nconst TrackerContext = createContext<Tracker | null>(null)\n\nexport function TrackerProvider({\n tracker,\n children,\n}: {\n tracker: Tracker\n children: ReactNode\n}): ReactNode {\n return createElement(TrackerContext.Provider, { value: tracker }, children)\n}\n\n/** Internal: the raw tracker, or a silent console fallback if none provided. */\nexport function useTrackerRef(): Tracker {\n return useContext(TrackerContext) ?? FALLBACK\n}\n\nconst FALLBACK = createConsoleTracker({ silent: true })\n\n/**\n * `const { track } = useTracker()` — emit a custom event. Auto events\n * (page.view, identify, purchase, …) fire on their own; this is the escape\n * hatch for funnel-specific events (`track('quiz_skipped', { step: 3 })`).\n */\nexport function useTracker(): { track: Tracker['track'] } {\n const tracker = useTrackerRef()\n const track = useCallback(\n (event: string, data?: Record<string, unknown>, userData?: Record<string, unknown>) =>\n tracker.track(event, data as never, userData),\n [tracker],\n )\n return { track }\n}\n","/**\n * The **`window.appfunnel` event bus** — the client-side integration surface\n * (port of v0 `admin/lib/funnel/utils/appfunnelRuntime.ts`).\n *\n * Every taxonomy event the runtime emits is mirrored here, so on-page pixels and\n * custom scripts integrate by **subscribing** — `window.appfunnel.on('purchase.complete', …)`\n * — instead of the funnel hand-injecting pixel config per page. The pre-built pixel\n * loaders (Meta/TikTok/GTM/Clarity) are just subscribers; CAPI stays the server-side\n * default (this is the *client* sink of the same events). See doc 08 §3.\n *\n * Two deliberate properties vs. v0:\n * - **Replay history** (`events`): async pixels load *after* `funnel.start`/`page.view`\n * fire, so a late subscriber would miss them. The bus keeps a bounded history a\n * subscriber can replay (the GTM `dataLayer` trick) — no lost events.\n * - **Subscribe + read only.** The window surface exposes `on`/`off`/`events` + read\n * getters; it has **no `emit`** (third-party code can't forge events) and **no\n * mutating actions** (`setVariable`/navigation) — the funnel can't be driven through\n * it. (v0's full-control Custom-JS API is deferred pending the bus-control-scope\n * decision; doc 08 §3 + §4.)\n */\n\nimport { newEventId, type Tracker } from './tracking'\n\n/** Read accessors the bus exposes — wired to the funnel's store + context. */\nexport interface BusAccessors {\n getVariable: (key: string) => unknown\n getVariables: () => Record<string, unknown>\n getCurrentPageId: () => string | null\n getCustomerId: () => string | null\n getVisitorId: () => string | null\n}\n\nexport interface BusEvent {\n event: string\n data: unknown\n /** Epoch ms the event was emitted (for ordering / replay). */\n ts: number\n}\n\ntype Listener = (data: unknown) => void\n\n/** The public `window.appfunnel` surface — subscribe + read, never emit or mutate. */\nexport interface AppFunnelBusApi extends BusAccessors {\n /** Subscribe to an event (or `'*'` for all). Returns an unsubscribe fn. */\n on(event: string, cb: Listener): () => void\n off(event: string, cb: Listener): void\n /** Bounded replay history — read past events, then `on()` for future ones. */\n readonly events: BusEvent[]\n}\n\nconst MAX_HISTORY = 250\n\n/**\n * The internal bus: the public {@link AppFunnelBusApi} plus `emit` (SDK-only) and\n * `now` injection. The SDK holds this; only {@link AppFunnelBusApi} reaches `window`.\n */\nexport interface FunnelBus extends AppFunnelBusApi {\n emit(event: string, data?: unknown): void\n}\n\n/** Create a bus over the given read accessors. `now` is injectable for tests. */\nexport function createBus(accessors: BusAccessors, now: () => number = () => Date.now()): FunnelBus {\n const listeners = new Map<string, Set<Listener>>()\n const events: BusEvent[] = []\n\n const on: AppFunnelBusApi['on'] = (event, cb) => {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(cb)\n return () => off(event, cb)\n }\n const off: AppFunnelBusApi['off'] = (event, cb) => {\n listeners.get(event)?.delete(cb)\n }\n\n const emit = (event: string, data?: unknown) => {\n events.push({ event, data, ts: now() })\n if (events.length > MAX_HISTORY) events.shift()\n // Exact-event listeners, then wildcard. A throwing subscriber never breaks the rest.\n for (const cb of listeners.get(event) ?? []) {\n try { cb(data) } catch { /* a pixel error must not break the funnel */ }\n }\n for (const cb of listeners.get('*') ?? []) {\n try { cb({ event, data }) } catch { /* ignore */ }\n }\n }\n\n return { on, off, events, emit, ...accessors }\n}\n\n/**\n * Wrap a {@link Tracker} so every emitted taxonomy event is mirrored to the bus\n * (the client sink). `identify()` also surfaces a `user.registered` to the bus, so\n * pixels see registration. The server sink (the inner tracker → CAPI) is untouched.\n */\nexport function withBus(tracker: Tracker, bus: FunnelBus): Tracker {\n return {\n // Spread preserves the original call arity (don't append an undefined userData).\n track: ((...args: [string, unknown?, Record<string, unknown>?]) => {\n ;(tracker.track as (...a: unknown[]) => void)(...args)\n bus.emit(args[0], args[1])\n }) as Tracker['track'],\n identify: (email: string, eventId?: string) => {\n // One id shared by the server (inner.identify → CAPI) and the bus (pixel) so\n // CompleteRegistration dedupes across browser + server.\n const id = eventId ?? newEventId()\n tracker.identify(email, id)\n bus.emit('user.registered', { email, eventId: id })\n },\n setVariables: tracker.setVariables ? (v) => tracker.setVariables!(v) : undefined,\n // Acquisition is persistence (session + first-touch Customer), not a bus event.\n setAcquisition: tracker.setAcquisition ? (a) => tracker.setAcquisition!(a) : undefined,\n }\n}\n\ndeclare global {\n interface Window {\n appfunnel?: AppFunnelBusApi\n }\n}\n\n/**\n * Attach the bus's public surface to `window.appfunnel` (client-side only).\n * Returns a detach fn for unmount. No-op under SSR.\n */\nexport function attachBus(bus: FunnelBus): () => void {\n if (typeof window === 'undefined') return () => {}\n const { on, off, getVariable, getVariables, getCurrentPageId, getCustomerId, getVisitorId } = bus\n const api: AppFunnelBusApi = {\n on, off, getVariable, getVariables, getCurrentPageId, getCustomerId, getVisitorId,\n get events() { return bus.events },\n }\n window.appfunnel = api\n return () => {\n if (window.appfunnel === api) delete window.appfunnel\n }\n}\n","/**\n * v2 localization — translated **text** (prices already localize via `Intl` in\n * {@link ./catalog}). Per doc 05: locales live in the funnel source — supported\n * locales + default + fallback are funnel config ({@link FunnelLocales}), and\n * each locale is a flat `key → string` **catalog** (`messages/en.json`, …),\n * versioned + published with the funnel. The dashboard's manual translation\n * table edits exactly these catalogs.\n *\n * Lookup walks a **fallback chain** (active → fallback → default) so a missing\n * string never blanks — it falls through, and only as a last resort returns the\n * key (flagged in dev). Interpolation is simple `{{var}}`; plurals use the\n * built-in `Intl.PluralRules`; numbers/dates/percent use `Intl`. No ICU, no rich\n * markup (markup stays in TSX).\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react'\nimport type { FunnelLocales } from '../flow/spine'\n\n/** locale → (message key → string). The shape of `messages/<locale>.json`. */\nexport type MessageCatalog = Record<string, Record<string, string>>\n\nexport type PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'\nexport type Direction = 'ltr' | 'rtl'\n\nconst RTL_LANGS = new Set(['ar', 'he', 'fa', 'ur', 'ps', 'sd', 'dv', 'yi'])\n\n/** Whether a locale is right-to-left (by language subtag). */\nexport function isRtl(locale: string): boolean {\n return RTL_LANGS.has(locale.split('-')[0])\n}\n\nconst base = (l: string | undefined): string | undefined => l?.split('-')[0]\n\n/**\n * Resolve the active locale: `override` (URL/param) → `detected` (device) →\n * funnel default, each only if supported (matched by exact tag or language\n * subtag). Mirrors doc 05's resolution chain (the geo/header steps happen\n * server-side and arrive via `override`/`detected`).\n */\nexport function resolveLocale(\n config: FunnelLocales | undefined,\n detected: string,\n override?: string,\n): string {\n const supported = config?.supported ?? (config?.default ? [config.default] : ['en'])\n const def = config?.default ?? supported[0] ?? 'en'\n const pick = (l?: string): string | undefined => {\n if (!l) return undefined\n if (supported.includes(l)) return l\n return supported.find((s) => base(s) === base(l))\n }\n return pick(override) ?? pick(detected) ?? def\n}\n\n/** Replace `{{name}}` placeholders; leaves unknown ones intact. */\nfunction interpolate(str: string, params?: Record<string, string | number>): string {\n if (!params) return str\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, k: string) => (k in params ? String(params[k]) : `{{${k}}}`))\n}\n\n/** Walk the fallback chain for a key; undefined if absent everywhere. */\nfunction lookup(catalog: MessageCatalog, chain: string[], key: string): string | undefined {\n for (const loc of chain) {\n const v = catalog[loc]?.[key]\n if (v !== undefined) return v\n }\n return undefined\n}\n\nfunction devWarn(message: string): void {\n const env = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV\n if (env === 'production') return\n try {\n console.warn(message)\n } catch {\n /* no-op */\n }\n}\n\n// ── Public types ─────────────────────────────────────────\n\nexport interface TFunction {\n /** Translate a key, with optional `{{var}}` params. Missing → fallback → key. */\n (key: string, params?: Record<string, string | number>): string\n /** Locale-correct plural: `t.plural(n, { one: '# day', other: '# days' })` (`#` → n). */\n plural: (\n n: number,\n forms: Partial<Record<PluralCategory, string>>,\n params?: Record<string, string | number>,\n ) => string\n}\n\nexport interface Formatters {\n number: (n: number, opts?: Intl.NumberFormatOptions) => string\n date: (d: Date | number, opts?: Intl.DateTimeFormatOptions) => string\n percent: (n: number, opts?: Intl.NumberFormatOptions) => string\n}\n\nexport interface Translation {\n t: TFunction\n fmt: Formatters\n /** The active (resolved) locale. */\n locale: string\n /** Switch locale at runtime (preview / language picker). */\n setLocale: (locale: string) => void\n /** Text direction for the active locale. */\n dir: Direction\n /** The funnel's supported locales. */\n locales: string[]\n}\n\n// ── React wiring ─────────────────────────────────────────\n\ninterface LocaleContextValue {\n locale: string\n setLocale: (locale: string) => void\n config?: FunnelLocales\n catalog: MessageCatalog\n}\n\nconst LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport interface LocaleProviderProps {\n config?: FunnelLocales\n catalog?: MessageCatalog\n /** Device/browser locale (from computed context) — the resolution input. */\n detected: string\n /** Explicit override (URL/param/geo), highest priority. */\n override?: string\n children: ReactNode\n}\n\n/** Resolves + holds the active locale and the message catalog. */\nexport function LocaleProvider({\n config,\n catalog = {},\n detected,\n override,\n children,\n}: LocaleProviderProps): ReactNode {\n const [locale, setLocale] = useState(() => resolveLocale(config, detected, override))\n const value = useMemo<LocaleContextValue>(\n () => ({ locale, setLocale, config, catalog }),\n [locale, config, catalog],\n )\n return createElement(LocaleContext.Provider, { value }, children)\n}\n\n/** The active (resolved) funnel locale, or `'en'` if no provider — for display\n * formatting (e.g. {@link ./catalog} prices) without building the full handle. */\nexport function useActiveLocale(): string {\n return useContext(LocaleContext)?.locale ?? 'en'\n}\n\n/**\n * `const { t, fmt, locale, dir } = useTranslation()` — translated text +\n * locale-aware `Intl` formatters for the active funnel locale.\n */\nexport function useTranslation(): Translation {\n const ctx = useContext(LocaleContext)\n if (!ctx) throw new Error('useTranslation must be used inside <FunnelProvider>')\n const { locale, setLocale, config, catalog } = ctx\n\n const chain = useMemo(() => {\n const def = config?.default\n const fb = config?.fallback\n return Array.from(new Set([locale, fb, def].filter(Boolean) as string[]))\n }, [locale, config])\n\n const t = useMemo<TFunction>(() => {\n const fn = ((key: string, params?: Record<string, string | number>) => {\n const raw = lookup(catalog, chain, key)\n if (raw === undefined) {\n devWarn(`[appfunnel] missing translation: \"${key}\" (${locale})`)\n return key\n }\n return interpolate(raw, params)\n }) as TFunction\n fn.plural = (n, forms, params) => {\n const rule = new Intl.PluralRules(locale).select(n) as PluralCategory\n const form = forms[rule] ?? forms.other ?? ''\n return interpolate(form.replace(/#/g, String(n)), params)\n }\n return fn\n }, [catalog, chain, locale])\n\n const fmt = useMemo<Formatters>(\n () => ({\n number: (n, opts) => new Intl.NumberFormat(locale, opts).format(n),\n date: (d, opts) => new Intl.DateTimeFormat(locale, opts).format(d),\n percent: (n, opts) => new Intl.NumberFormat(locale, { style: 'percent', ...opts }).format(n),\n }),\n [locale],\n )\n\n return {\n t,\n fmt,\n locale,\n setLocale,\n dir: isRtl(locale) ? 'rtl' : 'ltr',\n locales: config?.supported ?? [locale],\n }\n}\n","/**\n * v2 `products` — the **read-only** product catalog.\n *\n * **AppFunnel does not manage currency.** Multi-currency is entirely the payment\n * provider's job: the provider (or its preview API) resolves the visitor's price,\n * and we receive a single resolved `{ amount, currency }` per product. No FX, no\n * currency selection, no conversion on our side. (FX appears only for frozen-USD\n * *reporting*, never display — phase-3 §3.6b.) A provider that doesn't localize\n * simply gives one currency.\n *\n * Our only job is **display**: pick the product by logical id and **format** its\n * amount. Formatting happens at read time in the funnel's **active locale** (so\n * switching language reformats `kr 79,00` ⇄ `$9.99`), while the **currency** is\n * whatever the provider resolved. Currency selection is the platform's; the\n * authoring funnel only ever names a product id.\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n useMemo,\n type ReactNode,\n} from 'react'\nimport { useActiveLocale } from '../i18n/translation'\n\n// ── Shape ────────────────────────────────────────────────\n\nexport type Interval = 'day' | 'week' | 'month' | 'year' | 'one_time'\n\n/** What the platform hands the funnel per product (a single provider-resolved price). */\nexport interface ProductInput {\n id: string\n name?: string\n displayName?: string\n /** Provider-resolved price in **minor units** (the provider chose the currency). */\n amount: number\n /** Currency of `amount`, as the provider resolved it (e.g. `DKK`). */\n currency: string\n interval?: Interval\n intervalCount?: number\n trialDays?: number\n /** Trial price in minor units (omit/0 = free trial). */\n trialAmount?: number\n /** Settlement provider — opaque to the author, used by the checkout driver. */\n provider?: string\n}\n\n/** A money value with a locale-formatted string. */\nexport interface Money {\n /** Major units, e.g. `79`. */\n amount: number\n /** Minor units, e.g. `7900`. */\n minor: number\n currency: string\n /** Locale-formatted, e.g. `kr 79,00` / `€9,99` / `$9.99`. */\n formatted: string\n}\n\n/**\n * The product with its amounts resolved (currency + period math), **before**\n * locale formatting — what the catalog stores. {@link useProduct} formats it.\n */\nexport interface ResolvedProduct {\n id: string\n name: string\n displayName: string\n provider: string\n currency: string\n priceMinor: number\n perDayMinor: number\n perWeekMinor: number\n perMonthMinor: number\n perYearMinor: number\n period: string\n periodly: string\n hasTrial: boolean\n trialDays: number\n trialMinor: number\n}\n\n/** Display-ready product the author reads (every amount locale-formatted). */\nexport interface Product {\n id: string\n name: string\n displayName: string\n provider: string\n price: Money\n /** e.g. `month`, `quarter`, `one-time`. */\n period: string\n /** e.g. `monthly`, `quarterly`, `one-time`. */\n periodly: string\n /** Period-normalized prices (for \"just $0.27/day\" style copy). */\n perDay: Money\n perWeek: Money\n perMonth: Money\n perYear: Money\n hasTrial: boolean\n trialDays: number\n trialPrice: Money | null\n}\n\n// ── Resolve (currency-agnostic) ──────────────────────────\n\nconst PERIOD_DAYS: Record<Interval, number> = {\n day: 1, week: 7, month: 30, year: 365, one_time: 0,\n}\n\nfunction periodDays(interval: Interval, count: number): number {\n return PERIOD_DAYS[interval] * count\n}\n\nfunction intervalLabel(interval: Interval, count: number): { period: string; periodly: string } {\n if (interval === 'one_time') return { period: 'one-time', periodly: 'one-time' }\n if (interval === 'month' && count === 3) return { period: 'quarter', periodly: 'quarterly' }\n if (interval === 'month' && count === 6) return { period: '6 months', periodly: 'semiannually' }\n if (interval === 'week' && count === 2) return { period: '2 weeks', periodly: 'biweekly' }\n if (count === 1) {\n const periodly = { day: 'daily', week: 'weekly', month: 'monthly', year: 'yearly' }[interval]\n return { period: interval, periodly }\n }\n return { period: `${count} ${interval}s`, periodly: `every ${count} ${interval}s` }\n}\n\n/** Resolve a {@link ProductInput} into amounts + period math (no formatting yet). */\nexport function resolveProduct(input: ProductInput): ResolvedProduct {\n const interval = input.interval ?? 'one_time'\n const count = input.intervalCount ?? 1\n const days = periodDays(interval, count)\n const perDayMinor = days > 0 ? input.amount / days : input.amount\n const label = intervalLabel(interval, count)\n\n return {\n id: input.id,\n name: input.name ?? input.id,\n displayName: input.displayName ?? input.name ?? input.id,\n provider: input.provider ?? 'stripe',\n currency: input.currency,\n priceMinor: input.amount,\n perDayMinor,\n perWeekMinor: perDayMinor * 7,\n perMonthMinor: perDayMinor * 30,\n perYearMinor: perDayMinor * 365,\n period: label.period,\n periodly: label.periodly,\n hasTrial: (input.trialDays ?? 0) > 0,\n trialDays: input.trialDays ?? 0,\n trialMinor: input.trialAmount ?? 0,\n }\n}\n\n/** Build the id → {@link ResolvedProduct} catalog. Formatting happens at read time. */\nexport function buildCatalog(inputs: ProductInput[]): Map<string, ResolvedProduct> {\n return new Map(inputs.map((i) => [i.id, resolveProduct(i)]))\n}\n\n// ── Format (locale-dependent) ────────────────────────────\n\nfunction formatMoney(minor: number, currency: string, locale: string): Money {\n const amount = minor / 100\n const code = currency.toUpperCase()\n let formatted: string\n try {\n formatted = new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n } catch {\n formatted = `${code} ${amount.toFixed(2)}`\n }\n return { amount, minor, currency: code, formatted }\n}\n\n/** Format a {@link ResolvedProduct} into a display {@link Product} in `locale`. */\nexport function formatProduct(r: ResolvedProduct, locale: string): Product {\n const m = (minor: number): Money => formatMoney(minor, r.currency, locale)\n return {\n id: r.id,\n name: r.name,\n displayName: r.displayName,\n provider: r.provider,\n price: m(r.priceMinor),\n period: r.period,\n periodly: r.periodly,\n perDay: m(r.perDayMinor),\n perWeek: m(r.perWeekMinor),\n perMonth: m(r.perMonthMinor),\n perYear: m(r.perYearMinor),\n hasTrial: r.hasTrial,\n trialDays: r.trialDays,\n trialPrice: r.hasTrial ? m(r.trialMinor) : null,\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\nconst CatalogContext = createContext<Map<string, ResolvedProduct> | null>(null)\n\nexport function CatalogProvider({\n catalog,\n children,\n}: {\n catalog: Map<string, ResolvedProduct>\n children: ReactNode\n}): ReactNode {\n return createElement(CatalogContext.Provider, { value: catalog }, children)\n}\n\nfunction useCatalog(): Map<string, ResolvedProduct> {\n return useContext(CatalogContext) ?? EMPTY\n}\nconst EMPTY = new Map<string, ResolvedProduct>()\n\n/** `useProduct('monthly')` — one product, formatted in the active locale. */\nexport function useProduct(id: string | undefined): Product | undefined {\n const catalog = useCatalog()\n const locale = useActiveLocale()\n const resolved = id ? catalog.get(id) : undefined\n return useMemo(() => (resolved ? formatProduct(resolved, locale) : undefined), [resolved, locale])\n}\n\n/** `useProducts()` — every product, formatted in the active locale, in order. */\nexport function useProducts(): Product[] {\n const catalog = useCatalog()\n const locale = useActiveLocale()\n return useMemo(\n () => Array.from(catalog.values()).map((r) => formatProduct(r, locale)),\n [catalog, locale],\n )\n}\n","import type { ComponentType } from 'react'\nimport type { VariableConfig, VariableValue } from '../types'\nimport type { FunnelContext } from '../state/context'\n\n/**\n * The funnel **spine** — the constrained, declarative configuration authored as\n * code (`defineFunnel` / `pageMeta` / `definePage`) yet **dashboard-editable**\n * (static AST parse → pretty UI → codegen) and compiled to the manifest IR.\n *\n * Principle: **presentation = code** (the page components), **configuration =\n * data** (this spine). See docs/platform-v2/06-funnel-project-model.md.\n *\n * Routing is **declarative nodes + code predicates** (decided — doc 06): a\n * page's `next` is an ordered list of {@link Route}s, each with a **static `to`\n * page key** (so the dashboard can draw every possible edge without executing\n * anything) and an optional `when` **gate** that returns true/false. The gate is\n * either a declarative {@link Condition} (one field — UI-editable data) or a code\n * {@link Predicate} (`s => boolean` — the escape hatch, opaque body but the edge\n * is still visible). First matching route wins; a route with no `when` is the\n * fallback. Multiple conditions = multiple routes (or boolean logic in one\n * predicate). Omit `next` entirely for the default linear flow.\n */\n\n// ── Snapshot (what a predicate sees) ─────────────────────\n\n/**\n * Read-only view of every namespace a routing/condition predicate can branch\n * on. `user`/`responses`/`data` are the writable namespaces; `context` is the\n * read-only computed one ({@link FunnelContext}).\n */\nexport interface FunnelSnapshot {\n user: Record<string, VariableValue>\n responses: Record<string, VariableValue>\n data: Record<string, VariableValue>\n context: FunnelContext\n}\n\n/** A code-predicate gate — `s => s.responses.goal === 'gain'`. */\nexport type Predicate = (s: FunnelSnapshot) => boolean\n\nexport type ConditionOp =\n | 'eq' | 'neq' | 'in' | 'gt' | 'gte' | 'lt' | 'lte'\n | 'exists' | 'empty' | 'contains'\n\n/**\n * A declarative gate over **one** namespaced field — UI-editable data the\n * dashboard renders as a condition row (`field` `op` `value`). `field` is a\n * dotted path into the snapshot: `responses.goal`, `user.country`,\n * `context.device.isMobile`.\n */\nexport interface Condition {\n field: string\n op: ConditionOp\n value?: VariableValue | VariableValue[]\n}\n\n/** An edge gate: either declarative data ({@link Condition}) or a {@link Predicate}. */\nexport type Gate = Condition | Predicate\n\n/**\n * One routing edge out of a page. `to` is a **static** target key (the dashboard\n * reads these to draw the flow graph); `when` gates the edge (omit = fallback).\n */\nexport interface Route {\n to: string\n when?: Gate\n}\n\n/** Read a dotted path out of the snapshot (flat namespaces + nested `context`). */\nfunction readField(s: FunnelSnapshot, field: string): VariableValue {\n let cur: unknown = s\n for (const part of field.split('.')) {\n if (cur == null) return undefined\n cur = (cur as Record<string, unknown>)[part]\n }\n return cur as VariableValue\n}\n\n/** Evaluate a declarative {@link Condition} against a snapshot. */\nexport function evaluateCondition(cond: Condition, s: FunnelSnapshot): boolean {\n const val = readField(s, cond.field)\n const { op, value } = cond\n switch (op) {\n case 'eq': return val === value\n case 'neq': return val !== value\n case 'in': return Array.isArray(value) && (value as VariableValue[]).includes(val as VariableValue)\n case 'gt': return typeof val === 'number' && typeof value === 'number' && val > value\n case 'gte': return typeof val === 'number' && typeof value === 'number' && val >= value\n case 'lt': return typeof val === 'number' && typeof value === 'number' && val < value\n case 'lte': return typeof val === 'number' && typeof value === 'number' && val <= value\n case 'contains':\n if (typeof val === 'string') return val.includes(String(value))\n if (Array.isArray(val)) return (val as VariableValue[]).includes(value as VariableValue)\n return false\n case 'exists': return val !== undefined && val !== null && val !== ''\n case 'empty':\n return val === undefined || val === null || val === '' ||\n (Array.isArray(val) && val.length === 0)\n default: return false\n }\n}\n\n/** Evaluate either gate kind to a boolean. */\nexport function evaluateGate(gate: Gate, s: FunnelSnapshot): boolean {\n return typeof gate === 'function' ? gate(s) : evaluateCondition(gate, s)\n}\n\n/**\n * Resolve an ordered list of routes to a target page key, or `undefined` to fall\n * through to the linear next. First route whose gate passes (or has no `when`)\n * wins.\n */\nexport function resolveRoute(\n routes: Route[] | undefined,\n s: FunnelSnapshot,\n): string | undefined {\n if (!routes) return undefined\n for (const route of routes) {\n if (!route.when || evaluateGate(route.when, s)) return route.to\n }\n return undefined\n}\n\n// ── Pages ────────────────────────────────────────────────\n\nexport type PageType =\n | 'default' // plain content/step page (the baseline)\n | 'email-capture' // collects user.email — the mandatory identity step (validated)\n | 'paywall' // the offer/pricing page → drives paywall-view + paywall-CR\n | 'upsell' // post-purchase one-click → drives Upsell Rate + off-session charge\n | 'finish' // terminal success/thank-you page → completion analytics, ends the flow\n\nexport interface PageMeta {\n /** Page kind — drives behavior + analytics (e.g. `paywall`, `upsell`). */\n type?: PageType\n /** URL slug; defaults to the page key. */\n slug?: string\n /**\n * Ordered routing edges out of this page (first match wins). Each has a static\n * `to` key + an optional `when` gate. Omit for the default linear flow.\n */\n next?: Route[]\n /**\n * Entry precondition for **deep-link / reload** restoration. When the runtime is\n * asked to start *on this page* (not via in-funnel navigation), it restores there\n * only if `guard` passes against the restored snapshot — otherwise it falls back\n * to the start page. e.g. an upsell page: `guard: s => s.data.purchased === true`.\n * Reaching the page via `next()` is unaffected (routing already gated it). Omit =\n * always restorable. Same gate kind as routing (`Condition` or predicate).\n */\n guard?: Gate\n}\n\n/**\n * Identity helper for a page's co-located metadata.\n * `export const meta = pageMeta({ type: 'paywall', next: s => … })`.\n */\nexport function pageMeta(meta: PageMeta): PageMeta {\n return meta\n}\n\n/**\n * Default entry guard implied by a page **type** — a built-in precondition every\n * funnel inherits. `paywall` and `upsell` require a captured `user.email` (the\n * mandatory identity step), so a deep-link / reload straight into them without\n * email bounces to the start. Authors don't write this; an explicit `meta.guard`\n * **overrides** it (see {@link entryGuard}).\n */\nconst TYPE_GUARDS: Partial<Record<PageType, Gate>> = {\n paywall: { field: 'user.email', op: 'exists' },\n upsell: { field: 'user.email', op: 'exists' },\n}\n\n/**\n * The effective entry guard for a page: an explicit `meta.guard` if the author set\n * one, **otherwise** the page-type default (e.g. paywall/upsell need email). The\n * explicit guard fully **overrides** the default — it's not combined. Returns\n * `undefined` when neither applies.\n */\nexport function entryGuard(meta?: PageMeta): Gate | undefined {\n return meta?.guard ?? (meta?.type ? TYPE_GUARDS[meta.type] : undefined)\n}\n\n/**\n * Identity helper for a page component. The page is plain React that reaches the\n * runtime through hooks (`useResponse`, `useNavigation`, …) — there is no `sdk`\n * prop. `export default definePage(function Welcome() { … })`.\n */\nexport function definePage<P extends object = Record<string, never>>(\n component: ComponentType<P>,\n): ComponentType<P> {\n return component\n}\n\n// ── Flow resolution ──────────────────────────────────────\n\n/** A page in the flow: its key + (optional) co-located meta. */\nexport interface FlowPage {\n key: string\n meta?: PageMeta\n}\n\n/**\n * Decide the next page from `currentKey`:\n * 1. the current page's `next` routes ({@link resolveRoute}), if one matches, else\n * 2. the next page in file order (the default linear flow), else\n * 3. `undefined` (end of funnel / current key not found).\n */\nexport function nextPage(\n pages: FlowPage[],\n currentKey: string,\n s: FunnelSnapshot,\n): string | undefined {\n const idx = pages.findIndex((p) => p.key === currentKey)\n if (idx === -1) return undefined\n const routed = resolveRoute(pages[idx].meta?.next, s)\n if (routed) return routed\n return pages[idx + 1]?.key\n}\n\n/**\n * Every page a visitor *could* go to next from `currentKey` — all route targets\n * (regardless of gate, since we don't know which will pass) plus the linear next.\n * Used to **prefetch** the likely-next page chunks; not for navigation.\n */\nexport function outgoingKeys(pages: FlowPage[], currentKey: string): string[] {\n const idx = pages.findIndex((p) => p.key === currentKey)\n if (idx === -1) return []\n const out = new Set<string>()\n for (const route of pages[idx].meta?.next ?? []) out.add(route.to)\n const linear = pages[idx + 1]?.key\n if (linear) out.add(linear)\n return [...out]\n}\n\n/**\n * The number of pages on the path from `startKey` to a `finish` (or the end of\n * the flow) **given the current state** — the denominator for progress. It walks\n * the actual routing ({@link nextPage}) rather than counting all files, so a\n * branched funnel reaches 100% on whichever path the visitor's answers select.\n * Re-traced per navigation; a visited set guards against routing cycles.\n */\nexport function expectedPathLength(\n pages: FlowPage[],\n startKey: string,\n s: FunnelSnapshot,\n): number {\n const seen = new Set<string>()\n let key: string | undefined = startKey\n let count = 0\n while (key && !seen.has(key)) {\n seen.add(key)\n count++\n if (pages.find((p) => p.key === key)?.meta?.type === 'finish') break\n key = nextPage(pages, key, s)\n }\n return count\n}\n\n// ── Funnel definition ────────────────────────────────────\n\nexport interface FunnelLocales {\n default: string\n supported: string[]\n fallback?: string\n}\n\n/**\n * The funnel-level spine. Flow is mostly inferred from page file order + each\n * page's `next`; this holds the funnel-wide config. Stays **thin** — routing\n * lives co-located on pages (doc 06: \"funnel.ts stays thin\").\n */\nexport interface FunnelDefinition {\n id: string\n /** `responses.*` runtime variables (default values). */\n responses?: Record<string, VariableConfig>\n /** `data.*` working/scratch variables (default values). */\n data?: Record<string, VariableConfig>\n /** Product ids from the platform catalog this funnel uses (prices resolved at render). */\n products?: string[]\n locales?: FunnelLocales\n /**\n * When `true`, the funnel shows the **geo-specific** currency/price the payment\n * provider resolves (Stripe `currency_options`, Paddle preview, Whop, SolidGate,\n * …). When `false` (default), a single fixed currency is used. AppFunnel does no\n * FX — this only toggles whether the platform asks the provider for the geo\n * price; the SDK just displays whatever resolved `{amount, currency}` it's handed.\n * (See docs/platform-v2 phase-3 §3.6.)\n */\n locationAwareCurrency?: boolean\n}\n\n/** Identity helper for a funnel definition. */\nexport function defineFunnel(def: FunnelDefinition): FunnelDefinition {\n return def\n}\n","/**\n * **Runtime page-level experiments** — A/B/n on a *single page inside one funnel*,\n * resolved at render time (phase-4). No funnel duplication: a slot (e.g. the page\n * `welcome`) has alternate versions filed as siblings (`welcome@b.tsx`), and the\n * runtime shows **one** of them per visitor, collapsing the losers out of the\n * linear flow. The flow keeps stable **slot keys** (the control's key); only the\n * rendered component swaps — so routing, the manifest, and analytics all key on the\n * slot, not the variant.\n *\n * **Where the wiring lives:** the *variant pages* are code (compiled into the\n * bundle). The *experiment wiring* — slot, variant→page map, weights, status — is\n * **operational data the platform owns** (a DB record, edited by the dashboard,\n * changed without recompiling the funnel). The SDK is storage-agnostic: the\n * platform hands the runtime experiment records to `FunnelProvider`, the same way\n * it hands in resolved product prices. This module just resolves them.\n *\n * **The only source-side marker** is the `@` in a variant file's key\n * (`welcome@b`): it tells the *build* (manifest, flow graph) that a page is an\n * off-flow variant of its slot, so the structure is correct without the DB. The\n * label/weight/experiment-id are not in source.\n *\n * Bucketing is a deterministic FNV-1a hash, **namespaced by experiment id** so\n * independent experiments bucket orthogonally (the basis for layering 100+ tests,\n * §4.3). The seed is the durable identity ({@link bucketingSeed}) — never the\n * session/fingerprint — so a returning visitor keeps their variant (landmine #4).\n * Stability across an *add-a-variant* edit is the platform's job: an experiment's\n * variant set is immutable while running (reweighting / adding an arm = a new\n * experiment version), so within one record the assignment never moves.\n *\n * This module is pure (no React, no I/O) → it unit-tests trivially and the\n * dashboard/server can reuse the same assignment math.\n */\n\nimport type { FunnelContext } from '../state/context'\n\n// ── Hashing ──────────────────────────────────────────────\n\n/**\n * FNV-1a 32-bit hash → unsigned int. Deterministic and isomorphic (no `crypto`,\n * runs the same in the browser, a worker, and a build). The same math v0 used,\n * kept because it's sound — only the *seed* changes (identity, not session).\n */\nexport function fnv1a(input: string): number {\n let h = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i)\n // h *= 16777619, in uint32, via shift-adds.\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0\n }\n return h >>> 0\n}\n\n/** Map a seed string to a stable float in `[0, 1)`. */\nexport function hashToUnit(seed: string): number {\n return fnv1a(seed) / 0x1_0000_0000\n}\n\n/**\n * Pick a variant key by weight from a stable unit position `u ∈ [0,1)`. Variants\n * are walked in declaration order and the first whose cumulative weight band\n * contains `u` wins, so the same `u` always lands in the same variant.\n */\nexport function pickByWeight(weights: Record<string, number>, u: number): string {\n const entries = Object.entries(weights).filter(([, w]) => w > 0)\n if (entries.length === 0) return Object.keys(weights)[0] ?? ''\n const total = entries.reduce((sum, [, w]) => sum + w, 0)\n const target = u * total\n let acc = 0\n for (const [key, w] of entries) {\n acc += w\n if (target < acc) return key\n }\n return entries[entries.length - 1][0]\n}\n\n/**\n * Deterministically assign a visitor (`seed`) to a variant of one experiment.\n * The hash is **namespaced by `experimentId`** so two experiments on the same\n * traffic don't correlate (orthogonal layering).\n */\nexport function assignVariant(\n experimentId: string,\n seed: string,\n weights: Record<string, number>,\n): string {\n return pickByWeight(weights, hashToUnit(`${experimentId}:${seed}`))\n}\n\n// ── Seed + slot parsing ──────────────────────────────────\n\n/**\n * The stable bucketing seed: the known `customerId`, else the signed `visitorId`.\n * Never the session id or fingerprint (landmine #4). `null` when neither is known\n * — the caller then serves control instead of bucketing on nothing.\n */\nexport function bucketingSeed(context: FunnelContext): string | null {\n return context.identity.customerId ?? context.identity.visitorId ?? null\n}\n\n/** Split a page key into its slot + optional variant: `welcome@b` → `{ slot, variant: 'b' }`. */\nexport function parseSlotKey(key: string): { slot: string; variant?: string } {\n const at = key.indexOf('@')\n return at === -1 ? { slot: key } : { slot: key.slice(0, at), variant: key.slice(at + 1) }\n}\n\n/** True if a page key is an off-flow variant (`welcome@b`), by the source-side `@` marker. */\nexport function isVariantKey(key: string): boolean {\n return parseSlotKey(key).variant !== undefined\n}\n\n// ── Runtime experiment records (platform/DB-sourced) ─────\n\n/** One arm of an experiment: which page renders, at what weight. */\nexport interface ExperimentVariant {\n /** The page key this arm renders (the slot's control, or a `@variant` sibling). */\n page: string\n /** Relative weight in the split (need not sum to 100; zero = paused arm). */\n weight: number\n}\n\n/**\n * A runtime experiment record — the operational wiring the **platform** owns and\n * hands to the SDK (not authored in the funnel source). The variant *pages* are\n * code in the bundle; this is the live config over them.\n */\nexport interface RuntimeExperiment {\n id: string\n /** The page key holding the flow position (the anchor / control). */\n slot: string\n /** label → arm. One arm's `page` is the `slot` (control); others are `@variant` siblings. */\n variants: Record<string, ExperimentVariant>\n /** Lifecycle. Absent = running. */\n status?: 'running' | 'paused' | 'stopped'\n /** When stopped, the variant label everyone sees until promotion bakes it into the slot. */\n winner?: string\n /** Primary metric (analytics only; not used for resolution). */\n metric?: string\n}\n\n// ── Flow resolution ──────────────────────────────────────\n\nexport interface ExperimentResolution {\n /** experiment id → assigned variant label. */\n assignments: Record<string, string>\n /** Page keys forming the effective linear flow (variant siblings removed), in order. */\n activeKeys: string[]\n /** Slot key → the page key whose component should render there. */\n render: Record<string, string>\n /** Variant page key → its slot key. For remapping a route that targets a variant. */\n slotOf: Record<string, string>\n /** Slot key → the experiment id it hosts (drives the exposure event). */\n experimentOf: Record<string, string>\n}\n\n/** Weights map (label → weight) for one experiment's arms. */\nfunction weightsOf(exp: RuntimeExperiment): Record<string, number> {\n const out: Record<string, number> = {}\n for (const [label, v] of Object.entries(exp.variants)) out[label] = v.weight\n return out\n}\n\n/**\n * Resolve which page version each experiment slot shows for this visitor, and\n * which page keys remain in the linear flow.\n *\n * Variant pages are detected structurally by the `@` in their key, so they\n * collapse out of the linear flow even for a slot with no active experiment.\n * For each *running* experiment the visitor is bucketed (stable on `seed`); a\n * *stopped* one serves its `winner`; a *paused* one (or no seed) serves the slot.\n */\nexport function resolveExperiments(\n pages: { key: string }[],\n experiments: RuntimeExperiment[],\n seed: string | null,\n): ExperimentResolution {\n const assignments: Record<string, string> = {}\n const render: Record<string, string> = {}\n const experimentOf: Record<string, string> = {}\n\n for (const exp of experiments) {\n const status = exp.status ?? 'running'\n let label: string\n if (status === 'stopped' && exp.winner) label = exp.winner\n else if (status === 'running' && seed) label = assignVariant(exp.id, seed, weightsOf(exp))\n else continue // paused, or no seed → the slot renders its own (control) page\n\n const arm = exp.variants[label]\n if (!arm) continue\n assignments[exp.id] = label\n experimentOf[exp.slot] = exp.id\n if (arm.page !== exp.slot) render[exp.slot] = arm.page // swap only when a non-control arm won\n }\n\n // Variant siblings (`@`) never stand alone in the linear flow.\n const slotOf: Record<string, string> = {}\n const activeKeys: string[] = []\n for (const p of pages) {\n const { slot, variant } = parseSlotKey(p.key)\n if (variant !== undefined) slotOf[p.key] = slot\n else activeKeys.push(p.key)\n }\n\n return { assignments, activeKeys, render, slotOf, experimentOf }\n}\n\n// ── Validation ───────────────────────────────────────────\n\n/** One referential problem with an experiment record. */\nexport interface ExperimentIssue {\n /** The offending experiment id (`'*'` for a cross-experiment issue). */\n experimentId: string\n code:\n | 'slot_missing' // slot is not a page in the funnel\n | 'slot_is_variant' // slot points at an `@variant`, not a real flow page\n | 'slot_conflict' // two experiments target the same slot\n | 'duplicate_id' // two experiments share an id (bucketing namespace collision)\n | 'variant_page_missing' // a variant references a page that doesn't exist (dangling)\n | 'variant_slot_mismatch' // a variant's `@`-page belongs to a different slot\n | 'no_control' // no arm renders the slot itself (the baseline)\n | 'no_traffic' // every arm has weight ≤ 0\n | 'negative_weight' // an arm has a negative weight\n | 'bad_winner' // a stopped experiment's winner isn't one of its variants\n | 'single_arm' // only one variant — nothing to test (warning)\n | 'orphan_variant' // a `@variant` page no running experiment renders (warning)\n message: string\n}\n\nexport interface ExperimentValidation {\n ok: boolean\n errors: ExperimentIssue[]\n warnings: ExperimentIssue[]\n}\n\n/**\n * Cross-check experiment records against the funnel's pages — the publish-time /\n * experiment-edit gate that catches the dangling references the runtime can't see\n * (the experiment wiring lives in the DB; the pages live in the build, so they can\n * drift). Pure: hand it the runtime experiments + the funnel's page keys (e.g.\n * `manifest.pages`).\n *\n * Errors block; warnings inform. `orphan_variant` is a warning, not an error — a\n * `@variant` file with no running experiment is dead-but-harmless (a paused test, or\n * one not wired yet).\n */\nexport function validateExperiments(\n experiments: RuntimeExperiment[],\n pages: { key: string }[],\n): ExperimentValidation {\n const errors: ExperimentIssue[] = []\n const warnings: ExperimentIssue[] = []\n const pageKeys = new Set(pages.map((p) => p.key))\n\n const seenIds = new Set<string>()\n const slotOwner = new Map<string, string>()\n const renderedVariantPages = new Set<string>() // arm pages that are `@variant`s\n\n for (const exp of experiments) {\n const err = (code: ExperimentIssue['code'], message: string) =>\n errors.push({ experimentId: exp.id, code, message })\n const warn = (code: ExperimentIssue['code'], message: string) =>\n warnings.push({ experimentId: exp.id, code, message })\n\n if (seenIds.has(exp.id)) err('duplicate_id', `Experiment id \"${exp.id}\" is used more than once.`)\n seenIds.add(exp.id)\n\n // Slot must be a real flow page (not missing, not itself a variant).\n if (!pageKeys.has(exp.slot)) err('slot_missing', `Slot \"${exp.slot}\" is not a page in the funnel.`)\n if (isVariantKey(exp.slot)) err('slot_is_variant', `Slot \"${exp.slot}\" is a variant page; a slot must be a real flow page.`)\n if (slotOwner.has(exp.slot)) {\n err('slot_conflict', `Slot \"${exp.slot}\" is already targeted by experiment \"${slotOwner.get(exp.slot)}\".`)\n } else {\n slotOwner.set(exp.slot, exp.id)\n }\n\n const arms = Object.entries(exp.variants)\n if (arms.length < 2) warn('single_arm', `Experiment \"${exp.id}\" has fewer than two variants — nothing to test.`)\n\n let hasControl = false\n let totalWeight = 0\n for (const [label, arm] of arms) {\n if (!pageKeys.has(arm.page)) {\n err('variant_page_missing', `Variant \"${label}\" references page \"${arm.page}\", which doesn't exist.`)\n }\n if (arm.page === exp.slot) hasControl = true\n else if (isVariantKey(arm.page)) {\n renderedVariantPages.add(arm.page)\n if (parseSlotKey(arm.page).slot !== exp.slot) {\n err('variant_slot_mismatch', `Variant \"${label}\" page \"${arm.page}\" belongs to a different slot than \"${exp.slot}\".`)\n }\n }\n if (arm.weight < 0) err('negative_weight', `Variant \"${label}\" has a negative weight (${arm.weight}).`)\n totalWeight += arm.weight\n }\n if (!hasControl) err('no_control', `No variant of \"${exp.id}\" renders the slot \"${exp.slot}\" itself (the control/baseline).`)\n if (totalWeight <= 0) err('no_traffic', `Experiment \"${exp.id}\" has no positive weight — no traffic would enter it.`)\n\n if (exp.status === 'stopped' && exp.winner && !exp.variants[exp.winner]) {\n err('bad_winner', `Stopped experiment \"${exp.id}\" names winner \"${exp.winner}\", which isn't one of its variants.`)\n }\n }\n\n // A `@variant` page that no running experiment renders is dead (but harmless).\n const running = new Set(experiments.filter((e) => (e.status ?? 'running') === 'running').flatMap((e) =>\n Object.values(e.variants).map((v) => v.page),\n ))\n for (const p of pages) {\n if (isVariantKey(p.key) && !running.has(p.key)) {\n warnings.push({ experimentId: '*', code: 'orphan_variant', message: `Variant page \"${p.key}\" is rendered by no running experiment.` })\n }\n }\n\n return { ok: errors.length === 0, errors, warnings }\n}\n","import {\n createContext,\n createElement,\n lazy,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useTransition,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport { useFunnel } from '../state/namespaces'\nimport { newEventId, useTrackerRef } from '../tracking/tracking'\nimport { entryGuard, evaluateGate, expectedPathLength, nextPage, outgoingKeys, type FlowPage, type PageMeta } from './spine'\nimport { bucketingSeed, resolveExperiments } from './experiments'\nimport type { PageContext } from '../state/context'\n\n/** What a page's `load` resolves to — a component, or a module default-exporting one. */\nexport type PageModule = ComponentType | { default: ComponentType }\n\n/**\n * A page wired into the runtime. Provide **either** an eager `Component` (small\n * funnels, tests) **or** a lazy `load` (code-split: the renderer hands a dynamic\n * `import()` so a big funnel ships one chunk per page, not the whole funnel).\n */\nexport interface RuntimePage {\n key: string\n meta?: PageMeta\n /** Eager component. Provide this or `load`. */\n Component?: ComponentType\n /** Lazy loader for a code-split chunk. Provide this or `Component`. */\n load?: () => Promise<PageModule>\n}\n\nexport interface NavigationState {\n /** The current page's read-only context (key, index, total, progress). */\n page: PageContext\n /** Advance via the current page's `next` predicate, else the linear next. */\n next: () => void\n /** Go to the previous page in history. */\n back: () => void\n /** Jump to a specific page key. */\n go: (key: string) => void\n /** Warm a page's code-split chunk ahead of navigation (e.g. on link hover). No-op for eager pages. */\n prefetch: (key: string) => void\n /**\n * The page keys the visitor could go to next, already resolved to the chunk that\n * would render (experiment variant applied). The **renderer** maps these to chunk\n * URLs and emits `<link rel=\"modulepreload\">` (the browser-native, non-executing,\n * SSR-able prefetch — see v0 `HeadlessFunnelRenderer`). The SDK's `load()`-based\n * `prefetch` is the fallback for mounts without a modulepreload manager.\n */\n nextCandidates: string[]\n canGoBack: boolean\n /**\n * True while a navigation's target page chunk is still resolving (a cold,\n * un-prefetched lazy chunk). The current page stays on screen during this window\n * (no Suspense-fallback flicker); read this to show a subtle \"working\" affordance\n * so a tapped button doesn't feel dead. Usually false/instant when the next chunk\n * was prefetched.\n */\n isNavigating: boolean\n}\n\nconst NavContext = createContext<NavigationState | null>(null)\n\n/** experiment id → the variant this visitor is bucketed into, for the live render. */\nconst ExperimentContext = createContext<Record<string, string>>({})\n\n/**\n * `const variant = useExperiment('welcome-headline')` — the variant key this\n * visitor is assigned in an experiment (`undefined` if not in one). Page-variant\n * swapping is automatic; this is for branching *within* a page or custom logging.\n */\nexport function useExperiment(id: string): string | undefined {\n return useContext(ExperimentContext)[id]\n}\n\n/**\n * Compute the read-only page context for a position in the flow. `total` is the\n * **expected** path length for the visitor's current answers (see\n * {@link expectedPathLength}) — not the raw file count — so progress reaches 100%\n * on whichever branch the funnel actually takes. Clamped so a visitor who jumped\n * past the traced path can't read above 100%.\n */\nfunction pageContextFor(\n currentKey: string,\n slug: string,\n index: number,\n total: number,\n startedAt: number,\n): PageContext {\n const denom = Math.max(total, index + 1)\n return {\n key: currentKey,\n slug,\n index,\n total: denom,\n progressPercentage: denom > 0 ? Math.min(100, Math.round(((index + 1) / denom) * 100)) : 0,\n startedAt,\n }\n}\n\n/**\n * Renders the funnel: shows the current page and drives navigation. `next()`\n * resolves the current page's `next` predicate against the live snapshot\n * (writable namespaces + read-only `context`), falling back to the linear next\n * page in file order (see {@link nextPage}).\n *\n * Auto-emits `funnel.start` on mount and `page.view` on each page change, and\n * keeps `context.page` in sync so predicates and `usePage()` see the live page.\n *\n * Pass a `layout` (a `{ children }` component) for **persistent chrome** — a\n * header, progress bar, background — rendered *inside* the nav context but\n * *outside* the page swap, so it mounts once and never remounts on navigation\n * (and can read `usePage`/`useNavigation`).\n *\n * Must live inside `<FunnelProvider>`.\n */\nexport function FunnelView({\n pages,\n initialKey,\n layout,\n fallback,\n prefetch: prefetchMode = 'auto',\n onNavigate,\n}: {\n pages: RuntimePage[]\n initialKey?: string\n layout?: ComponentType<{ children: ReactNode }>\n /** Shown in the page area while a lazy page's chunk loads (the layout persists around it). */\n fallback?: ReactNode\n /**\n * `'auto'` (default): the SDK warms next-likely chunks by calling `load()`.\n * `'off'`: the **renderer** owns prefetch (via `<link rel=\"modulepreload\">` over\n * `useNavigation().nextCandidates`) — avoids the redundant `load()` execution.\n */\n prefetch?: 'auto' | 'off'\n /**\n * Fires on every page change (incl. the initial page) with the current page key\n * + slug. The **renderer** uses it to sync the URL path (`history.replaceState`,\n * v0-style — funnel back is in-memory, not browser history). Fires for the\n * *resolved* page, so if an entry `guard` bounced a deep-link to the start, the\n * URL gets corrected.\n */\n onNavigate?: (key: string, slug: string) => void\n}): ReactNode {\n const funnel = useFunnel()\n const tracker = useTrackerRef()\n\n // Resolve each page to a renderable component: eager `Component` as-is, or a\n // stable `React.lazy` over `load` (memoized so the lazy element identity is\n // stable across renders → no remount). `loaders` keeps the raw `load` fns for\n // prefetch (dynamic import dedupes, so calling them early just warms the chunk).\n const components = useMemo(() => {\n const map = new Map<string, ComponentType>()\n for (const p of pages) {\n if (p.Component) map.set(p.key, p.Component)\n else if (p.load) {\n const load = p.load\n map.set(p.key, lazy(() => Promise.resolve(load()).then((m) =>\n typeof m === 'function' ? { default: m } : m,\n )))\n }\n }\n return map\n }, [pages])\n const loaders = useMemo(\n () => new Map(pages.filter((p) => p.load).map((p) => [p.key, p.load!])),\n [pages],\n )\n\n // Resolve page-level experiments once for this visitor: which variant of each\n // slot to show, and which variant pages drop out of the linear flow. Stable for\n // the render — the seed is the durable identity, memoized so a later\n // identification can't flip an in-progress visitor's variant.\n const seed = bucketingSeed(funnel.context)\n const experiments = useMemo(\n () => resolveExperiments(pages, funnel.experiments, seed),\n [pages, funnel.experiments, seed],\n )\n const pageByKey = useMemo(() => new Map(pages.map((p) => [p.key, p])), [pages])\n // The effective flow: anchors + standalone pages, in order (losers removed).\n const flowPages = useMemo<RuntimePage[]>(\n () => experiments.activeKeys.map((k) => pageByKey.get(k)!).filter(Boolean),\n [experiments, pageByKey],\n )\n\n // The flow as plain {key, meta} for routing + path-length tracing.\n const flow = useMemo<FlowPage[]>(\n () => flowPages.map((p) => ({ key: p.key, meta: p.meta })),\n [flowPages],\n )\n\n // Resolve the starting page. A deep-link / reload `initialKey` is honored only if\n // the page's entry `guard` passes against the (restored) snapshot — else fall\n // back to the start page. (In-funnel navigation never hits this; routing gated it.)\n const [history, setHistory] = useState<string[]>(() => {\n const start = flowPages[0]?.key\n if (!initialKey || initialKey === start) return [start].filter(Boolean) as string[]\n const target = experiments.slotOf[initialKey] ?? initialKey\n const page = flowPages.find((p) => p.key === target)\n // Effective guard = the page-type default (paywall/upsell need email) AND any\n // explicit meta.guard.\n const guard = entryGuard(page?.meta)\n const ok = page && (!guard || evaluateGate(guard, funnel.snapshot()))\n return [ok ? target : start].filter(Boolean) as string[]\n })\n const currentKey = history[history.length - 1]\n const index = history.length - 1\n const startKey = history[0]\n\n // Expected path length for the visitor's current answers — re-traced per\n // navigation so progress reaches 100% on whichever branch the funnel takes.\n const total = useMemo(\n () => expectedPathLength(flow, startKey, funnel.snapshot()),\n // currentKey in deps: re-trace as each step's answers settle the branch.\n [flow, startKey, currentKey, funnel],\n )\n\n // Keep the read-only context's `page` slice current so predicates + usePage see it.\n const slug = pageByKey.get(currentKey)?.meta?.slug ?? currentKey\n const page = useMemo(\n () => pageContextFor(currentKey, slug, index, total, funnel.context.system.now),\n [currentKey, slug, index, total, funnel.context.system.now],\n )\n // context.page is mutable internal state of the read-only namespace.\n funnel.context.page = page\n\n // funnel.start once, on mount.\n const started = useRef(false)\n useEffect(() => {\n if (started.current) return\n started.current = true\n tracker.track('funnel.start', {})\n }, [tracker])\n\n // page.view on every page change.\n useEffect(() => {\n if (!currentKey) return\n tracker.track('page.view', { pageId: currentKey, pageKey: currentKey, isInitial: index === 0, eventId: newEventId() })\n }, [tracker, currentKey, index])\n\n // Tell the renderer the live page (key + slug) so it can sync the URL path.\n useEffect(() => {\n if (currentKey && onNavigate) onNavigate(currentKey, slug)\n }, [onNavigate, currentKey, slug])\n\n // experiment.exposure the first time the visitor lands on an experiment slot.\n const exposed = useRef<Set<string>>(new Set())\n useEffect(() => {\n const expId = experiments.experimentOf[currentKey]\n if (!expId || exposed.current.has(expId)) return\n exposed.current.add(expId)\n tracker.track('experiment.exposure', { experimentId: expId, variant: experiments.assignments[expId] })\n }, [tracker, currentKey, experiments])\n\n // page.exit timing — wall-clock duration on a page, minus time the tab was\n // hidden (active engagement). Uses a real clock (effects only, never render).\n const timer = useRef<{ key: string; enteredAt: number; hidden: number; hiddenSince: number | null } | null>(null)\n const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now())\n const emitExit = useCallback(() => {\n const t = timer.current\n if (!t) return\n const at = now()\n const hidden = t.hidden + (t.hiddenSince != null ? at - t.hiddenSince : 0)\n const durationMs = Math.round(at - t.enteredAt)\n tracker.track('page.exit', { pageId: t.key, durationMs, activeMs: Math.max(0, Math.round(durationMs - hidden)) })\n }, [tracker])\n\n // Track tab visibility so `activeMs` excludes backgrounded time.\n useEffect(() => {\n if (typeof document === 'undefined') return\n const onVis = () => {\n const t = timer.current\n if (!t) return\n if (document.visibilityState === 'hidden') t.hiddenSince = now()\n else if (t.hiddenSince != null) {\n t.hidden += now() - t.hiddenSince\n t.hiddenSince = null\n }\n }\n document.addEventListener('visibilitychange', onVis)\n return () => document.removeEventListener('visibilitychange', onVis)\n }, [])\n\n // On each page change emit page.exit for the page being left, then start the\n // new page's timer. The final page's exit fires on unmount.\n useEffect(() => {\n if (!currentKey) return\n if (timer.current && timer.current.key !== currentKey) emitExit()\n const hidden = typeof document !== 'undefined' && document.visibilityState === 'hidden'\n timer.current = { key: currentKey, enteredAt: now(), hidden: 0, hiddenSince: hidden ? now() : null }\n }, [currentKey, emitExit])\n\n useEffect(() => () => emitExit(), [emitExit])\n\n // Navigation swaps a code-split page (a lazy chunk). Wrap the history update in a\n // transition so React keeps the CURRENT page on screen until the next page's chunk\n // is ready, instead of flashing the Suspense `fallback` (the inter-page flicker).\n // `isNavigating` is true while a cold chunk resolves → show a \"working\" affordance\n // so the button doesn't feel dead. Prefetch makes this window usually invisible.\n const [isNavigating, startNav] = useTransition()\n const next = useCallback(() => {\n // Route over the effective flow (slots); the slot page's `meta.next` governs\n // routing. Remap any target that points at a collapsed variant key to its slot.\n const target = nextPage(flow, currentKey, funnel.snapshot())\n const resolved = target ? experiments.slotOf[target] ?? target : target\n if (resolved) startNav(() => setHistory((h) => [...h, resolved]))\n }, [flow, currentKey, funnel, experiments])\n\n const back = useCallback(\n () => startNav(() => setHistory((h) => (h.length > 1 ? h.slice(0, -1) : h))),\n [],\n )\n const go = useCallback(\n (key: string) => startNav(() => setHistory((h) => [...h, experiments.slotOf[key] ?? key])),\n [experiments],\n )\n\n // Warm a slot's code-split chunk (the variant that would actually render). Idempotent.\n const prefetched = useRef<Set<string>>(new Set())\n const prefetch = useCallback(\n (key: string) => {\n const target = experiments.render[key] ?? key\n const load = loaders.get(target)\n if (!load || prefetched.current.has(target)) return\n prefetched.current.add(target)\n load().catch(() => prefetched.current.delete(target)) // let a failed load retry later\n },\n [loaders, experiments],\n )\n\n // The next-likely pages, resolved to the chunk that would actually render\n // (experiment variant applied) — the renderer modulepreloads these.\n const nextCandidates = useMemo(\n () => [...new Set(outgoingKeys(flow, currentKey).map((k) => experiments.render[k] ?? k))],\n [flow, currentKey, experiments],\n )\n\n // 'auto' mode: warm those chunks by calling load(). 'off': the renderer owns it.\n useEffect(() => {\n if (prefetchMode !== 'auto') return\n for (const key of nextCandidates) prefetch(key)\n }, [prefetchMode, nextCandidates, prefetch])\n\n const value: NavigationState = {\n page,\n next,\n back,\n go,\n prefetch,\n nextCandidates,\n canGoBack: history.length > 1,\n isNavigating,\n }\n // Render the assigned variant's component at the current slot (the anchor key\n // stays the flow position; only the component swaps). Lazy pages suspend, so the\n // page area shows `fallback` while the chunk loads — inside the layout, so the\n // persistent chrome stays put.\n const renderKey = experiments.render[currentKey] ?? currentKey\n const Current = components.get(renderKey)\n const pageEl = createElement(Suspense, { fallback: fallback ?? null }, Current ? createElement(Current) : null)\n // The layout wraps the page inside NavContext → it persists across navigation\n // (same element type, only the page child swaps) and can use nav/funnel hooks.\n const content = layout ? createElement(layout, null, pageEl) : pageEl\n\n return createElement(\n ExperimentContext.Provider,\n { value: experiments.assignments },\n createElement(NavContext.Provider, { value }, content),\n )\n}\n\n/** `const { next, back, go, page } = useNavigation()`. */\nexport function useNavigation(): NavigationState {\n const ctx = useContext(NavContext)\n if (!ctx) throw new Error('useNavigation must be used inside <FunnelView>')\n return ctx\n}\n\n/** `usePage()` — the current page's read-only context, reactive to navigation. */\nexport function usePage(): PageContext {\n return useNavigation().page\n}\n","/**\n * Imperative, promise-based modal registry — our trimmed adaptation of\n * eBay's `@ebay/nice-modal-react` (MIT). The model: a module-level registry +\n * a reducer-backed store, so any code can `showModal(MyModal)` from anywhere\n * (no prop-drilling, no rendering the modal where you trigger it) and get back a\n * **promise** that resolves when the modal calls `resolve()` — perfect for\n * confirm/upsell/detail flows.\n *\n * Every modal is keyed by a **stable id**, which also makes it natural to bind\n * analytics later (open/close per id, like pages).\n *\n * Pair it with the controlled chrome in {@link ./overlay}: a `defineModal`\n * component renders a `<Sheet open={m.visible} onClose={m.hide}>`/`<Modal>`.\n * The runtime ({@link ./namespaces}.FunnelProvider) mounts {@link ModalRoot} for\n * you, so there's no provider to wire.\n *\n * Trimmed vs upstream: dropped the antd/mui/bootstrap binding adapters and the\n * standalone `<Provider>` (folded into the funnel runtime).\n */\n\nimport {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n type ComponentType,\n type Dispatch,\n type ReactNode,\n} from 'react'\n\n// ── State ────────────────────────────────────────────────\n\nexport interface ModalState {\n id: string\n args?: Record<string, unknown>\n visible?: boolean\n delayVisible?: boolean\n keepMounted?: boolean\n}\nexport interface ModalStore {\n [id: string]: ModalState\n}\ninterface ModalAction {\n type: 'show' | 'hide' | 'remove' | 'set-flags'\n payload: { modalId: string; args?: Record<string, unknown>; flags?: Record<string, unknown> }\n}\ninterface ModalCallbacks {\n [id: string]: { resolve: (v: unknown) => void; reject: (v: unknown) => void; promise: Promise<unknown> }\n}\n\n/** The handle `useModal()` returns to control one modal. */\nexport interface ModalHandler<Props = Record<string, unknown>> {\n id: string\n args?: Record<string, unknown>\n visible: boolean\n keepMounted: boolean\n show: (args?: Props) => Promise<unknown>\n hide: () => Promise<unknown>\n remove: () => void\n /** Resolve the promise returned by `show()` (e.g. a confirm result). */\n resolve: (value?: unknown) => void\n /** Reject the promise returned by `show()`. */\n reject: (value?: unknown) => void\n /** Resolve the promise returned by `hide()` (after a close transition). */\n resolveHide: (value?: unknown) => void\n}\n\n// ── Module-level registry + dispatch ─────────────────────\n\nconst symModalId = Symbol('AppFunnelModalId')\nconst initialState: ModalStore = {}\nconst ModalStateContext = createContext<ModalStore>(initialState)\nconst ModalIdContext = createContext<string | null>(null)\n\nconst REGISTRY: { [id: string]: { comp: ComponentType<any>; props?: Record<string, unknown> } } = {}\nconst ALREADY_MOUNTED: Record<string, boolean> = {}\nconst modalCallbacks: ModalCallbacks = {}\nconst hideCallbacks: ModalCallbacks = {}\n\nlet uid = 0\nconst getUid = () => `_af_modal_${uid++}`\n\nlet dispatch: Dispatch<ModalAction> = () => {\n throw new Error('No modal dispatch — render inside <FunnelProvider> (which mounts the modal runtime).')\n}\n\nexport const modalReducer = (state: ModalStore = initialState, action: ModalAction): ModalStore => {\n const { modalId, args, flags } = action.payload\n switch (action.type) {\n case 'show':\n return {\n ...state,\n [modalId]: {\n ...state[modalId],\n id: modalId,\n args,\n // Mount first, then flip visible on the next effect → enter transition.\n visible: !!ALREADY_MOUNTED[modalId],\n delayVisible: !ALREADY_MOUNTED[modalId],\n },\n }\n case 'hide':\n return state[modalId] ? { ...state, [modalId]: { ...state[modalId], visible: false } } : state\n case 'remove': {\n const next = { ...state }\n delete next[modalId]\n return next\n }\n case 'set-flags':\n return { ...state, [modalId]: { ...state[modalId], ...flags } }\n default:\n return state\n }\n}\n\nfunction idOf(modal: string | ComponentType<any>): string {\n if (typeof modal === 'string') return modal\n const m = modal as ComponentType<any> & { [symModalId]?: string }\n if (!m[symModalId]) m[symModalId] = getUid()\n return m[symModalId] as string\n}\n\n// ── Imperative API (callable from anywhere) ──────────────\n\n/** Register a component as an id-keyed modal so the placeholder can render it. */\nexport function registerModal(id: string, comp: ComponentType<any>, props?: Record<string, unknown>): void {\n if (!REGISTRY[id]) REGISTRY[id] = { comp, props }\n else REGISTRY[id].props = props\n}\n\nexport function unregisterModal(id: string): void {\n delete REGISTRY[id]\n}\n\n/** Show a modal (by component or id). Returns a promise resolved by `resolve()`. */\nexport function showModal<T = unknown>(modal: string | ComponentType<any>, args?: Record<string, unknown>): Promise<T> {\n const id = idOf(modal)\n if (typeof modal !== 'string' && !REGISTRY[id]) registerModal(id, modal)\n dispatch({ type: 'show', payload: { modalId: id, args } })\n if (!modalCallbacks[id]) {\n let res!: (v: unknown) => void\n let rej!: (v: unknown) => void\n const promise = new Promise<unknown>((resolve, reject) => {\n res = resolve\n rej = reject\n })\n modalCallbacks[id] = { resolve: res, reject: rej, promise }\n }\n return modalCallbacks[id].promise as Promise<T>\n}\n\n/** Hide a modal. Returns a promise resolved by `resolveHide()` (post-transition). */\nexport function hideModal<T = unknown>(modal: string | ComponentType<any>): Promise<T> {\n const id = idOf(modal)\n dispatch({ type: 'hide', payload: { modalId: id } })\n delete modalCallbacks[id]\n if (!hideCallbacks[id]) {\n let res!: (v: unknown) => void\n let rej!: (v: unknown) => void\n const promise = new Promise<unknown>((resolve, reject) => {\n res = resolve\n rej = reject\n })\n hideCallbacks[id] = { resolve: res, reject: rej, promise }\n }\n return hideCallbacks[id].promise as Promise<T>\n}\n\n/** Remove a modal from the tree (frees its state; better than just hiding). */\nexport function removeModal(modal: string | ComponentType<any>): void {\n const id = idOf(modal)\n dispatch({ type: 'remove', payload: { modalId: id } })\n delete modalCallbacks[id]\n delete hideCallbacks[id]\n}\n\nfunction setFlags(id: string, flags: Record<string, unknown>): void {\n dispatch({ type: 'set-flags', payload: { modalId: id, flags } })\n}\n\n// ── Hook ─────────────────────────────────────────────────\n\nexport function useModal(): ModalHandler\nexport function useModal(modal: string, args?: Record<string, unknown>): ModalHandler\nexport function useModal<P extends object>(modal: ComponentType<P>, args?: Partial<P>): ModalHandler<P>\nexport function useModal(modal?: string | ComponentType<any>, args?: Record<string, unknown>): ModalHandler {\n const modals = useContext(ModalStateContext)\n const contextId = useContext(ModalIdContext)\n const isComponent = !!modal && typeof modal !== 'string'\n const id = modal ? idOf(modal) : contextId\n if (!id) throw new Error('useModal: no modal id (call inside a defineModal component, or pass an id/component).')\n\n useEffect(() => {\n if (isComponent && !REGISTRY[id]) registerModal(id, modal as ComponentType<any>, args)\n }, [isComponent, id, modal, args])\n\n const info = modals[id]\n const show = useCallback((a?: Record<string, unknown>) => showModal(id, a), [id])\n const hide = useCallback(() => hideModal(id), [id])\n const remove = useCallback(() => removeModal(id), [id])\n const resolve = useCallback((v?: unknown) => {\n modalCallbacks[id]?.resolve(v)\n delete modalCallbacks[id]\n }, [id])\n const reject = useCallback((v?: unknown) => {\n modalCallbacks[id]?.reject(v)\n delete modalCallbacks[id]\n }, [id])\n const resolveHide = useCallback((v?: unknown) => {\n hideCallbacks[id]?.resolve(v)\n delete hideCallbacks[id]\n }, [id])\n\n return useMemo(\n () => ({\n id,\n args: info?.args,\n visible: !!info?.visible,\n keepMounted: !!info?.keepMounted,\n show,\n hide,\n remove,\n resolve,\n reject,\n resolveHide,\n }),\n [id, info?.args, info?.visible, info?.keepMounted, show, hide, remove, resolve, reject, resolveHide],\n )\n}\n\n// ── defineModal (HOC) ────────────────────────────────────\n\nexport interface ModalHocProps {\n id: string\n defaultVisible?: boolean\n keepMounted?: boolean\n}\n\n/**\n * Wrap a component into an id-keyed modal. Inside it, `useModal()` (no args)\n * gives the handle. Render a controlled `<Sheet>`/`<Modal>` with\n * `open={m.visible} onClose={m.hide}`.\n */\nexport function defineModal<P extends object>(Comp: ComponentType<P>): ComponentType<P & ModalHocProps> {\n return function Wrapped({ id, defaultVisible, keepMounted, ...props }: P & ModalHocProps): ReactNode {\n const { args, show } = useModal(id)\n const modals = useContext(ModalStateContext)\n const shouldMount = !!modals[id]\n\n useEffect(() => {\n if (defaultVisible) show()\n ALREADY_MOUNTED[id] = true\n return () => {\n delete ALREADY_MOUNTED[id]\n }\n }, [id, show, defaultVisible])\n\n useEffect(() => {\n if (keepMounted) setFlags(id, { keepMounted: true })\n }, [id, keepMounted])\n\n const delayVisible = modals[id]?.delayVisible\n useEffect(() => {\n if (delayVisible) show(args)\n }, [delayVisible, args, show])\n\n if (!shouldMount) return null\n return createElement(\n ModalIdContext.Provider,\n { value: id },\n createElement(Comp, { ...(props as P), ...args }),\n )\n }\n}\n\n// ── Runtime (mounted by FunnelProvider) ──────────────────\n\n/** Renders every visible registered modal. Mounted once by the funnel runtime. */\nexport function ModalRoot(): ReactNode {\n const modals = useContext(ModalStateContext)\n const toRender = Object.keys(modals)\n .filter((id) => REGISTRY[id])\n .map((id) => ({ id, ...REGISTRY[id] }))\n return createElement(\n 'div',\n { 'data-appfunnel-modal-root': '' },\n ...toRender.map((t) => createElement(t.comp, { key: t.id, id: t.id, ...t.props })),\n )\n}\n\n/**\n * Provides the modal store + sets the module dispatch + renders {@link ModalRoot}.\n * Wrapped around the funnel tree by `FunnelProvider`.\n */\nexport function ModalRuntime({ children }: { children: ReactNode }): ReactNode {\n const [state, localDispatch] = useReducer(modalReducer, initialState)\n dispatch = localDispatch\n return createElement(\n ModalStateContext.Provider,\n { value: state },\n children,\n createElement(ModalRoot, null),\n )\n}\n","/**\n * Raw, **controlled** overlay chrome — `<Sheet>` (a drawer) and `<Modal>` (a\n * centered dialog). Headless and styleable (className/portal/dismiss), the same\n * two-tier contract as `<Choice>`: thin wrappers you restyle or eject.\n *\n * These are the presentation layer. For *imperative*, promise-based modals\n * triggered from anywhere, wrap one in `defineModal` and `showModal(...)`\n * (see {@link ./modals}) — that registry drives these controlled primitives.\n * They're also used directly (no registry) where local state is simpler, e.g.\n * the checkout `sheet` surface.\n *\n * Deliberately minimal: portal to `document.body`, lock body scroll while open,\n * dismiss on Escape / backdrop. No animation engine, no focus-trap dependency.\n */\n\nimport {\n createElement,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { useModal } from './registry'\n\nexport type SheetSide = 'bottom' | 'top' | 'left' | 'right'\n\n/**\n * `<Sheet>`/`<Modal>` bind themselves to the surrounding {@link defineModal} via\n * its context — so inside a modal you write just `<Sheet>…</Sheet>`, with no\n * open/onClose plumbing. They are therefore **only valid inside a `defineModal`**\n * (rendered through `showModal`); used anywhere else `useModal()` throws, which\n * is the correct signal. For an overlay driven by local state, wrap it in a\n * `defineModal` and `showModal` it — that's the one overlay path.\n */\nfunction useModalControl(): { open: boolean; onClose: () => void } {\n const m = useModal()\n return {\n open: m.visible,\n onClose: () => {\n m.hide()\n m.resolveHide()\n if (!m.keepMounted) m.remove()\n },\n }\n}\n\ninterface OverlayCommon {\n className?: string\n backdropClassName?: string\n dismissOnBackdrop?: boolean\n ariaLabel?: string\n children: ReactNode\n}\n\ninterface ShellProps {\n open: boolean\n onClose: () => void\n className?: string\n backdropClassName?: string\n dismissOnBackdrop?: boolean\n ariaLabel?: string\n /** Flexbox alignment of the panel within the viewport. */\n container: Pick<CSSProperties, 'justifyContent' | 'alignItems'>\n /** Panel layout (size + corners per variant). */\n panel: CSSProperties\n children: ReactNode\n}\n\n/** Shared overlay shell: portal, backdrop, scroll-lock, Escape — variant-agnostic. */\nfunction OverlayShell({\n open,\n onClose,\n className,\n backdropClassName,\n dismissOnBackdrop = true,\n ariaLabel,\n container,\n panel,\n children,\n}: ShellProps): ReactNode {\n useEffect(() => {\n if (!open || typeof document === 'undefined') return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n document.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = prev\n document.removeEventListener('keydown', onKey)\n }\n }, [open, onClose])\n\n if (!open || typeof document === 'undefined') return null\n\n const overlay = createElement(\n 'div',\n {\n role: 'dialog',\n 'aria-modal': true,\n 'aria-label': ariaLabel,\n 'data-appfunnel-overlay': '',\n style: { position: 'fixed', inset: 0, zIndex: 1000, display: 'flex', ...container },\n },\n createElement('div', {\n 'data-appfunnel-overlay-backdrop': '',\n className: backdropClassName,\n onClick: dismissOnBackdrop ? onClose : undefined,\n style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)' },\n }),\n createElement(\n 'div',\n { 'data-appfunnel-overlay-panel': '', className, style: { position: 'relative', background: '#fff', ...panel } },\n children,\n ),\n )\n\n return createPortal(overlay, document.body)\n}\n\nexport type SheetProps = OverlayCommon & {\n /** Edge the drawer slides from (default `bottom`). */\n side?: SheetSide\n}\n\nconst SHEET_LAYOUT: Record<SheetSide, { container: ShellProps['container']; panel: CSSProperties }> = {\n bottom: { container: { justifyContent: 'flex-end', alignItems: 'stretch' }, panel: { borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 16, maxHeight: '90vh', overflow: 'auto' } },\n top: { container: { justifyContent: 'flex-start', alignItems: 'stretch' }, panel: { borderBottomLeftRadius: 16, borderBottomRightRadius: 16, padding: 16, maxHeight: '90vh', overflow: 'auto' } },\n left: { container: { justifyContent: 'flex-start', alignItems: 'stretch' }, panel: { height: '100%', width: 'min(420px, 90vw)', padding: 16, overflow: 'auto' } },\n right: { container: { justifyContent: 'flex-end', alignItems: 'stretch' }, panel: { height: '100%', width: 'min(420px, 90vw)', padding: 16, overflow: 'auto' } },\n}\n\n/**\n * An edge-anchored drawer. Inside a `defineModal` it auto-binds — `<Sheet>…`;\n * outside one, control it with `open`/`onClose`.\n */\nexport function Sheet(props: SheetProps): ReactNode {\n const control = useModalControl()\n const layout = SHEET_LAYOUT[props.side ?? 'bottom']\n return createElement(OverlayShell, {\n ...control,\n className: props.className,\n backdropClassName: props.backdropClassName,\n dismissOnBackdrop: props.dismissOnBackdrop,\n ariaLabel: props.ariaLabel,\n container: layout.container,\n panel: layout.panel,\n children: props.children,\n })\n}\n\nexport type ModalProps = OverlayCommon\n\n/** A centered dialog. Auto-binds to its `defineModal` — `<Modal>…`. */\nexport function Modal(props: ModalProps): ReactNode {\n const control = useModalControl()\n return createElement(OverlayShell, {\n ...control,\n className: props.className,\n backdropClassName: props.backdropClassName,\n dismissOnBackdrop: props.dismissOnBackdrop,\n ariaLabel: props.ariaLabel,\n container: { justifyContent: 'center', alignItems: 'center' },\n panel: { borderRadius: 16, padding: 24, width: 'min(480px, 92vw)', maxHeight: '90vh', overflow: 'auto' },\n children: props.children,\n })\n}\n","/**\n * v2 commerce primitives — the two intents from phase-3, made trivial.\n *\n * - `<Checkout product surface>` — the **purchase** primitive. The `surface`\n * prop picks presentation; some surfaces render **inline** (express wallets,\n * inline card, provider iframe), some **open on click** (sheet/popup/redirect).\n * `<Checkout>` covers both: it renders inline surfaces and renders a trigger\n * button for the rest (`asChild` to use your own button).\n * - `<Upsell product>` — the **upsell** primitive. Off-session charge to the\n * saved method, no card re-entry, one tap.\n * - `useCheckout()` — the headless hook under both, always available for a\n * fully-custom CTA.\n *\n * The SDK never talks to a provider. It owns the state machine + the analytics\n * (`checkout.start` / `purchase.complete`) + post-charge navigation, and\n * delegates the actual charge/render to an injected {@link CheckoutDriver}\n * (the real one is platform-side; tests use {@link createMockDriver}).\n *\n * Which product is charged is the author's bound variable, captured at render\n * (inline surfaces) or at `open()` time (trigger surfaces).\n */\n\nimport {\n createContext,\n createElement,\n isValidElement,\n cloneElement,\n useCallback,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { useTrackerRef } from '../tracking/tracking'\nimport { useNavigation } from '../flow/flow'\nimport { Sheet } from '../modals/sheet'\nimport { defineModal, useModal, showModal } from '../modals/registry'\n\n// ── Surfaces, providers, capability matrix ───────────────\n\nexport type CheckoutSurface =\n | 'express' // wallet quick-buttons (Apple/Google Pay) — inline\n | 'element' // inline card form — inline\n | 'embedded' // provider-managed inline checkout — inline\n | 'sheet' // bottom-sheet popup — opens on click\n | 'popup' // provider-hosted overlay — opens on click\n | 'redirect' // provider-hosted page — opens on click\n\nexport type CheckoutProvider = 'stripe' | 'paddle' | 'whop' | 'primer' | 'solidgate'\nexport type CheckoutIntent = 'purchase' | 'upsell'\n\n/** Surfaces that render inline (vs. those that open on click). */\nexport const INLINE_SURFACES: ReadonlySet<CheckoutSurface> = new Set<CheckoutSurface>([\n 'express',\n 'element',\n 'embedded',\n])\n\nexport function isInlineSurface(surface: CheckoutSurface): boolean {\n return INLINE_SURFACES.has(surface)\n}\n\n/**\n * The kind of off-session upsell (researched against Funnelfox's changelog, which\n * ships these as distinct features). The discriminating real-world constraint is\n * **stacking a 2nd concurrent subscription** — Paddle can't, SolidGate/Stripe can.\n */\nexport type UpsellKind =\n | 'subscription' // charge a NEW, 2nd concurrent subscription off-session (stacking)\n | 'one-time' // charge a one-time add-on off-session\n | 'upgrade' // change the existing subscription's plan\n\n/** Reliability of an off-session upsell charge AFTER a purchase on a surface. */\nexport type OffSessionReliability =\n | 'reliable' // we hold the saved method (Stripe Elements / SolidGate / Primer) or the provider charges it (Paddle / Whop API)\n | 'conditional' // possible but may decline — Stripe **managed** checkout: the upsell is a direct off-session charge against Stripe's vaulted card (SCA / setup_future_usage not guaranteed)\n | 'none'\n\nexport interface SurfaceCapability {\n purchase: boolean\n /** Apple/Google Pay available on this surface. */\n wallets: boolean\n /** Reliability of an off-session upsell after a purchase on this surface. */\n offSession: OffSessionReliability\n}\n\nexport interface ProviderProfile {\n /** Merchant-of-Record (handles tax/compliance) vs. a PSP you settle through. */\n isMoR: boolean\n /** Upsell kinds this provider can charge off-session (one-click, no re-entry). */\n offSessionUpsells: UpsellKind[]\n /** Who charges the saved method off-session: you (PSP) or the provider (MoR/managed). */\n tokenModel: 'merchant' | 'provider'\n /** Routes across multiple processors (Primer; SolidGate also offers this) vs. a single acquirer. */\n orchestrator: boolean\n /** Supported surfaces → per-surface capabilities. **Absent = not supported.** */\n surfaces: Partial<Record<CheckoutSurface, SurfaceCapability>>\n}\n\n/** Reliable off-session after this surface (we/the provider hold a chargeable method). */\nconst ON: SurfaceCapability = { purchase: true, wallets: true, offSession: 'reliable' }\n/** Stripe-managed checkout: a purchase works, but the off-session upsell may decline. */\nconst MANAGED: SurfaceCapability = { purchase: true, wallets: true, offSession: 'conditional' }\nconst ALL_UPSELLS: UpsellKind[] = ['subscription', 'one-time', 'upgrade']\n\n/**\n * Provider capabilities (researched 2026-06-23 against provider docs + Funnelfox).\n *\n * Three real-world corrections to the naive model:\n * 1. **Off-session upsell support is per-provider by *kind*** (`offSessionUpsells`):\n * Paddle can't stack a 2nd concurrent subscription (upgrade + one-time only);\n * Stripe/SolidGate/Whop/Primer can do all kinds.\n * 2. **Off-session *reliability* varies by the paywall surface** (`SurfaceCapability.\n * offSession`): Stripe **managed** checkout (`embedded`/`redirect`) upsells as a\n * direct charge against Stripe's vault → `conditional` (may decline); Elements\n * surfaces are `reliable`.\n * 3. **Surface availability is a hard constraint.** MoR/managed providers can't\n * expose a raw card field to your own UI: Paddle has no `express`/`element`/your\n * `sheet`; Whop has no raw `element`/`express`; Primer has no hosted `redirect`;\n * Stripe/SolidGate have no `popup`. A missing entry means \"not possible.\"\n */\nexport const PROVIDER_PROFILES: Record<CheckoutProvider, ProviderProfile> = {\n // PSP; you hold the PaymentMethod and fire your own off-session PaymentIntent on\n // the Elements surfaces (reliable). **Managed** Checkout (`embedded`/`redirect`)\n // upsells too, but as a direct charge against Stripe's vaulted card → conditional.\n // No provider \"popup\" surface.\n stripe: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: false,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: MANAGED, redirect: MANAGED },\n },\n // Merchant-of-Record; card entry is always Paddle's frame → no own element/sheet/\n // express. Off-session via subscription one-time charge / collection_mode, but\n // **no 2nd concurrent subscription** (upgrade + one-time only), provider-initiated.\n paddle: {\n isMoR: true, offSessionUpsells: ['one-time', 'upgrade'], tokenModel: 'provider', orchestrator: false,\n surfaces: { embedded: ON, popup: ON, redirect: ON },\n },\n // Merchant-of-Record; iframe-only (no raw card field). Off-session works\n // (provider-initiated, async via webhooks). `sheet` = our chrome hosting their embed.\n whop: {\n isMoR: true, offSessionUpsells: ALL_UPSELLS, tokenModel: 'provider', orchestrator: false,\n surfaces: { embedded: ON, redirect: ON, sheet: ON },\n },\n // Pure orchestrator (PSP-side); Headless renders express/element/sheet/embedded.\n // No hosted redirect page, no popup checkout. Off-session is PSP-conditional.\n primer: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: true,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: ON },\n },\n // PSP **and** orchestrator (own acquiring + connectors routing across Stripe/Adyen/\n // PayPal). One Payment Form (element/sheet/embedded) + hosted page + wallet button.\n // Strong native off-session (Recurring API). No popup.\n solidgate: {\n isMoR: false, offSessionUpsells: ALL_UPSELLS, tokenModel: 'merchant', orchestrator: true,\n surfaces: { express: ON, element: ON, sheet: ON, embedded: ON, redirect: ON },\n },\n}\n\nexport interface ValidationResult {\n ok: boolean\n reason?: string\n /** Non-fatal caveat (e.g. Paddle upgrade-only). */\n note?: string\n}\n\n/** Surfaces a provider supports, for the editor/AI to steer authors. */\nexport function surfacesFor(provider: CheckoutProvider): CheckoutSurface[] {\n return Object.keys(PROVIDER_PROFILES[provider]?.surfaces ?? {}) as CheckoutSurface[]\n}\n\n/** Whether a provider is a Merchant of Record (it owns tax/compliance). */\nexport function isMerchantOfRecord(provider: CheckoutProvider): boolean {\n return PROVIDER_PROFILES[provider]?.isMoR ?? false\n}\n\n/** Whether a provider routes across multiple processors (Primer, SolidGate). */\nexport function isOrchestrator(provider: CheckoutProvider): boolean {\n return PROVIDER_PROFILES[provider]?.orchestrator ?? false\n}\n\n/**\n * Validate a (provider, surface) for a **purchase**: the surface must exist for\n * the provider and accept a payment. Surface availability is the real constraint\n * (e.g. Paddle has no `element`).\n */\nexport function validateCheckout(provider: CheckoutProvider, surface: CheckoutSurface): ValidationResult {\n const cap = PROVIDER_PROFILES[provider]?.surfaces[surface]\n if (!cap) return { ok: false, reason: `${provider} has no '${surface}' surface` }\n return cap.purchase ? { ok: true } : { ok: false, reason: `'${surface}' can't take a purchase on ${provider}` }\n}\n\n/**\n * Validate an **off-session upsell** of `kind` after a purchase made on\n * `paywallSurface`. Combines provider support for the kind (Paddle can't stack a\n * 2nd subscription) with the paywall surface's off-session reliability (Stripe\n * managed checkout is `conditional` — returned as a `note`, not a hard block).\n */\nexport function validateUpsell(\n provider: CheckoutProvider,\n paywallSurface: CheckoutSurface,\n kind: UpsellKind = 'subscription',\n): ValidationResult {\n const profile = PROVIDER_PROFILES[provider]\n if (!profile) return { ok: false, reason: `unknown provider '${provider}'` }\n if (!profile.offSessionUpsells.includes(kind)) {\n const can = profile.offSessionUpsells.length ? ` (it supports: ${profile.offSessionUpsells.join(', ')})` : ''\n return { ok: false, reason: `${provider} can't charge a '${kind}' upsell off-session${can}` }\n }\n const cap = profile.surfaces[paywallSurface]\n if (!cap) return { ok: false, reason: `${provider} has no '${paywallSurface}' surface to upsell after` }\n if (cap.offSession === 'none') {\n return { ok: false, reason: `a purchase on '${paywallSurface}' retains no chargeable method for an upsell` }\n }\n if (cap.offSession === 'conditional') {\n return { ok: true, note: `off-session upsell after ${provider} '${paywallSurface}' (managed checkout) may decline — prefer element/sheet/express` }\n }\n return { ok: true }\n}\n\n// ── Driver seam ──────────────────────────────────────────\n\nexport type CheckoutStatus = 'idle' | 'loading' | 'requires_action' | 'success' | 'error'\n\nexport interface CheckoutRequest {\n product: string\n intent: CheckoutIntent\n surface?: CheckoutSurface\n /** For `upsell` intent — which kind of off-session charge (default `subscription`). */\n kind?: UpsellKind\n}\n\n/**\n * Normalized failure category — the driver/platform maps each provider's decline\n * codes into one of these so funnels can route/recover by reason. `authentication_\n * required` (3DS/SCA) and `requires_payment_method` are the cases an **off-session**\n * upsell can't satisfy → recover on-session (re-collect a card).\n */\nexport type CheckoutErrorCategory =\n | 'card_declined'\n | 'insufficient_funds'\n | 'expired_card'\n | 'authentication_required' // SCA/3DS needed — off-session can't challenge\n | 'requires_payment_method' // no usable saved method\n | 'processing_error'\n | 'canceled'\n | 'unknown'\n\nexport interface CheckoutError {\n category: CheckoutErrorCategory\n message: string\n /** Raw provider decline code, if any (e.g. Stripe `card_declined`/`insufficient_funds`). */\n declineCode?: string\n /** Whether re-attempting (e.g. an on-session re-collection) may succeed. */\n retryable: boolean\n}\n\n/** Build a {@link CheckoutError} (driver/test helper). */\nexport function checkoutError(\n category: CheckoutErrorCategory,\n message: string,\n extra: { declineCode?: string; retryable?: boolean } = {},\n): CheckoutError {\n const retryable = extra.retryable ?? (category === 'authentication_required' || category === 'requires_payment_method' || category === 'processing_error')\n return { category, message, declineCode: extra.declineCode, retryable }\n}\n\nexport interface CheckoutResult {\n ok: boolean\n error?: CheckoutError\n /** Charged amount in minor units (for the purchase event). */\n amountMinor?: number\n currency?: string\n /**\n * The **server-minted** dedup id for the purchase event — the platform creates it\n * when the charge settles and fires CAPI with it; the SDK emits `purchase.complete`\n * with the same id so the browser pixel dedupes against the server. (Server is the\n * source of truth for payment events; the SDK doesn't mint these.)\n */\n eventId?: string\n}\n\nexport interface CheckoutCallbacks {\n onSuccess: (result: CheckoutResult) => void\n onError: (error: CheckoutError) => void\n /**\n * The inline surface reports a valid payment method was entered (e.g. Stripe's\n * Payment Element became `complete`), before the charge. Drives the\n * `checkout.payment_added` analytics step; optional — drivers that can't observe\n * it (or off-session charges) simply never call it.\n */\n onPaymentAdded?: () => void\n}\n\n/**\n * The provider seam. The platform injects the real one (Stripe/Paddle/Whop/…);\n * tests use {@link createMockDriver}.\n *\n * Most providers ship their **own React SDK** (`@stripe/react-stripe-js`,\n * `@paddle/paddle-js`, Primer's React components, …). A driver's `renderInline`\n * returns exactly that: the provider's React element mounted in our chrome (inline,\n * or inside the `<Sheet>`). Those provider SDKs live in the **driver/platform**\n * package, not our core funnel SDK — which is why the driver is injected: the core\n * stays lean and provider-agnostic, and you only pull the SDK for the provider you use.\n */\nexport interface CheckoutDriver {\n provider: CheckoutProvider\n /** Trigger a charge (trigger surfaces + programmatic). Resolves when settled. */\n start(req: CheckoutRequest): Promise<CheckoutResult>\n /** Render an inline surface (e.g. the provider's React payment element); report via callbacks. */\n renderInline?(req: CheckoutRequest, cb: CheckoutCallbacks): ReactNode\n}\n\nexport interface MockDriverOptions {\n /** The result a successful charge resolves with. */\n result?: CheckoutResult\n /** Make **off-session** charges (no surface) fail — to exercise the upsell fallback. */\n failOffSession?: CheckoutError | boolean\n}\n\n/** A console/no-op driver — tests, preview, local dev. Succeeds unless configured to fail. */\nexport function createMockDriver(\n provider: CheckoutProvider = 'stripe',\n options: MockDriverOptions = {},\n): CheckoutDriver {\n const success: CheckoutResult = options.result ?? { ok: true, amountMinor: 0, currency: 'USD' }\n const offError: CheckoutError =\n typeof options.failOffSession === 'object'\n ? options.failOffSession\n : checkoutError('authentication_required', 'off-session charge declined (mock)')\n return {\n provider,\n start: (req) => {\n if (options.failOffSession && !req.surface) return Promise.resolve({ ok: false, error: offError })\n return Promise.resolve(success)\n },\n renderInline: (req, cb) =>\n createElement(\n 'button',\n {\n type: 'button',\n 'data-mock-surface': req.surface,\n onClick: () =>\n success.ok\n ? cb.onSuccess(success)\n : cb.onError(success.error ?? checkoutError('processing_error', 'failed (mock)')),\n },\n `Pay (mock ${req.surface})`,\n ),\n }\n}\n\nconst DriverContext = createContext<CheckoutDriver | null>(null)\n\nexport function CheckoutDriverProvider({\n driver,\n children,\n}: {\n driver: CheckoutDriver\n children: ReactNode\n}): ReactNode {\n return createElement(DriverContext.Provider, { value: driver }, children)\n}\n\nfunction useDriver(): CheckoutDriver {\n return useContext(DriverContext) ?? FALLBACK_DRIVER\n}\nconst FALLBACK_DRIVER = createMockDriver()\n\n// ── The headless hook ────────────────────────────────────\n\nexport interface UseCheckoutOptions {\n intent?: CheckoutIntent\n /** For `upsell` intent — which kind of off-session charge (default `subscription`). */\n kind?: UpsellKind\n /** Advance to the next page after a successful charge (default: true). */\n advanceOnSuccess?: boolean\n onSuccess?: (result: CheckoutResult) => void\n onError?: (error: CheckoutError) => void\n}\n\nexport interface CheckoutHandle {\n /** Start the charge for a product; resolves with the result (no surface = off-session). */\n open: (product: string, surface?: CheckoutSurface) => Promise<CheckoutResult>\n status: CheckoutStatus\n /** The last failure, structured so you can route/recover by `category`. */\n error: CheckoutError | null\n isLoading: boolean\n reset: () => void\n /** Build the callbacks an inline surface reports through (used by `<Checkout>`). */\n callbacksFor: (product: string, surface?: CheckoutSurface) => CheckoutCallbacks & { onStart: () => void }\n}\n\n/**\n * The headless checkout hook. Owns the state machine + analytics + post-charge\n * navigation; delegates the charge to the injected {@link CheckoutDriver}.\n */\nexport function useCheckout(opts: UseCheckoutOptions = {}): CheckoutHandle {\n const driver = useDriver()\n const tracker = useTrackerRef()\n const nav = useNavigation()\n const [status, setStatus] = useState<CheckoutStatus>('idle')\n const [error, setError] = useState<CheckoutError | null>(null)\n\n const intent = opts.intent ?? 'purchase'\n const kind = opts.kind\n const advance = opts.advanceOnSuccess ?? true\n\n const succeed = useCallback(\n (result: CheckoutResult) => {\n setStatus('success')\n tracker.track('purchase.complete', {\n amount: result.amountMinor != null ? result.amountMinor / 100 : undefined,\n currency: result.currency,\n eventId: result.eventId, // server-minted (browser↔CAPI dedup); undefined if none\n })\n opts.onSuccess?.(result)\n if (advance) nav.next()\n },\n [tracker, nav, advance, opts],\n )\n\n const fail = useCallback(\n (err: CheckoutError, product?: string) => {\n // 3DS/SCA that an off-session charge can't satisfy → flag for recovery.\n setStatus(err.category === 'authentication_required' ? 'requires_action' : 'error')\n setError(err)\n tracker.track('checkout.failed', {\n category: err.category,\n declineCode: err.declineCode,\n productId: product,\n intent,\n } as never)\n opts.onError?.(err)\n },\n [tracker, intent, opts],\n )\n\n const begin = useCallback(\n (product: string, surface?: CheckoutSurface) => {\n setStatus('loading')\n setError(null)\n tracker.track('checkout.start', { productId: product, surface } as never)\n },\n [tracker],\n )\n\n const paymentAdded = useCallback(() => tracker.track('checkout.payment_added', {}), [tracker])\n\n const open = useCallback(\n async (product: string, surface?: CheckoutSurface): Promise<CheckoutResult> => {\n begin(product, surface)\n try {\n const result = await driver.start({ product, intent, surface, kind })\n if (result.ok) succeed(result)\n else fail(result.error ?? checkoutError('unknown', 'Checkout failed'), product)\n return result\n } catch (e) {\n const err = checkoutError('processing_error', e instanceof Error ? e.message : 'Checkout failed')\n fail(err, product)\n return { ok: false, error: err }\n }\n },\n [driver, intent, kind, begin, succeed, fail],\n )\n\n const callbacksFor = useCallback(\n (product: string, surface?: CheckoutSurface) => ({\n onStart: () => begin(product, surface),\n onSuccess: (result: CheckoutResult) => succeed(result),\n onError: (err: CheckoutError) => fail(err, product),\n onPaymentAdded: () => paymentAdded(),\n }),\n [begin, succeed, fail, paymentAdded],\n )\n\n const reset = useCallback(() => {\n setStatus('idle')\n setError(null)\n }, [])\n\n return { open, status, error, isLoading: status === 'loading', reset, callbacksFor }\n}\n\n// ── The components ───────────────────────────────────────\n\nexport interface CheckoutProps extends UseCheckoutOptions {\n /** Logical product id (the author's bound selection). */\n product: string\n surface: CheckoutSurface\n /** Render your own trigger element instead of the default button (trigger surfaces). */\n asChild?: boolean\n /** Trigger label / your trigger element. */\n children?: ReactNode\n className?: string\n}\n\n/**\n * The `sheet` surface as a registry modal: our {@link Sheet} hosts the driver's\n * element. It resolves outcomes by invoking the callbacks passed via `showModal`\n * args — closures created in the `<Checkout>` trigger (which lives inside\n * `<FunnelView>`, so they carry navigation). Dismissing the sheet just closes it.\n */\nconst CheckoutSheet = defineModal<{\n product: string\n surface: CheckoutSurface\n intent: CheckoutIntent\n onSuccess: (result: CheckoutResult) => void\n onError: (error: CheckoutError) => void\n}>(({ product, surface, intent, onSuccess, onError }) => {\n const driver = useDriver()\n const modal = useModal()\n if (!driver.renderInline) return null\n return createElement(Sheet, {\n children: driver.renderInline(\n { product, intent, surface },\n {\n onSuccess: (r) => { modal.hide(); onSuccess(r) },\n onError: (e) => { modal.hide(); onError(e) },\n },\n ),\n })\n})\n\n/** Render the default trigger button, or clone the author's `asChild` element. */\nfunction trigger(\n onClick: () => void,\n { asChild, children, className, disabled }: { asChild?: boolean; children?: ReactNode; className?: string; disabled?: boolean },\n): ReactNode {\n if (asChild && isValidElement(children)) {\n const child = children as ReactElement<{ onClick?: () => void }>\n return cloneElement(child, { onClick })\n }\n return createElement('button', { type: 'button', className, disabled, onClick }, children ?? 'Continue')\n}\n\n/**\n * The purchase primitive. Three presentation modes by `surface`:\n * - **inline** (`express`/`element`/`embedded`) — the driver renders the\n * provider UI in place (keyed by product so a selection change remounts it);\n * - **SDK sheet** (`sheet`) — a trigger opens the AppFunnel-owned {@link Sheet}\n * and the driver renders the provider element inside it;\n * - **provider-hosted** (`popup`/`redirect`) — a trigger hands off to the\n * provider's own overlay/page.\n */\nexport function Checkout({\n product,\n surface,\n asChild,\n children,\n className,\n ...options\n}: CheckoutProps): ReactNode {\n const driver = useDriver()\n const checkout = useCheckout(options)\n const intent = options.intent ?? 'purchase'\n\n // Inline: driver renders the mounted UI; keyed by product so changing the\n // selected plan cleanly remounts the surface.\n if (isInlineSurface(surface)) {\n return driver.renderInline\n ? createElement(\n 'div',\n { key: product, className },\n driver.renderInline({ product, intent, surface }, checkout.callbacksFor(product, surface)),\n )\n : null\n }\n\n // SDK sheet: open our overlay (a registry modal) hosting the driver's element.\n if (surface === 'sheet') {\n const cb = checkout.callbacksFor(product, surface)\n const open = () => {\n cb.onStart()\n showModal(CheckoutSheet, { product, surface, intent, onSuccess: cb.onSuccess, onError: cb.onError })\n }\n return trigger(open, { asChild, children, className, disabled: checkout.isLoading })\n }\n\n // Provider-hosted (popup/redirect): trigger hands off to the provider.\n return trigger(() => checkout.open(product, surface), {\n asChild,\n children,\n className,\n disabled: checkout.isLoading,\n })\n}\n\nexport interface UpsellProps extends Omit<UseCheckoutOptions, 'intent'> {\n product: string\n /**\n * If the off-session charge fails, present this surface **on-session** to\n * re-collect a card and charge again — e.g. `fallback=\"sheet\"` opens the\n * payment sheet, `fallback=\"popup\"` the provider overlay. Omit to just report\n * the failure (via `onError` / the `checkout.failed` event).\n */\n fallback?: CheckoutSurface\n asChild?: boolean\n children?: ReactNode\n className?: string\n}\n\n/**\n * The upsell primitive — an off-session, one-tap charge to the saved method (no\n * surface, no card re-entry). On failure, optionally `fallback` to an on-session\n * surface to re-collect and retry.\n */\nexport function Upsell({ product, fallback, asChild, children, className, ...options }: UpsellProps): ReactNode {\n const checkout = useCheckout({ ...options, intent: 'upsell' })\n\n const start = async () => {\n const result = await checkout.open(product) // off-session (no surface)\n if (result.ok || !fallback) return\n // Recover on-session via the fallback surface (re-collect a card).\n const cb = checkout.callbacksFor(product, fallback)\n if (fallback === 'sheet') {\n cb.onStart()\n showModal(CheckoutSheet, { product, surface: 'sheet', intent: 'upsell', onSuccess: cb.onSuccess, onError: cb.onError })\n } else {\n await checkout.open(product, fallback) // hosted on-session re-collect\n }\n }\n\n return trigger(start, {\n asChild,\n children: children ?? 'Add to my plan',\n className,\n disabled: checkout.isLoading,\n })\n}\n","/**\n * Toast — a thin convenience re-export of {@link https://sonner.emilkowal.ski | sonner}.\n *\n * Authors call `toast.success(...)` / `toast.error(...)` anywhere in their funnel.\n * `FunnelProvider` auto-mounts {@link FunnelToaster} (opt out with `toaster={false}`),\n * so toasts work with no setup; render it yourself if you want a custom location.\n *\n * This is the *one* opinionated UI we re-export — kept deliberately thin (just the\n * imperative `toast` + a defaulted `<Toaster>`), because error/info surfacing is a\n * near-universal funnel need and sonner is tiny. Everything else stays headless.\n */\n\nimport { createElement, type ReactNode } from 'react'\nimport { Toaster, type ToasterProps } from 'sonner'\n\nexport { toast } from 'sonner'\nexport type { ToasterProps }\n\n/** Sonner's `<Toaster>` with funnel defaults (top-center); pass any `ToasterProps` to override. */\nexport function FunnelToaster(props: ToasterProps = {}): ReactNode {\n return createElement(Toaster, { position: 'top-center', ...props })\n}\n\n/** Internal: resolve the `FunnelProvider` `toaster` prop to an element (or null). */\nexport function renderToaster(toaster: boolean | ToasterProps): ReactNode {\n if (toaster === false) return null\n return createElement(Toaster, { position: 'top-center', ...(toaster === true ? {} : toaster) })\n}\n","import {\n createContext,\n createElement,\n Fragment,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport type { VariableStore } from './variableStore'\nimport { createFunnelStore, NAMESPACE_PREFIX, type WritableNamespace } from './store'\nimport { buildAcquisition, buildContext, type FunnelContext } from './context'\nimport {\n TrackerProvider,\n createConsoleTracker,\n type Tracker,\n} from '../tracking/tracking'\nimport { attachBus, createBus, withBus, type FunnelBus } from '../tracking/bus'\nimport { CatalogProvider, buildCatalog, type ResolvedProduct, type ProductInput } from '../commerce/catalog'\nimport { CheckoutDriverProvider, createMockDriver, type CheckoutDriver } from '../commerce/checkout'\nimport { ModalRuntime } from '../modals/registry'\nimport { LocaleProvider, type MessageCatalog } from '../i18n/translation'\nimport { renderToaster, type ToasterProps } from '../toast/toast'\nimport type { FunnelDefinition, FunnelSnapshot } from '../flow/spine'\nimport type { RuntimeExperiment } from '../flow/experiments'\nimport type { VariableValue } from '../types'\n\n/**\n * v2 namespace layer over the flat {@link VariableStore}.\n *\n * **The public surface is hooks, not a god object.** Reactive reads use\n * `useState`-shaped tuple hooks (`const [goal, setGoal] = useResponse('goal')`);\n * read-only computed values use `useDevice()`/`useLocale()`/`usePage()`/`useUtm()`.\n * `useFunnel()` returns an **imperative, non-subscribing** handle for use in\n * handlers/effects only — it is not the documented primary API and carries no\n * `sdk` branding.\n *\n * Three writable namespaces (`user`/`responses`/`data`) + the read-only\n * `context`. Entitlements are **not** here — they're the separate app/IdentitySDK.\n *\n * All writes route through {@link Namespace.set}, so persistence + identify fire\n * from one place (the \"magic behind set()\", doc 07 §Layer 1).\n */\n\n// ── Writable namespace view ──────────────────────────────\n\n/** A typed view over one writable namespace's slice of the store. */\nexport class Namespace<\n T extends Record<string, VariableValue> = Record<string, VariableValue>,\n> {\n private readonly dot: string\n\n constructor(\n private readonly store: VariableStore,\n readonly name: WritableNamespace,\n /** Side-effect run after every write (persistence, identify). */\n private readonly onWrite: (ns: WritableNamespace, values: Partial<T>) => void,\n ) {\n this.dot = `${NAMESPACE_PREFIX[name]}.`\n }\n\n /** Fully-qualified store key for a namespace-relative key. */\n storeKey(key: string): string {\n return this.dot + key\n }\n\n /** The store-key prefix this namespace reads/writes (e.g. `user.`). */\n get prefix(): string {\n return this.dot\n }\n\n /** Read the whole namespace as a flat object (prefix stripped). */\n getAll(): T {\n const out: Record<string, VariableValue> = {}\n const all = this.store.getState()\n for (const key in all) {\n if (key.startsWith(this.dot)) out[key.slice(this.dot.length)] = all[key]\n }\n return out as T\n }\n\n /** Read one key, or the whole namespace when called with no argument. */\n get<K extends keyof T & string>(key: K): T[K]\n get(): T\n get(key?: string): VariableValue | T {\n return key === undefined ? this.getAll() : this.store.get(this.storeKey(key))\n }\n\n /** Write one or more keys from a plain object (batched + side-effected). */\n set(values: Partial<T>): void {\n const updates: Record<string, VariableValue> = {}\n for (const key in values) {\n updates[this.storeKey(key)] = values[key] as VariableValue\n }\n this.store.setMany(updates)\n this.onWrite(this.name, values)\n }\n}\n\n// ── The imperative handle ────────────────────────────────\n\n/**\n * The imperative funnel handle (`useFunnel()`). Non-reactive — for event\n * handlers and effects. Reactive render reads go through the hooks instead.\n */\nexport interface Funnel {\n user: Namespace\n responses: Namespace\n data: Namespace\n /** Read-only computed namespace. `page` reflects the latest navigation. */\n readonly context: FunnelContext\n /** Live page-level experiment records (platform/DB-sourced); the runtime buckets visitors into them. */\n readonly experiments: RuntimeExperiment[]\n /** Emit a custom analytics event. */\n track: Tracker['track']\n /** A point-in-time snapshot for predicates (routing/conditions). */\n snapshot(): FunnelSnapshot\n}\n\n/** Build the imperative handle over a store + context + tracker. */\nexport function createFunnel(\n store: VariableStore,\n context: FunnelContext,\n tracker: Tracker,\n experiments: RuntimeExperiment[] = [],\n): Funnel {\n // One write path → one place for the \"magic behind set()\".\n const onWrite = (ns: WritableNamespace, values: Record<string, VariableValue>) => {\n // Identify the moment a non-empty email is written.\n if (ns === 'user' && typeof values.email === 'string' && values.email) {\n tracker.identify(values.email)\n }\n // Push the writable snapshot for debounced persistence.\n tracker.setVariables?.(store.getState())\n }\n\n const user = new Namespace(store, 'user', onWrite)\n const responses = new Namespace(store, 'responses', onWrite)\n const data = new Namespace(store, 'data', onWrite)\n\n return {\n user,\n responses,\n data,\n context,\n experiments,\n track: (event: string, eventData?: never, userData?: Record<string, unknown>) =>\n tracker.track(event, eventData, userData),\n snapshot: () => ({\n user: user.getAll(),\n responses: responses.getAll(),\n data: data.getAll(),\n context,\n }),\n }\n}\n\n// ── React wiring ─────────────────────────────────────────\n\ninterface FunnelContextValue {\n funnel: Funnel\n store: VariableStore\n context: FunnelContext\n catalog: Map<string, ResolvedProduct>\n driver: CheckoutDriver\n /** Tracker composed with the client bus sink (every track() also hits window.appfunnel). */\n tracker: Tracker\n /** The window.appfunnel event bus (client-side integration surface). */\n bus: FunnelBus\n}\n\nconst FunnelCtx = createContext<FunnelContextValue | null>(null)\n\nexport interface FunnelProviderProps {\n /** Mount from a funnel definition (the normal case). */\n config?: FunnelDefinition\n /** Server / session-restored values overriding declared defaults. */\n sessionValues?: Record<string, VariableValue>\n /** The platform tracker; defaults to a silent console tracker (tests/dev). */\n tracker?: Tracker\n /** Computed-context seed (funnel id, test/live mode, server-hydrated utm/session). */\n context?: Parameters<typeof buildContext>[0]\n /** Products with their provider-resolved price (`{ amount, currency }`). */\n products?: ProductInput[]\n /** Live page-level experiment records, platform/DB-sourced (not authored in funnel code). */\n experiments?: RuntimeExperiment[]\n /** The platform checkout driver; defaults to a mock that resolves successfully. */\n checkout?: CheckoutDriver\n /** Message catalogs per locale (`messages/<locale>.json`) for translation. */\n messages?: MessageCatalog\n /** Explicit locale override (URL/param/geo); wins over the detected device locale. */\n locale?: string\n /** Auto-mount the toast `<Toaster>` (default true). Pass props to customize, or `false` to opt out. */\n toaster?: boolean | ToasterProps\n /** Advanced / testing: supply a pre-built store instead of a `config`. */\n store?: VariableStore\n children: ReactNode\n}\n\n/**\n * Mounts a funnel: builds the writable {@link VariableStore} + the read-only\n * {@link FunnelContext} (once) and provides the runtime to the tree via hooks.\n */\nexport function FunnelProvider({\n config,\n sessionValues,\n tracker,\n context: contextOpts,\n products,\n experiments,\n checkout,\n messages,\n locale: localeOverride,\n toaster = true,\n store,\n children,\n}: FunnelProviderProps): ReactNode {\n const resolvedTracker = tracker ?? FALLBACK_TRACKER\n const [value] = useState<FunnelContextValue>(() => {\n const s =\n store ??\n createFunnelStore(\n { responses: config?.responses, data: config?.data },\n sessionValues,\n )\n const ctx = buildContext({\n funnelId: config?.id,\n ...contextOpts,\n })\n // The client event bus (window.appfunnel), composed into the tracker so every\n // taxonomy event mirrors to it for on-page pixels. Read getters wire to store + context.\n const bus = createBus({\n getVariable: (key) => s.get(key),\n getVariables: () => s.getState(),\n getCurrentPageId: () => ctx.page.key || null,\n getCustomerId: () => ctx.identity.customerId,\n getVisitorId: () => ctx.identity.visitorId,\n })\n const busTracker = withBus(resolvedTracker, bus)\n return {\n funnel: createFunnel(s, ctx, busTracker, experiments ?? []),\n store: s,\n context: ctx,\n catalog: buildCatalog(products ?? []),\n driver: checkout ?? createMockDriver(),\n tracker: busTracker,\n bus,\n }\n })\n // Expose the bus on window.appfunnel for the funnel's lifetime (client-side only).\n useEffect(() => attachBus(value.bus), [value.bus])\n // Forward the acquisition snapshot once on entry → the platform persists it\n // first-class (session + first-touch Customer) + feeds CAPI.\n useEffect(() => {\n value.tracker.setAcquisition?.(buildAcquisition(value.context))\n }, [value])\n const tree = createElement(TrackerProvider, {\n tracker: value.tracker,\n children: createElement(CheckoutDriverProvider, {\n driver: value.driver,\n children: createElement(CatalogProvider, {\n catalog: value.catalog,\n children: createElement(FunnelCtx.Provider, {\n value,\n children: createElement(LocaleProvider, {\n config: config?.locales,\n catalog: messages,\n detected: value.context.locale.locale,\n override: localeOverride,\n children: createElement(ModalRuntime, { children }),\n }),\n }),\n }),\n }),\n })\n return createElement(Fragment, null, tree, renderToaster(toaster))\n}\n\nconst FALLBACK_TRACKER = createConsoleTracker({ silent: true })\n\nfunction useFunnelCtx(): FunnelContextValue {\n const ctx = useContext(FunnelCtx)\n if (!ctx) {\n throw new Error('useFunnel/useResponse/… must be used inside <FunnelProvider>')\n }\n return ctx\n}\n\n/**\n * The imperative handle. Does **not** subscribe — use it in event handlers and\n * effects (`useFunnel().responses.set({...})`). For reactive reads use the hooks.\n */\nexport function useFunnel(): Funnel {\n return useFunnelCtx().funnel\n}\n\n/** Internal: the raw {@link VariableStore} (for reactive condition/field hooks). */\nexport function useFunnelStore(): VariableStore {\n return useFunnelCtx().store\n}\n\n// ── Reactive field hooks ─────────────────────────────────\n\n/** Subscribe to a single flat store key; returns its reactive value. */\nfunction useStoreKey(store: VariableStore, key: string): VariableValue {\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(cb, { keys: [key] }),\n [store, key],\n )\n const getSnapshot = useCallback(() => store.get(key), [store, key])\n // Snapshot is the primitive value → stable by value, no caching needed.\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n\n/** Build a `useState`-shaped tuple hook bound to one writable namespace. */\nfunction makeFieldHook(ns: WritableNamespace) {\n return function useNamespaceField(\n key: string,\n ): [VariableValue, (value: VariableValue) => void] {\n const { funnel, store } = useFunnelCtx()\n const value = useStoreKey(store, `${NAMESPACE_PREFIX[ns]}.${key}`)\n const set = useCallback(\n (v: VariableValue) => funnel[ns].set({ [key]: v }),\n [funnel, key],\n )\n return [value, set]\n }\n}\n\n/**\n * `const [goal, setGoal] = useResponse('goal')` — one funnel answer,\n * `useState`-shaped and per-key reactive. Writing persists + (later) feeds\n * analytics aggregation.\n */\nexport const useResponse = makeFieldHook('responses')\n\n/**\n * `const [height, setHeight] = useUserAttribute('height')` — any field on the\n * user. The platform routes known fields → typed column, custom → attribute;\n * the author doesn't specify which. Writing `email` also identifies the visitor.\n */\nexport const useUserAttribute = makeFieldHook('user')\n\n/**\n * `const [score, setScore] = useData('score')` — working/scratch state. Persisted\n * (survives reload/return) but kept out of `responses` aggregation.\n */\nexport const useData = makeFieldHook('data')\n\n/**\n * The headless field hook — `useField('responses.goal')` — the building block\n * the styleable components (`<Choice>`) wrap. Takes a namespaced path and\n * returns `{ value, set }`. Accepts only writable namespaces.\n */\nexport function useField(path: string): {\n value: VariableValue\n set: (value: VariableValue) => void\n} {\n const dot = path.indexOf('.')\n const ns = path.slice(0, dot) as WritableNamespace\n const key = path.slice(dot + 1)\n const { funnel, store } = useFunnelCtx()\n if (!(ns in NAMESPACE_PREFIX)) {\n throw new Error(`useField: \"${path}\" is not a writable namespace (user/responses/data)`)\n }\n const value = useStoreKey(store, `${NAMESPACE_PREFIX[ns]}.${key}`)\n const set = useCallback(\n (v: VariableValue) => funnel[ns].set({ [key]: v }),\n [funnel, ns, key],\n )\n return { value, set }\n}\n\n// ── Read-only context hooks ──────────────────────────────\n\n/** The whole read-only computed namespace (non-reactive except `page`). */\nfunction useContextObject(): FunnelContext {\n return useFunnelCtx().context\n}\n\n/** `useDevice()` — viewport, device type, pixel ratio (read-only). */\nexport function useDevice(): FunnelContext['device'] {\n return useContextObject().device\n}\n\n/** `useLocale()` — resolved locale/language/region/timezone (read-only). */\nexport function useLocale(): FunnelContext['locale'] {\n return useContextObject().locale\n}\n\n/** `useUtm()` — the 5 utm params captured on entry (read-only). */\nexport function useUtm(): FunnelContext['utm'] {\n return useContextObject().utm\n}\n\n/** `useClickIds()` — per-network ad click-ids captured on entry (read-only). */\nexport function useClickIds(): FunnelContext['clickIds'] {\n return useContextObject().clickIds\n}\n\n/** `useSystem()` — funnel id, test/live mode, build clock (read-only). */\nexport function useSystem(): FunnelContext['system'] {\n return useContextObject().system\n}\n\n/** Read a dotted path out of context, e.g. `useContextValue('device.isMobile')`. */\nexport function useContextValue(path: string): unknown {\n const ctx = useContextObject()\n return useMemo(\n () => path.split('.').reduce<unknown>((acc, k) => (acc as Record<string, unknown>)?.[k], ctx),\n [ctx, path],\n )\n}\n","import {\n createElement,\n type ButtonHTMLAttributes,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react'\nimport { useField } from '../state/namespaces'\nimport { useNavigation } from './flow'\n\n/**\n * The two-tier component model (doc 07 §\"magic ≠ black box\"): the magic lives in\n * headless hooks (`useField`, `useNavigation`); these styleable components are\n * thin, restyle-able wrappers over them. Every `<Choice>` reduces to `useField`\n * + your own JSX — eject any time. They pass `className`/DOM props straight\n * through and never dictate a pixel beyond the minimum.\n */\n\nexport interface ChoiceOption {\n value: string\n label?: ReactNode\n}\n\nexport interface ChoiceProps {\n /** Writable namespaced path to bind, e.g. `responses.goal`. */\n bind: string\n /** The selectable options (a bare string is shorthand for `{value, label}`). */\n options: (string | ChoiceOption)[]\n /** Class applied to each option button. */\n className?: string\n /** Class applied to the selected option button (in addition to `className`). */\n selectedClassName?: string\n /** Advance navigation after a choice (handy for single-tap question pages). */\n advanceOnSelect?: boolean\n}\n\n/**\n * Single-select bound to a writable field. `<Choice bind=\"responses.goal\"\n * options={[\"lose\", \"gain\"]} />` — selecting persists + (later) tracks; pass\n * `advanceOnSelect` to move to the next page on tap.\n */\nexport function Choice({\n bind,\n options,\n className,\n selectedClassName,\n advanceOnSelect,\n}: ChoiceProps): ReactNode {\n const { value, set } = useField(bind)\n const nav = useNavigation()\n\n return options.map((opt) => {\n const o: ChoiceOption = typeof opt === 'string' ? { value: opt } : opt\n const selected = value === o.value\n return createElement(\n 'button',\n {\n key: o.value,\n type: 'button',\n 'aria-pressed': selected,\n 'data-selected': selected || undefined,\n className: selected && selectedClassName ? `${className ?? ''} ${selectedClassName}`.trim() : className,\n onClick: () => {\n set(o.value)\n if (advanceOnSelect) nav.next()\n },\n },\n o.label ?? o.value,\n )\n })\n}\n\nexport interface NextProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n children?: ReactNode\n}\n\n/** A button that advances the funnel (the current page's `next`, else linear). */\nexport function Next({ children, onClick, ...rest }: NextProps): ReactNode {\n const { next } = useNavigation()\n return createElement(\n 'button',\n {\n type: 'button',\n ...rest,\n onClick: (e: ReactMouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (!e.defaultPrevented) next()\n },\n },\n children ?? 'Continue',\n )\n}\n\nexport interface BackProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n children?: ReactNode\n}\n\n/** A button that returns to the previous page; hidden when there's no history. */\nexport function Back({ children, onClick, ...rest }: BackProps): ReactNode {\n const { back, canGoBack } = useNavigation()\n if (!canGoBack) return null\n return createElement(\n 'button',\n {\n type: 'button',\n ...rest,\n onClick: (e: ReactMouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (!e.defaultPrevented) back()\n },\n },\n children ?? 'Back',\n )\n}\n","/**\n * The **event catalog** — the single source of truth for *which* events exist and\n * how each is routed (analytics vs. integrations vs. runtime-only). Pairs with the\n * typed payloads in {@link ./tracking}.`FunnelEventDataMap`.\n *\n * This replaces the duplication the monorepo flags (`shared/events/catalog.ts` is\n * \"documentation, not imported\" — the taxonomy is re-declared in\n * `admin/lib/funnel/tracking.ts`, each `admin/lib/integrations/*` EVENT_MAP, and\n * `api/src/integrations/constants`). In v2 the **SDK owns the taxonomy** (it emits\n * it), so the bus, the pixel loaders, and the platform all import *this*.\n */\n\nexport type EventSource = 'frontend' | 'backend'\n\nexport interface EventMeta {\n /** Where the event originates. `backend` = the server emits it (e.g. a settled charge). */\n sources: EventSource[]\n /** Persisted to analytics. */\n tracking: boolean\n /** Forwarded to ad/integration pixels (Meta/GTM/TikTok/…). */\n integrations: boolean\n /** Runtime-only JS subscription — not persisted, not sent to integrations. */\n runtime?: boolean\n}\n\n/**\n * Every event the system knows, with its routing metadata. Keys are the taxonomy\n * names (a superset of `FunnelEventDataMap`: it also lists the **backend-originated**\n * monetary events the platform pushes to the client bus for pixel firing).\n */\nexport const EVENT_CATALOG = {\n // ── Runtime / navigation (JS subscriptions; not persisted) ──\n 'funnel.start': { sources: ['frontend'], tracking: false, integrations: false, runtime: true },\n 'experiment.exposure': { sources: ['frontend'], tracking: true, integrations: false },\n\n // ── Frontend, tracked; some also go to pixels ──\n 'page.view': { sources: ['frontend'], tracking: true, integrations: true },\n 'page.exit': { sources: ['frontend'], tracking: true, integrations: false },\n 'user.registered': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.start': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.payment_added': { sources: ['frontend'], tracking: true, integrations: true },\n 'checkout.failed': { sources: ['frontend'], tracking: true, integrations: false },\n\n // ── Backend-originated money events (server mints the eventId; client fires the pixel) ──\n 'purchase.complete': { sources: ['backend'], tracking: true, integrations: true },\n 'customer.first_purchase': { sources: ['backend'], tracking: true, integrations: true },\n 'subscription.created': { sources: ['backend'], tracking: true, integrations: true },\n 'subscription.renewal': { sources: ['backend'], tracking: true, integrations: true },\n} as const satisfies Record<string, EventMeta>\n\n/** A catalog event name. */\nexport type CatalogEvent = keyof typeof EVENT_CATALOG\n\n/** True if the event is persisted to analytics. */\nexport function isTrackableEvent(name: string): boolean {\n return EVENT_CATALOG[name as CatalogEvent]?.tracking ?? false\n}\n\n/** True if the event is forwarded to ad/integration pixels. */\nexport function isIntegrationEvent(name: string): boolean {\n return EVENT_CATALOG[name as CatalogEvent]?.integrations ?? false\n}\n\n/** The events that feed integrations — the set a pixel loader subscribes to. */\nexport function integrationEvents(): CatalogEvent[] {\n return (Object.keys(EVENT_CATALOG) as CatalogEvent[]).filter((e) => EVENT_CATALOG[e].integrations)\n}\n","/**\n * `<Script>` — the **declared third-party embed** primitive (phase-2 §2.3d).\n *\n * The controlled escape hatch for runtime widgets/embeds that genuinely need\n * client code — Intercom, Trustpilot, a calendar embed, an operator pixel. Unlike\n * arbitrary `<script>` injection, it's **declared** (the funnel author writes\n * `<Script src=…/>`), **deduped** (injected at most once per id/src, even across\n * page navigation in the SPA — a chat widget must not reload on every page), and\n * **CSP-friendly** (accepts a `nonce`).\n *\n * CSP enforcement itself is the **renderer's** job: it scans the funnel's declared\n * `<Script src>`s (build-time) into the `script-src` allowlist and supplies the\n * `nonce`. This component just injects the tag at the right time.\n *\n * For *analytics* pixels, prefer subscribing to the `window.appfunnel` bus\n * ({@link ../tracking/bus}) — `<Script>` is for non-analytics third-party widgets\n * (and the pixel loader snippets, which then subscribe to the bus).\n */\n\nimport { useEffect } from 'react'\n\n/** Module-level registry so a given script injects once for the app's lifetime. */\nconst injected = new Set<string>()\n\nexport interface ScriptProps {\n /** The third-party script URL. */\n src: string\n /**\n * When to inject. `afterInteractive` (default) injects on mount (after hydration);\n * `lazyOnload` waits for idle/`load` so it never competes with the funnel's own JS.\n */\n strategy?: 'afterInteractive' | 'lazyOnload'\n /** Dedup key (defaults to `src`) — the script injects at most once per id. */\n id?: string\n /** Defaults to `true`. */\n async?: boolean\n defer?: boolean\n /** CSP nonce — supplied by the renderer. */\n nonce?: string\n /** Extra attributes (e.g. `data-*`). */\n attributes?: Record<string, string>\n onLoad?: () => void\n onError?: () => void\n}\n\n/**\n * Injects a third-party script once. Renders nothing. Persists across navigation\n * (the tag is never removed on unmount — third-party widgets should stay loaded).\n */\nexport function Script({\n src,\n strategy = 'afterInteractive',\n id,\n async = true,\n defer,\n nonce,\n attributes,\n onLoad,\n onError,\n}: ScriptProps): null {\n useEffect(() => {\n if (typeof document === 'undefined') return\n const key = id ?? src\n if (injected.has(key)) {\n onLoad?.() // already present from an earlier mount\n return\n }\n\n const inject = () => {\n if (injected.has(key)) return\n injected.add(key)\n const el = document.createElement('script')\n el.src = src\n if (id) el.id = id\n if (async) el.async = true\n if (defer) el.defer = true\n if (nonce) el.nonce = nonce\n if (attributes) for (const [k, v] of Object.entries(attributes)) el.setAttribute(k, v)\n el.addEventListener('load', () => onLoad?.())\n el.addEventListener('error', () => {\n injected.delete(key) // allow a later retry\n onError?.()\n })\n document.head.appendChild(el)\n }\n\n if (strategy === 'lazyOnload') {\n const ric = (window as unknown as { requestIdleCallback?: (cb: () => void) => number })\n .requestIdleCallback\n if (ric) {\n ric(inject)\n } else {\n const t = setTimeout(inject, 0)\n return () => clearTimeout(t)\n }\n return\n }\n inject()\n // src/id identify the script; injection is idempotent via the registry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [src, id])\n\n return null\n}\n\n/** Internal: clear the injected-script registry (tests only). */\nexport function __resetScriptRegistry(): void {\n injected.clear()\n}\n","/**\n * The **manifest** — the declarative IR a funnel project compiles to (doc 06).\n * It's the machine-readable artifact the platform operates on without executing\n * the funnel: the dashboard draws the flow graph from it, analytics binds to its\n * **stable ids**, validation runs against it, and the renderer reads it to resolve\n * routing.\n *\n * `compileManifest` evaluates the spine (the funnel config + each page's co-located\n * `meta`) into that IR. It's pure — no I/O — so it unit-tests trivially. **It runs\n * server-side**, as the IR step of the publish build over the canonical files in our\n * storage (R2). The client/CLI never produces the authoritative manifest — R2 is the\n * source of truth, the server compiles. (A local dev preview may run it for itself,\n * but that output is never published.)\n *\n * Edge model mirrors the runtime ({@link ../flow/spine}.`nextPage`): a page's\n * `meta.next` routes become **branch** edges (with a serialized condition — a\n * declarative {@link Condition}, or an opaque marker for a code predicate), and the\n * implicit file-order fall-through becomes a **linear** edge (unless an\n * unconditional route already covers it, or the page is a `finish`).\n *\n * Experiments are **not** compiled here. A variant page is recognised structurally\n * by the `@` in its key (`welcome@b`) and tagged `variantOf` + collapsed out of the\n * linear flow; the experiment *wiring* (labels/weights/status) is operational data\n * the platform owns and overlays at render time, not part of the funnel build.\n *\n * Stable ids: the page **key** is the source anchor, so `id === key` here. The\n * durable analytics id is the semantic page name (a slot survives a winner being\n * promoted into it); transient `@variant` pages only ever key analytics by\n * `(experimentId, variant)` in immutable results — a platform concern.\n */\n\nimport type {\n Condition,\n FunnelDefinition,\n FunnelLocales,\n Gate,\n PageMeta,\n PageType,\n} from '../flow/spine'\nimport { isVariantKey, parseSlotKey } from '../flow/experiments'\n\nexport interface ManifestPage {\n id: string\n key: string\n type: PageType\n slug: string\n index: number\n /**\n * Set on a variant page (`welcome@b`) to its **slot** (`welcome`) — a structural\n * marker that this node is an off-flow alternate, not a linear step. The\n * experiment *wiring* (label/weight/id) is operational data the platform owns,\n * not the manifest.\n */\n variantOf?: string\n}\n\nexport type EdgeCondition =\n | { kind: 'declarative'; condition: Condition }\n /** A code predicate — opaque body; `label` may be supplied later by AST parsing. */\n | { kind: 'predicate'; label?: string }\n\nexport interface ManifestEdge {\n from: string\n to: string\n kind: 'branch' | 'linear'\n /** Absent = unconditional (a fallback route, or the linear fall-through). */\n condition?: EdgeCondition\n}\n\nexport interface ManifestValidation {\n ok: boolean\n /** Page ids you can't proceed from (and that aren't a `finish`). */\n deadEnds: string[]\n /** Page ids not reachable from the start. */\n unreachable: string[]\n /** Routes whose target page key doesn't exist. */\n badTargets: { from: string; to: string }[]\n /** True if the funnel never writes `user.email` (the mandatory identity step). */\n missingEmailCapture: boolean\n}\n\nexport interface FunnelManifest {\n id: string\n pages: ManifestPage[]\n flow: { start: string | null; nodes: string[]; edges: ManifestEdge[] }\n products: string[]\n locales?: FunnelLocales\n validation: ManifestValidation\n}\n\nexport interface CompileInput {\n funnel: FunnelDefinition\n /** Pages in file order (the default flow); `meta` holds type/slug/next. */\n pages: { key: string; meta?: PageMeta }[]\n}\n\n/**\n * A **variant** node — a page filed with an `@variant` key (e.g. `welcome@b`).\n * It's an alternate of its slot, not a step in the linear spine, so it gets no\n * linear edge and is excluded from dead-end/reachability checks (the runtime\n * resolves it by bucketing, not by an edge). The `@` is the only source-side\n * signal; the experiment wiring is the platform's operational data. The slot's\n * control (no `@`) stays the flow node. Mirrors {@link resolveExperiments}.\n */\nfunction isVariantNode(page: { key: string }): boolean {\n return isVariantKey(page.key)\n}\n\n/** Serialize a route gate for the manifest (declarative → data; predicate → opaque). */\nfunction serializeGate(when: Gate | undefined): EdgeCondition | undefined {\n if (!when) return undefined\n if (typeof when === 'function') return { kind: 'predicate' }\n return { kind: 'declarative', condition: when }\n}\n\n/** Compile a funnel's spine into its declarative {@link FunnelManifest} IR. */\nexport function compileManifest(input: CompileInput): FunnelManifest {\n const { funnel, pages } = input\n const keys = new Set(pages.map((p) => p.key))\n\n const manifestPages: ManifestPage[] = pages.map((p, index) => ({\n id: p.key,\n key: p.key,\n type: p.meta?.type ?? 'default',\n slug: p.meta?.slug ?? p.key,\n index,\n variantOf: isVariantKey(p.key) ? parseSlotKey(p.key).slot : undefined,\n }))\n\n const edges: ManifestEdge[] = []\n const badTargets: { from: string; to: string }[] = []\n\n // The next page in file order that is a real flow node (skip `@variant` siblings).\n const nextAnchor = (from: number) => {\n for (let j = from + 1; j < pages.length; j++) {\n if (!isVariantNode(pages[j])) return pages[j]\n }\n return undefined\n }\n\n pages.forEach((p, i) => {\n // Variant nodes are alternates of their slot, resolved at runtime by bucketing\n // — they carry no flow edges (routing lives on the slot's control/anchor).\n if (isVariantNode(p)) return\n\n const routes = p.meta?.next ?? []\n let hasUnconditional = false\n for (const route of routes) {\n if (!keys.has(route.to)) {\n badTargets.push({ from: p.key, to: route.to })\n continue\n }\n edges.push({ from: p.key, to: route.to, kind: 'branch', condition: serializeGate(route.when) })\n if (!route.when) hasUnconditional = true\n }\n // Linear fall-through, unless an unconditional route already covers it,\n // this is a `finish` page, or there is no next page.\n const next = nextAnchor(i)\n if (!hasUnconditional && next && p.meta?.type !== 'finish') {\n edges.push({ from: p.key, to: next.key, kind: 'linear' })\n }\n })\n\n // The start is the first real flow node (a leading variant can't be the entry).\n const startPage = pages.find((p) => !isVariantNode(p))\n const start = startPage?.key ?? null\n const variantKeys = new Set(pages.filter(isVariantNode).map((p) => p.key))\n const validation = validate(manifestPages, edges, badTargets, start, variantKeys)\n\n return {\n id: funnel.id,\n pages: manifestPages,\n flow: { start, nodes: manifestPages.map((p) => p.id), edges },\n products: funnel.products ?? [],\n locales: funnel.locales,\n validation,\n }\n}\n\nfunction validate(\n pages: ManifestPage[],\n edges: ManifestEdge[],\n badTargets: { from: string; to: string }[],\n start: string | null,\n variantKeys: Set<string>,\n): ManifestValidation {\n const outgoing = new Map<string, number>()\n for (const e of edges) outgoing.set(e.from, (outgoing.get(e.from) ?? 0) + 1)\n\n // Variant nodes are resolved by bucketing, not edges — they're neither dead\n // ends nor unreachable in the flow-graph sense, so exclude them from both.\n const deadEnds = pages\n .filter((p) => p.type !== 'finish' && !variantKeys.has(p.id) && !(outgoing.get(p.id)! > 0))\n .map((p) => p.id)\n\n // Reachability from the start over the edge set.\n const reachable = new Set<string>()\n if (start) {\n const adj = new Map<string, string[]>()\n for (const e of edges) {\n const list = adj.get(e.from)\n if (list) list.push(e.to)\n else adj.set(e.from, [e.to])\n }\n const stack = [start]\n while (stack.length) {\n const id = stack.pop()!\n if (reachable.has(id)) continue\n reachable.add(id)\n for (const to of adj.get(id) ?? []) stack.push(to)\n }\n }\n const unreachable = pages\n .filter((p) => !variantKeys.has(p.id) && !reachable.has(p.id))\n .map((p) => p.id)\n\n // The funnel must capture user.email somewhere (doc 06). We can see the typed\n // `email-capture` page; deeper detection (any user.email write) is a build-time\n // AST concern. Treat presence of an `email-capture` page as satisfying it.\n const missingEmailCapture = !pages.some((p) => p.type === 'email-capture')\n\n return {\n ok: deadEnds.length === 0 && unreachable.length === 0 && badTargets.length === 0 && !missingEmailCapture,\n deadEnds,\n unreachable,\n badTargets,\n missingEmailCapture,\n }\n}\n"]}