@mrrocket/sdk 0.10.0 → 0.12.0

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/native/index.tsx","../../src/core.ts","../../src/api-client.ts","../../src/batch.ts","../../src/errors.ts","../../src/flows.ts","../../src/rage.ts","../../src/native/recorder.ts","../../src/referral.ts","../../src/native/client.ts","../../src/native/flows-view.ts","../../src/native/platform.ts","../../src/native/widgets-view.ts"],"sourcesContent":["/**\n * `@mrrocket/sdk/react-native`: the MRRocket SDK for React Native and Expo apps.\n *\n * // app/_layout.tsx (Expo Router)\n * import { MRRocketProvider, useExpoRouterTracking } from \"@mrrocket/sdk/react-native\";\n *\n * function Screens() {\n * useExpoRouterTracking();\n * return <Stack />;\n * }\n *\n * export default function RootLayout() {\n * return (\n * <MRRocketProvider apiKey=\"mrr_pub_…\">\n * <Screens />\n * </MRRocketProvider>\n * );\n * }\n *\n * No DOM, no \"use client\", no session recorder: Metro bundles it as is. See the README for what it sends.\n */\nimport { type ReactNode, createContext, createElement, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { type CockpitConfig, SDK_VERSION, type VariantId } from \"../core\";\nimport type { CancelFlowOptions, CancelFlowResult } from \"../flows\";\nimport { type KeyValueStorage, type MRRocketClient, type MRRocketOptions, activeRouteName, createClient } from \"./client\";\nimport { MRRocketFlows, type NativeAppearance } from \"./flows-view\";\nimport { nativeDeps, optionalModules } from \"./platform\";\nimport { type Measurable, maskedViews } from \"./recorder\";\nimport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, type NativeFeedbackOptions, type NativeMessengerOptions, useFeedback, useMessenger } from \"./widgets-view\";\n\nexport type { AppContext, CockpitConfig, FlagConfig, VariantId } from \"../core\";\nexport type { CancelFlowConfig, CancelFlowOptions, CancelFlowResult, CancelOffer, FlowView, InAppMessage, OnboardingFlow, OnboardingStep } from \"../flows\";\nexport { MRRocketFlows, type NativeAppearance };\nexport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, useFeedback, useMessenger, type NativeFeedbackOptions, type NativeMessengerOptions };\nexport type { ChatMessage, ChatThread, FeedbackPost, SurveyDefinition } from \"../api-client\";\nexport type { KeyValueStorage, MRRocketClient, MRRocketOptions, NativeConsent, NativePushResult, NativePushStatus, RegisterForPushOptions } from \"./client\";\nexport { SDK_VERSION, activeRouteName };\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\nconst RN = require(\"react-native\") as { View: (props: Record<string, unknown>) => ReactNode };\n\n/**\n * Hides what it wraps in session recordings: its area is painted black on every frame before the frame is stored. Use\n * it for anything private on screen (balances, addresses, messages). Text fields need no wrapper: nothing is recorded\n * while the keyboard is open.\n *\n * <MRRocketMask><Text>{iban}</Text></MRRocketMask>\n */\nexport const MRRocketMask = ({ children, style }: { children?: ReactNode; style?: unknown }) => {\n const ref = useRef<Measurable | null>(null);\n useEffect(() => {\n maskedViews.add(ref);\n return () => {\n maskedViews.delete(ref);\n };\n }, []);\n // collapsable: false keeps the view on Android, so it can be measured.\n return createElement(RN.View, { ref, collapsable: false, style }, children);\n};\n\nlet shared: MRRocketClient | null = null;\nlet sharedKey = \"\";\n\n/**\n * The SDK's client outside React (a background task, a store, an API layer): the one the provider made, or a new one.\n * One client per app; a second call returns the first.\n */\nexport const createMRRocket = (options: MRRocketOptions & { storage?: KeyValueStorage | null }): MRRocketClient => {\n if (shared) {\n if (sharedKey !== options.apiKey) console.warn(\"[MRRocket] The SDK is already running with another key; keeping the first one.\");\n return shared;\n }\n const { storage, ...rest } = options;\n const deps = nativeDeps({ storage });\n shared = createClient(rest, deps);\n sharedKey = options.apiKey;\n if (options.debug) console.log(\"[MRRocket] optional modules\", JSON.stringify(optionalModules()));\n return shared;\n};\n\n/** The running client, or null before the provider (or createMRRocket) started it. */\nexport const getMRRocket = () => shared;\n\nconst Ctx = createContext<MRRocketClient | null>(null);\n\nexport interface MRRocketProviderProps extends Partial<MRRocketOptions> {\n /** The product's public key (MRRocket › Settings › Products), the same as on the website. */\n apiKey: string;\n /** A storage with AsyncStorage's shape instead of AsyncStorage (MMKV, SecureStore); null keeps everything in memory. */\n storage?: KeyValueStorage | null;\n /** A client you made with createMRRocket; the other props are then ignored. */\n client?: MRRocketClient;\n /**\n * Draw the cancel flow, onboarding and in-app messages (default true). False: draw `client.flows` yourself, or\n * place `<MRRocketFlows flows={client.flows} />` where you want it.\n */\n flows?: boolean;\n /** The look of those dialogs and the widgets: `{ theme: \"light\" | \"dark\" | \"auto\", accent: \"#0f766e\" }`. */\n appearance?: NativeAppearance;\n /** Show the live in-app survey MRRocket picks for the person, a few seconds after start (default true). */\n surveys?: boolean;\n /** The chat with your team, opened with `useMessenger().open()`; `{ launcher: true }` adds a round button. False: none. */\n messenger?: NativeMessengerOptions | false;\n /** The feedback sheet opened with `useFeedback().open()` (`{ title }`). False: none. */\n feedback?: NativeFeedbackOptions | false;\n /**\n * Taps for Heatmaps (default true). The provider then wraps the app in one `View` with `flex: 1` to see them; false\n * leaves the app as it is.\n */\n heatmaps?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Put it once around your app (Expo Router: app/_layout.tsx; React Navigation: around the NavigationContainer). It\n * starts the SDK: lifecycle events, the event queue, flags and experiments, error capture. Changing `consent` later\n * calls setConsent.\n */\nexport const MRRocketProvider = ({ client: given, children, consent, flows = true, appearance, surveys = true, messenger = {}, feedback = {}, heatmaps = true, ...options }: MRRocketProviderProps) => {\n const [client] = useState(() => given ?? createMRRocket({ ...options, consent }));\n useEffect(() => {\n if (consent) client.setConsent(consent);\n }, [client, consent]);\n // The person's answer to recordings can change later (a settings switch): the prop follows it.\n useEffect(() => {\n if (options.replay !== undefined) client.setReplay(options.replay);\n }, [client, options.replay]);\n // Taps for Heatmaps: a touch that ends near where it started within half a second, never a scroll or a drag.\n const start = useRef<{ x: number; y: number; t: number } | null>(null);\n const touch = (e: { nativeEvent: { pageX?: number; pageY?: number; changedTouches?: ArrayLike<{ pageX: number; pageY: number }> } }, end: boolean) => {\n // Phones give pageX on the event; React Native Web passes the browser's TouchEvent, with the point in changedTouches.\n const n = e.nativeEvent;\n const x = n.pageX ?? n.changedTouches?.[0]?.pageX;\n const y = n.pageY ?? n.changedTouches?.[0]?.pageY;\n if (x === undefined || y === undefined) return;\n if (!end) start.current = { x, y, t: Date.now() };\n else if (start.current && Math.hypot(x - start.current.x, y - start.current.y) < 10 && Date.now() - start.current.t < 500) client.tap(x, y);\n };\n return createElement(\n Ctx.Provider,\n { value: client },\n heatmaps\n ? createElement(RN.View, { style: { flex: 1 }, onTouchStartCapture: (e: never) => touch(e, false), onTouchEndCapture: (e: never) => touch(e, true) }, children)\n : children,\n flows ? createElement(MRRocketFlows, { flows: client.flows, appearance }) : null,\n surveys ? createElement(MRRocketSurveys, { client, appearance }) : null,\n feedback ? createElement(MRRocketFeedback, { client, appearance, options: feedback }) : null,\n messenger ? createElement(MRRocketMessenger, { client, appearance, options: messenger }) : null,\n );\n};\n\nconst useClient = () => {\n const c = useContext(Ctx);\n if (!c) throw new Error(\"MRRocket: wrap your app in <MRRocketProvider apiKey=…>.\");\n return c;\n};\n\n/** Re-renders when flags, the person or the consent change. */\nconst useVersion = (client: MRRocketClient) => useSyncExternalStore(client.subscribe, client.getVersion, client.getVersion);\n\n/**\n * `track`, `screen`, `identify`, `reset`, `setConsent`, `captureError`, `flush`, the visitor id, the consent and whether\n * flags and experiments have loaded.\n */\nexport const useMRRocket = () => {\n const client = useClient();\n useVersion(client);\n return {\n track: client.track,\n screen: client.screen,\n identify: client.identify,\n reset: client.reset,\n setConsent: client.setConsent,\n setReplay: client.setReplay,\n captureError: client.captureError,\n flush: client.flush,\n distinctId: client.getDistinctId(),\n consent: client.getConsent(),\n ready: client.isReady(),\n };\n};\n\n/**\n * The cancel flow built in MRRocket › Churn › Cancel flow. Call `open` from your Cancel button; the provider draws it.\n * MRRocket never changes the subscription: your `onCancel` and `onSave` do (RevenueCat, your server, the store's\n * subscription page).\n *\n * const cancelFlow = useCancelFlow();\n * <Button title=\"Cancel subscription\" onPress={() => cancelFlow.open({ customer: \"consumer\", onCancel: openStoreSubscriptions })} />\n */\nexport const useCancelFlow = (): { open: (options?: CancelFlowOptions) => Promise<CancelFlowResult> } => {\n const client = useClient();\n return { open: client.openCancelFlow };\n};\n\n/**\n * Push notifications from your Lifecycle journeys (needs `expo-notifications`). After sign-in (`identify`), call\n * `register()`: it asks the permission, gets the Expo push token and sends it to MRRocket. Sign-out (`reset`) takes the\n * token back on its own.\n *\n * const push = usePush();\n * useEffect(() => { if (user) void push.register(); }, [user]);\n */\nexport const usePush = (): { register: MRRocketClient[\"registerForPush\"]; unregister: MRRocketClient[\"unregisterForPush\"] } => {\n const client = useClient();\n return { register: client.registerForPush, unregister: client.unregisterForPush };\n};\n\n/** Starts an onboarding flow now (the first live one without an id), whatever its trigger. */\nexport const useOnboarding = (): { start: (id?: string) => boolean } => {\n const client = useClient();\n return { start: client.startOnboarding };\n};\n\n/** A feature flag from MRRocket › Build › Feature flags: true while it is on for this person; false while off, unknown or loading. */\nexport const useFlag = (key: string): boolean => {\n const client = useClient();\n useVersion(client);\n return client.getFlag(key);\n};\n\n/** The variant of a multivariate flag (\"control\", \"test\" …), or null while it is off. */\nexport const useFlagVariant = (key: string): string | null => {\n const client = useClient();\n useVersion(client);\n return client.getFlagVariant(key);\n};\n\n/**\n * The variant of an experiment this person sees (\"control\" until the config is known; the cached config is used on a\n * cold start, so the first screen is already stable). Records the exposure once per screen.\n */\nexport const useVariant = (key: string): VariantId => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const variant = client.peekVariant(key);\n useEffect(() => {\n if (config) client.expose(key, variant);\n }, [client, config, key, variant]);\n return variant;\n};\n\n/**\n * Copy MRRocket can change without an app update: the text published for `id` (a paywall's\n * `paywall.<placement>.headline`, `.body`, `.cta`), with this person's variant of a running text test on top,\n * the same rules as `<Text id>` on the web. Write your own words as `fallback`: they show while nothing is published\n * and on a first start before the config arrives. Records the exposure to every test that changes `id`, once per screen.\n *\n * const headline = useText(\"paywall.onboarding.headline\", \"Unlock everything\");\n * <Text style={styles.title}>{headline}</Text>\n */\nexport const useText = (id: string, fallback: string): string => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const text = client.peekText(id);\n const person = client.getDistinctId();\n useEffect(() => {\n if (config) client.exposeText(id);\n }, [client, config, id, person]);\n return text ?? fallback;\n};\n\ntype ExpoRouterModule = { usePathname: () => string };\nlet expoRouter: ExpoRouterModule | null | undefined;\nconst loadExpoRouter = (): ExpoRouterModule | null => {\n if (expoRouter !== undefined) return expoRouter;\n try {\n expoRouter = require(\"expo-router\") as ExpoRouterModule;\n } catch {\n expoRouter = null;\n }\n return expoRouter;\n};\nconst noPathname = () => undefined;\nlet routerWarned = false;\n\n/**\n * Screen views for Expo Router: one `$screen` per path (\"/settings\", \"/product/[id]\" as its real path). Call it in a\n * component inside both the router and MRRocketProvider, for example the root layout's child.\n */\nexport const useExpoRouterTracking = () => {\n const client = useClient();\n const router = loadExpoRouter();\n if (router === null && !routerWarned) {\n routerWarned = true;\n console.warn(\"[MRRocket] useExpoRouterTracking needs expo-router. With React Navigation use useNavigationTracking.\");\n }\n const pathname = (router?.usePathname ?? noPathname)();\n useEffect(() => {\n if (pathname) client.screen(pathname);\n }, [client, pathname]);\n};\n\n/**\n * Screen views for React Navigation: pass the result to the container's `onStateChange`, and call it once in `onReady`\n * with the root state, so the first screen counts too.\n *\n * const ref = useNavigationContainerRef();\n * const onStateChange = useNavigationTracking();\n * <NavigationContainer ref={ref} onReady={() => onStateChange(ref.getRootState())} onStateChange={onStateChange}>\n */\nexport const useNavigationTracking = () => {\n const client = useClient();\n return useCallback(\n (state: unknown) => {\n const name = activeRouteName(state);\n if (name) client.screen(name);\n },\n [client],\n );\n};\n","/**\n * The part of the SDK that runs anywhere: experiment config, variant assignment, preview links and event shapes.\n * No React, no browser APIs, so the server helper, the proxy helper and the client share it.\n */\nimport type { CancelFlowConfig, OnboardingFlow } from \"./flows\";\n\nexport type VariantId = string;\n\n/** This build of the SDK. Sent with the config request so MRRocket knows what the site runs (error tracking, flags). */\nexport const SDK_VERSION = \"0.10.0\";\n\n/** One variant of an experiment. `changes` replaces texts that the page marks with `<Text id>`. */\nexport interface VariantConfig {\n id: VariantId;\n /** Share of traffic, 0 to 1. The weights of an experiment add up to 1. */\n weight: number;\n changes?: Record<string, string>;\n /**\n * A redirect test: where this variant sends the visitor instead of the test's page (a path like \"/pricing-b\" or a\n * full address). Control has none and stays. SDK 0.7.0+.\n */\n url?: string;\n}\n\nexport interface ExperimentConfig {\n /** The experiment's key, the same as in Cockpit. */\n key: string;\n status: \"running\" | \"draft\" | \"stopped\";\n /** Control first. */\n variants: VariantConfig[];\n /** A winner that shipped: everyone gets it, and nobody is assigned anymore. */\n winner?: VariantId;\n /** A redirect test: the path of the page it runs on (\"/pricing\"). Visitors there are sent to their variant's `url`. */\n path?: string;\n}\n\n/** A page redirect set in MRRocket (Conversion › Landing pages › Redirect): everyone on `from` goes to `to`. SDK 0.7.0+. */\nexport interface RedirectConfig {\n /** A path of the site, like \"/old-pricing\". */\n from: string;\n /** A path or a full address. */\n to: string;\n}\n\nexport interface CockpitConfig {\n /** The product the public key belongs to. */\n project: string;\n experiments: ExperimentConfig[];\n /** The product's affiliate program: how many days a partner's referral is kept. Missing without a program. */\n referral?: { cookieDays: number };\n /** Session recordings: present only while the product records (Cockpit › Sessions). See `ReplayConfig`. */\n replay?: ReplayConfig;\n /** Feature flags of the product in Production (MRRocket › Build › Feature flags), evaluated by `useFlag` and `getFlag`. */\n flags?: FlagConfig[];\n /**\n * Published copy for texts the site marks (`<Text id>`, `data-ck-text`): a landing page's headline, subheadline and\n * button (`pricing.headline` …) and a paywall's (`paywall.<placement>.headline` …) as published in MRRocket. A\n * running test's variant changes them on top. Missing when nothing is published. SDK 0.5.0+.\n */\n texts?: Record<string, string>;\n /** The product's live cancel flow (MRRocket › Churn › Cancel flow), for `cancelFlow.open()`. SDK 0.7.0+. */\n cancelFlow?: CancelFlowConfig;\n /** The in-app steps of live onboarding flows (tours, checklists, modals). SDK 0.7.0+. */\n onboarding?: OnboardingFlow[];\n /** A live Lifecycle journey has in-app messages: signed-in people ask `/api/sdk/inapp` for theirs. SDK 0.7.0+. */\n messages?: boolean;\n /** Page redirects set in MRRocket; the SDK sends visitors on before the page shows (`redirectFor`). SDK 0.7.0+. */\n redirects?: RedirectConfig[];\n}\n\n/** One condition of a flag's audience, on a property of the person (`identify(id, props)`), the id or the page. */\nexport interface FlagCondition {\n /** \"Email\", \"Plan\", \"Country\", \"id\", \"path\" … Matched against the person's properties without regard to case. */\n property: string;\n op: \"is\" | \"is not\" | \"in\" | \"not in\" | \"≥\" | \"in cohort\";\n values: string[];\n}\n\n/** Users who match every condition, of whom `rollout` percent get the flag. No conditions: everyone. */\nexport interface FlagConditionSet {\n conditions: FlagCondition[];\n /** 0 to 100. */\n rollout: number;\n}\n\nexport interface FlagConfig {\n key: string;\n /** Off: everyone gets the off side. */\n on: boolean;\n /** The first set a person matches decides; none matched: off. */\n sets: FlagConditionSet[];\n /** Multivariate flags: the variants and their split in percent (control included). Missing for an on/off flag. */\n variants?: { key: string; split: number; payload?: string }[];\n}\n\n/** What a person is for flag conditions: their properties from identify(), their id and the page they are on. */\nexport type FlagPerson = Record<string, unknown>;\n\nconst propOf = (person: FlagPerson, name: string) => {\n const want = name.trim().toLowerCase();\n for (const [k, v] of Object.entries(person)) if (k.toLowerCase() === want) return v;\n return undefined;\n};\n\n/** `\"@acme.com\"` matches every address at that domain; anything else matches the whole value, without regard to case. */\nconst same = (actual: string, value: string) => {\n const a = actual.trim().toLowerCase();\n const v = value.trim().toLowerCase();\n return v.startsWith(\"@\") ? a.endsWith(v) : a === v;\n};\n\nconst matchesCondition = (c: FlagCondition, person: FlagPerson) => {\n // Cohorts live in MRRocket; a browser cannot know them, so a cohort condition never matches here.\n if (c.op === \"in cohort\") return false;\n const raw = propOf(person, c.property);\n const actual = raw === undefined || raw === null ? \"\" : String(raw);\n if (c.op === \"≥\") {\n const a = Number(actual);\n const b = Number(c.values[0]);\n return actual !== \"\" && Number.isFinite(a) && Number.isFinite(b) && a >= b;\n }\n const hit = actual !== \"\" && c.values.some((v) => same(actual, v));\n return c.op === \"is\" || c.op === \"in\" ? hit : !hit;\n};\n\n/**\n * The flag for one person: `false` (off), `true` (on, an on/off flag) or the variant's key (a multivariate flag). The\n * bucket is a stable hash of flag and person, so a person keeps their side as the rollout grows.\n */\nexport const evaluateFlag = (flag: FlagConfig, distinctId: string, person: FlagPerson = {}): boolean | string => {\n if (!flag.on) return false;\n const subject = { id: distinctId, ...person };\n const set = flag.sets.length ? flag.sets.find((s) => s.conditions.every((c) => matchesCondition(c, subject))) : { conditions: [], rollout: 100 };\n if (!set) return false;\n if (flagUnit(`${flag.key}:rollout:${distinctId}`) * 100 >= set.rollout) return false;\n if (!flag.variants?.length) return true;\n const u = flagUnit(`${flag.key}:variant:${distinctId}`) * 100;\n let acc = 0;\n for (const v of flag.variants) {\n acc += v.split;\n if (u < acc) return v.key;\n }\n return flag.variants[flag.variants.length - 1].key;\n};\n\n/** A flag of the config for this person; an unknown flag (or no config) is off. */\nexport const flagFor = (key: string, config: CockpitConfig | null, distinctId: string, person: FlagPerson = {}) => {\n const flag = config?.flags?.find((f) => f.key === key);\n return flag ? evaluateFlag(flag, distinctId, person) : false;\n};\n\n/** One JavaScript error as it goes over the wire to `POST /api/sdk/errors`. */\nexport interface ErrorReport {\n /** \"TypeError\", \"Error\" … */\n type: string;\n message: string;\n /** The raw stack, at most 8 KB. MRRocket parses it into frames. */\n stack?: string;\n /** \"onerror\" (uncaught), \"onunhandledrejection\" (a rejected promise nobody caught) or \"manual\" (captureError). */\n mechanism: \"onerror\" | \"onunhandledrejection\" | \"manual\";\n handled: boolean;\n url: string;\n ts: number;\n /** What happened just before: pages and clicks, newest last, at most 20. */\n crumbs?: { ts: number; type: \"navigation\" | \"click\" | \"lifecycle\"; message: string }[];\n /** Your release (a version or commit), from the provider's `release` prop. */\n release?: string;\n distinctId?: string;\n sessionId?: string;\n}\n\n/**\n * Session recordings of a product, from the config. Recording also needs the visitor's own replay consent\n * (`<CockpitProvider replay>` or `setConsent({ replay: true })`); without it nothing is recorded or buffered.\n */\nexport interface ReplayConfig {\n /**\n * Share of sessions uploaded from their start, 0 to 1 (default 0.1). The others keep only the last minute in\n * memory and upload it when something goes wrong: a JS error, a rage click, a `purchase…` or `checkout…` event.\n */\n sampleRate: number;\n}\n\n/**\n * What the SDK may send and store.\n * - \"cookieless\" (default): no cookie, no localStorage. Events go without a visitor id; the server counts visitors\n * with a hash of key, date, IP and user agent that changes every day.\n * - \"cookies\": a persistent `ck_id` cookie identifies the visitor across visits, `ck_sid` holds the session.\n * - \"off\": nothing is sent and nothing is stored.\n */\nexport type ConsentMode = \"cookieless\" | \"cookies\" | \"off\";\n\n/**\n * What `setConsent` takes: a mode as before, or the parts to change. `replay` is the separate consent for session\n * recordings (default false); it applies only while analytics is not \"off\".\n *\n * setConsent(\"cookies\");\n * setConsent({ replay: true });\n * setConsent({ analytics: \"cookieless\", replay: false });\n */\nexport type ConsentChoice = ConsentMode | { analytics?: ConsentMode; replay?: boolean };\n\n/** The campaign parameters the SDK reads from the landing URL. */\nexport const UTM_KEYS = [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_term\", \"utm_content\"] as const;\nexport type UtmKey = (typeof UTM_KEYS)[number];\n\n/** One event as it goes over the wire to `POST /api/sdk/events`. */\nexport interface CockpitEvent {\n event: string;\n /** The visitor. Missing in \"cookieless\" mode until identify(): the server then uses its daily visitor hash. */\n distinctId?: string;\n /** Ends after 30 minutes without an event. */\n sessionId?: string;\n props?: Record<string, unknown>;\n /** Milliseconds since the epoch. */\n ts: number;\n url?: string;\n /** `document.referrer` on the first page of a page load, the previous in-app URL after client-side navigation. */\n referrer?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_term?: string;\n utm_content?: string;\n /** The screen size in CSS pixels (points on a phone). */\n screen?: { w: number; h: number };\n /** The app that sent it (React Native only): MRRocket stores it with the event and fills OS and device from it. */\n app?: AppContext;\n}\n\n/** Where a React Native event comes from. Every field is optional except the platform; nothing identifies the person. */\nexport interface AppContext {\n /** \"ios\" or \"android\" (React Native's `Platform.OS`). */\n platform: string;\n /** The app's version, like \"1.4.0\" (`expo-application`'s `nativeApplicationVersion`). */\n appVersion?: string;\n /** The build number, like \"42\". */\n build?: string;\n /** The OS version, like \"17.4\". */\n osVersion?: string;\n /** The device model, like \"iPhone 15 Pro\" (`expo-device`). */\n deviceModel?: string;\n /** \"phone\", \"tablet\", \"desktop\" or \"tv\" when `expo-device` knows it. */\n deviceType?: string;\n /** The first preferred locale, like \"de-DE\". */\n locale?: string;\n}\n\n/** The query parameter that forces variants, for previews in Cockpit: `?ck_preview=pricing-annual:a,home-hero:control`. */\nexport const PREVIEW_PARAM = \"ck_preview\";\n/** Set when Cockpit embeds the page: nothing is tracked, so previews never count as visits. */\nexport const EMBED_PARAM = \"ck_embed\";\n/** The cookie that keeps a visitor in the same variant across visits. Only written in \"cookies\" mode. */\nexport const ID_COOKIE = \"ck_id\";\n/** The cookie that holds the session id in \"cookies\" mode. */\nexport const SESSION_COOKIE = \"ck_sid\";\n/** A session ends after this long without an event. */\nexport const SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\n/** The UTM parameters from a parameter lookup (`URLSearchParams.get` in a browser). Empty values are left out. */\nexport const utmFrom = (get: (name: string) => string | null | undefined): Partial<Record<UtmKey, string>> => {\n const out: Partial<Record<UtmKey, string>> = {};\n for (const key of UTM_KEYS) {\n const value = get(key)?.trim();\n if (value) out[key] = value.slice(0, 150);\n }\n return out;\n};\n\n/** The UTM parameters of a query string, like `\"?utm_source=x\"`. Empty values are left out. */\nexport const readUtm = (search: string): Partial<Record<UtmKey, string>> => {\n const params = new URLSearchParams(search);\n return utmFrom((k) => params.get(k));\n};\n\n/**\n * The query parameters of a URL or query string, without `URLSearchParams` (React Native's is incomplete): `+` is a\n * space, values are percent-decoded, the first of a repeated name wins.\n */\nexport const parseQuery = (url: string): Record<string, string> => {\n const out: Record<string, string> = {};\n const q = url.split(\"#\")[0];\n const at = q.indexOf(\"?\");\n if (at < 0) return out;\n const dec = (s: string) => {\n try {\n return decodeURIComponent(s.replace(/\\+/g, \" \"));\n } catch {\n return s;\n }\n };\n for (const pair of q.slice(at + 1).split(\"&\")) {\n if (!pair) continue;\n const eq = pair.indexOf(\"=\");\n const k = dec(eq < 0 ? pair : pair.slice(0, eq));\n if (k && !(k in out)) out[k] = eq < 0 ? \"\" : dec(pair.slice(eq + 1));\n }\n return out;\n};\n\n/** FNV-1a, 32 bit, mapped to [0, 1). Stable across server and browser. */\nexport const hashUnit = (input: string) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0) / 4294967296;\n};\n\n/**\n * FNV-1a with murmur3's finalizer, mapped to [0, 1): ids that differ only at the end (\"user-1\", \"user-2\") still spread\n * evenly, so a 30 % rollout reaches about 30 % of people. Flags only; experiments keep `hashUnit` so nobody switches.\n */\nexport const flagUnit = (input: string) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n h = Math.imul(h, 0xc2b2ae35);\n h ^= h >>> 16;\n return (h >>> 0) / 4294967296;\n};\n\n/** The variant a visitor sees: a shipped winner, control while the experiment does not run, else a stable bucket by visitor. */\nexport const assign = (experiment: ExperimentConfig, distinctId: string): VariantId => {\n const control = experiment.variants[0]?.id ?? \"control\";\n if (experiment.winner) return experiment.winner;\n if (experiment.status !== \"running\") return control;\n const u = hashUnit(`${experiment.key}:${distinctId}`);\n let acc = 0;\n for (const v of experiment.variants) {\n acc += v.weight;\n if (u < acc) return v.id;\n }\n return experiment.variants[experiment.variants.length - 1]?.id ?? control;\n};\n\n/** `\"a:b,c:d\"` → `{ a: \"b\", c: \"d\" }`. Ignores anything malformed. */\nexport const parsePreview = (value: string | string[] | null | undefined): Record<string, VariantId> => {\n const raw = Array.isArray(value) ? value[0] : value;\n if (!raw) return {};\n const out: Record<string, VariantId> = {};\n for (const pair of raw.split(\",\")) {\n const [key, variant] = pair.split(\":\");\n if (key && variant) out[key.trim()] = variant.trim();\n }\n return out;\n};\n\n/** A link that shows one variant of a page, for example in Cockpit's preview frames. */\nexport const previewHref = (url: string, forced: Record<string, VariantId>, embed = true) => {\n const [path, query = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(query);\n const value = Object.entries(forced)\n .map(([k, v]) => `${k}:${v}`)\n .join(\",\");\n if (value) params.set(PREVIEW_PARAM, value);\n if (embed) params.set(EMBED_PARAM, \"1\");\n return `${path}?${params.toString()}`;\n};\n\n/** The variant for one experiment, from a forced preview first, then the config. Unknown experiments get control. */\n/** The experiments whose variants change the text `id`: showing that text is an exposure to them. */\nexport const experimentsOfText = (config: CockpitConfig | null, id: string) =>\n (config?.experiments ?? []).filter((e) => e.variants.some((v) => v.changes && id in v.changes)).map((e) => e.key);\n\nexport const resolveVariant = (key: string, config: CockpitConfig | null, distinctId: string, preview: Record<string, VariantId>): VariantId => {\n if (preview[key]) return preview[key];\n const experiment = config?.experiments.find((e) => e.key === key);\n return experiment ? assign(experiment, distinctId) : \"control\";\n};\n\n/**\n * Every text change that applies to this visitor: the published texts first, then each experiment's in config order.\n * Control keeps the published (or the page's own) words, so only a non-control variant (assigned, forced in a preview,\n * or a shipped winner) changes them further.\n */\nexport const textChanges = (config: CockpitConfig | null, distinctId: string, preview: Record<string, VariantId>) => {\n const out: Record<string, string> = { ...(config?.texts ?? {}) };\n for (const experiment of config?.experiments ?? []) {\n const id = resolveVariant(experiment.key, config, distinctId, preview);\n if (id === (experiment.variants[0]?.id ?? \"control\")) continue;\n Object.assign(out, experiment.variants.find((v) => v.id === id)?.changes ?? {});\n }\n return out;\n};\n\n/**\n * The query parameter a redirect test adds to the variant's address (`ck_x=<test>:<variant>`): the page there records\n * the exposure and takes it out of the address bar. It also keeps that page from redirecting again.\n */\nexport const EXPOSURE_PARAM = \"ck_x\";\n\n/** What `redirectFor` decided: go to `to`, and/or the redirect test this page belongs to and the visitor's variant. */\nexport interface RedirectDecision {\n /** Where to send the visitor now. Missing for control, which stays on the page. */\n to?: string;\n /** The redirect test, while it runs: record `$exposure` for it (on this page for control, on `to` otherwise). */\n experiment?: string;\n variant?: VariantId;\n}\n\nconst pathOf = (p: string) => p.replace(/\\/+$/, \"\") || \"/\";\n\n/**\n * Where a page sends the visitor, before it shows: a page redirect set in MRRocket first, else a redirect test that runs\n * on this path (the visitor's variant, by the same stable assignment as every test). Null when nothing applies.\n *\n * - The new address keeps the page's query (UTM parameters) and its hash; a running test adds `ck_x=<test>:<variant>`,\n * so the page it lands on records the exposure (and never redirects again).\n * - `distinctId` null (no stable id, as on a server without the `ck_id` cookie): running tests are left to the browser,\n * page redirects and shipped winners still apply.\n * - A redirect to the page itself is ignored.\n */\nexport const redirectFor = (config: CockpitConfig | null, href: string, distinctId: string | null, preview: Record<string, VariantId> = {}): RedirectDecision | null => {\n if (!config) return null;\n let here: URL;\n try {\n here = new URL(href);\n } catch {\n return null;\n }\n if (here.searchParams.has(EXPOSURE_PARAM)) return null;\n const path = pathOf(here.pathname);\n const go = (to: string, mark?: string) => {\n let t: URL;\n try {\n t = new URL(to, here);\n } catch {\n return undefined;\n }\n if (!/^https?:$/.test(t.protocol) || (t.origin === here.origin && pathOf(t.pathname) === path)) return undefined;\n here.searchParams.forEach((v, k) => {\n if (!t.searchParams.has(k)) t.searchParams.set(k, v);\n });\n if (mark) t.searchParams.set(EXPOSURE_PARAM, mark);\n if (!t.hash) t.hash = here.hash;\n return t.href;\n };\n for (const r of config.redirects ?? []) {\n const to = r.from && pathOf(r.from) === path ? go(r.to) : undefined;\n if (to) return { to };\n }\n for (const e of config.experiments) {\n if (!e.path || pathOf(e.path) !== path) continue;\n const running = e.status === \"running\" && !e.winner;\n if (running && distinctId === null && !preview[e.key]) return null;\n const variant = resolveVariant(e.key, config, distinctId ?? \"\", preview);\n const url = e.variants.find((v) => v.id === variant)?.url;\n const to = url ? go(url, running ? `${e.key}:${variant}` : undefined) : undefined;\n return running ? { to, experiment: e.key, variant } : to ? { to } : null;\n }\n return null;\n};\n\n/** The test and variant a redirect test's `ck_x` names, when the config has them; null otherwise. */\nexport const exposureFrom = (config: CockpitConfig | null, value: string | null | undefined) => {\n const [key, variant] = (value ?? \"\").split(\":\");\n const e = config?.experiments.find((x) => x.key === key);\n return e && e.variants.some((v) => v.id === variant) ? { experiment: key, variant } : null;\n};\n\n/**\n * The MRRocket API host from `NEXT_PUBLIC_MRROCKET_HOST`. Written as a literal property access on purpose: Next.js\n * inlines `process.env.NEXT_PUBLIC_*` at build time, in the browser bundle and in the server bundle (also on\n * Cloudflare Workers), and only replaces the literal form. Without a bundler (or a `process`) it is undefined.\n */\nexport const envHost = (): string | undefined => {\n try {\n return process.env.NEXT_PUBLIC_MRROCKET_HOST || undefined;\n } catch {\n return undefined;\n }\n};\n\n/** The public key from `NEXT_PUBLIC_MRROCKET_KEY`, the default for the `apiKey` prop. Same literal-access rule as `envHost`. */\nexport const envKey = (): string | undefined => {\n try {\n return process.env.NEXT_PUBLIC_MRROCKET_KEY || undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Where the API lives: the `host` prop, else `NEXT_PUBLIC_MRROCKET_HOST`, else \"\" (the page's own origin, which is how\n * MRRocket's own demo pages call it). Without a trailing slash.\n */\nexport const resolveHost = (host?: string) => (host ?? envHost() ?? \"\").trim().replace(/\\/+$/, \"\");\n\n/** A random visitor id. */\nexport const newDistinctId = () =>\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto ? crypto.randomUUID() : `ck_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n","/**\n * The SDK's fetch client and the shapes it reads, without React, so the script tag's widgets (src/script) use it too.\n * `./api` re-exports all of it with the `useApi` hook.\n */\nexport type PostStatus = \"review\" | \"planned\" | \"progress\" | \"shipped\";\n\nexport const STATUS_LABEL: Record<PostStatus, string> = {\n review: \"Under review\",\n planned: \"Planned\",\n progress: \"In progress\",\n shipped: \"Shipped\",\n};\n\nexport interface FeedbackBoardInfo {\n id: string;\n label: string;\n}\n\nexport interface FeedbackPost {\n id: string;\n title: string;\n body: string;\n board: string;\n status: PostStatus;\n votes: number;\n comments: number;\n voted: boolean;\n createdAt: string;\n /** \"Lena K.\", \"Anonymous\" or \"Team\". Missing from servers before SDK 0.6. */\n author?: string;\n}\n\n/** The product's public face for the board's header. */\nexport interface FeedbackProduct {\n name: string;\n logo: string | null;\n /** The domain's favicon, tried when `logo` does not load. Older servers leave it out. */\n logoFallback?: string | null;\n}\n\nexport interface FeedbackList {\n boards: FeedbackBoardInfo[];\n posts: FeedbackPost[];\n product?: FeedbackProduct;\n}\n\nexport interface FeedbackRoadmap {\n /** `review` (Backlog) comes from servers of SDK 0.6 on. */\n columns: { review?: FeedbackPost[]; planned: FeedbackPost[]; progress: FeedbackPost[]; shipped: FeedbackPost[] };\n}\n\nexport interface ChangelogEntry {\n id: string;\n title: string;\n body: string;\n publishedAt: string;\n}\n\nexport interface FeedbackComment {\n id: string;\n body: string;\n author: string;\n isTeam: boolean;\n postedAt: string;\n}\n\nexport type SurveyQuestionKind = \"nps\" | \"rating\" | \"single\" | \"multi\" | \"text\";\n\nexport interface SurveyQuestion {\n key: string;\n kind: SurveyQuestionKind;\n title: string;\n description?: string;\n required: boolean;\n options?: string[];\n scale?: number;\n low?: string;\n high?: string;\n placeholder?: string;\n}\n\nexport interface SurveyDefinition {\n id: string;\n name: string;\n type: string;\n thanks: string;\n questions: SurveyQuestion[];\n}\n\nexport type SurveyAnswer = number | string | string[];\n\n/** One message of the messenger's chat. \"visitor\" is the person on the site; the rest come from the product's team. */\nexport interface ChatMessage {\n id: string;\n from: \"visitor\" | \"team\" | \"ai\" | \"auto\";\n body: string;\n at: string;\n /** Help articles an answer drew on (servers from SDK 0.9 on). */\n articles?: { id: string; title: string }[];\n}\n\n/** A published help article in a list (the messenger's Help tab). */\nexport interface ArticleSummary {\n id: string;\n title: string;\n collection: string;\n excerpt: string;\n updatedAt: string;\n}\n\n/** A run of text inside an article block. Links are http(s), mailto or tel only. */\nexport interface ArticleSpan {\n text: string;\n href?: string;\n bold?: boolean;\n italic?: boolean;\n code?: boolean;\n}\n\n/** An article's content as blocks, written with textContent (never parsed as HTML). */\nexport type ArticleBlock =\n | { type: \"h2\" | \"h3\" | \"p\" | \"quote\"; spans: ArticleSpan[] }\n | { type: \"ul\" | \"ol\"; items: ArticleSpan[][] }\n | { type: \"code\"; text: string }\n | { type: \"hr\" };\n\nexport interface Article {\n id: string;\n title: string;\n collection: string;\n updatedAt: string;\n blocks: ArticleBlock[];\n}\n\n/** The messenger's look and texts as set in MRRocket › Support › Messenger (servers from SDK 0.9 on). */\nexport interface MessengerLook {\n accent: string;\n theme: \"light\" | \"dark\" | \"auto\";\n position: \"bottom-right\" | \"bottom-left\";\n title: string;\n greeting: string;\n label: string;\n /** How soon the team usually answers (MRRocket from 0.10; older servers leave it out). */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** A round chat button in the app (React Native) too. */\n appLauncher?: boolean;\n help: boolean;\n sound: boolean;\n preview: boolean;\n askEmail: boolean;\n}\n\n/** The line under \"Send us a message\" and in the chat's head. */\nexport const replyLine = (t: MessengerLook[\"replyTime\"]) =>\n t === \"minutes\" ? \"We usually reply in a few minutes\" : t === \"day\" ? \"We usually reply within a day\" : \"We usually reply in a few hours\";\n\n/** Black or white, whichever reads better on the accent (a light custom color gets dark text). */\nexport const inkOn = (hex: string) => {\n const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex);\n if (!m) return \"#ffffff\";\n const [r, g, b] = [m[1], m[2], m[3]].map((x) => {\n const c = parseInt(x, 16) / 255;\n return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.45 ? \"#111214\" : \"#ffffff\";\n};\n\n/** The visitor's newest chat (open or closed) and its messages. */\nexport interface ChatThread {\n conversation: { id: string; status: \"open\" | \"solved\" } | null;\n messages: ChatMessage[];\n /** The visitor gave an email already: the messenger stops asking. */\n hasEmail: boolean;\n}\n\nexport class ApiError extends Error {\n status: number;\n constructor(message: string, status: number) {\n super(message);\n this.status = status;\n }\n}\n\ninterface Conn {\n host: string;\n apiKey: string;\n distinctId: string;\n user?: { id?: string; [key: string]: unknown };\n}\n\n// Not URLSearchParams: React Native's lacks `set` in older versions, and the apps use this client too.\nconst qs = (params: Record<string, string | undefined>) =>\n Object.entries(params)\n .filter((e): e is [string, string] => !!e[1])\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n\nconst call = async <T>(url: string, init: RequestInit | undefined, signal?: AbortSignal): Promise<T> => {\n let res: Response;\n try {\n res = await fetch(url, {\n ...init,\n signal,\n headers: init?.body ? { \"content-type\": \"application/json\" } : undefined,\n });\n } catch (e) {\n if ((e as Error).name === \"AbortError\") throw e;\n throw new ApiError(\"Could not reach the server. Check your connection and try again.\", 0);\n }\n if (!res.ok) {\n let detail = \"\";\n try {\n detail = ((await res.json()) as { error?: string }).error ?? \"\";\n } catch {\n // Not JSON; the status is enough.\n }\n throw new ApiError(detail || (res.status === 429 ? \"Too many requests. Try again in a minute.\" : \"Something went wrong. Please try again.\"), res.status);\n }\n return (await res.json()) as T;\n};\n\n/** The small fetch client behind the widgets. Every read takes an AbortSignal so unmounting cancels it. */\nexport const createApi = (c: Conn) => {\n const base = `${c.host}/api/sdk`;\n const who = { key: c.apiKey, distinctId: c.distinctId, user: c.user };\n const post = <T>(path: string, body: Record<string, unknown>, signal?: AbortSignal) =>\n call<T>(`${base}${path}`, { method: \"POST\", body: JSON.stringify({ ...who, ...body }) }, signal);\n return {\n list: (o: { board?: string; sort?: \"top\" | \"new\"; q?: string }, signal?: AbortSignal) =>\n call<FeedbackList>(`${base}/feedback?${qs({ key: c.apiKey, distinctId: c.distinctId, board: o.board, sort: o.sort, q: o.q })}`, undefined, signal),\n post: (id: string, signal?: AbortSignal) =>\n call<FeedbackPost>(`${base}/feedback/${encodeURIComponent(id)}?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n roadmap: (signal?: AbortSignal) => call<FeedbackRoadmap>(`${base}/feedback/roadmap?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n changelog: (signal?: AbortSignal) => call<{ entries: ChangelogEntry[] }>(`${base}/feedback/changelog?${qs({ key: c.apiKey })}`, undefined, signal),\n submit: (p: { title: string; body?: string; board: string }) => post<FeedbackPost>(\"/feedback\", p),\n vote: (id: string) => post<{ voted: boolean; votes: number }>(`/feedback/${encodeURIComponent(id)}/vote`, {}),\n comments: (id: string, signal?: AbortSignal) =>\n call<{ comments: FeedbackComment[] }>(`${base}/feedback/${encodeURIComponent(id)}/comments?${qs({ key: c.apiKey })}`, undefined, signal),\n comment: (id: string, body: string) => post<FeedbackComment>(`/feedback/${encodeURIComponent(id)}/comments`, { body }),\n survey: (url: string, signal?: AbortSignal) =>\n call<{ survey: SurveyDefinition | null }>(`${base}/surveys?${qs({ key: c.apiKey, distinctId: c.distinctId, url })}`, undefined, signal),\n seen: (id: string) => post<unknown>(`/surveys/${encodeURIComponent(id)}/seen`, { user: undefined }),\n respond: (id: string, r: { answers: Record<string, SurveyAnswer>; completed: boolean; seconds: number }) =>\n post<unknown>(`/surveys/${encodeURIComponent(id)}/respond`, r),\n chat: (signal?: AbortSignal) => call<ChatThread>(`${base}/messages?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n sendChat: (m: { body: string; email?: string; url?: string }) => post<ChatThread>(\"/messages\", m),\n articles: (q?: string, signal?: AbortSignal) => call<{ articles: ArticleSummary[] }>(`${base}/articles?${qs({ key: c.apiKey, q })}`, undefined, signal),\n article: (id: string, signal?: AbortSignal) =>\n call<Article>(`${base}/articles/${encodeURIComponent(id)}?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n messengerLook: (signal?: AbortSignal) => call<MessengerLook>(`${base}/messenger?${qs({ key: c.apiKey })}`, undefined, signal),\n rateArticle: (id: string, helpful: boolean) => post<{ counted: boolean }>(`/articles/${encodeURIComponent(id)}/rate`, { helpful }),\n };\n};\n\nexport type Api = ReturnType<typeof createApi>;\n","/**\n * How events go over the wire to `POST /api/sdk/events`, shared by every runtime (Next.js, the script tag, React\n * Native): request bodies of at most 100 events each, under the server's 64 KB. No React, no browser APIs, no\n * TextEncoder (Hermes on older React Native lacks it), so it runs anywhere.\n */\nimport type { CockpitEvent } from \"./core\";\n\n/** The server takes at most 100 events and 64 KB per request; stay a little under the size. */\nexport const MAX_BATCH = 100;\nexport const MAX_BYTES = 60_000;\n\n/** What a batch says about the SDK that sent it (Build › Errors and Feature flags show it). */\nexport interface SdkInfo {\n v: string;\n errors: boolean;\n /** \"web\" (script tag), \"ios\" or \"android\" (React Native). Missing from the Next.js provider. */\n platform?: string;\n}\n\n/** UTF-8 length of a string, the way TextEncoder counts it (a lone surrogate becomes U+FFFD, three bytes). */\nexport const byteLength = (s: string) => {\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) n += 1;\n else if (c < 0x800) n += 2;\n else if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {\n n += 4;\n i++;\n } else n += 3;\n }\n return n;\n};\n\n/** One request: its body and the events in it (so a client can keep the ones that did not arrive). */\nexport interface BatchRequest<E> {\n body: string;\n events: E[];\n}\n\n/**\n * Splits events into request bodies of at most 100 events each, under the size limit. An event too large on its own is\n * dropped (it is in no request).\n */\nexport const batchRequests = <E extends CockpitEvent>(key: string, events: E[], sdk: SdkInfo): BatchRequest<E>[] => {\n const head = `{\"key\":${JSON.stringify(key)},\"sdk\":${JSON.stringify(sdk)},\"events\":[`;\n const empty = byteLength(head) + 2;\n const out: BatchRequest<E>[] = [];\n let chunk: string[] = [];\n let items: E[] = [];\n let size = empty;\n const close = () => {\n if (chunk.length) out.push({ body: `${head}${chunk.join(\",\")}]}`, events: items });\n chunk = [];\n items = [];\n size = empty;\n };\n for (const event of events) {\n const json = JSON.stringify(event);\n const n = byteLength(json) + 1;\n if (empty + n > MAX_BYTES) continue;\n if (chunk.length === MAX_BATCH || size + n > MAX_BYTES) close();\n chunk.push(json);\n items.push(event);\n size += n;\n }\n close();\n return out;\n};\n\n/**\n * Request bodies of at most 100 events each, under the size limit. An event too large on its own is dropped. `sdk` tells\n * MRRocket which SDK the site runs and whether it reports errors (Build › Errors and Feature flags show it).\n */\nexport const bodies = (key: string, events: CockpitEvent[], sdk: SdkInfo) => batchRequests(key, events, sdk).map((r) => r.body);\n","/**\n * Error tracking: uncaught errors and unhandled promise rejections of the page (and `captureError` for ones you\n * catch), sent to `POST /api/sdk/errors`, where MRRocket groups them into issues for Build › Errors. Independent of\n * session recordings. Only the error itself, the page URL and the last pages and clicks go along (no typed text, no\n * network bodies), under the same consent as analytics.\n *\n * Limits on the page: the same error is sent once per page load, at most 20 errors per page load, in batches every\n * 2 seconds and with `sendBeacon` when the page hides.\n */\nimport type { ErrorReport } from \"./core\";\n\nconst MAX_STACK = 8 * 1024;\nconst MAX_PER_PAGE = 20;\nconst MAX_CRUMBS = 20;\nconst FLUSH_MS = 2000;\n\nexport interface ErrorCapture {\n /** An error you caught yourself; `handled` is true. */\n capture: (error: unknown, mechanism?: ErrorReport[\"mechanism\"]) => void;\n /** A page view or a click for the breadcrumbs. */\n crumb: (type: \"navigation\" | \"click\" | \"lifecycle\", message: string) => void;\n stop: () => void;\n}\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}…` : s);\n\n/** Type, message and stack of anything thrown. */\nexport const describeError = (error: unknown): { type: string; message: string; stack?: string } => {\n if (error instanceof Error) return { type: error.name || \"Error\", message: clip(error.message || String(error), 1000), stack: error.stack ? clip(error.stack, MAX_STACK) : undefined };\n if (typeof error === \"string\") return { type: \"Error\", message: clip(error, 1000) };\n try {\n return { type: \"Error\", message: clip(JSON.stringify(error) ?? String(error), 1000) };\n } catch {\n return { type: \"Error\", message: String(error) };\n }\n};\n\nexport const startErrorCapture = (opts: {\n host: string;\n apiKey: string;\n release?: string;\n /** Read when an error happens: whether to send at all (consent), and who and which session. */\n context: () => { send: boolean; distinctId?: string; sessionId?: string };\n warn: (message: string) => void;\n}): ErrorCapture => {\n const queue: ErrorReport[] = [];\n const crumbs: NonNullable<ErrorReport[\"crumbs\"]> = [];\n const seen = new Set<string>();\n let sent = 0;\n const url = `${opts.host}/api/sdk/errors`;\n\n const flush = (beacon = false) => {\n // At most four reports per request: four full stacks stay under the server's 64 KB.\n while (queue.length) {\n const body = JSON.stringify({ key: opts.apiKey, errors: queue.splice(0, 4) });\n const ok = beacon && typeof navigator !== \"undefined\" && \"sendBeacon\" in navigator && navigator.sendBeacon(url, body);\n if (!ok)\n fetch(url, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body, keepalive: true })\n .then((r) => {\n if (!r.ok && r.status !== 429) opts.warn(`Error reports were rejected with ${r.status}. Check the public key and NEXT_PUBLIC_MRROCKET_HOST.`);\n })\n .catch(() => {});\n }\n };\n\n const capture = (error: unknown, mechanism: ErrorReport[\"mechanism\"] = \"manual\") => {\n const ctx = opts.context();\n if (!ctx.send || sent >= MAX_PER_PAGE) return;\n const d = describeError(error);\n // Our own reports failing must never report themselves.\n if (/\\/api\\/sdk\\/errors/.test(d.message)) return;\n const mark = `${d.type}:${d.message}`;\n if (seen.has(mark)) return;\n seen.add(mark);\n sent++;\n queue.push({\n ...d,\n mechanism,\n handled: mechanism === \"manual\",\n url: window.location.href,\n ts: Date.now(),\n crumbs: crumbs.slice(),\n ...(opts.release ? { release: opts.release } : {}),\n ...(ctx.distinctId ? { distinctId: ctx.distinctId } : {}),\n ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),\n });\n };\n\n const onError = (e: ErrorEvent) => {\n // \"Script error.\" from a cross-origin script carries nothing useful.\n if (!e.error && (!e.message || e.message === \"Script error.\")) return;\n capture(e.error ?? new Error(e.message), \"onerror\");\n };\n const onRejection = (e: PromiseRejectionEvent) => capture(e.reason ?? new Error(\"Unhandled promise rejection\"), \"onunhandledrejection\");\n const onHide = () => flush(true);\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n window.addEventListener(\"pagehide\", onHide);\n const timer = window.setInterval(() => flush(), FLUSH_MS);\n\n return {\n capture,\n crumb: (type, message) => {\n crumbs.push({ ts: Date.now(), type, message: clip(message, 120) });\n if (crumbs.length > MAX_CRUMBS) crumbs.shift();\n },\n stop: () => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n window.removeEventListener(\"pagehide\", onHide);\n window.clearInterval(timer);\n flush(true);\n },\n };\n};\n","/**\n * The cancel flow, onboarding and in-app messages (SDK 0.7.0): what MRRocket's config and `GET /api/sdk/inapp` serve,\n * and one controller that decides what shows when and records what the person did. No DOM and no React: the web\n * renderer (flows-ui.ts, loaded only when something shows) and the React Native one (native/flows-view.ts) draw\n * `view()` and call the actions.\n *\n * What it records, as normal events under the SDK's analytics consent (nothing with consent \"off\"):\n * - `$cancel_flow` `{action: \"shown\" | \"answered\" | \"offer\" | \"finished\", run, version, …}`. MRRocket turns a\n * `finished` with `outcome: \"saved\"` into a save and with `outcome: \"cancelled\"` into a cancellation on the Churn page.\n * MRRocket never changes a subscription: an accepted offer goes to the app's `onSave`, a confirmed cancel to its\n * `onCancel`, and only after they succeed is the outcome recorded.\n * - `$onboarding` `{flow, step?, action: \"started\" | \"shown\" | \"completed\" | \"dismissed\"}`.\n * - `$inapp` `{message, journey, action: \"shown\" | \"clicked\" | \"dismissed\"}`; the journey moves the person on.\n */\nimport type { CockpitConfig } from \"./core\";\n\nexport const CANCEL_EVENT = \"$cancel_flow\";\nexport const ONBOARDING_EVENT = \"$onboarding\";\nexport const INAPP_EVENT = \"$inapp\";\n\nexport type CancelOfferKind = \"discount\" | \"pause\" | \"downgrade\" | \"contact\";\n\n/** What one answer of the survey offers before the confirmation. An answer without one goes straight to it. */\nexport interface CancelOffer {\n kind: CancelOfferKind;\n headline: string;\n /** Discount: percent off. */\n percent?: number;\n /** Discount: for how many months; pause: up to how many months. */\n months?: number;\n /** Downgrade: the plan to switch to, as MRRocket knows it from the payment provider. */\n plan?: string;\n planName?: string;\n}\n\n/** The product's live cancel flow (MRRocket › Churn › Cancel flow). */\nexport interface CancelFlowConfig {\n /** Grows with every publish. */\n version: number;\n question: string;\n /** The survey's answers, in order. */\n reasons: { id: string; label: string }[];\n /** The offer per answer id. */\n offers: Record<string, CancelOffer>;\n confirm: { title: string; body: string; button: string };\n /**\n * Who gets the survey and the offers: business customers only. Anyone else (a consumer, or a customer the app does\n * not say) gets the plain confirmation, with nothing in the way of cancelling (§ 312k BGB).\n */\n offersFor: \"business\";\n}\n\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\";\n\nexport interface OnboardingStep {\n id: string;\n kind: OnboardingStepKind;\n title: string;\n body?: string;\n button?: string;\n /** Tour steps: the element they point at, marked `data-ck-target=\"<target>\"` in the app. Without it: a card. */\n target?: string;\n /** Checklist items: the event that ticks them (`track(\"<event>\")`). Without it the person ticks it themselves. */\n event?: string;\n}\n\n/** A live onboarding flow's in-app steps (MRRocket › Conversion › Onboarding); its emails go out from MRRocket. */\nexport interface OnboardingFlow {\n id: string;\n name: string;\n /** When it starts: an event's words (\"Signed up\", \"First export\"), or \"First launch\" / \"First visit\". */\n trigger: string;\n steps: OnboardingStep[];\n}\n\n/** An in-app message a Lifecycle journey has for this person. */\nexport interface InAppMessage {\n id: string;\n journey?: string;\n title: string;\n body?: string;\n button?: string;\n /** Where the button goes (http(s) or a path of the app). */\n url?: string;\n style: \"banner\" | \"modal\";\n}\n\n/** What `GET /api/sdk/inapp` answers for one signed-in person. */\nexport interface InAppState {\n /** Progress per onboarding flow: the steps done and whether the person closed it. */\n onboarding: Record<string, { done: string[]; dismissed?: boolean }>;\n messages: InAppMessage[];\n}\n\nexport interface CancelFlowResult {\n /** \"cancelled\": confirmed; \"saved\": took the offer; \"kept\": closed the dialog without cancelling. */\n outcome: \"cancelled\" | \"saved\" | \"kept\";\n reason?: string;\n reasonLabel?: string;\n offer?: CancelOffer;\n /** What the customer wrote on the confirmation, if anything. */\n comment?: string;\n /** This run's id, the same as in the events. */\n run: string;\n}\n\nexport interface CancelFlowOptions {\n /**\n * \"business\" shows the survey and the offers; anything else (the default) only the plain confirmation, so a\n * consumer can always cancel in one step (§ 312k BGB).\n */\n customer?: \"business\" | \"consumer\";\n /** The customer's current price, to show what a discount costs (`{ amount: 29, currency: \"EUR\" }`). */\n price?: { amount: number; currency: string; interval?: \"month\" | \"year\" };\n /** The customer confirmed: cancel the subscription in your code. Throwing keeps the dialog open with an error. */\n onCancel?: (result: CancelFlowResult) => unknown;\n /** The customer took an offer: apply it in your code (coupon, pause, plan change). Throwing keeps the dialog open. */\n onSave?: (result: CancelFlowResult) => unknown;\n /** Closed without cancelling or taking an offer. */\n onClose?: (result: CancelFlowResult) => void;\n}\n\n/** What a renderer draws. */\nexport type FlowView =\n | {\n type: \"cancel\";\n screen: \"survey\" | \"offer\" | \"confirm\";\n flow: CancelFlowConfig;\n /** The answer picked on the survey. */\n reason?: string;\n offer?: CancelOffer;\n price?: CancelFlowOptions[\"price\"];\n busy: boolean;\n error?: string;\n /** The step for the dots, 1 to `steps`. */\n step: number;\n steps: number;\n }\n | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean }\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean }[] }\n | { type: \"message\"; message: InAppMessage };\n\nexport interface FlowsEnv {\n /** Records an event under the SDK's consent (the normal queue). */\n track(event: string, props?: Record<string, unknown>): void;\n /** Whose messages and progress these are: the identify() id; undefined while nobody is signed in. */\n personId(): string | undefined;\n /** `GET /api/sdk/inapp` for that person; null when it fails. */\n fetchInApp(personId: string): Promise<InAppState | null>;\n /** Keeps onboarding progress on the device; only while the consent lets the SDK store something. */\n storage?: () => { get(key: string): string | null | Promise<string | null>; set(key: string, value: string): void } | null;\n /** Opens a message's link. */\n openUrl?: (url: string) => void;\n /** Start onboarding flows by their trigger on its own (default true). */\n auto?: boolean;\n}\n\nexport interface FlowsController {\n setConfig(config: CockpitConfig | null): void;\n /** The person changed (identify, reset, consent): loads their messages and onboarding progress. */\n refresh(): Promise<void>;\n /** An event the app recorded: starts flows whose trigger it is and ticks checklist items. */\n onEvent(name: string): void;\n openCancelFlow(options?: CancelFlowOptions): Promise<CancelFlowResult>;\n /** Starts an onboarding flow now (the first live one without an id). False when there is none to start. */\n startOnboarding(id?: string): boolean;\n view(): FlowView | null;\n subscribe(listener: () => void): () => void;\n /** `accept(comment)`: a \"Talk to us\" offer sends what the customer wrote with it. */\n cancel: { pick(reason: string): void; next(): void; accept(comment?: string): void; decline(): void; confirm(comment?: string): void; close(): void };\n onboarding: { next(): void; check(stepId: string): void; dismiss(): void };\n message: { click(): void; dismiss(): void };\n}\n\n/** The plain confirmation, when the product has no live cancel flow (or MRRocket was not reachable). */\nexport const PLAIN_CANCEL: CancelFlowConfig = {\n version: 0,\n question: \"\",\n reasons: [],\n offers: {},\n confirm: { title: \"Cancel your subscription?\", body: \"You keep access until the end of the billing period.\", button: \"Cancel subscription\" },\n offersFor: \"business\",\n};\n\nconst FAILED = \"Something went wrong. Please try again.\";\nconst PROGRESS_KEY = \"mrrocket:onboarding\";\n\n/** `\"Signed up\"` → `signed_up`, the way MRRocket names events from words. */\nexport const eventSlug = (s: string) =>\n s\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst SIGNUP = new Set([\"signed_up\", \"signup\", \"sign_up\", \"registered\", \"account_created\", \"user_signed_up\"]);\n\n/** Whether recording `event` is the trigger's moment (\"Signed up\" is any of the usual signup event names). */\nexport const matchesTrigger = (trigger: string, event: string) => {\n const t = eventSlug(trigger);\n const e = eventSlug(event);\n if (!t || !e) return false;\n return t === e || (SIGNUP.has(t) && SIGNUP.has(e));\n};\n\n/** Triggers that mean \"the first time the person opens the app\": the flow starts on load until it is done. */\nexport const startsOnLoad = (trigger: string) =>\n /^(first (launch|visit|open|session|login|sign ?in|app open)|app (opened|launched)|on load|every visit|always)?$/i.test(trigger.trim());\n\n/** A random id for one cancel flow run. */\nexport const runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;\n\n/** The money a discount leaves: `29 EUR` at 30 % → `20.30`. */\nexport const discounted = (amount: number, percent: number) => Math.round(amount * (1 - percent / 100) * 100) / 100;\n\n/** \"€20.30\" in the customer's own currency, without a library. */\nexport const money = (amount: number, currency: string) => {\n try {\n return new Intl.NumberFormat(undefined, { style: \"currency\", currency }).format(amount);\n } catch {\n return `${amount.toFixed(2)} ${currency}`;\n }\n};\n\n/** The button of an offer. */\nexport const offerButton = (o: CancelOffer) =>\n o.kind === \"contact\" ? \"Send to the team\" : o.kind === \"pause\" ? \"Pause instead\" : o.kind === \"downgrade\" ? \"Switch plan\" : \"Accept offer\";\n\n/** A link a message may open: http(s), or a path of the app. Nothing else (no `javascript:`). */\nexport const safeUrl = (url: string | undefined) => {\n const u = (url ?? \"\").trim();\n return /^https?:\\/\\//i.test(u) || /^\\/(?!\\/)/.test(u) ? u : undefined;\n};\n\ninterface Progress {\n done: Set<string>;\n dismissed: boolean;\n}\n\ninterface CancelRun {\n flow: CancelFlowConfig;\n options: CancelFlowOptions;\n plain: boolean;\n screen: \"survey\" | \"offer\" | \"confirm\";\n reason?: string;\n run: string;\n busy: boolean;\n error?: string;\n resolve: (r: CancelFlowResult) => void;\n promise: Promise<CancelFlowResult>;\n}\n\nexport const createFlows = (env: FlowsEnv): FlowsController => {\n let config: CockpitConfig | null = null;\n let cancel: CancelRun | null = null;\n let active: string | null = null;\n let messages: InAppMessage[] = [];\n let known = false;\n let loading: Promise<void> | null = null;\n let loadedFor: string | undefined;\n let progressFor: string | undefined | null = null;\n const progress = new Map<string, Progress>();\n const handled = new Set<string>();\n const shown = new Set<string>();\n const listeners = new Set<() => void>();\n const auto = env.auto !== false;\n\n const flows = () => config?.onboarding ?? [];\n const flowById = (id: string | null) => (id ? flows().find((f) => f.id === id) : undefined);\n const prog = (id: string) => {\n let p = progress.get(id);\n if (!p) progress.set(id, (p = { done: new Set(), dismissed: false }));\n return p;\n };\n const finished = (f: OnboardingFlow) => {\n const p = progress.get(f.id);\n return !!p && (p.dismissed || f.steps.every((s) => p.done.has(s.id)));\n };\n\n const keyOf = (pid: string | undefined) => `${PROGRESS_KEY}:${pid ?? \"visitor\"}`;\n\n const save = () => {\n const store = env.storage?.();\n if (!store) return;\n const out: Record<string, { done: string[]; dismissed?: boolean }> = {};\n for (const [id, p] of progress) out[id] = { done: [...p.done], ...(p.dismissed ? { dismissed: true } : {}) };\n try {\n store.set(keyOf(env.personId()), JSON.stringify(out));\n } catch {\n // Storage full or gone: progress stays in memory.\n }\n };\n\n const merge = (state: InAppState[\"onboarding\"] | undefined) => {\n for (const [id, s] of Object.entries(state ?? {})) {\n const p = prog(id);\n for (const d of s.done ?? []) p.done.add(d);\n if (s.dismissed) p.dismissed = true;\n }\n };\n\n // ---------- What shows ----------\n\n const onboardingView = (): FlowView | null => {\n const flow = flowById(active);\n if (!flow) return null;\n const p = prog(flow.id);\n const at = flow.steps.findIndex((s) => !p.done.has(s.id));\n if (at < 0 || p.dismissed) return null;\n const step = flow.steps[at];\n if (step.kind === \"checklist\") {\n let from = at;\n while (from > 0 && flow.steps[from - 1].kind === \"checklist\") from--;\n let to = at;\n while (to + 1 < flow.steps.length && flow.steps[to + 1].kind === \"checklist\") to++;\n return { type: \"checklist\", flow, items: flow.steps.slice(from, to + 1).map((s) => ({ step: s, done: p.done.has(s.id) })) };\n }\n return { type: \"step\", flow, step, index: at, total: flow.steps.length, last: at === flow.steps.length - 1 };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const offer = cancel.reason ? cancel.flow.offers[cancel.reason] : undefined;\n return {\n type: \"cancel\",\n screen: cancel.screen,\n flow: cancel.flow,\n reason: cancel.reason,\n offer: cancel.screen === \"offer\" ? offer : undefined,\n price: cancel.options.price,\n busy: cancel.busy,\n error: cancel.error,\n step: cancel.plain ? 1 : cancel.screen === \"survey\" ? 1 : cancel.screen === \"offer\" ? 2 : 3,\n steps: cancel.plain ? 1 : 3,\n };\n }\n const ob = onboardingView();\n if (ob) return ob;\n // A flow that just ended lets the next thing show.\n if (active) active = null;\n const m = messages.find((x) => !handled.has(x.id));\n return m ? { type: \"message\", message: m } : null;\n };\n\n /** Tells the renderers, and records what became visible (once per step or message per page load). */\n const emit = () => {\n const v = view();\n if (v?.type === \"step\" && !shown.has(`s:${v.step.id}`)) {\n shown.add(`s:${v.step.id}`);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: \"shown\" });\n } else if (v?.type === \"checklist\") {\n for (const i of v.items)\n if (!i.done && !shown.has(`s:${i.step.id}`)) {\n shown.add(`s:${i.step.id}`);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: i.step.id, kind: \"checklist\", action: \"shown\" });\n }\n } else if (v?.type === \"message\" && !shown.has(`m:${v.message.id}`)) {\n shown.add(`m:${v.message.id}`);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"shown\" });\n }\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n\n const start = (flow: OnboardingFlow) => {\n if (active === flow.id) return true;\n if (active && flowById(active) && !finished(flowById(active)!)) return false;\n active = flow.id;\n env.track(ONBOARDING_EVENT, { flow: flow.id, action: \"started\" });\n emit();\n return true;\n };\n\n /** Flows whose trigger is \"the first launch\" start once their progress is known (never twice for a done flow). */\n const autoStart = () => {\n if (!auto || active || !known) return;\n // Without an id or storage a \"first launch\" could not be told from any other: no automatic start then.\n if (!env.personId() && !env.storage?.()) return;\n const next = flows().find((f) => startsOnLoad(f.trigger) && f.steps.length && !finished(f));\n if (next) start(next);\n };\n\n const refresh = () => {\n const pid = env.personId();\n // Another person on this device: nothing of the one before carries over.\n if (progressFor !== null && progressFor !== pid) {\n progress.clear();\n handled.clear();\n active = null;\n loadedFor = undefined;\n }\n progressFor = pid;\n const run = (async () => {\n const store = env.storage?.();\n if (store) {\n try {\n const raw = await store.get(keyOf(pid));\n if (raw) merge(JSON.parse(raw) as InAppState[\"onboarding\"]);\n } catch {\n // A damaged entry is ignored.\n }\n }\n const wants = flows().length > 0 || !!config?.messages;\n if (pid && wants && loadedFor !== pid) {\n loadedFor = pid;\n const state = await env.fetchInApp(pid).catch(() => null);\n if (state && env.personId() === pid) {\n merge(state.onboarding);\n messages = (state.messages ?? []).filter((m) => m && m.id && m.title);\n }\n }\n if (!pid) messages = [];\n known = true;\n autoStart();\n emit();\n })();\n loading = run.finally(() => {\n if (loading === run) loading = null;\n });\n return loading;\n };\n\n // ---------- Cancel flow ----------\n\n const result = (c: CancelRun, outcome: CancelFlowResult[\"outcome\"], comment?: string): CancelFlowResult => {\n const offer = c.reason ? c.flow.offers[c.reason] : undefined;\n return {\n outcome,\n run: c.run,\n ...(c.reason ? { reason: c.reason, reasonLabel: c.flow.reasons.find((r) => r.id === c.reason)?.label } : {}),\n ...(outcome === \"saved\" && offer ? { offer } : {}),\n ...(comment?.trim() ? { comment: comment.trim().slice(0, 500) } : {}),\n };\n };\n\n const finish = (c: CancelRun, r: CancelFlowResult) => {\n env.track(CANCEL_EVENT, {\n action: \"finished\",\n run: c.run,\n version: c.flow.version,\n outcome: r.outcome,\n customer: c.options.customer ?? \"consumer\",\n ...(r.reason ? { reason: r.reason } : {}),\n ...(r.offer ? { offer: r.offer.kind } : {}),\n ...(r.comment ? { comment: r.comment } : {}),\n });\n if (cancel === c) cancel = null;\n c.resolve(r);\n emit();\n };\n\n /** Runs the app's callback; the outcome is recorded only once it went through. */\n const settle = (c: CancelRun, outcome: \"saved\" | \"cancelled\", comment?: string) => {\n if (c.busy) return;\n const r = result(c, outcome, comment);\n const fn = outcome === \"saved\" ? c.options.onSave : c.options.onCancel;\n c.busy = true;\n c.error = undefined;\n emit();\n Promise.resolve()\n .then(() => fn?.(r))\n .then(\n () => finish(c, r),\n () => {\n c.busy = false;\n c.error = FAILED;\n emit();\n },\n );\n };\n\n const openCancelFlow = (options: CancelFlowOptions = {}) => {\n if (cancel) return cancel.promise;\n const flow = config?.cancelFlow ?? PLAIN_CANCEL;\n const plain = options.customer !== \"business\" || flow.reasons.length < 2;\n let resolve: (r: CancelFlowResult) => void = () => {};\n const promise = new Promise<CancelFlowResult>((r) => (resolve = r));\n const c: CancelRun = { flow, options, plain, screen: plain ? \"confirm\" : \"survey\", run: runId(), busy: false, resolve, promise };\n cancel = c;\n env.track(CANCEL_EVENT, { action: \"shown\", run: c.run, version: flow.version, customer: options.customer ?? \"consumer\", plain });\n emit();\n return promise;\n };\n\n const controller: FlowsController = {\n setConfig: (c) => {\n config = c;\n if (active && !flowById(active)) active = null;\n emit();\n },\n refresh,\n onEvent: (name) => {\n if (!name || name.startsWith(\"$\")) return;\n const flow = flowById(active);\n let ticked = false;\n if (flow) {\n const p = prog(flow.id);\n for (const s of flow.steps)\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n p.done.add(s.id);\n ticked = true;\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n }\n if (ticked) {\n save();\n emit();\n }\n // Like the first-launch start: only for someone whose progress is kept, so nobody gets a flow twice.\n if (!auto || (!env.personId() && !env.storage?.())) return;\n const next = flows().find((f) => f.steps.length && matchesTrigger(f.trigger, name) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : flows().find((x) => x.steps.length && !finished(x));\n if (!f || !f.steps.length) return false;\n const p = prog(f.id);\n // Started by hand: a flow the person closed before shows again.\n p.dismissed = false;\n return start(f);\n },\n view,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n cancel: {\n pick: (reason) => {\n if (!cancel || cancel.busy || !cancel.flow.reasons.some((r) => r.id === reason)) return;\n cancel.reason = reason;\n cancel.error = undefined;\n emit();\n },\n next: () => {\n const c = cancel;\n if (!c || c.screen !== \"survey\" || !c.reason) return;\n env.track(CANCEL_EVENT, { action: \"answered\", run: c.run, version: c.flow.version, reason: c.reason });\n c.screen = c.flow.offers[c.reason] ? \"offer\" : \"confirm\";\n emit();\n },\n accept: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || !c.reason) return;\n const offer = c.flow.offers[c.reason];\n if (!c.busy)\n env.track(CANCEL_EVENT, {\n action: \"offer\",\n run: c.run,\n version: c.flow.version,\n reason: c.reason,\n offer: offer?.kind,\n outcome: \"accepted\",\n });\n settle(c, \"saved\", comment);\n },\n decline: () => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || c.busy) return;\n env.track(CANCEL_EVENT, {\n action: \"offer\",\n run: c.run,\n version: c.flow.version,\n reason: c.reason,\n offer: c.reason ? c.flow.offers[c.reason]?.kind : undefined,\n outcome: \"declined\",\n });\n c.screen = \"confirm\";\n c.error = undefined;\n emit();\n },\n confirm: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"confirm\") return;\n settle(c, \"cancelled\", comment);\n },\n close: () => {\n const c = cancel;\n if (!c || c.busy) return;\n const r = result(c, \"kept\");\n c.options.onClose?.(r);\n finish(c, r);\n },\n },\n onboarding: {\n next: () => {\n const v = onboardingView();\n if (v?.type !== \"step\") return;\n prog(v.flow.id).done.add(v.step.id);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: \"completed\" });\n save();\n emit();\n },\n check: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return;\n const item = v.items.find((i) => i.step.id === stepId);\n if (!item || item.done) return;\n prog(v.flow.id).done.add(stepId);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"completed\" });\n save();\n emit();\n },\n dismiss: () => {\n const v = onboardingView();\n if (!v || (v.type !== \"step\" && v.type !== \"checklist\")) return;\n prog(v.flow.id).dismissed = true;\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, ...(v.type === \"step\" ? { step: v.step.id } : {}), action: \"dismissed\" });\n active = null;\n save();\n emit();\n },\n },\n message: {\n click: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"clicked\" });\n const url = safeUrl(v.message.url);\n emit();\n if (url) env.openUrl?.(url);\n },\n dismiss: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"dismissed\" });\n emit();\n },\n },\n };\n return controller;\n};\n","/** Rage clicks without the DOM, so the web SDK and the apps (taps) count them the same. */\n\n/**\n * Three or more clicks within one second on the same spot (30 pixels) are a rage click. `push` answers true once per\n * burst, on the third click.\n */\nexport class RageDetector {\n private clicks: { x: number; y: number; t: number }[] = [];\n private fired = false;\n constructor(\n private readonly windowMs = 1000,\n private readonly radius = 30,\n private readonly count = 3,\n ) {}\n push(x: number, y: number, t: number) {\n const near = this.clicks.filter((c) => t - c.t <= this.windowMs && Math.hypot(c.x - x, c.y - y) <= this.radius);\n if (near.length !== this.clicks.length) this.fired = false;\n this.clicks = [...near, { x, y, t }];\n if (this.clicks.length >= this.count && !this.fired) {\n this.fired = true;\n return true;\n }\n return false;\n }\n}\n","/**\n * Session recordings in apps: about once a second, while the app is open and the screen changed, a small JPEG of the\n * screen (react-native-view-shot's `captureScreen`, an optional peer), sent in chunks to `/api/sdk/replay` as\n * `enc: \"frames\"` with the screens, taps, rage taps and errors as marks. MRRocket plays them in Sessions.\n *\n * It records only with the person's own replay consent (`replay` on the provider, `setReplay(true)`), never while the\n * consent is off, and only while the product's recordings are on. Privacy on the device: no frame while the keyboard is\n * open (what someone types is never on a frame), and every view wrapped in `<MRRocketMask>` goes as a rectangle that the\n * server paints black before it stores the frame (src/server/replay/frames.ts in the app).\n *\n * Like the web: a session in the product's sample rate uploads from its start; any other keeps the last minute in\n * memory and uploads it when a rage tap or an error happens (then keeps recording). At most 30 minutes per recording.\n */\nimport type { AppContext, ReplayConfig } from \"../core\";\n\nexport interface Frame {\n t: number;\n w: number;\n h: number;\n img: string;\n /** Masked areas in the frame's pixels: [x, y, w, h]. */\n masks: [number, number, number, number][];\n}\n\nexport interface Mark {\n t: number;\n kind: \"pageview\" | \"click\" | \"rage\" | \"error\";\n path: string;\n label?: string;\n x?: number;\n y?: number;\n vw?: number;\n}\n\nexport interface RecorderDeps {\n now: () => number;\n setInterval: (fn: () => void, ms: number) => unknown;\n clearInterval: (id: unknown) => void;\n /** The screen as a JPEG of about `width` pixels wide, base64, or null (no view-shot, or it failed). */\n capture: (width: number) => Promise<{ img: string; w: number; h: number } | null>;\n keyboardOpen: () => boolean;\n /** The masked views' rectangles in screen points; null when one could not be measured (the frame is then skipped). */\n masks: () => Promise<[number, number, number, number][] | null>;\n /** The screen size in points. */\n screen: () => { w: number; h: number } | undefined;\n send: (body: string) => Promise<number>;\n}\n\nexport interface RecorderState {\n /** May record now: the person's replay consent, tracking on, a key. */\n allowed: () => boolean;\n config: () => ReplayConfig | undefined;\n session: () => string;\n who: () => { distinctId?: string; identified: boolean };\n apiKey: string;\n app: AppContext;\n}\n\nconst FRAME_MS = 1000;\nconst WIDTH = 360;\nconst BUFFER_MS = 60_000;\nconst CHUNK_FRAMES = 12;\nconst CHUNK_CHARS = 700_000;\nconst MAX_MS = 30 * 60_000;\n\n/** A stable share in [0, 1) for a session, so its sample decision holds for the whole session. */\nconst shareOf = (s: string) => {\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) h = Math.imul(h ^ s.charCodeAt(i), 16777619);\n return (h >>> 0) / 4294967296;\n};\n\nexport const createRecorder = (deps: RecorderDeps, st: RecorderState) => {\n let timer: unknown = null;\n let busy = false;\n let last = \"\";\n // The current recording: its session, start, next chunk, and whether it uploads (else it buffers).\n let rec: { session: string; start: number; seq: number; uploading: boolean; trigger: string; stopped: boolean } | null = null;\n let frames: Frame[] = [];\n let marks: Mark[] = [];\n\n const ensure = () => {\n const session = st.session();\n const cfg = st.config();\n if (!rec || rec.session !== session) {\n frames = [];\n marks = [];\n last = \"\";\n const sampled = !!cfg && shareOf(session) < (cfg.sampleRate ?? 0.1);\n rec = { session, start: deps.now(), seq: 0, uploading: sampled, trigger: \"sample\", stopped: false };\n }\n return rec;\n };\n\n const send = async (r: NonNullable<typeof rec>) => {\n if (!frames.length || r.stopped) return;\n const batch = frames.splice(0, frames.length);\n const ms = marks.splice(0, marks.length);\n const size = deps.screen();\n const { distinctId, identified } = st.who();\n const body = JSON.stringify({\n key: st.apiKey,\n consent: { replay: true },\n sessionId: r.session,\n start: r.start,\n seq: r.seq++,\n enc: \"frames\",\n data: JSON.stringify(batch),\n meta: { first: batch[0].t, last: batch[batch.length - 1].t, vw: size ? Math.round(size.w) : null, vh: size ? Math.round(size.h) : null, marks: ms },\n distinctId,\n identified,\n trigger: r.trigger,\n app: st.app,\n });\n const status = await deps.send(body);\n // Refused for good (no consent on the server's side, recordings off, too long or too big): stop this recording.\n if (status === 403 || status === 409 || status === 413) r.stopped = true;\n };\n\n const tick = async () => {\n if (busy || !st.allowed() || !st.config()) return;\n const r = ensure();\n if (r.stopped || deps.now() - r.start > MAX_MS) return;\n // Typing is never recorded: no frame while the keyboard is up.\n if (deps.keyboardOpen()) return;\n busy = true;\n try {\n const shot = await deps.capture(WIDTH);\n if (!shot || shot.img === last) return;\n last = shot.img;\n const size = deps.screen();\n const scale = size && size.w ? shot.w / size.w : 1;\n const measured = await deps.masks();\n // A masked view that could not be measured: no frame at all rather than one without its mask.\n if (measured === null) {\n last = \"\";\n return;\n }\n const masks = measured.map(([x, y, w, h]) => [x * scale, y * scale, w * scale, h * scale].map(Math.round) as Frame[\"masks\"][number]);\n frames.push({ t: deps.now(), w: shot.w, h: shot.h, img: shot.img, masks });\n if (!r.uploading) {\n // Buffering: only the last minute stays.\n const since = deps.now() - BUFFER_MS;\n frames = frames.filter((f) => f.t >= since);\n marks = marks.filter((m) => m.t >= since);\n return;\n }\n const chars = frames.reduce((a, f) => a + f.img.length, 0);\n if (frames.length >= CHUNK_FRAMES || chars >= CHUNK_CHARS) await send(r);\n } catch {\n // A failed frame is skipped; recording must never disturb the app.\n } finally {\n busy = false;\n }\n };\n\n return {\n /** Starts or stops the frame loop to match the app state (active) and whether recording is allowed. */\n sync(active: boolean) {\n const on = active && st.allowed() && !!st.config();\n if (on && timer === null) timer = deps.setInterval(() => void tick(), FRAME_MS);\n if (!on && timer !== null) {\n deps.clearInterval(timer);\n timer = null;\n if (rec?.uploading) void send(rec);\n }\n },\n /** A screen, tap, rage tap or error, for the timeline. */\n mark(m: Omit<Mark, \"t\">) {\n if (!st.allowed() || !st.config()) return;\n ensure();\n marks.push({ t: deps.now(), ...m });\n if (marks.length > 300) marks.splice(0, marks.length - 300);\n },\n /** A rage tap or an error: a buffering recording uploads its last minute and keeps recording. */\n trigger(kind: \"rage\" | \"error\") {\n if (!rec || rec.uploading || rec.stopped || !st.allowed()) return;\n rec.uploading = true;\n rec.trigger = kind;\n void send(rec);\n },\n /** Sends what waits (going to the background). */\n flush() {\n if (rec?.uploading) return send(rec);\n return Promise.resolve();\n },\n /** Consent withdrawn: forget everything not sent. */\n drop() {\n frames = [];\n marks = [];\n rec = null;\n last = \"\";\n },\n /** For tests: one frame now. */\n tick,\n };\n};\n\nexport type Recorder = ReturnType<typeof createRecorder>;\n\n// ---------- Masked views ----------\n\nexport interface Measurable {\n measureInWindow(cb: (x: number, y: number, w: number, h: number) => void): void;\n}\n\n/** The views wrapped in `<MRRocketMask>` that are on screen now. */\nexport const maskedViews = new Set<{ current: Measurable | null }>();\n\n/** Their rectangles in screen points; null when one did not answer within 100 ms (that frame is not taken). */\nexport const measureMasks = (): Promise<[number, number, number, number][] | null> =>\n Promise.all(\n [...maskedViews].map(\n (ref) =>\n new Promise<[number, number, number, number] | \"none\" | \"failed\">((resolve) => {\n const v = ref.current;\n // Not mounted (yet or any more): nothing on screen to hide.\n if (!v) return resolve(\"none\");\n const t = setTimeout(() => resolve(\"failed\"), 100);\n try {\n v.measureInWindow((x, y, w, h) => {\n clearTimeout(t);\n resolve(w > 0 && h > 0 ? [x, y, w, h] : \"none\");\n });\n } catch {\n clearTimeout(t);\n resolve(\"failed\");\n }\n }),\n ),\n ).then((rs) => (rs.includes(\"failed\") ? null : rs.filter((r): r is [number, number, number, number] => Array.isArray(r))));\n","/**\n * Affiliate referrals, after Rewardful's and Dub's client scripts. A partner's tracked link (`<mrrocket>/r/<code>`)\n * counts the click on MRRocket and sends the visitor to your site with `?mrr_ref=<code>&mrr_click=<clickId>`; a direct\n * link is `https://your.site/?ref=<code>`. The provider reads either on page load, keeps the referral for the program's\n * cookie days in a FIRST-PARTY cookie on your domain (`mrr_ref`) plus localStorage, and sends a click beacon for direct\n * links. MRRocket never sets a cookie for you: its domain is not yours.\n *\n * Storage follows consent (see the README): with `attribution=\"consent\"` (default) the referral is only stored when\n * the provider's consent is \"cookies\"; otherwise it lives in memory for the page load. `attribution=\"always\"` stores\n * it whatever the consent (your legal call), `\"off\"` ignores referrals.\n *\n * Plain functions, no React: `getReferral()` and `referralForCheckout()` work in any client code, and on the server\n * with the cookie's value (`readReferralCookie`).\n */\n\nexport interface Referral {\n /** The partner's code. */\n code: string;\n /** The click MRRocket counted (tracked link or beacon); null when it was not counted. */\n clickId: string | null;\n /** When the visitor arrived through the partner, ms. */\n at: number;\n}\n\n/** What to pass to Stripe Checkout (`stripe.checkout.sessions.create({ ..., ...referralForCheckout() })`). */\nexport interface CheckoutReferral {\n client_reference_id: string;\n metadata: { mrr_ref: string; mrr_click: string };\n}\n\nexport type AttributionMode = \"consent\" | \"always\" | \"off\";\n\nexport const REFERRAL_COOKIE = \"mrr_ref\";\nexport const REFERRAL_STORAGE_KEY = \"mrr_ref\";\nexport const REF_PARAM = \"mrr_ref\";\nexport const CLICK_PARAM = \"mrr_click\";\nexport const DEFAULT_REFERRAL_DAYS = 60;\n\nconst CODE = /^[A-Za-z0-9_-]{1,64}$/;\nconst DAY_MS = 86_400_000;\n\n/** The referral in the landing URL: the tracked link's markers first, else the direct-link parameter (`ref`). */\nexport const readReferralParams = (search: string, param = \"ref\"): { code: string; clickId: string | null; direct: boolean } | null => {\n const q = new URLSearchParams(search);\n return referralFrom((k) => q.get(k), param);\n};\n\n/** The same from a parameter lookup, for runtimes without `URLSearchParams` (React Native deep links). */\nexport const referralFrom = (get: (name: string) => string | null | undefined, param = \"ref\"): { code: string; clickId: string | null; direct: boolean } | null => {\n const marked = get(REF_PARAM);\n if (marked && CODE.test(marked)) {\n const click = get(CLICK_PARAM);\n return { code: marked, clickId: click && CODE.test(click) ? click : null, direct: false };\n }\n const direct = get(param);\n return direct && CODE.test(direct) ? { code: direct, clickId: null, direct: true } : null;\n};\n\n/** `code.clickId.at`: dots never occur in a code or a click id. */\nexport const encodeReferral = (r: Referral) => `${r.code}.${r.clickId ?? \"\"}.${r.at}`;\n\n/** A stored referral, or null when it is malformed or older than `maxDays`. */\nexport const decodeReferral = (value: string | null | undefined, maxDays = DEFAULT_REFERRAL_DAYS, now = Date.now()): Referral | null => {\n if (!value) return null;\n const [code, click, at] = value.split(\".\");\n const t = Number(at);\n if (!code || !CODE.test(code) || !Number.isFinite(t) || (click && !CODE.test(click))) return null;\n if (now - t > maxDays * DAY_MS || t > now + DAY_MS) return null;\n return { code, clickId: click || null, at: t };\n};\n\n/** The referral for a Stripe Checkout Session: `client_reference_id` and `metadata`. Null without a referral. */\nexport const referralForCheckout = (r: Referral | null = getReferral()): CheckoutReferral | null =>\n r ? { client_reference_id: `mrr_ref:${r.code}:${r.clickId ?? \"\"}`, metadata: { mrr_ref: r.code, mrr_click: r.clickId ?? \"\" } } : null;\n\n/**\n * A Stripe Payment Link (or Pricing Table URL) with the referral as `client_reference_id`. Payment Links only accept\n * letters, digits, `-` and `_` there, so the form is `mrr_ref__<code>__<clickId>`. Without a referral the URL is unchanged.\n */\nexport const referralLink = (url: string, r: Referral | null = getReferral()) => {\n if (!r) return url;\n try {\n const u = new URL(url);\n u.searchParams.set(\"client_reference_id\", `mrr_ref__${r.code}__${r.clickId ?? \"\"}`);\n return u.toString();\n } catch {\n return url;\n }\n};\n\n// ---------- The browser side ----------\n\nlet current: Referral | null = null;\n\nconst hasDocument = () => typeof document !== \"undefined\";\n\nconst readCookie = (name: string) => {\n if (!hasDocument()) return undefined;\n const raw = document.cookie\n .split(\"; \")\n .find((c) => c.startsWith(`${name}=`))\n ?.slice(name.length + 1);\n try {\n return raw ? decodeURIComponent(raw) : undefined;\n } catch {\n return raw;\n }\n};\n\nconst storage = () => {\n try {\n return typeof localStorage === \"undefined\" ? null : localStorage;\n } catch {\n return null;\n }\n};\n\n/** The visitor's referral: this page load's, else the stored one. Null on the server (use `readReferralCookie` there). */\nexport const getReferral = (): Referral | null => {\n if (current) return current;\n if (!hasDocument()) return null;\n return decodeReferral(readCookie(REFERRAL_COOKIE), 3650) ?? decodeReferral(storage()?.getItem(REFERRAL_STORAGE_KEY), 3650);\n};\n\n/** The referral from the `mrr_ref` cookie's value, for server code (a route that creates the Checkout Session). */\nexport const readReferralCookie = (value: string | null | undefined) => decodeReferral(value, 3650);\n\n/** Writes the referral to the first-party cookie and localStorage for `days`. */\nexport const storeReferral = (r: Referral, days: number) => {\n if (!hasDocument()) return;\n const maxAge = Math.max(1, Math.round(days)) * 86_400;\n const secure = typeof location !== \"undefined\" && location.protocol === \"https:\" ? \"; secure\" : \"\";\n document.cookie = `${REFERRAL_COOKIE}=${encodeURIComponent(encodeReferral(r))}; path=/; max-age=${maxAge}; samesite=lax${secure}`;\n try {\n storage()?.setItem(REFERRAL_STORAGE_KEY, encodeReferral(r));\n } catch {\n // Storage full or blocked: the cookie is enough.\n }\n};\n\n/** Deletes what was stored (consent withdrawn); the referral of this page load stays in memory. */\nexport const forgetStoredReferral = () => {\n if (!hasDocument()) return;\n document.cookie = `${REFERRAL_COOKIE}=; path=/; max-age=0; samesite=lax`;\n try {\n storage()?.removeItem(REFERRAL_STORAGE_KEY);\n } catch {\n // Nothing stored.\n }\n};\n\n/** For tests and `consent=\"off\"`: forget the page load's referral too. */\nexport const resetReferral = () => {\n current = null;\n};\n\nexport interface CaptureOptions {\n /** `location.search` of the landing page. */\n search: string;\n /** The direct-link parameter, default `ref`. */\n param?: string;\n /** May the referral be stored (consent)? */\n store: boolean;\n /** Days to keep it. */\n days: number;\n /** Sends the click beacon; answers the click id MRRocket counted (or confirmed). */\n beacon?: (body: { code: string; clickId: string | null }) => Promise<string | null>;\n now?: number;\n}\n\n/**\n * Reads the referral of a page load: a new one from the URL (sent to the beacon and stored when allowed) or the stored\n * one. A new link replaces an older referral (last click within the window wins). Returns the referral in effect.\n */\nexport const captureReferral = async (o: CaptureOptions): Promise<Referral | null> => {\n const found = readReferralParams(o.search, o.param);\n const now = o.now ?? Date.now();\n if (!found) {\n if (!current && o.store) {\n current = decodeReferral(readCookie(REFERRAL_COOKIE), o.days, now) ?? decodeReferral(storage()?.getItem(REFERRAL_STORAGE_KEY), o.days, now);\n if (!current) forgetStoredReferral();\n }\n return current;\n }\n current = { code: found.code, clickId: found.clickId, at: now };\n if (o.store) storeReferral(current, o.days);\n if (o.beacon) {\n try {\n const id = await o.beacon({ code: found.code, clickId: found.clickId });\n if (id && current && current.code === found.code && !current.clickId) {\n current = { ...current, clickId: id };\n if (o.store) storeReferral(current, o.days);\n }\n } catch {\n // The referral still counts for checkout without a click id.\n }\n }\n return current;\n};\n\n/** Events that carry the referral: identify, signup and your own events (not page views or exposures). */\nexport const carriesReferral = (event: string) => event === \"$identify\" || !event.startsWith(\"$\");\n","/**\n * The React Native client without React: the event queue (batched, persisted for offline use, retried with backoff),\n * the app lifecycle (`$app_open`, `$app_background`, a new session after 30 minutes away), screens, identity and\n * consent, the cached config for flags and experiments, install attribution from the first open's deep link, and error\n * capture. Everything the platform gives (storage, AppState, ErrorUtils, device info, fetch) comes in as `deps`, so\n * it runs in tests without React Native; `platform.ts` builds the real ones.\n */\nimport { type Api, createApi } from \"../api-client\";\nimport { type SdkInfo, batchRequests } from \"../batch\";\nimport {\n type AppContext,\n type CockpitConfig,\n type CockpitEvent,\n type ErrorReport,\n SDK_VERSION,\n SESSION_TIMEOUT_MS,\n type UtmKey,\n type VariantId,\n experimentsOfText,\n flagFor,\n newDistinctId,\n parseQuery,\n resolveVariant,\n textChanges,\n utmFrom,\n} from \"../core\";\nimport { describeError } from \"../errors\";\nimport { type CancelFlowOptions, type CancelFlowResult, type FlowsController, type InAppState, createFlows } from \"../flows\";\nimport { RageDetector } from \"../rage\";\nimport { type Recorder, type RecorderDeps, createRecorder } from \"./recorder\";\nimport { carriesReferral, referralFrom } from \"../referral\";\n\n/**\n * What the app may send and store.\n * - \"anonymous\" (default): no id is stored on the device. Events go without a person id until `identify()` (MRRocket\n * counts visitors by its daily hash); flags and experiments use a random id that lives until the app is closed.\n * - \"persistent\": a random install id is stored on the device (removed with the app) and sent with every event.\n * - \"off\": nothing is sent, and what the SDK stored is deleted.\n */\nexport type NativeConsent = \"anonymous\" | \"persistent\" | \"off\";\n\nexport interface MRRocketOptions {\n /** The product's public key (MRRocket › Settings › Products), the same as on the website. */\n apiKey: string;\n /** Where MRRocket runs. Default `https://app.mrrocket.dev`. */\n host?: string;\n /** Default \"anonymous\". The SDK does not remember it: pass it on every start (from your consent screen's stored answer). */\n consent?: NativeConsent;\n /** Uncaught JavaScript errors and `captureError` go to Build › Errors (default true). */\n errors?: boolean;\n /** Your release, for Build › Errors. Default: the app version and build, like \"1.4.0 (42)\". */\n release?: string;\n /** `$app_open` and `$app_background` events (default true). */\n lifecycle?: boolean;\n /** Read UTM and referral parameters of the deep link that opened the app the first time, sent with `$install` (default true). */\n attribution?: boolean;\n /** How often the queue is sent while the app is open, in ms (default 10 000). It is also sent when the app goes to the background. */\n flushIntervalMs?: number;\n /** At most this many events wait on the device; the oldest go first (default 1,000). */\n maxQueue?: number;\n /** Log what the SDK does to the console. */\n debug?: boolean;\n /** Onboarding flows start on their own when the person does their trigger (default true). False: only `startOnboarding()`. */\n onboarding?: boolean;\n /** Taps go to Heatmaps as clicks on the screen they happened on (default true; `MRRocketProvider` captures them). */\n heatmaps?: boolean;\n /**\n * The person agreed to session recordings (default false; ask them first). Needs `react-native-view-shot` and the\n * product's recordings switched on in MRRocket. No frame while the keyboard is open; wrap private views in\n * `<MRRocketMask>`. Change it later with `setReplay`.\n */\n replay?: boolean;\n}\n\n/** AsyncStorage's shape. */\nexport interface KeyValueStorage {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n/** React Native's AppState. */\nexport interface AppStateLike {\n currentState?: string | null;\n addEventListener(type: \"change\", listener: (state: string) => void): { remove(): void } | undefined;\n}\n\n/** React Native's global ErrorUtils. */\nexport interface ErrorUtilsLike {\n getGlobalHandler(): ((error: unknown, isFatal?: boolean) => void) | undefined;\n setGlobalHandler(handler: (error: unknown, isFatal?: boolean) => void): void;\n}\n\nexport type FetchLike = (\n url: string,\n init: { method?: string; headers?: Record<string, string>; body?: string; signal?: AbortSignal },\n) => Promise<{ ok: boolean; status: number; json(): Promise<unknown> }>;\n\nexport interface NativeDeps {\n /** Null: everything stays in memory (no offline queue, no install attribution). */\n storage: KeyValueStorage | null;\n fetch: FetchLike;\n appState: AppStateLike | null;\n errorUtils: ErrorUtilsLike | null;\n /** The app and device, read once at start. */\n context: () => AppContext;\n /** The app's id (bundle id), for the `app://<id>/<screen>` address of events. */\n appId?: string;\n /** The screen size in points. */\n screen?: () => { w: number; h: number } | undefined;\n /** The deep link that opened the app (`Linking.getInitialURL`). */\n initialUrl?: () => Promise<string | null>;\n /** Opens an in-app message's link (`Linking.openURL`). */\n openUrl?: (url: string) => void;\n /** Push notifications through `expo-notifications`, when the app has it installed. */\n push?: PushDeps | null;\n /** Screen frames for session recordings, when the app has `react-native-view-shot` (platform.ts). */\n recorder?: Pick<RecorderDeps, \"capture\" | \"keyboardOpen\" | \"masks\"> | null;\n now?: () => number;\n setInterval?: (fn: () => void, ms: number) => unknown;\n clearInterval?: (id: unknown) => void;\n setTimeout?: (fn: () => void, ms: number) => unknown;\n clearTimeout?: (id: unknown) => void;\n log?: (message: string) => void;\n}\n\n/** What a journey's push step carries in the notification's data, so an open is counted on the step. */\nexport interface PushData {\n mrrocket?: { id?: string; url?: string };\n}\n\n/** What `registerForPush` needs of `expo-notifications` (platform.ts wraps it; tests pass a fake). */\nexport interface PushDeps {\n /** The permission now, after asking when `ask` and it was not decided yet. */\n permission(ask: boolean): Promise<\"granted\" | \"denied\" | \"undetermined\">;\n /** The Expo push token (`ExponentPushToken[…]`), or null when the device has none (a simulator). */\n token(projectId?: string): Promise<string | null>;\n /** Calls `listener` with the data of every notification the person opens; returns the unsubscribe. */\n onOpen(listener: (data: PushData) => void): () => void;\n /** The notification that opened the app from a cold start, if any. */\n lastOpen?(): Promise<PushData | null>;\n}\n\nexport interface RegisterForPushOptions {\n /** Ask for the permission when it was not decided yet (default true). False: only register when already allowed. */\n ask?: boolean;\n /** Your EAS project id; default: the one in your app config (`expo-constants`). */\n projectId?: string;\n}\n\nexport type NativePushStatus = \"registered\" | \"denied\" | \"not-asked\" | \"unavailable\" | \"not-signed-in\" | \"error\";\n\nexport interface NativePushResult {\n status: NativePushStatus;\n /** The Expo push token, once registered. */\n token?: string;\n /** Why it is unavailable or failed. */\n reason?: string;\n}\n\n/** What the app (and the React hooks) use. */\nexport interface MRRocketClient {\n track(event: string, props?: Record<string, unknown>): void;\n /** A screen view: a route name (\"Settings\") or an Expo Router path (\"/settings\"). */\n screen(name: string, props?: Record<string, unknown>): void;\n /** A tap at screen points (x, y) for Heatmaps, on the current screen; `MRRocketProvider` calls it. */\n tap(x: number, y: number): void;\n /** The person's answer to session recordings (`replay` in the options); false stops and forgets what was not sent. */\n setReplay(on: boolean): void;\n identify(id: string, props?: Record<string, unknown>): void;\n /** Forgets the signed-in person (sign-out): a new anonymous id and a new session. */\n reset(): void;\n setConsent(consent: NativeConsent): void;\n captureError(error: unknown): void;\n getFlag(key: string): boolean;\n getFlagVariant(key: string): string | null;\n /** The variant of an experiment (\"control\" until the config is known); records the exposure once per screen. */\n getVariant(key: string): VariantId;\n /** The variant without recording anything (render code); pair it with `expose`. */\n peekVariant(key: string): VariantId;\n /** Records that the person saw `variant` of `key`, once per screen. */\n expose(key: string, variant: VariantId): void;\n /**\n * The copy for text `id` as published in MRRocket (a paywall's `paywall.<placement>.headline`, an onboarding title …)\n * with this person's experiment variant applied on top, the same rules as `<Text id>` on the web; `fallback` (your\n * own words) while nothing is published or the config is unknown. Records the exposure to every test that changes\n * `id`, once per screen.\n */\n getText(id: string, fallback: string): string;\n /** The text without recording anything (render code); undefined when MRRocket has none. Pair it with `exposeText`. */\n peekText(id: string): string | undefined;\n /** Records that the person saw text `id`: an exposure to each test that changes it, once per screen. */\n exposeText(id: string): void;\n /**\n * Shows the cancel flow built in MRRocket › Churn (drawn by `<MRRocketProvider>`), resolves with what the customer\n * did. MRRocket never changes the subscription: your `onCancel` and `onSave` do.\n */\n openCancelFlow(options?: CancelFlowOptions): Promise<CancelFlowResult>;\n /** Starts an onboarding flow now (the first live one without an id). False when there is none. */\n startOnboarding(id?: string): boolean;\n /**\n * Push notifications from your Lifecycle journeys for the signed-in person (call `identify` first). Asks the\n * permission (unless `ask: false`), gets the Expo push token and sends it to MRRocket. Needs `expo-notifications`.\n * Safe to call on every start: an existing token is sent again without asking. Opens of MRRocket's notifications\n * are counted from then on.\n */\n registerForPush(options?: RegisterForPushOptions): Promise<NativePushResult>;\n /** Removes this device's token for the signed-in person (sign-out does it on its own in `reset`). */\n unregisterForPush(): Promise<boolean>;\n /** The cancel flow, onboarding and messages for a renderer (the provider's, or your own). */\n flows: FlowsController;\n /** Sends what is queued now. */\n flush(): Promise<void>;\n /** Resolves once stored state and the config (cached or fetched) are known. */\n ready: Promise<void>;\n isReady(): boolean;\n getDistinctId(): string;\n getConsent(): NativeConsent;\n /**\n * The client of the SDK's widget API (surveys, feedback, the messenger) for the person now: their id, and the name and\n * email given to identify (or `as`, typed into a widget). Null while the consent is off or without a key.\n */\n api(as?: { name?: string; email?: string }): Api | null;\n /** The signed-in person (identify): their id, and the name and email given there. Undefined before identify. */\n getUser(): { id: string; name?: string; email?: string } | undefined;\n /** Surveys answered or closed on this device: not shown again (kept on the device only with \"persistent\"). */\n isSurveyDone(id: string): boolean;\n markSurveyDone(id: string): void;\n getConfig(): CockpitConfig | null;\n /** For React: called after every change flags, variants or the consent depend on. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void;\n /** Grows with every such change (useSyncExternalStore's snapshot). */\n getVersion(): number;\n /** Stops timers and listeners and sends what is queued (tests, or an app that tears the SDK down). */\n close(): Promise<void>;\n /** For tests: what waits to be sent. */\n queued(): readonly CockpitEvent[];\n}\n\nexport const DEFAULT_HOST = \"https://app.mrrocket.dev\";\n/** Storage keys. */\nexport const KEYS = {\n id: \"mrrocket:id\",\n queue: \"mrrocket:queue\",\n config: \"mrrocket:config\",\n installed: \"mrrocket:installed\",\n referral: \"mrrocket:referral\",\n surveys: \"mrrocket:surveys\",\n} as const;\n\nconst MAX_ERRORS = 20;\nconst MAX_CRUMBS = 20;\nconst MAX_BACKOFF_MS = 5 * 60 * 1000;\nconst REQUEST_TIMEOUT_MS = 15_000;\n/** A batch is sent early once this many events wait. */\nconst EAGER_COUNT = 20;\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}…` : s);\n\nexport const createClient = (options: MRRocketOptions, deps: NativeDeps): MRRocketClient => {\n const apiKey = (options.apiKey ?? \"\").trim();\n const host = (options.host ?? DEFAULT_HOST).trim().replace(/\\/+$/, \"\");\n const now = deps.now ?? (() => Date.now());\n const setIntervalFn = deps.setInterval ?? ((fn, ms) => setInterval(fn, ms));\n const clearIntervalFn = deps.clearInterval ?? ((id) => clearInterval(id as ReturnType<typeof setInterval>));\n const setTimeoutFn = deps.setTimeout ?? ((fn, ms) => setTimeout(fn, ms));\n const clearTimeoutFn = deps.clearTimeout ?? ((id) => clearTimeout(id as ReturnType<typeof setTimeout>));\n const flushEvery = Math.max(1000, options.flushIntervalMs ?? 10_000);\n const maxQueue = Math.max(10, options.maxQueue ?? 1000);\n const errorsOn = options.errors !== false;\n const storage = deps.storage;\n\n const warned = new Set<string>();\n const warn = (message: string) => {\n if (warned.has(message)) return;\n warned.add(message);\n (deps.log ?? ((m: string) => console.warn(m)))(`[MRRocket] ${message}`);\n };\n const debug = (message: string) => {\n if (options.debug) (deps.log ?? ((m: string) => console.log(m)))(`[MRRocket] ${message}`);\n };\n if (!apiKey) warn(\"No public key. Pass apiKey to MRRocketProvider; nothing is sent until then.\");\n\n let context: AppContext = { platform: \"unknown\" };\n try {\n context = deps.context();\n } catch {\n // Device details are optional.\n }\n const appId = (deps.appId || \"app\").replace(/[^A-Za-z0-9._-]/g, \"\") || \"app\";\n const release = options.release ?? (context.appVersion ? `${context.appVersion}${context.build ? ` (${context.build})` : \"\"}` : undefined);\n const sdk: SdkInfo = { v: SDK_VERSION, errors: errorsOn, platform: context.platform };\n\n let consent: NativeConsent = options.consent ?? \"anonymous\";\n let installId: string | null = null;\n let memoryId = newDistinctId();\n let identified: string | undefined;\n let person: Record<string, unknown> | undefined;\n let config: CockpitConfig | null = null;\n let queue: CockpitEvent[] = [];\n let session: { id: string; last: number } | null = null;\n // The first open's campaign rides on the events of its session only.\n let utm: { session: string; values: Partial<Record<UtmKey, string>> } | null = null;\n let referral: { code: string; clickId: string | null } | null = null;\n let currentScreen: string | undefined;\n let loaded = false;\n let closed = false;\n let isReady = false;\n let version = 0;\n let failures = 0;\n let backoffUntil = 0;\n let inFlight: Promise<void> | null = null;\n let persistTimer: unknown = null;\n let flushTimer: unknown = null;\n let errorTimer: unknown = null;\n let appState = deps.appState?.currentState ?? \"active\";\n let backgroundSince: number | null = null;\n const early: (() => void)[] = [];\n const exposed = new Set<string>();\n const surveysDone = new Set<string>();\n const rage = new RageDetector();\n // The texts for this config and person, recomputed only when either changes.\n let textsFor: { config: CockpitConfig | null; id: string; texts: Record<string, string> } | null = null;\n const texts = () => {\n const id = distinctId();\n if (!textsFor || textsFor.config !== config || textsFor.id !== id) textsFor = { config, id, texts: textChanges(config, id, {}) };\n return textsFor.texts;\n };\n const listeners = new Set<() => void>();\n const crumbs: NonNullable<ErrorReport[\"crumbs\"]> = [];\n const errorQueue: ErrorReport[] = [];\n const errorsSeen = new Set<string>();\n let errorsSent = 0;\n\n // The cancel flow, onboarding and in-app messages (../flows.ts); `<MRRocketProvider>` draws them.\n const flows = createFlows({\n track: (event, props) => record(event, props),\n personId: () => (consent !== \"off\" ? identified : undefined),\n auto: options.onboarding !== false,\n storage: () =>\n storage && consent === \"persistent\"\n ? {\n get: (k: string) => get(k),\n set: (k: string, v: string) => void set(k, v),\n }\n : null,\n openUrl: deps.openUrl,\n fetchInApp: async (id) => {\n if (!apiKey) return null;\n const r = await deps.fetch(`${host}/api/sdk/inapp?key=${encodeURIComponent(apiKey)}&distinctId=${encodeURIComponent(id)}`, { method: \"GET\" });\n return r.ok ? ((await r.json()) as InAppState) : null;\n },\n });\n const refreshFlows = () => {\n if (!isReady || closed) return;\n flows.setConfig(config);\n void flows.refresh();\n };\n\n // Created below once sending is defined; `changed` keeps its frame loop in step with consent and config.\n let recorder: Recorder | null = null;\n const changed = () => {\n version++;\n recorder?.sync(appState === \"active\");\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // A listener must not stop the others.\n }\n }\n };\n\n const crumb = (type: \"navigation\" | \"click\" | \"lifecycle\", message: string) => {\n crumbs.push({ ts: now(), type, message: clip(message, 120) });\n if (crumbs.length > MAX_CRUMBS) crumbs.shift();\n };\n\n // ---------- Storage (every call may fail: storage full, native module missing) ----------\n\n const get = async (key: string) => {\n if (!storage) return null;\n try {\n return await storage.getItem(key);\n } catch {\n return null;\n }\n };\n const set = async (key: string, value: string) => {\n if (!storage) return;\n try {\n await storage.setItem(key, value);\n } catch {\n warn(\"Could not write to the device storage; events wait in memory only.\");\n }\n };\n const remove = async (key: string) => {\n if (!storage) return;\n try {\n await storage.removeItem(key);\n } catch {\n // Nothing stored.\n }\n };\n\n const persistQueue = async () => {\n if (persistTimer !== null) {\n clearTimeoutFn(persistTimer);\n persistTimer = null;\n }\n if (!storage || consent === \"off\") return;\n if (queue.length) await set(KEYS.queue, JSON.stringify(queue));\n else await remove(KEYS.queue);\n };\n const schedulePersist = () => {\n if (!storage || persistTimer !== null) return;\n persistTimer = setTimeoutFn(() => {\n persistTimer = null;\n void persistQueue();\n }, 1000);\n };\n\n // ---------- Identity and session ----------\n\n const distinctId = () => identified ?? (consent === \"persistent\" && installId ? installId : memoryId);\n // Without the persistent id, events carry an id only after identify(); the server counts everyone else by its daily hash.\n const sendId = () => (consent === \"persistent\" ? distinctId() : identified);\n\n const touchSession = () => {\n const t = now();\n if (!session || t - session.last >= SESSION_TIMEOUT_MS) session = { id: newDistinctId(), last: t };\n else session.last = t;\n return session.id;\n };\n\n const urlOf = (path = currentScreen) => `app://${appId}${path ?? \"/\"}`;\n\n // ---------- Recording ----------\n\n const record = (event: string, props?: Record<string, unknown>, ts = now()) => {\n if (closed) return;\n if (!loaded) {\n early.push(() => record(event, props, ts));\n return;\n }\n if (consent === \"off\" || !apiKey) return;\n const sessionId = touchSession();\n const ref = referral && carriesReferral(event) ? referral : null;\n const size = deps.screen?.();\n queue.push({\n event,\n props: ref ? { ...props, $referral: ref } : props,\n distinctId: sendId(),\n sessionId,\n ts,\n url: urlOf(),\n ...(utm && utm.session === sessionId ? utm.values : {}),\n ...(size ? { screen: { w: Math.round(size.w), h: Math.round(size.h) } } : {}),\n app: context,\n });\n if (queue.length > maxQueue) queue.splice(0, queue.length - maxQueue);\n schedulePersist();\n if (queue.length >= EAGER_COUNT) void flush();\n };\n\n // ---------- Sending ----------\n\n const post = async (path: string, body: string): Promise<number> => {\n const ctl = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ctl ? setTimeoutFn(() => ctl.abort(), REQUEST_TIMEOUT_MS) : null;\n try {\n const r = await deps.fetch(`${host}${path}`, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body, signal: ctl?.signal });\n return r.status;\n } catch {\n return 0;\n } finally {\n if (timer !== null) clearTimeoutFn(timer);\n }\n };\n\n const sendQueue = async () => {\n if (!queue.length || consent === \"off\" || !apiKey) return;\n if (now() < backoffUntil) return;\n const snapshot = queue.slice();\n const requests = batchRequests(apiKey, snapshot, sdk);\n const included = new Set(requests.flatMap((r) => r.events));\n const done = new Set<CockpitEvent>();\n for (const r of requests) {\n const status = await post(\"/api/sdk/events\", r.body);\n if (status >= 200 && status < 300) {\n r.events.forEach((e) => done.add(e));\n failures = 0;\n backoffUntil = 0;\n } else if (status >= 400 && status < 500 && status !== 408 && status !== 429) {\n // Will never be accepted (a wrong key, a malformed event): drop instead of retrying forever.\n r.events.forEach((e) => done.add(e));\n warn(`Events were rejected with ${status}. Check the public key (MRRocket › Settings › Products) and the host.`);\n } else {\n failures++;\n backoffUntil = now() + Math.min(MAX_BACKOFF_MS, 1000 * 2 ** failures);\n debug(`Sending failed (${status || \"offline\"}); next try in ${Math.round((backoffUntil - now()) / 1000)} s.`);\n break;\n }\n }\n // Sent, rejected, or too large to ever fit in a request: out of the queue. Newer events stay.\n queue = queue.filter((e) => !done.has(e) && (included.has(e) || !snapshot.includes(e)));\n await persistQueue();\n };\n\n // A flush asked for while one runs follows it, so events queued meanwhile go too.\n let nextFlush: Promise<void> | null = null;\n const flush = (): Promise<void> => {\n if (inFlight)\n return (nextFlush ??= inFlight.then(() => {\n nextFlush = null;\n return flush();\n }));\n inFlight = sendQueue().finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n\n const startTimer = () => {\n if (flushTimer !== null || closed) return;\n flushTimer = setIntervalFn(() => void flush(), flushEvery);\n };\n const stopTimer = () => {\n if (flushTimer === null) return;\n clearIntervalFn(flushTimer);\n flushTimer = null;\n };\n\n // ---------- Errors ----------\n\n const sendErrors = async () => {\n if (errorTimer !== null) {\n clearTimeoutFn(errorTimer);\n errorTimer = null;\n }\n while (errorQueue.length) {\n // Four full stacks stay under the server's 64 KB.\n const batch = errorQueue.splice(0, 4);\n const status = await post(\"/api/sdk/errors\", JSON.stringify({ key: apiKey, sdk, errors: batch }));\n if (status >= 400 && status < 500 && status !== 429) warn(`Error reports were rejected with ${status}. Check the public key and the host.`);\n }\n };\n\n const capture = (error: unknown, mechanism: ErrorReport[\"mechanism\"], fatal = false) => {\n if (!errorsOn || closed || consent === \"off\" || !apiKey || errorsSent >= MAX_ERRORS) return;\n const d = describeError(error);\n if (/\\/api\\/sdk\\/errors/.test(d.message)) return;\n const mark = `${d.type}:${d.message}`;\n if (errorsSeen.has(mark)) return;\n errorsSeen.add(mark);\n errorsSent++;\n const who = sendId();\n errorQueue.push({\n ...d,\n mechanism,\n handled: mechanism === \"manual\",\n url: urlOf(),\n ts: now(),\n crumbs: crumbs.slice(),\n ...(release ? { release } : {}),\n ...(who ? { distinctId: who } : {}),\n ...(session ? { sessionId: session.id } : {}),\n });\n recorder?.mark({ kind: \"error\", path: currentScreen ?? \"/\", label: clip(d.message, 120) });\n recorder?.trigger(\"error\");\n // A fatal error ends the app: send at once (it may still not make it); others wait for company.\n if (fatal) void sendErrors();\n else if (errorTimer === null) errorTimer = setTimeoutFn(() => void sendErrors(), 2000);\n };\n\n let previousHandler: ((error: unknown, isFatal?: boolean) => void) | undefined;\n let handlerInstalled = false;\n const installErrorHandler = () => {\n if (!errorsOn || !deps.errorUtils || handlerInstalled) return;\n handlerInstalled = true;\n previousHandler = deps.errorUtils.getGlobalHandler();\n deps.errorUtils.setGlobalHandler((error, isFatal) => {\n try {\n capture(error, \"onerror\", !!isFatal);\n } catch {\n // Reporting must never change how the app handles its error.\n }\n previousHandler?.(error, isFatal);\n });\n };\n\n // ---------- Session recordings ----------\n\n let replayOn = options.replay === true;\n recorder = deps.recorder\n ? createRecorder(\n {\n now,\n setInterval: setIntervalFn,\n clearInterval: clearIntervalFn,\n capture: deps.recorder.capture,\n keyboardOpen: deps.recorder.keyboardOpen,\n masks: deps.recorder.masks,\n screen: () => deps.screen?.(),\n send: (body) => post(\"/api/sdk/replay\", body),\n },\n {\n allowed: () => replayOn && loaded && !closed && consent !== \"off\" && !!apiKey,\n config: () => config?.replay,\n session: () => session?.id ?? touchSession(),\n who: () => ({ distinctId: sendId(), identified: !!identified }),\n apiKey,\n app: context,\n },\n )\n : null;\n if (options.replay && !deps.recorder) warn(\"Session recordings need react-native-view-shot: npx expo install react-native-view-shot\");\n\n // ---------- Lifecycle ----------\n\n let appStateSub: { remove(): void } | undefined;\n const onAppState = (next: string) => {\n if (closed) return;\n const prev = appState;\n appState = next;\n recorder?.sync(next === \"active\");\n if (next === \"active\" && prev !== \"active\") {\n startTimer();\n if (backgroundSince !== null) {\n // Back from the background: a new session after 30 minutes away (the session rule does it by itself).\n backgroundSince = null;\n crumb(\"lifecycle\", \"app_open\");\n if (options.lifecycle !== false) record(\"$app_open\", { cold: false });\n }\n } else if (next === \"background\" && prev !== \"background\") {\n backgroundSince = now();\n crumb(\"lifecycle\", \"app_background\");\n if (options.lifecycle !== false) record(\"$app_background\");\n stopTimer();\n void recorder?.flush();\n // The system gives a few seconds in the background: send now, and keep the rest on the device.\n void persistQueue();\n void flush();\n if (errorQueue.length) void sendErrors();\n }\n };\n\n // ---------- Config ----------\n\n const fetchConfig = async () => {\n if (!apiKey) return;\n try {\n const r = await deps.fetch(`${host}/api/sdk/config?key=${encodeURIComponent(apiKey)}`, { method: \"GET\" });\n if (!r.ok) {\n warn(`Config request answered ${r.status}. Check the public key and the host.`);\n return;\n }\n const c = (await r.json()) as CockpitConfig | null;\n if (c && Array.isArray(c.experiments)) {\n config = c;\n if (consent !== \"off\") await set(KEYS.config, JSON.stringify(c));\n changed();\n }\n } catch {\n debug(\"Config not reachable; using the cached one.\");\n }\n };\n\n // ---------- Push ----------\n\n // The token this run registered, and for whom, so sign-out (`reset`) can take it back.\n let pushToken: string | null = null;\n let pushFor: string | undefined;\n let pushOff: (() => void) | null = null;\n const opened = new Set<string>();\n\n /** A MRRocket notification the person opened: counted on its journey step, its link opened when it is a full address. */\n const onPushOpen = (data: PushData | null | undefined) => {\n const m = data?.mrrocket;\n if (!m?.id || opened.has(m.id)) return;\n opened.add(m.id);\n record(\"$push\", { action: \"opened\", message: m.id });\n if (m.url && /^[a-z][a-z0-9+.-]*:/i.test(m.url)) deps.openUrl?.(m.url);\n };\n const listenForOpens = () => {\n if (pushOff || !deps.push || closed) return;\n try {\n pushOff = deps.push.onOpen(onPushOpen);\n void deps.push\n .lastOpen?.()\n .then(onPushOpen)\n .catch(() => undefined);\n } catch {\n pushOff = null;\n }\n };\n\n const loadedNow = () =>\n loaded\n ? Promise.resolve()\n : new Promise<void>((resolve) => {\n early.push(resolve);\n });\n\n const registerForPush = async (o: RegisterForPushOptions = {}): Promise<NativePushResult> => {\n if (!deps.push) return { status: \"unavailable\", reason: \"Install expo-notifications to receive push notifications.\" };\n await loadedNow();\n if (!apiKey || consent === \"off\") return { status: \"error\", reason: !apiKey ? \"No public key.\" : \"The consent is off.\" };\n if (!identified) return { status: \"not-signed-in\" };\n const who = identified;\n try {\n const permission = await deps.push.permission(o.ask !== false);\n if (permission !== \"granted\") return { status: permission === \"denied\" ? \"denied\" : \"not-asked\" };\n const token = await deps.push.token(o.projectId);\n if (!token) return { status: \"unavailable\", reason: \"This device has no push token (a simulator, or no EAS project id).\" };\n const status = await post(\"/api/sdk/push\", JSON.stringify({ key: apiKey, distinctId: who, platform: \"expo\", token, app: context }));\n if (status < 200 || status >= 300) {\n warn(`Push registration was rejected with ${status || \"no answer\"}. Check the public key and the host.`);\n return { status: \"error\", reason: `MRRocket answered ${status || \"nothing\"}.` };\n }\n pushToken = token;\n pushFor = who;\n listenForOpens();\n debug(\"Registered for push.\");\n return { status: \"registered\", token };\n } catch (e) {\n return { status: \"error\", reason: e instanceof Error ? e.message : String(e) };\n }\n };\n\n const unregisterForPush = async () => {\n const token = pushToken;\n if (!token || !apiKey) return false;\n pushToken = null;\n const status = await post(\"/api/sdk/push\", JSON.stringify({ key: apiKey, distinctId: pushFor, platform: \"expo\", token, remove: true }));\n return status >= 200 && status < 300;\n };\n\n // ---------- Start ----------\n\n let resolveReady: () => void = () => {};\n const ready = new Promise<void>((r) => {\n resolveReady = r;\n });\n const markReady = () => {\n if (isReady) return;\n isReady = true;\n resolveReady();\n changed();\n };\n\n const start = async () => {\n let firstOpen = false;\n if (consent !== \"off\") {\n const [id, stored, cached, installed, ref, surveys] = await Promise.all([\n get(KEYS.id),\n get(KEYS.queue),\n get(KEYS.config),\n get(KEYS.installed),\n get(KEYS.referral),\n get(KEYS.surveys),\n ]);\n if (consent === \"persistent\") {\n installId = id || newDistinctId();\n if (!id) await set(KEYS.id, installId);\n } else if (id) await remove(KEYS.id);\n try {\n const old = stored ? (JSON.parse(stored) as CockpitEvent[]) : [];\n if (Array.isArray(old)) queue = [...old.filter((e) => e && typeof e.event === \"string\"), ...queue].slice(-maxQueue);\n } catch {\n await remove(KEYS.queue);\n }\n try {\n const c = cached ? (JSON.parse(cached) as CockpitConfig) : null;\n if (c && Array.isArray(c.experiments) && !config) config = c;\n } catch {\n await remove(KEYS.config);\n }\n try {\n const r = ref && consent === \"persistent\" ? (JSON.parse(ref) as { code: string; clickId: string | null }) : null;\n if (r && typeof r.code === \"string\") referral = r;\n } catch {\n // Ignore a damaged referral.\n }\n try {\n const done = surveys && consent === \"persistent\" ? (JSON.parse(surveys) as unknown) : null;\n if (Array.isArray(done)) for (const x of done) if (typeof x === \"string\") surveysDone.add(x);\n } catch {\n await remove(KEYS.surveys);\n }\n // Without storage there is no telling a first open from any other: no $install then.\n firstOpen = !!storage && !installed;\n if (firstOpen) await set(KEYS.installed, String(now()));\n } else {\n await Promise.all(Object.values(KEYS).map(remove));\n }\n if (closed) return;\n loaded = true;\n if (config) markReady();\n\n // The first open: the deep link's campaign and referral (no store data, no advertising id).\n let install: Record<string, unknown> | null = null;\n if (firstOpen) {\n install = {};\n if (options.attribution !== false && deps.initialUrl) {\n const url = await deps.initialUrl().catch(() => null);\n if (url) {\n const q = parseQuery(url);\n const values = utmFrom((k) => q[k]);\n if (Object.keys(values).length) utm = { session: touchSession(), values };\n const found = referralFrom((k) => q[k]);\n if (found) {\n referral = { code: found.code, clickId: found.clickId };\n install.$referral = referral;\n if (consent === \"persistent\") await set(KEYS.referral, JSON.stringify(referral));\n }\n install.link = clip(url.split(\"?\")[0], 300);\n }\n }\n }\n\n crumb(\"lifecycle\", \"app_open\");\n if (options.lifecycle !== false) record(\"$app_open\", { cold: true });\n if (install) record(\"$install\", install);\n for (const run of early.splice(0)) run();\n\n if (deps.appState) appStateSub = deps.appState.addEventListener(\"change\", onAppState);\n installErrorHandler();\n // Opens of MRRocket's notifications count from the first start, also the one that opened the app.\n listenForOpens();\n if (appState === \"active\" || !deps.appState) startTimer();\n if (queue.length) void flush();\n\n await fetchConfig();\n markReady();\n refreshFlows();\n };\n void start().catch(() => {\n loaded = true;\n markReady();\n });\n\n // ---------- The API ----------\n\n const client: MRRocketClient = {\n track: (event, props) => {\n if (typeof event !== \"string\" || !event) return;\n record(event, props);\n flows.onEvent(event);\n },\n tap: (x, y) => {\n if (options.heatmaps === false || consent === \"off\") return;\n const size = deps.screen?.();\n if (!size || !Number.isFinite(x) || !Number.isFinite(y)) return;\n // In the shape of the web's clicks (capture.ts): x and y in points, the screen as viewport and page.\n const props = { x: Math.round(x), y: Math.round(y), vw: Math.round(size.w), vh: Math.round(size.h), docH: Math.round(size.h), selector: \"\", label: \"\", dead: false };\n record(\"$click\", props);\n recorder?.mark({ kind: \"click\", path: currentScreen ?? \"/\", x: props.x, y: props.y, vw: props.vw });\n if (rage.push(x, y, now())) {\n record(\"$rageclick\", props);\n recorder?.mark({ kind: \"rage\", path: currentScreen ?? \"/\", x: props.x, y: props.y, vw: props.vw });\n recorder?.trigger(\"rage\");\n }\n },\n setReplay: (on) => {\n replayOn = on;\n if (!on) recorder?.drop();\n recorder?.sync(appState === \"active\");\n },\n screen: (name, props) => {\n if (typeof name !== \"string\" || !name.trim()) return;\n const path = (name.startsWith(\"/\") ? name : `/${name}`).slice(0, 300);\n if (path === currentScreen && !props) return;\n const previous = currentScreen;\n currentScreen = path;\n crumb(\"navigation\", path);\n record(\"$screen\", { ...props, path, screen: name, ...(previous ? { previous } : {}) });\n recorder?.mark({ kind: \"pageview\", path });\n },\n identify: (id, props) => {\n if (typeof id !== \"string\" || !id) return;\n if (!loaded) {\n early.push(() => client.identify(id, props));\n return;\n }\n const previous = sendId();\n identified = id;\n person = { ...props, id };\n record(\"$identify\", { ...props, id, ...(previous && previous !== id ? { previousId: previous } : {}) });\n if (consent === \"persistent\") void set(KEYS.id, id);\n changed();\n refreshFlows();\n },\n reset: () => {\n if (!loaded) {\n early.push(() => client.reset());\n return;\n }\n // Signed out: this device stops getting the person's notifications.\n if (pushToken) void unregisterForPush();\n identified = undefined;\n person = undefined;\n session = null;\n utm = null;\n exposed.clear();\n memoryId = newDistinctId();\n if (consent === \"persistent\") {\n installId = newDistinctId();\n void set(KEYS.id, installId);\n }\n changed();\n refreshFlows();\n },\n setConsent: (next) => {\n if (next !== \"anonymous\" && next !== \"persistent\" && next !== \"off\") {\n warn(`setConsent: \"${String(next)}\" is not a consent mode. Use \"anonymous\", \"persistent\" or \"off\".`);\n return;\n }\n if (!loaded) {\n early.push(() => client.setConsent(next));\n return;\n }\n if (next === consent) return;\n const before = consent;\n consent = next;\n if (next === \"off\") {\n recorder?.drop();\n queue = [];\n session = null;\n errorQueue.length = 0;\n void Promise.all(Object.values(KEYS).map(remove));\n } else if (next === \"anonymous\") {\n installId = null;\n void remove(KEYS.id);\n void remove(KEYS.referral);\n void remove(KEYS.surveys);\n } else {\n installId = identified ?? newDistinctId();\n void set(KEYS.id, installId);\n if (referral) void set(KEYS.referral, JSON.stringify(referral));\n if (surveysDone.size) void set(KEYS.surveys, JSON.stringify([...surveysDone]));\n }\n // Switching tracking on records the screen the person is on.\n if (before === \"off\" && currentScreen && loaded) record(\"$screen\", { path: currentScreen, screen: currentScreen });\n changed();\n refreshFlows();\n },\n captureError: (error) => capture(error, \"manual\"),\n getFlag: (key) => flagFor(key, config, distinctId(), { ...person }) !== false,\n getFlagVariant: (key) => {\n const v = flagFor(key, config, distinctId(), { ...person });\n return typeof v === \"string\" ? v : null;\n },\n getVariant: (key) => {\n const variant = resolveVariant(key, config, distinctId(), {});\n client.expose(key, variant);\n return variant;\n },\n peekVariant: (key) => resolveVariant(key, config, distinctId(), {}),\n expose: (key, variant) => {\n if (!config || consent === \"off\") return;\n const mark = `${currentScreen ?? \"/\"}|${key}`;\n if (exposed.has(mark)) return;\n exposed.add(mark);\n record(\"$exposure\", { experiment: key, variant });\n },\n getText: (id, fallback) => {\n client.exposeText(id);\n return client.peekText(id) ?? fallback;\n },\n peekText: (id) => texts()[id],\n exposeText: (id) => {\n // Showing a text a running test changes is an exposure to that test, whichever variant the person has.\n for (const key of experimentsOfText(config, id)) client.expose(key, resolveVariant(key, config, distinctId(), {}));\n },\n openCancelFlow: (o) => flows.openCancelFlow(o),\n startOnboarding: (id) => flows.startOnboarding(id),\n registerForPush,\n unregisterForPush,\n flows,\n flush,\n ready,\n isReady: () => isReady,\n getDistinctId: distinctId,\n getConsent: () => consent,\n getUser: () => {\n if (!identified) return undefined;\n const p = person as { name?: unknown; email?: unknown } | undefined;\n return { id: identified, ...(typeof p?.name === \"string\" ? { name: p.name } : {}), ...(typeof p?.email === \"string\" ? { email: p.email } : {}) };\n },\n api: (as) => {\n if (!apiKey || consent === \"off\") return null;\n const known = client.getUser();\n // A name and email the person typed into a widget, for this request only.\n const user = as?.name || as?.email ? { ...known, ...(as.name ? { name: as.name } : {}), ...(as.email ? { email: as.email } : {}) } : known;\n return createApi({ host, apiKey, distinctId: distinctId(), user });\n },\n isSurveyDone: (id) => surveysDone.has(id),\n markSurveyDone: (id) => {\n surveysDone.add(id);\n if (consent === \"persistent\") void set(KEYS.surveys, JSON.stringify([...surveysDone].slice(-100)));\n },\n getConfig: () => config,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getVersion: () => version,\n close: async () => {\n if (closed) return;\n stopTimer();\n recorder?.sync(false);\n appStateSub?.remove();\n pushOff?.();\n pushOff = null;\n if (handlerInstalled && deps.errorUtils && previousHandler) deps.errorUtils.setGlobalHandler(previousHandler);\n await flush();\n await sendErrors();\n await persistQueue();\n closed = true;\n },\n queued: () => queue,\n };\n return client;\n};\n\n/** The name of the screen a React Navigation state shows: the focused route, followed into nested navigators. */\nexport const activeRouteName = (state: unknown): string | undefined => {\n let s = state as { index?: number; routes?: { name?: string; state?: unknown }[] } | undefined;\n let name: string | undefined;\n for (let depth = 0; s && Array.isArray(s.routes) && s.routes.length && depth < 20; depth++) {\n const route = s.routes[typeof s.index === \"number\" ? s.index : s.routes.length - 1];\n if (!route) break;\n name = route.name ?? name;\n s = route.state as typeof s;\n }\n return name;\n};\n","/**\n * The React Native renderer of the cancel flow, onboarding and in-app messages (../flows.ts), drawn by\n * `<MRRocketProvider>` next to the app (`flows={false}` switches it off, e.g. to draw `client.flows` yourself).\n * Dialogs (the cancel flow, modal and tour steps, modal messages) use React Native's `Modal`; a checklist and a banner\n * float over the app as absolutely placed views, so the provider should sit at the root, like a toast library.\n *\n * Themeable with `appearance={{ theme: \"light\" | \"dark\" | \"auto\", accent: \"#0f766e\" }}`. Tour steps show as a card at\n * the bottom (no pointing at elements in apps yet).\n */\nimport { type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FlowView, type FlowsController, discounted, money, offerButton } from \"../flows\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ntype Any = (props: Record<string, unknown>) => ReactNode;\ninterface RNModule {\n Modal: Any;\n View: Any;\n Text: Any;\n Pressable: Any;\n TextInput: Any;\n ScrollView: Any;\n useColorScheme?: () => string | null | undefined;\n}\nconst RN = require(\"react-native\") as RNModule;\n\nexport interface NativeAppearance {\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n}\n\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nexport const LIGHT = { bg: \"#ffffff\", fg: \"#1c1d20\", muted: \"#5d6068\", soft: \"#f4f5f7\", line: \"#e4e5e8\" };\nexport const DARK = { bg: \"#17181b\", fg: \"#f1f2f4\", muted: \"#a9acb3\", soft: \"#232428\", line: \"#2e2f35\" };\n\nconst months = (n: number) => `${n} ${n === 1 ? \"month\" : \"months\"}`;\n\nexport const MRRocketFlows = ({ flows, appearance = {} }: { flows: FlowsController; appearance?: NativeAppearance }) => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n // Re-render on every change of the controller.\n const [, setTick] = useState(0);\n useEffect(() => flows.subscribe(() => setTick((t) => t + 1)), [flows]);\n const v = flows.view();\n const [comment, setComment] = useState(\"\");\n const screen = v?.type === \"cancel\" ? v.screen : null;\n useEffect(() => {\n if (!screen) setComment(\"\");\n }, [screen]);\n if (!v) return null;\n\n const text = (children: ReactNode, style: Record<string, unknown> = {}) => h(RN.Text, { style: { color: p.fg, fontSize: 15, ...style } }, children);\n const muted = (children: ReactNode, style: Record<string, unknown> = {}) => text(children, { color: p.muted, fontSize: 13, ...style });\n const title = (children: ReactNode) => h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 18, fontWeight: \"700\" } }, children);\n const btn = (label: string, kind: \"primary\" | \"danger\" | \"secondary\" | \"quiet\", onPress: () => void, disabled = false) =>\n h(\n RN.Pressable,\n {\n key: label,\n onPress,\n disabled,\n accessibilityRole: \"button\",\n accessibilityState: { disabled },\n style: {\n height: kind === \"quiet\" ? 36 : 44,\n borderRadius: 10,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: disabled ? 0.55 : 1,\n backgroundColor: kind === \"primary\" ? p.accent : kind === \"danger\" ? p.danger : kind === \"secondary\" ? p.bg : \"transparent\",\n borderWidth: kind === \"secondary\" ? 1 : 0,\n borderColor: p.line,\n },\n },\n text(label, {\n color: kind === \"primary\" || kind === \"danger\" ? \"#ffffff\" : kind === \"quiet\" ? p.muted : p.fg,\n fontWeight: kind === \"quiet\" ? \"500\" : \"600\",\n }),\n );\n const close = (label: string, onPress: () => void) =>\n h(\n RN.Pressable,\n { onPress, accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 12, style: { marginLeft: \"auto\", padding: 4 } },\n text(\"×\", { fontSize: 22, color: p.muted }),\n );\n const card = (children: ReactNode[], style: Record<string, unknown> = {}) =>\n h(\n RN.View,\n {\n style: {\n backgroundColor: p.bg,\n borderRadius: 16,\n padding: 20,\n gap: 12,\n shadowColor: \"#000\",\n shadowOpacity: 0.18,\n shadowRadius: 20,\n elevation: 8,\n ...style,\n },\n },\n ...children,\n );\n const sheet = (children: ReactNode[], onClose: () => void) =>\n h(\n RN.Modal,\n { visible: true, transparent: true, animationType: \"fade\", onRequestClose: onClose },\n h(\n RN.View,\n { style: { flex: 1, backgroundColor: \"rgba(0,0,0,0.4)\", justifyContent: \"flex-end\" } },\n card(children, { borderBottomLeftRadius: 0, borderBottomRightRadius: 0, paddingBottom: 34 }),\n ),\n );\n const input = (placeholder: string) =>\n h(RN.TextInput, {\n value: comment,\n onChangeText: setComment,\n placeholder,\n placeholderTextColor: p.muted,\n multiline: true,\n maxLength: 500,\n accessibilityLabel: placeholder,\n style: { minHeight: 72, borderWidth: 1, borderColor: p.line, borderRadius: 10, padding: 10, color: p.fg, textAlignVertical: \"top\" },\n });\n\n if (v.type === \"cancel\") {\n const top = h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(v.steps > 1\n ? Array.from({ length: v.steps }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i < v.step ? p.accent : p.line } }),\n )\n : []),\n close(\"Close\", flows.cancel.close),\n );\n const error = v.error ? text(v.error, { color: p.danger, fontSize: 13 }) : null;\n let body: ReactNode[] = [];\n if (v.screen === \"survey\")\n body = [\n title(v.flow.question || \"Why are you leaving?\"),\n h(\n RN.ScrollView,\n { style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...v.flow.reasons.map((r) =>\n h(\n RN.Pressable,\n {\n key: r.id,\n onPress: () => flows.cancel.pick(r.id),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: v.reason === r.id },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: v.reason === r.id ? p.accent : p.line,\n backgroundColor: v.reason === r.id ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(r.label, { fontWeight: \"500\" }),\n ),\n ),\n ),\n btn(\"Continue\", \"primary\", flows.cancel.next, !v.reason),\n btn(\"Never mind, keep my plan\", \"quiet\", flows.cancel.close),\n ];\n else if (v.screen === \"offer\" && v.offer) {\n const o = v.offer;\n const label = v.flow.reasons.find((r) => r.id === v.reason)?.label;\n const detail =\n o.kind === \"discount\" && o.percent\n ? v.price\n ? `${money(discounted(v.price.amount, o.percent), v.price.currency)} instead of ${money(v.price.amount, v.price.currency)}${o.months ? ` for ${months(o.months)}` : \"\"}`\n : `${o.percent}% off${o.months ? ` for ${months(o.months)}` : \"\"}`\n : o.kind === \"pause\" && o.months\n ? `Pause for up to ${months(o.months)}. Your data stays.`\n : o.kind === \"downgrade\" && o.planName\n ? o.planName\n : null;\n body = [\n label ? muted(`You said: ${label}`) : null,\n title(o.headline),\n detail ? h(RN.View, { style: { backgroundColor: p.soft, borderRadius: 10, padding: 12 } }, text(detail, { fontWeight: \"600\" })) : null,\n o.kind === \"contact\" ? input(\"What would make you stay?\") : null,\n btn(v.busy ? \"One moment…\" : offerButton(o), \"primary\", () => flows.cancel.accept(comment), v.busy),\n btn(\"No thanks, continue cancelling\", \"quiet\", flows.cancel.decline, v.busy),\n ];\n } else\n body = [\n title(v.flow.confirm.title),\n v.flow.confirm.body ? muted(v.flow.confirm.body, { fontSize: 15 }) : null,\n v.steps > 1 ? input(\"Anything else we should know? (optional)\") : null,\n btn(v.busy ? \"One moment…\" : v.flow.confirm.button, \"danger\", () => flows.cancel.confirm(comment), v.busy),\n btn(\"Keep my plan\", \"secondary\", flows.cancel.close, v.busy),\n ];\n return sheet([top, ...body, error], flows.cancel.close);\n }\n\n if (v.type === \"step\")\n return sheet(\n [\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\" } },\n v.total > 1 ? muted(`Step ${v.index + 1} of ${v.total}`) : null,\n close(\"Close the tour\", flows.onboarding.dismiss),\n ),\n title(v.step.title),\n v.step.body ? muted(v.step.body, { fontSize: 15 }) : null,\n btn(v.step.button || (v.last ? \"Done\" : \"Next\"), \"primary\", flows.onboarding.next),\n ],\n flows.onboarding.dismiss,\n );\n\n if (v.type === \"checklist\") {\n const done = v.items.filter((i) => i.done).length;\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, bottom: 28 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\" } },\n title(v.flow.name),\n close(\"Hide the checklist\", flows.onboarding.dismiss),\n ),\n muted(`${done} of ${v.items.length} done`),\n ...v.items.map(({ step, done: d }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n disabled: d || !!step.event,\n onPress: () => flows.onboarding.check(step.id),\n accessibilityRole: \"checkbox\",\n accessibilityState: { checked: d },\n style: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\", paddingVertical: 6 },\n },\n h(\n RN.View,\n {\n style: {\n width: 20,\n height: 20,\n borderRadius: 10,\n borderWidth: 1.5,\n borderColor: d ? p.accent : p.line,\n backgroundColor: d ? p.accent : \"transparent\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n },\n d ? text(\"✓\", { color: \"#fff\", fontSize: 12 }) : null,\n ),\n h(\n RN.View,\n { style: { flex: 1 } },\n text(step.title, { fontWeight: \"600\", color: d ? p.muted : p.fg, textDecorationLine: d ? \"line-through\" : \"none\" }),\n step.body ? muted(step.body) : null,\n ),\n ),\n ),\n ]),\n );\n }\n\n const m = v.message;\n if (m.style === \"banner\")\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, top: 56 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8 } },\n h(RN.View, { style: { flex: 1 } }, text(m.title, { fontWeight: \"700\" }), m.body ? muted(m.body) : null),\n close(\"Dismiss\", flows.message.dismiss),\n ),\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ]),\n );\n return sheet(\n [\n h(RN.View, { key: \"t\", style: { flexDirection: \"row\" } }, close(\"Dismiss\", flows.message.dismiss)),\n title(m.title),\n m.body ? muted(m.body, { fontSize: 15 }) : null,\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ],\n flows.message.dismiss,\n );\n};\n","/**\n * The real platform for the React Native client: React Native itself, plus optional modules the app may have installed.\n * Each optional `require` sits directly in its own `try` block: that is how Metro knows the module is optional and\n * bundles the app without it when it is not installed (and how the CommonJS build keeps the call literal).\n *\n * - `@react-native-async-storage/async-storage`: the offline queue, the install id (\"persistent\" consent), the cached\n * config and the first-open marker. Without it everything stays in memory for the app's run.\n * - `expo-device`, `expo-application`, `expo-localization`: model, OS version, app version and build, locale.\n * Without them the SDK falls back to what React Native knows (platform, OS version, the JS locale).\n * - `expo-notifications` (with `expo-constants` for the EAS project id): push notifications, `registerForPush()`.\n * Without it `registerForPush` answers \"unavailable\".\n */\nimport type { AppContext } from \"../core\";\nimport type { AppStateLike, ErrorUtilsLike, FetchLike, KeyValueStorage, NativeDeps, PushData, PushDeps } from \"./client\";\nimport { measureMasks } from \"./recorder\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ninterface ReactNativeModule {\n Platform: { OS: string; Version?: string | number; isPad?: boolean; constants?: { Model?: string; Manufacturer?: string } };\n AppState: AppStateLike;\n Linking: { getInitialURL(): Promise<string | null>; openURL(url: string): Promise<unknown> };\n Dimensions: { get(dim: \"screen\" | \"window\"): { width: number; height: number } };\n Keyboard: { addListener(event: \"keyboardDidShow\" | \"keyboardDidHide\" | \"keyboardWillShow\", l: () => void): { remove(): void } };\n}\n\ninterface ViewShot {\n captureScreen?: (o: { format: \"jpg\"; quality: number; result: \"base64\"; width?: number; height?: number }) => Promise<string>;\n}\n\ninterface ExpoDevice {\n modelName?: string | null;\n osVersion?: string | null;\n deviceType?: number | null;\n}\ninterface ExpoApplication {\n nativeApplicationVersion?: string | null;\n nativeBuildVersion?: string | null;\n applicationId?: string | null;\n}\ninterface ExpoLocalization {\n getLocales?: () => { languageTag?: string }[];\n}\n\nconst RN = require(\"react-native\") as ReactNativeModule;\n\nlet asyncStorageModule: unknown = null;\ntry {\n asyncStorageModule = require(\"@react-native-async-storage/async-storage\");\n} catch {\n asyncStorageModule = null;\n}\nlet expoDevice: ExpoDevice | null = null;\ntry {\n expoDevice = require(\"expo-device\") as ExpoDevice;\n} catch {\n expoDevice = null;\n}\nlet expoApplication: ExpoApplication | null = null;\ntry {\n expoApplication = require(\"expo-application\") as ExpoApplication;\n} catch {\n expoApplication = null;\n}\nlet expoLocalization: ExpoLocalization | null = null;\ntry {\n expoLocalization = require(\"expo-localization\") as ExpoLocalization;\n} catch {\n expoLocalization = null;\n}\nlet viewShot: ViewShot | null = null;\ntry {\n viewShot = require(\"react-native-view-shot\") as ViewShot;\n} catch {\n viewShot = null;\n}\nlet expoNotifications: ExpoNotifications | null = null;\ntry {\n expoNotifications = require(\"expo-notifications\") as ExpoNotifications;\n} catch {\n expoNotifications = null;\n}\nlet expoConstants: { default?: ExpoConstants } & ExpoConstants = {};\ntry {\n expoConstants = require(\"expo-constants\") as typeof expoConstants;\n} catch {\n expoConstants = {};\n}\n\ninterface NotificationResponse {\n notification?: { request?: { content?: { data?: unknown } } };\n}\ninterface ExpoNotifications {\n getPermissionsAsync(): Promise<{ status?: string; granted?: boolean }>;\n requestPermissionsAsync(): Promise<{ status?: string; granted?: boolean }>;\n getExpoPushTokenAsync(o?: { projectId?: string }): Promise<{ data?: string }>;\n setNotificationChannelAsync?(id: string, o: Record<string, unknown>): Promise<unknown>;\n addNotificationResponseReceivedListener(fn: (r: NotificationResponse) => void): { remove(): void };\n getLastNotificationResponseAsync?(): Promise<NotificationResponse | null>;\n AndroidImportance?: { DEFAULT?: number; HIGH?: number };\n}\ninterface ExpoConstants {\n expoConfig?: { extra?: { eas?: { projectId?: string } } } | null;\n easConfig?: { projectId?: string } | null;\n}\n\nconst dataOf = (r: NotificationResponse | null | undefined) => (r?.notification?.request?.content?.data ?? null) as PushData | null;\n\n/** Push through `expo-notifications`; null when the app does not have it. */\nconst expoPush = (): PushDeps | null => {\n const n = expoNotifications;\n if (!n || typeof n.getExpoPushTokenAsync !== \"function\") return null;\n const constants = expoConstants.default ?? expoConstants;\n return {\n permission: async (ask) => {\n const now = await n.getPermissionsAsync();\n if (now.granted || now.status === \"granted\") return \"granted\";\n if (now.status === \"denied\" || !ask) return now.status === \"denied\" ? \"denied\" : \"undetermined\";\n const asked = await n.requestPermissionsAsync();\n return asked.granted || asked.status === \"granted\" ? \"granted\" : asked.status === \"denied\" ? \"denied\" : \"undetermined\";\n },\n token: async (projectId) => {\n // Android shows nothing without a channel.\n if (RN.Platform.OS === \"android\" && n.setNotificationChannelAsync)\n await n.setNotificationChannelAsync(\"default\", { name: \"Default\", importance: n.AndroidImportance?.HIGH ?? 4 });\n const id = projectId ?? constants.expoConfig?.extra?.eas?.projectId ?? constants.easConfig?.projectId;\n const t = await n.getExpoPushTokenAsync(id ? { projectId: id } : undefined);\n return typeof t?.data === \"string\" && t.data ? t.data : null;\n },\n onOpen: (listener) => {\n const sub = n.addNotificationResponseReceivedListener((r) => listener(dataOf(r) ?? {}));\n return () => sub.remove();\n },\n lastOpen: async () => dataOf(await n.getLastNotificationResponseAsync?.()),\n };\n};\n\n/** AsyncStorage's default export, or null when it is not installed. */\nconst asyncStorage = (): KeyValueStorage | null => {\n const m = asyncStorageModule as { default?: KeyValueStorage } & Partial<KeyValueStorage>;\n const s = (m?.default ?? m) as Partial<KeyValueStorage> | null;\n return s && typeof s.getItem === \"function\" && typeof s.setItem === \"function\" && typeof s.removeItem === \"function\" ? (s as KeyValueStorage) : null;\n};\n\nconst DEVICE_TYPES: Record<number, string> = { 1: \"phone\", 2: \"tablet\", 3: \"desktop\", 4: \"tv\" };\n\nconst text = (v: unknown, max = 80) => (typeof v === \"string\" && v.trim() ? v.trim().slice(0, max) : typeof v === \"number\" ? String(v) : undefined);\n\n/** The app and device, from the Expo modules when installed, else from React Native. Nothing that identifies a person. */\nexport const readContext = (): AppContext => {\n const p = RN.Platform;\n let locale: string | undefined;\n try {\n locale = text(expoLocalization?.getLocales?.()[0]?.languageTag, 35);\n } catch {\n locale = undefined;\n }\n if (!locale) {\n try {\n locale = text(Intl.DateTimeFormat().resolvedOptions().locale, 35);\n } catch {\n locale = undefined;\n }\n }\n const ctx: AppContext = {\n platform: p.OS,\n appVersion: text(expoApplication?.nativeApplicationVersion),\n build: text(expoApplication?.nativeBuildVersion),\n osVersion: text(expoDevice?.osVersion) ?? text(p.Version),\n deviceModel: text(expoDevice?.modelName) ?? text(p.constants?.Model),\n deviceType: (expoDevice?.deviceType ? DEVICE_TYPES[expoDevice.deviceType] : undefined) ?? (p.isPad ? \"tablet\" : undefined),\n locale,\n };\n for (const k of Object.keys(ctx) as (keyof AppContext)[]) if (ctx[k] === undefined) delete ctx[k];\n return ctx;\n};\n\n/**\n * Frames for session recordings: the whole screen (with modals) as a JPEG about 360 pixels wide, through\n * react-native-view-shot when the app has it. The keyboard's state comes from its own events; `keyboardWillShow`\n * (iOS) stops frames before it is on screen.\n */\nconst recorderDeps = (): NativeDeps[\"recorder\"] => {\n const capture = viewShot?.captureScreen;\n if (!capture) return null;\n let keyboard = false;\n try {\n RN.Keyboard.addListener(\"keyboardWillShow\", () => (keyboard = true));\n RN.Keyboard.addListener(\"keyboardDidShow\", () => (keyboard = true));\n RN.Keyboard.addListener(\"keyboardDidHide\", () => (keyboard = false));\n } catch {\n // Without keyboard events no frame can be taken safely.\n return null;\n }\n return {\n capture: async (width) => {\n const s = RN.Dimensions.get(\"screen\");\n if (!s?.width) return null;\n const w = Math.round(width);\n const h = Math.round((s.height / s.width) * width);\n const img = await capture({ format: \"jpg\", quality: 0.5, result: \"base64\", width: w, height: h });\n return img ? { img: img.replace(/^data:image\\/\\w+;base64,/, \"\"), w, h } : null;\n },\n keyboardOpen: () => keyboard,\n masks: measureMasks,\n };\n};\n\n/** The dependencies of the client on a real device. `storage` overrides AsyncStorage (pass null for memory only). */\nexport const nativeDeps = (overrides: { storage?: KeyValueStorage | null } = {}): NativeDeps => ({\n storage: overrides.storage !== undefined ? overrides.storage : asyncStorage(),\n fetch: ((url, init) => fetch(url, init)) as FetchLike,\n appState: RN.AppState,\n errorUtils: ((globalThis as { ErrorUtils?: ErrorUtilsLike }).ErrorUtils ?? null) as ErrorUtilsLike | null,\n context: readContext,\n appId: text(expoApplication?.applicationId, 150),\n screen: () => {\n const s = RN.Dimensions.get(\"screen\");\n return s ? { w: s.width, h: s.height } : undefined;\n },\n initialUrl: () => RN.Linking.getInitialURL(),\n openUrl: (url) => void RN.Linking.openURL(url).catch(() => undefined),\n push: expoPush(),\n recorder: recorderDeps(),\n});\n\n/** Whether the optional modules were found (for the debug log and the docs' checklist). */\nexport const optionalModules = () => ({\n asyncStorage: !!asyncStorage(),\n expoDevice: !!expoDevice,\n expoApplication: !!expoApplication,\n expoLocalization: !!expoLocalization,\n expoNotifications: !!expoNotifications,\n viewShot: !!viewShot?.captureScreen,\n});\n","/**\n * The React Native widgets of the web SDK's survey, feedback widget and messenger, on the same API (../api-client.ts),\n * drawn by `<MRRocketProvider>` next to the app:\n * - surveys: the live in-app survey MRRocket picks for the person shows as a sheet a few seconds after start (on by\n * default; `surveys={false}` switches it off),\n * - feedback: `useFeedback().open()` shows the top requests with votes and a form to suggest one,\n * - messenger: `useMessenger().open()` shows Home, Messages (the chat with the team, MRRocket › Support) and Help (the\n * product's published help articles); `messenger={{ launcher: true }}` (or \"Chat button in the app\" in MRRocket ›\n * Support › Messenger) adds a round button. Home has the accent head of the web messenger; its line icons need\n * react-native-svg (text glyphs without it). While it is closed and the person waits for an answer, it checks now\n * and then; a new answer shows as a banner at the top with a light haptic (expo-haptics, when installed; apps play\n * no sound of their own).\n * Same look as the flows (`appearance`). Nothing loads before it shows, except one survey request after start.\n */\nimport { type ReactNode, createElement as h, useCallback, useEffect, useRef, useState } from \"react\";\nimport { inkOn, replyLine } from \"../api-client\";\nimport type { Api, Article, ArticleSpan, ArticleSummary, ChatMessage, MessengerLook, ChatThread, FeedbackBoardInfo, FeedbackPost, SurveyAnswer, SurveyDefinition, SurveyQuestion } from \"../api-client\";\nimport type { MRRocketClient } from \"./client\";\nimport { DARK, LIGHT, type NativeAppearance } from \"./flows-view\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ntype Any = (props: Record<string, unknown>) => ReactNode;\ninterface RNModule {\n Modal: Any;\n View: Any;\n Text: Any;\n Pressable: Any;\n TextInput: Any;\n ScrollView: Any;\n KeyboardAvoidingView: Any;\n Platform: { OS: string };\n Linking: { openURL(url: string): Promise<unknown> };\n AppState: { currentState: string; addEventListener(type: \"change\", l: (s: string) => void): { remove(): void } };\n useColorScheme?: () => string | null | undefined;\n}\nconst RN = require(\"react-native\") as RNModule;\n\ntype Style = Record<string, unknown>;\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nconst usePalette = (appearance: NativeAppearance = {}): Palette => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n return { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n};\n\n/** Small building blocks in the flows' look. */\nconst kit = (p: Palette) => {\n const text = (children: ReactNode, style: Style = {}) => h(RN.Text, { style: { color: p.fg, fontSize: 15, ...style } }, children);\n const muted = (children: ReactNode, style: Style = {}) => text(children, { color: p.muted, fontSize: 13, ...style });\n const title = (children: ReactNode) => h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 17, fontWeight: \"700\", flex: 1 } }, children);\n const btn = (label: string, kind: \"primary\" | \"secondary\", onPress: () => void, disabled = false, style: Style = {}) =>\n h(\n RN.Pressable,\n {\n key: label,\n onPress,\n disabled,\n accessibilityRole: \"button\",\n accessibilityState: { disabled },\n style: {\n height: 44,\n paddingHorizontal: 16,\n borderRadius: 10,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: disabled ? 0.55 : 1,\n backgroundColor: kind === \"primary\" ? p.accent : p.bg,\n borderWidth: kind === \"secondary\" ? 1 : 0,\n borderColor: p.line,\n ...style,\n },\n },\n text(label, { color: kind === \"primary\" ? \"#ffffff\" : p.fg, fontWeight: \"600\" }),\n );\n const closeX = (label: string, onPress: () => void) =>\n h(RN.Pressable, { onPress, accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 12, style: { padding: 4 } }, text(\"×\", { fontSize: 24, color: p.muted }));\n const field = (o: { value: string; onChange: (v: string) => void; placeholder: string; multiline?: boolean; max?: number; email?: boolean; style?: Style; onSubmit?: () => void }) =>\n h(RN.TextInput, {\n value: o.value,\n onChangeText: o.onChange,\n placeholder: o.placeholder,\n placeholderTextColor: p.muted,\n multiline: !!o.multiline,\n maxLength: o.max ?? 2000,\n accessibilityLabel: o.placeholder,\n ...(o.email ? { keyboardType: \"email-address\", autoCapitalize: \"none\", autoComplete: \"email\", textContentType: \"emailAddress\" } : {}),\n ...(o.onSubmit ? { onSubmitEditing: o.onSubmit, returnKeyType: \"send\" } : {}),\n style: {\n minHeight: o.multiline ? 72 : 44,\n borderWidth: 1,\n borderColor: p.line,\n borderRadius: 10,\n paddingHorizontal: 12,\n paddingVertical: 10,\n color: p.fg,\n backgroundColor: p.bg,\n textAlignVertical: o.multiline ? \"top\" : \"center\",\n ...o.style,\n },\n });\n const chip = (label: string, on: boolean, onPress: () => void, key = label) =>\n h(\n RN.Pressable,\n {\n key,\n onPress,\n accessibilityRole: \"button\",\n accessibilityState: { selected: on },\n style: { paddingHorizontal: 12, height: 32, borderRadius: 16, justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.soft : p.bg },\n },\n text(label, { fontSize: 13, fontWeight: \"600\", color: on ? p.accent : p.fg }),\n );\n /** A full-height sheet (pageSheet on iOS) with a title row and the keyboard kept off the bottom. */\n const page = (heading: string, onClose: () => void, children: ReactNode[]) =>\n h(\n RN.Modal,\n { visible: true, animationType: \"slide\", presentationStyle: \"pageSheet\", onRequestClose: onClose },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: p.bg } },\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", paddingHorizontal: 16, paddingTop: 16, paddingBottom: 12, borderBottomWidth: 1, borderBottomColor: p.line } },\n title(heading),\n closeX(\"Close\", onClose),\n ),\n ...children,\n ),\n );\n return { text, muted, title, btn, closeX, field, chip, page };\n};\n\nconst timeAgo = (iso: string) => {\n const t = new Date(iso).getTime();\n if (Number.isNaN(t)) return \"\";\n const d = Math.max(0, Date.now() - t) / 1000;\n if (d < 60) return \"just now\";\n if (d < 3600) return `${Math.floor(d / 60)}m ago`;\n if (d < 86400) return `${Math.floor(d / 3600)}h ago`;\n return `${Math.floor(d / 86400)}d ago`;\n};\n\n/** Open state shared by a hook and the view the provider draws. */\nconst opener = () => {\n let open = false;\n const listeners = new Set<(v: boolean) => void>();\n const set = (v: boolean) => {\n open = v;\n listeners.forEach((l) => l(v));\n };\n const useOpen = () => {\n const [v, setV] = useState(open);\n useEffect(() => {\n listeners.add(setV);\n setV(open);\n return () => {\n listeners.delete(setV);\n };\n }, []);\n return v;\n };\n return { set, get: () => open, useOpen };\n};\n\n// ---------- Surveys ----------\n\nconst isAnswered = (a: SurveyAnswer | undefined) => (Array.isArray(a) ? a.length > 0 : typeof a === \"number\" ? true : !!a?.trim());\n\nconst SurveySheet = ({ survey, api, p, onDone }: { survey: SurveyDefinition; api: Api; p: Palette; onDone: () => void }) => {\n const k = kit(p);\n const [step, setStep] = useState(0);\n const [answers, setAnswers] = useState<Record<string, SurveyAnswer>>({});\n const [done, setDone] = useState(false);\n const [error, setError] = useState(\"\");\n const started = useRef(Date.now());\n const finished = useRef(false);\n const q: SurveyQuestion = survey.questions[step];\n const last = step === survey.questions.length - 1;\n const value = answers[q.key];\n\n useEffect(() => {\n api.seen(survey.id).catch(() => undefined);\n }, [api, survey.id]);\n useEffect(() => {\n if (!done) return;\n const t = setTimeout(onDone, 2500);\n return () => clearTimeout(t);\n }, [done, onDone]);\n\n const finish = (completed: boolean, all = answers) => {\n if (finished.current) return;\n finished.current = true;\n api.respond(survey.id, { answers: all, completed, seconds: Math.round((Date.now() - started.current) / 1000) }).catch(() => undefined);\n };\n const dismiss = () => {\n // Partial answers still count, so nothing the person typed is lost.\n if (Object.values(answers).some(isAnswered)) finish(false);\n onDone();\n };\n const next = () => {\n if (q.required && !isAnswered(value)) return setError(\"Please answer this question.\");\n setError(\"\");\n if (!last) return setStep(step + 1);\n finish(true);\n setDone(true);\n };\n const pick = (v: SurveyAnswer) => {\n setAnswers((a) => ({ ...a, [q.key]: v }));\n setError(\"\");\n };\n\n let input: ReactNode;\n if (q.kind === \"nps\" || q.kind === \"rating\") {\n const scale = q.kind === \"nps\" ? 11 : Math.min(Math.max(q.scale ?? 5, 2), 10);\n const start = q.kind === \"nps\" ? 0 : 1;\n input = h(\n RN.View,\n { style: { gap: 6 } },\n h(\n RN.View,\n { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 }, accessibilityRole: \"radiogroup\", accessibilityLabel: q.title },\n ...Array.from({ length: scale }, (_, i) => {\n const n = i + start;\n const on = value === n;\n return h(\n RN.Pressable,\n {\n key: n,\n onPress: () => pick(n),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: on },\n accessibilityLabel: `${n} of ${scale - 1 + start}`,\n style: { width: 40, height: 40, borderRadius: 8, alignItems: \"center\", justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.accent : p.bg },\n },\n k.text(String(n), { color: on ? \"#ffffff\" : p.fg, fontWeight: \"600\" }),\n );\n }),\n ),\n q.low || q.high || q.kind === \"nps\"\n ? h(RN.View, { style: { flexDirection: \"row\", justifyContent: \"space-between\" } }, k.muted(q.low ?? (q.kind === \"nps\" ? \"Not likely\" : \"\")), k.muted(q.high ?? (q.kind === \"nps\" ? \"Very likely\" : \"\")))\n : null,\n );\n } else if (q.kind === \"single\" || q.kind === \"multi\") {\n const multi = q.kind === \"multi\";\n const picked = multi ? ((value as string[] | undefined) ?? []) : [];\n input = h(\n RN.View,\n { style: { gap: 6 } },\n ...(q.options ?? []).map((o) => {\n const on = multi ? picked.includes(o) : value === o;\n return h(\n RN.Pressable,\n {\n key: o,\n onPress: () => pick(multi ? (on ? picked.filter((x) => x !== o) : [...picked, o]) : o),\n accessibilityRole: multi ? \"checkbox\" : \"radio\",\n accessibilityState: { checked: on },\n style: { minHeight: 44, paddingHorizontal: 12, borderRadius: 10, justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.soft : p.bg },\n },\n k.text(o, { fontWeight: \"500\" }),\n );\n }),\n );\n } else input = k.field({ value: (value as string | undefined) ?? \"\", onChange: pick, placeholder: q.placeholder ?? \"Type your answer\", multiline: true });\n\n const body = done\n ? [k.text(survey.thanks || \"Thanks for your feedback.\", { fontWeight: \"600\", textAlign: \"center\", paddingVertical: 16 })]\n : [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...survey.questions.map((x, i) => h(RN.View, { key: x.key, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= step ? p.accent : p.line } })),\n h(RN.View, { style: { flex: 1 } }),\n k.closeX(\"Close survey\", dismiss),\n ),\n h(RN.Text, { key: \"q\", accessibilityRole: \"header\", style: { color: p.fg, fontSize: 17, fontWeight: \"700\" } }, q.title, q.required ? \"\" : h(RN.Text, { style: { color: p.muted, fontSize: 13, fontWeight: \"400\" } }, \" optional\")),\n q.description ? k.muted(q.description) : null,\n input,\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n k.btn(last ? \"Send\" : \"Next\", \"primary\", next),\n ];\n\n return h(\n RN.Modal,\n { visible: true, transparent: true, animationType: \"slide\", onRequestClose: dismiss },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: \"rgba(0,0,0,0.35)\", justifyContent: \"flex-end\" } },\n h(\n RN.View,\n {\n accessibilityViewIsModal: true,\n accessibilityLabel: survey.name,\n style: { backgroundColor: p.bg, borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 20, paddingBottom: 34, gap: 12 },\n },\n ...body,\n ),\n ),\n );\n};\n\n/** Asks the person the survey MRRocket picks for them, a few seconds after start and again for a new person. */\nexport const MRRocketSurveys = ({ client, appearance }: { client: MRRocketClient; appearance?: NativeAppearance }) => {\n const p = usePalette(appearance);\n const [survey, setSurvey] = useState<{ s: SurveyDefinition; api: Api } | null>(null);\n const [who, setWho] = useState(() => client.getDistinctId());\n useEffect(() => client.subscribe(() => setWho(client.getDistinctId())), [client]);\n\n useEffect(() => {\n let stop = false;\n const ctrl = new AbortController();\n const timer = setTimeout(() => {\n void client.ready.then(() => {\n const api = client.api();\n if (stop || !api) return;\n api.survey(\"\", ctrl.signal)\n .then((r) => {\n const s = r.survey;\n if (stop || !s || !s.questions.length || client.isSurveyDone(s.id)) return;\n setSurvey({ s, api });\n })\n .catch(() => undefined);\n });\n }, 3000);\n return () => {\n stop = true;\n clearTimeout(timer);\n ctrl.abort();\n };\n }, [client, who]);\n\n const done = useCallback(() => {\n setSurvey((cur) => {\n if (cur) client.markSurveyDone(cur.s.id);\n return null;\n });\n }, [client]);\n if (!survey) return null;\n return h(SurveySheet, { key: survey.s.id, survey: survey.s, api: survey.api, p, onDone: done });\n};\n\n// ---------- Feedback ----------\n\nconst feedbackOpen = opener();\n\n/** Opens the feedback sheet: the top requests with votes, and a form to suggest one. */\nexport const useFeedback = () => ({ open: () => feedbackOpen.set(true), close: () => feedbackOpen.set(false) });\n\nexport interface NativeFeedbackOptions {\n /** The sheet's title. Default \"Feedback\". */\n title?: string;\n}\n\nconst FeedbackSheet = ({ client, p, title }: { client: MRRocketClient; p: Palette; title: string }) => {\n const k = kit(p);\n const [tab, setTab] = useState<\"top\" | \"new\">(\"top\");\n const [posts, setPosts] = useState<FeedbackPost[] | null>(null);\n const [boards, setBoards] = useState<FeedbackBoardInfo[]>([]);\n const [error, setError] = useState(\"\");\n const [board, setBoard] = useState(\"feature\");\n const [subject, setSubject] = useState(\"\");\n const [details, setDetails] = useState(\"\");\n const [name, setName] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const close = () => feedbackOpen.set(false);\n const user = client.getUser();\n\n useEffect(() => {\n const api = client.api();\n if (!api) return setError(\"Feedback is off while tracking is off.\");\n const ctrl = new AbortController();\n api.list({ sort: \"top\" }, ctrl.signal)\n .then((l) => {\n setPosts(l.posts);\n setBoards(l.boards);\n if (l.boards.length && !l.boards.some((b) => b.id === \"feature\")) setBoard(l.boards[0].id);\n })\n .catch((e: Error) => e.name !== \"AbortError\" && setError(e.message));\n return () => ctrl.abort();\n }, [client]);\n\n const vote = (post: FeedbackPost) => {\n const api = client.api();\n if (!api) return;\n // At once on screen; the server's count replaces it.\n setPosts((all) => all?.map((x) => (x.id === post.id ? { ...x, voted: !x.voted, votes: x.votes + (x.voted ? -1 : 1) } : x)) ?? null);\n api.vote(post.id)\n .then((r) => setPosts((all) => all?.map((x) => (x.id === post.id ? { ...x, voted: r.voted, votes: r.votes } : x)) ?? null))\n .catch((e: Error) => {\n setError(e.message);\n setPosts((all) => all?.map((x) => (x.id === post.id ? post : x)) ?? null);\n });\n };\n\n const submit = () => {\n const api = client.api({ name: name.trim(), email: email.trim() });\n if (!api || subject.trim().length < 3 || sending) return;\n setSending(true);\n setError(\"\");\n api.submit({ title: subject.trim(), body: details.trim() || undefined, board })\n .then((post) => {\n setPosts((all) => [post, ...(all ?? [])]);\n setSubject(\"\");\n setDetails(\"\");\n setSent(true);\n })\n .catch((e: Error) => setError(e.message))\n .finally(() => setSending(false));\n };\n\n const tabs = h(\n RN.View,\n { style: { flexDirection: \"row\", gap: 8, paddingHorizontal: 16, paddingTop: 12 } },\n k.chip(\"Top requests\", tab === \"top\", () => setTab(\"top\")),\n k.chip(\"Suggest\", tab === \"new\", () => {\n setTab(\"new\");\n setSent(false);\n }),\n );\n\n const list = h(\n RN.ScrollView,\n { style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 10 } },\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n posts === null && !error ? k.muted(\"Loading…\") : null,\n posts?.length === 0 ? k.muted(\"No requests yet. Be the first to suggest one.\") : null,\n ...(posts ?? []).map((post) =>\n h(\n RN.View,\n { key: post.id, style: { flexDirection: \"row\", gap: 12, alignItems: \"flex-start\", paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: p.line } },\n h(\n RN.Pressable,\n {\n onPress: () => vote(post),\n accessibilityRole: \"button\",\n accessibilityState: { selected: post.voted },\n accessibilityLabel: `${post.voted ? \"Remove your vote from\" : \"Upvote\"} ${post.title}. ${post.votes} votes`,\n style: { width: 44, minHeight: 48, borderRadius: 10, alignItems: \"center\", justifyContent: \"center\", borderWidth: 1, borderColor: post.voted ? p.accent : p.line },\n },\n k.text(\"▲\", { fontSize: 11, color: post.voted ? p.accent : p.muted }),\n k.text(String(post.votes), { fontWeight: \"700\", fontSize: 14, color: post.voted ? p.accent : p.fg }),\n ),\n h(RN.View, { style: { flex: 1, gap: 2 } }, k.text(post.title, { fontWeight: \"600\" }), post.body ? k.muted(post.body.slice(0, 160)) : null),\n ),\n ),\n );\n\n const form = h(\n RN.ScrollView,\n { style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 10 }, keyboardShouldPersistTaps: \"handled\" },\n sent ? k.text(\"Thanks! Your request is on the board.\", { fontWeight: \"600\" }) : null,\n boards.length > 1 ? h(RN.View, { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 } }, ...boards.map((b) => k.chip(b.label, board === b.id, () => setBoard(b.id), b.id))) : null,\n k.field({ value: subject, onChange: setSubject, placeholder: \"Short title\", max: 120 }),\n k.field({ value: details, onChange: setDetails, placeholder: \"Details (optional)\", multiline: true }),\n ...(user?.email\n ? []\n : [\n k.muted(\"Your name and email are optional; they let the team follow up.\"),\n k.field({ value: name, onChange: setName, placeholder: \"Your name (optional)\", max: 100 }),\n k.field({ value: email, onChange: setEmail, placeholder: \"Your email (optional)\", max: 200, email: true }),\n ]),\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n k.btn(sending ? \"Sending…\" : \"Send request\", \"primary\", submit, subject.trim().length < 3 || sending),\n );\n\n return k.page(title, close, [tabs, tab === \"top\" ? list : form]);\n};\n\nexport const MRRocketFeedback = ({ client, appearance, options = {} }: { client: MRRocketClient; appearance?: NativeAppearance; options?: NativeFeedbackOptions }) => {\n const p = usePalette(appearance);\n const open = feedbackOpen.useOpen();\n return open ? h(FeedbackSheet, { client, p, title: options.title ?? \"Feedback\" }) : null;\n};\n\n// ---------- Messenger ----------\n\nconst POLL_OPEN_MS = 4000;\nconst POLL_WAITING_MS = 8000;\nconst POLL_IDLE_MS = 30000;\nconst WAITING_FOR_MS = 10 * 60_000;\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst whoLabel: Record<ChatMessage[\"from\"], string> = { visitor: \"You\", team: \"Team\", ai: \"AI agent\", auto: \"Team\" };\n\ntype MsgView = \"home\" | \"messages\" | \"help\" | { article: string };\nlet msgView: MsgView = \"home\";\nconst messengerOpen = opener();\nconst openAt = (v: MsgView = \"home\") => {\n msgView = v;\n messengerOpen.set(true);\n};\n\n/** Opens (on Home, a tab or `{ article: id }`), closes or toggles the messenger. */\nexport const useMessenger = () => ({\n open: (view?: MsgView) => openAt(view),\n close: () => messengerOpen.set(false),\n toggle: () => (messengerOpen.get() ? messengerOpen.set(false) : openAt()),\n});\n\nexport interface NativeMessengerOptions {\n /** A round chat button (default false: open it with `useMessenger().open()` from your own button). */\n launcher?: boolean;\n /** Where the chat button sits (default bottom right). */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Text beside the chat button's icon; empty: the round button. */\n label?: string;\n title?: string;\n /** The big line on Home and the first line of an empty chat. */\n greeting?: string;\n /** How soon the team usually answers, said under \"Send us a message\" and in the chat's head. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** Ask people the app did not identify with an email for an email (optional for them). Default true. */\n askEmail?: boolean;\n /** The Help tab with your published help articles (default true; hidden while there are none). */\n help?: boolean;\n /** A banner at the top when an answer arrives while the messenger is closed (default true). */\n preview?: boolean;\n /** A light haptic when an answer arrives (default true; needs expo-haptics). */\n haptics?: boolean;\n}\n\ninterface ExpoHaptics {\n notificationAsync?: (t: unknown) => Promise<void>;\n NotificationFeedbackType?: { Success: unknown };\n}\nlet haptics: ExpoHaptics | null = null;\ntry {\n haptics = require(\"expo-haptics\") as ExpoHaptics;\n} catch {\n haptics = null;\n}\nconst buzz = () => {\n try {\n void haptics?.notificationAsync?.(haptics.NotificationFeedbackType?.Success)?.catch(() => undefined);\n } catch {\n // No haptics.\n }\n};\n\nconst teamOf = (t: ChatThread | null) => (t?.messages ?? []).filter((m) => m.from !== \"visitor\");\n\ninterface SvgModule {\n Svg?: Any;\n default?: Any;\n Path: Any;\n}\nlet svg: SvgModule | null = null;\ntry {\n svg = require(\"react-native-svg\") as SvgModule;\n} catch {\n svg = null;\n}\n/** The web messenger's line icons (16-unit paths), drawn with react-native-svg when the app has it, else a text glyph. */\nconst GLYPH = {\n chat: \"M2.5 4.5a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v4.5a2 2 0 0 1-2 2H7l-3 2.5V11a2 2 0 0 1-1.5-2z\",\n home: \"M2.5 7 8 2.5 13.5 7v6a1 1 0 0 1-1 1h-3v-4h-3v4h-3a1 1 0 0 1-1-1z\",\n help: \"M8 14.5A6.5 6.5 0 1 0 8 1.5a6.5 6.5 0 0 0 0 13zM6.2 6.2a1.9 1.9 0 1 1 2.6 1.8c-.5.2-.8.6-.8 1.1v.4M8 11.6v.1\",\n send: \"M2.5 8h10M8.5 3.5 13 8l-4.5 4.5\",\n up: \"M8 13V3M3.5 7.5 8 3l4.5 4.5\",\n next: \"M6 3.5 10.5 8 6 12.5\",\n search: \"M7 11.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9zM10.5 10.5l3 3\",\n cross: \"m4 4 8 8M12 4l-8 8\",\n};\nconst FALLBACK: Record<keyof typeof GLYPH, string> = { chat: \"💬\", home: \"⌂\", help: \"?\", send: \"→\", up: \"↑\", next: \"›\", search: \"⌕\", cross: \"×\" };\nconst glyph = (name: keyof typeof GLYPH, color: string, size = 20) => {\n const Svg = svg?.Svg ?? svg?.default;\n if (!svg || !Svg) return h(RN.Text, { style: { color, fontSize: Math.round(size * 0.85), lineHeight: size + 2, textAlign: \"center\", minWidth: size } }, FALLBACK[name]);\n return h(Svg, { width: size, height: size, viewBox: \"0 0 16 16\", fill: \"none\" }, h(svg.Path, { d: GLYPH[name], stroke: color, strokeWidth: 1.7, strokeLinecap: \"round\", strokeLinejoin: \"round\", fill: \"none\" }));\n};\n/** \"#rrggbb\" with an opacity, for the accent's soft fills. */\nconst alpha = (hex: string, a: number) => (/^#[0-9a-f]{6}$/i.test(hex) ? `${hex}${Math.round(a * 255).toString(16).padStart(2, \"0\")}` : hex);\n/** The team's mark: the title's first letter on the accent (or the accent on the ink, over the colored head). */\nconst teamMark = (title: string, bg: string, fg: string, size = 36) =>\n h(\n RN.View,\n { style: { width: size, height: size, borderRadius: size / 2, backgroundColor: bg, alignItems: \"center\", justifyContent: \"center\" } },\n h(RN.Text, { style: { color: fg, fontSize: Math.round(size * 0.42), fontWeight: \"700\" } }, (title.trim()[0] ?? \"?\").toUpperCase()),\n );\nconst lift = { shadowColor: \"#101218\", shadowOpacity: 0.07, shadowRadius: 14, shadowOffset: { width: 0, height: 4 }, elevation: 2 };\n\n/** The chat's state, kept while the sheet is closed so answers count and preview. */\nconst useChat = (client: MRRocketClient, o: NativeMessengerOptions, open: boolean, view: MsgView) => {\n const [thread, setThread] = useState<ChatThread | null>(null);\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState(\"\");\n const [unseen, setUnseen] = useState<ChatMessage[]>([]);\n const known = useRef<string | null>(null);\n const watching = open && view === \"messages\";\n const watch = useRef(watching);\n watch.current = watching;\n const [active, setActive] = useState(RN.AppState.currentState === \"active\");\n useEffect(() => {\n const sub = RN.AppState.addEventListener(\"change\", (st) => setActive(st === \"active\"));\n return () => sub.remove();\n }, []);\n\n const take = useCallback(\n (t: ChatThread) => {\n const team = teamOf(t);\n if (known.current !== null) {\n const i = team.findIndex((m) => m.id === known.current);\n const fresh = team.slice(i + 1).filter((m) => m.from !== \"auto\");\n if (fresh.length) {\n if (o.haptics !== false) buzz();\n if (!watch.current) setUnseen((u) => [...u, ...fresh]);\n }\n }\n known.current = team.at(-1)?.id ?? \"\";\n setThread(t);\n },\n [o.haptics],\n );\n\n useEffect(() => {\n if (watching) setUnseen([]);\n }, [watching]);\n\n // Reads: often while the chat is on screen, now and then while the person waits for an answer, never in the background.\n useEffect(() => {\n if (!active) return;\n let stop = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let ctrl: AbortController | null = null;\n const tick = async () => {\n const api = client.api();\n if (!api) {\n setLoaded(true);\n return;\n }\n ctrl = new AbortController();\n let t: ChatThread | null = null;\n try {\n await client.ready;\n t = await api.chat(ctrl.signal);\n if (stop) return;\n take(t);\n setError(\"\");\n } catch (e) {\n if ((e as Error).name === \"AbortError\" || stop) return;\n if (watch.current) setError((e as Error).message);\n }\n setLoaded(true);\n const waiting = !!t?.messages.some((m) => m.from === \"visitor\") && t?.conversation?.status !== \"solved\";\n const wrote = (t?.messages ?? []).filter((m) => m.from === \"visitor\").at(-1)?.at;\n const recent = !!wrote && Date.now() - new Date(wrote).getTime() < WAITING_FOR_MS;\n const ms = watch.current ? POLL_OPEN_MS : waiting && recent ? POLL_WAITING_MS : waiting || open ? POLL_IDLE_MS : 0;\n if (!stop && ms) timer = setTimeout(tick, ms);\n };\n void tick();\n return () => {\n stop = true;\n ctrl?.abort();\n clearTimeout(timer);\n };\n }, [client, take, active, open, watching]);\n\n return { thread, loaded, error, setError, unseen, take };\n};\n\nconst useArticles = (client: MRRocketClient, on: boolean, query: string) => {\n const [list, setList] = useState<ArticleSummary[] | null>(null);\n const [any, setAny] = useState<boolean | null>(null);\n useEffect(() => {\n if (!on) return;\n let stop = false;\n const t = setTimeout(\n () =>\n void client.ready.then(() =>\n client\n .api()\n ?.articles(query.trim() || undefined)\n .then((r) => {\n if (stop) return;\n setList(r.articles);\n if (!query.trim()) setAny(r.articles.length > 0);\n })\n .catch(() => !stop && setList((l) => l ?? [])),\n ),\n query ? 250 : 0,\n );\n return () => {\n stop = true;\n clearTimeout(t);\n };\n }, [client, on, query]);\n return { list, any };\n};\n\nconst spansOf = (p: Palette, spans: ArticleSpan[], base: Style) =>\n spans.map((s, i) =>\n h(\n RN.Text,\n {\n key: i,\n onPress: s.href ? () => void RN.Linking.openURL(s.href!).catch(() => undefined) : undefined,\n accessibilityRole: s.href ? \"link\" : undefined,\n style: {\n ...base,\n ...(s.bold ? { fontWeight: \"700\" } : {}),\n ...(s.italic ? { fontStyle: \"italic\" } : {}),\n ...(s.code ? { fontFamily: RN.Platform.OS === \"ios\" ? \"Menlo\" : \"monospace\", backgroundColor: p.soft } : {}),\n ...(s.href ? { color: p.accent, textDecorationLine: \"underline\" } : {}),\n },\n },\n s.text,\n ),\n );\n\nconst ArticleView = ({ client, p, id, onAsk }: { client: MRRocketClient; p: Palette; id: string; onAsk: () => void }) => {\n const k = kit(p);\n const [a, setA] = useState<Article | null>(null);\n const [error, setError] = useState(\"\");\n const [rated, setRated] = useState(false);\n useEffect(() => {\n const ctrl = new AbortController();\n client\n .api()\n ?.article(id, ctrl.signal)\n .then(setA)\n .catch((e: Error) => e.name !== \"AbortError\" && setError(e.message));\n return () => ctrl.abort();\n }, [client, id]);\n if (error) return k.text(error, { color: p.danger });\n if (!a) return k.muted(\"Loading…\");\n const base = { color: p.fg, fontSize: 15, lineHeight: 22 };\n const blocks = a.blocks.map((b, i) => {\n if (b.type === \"h2\" || b.type === \"h3\") return h(RN.Text, { key: i, accessibilityRole: \"header\", style: { ...base, fontSize: b.type === \"h2\" ? 17 : 16, fontWeight: \"700\", marginTop: 8 } }, ...spansOf(p, b.spans, {}));\n if (b.type === \"p\") return h(RN.Text, { key: i, style: base }, ...spansOf(p, b.spans, {}));\n if (b.type === \"quote\") return h(RN.View, { key: i, style: { borderLeftWidth: 3, borderLeftColor: p.line, paddingLeft: 10 } }, h(RN.Text, { style: { ...base, color: p.muted } }, ...spansOf(p, b.spans, {})));\n if (b.type === \"ul\" || b.type === \"ol\")\n return h(\n RN.View,\n { key: i, style: { gap: 4 } },\n ...b.items.map((it, j) => h(RN.View, { key: j, style: { flexDirection: \"row\", gap: 8 } }, k.text(b.type === \"ol\" ? `${j + 1}.` : \"•\", base), h(RN.Text, { style: { ...base, flex: 1 } }, ...spansOf(p, it, {})))),\n );\n if (b.type === \"code\") return h(RN.View, { key: i, style: { backgroundColor: p.soft, borderRadius: 8, padding: 10 } }, k.text(b.text, { fontFamily: RN.Platform.OS === \"ios\" ? \"Menlo\" : \"monospace\", fontSize: 13 }));\n return h(RN.View, { key: i, style: { height: 1, backgroundColor: p.line } });\n });\n const rate = (helpful: boolean) => {\n setRated(true);\n client\n .api()\n ?.rateArticle(id, helpful)\n .catch(() => undefined);\n if (!helpful) onAsk();\n };\n return h(\n RN.View,\n { style: { gap: 10 } },\n k.muted(a.collection),\n h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 20, fontWeight: \"700\" } }, a.title),\n ...blocks,\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, padding: 12, borderRadius: 10, backgroundColor: p.soft, marginTop: 8 } },\n rated ? k.muted(\"Thanks for letting us know.\") : k.muted(\"Did this answer your question?\", { flex: 1 }),\n rated ? null : k.btn(\"Yes\", \"secondary\", () => rate(true), false, { height: 34 }),\n rated ? null : k.btn(\"No\", \"secondary\", () => rate(false), false, { height: 34 }),\n ),\n k.btn(\"Still need help? Send us a message\", \"secondary\", onAsk),\n );\n};\n\nconst MessengerSheet = ({\n client,\n p,\n o,\n chat,\n view,\n setView,\n}: {\n client: MRRocketClient;\n p: Palette;\n o: NativeMessengerOptions;\n chat: ReturnType<typeof useChat>;\n view: MsgView;\n setView: (v: MsgView) => void;\n}) => {\n const k = kit(p);\n const [body, setBody] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n const [pending, setPending] = useState<ChatMessage | null>(null);\n const [query, setQuery] = useState(\"\");\n const helpOn = o.help !== false;\n const arts = useArticles(client, helpOn, query);\n const scroll = useRef<{ scrollToEnd?: (o: { animated: boolean }) => void } | null>(null);\n const close = () => messengerOpen.set(false);\n const greeting = o.greeting ?? \"Hi! How can we help?\";\n const { thread } = chat;\n\n const count = (thread?.messages.length ?? 0) + (pending ? 1 : 0);\n useEffect(() => {\n if (view === \"messages\") setTimeout(() => scroll.current?.scrollToEnd?.({ animated: true }), 50);\n }, [count, view]);\n\n const needEmail = (o.askEmail ?? true) && !thread?.hasEmail && !client.getUser()?.email;\n const emailOk = !email.trim() || EMAIL.test(email.trim());\n const send = async () => {\n const text = body.trim();\n const api = client.api();\n if (!text || pending || !emailOk || !api) return;\n setPending({ id: \"pending\", from: \"visitor\", body: text, at: new Date().toISOString() });\n setBody(\"\");\n chat.setError(\"\");\n try {\n chat.take(await api.sendChat({ body: text, email: needEmail && email.trim() ? email.trim() : undefined }));\n } catch (e) {\n setBody(text);\n chat.setError((e as Error).message);\n } finally {\n setPending(null);\n }\n };\n\n const ink = inkOn(p.accent);\n const dark = p.bg === DARK.bg;\n // Light: white cards on a soft gray; dark: lighter cards on the dark ground.\n const canvas = dark ? p.bg : p.soft;\n const raised = dark ? p.soft : p.bg;\n const title = o.title ?? \"Chat with us\";\n const reply = replyLine(o.replyTime);\n\n const bubble = (m: ChatMessage, isPending = false) => {\n const mine = m.from === \"visitor\";\n return h(\n RN.View,\n { key: m.id, style: { alignSelf: mine ? \"flex-end\" : \"flex-start\", maxWidth: \"82%\", gap: 4 } },\n h(\n RN.View,\n {\n style: {\n backgroundColor: mine ? p.accent : dark ? p.soft : \"#eeeff1\",\n borderRadius: 18,\n borderBottomRightRadius: mine ? 6 : 18,\n borderBottomLeftRadius: mine ? 18 : 6,\n paddingHorizontal: 14,\n paddingVertical: 9,\n opacity: isPending ? 0.7 : 1,\n },\n },\n k.text(m.body, { color: mine ? ink : p.fg }),\n ),\n ...(m.articles ?? []).map((a) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"link\", style: { borderWidth: 1, borderColor: p.line, borderRadius: 12, paddingHorizontal: 10, paddingVertical: 7 } },\n k.text(`📄 ${a.title}`, { fontSize: 13 }),\n ),\n ),\n m.at ? k.muted(`${mine ? \"\" : `${whoLabel[m.from]} · `}${isPending ? \"Sending…\" : timeAgo(m.at)}`, { fontSize: 11, textAlign: mine ? \"right\" : \"left\", paddingHorizontal: 6 }) : null,\n );\n };\n const row = (a: ArticleSummary) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"button\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingVertical: 11, paddingHorizontal: 8 } },\n k.text(a.title, { flex: 1 }),\n glyph(\"next\", p.accent, 14),\n );\n const card = (children: ReactNode[], style: Style = {}) => h(RN.View, { style: { backgroundColor: raised, borderRadius: 16, padding: 16, ...(dark ? { borderWidth: 1, borderColor: p.line } : lift), ...style } }, ...children);\n const searchRow = (onPress: () => void) =>\n h(\n RN.Pressable,\n { key: \"s\", onPress, accessibilityRole: \"search\", style: { flexDirection: \"row\", alignItems: \"center\", height: 44, borderRadius: 12, paddingHorizontal: 14, backgroundColor: canvas } },\n k.muted(\"Search for help\", { flex: 1, fontSize: 15 }),\n glyph(\"search\", p.accent, 16),\n );\n const search = k.field({ value: query, onChange: setQuery, placeholder: \"Search for help\", max: 200, style: { borderWidth: 0, borderRadius: 12, backgroundColor: raised, ...(dark ? {} : lift) } });\n\n const last = thread?.messages.at(-1);\n const showHelp = helpOn && arts.any !== false;\n let content: ReactNode;\n if (view === \"home\")\n content = h(\n RN.ScrollView,\n { key: \"home\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { paddingBottom: 24 }, keyboardShouldPersistTaps: \"handled\" },\n h(RN.View, { style: { backgroundColor: p.accent, paddingHorizontal: 22, paddingTop: 4, paddingBottom: 64 } }, h(RN.Text, { style: { color: ink, fontSize: 28, fontWeight: \"700\", letterSpacing: -0.4, lineHeight: 34 } }, greeting)),\n h(\n RN.View,\n { style: { marginTop: -48, paddingHorizontal: 16, gap: 12 } },\n last\n ? h(\n RN.Pressable,\n { key: \"recent\", onPress: () => setView(\"messages\"), accessibilityRole: \"button\" },\n card([\n k.muted(\"Recent message\", { fontSize: 12, fontWeight: \"600\", marginBottom: 10 }),\n h(\n RN.View,\n { key: \"r\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 12 } },\n teamMark(title, p.accent, ink),\n h(RN.View, { style: { flex: 1, gap: 2 } }, h(RN.Text, { numberOfLines: 1, style: { color: p.fg, fontSize: 15 } }, last.body), k.muted(`${last.from === \"visitor\" ? \"You\" : whoLabel[last.from]} · ${timeAgo(last.at)}`, { fontSize: 12 })),\n chat.unseen.length\n ? h(RN.View, { style: { minWidth: 20, height: 20, borderRadius: 10, paddingHorizontal: 6, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\" } }, k.text(String(chat.unseen.length), { color: \"#fff\", fontSize: 12, fontWeight: \"700\" }))\n : glyph(\"next\", p.muted, 14),\n ),\n ]),\n )\n : null,\n h(\n RN.Pressable,\n { key: \"send\", onPress: () => setView(\"messages\"), accessibilityRole: \"button\" },\n card(\n [\n h(RN.View, { key: \"t\", style: { flex: 1, gap: 2 } }, k.text(\"Send us a message\", { fontWeight: \"700\", fontSize: 16 }), k.muted(reply)),\n h(RN.View, { key: \"g\", style: { width: 36, height: 36, borderRadius: 18, backgroundColor: alpha(p.accent, 0.12), alignItems: \"center\", justifyContent: \"center\" } }, glyph(\"send\", p.accent, 18)),\n ],\n { flexDirection: \"row\", alignItems: \"center\", gap: 12 },\n ),\n ),\n showHelp ? card([searchRow(() => setView(\"help\")), ...(arts.list ?? []).slice(0, 4).map(row)], { padding: 8, gap: 2 }) : null,\n ),\n );\n else if (view === \"messages\")\n content = h(\n RN.View,\n { key: \"messages\", style: { flex: 1, backgroundColor: p.bg } },\n h(\n RN.ScrollView,\n { ref: scroll, style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 12 } },\n bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }),\n !chat.loaded ? k.muted(\"Loading…\") : null,\n ...(thread?.messages ?? []).map((m) => bubble(m)),\n pending ? bubble(pending, true) : null,\n thread?.conversation?.status === \"solved\" && !pending ? k.muted(\"This conversation is closed. Write to start a new one.\", { textAlign: \"center\" }) : null,\n ),\n h(\n RN.View,\n { style: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 10, gap: 8 } },\n chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,\n needEmail\n ? k.field({ value: email, onChange: setEmail, placeholder: \"Your email (optional), so we can follow up\", email: true, max: 200, style: { borderWidth: emailOk ? 0 : 1, borderColor: p.danger, borderRadius: 12, backgroundColor: canvas } })\n : null,\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, borderWidth: 1, borderColor: p.line, borderRadius: 22, paddingVertical: 5, paddingRight: 5, paddingLeft: 16, backgroundColor: p.bg } },\n k.field({ value: body, onChange: setBody, placeholder: \"Write a message…\", multiline: true, max: 4000, style: { flex: 1, minHeight: 34, maxHeight: 120, borderWidth: 0, paddingHorizontal: 0, paddingVertical: 7, backgroundColor: \"transparent\" } }),\n h(\n RN.Pressable,\n {\n onPress: () => void send(),\n disabled: !body.trim() || !!pending || !emailOk,\n accessibilityRole: \"button\",\n accessibilityLabel: \"Send\",\n style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\", backgroundColor: !body.trim() || !!pending || !emailOk ? p.line : p.accent },\n },\n glyph(\"up\", !body.trim() || !!pending || !emailOk ? p.muted : ink, 18),\n ),\n ),\n ),\n );\n else if (view === \"help\") {\n const groups = new Map<string, ArticleSummary[]>();\n for (const a of arts.list ?? []) groups.set(a.collection, [...(groups.get(a.collection) ?? []), a]);\n content = h(\n RN.ScrollView,\n { key: \"help\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { padding: 16, gap: 12 }, keyboardShouldPersistTaps: \"handled\" },\n search,\n arts.list === null ? k.muted(\"Loading…\") : null,\n arts.list?.length === 0\n ? h(RN.View, { style: { gap: 10, alignItems: \"center\", paddingVertical: 24 } }, k.muted(query.trim() ? `Nothing found for “${query.trim()}”.` : \"No help articles yet.\"), k.btn(\"Send us a message\", \"primary\", () => setView(\"messages\")))\n : null,\n ...(query.trim()\n ? arts.list?.length\n ? [card((arts.list ?? []).map(row), { padding: 8 })]\n : []\n : [...groups].map(([name, items]) => h(RN.View, { key: name, style: { gap: 6 } }, k.muted(`${name} · ${items.length}`, { fontSize: 12, fontWeight: \"600\", paddingHorizontal: 2 }), card(items.map(row), { padding: 8 })))),\n );\n } else\n content = h(\n RN.ScrollView,\n { key: `a-${view.article}`, style: { flex: 1 }, contentContainerStyle: { padding: 16, paddingBottom: 32 } },\n h(ArticleView, { client, p, id: view.article, onAsk: () => setView(\"messages\") }),\n );\n\n const current = typeof view === \"string\" ? view : \"help\";\n const tab = (v: \"home\" | \"messages\" | \"help\", name: string, icon: keyof typeof GLYPH, badge = 0) =>\n h(\n RN.Pressable,\n { key: v, onPress: () => setView(v), accessibilityRole: \"tab\", accessibilityState: { selected: current === v }, style: { flex: 1, alignItems: \"center\", paddingTop: 8, paddingBottom: 6, gap: 3 } },\n glyph(icon, current === v ? p.accent : p.muted, 22),\n k.text(name, { fontSize: 12, fontWeight: \"600\", color: current === v ? p.accent : p.muted }),\n badge ? h(RN.View, { style: { position: \"absolute\", top: 4, right: \"28%\", minWidth: 18, height: 18, borderRadius: 9, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\" } }, k.text(String(Math.min(badge, 9)), { color: \"#fff\", fontSize: 11, fontWeight: \"700\" })) : null,\n );\n // The head: on Home in the accent with the team's mark, in the chat with the reply time, in Help plain.\n const onHome = view === \"home\";\n const headFg = onHome ? ink : p.fg;\n const head = h(\n RN.View,\n { key: \"head\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 10, paddingLeft: 16, paddingRight: 12, paddingTop: 16, paddingBottom: 12, backgroundColor: onHome ? p.accent : p.bg, borderBottomWidth: onHome ? 0 : 1, borderBottomColor: p.line } },\n typeof view !== \"string\"\n ? h(RN.Pressable, { key: \"back\", onPress: () => setView(\"help\"), accessibilityRole: \"button\", hitSlop: 10 }, k.text(\"‹ All articles\", { color: p.accent, fontWeight: \"600\" }))\n : view === \"help\"\n ? null\n : teamMark(title, onHome ? ink : p.accent, onHome ? p.accent : ink, onHome ? 28 : 36),\n h(\n RN.View,\n { style: { flex: 1, minWidth: 0 } },\n typeof view !== \"string\" ? null : h(RN.Text, { accessibilityRole: \"header\", numberOfLines: 1, style: { color: headFg, fontSize: 17, fontWeight: \"700\" } }, view === \"help\" ? \"Help\" : title),\n view === \"messages\" ? k.muted(reply, { fontSize: 12 }) : null,\n ),\n h(RN.Pressable, { onPress: close, accessibilityRole: \"button\", accessibilityLabel: \"Close\", hitSlop: 12, style: { width: 32, height: 32, borderRadius: 10, alignItems: \"center\", justifyContent: \"center\" } }, glyph(\"cross\", onHome ? ink : p.muted, 18)),\n );\n return h(\n RN.Modal,\n { visible: true, animationType: \"slide\", presentationStyle: \"pageSheet\", onRequestClose: close },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: p.bg } },\n head,\n content,\n h(\n RN.View,\n { key: \"tabs\", accessibilityRole: \"tablist\", style: { flexDirection: \"row\", borderTopWidth: 1, borderTopColor: p.line, paddingHorizontal: 8, paddingBottom: 22, backgroundColor: p.bg } },\n tab(\"home\", \"Home\", \"home\"),\n tab(\"messages\", \"Messages\", \"chat\", view === \"messages\" ? 0 : chat.unseen.length),\n showHelp ? tab(\"help\", \"Help\", \"help\") : null,\n ),\n ),\n );\n};\n\nexport const MRRocketMessenger = ({ client, appearance, options: given = {} }: { client: MRRocketClient; appearance?: NativeAppearance; options?: NativeMessengerOptions }) => {\n // The look from MRRocket › Support › Messenger under what the app passes.\n const [look, setLook] = useState<MessengerLook | null>(null);\n useEffect(() => {\n const ctrl = new AbortController();\n void client.ready.then(() =>\n client\n .api()\n ?.messengerLook(ctrl.signal)\n .then(setLook)\n .catch(() => undefined),\n );\n return () => ctrl.abort();\n }, [client]);\n const defined = Object.fromEntries(Object.entries(given).filter(([, v]) => v !== undefined)) as NativeMessengerOptions;\n const options: NativeMessengerOptions = look\n ? {\n title: look.title,\n greeting: look.greeting,\n replyTime: look.replyTime,\n launcher: look.appLauncher ?? false,\n position: look.position,\n label: look.label,\n help: look.help,\n preview: look.preview,\n askEmail: look.askEmail,\n haptics: look.sound,\n ...defined,\n }\n : given;\n const p = usePalette({ theme: appearance?.theme ?? look?.theme, accent: appearance?.accent ?? look?.accent });\n const k = kit(p);\n const open = messengerOpen.useOpen();\n const [view, setViewState] = useState<MsgView>(msgView);\n const [banner, setBanner] = useState<ChatMessage | null>(null);\n useEffect(() => {\n if (open) setViewState(msgView);\n }, [open]);\n const setView = (v: MsgView) => {\n msgView = v;\n setViewState(v);\n };\n const chat = useChat(client, options, open, view);\n\n // A new answer while closed: a banner at the top for a few seconds (tap to open the chat).\n const latest = chat.unseen.at(-1);\n useEffect(() => {\n if (!latest || open || options.preview === false) return;\n setBanner(latest);\n const t = setTimeout(() => setBanner(null), 6000);\n return () => clearTimeout(t);\n }, [latest, open, options.preview]);\n useEffect(() => {\n if (open) setBanner(null);\n }, [open]);\n\n const unseen = chat.unseen.length;\n const ink = inkOn(p.accent);\n const label = options.label?.trim() ?? \"\";\n const side = options.position === \"bottom-left\" ? { left: 20 } : { right: 20 };\n const launcher = options.launcher\n ? h(\n RN.Pressable,\n {\n key: \"launcher\",\n onPress: () => openAt(unseen ? \"messages\" : \"home\"),\n accessibilityRole: \"button\",\n accessibilityLabel: unseen ? `Open chat, ${unseen} new` : \"Open chat\",\n style: {\n position: \"absolute\",\n ...side,\n bottom: 34,\n height: label ? 50 : 56,\n minWidth: label ? 0 : 56,\n paddingHorizontal: label ? 18 : 0,\n borderRadius: 28,\n flexDirection: \"row\",\n gap: 8,\n backgroundColor: p.accent,\n alignItems: \"center\",\n justifyContent: \"center\",\n shadowColor: p.accent,\n shadowOpacity: 0.4,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n elevation: 6,\n },\n },\n glyph(\"chat\", ink, label ? 20 : 26),\n label ? k.text(label, { color: ink, fontWeight: \"700\" }) : null,\n unseen\n ? h(RN.View, { style: { position: \"absolute\", top: -2, right: -2, minWidth: 20, height: 20, borderRadius: 10, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\", borderWidth: 2, borderColor: p.bg } }, k.text(String(Math.min(unseen, 9)), { color: \"#fff\", fontSize: 11, fontWeight: \"700\" }))\n : null,\n )\n : null;\n const toast = banner\n ? h(\n RN.Pressable,\n {\n key: \"banner\",\n onPress: () => openAt(\"messages\"),\n accessibilityRole: \"button\",\n accessibilityLiveRegion: \"polite\",\n style: { position: \"absolute\", top: 54, left: 16, right: 16, flexDirection: \"row\", alignItems: \"flex-start\", gap: 12, backgroundColor: p.bg, borderRadius: 18, padding: 14, borderWidth: 1, borderColor: p.line, shadowColor: \"#000\", shadowOpacity: 0.16, shadowRadius: 18, shadowOffset: { width: 0, height: 8 }, elevation: 8 },\n },\n teamMark(options.title ?? \"Chat with us\", p.accent, ink),\n h(\n RN.View,\n { style: { flex: 1, gap: 2 } },\n k.muted(`${whoLabel[banner.from]}${unseen > 1 ? ` · ${unseen} new` : \"\"}`, { fontWeight: \"600\", fontSize: 12 }),\n h(RN.Text, { numberOfLines: 3, style: { color: p.fg, fontSize: 15 } }, banner.body),\n ),\n )\n : null;\n if (!launcher && !toast && !open) return null;\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", top: 0, left: 0, right: 0, bottom: 0 } },\n launcher,\n toast,\n open ? h(MessengerSheet, { client, p, o: options, chat, view, setView }) : null,\n );\n};\n"],"mappings":"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","names":["import_react","h","h","clip","text","h","RN","h","import_react","RN","text","h","RN","text"]}
1
+ {"version":3,"sources":["../../src/native/index.tsx","../../src/core.ts","../../src/api-client.ts","../../src/batch.ts","../../src/errors.ts","../../src/flows.ts","../../src/rage.ts","../../src/native/recorder.ts","../../src/referral.ts","../../src/native/client.ts","../../src/native/flows-view.ts","../../src/native/platform.ts","../../src/native/widgets-view.ts"],"sourcesContent":["/**\n * `@mrrocket/sdk/react-native`: the MRRocket SDK for React Native and Expo apps.\n *\n * // app/_layout.tsx (Expo Router)\n * import { MRRocketProvider, useExpoRouterTracking } from \"@mrrocket/sdk/react-native\";\n *\n * function Screens() {\n * useExpoRouterTracking();\n * return <Stack />;\n * }\n *\n * export default function RootLayout() {\n * return (\n * <MRRocketProvider apiKey=\"mrr_pub_…\">\n * <Screens />\n * </MRRocketProvider>\n * );\n * }\n *\n * No DOM, no \"use client\", no session recorder: Metro bundles it as is. See the README for what it sends.\n */\nimport { type ReactNode, createContext, createElement, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { type CockpitConfig, SDK_VERSION, type VariantId } from \"../core\";\nimport type { CancelFlowOptions, CancelFlowResult } from \"../flows\";\nimport { type KeyValueStorage, type MRRocketClient, type MRRocketOptions, activeRouteName, createClient } from \"./client\";\nimport { MRRocketFlows, type NativeAppearance } from \"./flows-view\";\nimport { nativeDeps, optionalModules } from \"./platform\";\nimport { type Measurable, maskedViews } from \"./recorder\";\nimport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, type NativeFeedbackOptions, type NativeMessengerOptions, useFeedback, useMessenger } from \"./widgets-view\";\n\nexport type { AppContext, CockpitConfig, FlagConfig, VariantId } from \"../core\";\nexport type { CancelFlowConfig, CancelFlowOptions, CancelFlowResult, CancelOffer, FlowView, InAppMessage, OnboardingFlow, OnboardingStep } from \"../flows\";\nexport { MRRocketFlows, type NativeAppearance };\nexport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, useFeedback, useMessenger, type NativeFeedbackOptions, type NativeMessengerOptions };\nexport type { ChatMessage, ChatThread, FeedbackPost, SurveyDefinition } from \"../api-client\";\nexport type { KeyValueStorage, MRRocketClient, MRRocketOptions, NativeConsent, NativePushResult, NativePushStatus, RegisterForPushOptions } from \"./client\";\nexport { SDK_VERSION, activeRouteName };\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\nconst RN = require(\"react-native\") as { View: (props: Record<string, unknown>) => ReactNode };\n\n/**\n * Hides what it wraps in session recordings: its area is painted black on every frame before the frame is stored. Use\n * it for anything private on screen (balances, addresses, messages). Text fields need no wrapper: nothing is recorded\n * while the keyboard is open.\n *\n * <MRRocketMask><Text>{iban}</Text></MRRocketMask>\n */\nexport const MRRocketMask = ({ children, style }: { children?: ReactNode; style?: unknown }) => {\n const ref = useRef<Measurable | null>(null);\n useEffect(() => {\n maskedViews.add(ref);\n return () => {\n maskedViews.delete(ref);\n };\n }, []);\n // collapsable: false keeps the view on Android, so it can be measured.\n return createElement(RN.View, { ref, collapsable: false, style }, children);\n};\n\nlet shared: MRRocketClient | null = null;\nlet sharedKey = \"\";\n\n/**\n * The SDK's client outside React (a background task, a store, an API layer): the one the provider made, or a new one.\n * One client per app; a second call returns the first.\n */\nexport const createMRRocket = (options: MRRocketOptions & { storage?: KeyValueStorage | null }): MRRocketClient => {\n if (shared) {\n if (sharedKey !== options.apiKey) console.warn(\"[MRRocket] The SDK is already running with another key; keeping the first one.\");\n return shared;\n }\n const { storage, ...rest } = options;\n const deps = nativeDeps({ storage });\n shared = createClient(rest, deps);\n sharedKey = options.apiKey;\n if (options.debug) console.log(\"[MRRocket] optional modules\", JSON.stringify(optionalModules()));\n return shared;\n};\n\n/** The running client, or null before the provider (or createMRRocket) started it. */\nexport const getMRRocket = () => shared;\n\nconst Ctx = createContext<MRRocketClient | null>(null);\n\nexport interface MRRocketProviderProps extends Partial<MRRocketOptions> {\n /** The product's public key (MRRocket › Settings › Products), the same as on the website. */\n apiKey: string;\n /** A storage with AsyncStorage's shape instead of AsyncStorage (MMKV, SecureStore); null keeps everything in memory. */\n storage?: KeyValueStorage | null;\n /** A client you made with createMRRocket; the other props are then ignored. */\n client?: MRRocketClient;\n /**\n * Draw the cancel flow, onboarding and in-app messages (default true). False: draw `client.flows` yourself, or\n * place `<MRRocketFlows flows={client.flows} />` where you want it.\n */\n flows?: boolean;\n /** The look of those dialogs and the widgets: `{ theme: \"light\" | \"dark\" | \"auto\", accent: \"#0f766e\" }`. */\n appearance?: NativeAppearance;\n /** Show the live in-app survey MRRocket picks for the person, a few seconds after start (default true). */\n surveys?: boolean;\n /** The chat with your team, opened with `useMessenger().open()`; `{ launcher: true }` adds a round button. False: none. */\n messenger?: NativeMessengerOptions | false;\n /** The feedback sheet opened with `useFeedback().open()` (`{ title }`). False: none. */\n feedback?: NativeFeedbackOptions | false;\n /**\n * Taps for Heatmaps (default true). The provider then wraps the app in one `View` with `flex: 1` to see them; false\n * leaves the app as it is.\n */\n heatmaps?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Put it once around your app (Expo Router: app/_layout.tsx; React Navigation: around the NavigationContainer). It\n * starts the SDK: lifecycle events, the event queue, flags and experiments, error capture. Changing `consent` later\n * calls setConsent.\n */\nexport const MRRocketProvider = ({ client: given, children, consent, flows = true, appearance, surveys = true, messenger = {}, feedback = {}, heatmaps = true, ...options }: MRRocketProviderProps) => {\n const [client] = useState(() => given ?? createMRRocket({ ...options, consent }));\n useEffect(() => {\n if (consent) client.setConsent(consent);\n }, [client, consent]);\n // The person's answer to recordings can change later (a settings switch): the prop follows it.\n useEffect(() => {\n if (options.replay !== undefined) client.setReplay(options.replay);\n }, [client, options.replay]);\n // Taps for Heatmaps: a touch that ends near where it started within half a second, never a scroll or a drag.\n const start = useRef<{ x: number; y: number; t: number } | null>(null);\n const touch = (e: { nativeEvent: { pageX?: number; pageY?: number; changedTouches?: ArrayLike<{ pageX: number; pageY: number }> } }, end: boolean) => {\n // Phones give pageX on the event; React Native Web passes the browser's TouchEvent, with the point in changedTouches.\n const n = e.nativeEvent;\n const x = n.pageX ?? n.changedTouches?.[0]?.pageX;\n const y = n.pageY ?? n.changedTouches?.[0]?.pageY;\n if (x === undefined || y === undefined) return;\n if (!end) start.current = { x, y, t: Date.now() };\n else if (start.current && Math.hypot(x - start.current.x, y - start.current.y) < 10 && Date.now() - start.current.t < 500) client.tap(x, y);\n };\n return createElement(\n Ctx.Provider,\n { value: client },\n heatmaps\n ? createElement(RN.View, { style: { flex: 1 }, onTouchStartCapture: (e: never) => touch(e, false), onTouchEndCapture: (e: never) => touch(e, true) }, children)\n : children,\n flows ? createElement(MRRocketFlows, { flows: client.flows, appearance }) : null,\n surveys ? createElement(MRRocketSurveys, { client, appearance }) : null,\n feedback ? createElement(MRRocketFeedback, { client, appearance, options: feedback }) : null,\n messenger ? createElement(MRRocketMessenger, { client, appearance, options: messenger }) : null,\n );\n};\n\nconst useClient = () => {\n const c = useContext(Ctx);\n if (!c) throw new Error(\"MRRocket: wrap your app in <MRRocketProvider apiKey=…>.\");\n return c;\n};\n\n/** Re-renders when flags, the person or the consent change. */\nconst useVersion = (client: MRRocketClient) => useSyncExternalStore(client.subscribe, client.getVersion, client.getVersion);\n\n/**\n * `track`, `screen`, `identify`, `reset`, `setConsent`, `captureError`, `flush`, the visitor id, the consent and whether\n * flags and experiments have loaded.\n */\nexport const useMRRocket = () => {\n const client = useClient();\n useVersion(client);\n return {\n track: client.track,\n screen: client.screen,\n identify: client.identify,\n reset: client.reset,\n setConsent: client.setConsent,\n setReplay: client.setReplay,\n captureError: client.captureError,\n flush: client.flush,\n distinctId: client.getDistinctId(),\n consent: client.getConsent(),\n ready: client.isReady(),\n };\n};\n\n/**\n * The cancel flow built in MRRocket › Churn › Cancel flow. Call `open` from your Cancel button; the provider draws it.\n * MRRocket never changes the subscription: your `onCancel` and `onSave` do (RevenueCat, your server, the store's\n * subscription page).\n *\n * const cancelFlow = useCancelFlow();\n * <Button title=\"Cancel subscription\" onPress={() => cancelFlow.open({ customer: \"consumer\", onCancel: openStoreSubscriptions })} />\n */\nexport const useCancelFlow = (): { open: (options?: CancelFlowOptions) => Promise<CancelFlowResult> } => {\n const client = useClient();\n return { open: client.openCancelFlow };\n};\n\n/**\n * Push notifications from your Lifecycle journeys (needs `expo-notifications`). After sign-in (`identify`), call\n * `register()`: it asks the permission, gets the Expo push token and sends it to MRRocket. Sign-out (`reset`) takes the\n * token back on its own.\n *\n * const push = usePush();\n * useEffect(() => { if (user) void push.register(); }, [user]);\n */\nexport const usePush = (): { register: MRRocketClient[\"registerForPush\"]; unregister: MRRocketClient[\"unregisterForPush\"] } => {\n const client = useClient();\n return { register: client.registerForPush, unregister: client.unregisterForPush };\n};\n\n/** Starts an onboarding flow now (the first live one without an id), whatever its trigger. */\nexport const useOnboarding = (): { start: (id?: string) => boolean } => {\n const client = useClient();\n return { start: client.startOnboarding };\n};\n\n/** A feature flag from MRRocket › Build › Feature flags: true while it is on for this person; false while off, unknown or loading. */\nexport const useFlag = (key: string): boolean => {\n const client = useClient();\n useVersion(client);\n return client.getFlag(key);\n};\n\n/** The variant of a multivariate flag (\"control\", \"test\" …), or null while it is off. */\nexport const useFlagVariant = (key: string): string | null => {\n const client = useClient();\n useVersion(client);\n return client.getFlagVariant(key);\n};\n\n/**\n * The variant of an experiment this person sees (\"control\" until the config is known; the cached config is used on a\n * cold start, so the first screen is already stable). Records the exposure once per screen.\n */\nexport const useVariant = (key: string): VariantId => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const variant = client.peekVariant(key);\n useEffect(() => {\n if (config) client.expose(key, variant);\n }, [client, config, key, variant]);\n return variant;\n};\n\n/**\n * Copy MRRocket can change without an app update: the text published for `id` (a paywall's\n * `paywall.<placement>.headline`, `.body`, `.cta`), with this person's variant of a running text test on top,\n * the same rules as `<Text id>` on the web. Write your own words as `fallback`: they show while nothing is published\n * and on a first start before the config arrives. Records the exposure to every test that changes `id`, once per screen.\n *\n * const headline = useText(\"paywall.onboarding.headline\", \"Unlock everything\");\n * <Text style={styles.title}>{headline}</Text>\n */\nexport const useText = (id: string, fallback: string): string => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const text = client.peekText(id);\n const person = client.getDistinctId();\n useEffect(() => {\n if (config) client.exposeText(id);\n }, [client, config, id, person]);\n return text ?? fallback;\n};\n\ntype ExpoRouterModule = { usePathname: () => string };\nlet expoRouter: ExpoRouterModule | null | undefined;\nconst loadExpoRouter = (): ExpoRouterModule | null => {\n if (expoRouter !== undefined) return expoRouter;\n try {\n expoRouter = require(\"expo-router\") as ExpoRouterModule;\n } catch {\n expoRouter = null;\n }\n return expoRouter;\n};\nconst noPathname = () => undefined;\nlet routerWarned = false;\n\n/**\n * Screen views for Expo Router: one `$screen` per path (\"/settings\", \"/product/[id]\" as its real path). Call it in a\n * component inside both the router and MRRocketProvider, for example the root layout's child.\n */\nexport const useExpoRouterTracking = () => {\n const client = useClient();\n const router = loadExpoRouter();\n if (router === null && !routerWarned) {\n routerWarned = true;\n console.warn(\"[MRRocket] useExpoRouterTracking needs expo-router. With React Navigation use useNavigationTracking.\");\n }\n const pathname = (router?.usePathname ?? noPathname)();\n useEffect(() => {\n if (pathname) client.screen(pathname);\n }, [client, pathname]);\n};\n\n/**\n * Screen views for React Navigation: pass the result to the container's `onStateChange`, and call it once in `onReady`\n * with the root state, so the first screen counts too.\n *\n * const ref = useNavigationContainerRef();\n * const onStateChange = useNavigationTracking();\n * <NavigationContainer ref={ref} onReady={() => onStateChange(ref.getRootState())} onStateChange={onStateChange}>\n */\nexport const useNavigationTracking = () => {\n const client = useClient();\n return useCallback(\n (state: unknown) => {\n const name = activeRouteName(state);\n if (name) client.screen(name);\n },\n [client],\n );\n};\n","/**\n * The part of the SDK that runs anywhere: experiment config, variant assignment, preview links and event shapes.\n * No React, no browser APIs, so the server helper, the proxy helper and the client share it.\n */\nimport type { CancelFlowConfig, OnboardingFlow } from \"./flows\";\n\nexport type VariantId = string;\n\n/** This build of the SDK. Sent with the config request so MRRocket knows what the site runs (error tracking, flags). */\nexport const SDK_VERSION = \"0.12.0\";\n\n/** One variant of an experiment. `changes` replaces texts that the page marks with `<Text id>`. */\nexport interface VariantConfig {\n id: VariantId;\n /** Share of traffic, 0 to 1. The weights of an experiment add up to 1. */\n weight: number;\n changes?: Record<string, string>;\n /**\n * A redirect test: where this variant sends the visitor instead of the test's page (a path like \"/pricing-b\" or a\n * full address). Control has none and stays. SDK 0.7.0+.\n */\n url?: string;\n}\n\nexport interface ExperimentConfig {\n /** The experiment's key, the same as in Cockpit. */\n key: string;\n status: \"running\" | \"draft\" | \"stopped\";\n /** Control first. */\n variants: VariantConfig[];\n /** A winner that shipped: everyone gets it, and nobody is assigned anymore. */\n winner?: VariantId;\n /** A redirect test: the path of the page it runs on (\"/pricing\"). Visitors there are sent to their variant's `url`. */\n path?: string;\n}\n\n/** A page redirect set in MRRocket (Conversion › Landing pages › Redirect): everyone on `from` goes to `to`. SDK 0.7.0+. */\nexport interface RedirectConfig {\n /** A path of the site, like \"/old-pricing\". */\n from: string;\n /** A path or a full address. */\n to: string;\n}\n\nexport interface CockpitConfig {\n /** The product the public key belongs to. */\n project: string;\n experiments: ExperimentConfig[];\n /** The product's affiliate program: how many days a partner's referral is kept. Missing without a program. */\n referral?: { cookieDays: number };\n /** Session recordings: present only while the product records (Cockpit › Sessions). See `ReplayConfig`. */\n replay?: ReplayConfig;\n /** Feature flags of the product in Production (MRRocket › Build › Feature flags), evaluated by `useFlag` and `getFlag`. */\n flags?: FlagConfig[];\n /**\n * Published copy for texts the site marks (`<Text id>`, `data-ck-text`): a landing page's headline, subheadline and\n * button (`pricing.headline` …) and a paywall's (`paywall.<placement>.headline` …) as published in MRRocket. A\n * running test's variant changes them on top. Missing when nothing is published. SDK 0.5.0+.\n */\n texts?: Record<string, string>;\n /** The product's live cancel flow (MRRocket › Churn › Cancel flow), for `cancelFlow.open()`. SDK 0.7.0+. */\n cancelFlow?: CancelFlowConfig;\n /** The in-app steps of live onboarding flows (tours, checklists, modals). SDK 0.7.0+. */\n onboarding?: OnboardingFlow[];\n /** A live Lifecycle journey has in-app messages: signed-in people ask `/api/sdk/inapp` for theirs. SDK 0.7.0+. */\n messages?: boolean;\n /** Page redirects set in MRRocket; the SDK sends visitors on before the page shows (`redirectFor`). SDK 0.7.0+. */\n redirects?: RedirectConfig[];\n}\n\n/** One condition of a flag's audience, on a property of the person (`identify(id, props)`), the id or the page. */\nexport interface FlagCondition {\n /** \"Email\", \"Plan\", \"Country\", \"id\", \"path\" … Matched against the person's properties without regard to case. */\n property: string;\n op: \"is\" | \"is not\" | \"in\" | \"not in\" | \"≥\" | \"in cohort\";\n values: string[];\n}\n\n/** Users who match every condition, of whom `rollout` percent get the flag. No conditions: everyone. */\nexport interface FlagConditionSet {\n conditions: FlagCondition[];\n /** 0 to 100. */\n rollout: number;\n}\n\nexport interface FlagConfig {\n key: string;\n /** Off: everyone gets the off side. */\n on: boolean;\n /** The first set a person matches decides; none matched: off. */\n sets: FlagConditionSet[];\n /** Multivariate flags: the variants and their split in percent (control included). Missing for an on/off flag. */\n variants?: { key: string; split: number; payload?: string }[];\n}\n\n/** What a person is for flag conditions: their properties from identify(), their id and the page they are on. */\nexport type FlagPerson = Record<string, unknown>;\n\nconst propOf = (person: FlagPerson, name: string) => {\n const want = name.trim().toLowerCase();\n for (const [k, v] of Object.entries(person)) if (k.toLowerCase() === want) return v;\n return undefined;\n};\n\n/** `\"@acme.com\"` matches every address at that domain; anything else matches the whole value, without regard to case. */\nconst same = (actual: string, value: string) => {\n const a = actual.trim().toLowerCase();\n const v = value.trim().toLowerCase();\n return v.startsWith(\"@\") ? a.endsWith(v) : a === v;\n};\n\nconst matchesCondition = (c: FlagCondition, person: FlagPerson) => {\n // Cohorts live in MRRocket; a browser cannot know them, so a cohort condition never matches here.\n if (c.op === \"in cohort\") return false;\n const raw = propOf(person, c.property);\n const actual = raw === undefined || raw === null ? \"\" : String(raw);\n if (c.op === \"≥\") {\n const a = Number(actual);\n const b = Number(c.values[0]);\n return actual !== \"\" && Number.isFinite(a) && Number.isFinite(b) && a >= b;\n }\n const hit = actual !== \"\" && c.values.some((v) => same(actual, v));\n return c.op === \"is\" || c.op === \"in\" ? hit : !hit;\n};\n\n/**\n * The flag for one person: `false` (off), `true` (on, an on/off flag) or the variant's key (a multivariate flag). The\n * bucket is a stable hash of flag and person, so a person keeps their side as the rollout grows.\n */\nexport const evaluateFlag = (flag: FlagConfig, distinctId: string, person: FlagPerson = {}): boolean | string => {\n if (!flag.on) return false;\n const subject = { id: distinctId, ...person };\n const set = flag.sets.length ? flag.sets.find((s) => s.conditions.every((c) => matchesCondition(c, subject))) : { conditions: [], rollout: 100 };\n if (!set) return false;\n if (flagUnit(`${flag.key}:rollout:${distinctId}`) * 100 >= set.rollout) return false;\n if (!flag.variants?.length) return true;\n const u = flagUnit(`${flag.key}:variant:${distinctId}`) * 100;\n let acc = 0;\n for (const v of flag.variants) {\n acc += v.split;\n if (u < acc) return v.key;\n }\n return flag.variants[flag.variants.length - 1].key;\n};\n\n/** A flag of the config for this person; an unknown flag (or no config) is off. */\nexport const flagFor = (key: string, config: CockpitConfig | null, distinctId: string, person: FlagPerson = {}) => {\n const flag = config?.flags?.find((f) => f.key === key);\n return flag ? evaluateFlag(flag, distinctId, person) : false;\n};\n\n/** One JavaScript error as it goes over the wire to `POST /api/sdk/errors`. */\nexport interface ErrorReport {\n /** \"TypeError\", \"Error\" … */\n type: string;\n message: string;\n /** The raw stack, at most 8 KB. MRRocket parses it into frames. */\n stack?: string;\n /** \"onerror\" (uncaught), \"onunhandledrejection\" (a rejected promise nobody caught) or \"manual\" (captureError). */\n mechanism: \"onerror\" | \"onunhandledrejection\" | \"manual\";\n handled: boolean;\n url: string;\n ts: number;\n /** What happened just before: pages and clicks, newest last, at most 20. */\n crumbs?: { ts: number; type: \"navigation\" | \"click\" | \"lifecycle\"; message: string }[];\n /** Your release (a version or commit), from the provider's `release` prop. */\n release?: string;\n distinctId?: string;\n sessionId?: string;\n}\n\n/**\n * Session recordings of a product, from the config. Recording also needs the visitor's own replay consent\n * (`<CockpitProvider replay>` or `setConsent({ replay: true })`); without it nothing is recorded or buffered.\n */\nexport interface ReplayConfig {\n /**\n * Share of sessions uploaded from their start, 0 to 1 (default 0.1). The others keep only the last minute in\n * memory and upload it when something goes wrong: a JS error, a rage click, a `purchase…` or `checkout…` event.\n */\n sampleRate: number;\n}\n\n/**\n * What the SDK may send and store.\n * - \"cookieless\" (default): no cookie, no localStorage. Events go without a visitor id; the server counts visitors\n * with a hash of key, date, IP and user agent that changes every day.\n * - \"cookies\": a persistent `ck_id` cookie identifies the visitor across visits, `ck_sid` holds the session.\n * - \"off\": nothing is sent and nothing is stored.\n */\nexport type ConsentMode = \"cookieless\" | \"cookies\" | \"off\";\n\n/**\n * What `setConsent` takes: a mode as before, or the parts to change. `replay` is the separate consent for session\n * recordings (default false); it applies only while analytics is not \"off\".\n *\n * setConsent(\"cookies\");\n * setConsent({ replay: true });\n * setConsent({ analytics: \"cookieless\", replay: false });\n */\nexport type ConsentChoice = ConsentMode | { analytics?: ConsentMode; replay?: boolean };\n\n/** The campaign parameters the SDK reads from the landing URL. */\nexport const UTM_KEYS = [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_term\", \"utm_content\"] as const;\nexport type UtmKey = (typeof UTM_KEYS)[number];\n\n/** One event as it goes over the wire to `POST /api/sdk/events`. */\nexport interface CockpitEvent {\n event: string;\n /** The visitor. Missing in \"cookieless\" mode until identify(): the server then uses its daily visitor hash. */\n distinctId?: string;\n /** Ends after 30 minutes without an event. */\n sessionId?: string;\n props?: Record<string, unknown>;\n /** Milliseconds since the epoch. */\n ts: number;\n url?: string;\n /** `document.referrer` on the first page of a page load, the previous in-app URL after client-side navigation. */\n referrer?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_term?: string;\n utm_content?: string;\n /** The screen size in CSS pixels (points on a phone). */\n screen?: { w: number; h: number };\n /** The app that sent it (React Native only): MRRocket stores it with the event and fills OS and device from it. */\n app?: AppContext;\n}\n\n/** Where a React Native event comes from. Every field is optional except the platform; nothing identifies the person. */\nexport interface AppContext {\n /** \"ios\" or \"android\" (React Native's `Platform.OS`). */\n platform: string;\n /** The app's version, like \"1.4.0\" (`expo-application`'s `nativeApplicationVersion`). */\n appVersion?: string;\n /** The build number, like \"42\". */\n build?: string;\n /** The OS version, like \"17.4\". */\n osVersion?: string;\n /** The device model, like \"iPhone 15 Pro\" (`expo-device`). */\n deviceModel?: string;\n /** \"phone\", \"tablet\", \"desktop\" or \"tv\" when `expo-device` knows it. */\n deviceType?: string;\n /** The first preferred locale, like \"de-DE\". */\n locale?: string;\n}\n\n/** The query parameter that forces variants, for previews in Cockpit: `?ck_preview=pricing-annual:a,home-hero:control`. */\nexport const PREVIEW_PARAM = \"ck_preview\";\n/** Set when Cockpit embeds the page: nothing is tracked, so previews never count as visits. */\nexport const EMBED_PARAM = \"ck_embed\";\n/** The cookie that keeps a visitor in the same variant across visits. Only written in \"cookies\" mode. */\nexport const ID_COOKIE = \"ck_id\";\n/** The cookie that holds the session id in \"cookies\" mode. */\nexport const SESSION_COOKIE = \"ck_sid\";\n/** A session ends after this long without an event. */\nexport const SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\n/** The UTM parameters from a parameter lookup (`URLSearchParams.get` in a browser). Empty values are left out. */\nexport const utmFrom = (get: (name: string) => string | null | undefined): Partial<Record<UtmKey, string>> => {\n const out: Partial<Record<UtmKey, string>> = {};\n for (const key of UTM_KEYS) {\n const value = get(key)?.trim();\n if (value) out[key] = value.slice(0, 150);\n }\n return out;\n};\n\n/** The UTM parameters of a query string, like `\"?utm_source=x\"`. Empty values are left out. */\nexport const readUtm = (search: string): Partial<Record<UtmKey, string>> => {\n const params = new URLSearchParams(search);\n return utmFrom((k) => params.get(k));\n};\n\n/**\n * The query parameters of a URL or query string, without `URLSearchParams` (React Native's is incomplete): `+` is a\n * space, values are percent-decoded, the first of a repeated name wins.\n */\nexport const parseQuery = (url: string): Record<string, string> => {\n const out: Record<string, string> = {};\n const q = url.split(\"#\")[0];\n const at = q.indexOf(\"?\");\n if (at < 0) return out;\n const dec = (s: string) => {\n try {\n return decodeURIComponent(s.replace(/\\+/g, \" \"));\n } catch {\n return s;\n }\n };\n for (const pair of q.slice(at + 1).split(\"&\")) {\n if (!pair) continue;\n const eq = pair.indexOf(\"=\");\n const k = dec(eq < 0 ? pair : pair.slice(0, eq));\n if (k && !(k in out)) out[k] = eq < 0 ? \"\" : dec(pair.slice(eq + 1));\n }\n return out;\n};\n\n/** FNV-1a, 32 bit, mapped to [0, 1). Stable across server and browser. */\nexport const hashUnit = (input: string) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0) / 4294967296;\n};\n\n/**\n * FNV-1a with murmur3's finalizer, mapped to [0, 1): ids that differ only at the end (\"user-1\", \"user-2\") still spread\n * evenly, so a 30 % rollout reaches about 30 % of people. Flags only; experiments keep `hashUnit` so nobody switches.\n */\nexport const flagUnit = (input: string) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n h = Math.imul(h, 0xc2b2ae35);\n h ^= h >>> 16;\n return (h >>> 0) / 4294967296;\n};\n\n/** The variant a visitor sees: a shipped winner, control while the experiment does not run, else a stable bucket by visitor. */\nexport const assign = (experiment: ExperimentConfig, distinctId: string): VariantId => {\n const control = experiment.variants[0]?.id ?? \"control\";\n if (experiment.winner) return experiment.winner;\n if (experiment.status !== \"running\") return control;\n const u = hashUnit(`${experiment.key}:${distinctId}`);\n let acc = 0;\n for (const v of experiment.variants) {\n acc += v.weight;\n if (u < acc) return v.id;\n }\n return experiment.variants[experiment.variants.length - 1]?.id ?? control;\n};\n\n/** `\"a:b,c:d\"` → `{ a: \"b\", c: \"d\" }`. Ignores anything malformed. */\nexport const parsePreview = (value: string | string[] | null | undefined): Record<string, VariantId> => {\n const raw = Array.isArray(value) ? value[0] : value;\n if (!raw) return {};\n const out: Record<string, VariantId> = {};\n for (const pair of raw.split(\",\")) {\n const [key, variant] = pair.split(\":\");\n if (key && variant) out[key.trim()] = variant.trim();\n }\n return out;\n};\n\n/** A link that shows one variant of a page, for example in Cockpit's preview frames. */\nexport const previewHref = (url: string, forced: Record<string, VariantId>, embed = true) => {\n const [path, query = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(query);\n const value = Object.entries(forced)\n .map(([k, v]) => `${k}:${v}`)\n .join(\",\");\n if (value) params.set(PREVIEW_PARAM, value);\n if (embed) params.set(EMBED_PARAM, \"1\");\n return `${path}?${params.toString()}`;\n};\n\n/** The variant for one experiment, from a forced preview first, then the config. Unknown experiments get control. */\n/** The experiments whose variants change the text `id`: showing that text is an exposure to them. */\nexport const experimentsOfText = (config: CockpitConfig | null, id: string) =>\n (config?.experiments ?? []).filter((e) => e.variants.some((v) => v.changes && id in v.changes)).map((e) => e.key);\n\nexport const resolveVariant = (key: string, config: CockpitConfig | null, distinctId: string, preview: Record<string, VariantId>): VariantId => {\n if (preview[key]) return preview[key];\n const experiment = config?.experiments.find((e) => e.key === key);\n return experiment ? assign(experiment, distinctId) : \"control\";\n};\n\n/**\n * Every text change that applies to this visitor: the published texts first, then each experiment's in config order.\n * Control keeps the published (or the page's own) words, so only a non-control variant (assigned, forced in a preview,\n * or a shipped winner) changes them further.\n */\nexport const textChanges = (config: CockpitConfig | null, distinctId: string, preview: Record<string, VariantId>) => {\n const out: Record<string, string> = { ...(config?.texts ?? {}) };\n for (const experiment of config?.experiments ?? []) {\n const id = resolveVariant(experiment.key, config, distinctId, preview);\n if (id === (experiment.variants[0]?.id ?? \"control\")) continue;\n Object.assign(out, experiment.variants.find((v) => v.id === id)?.changes ?? {});\n }\n return out;\n};\n\n/**\n * The query parameter a redirect test adds to the variant's address (`ck_x=<test>:<variant>`): the page there records\n * the exposure and takes it out of the address bar. It also keeps that page from redirecting again.\n */\nexport const EXPOSURE_PARAM = \"ck_x\";\n\n/** What `redirectFor` decided: go to `to`, and/or the redirect test this page belongs to and the visitor's variant. */\nexport interface RedirectDecision {\n /** Where to send the visitor now. Missing for control, which stays on the page. */\n to?: string;\n /** The redirect test, while it runs: record `$exposure` for it (on this page for control, on `to` otherwise). */\n experiment?: string;\n variant?: VariantId;\n}\n\nconst pathOf = (p: string) => p.replace(/\\/+$/, \"\") || \"/\";\n\n/**\n * Where a page sends the visitor, before it shows: a page redirect set in MRRocket first, else a redirect test that runs\n * on this path (the visitor's variant, by the same stable assignment as every test). Null when nothing applies.\n *\n * - The new address keeps the page's query (UTM parameters) and its hash; a running test adds `ck_x=<test>:<variant>`,\n * so the page it lands on records the exposure (and never redirects again).\n * - `distinctId` null (no stable id, as on a server without the `ck_id` cookie): running tests are left to the browser,\n * page redirects and shipped winners still apply.\n * - A redirect to the page itself is ignored.\n */\nexport const redirectFor = (config: CockpitConfig | null, href: string, distinctId: string | null, preview: Record<string, VariantId> = {}): RedirectDecision | null => {\n if (!config) return null;\n let here: URL;\n try {\n here = new URL(href);\n } catch {\n return null;\n }\n if (here.searchParams.has(EXPOSURE_PARAM)) return null;\n const path = pathOf(here.pathname);\n const go = (to: string, mark?: string) => {\n let t: URL;\n try {\n t = new URL(to, here);\n } catch {\n return undefined;\n }\n if (!/^https?:$/.test(t.protocol) || (t.origin === here.origin && pathOf(t.pathname) === path)) return undefined;\n here.searchParams.forEach((v, k) => {\n if (!t.searchParams.has(k)) t.searchParams.set(k, v);\n });\n if (mark) t.searchParams.set(EXPOSURE_PARAM, mark);\n if (!t.hash) t.hash = here.hash;\n return t.href;\n };\n for (const r of config.redirects ?? []) {\n const to = r.from && pathOf(r.from) === path ? go(r.to) : undefined;\n if (to) return { to };\n }\n for (const e of config.experiments) {\n if (!e.path || pathOf(e.path) !== path) continue;\n const running = e.status === \"running\" && !e.winner;\n if (running && distinctId === null && !preview[e.key]) return null;\n const variant = resolveVariant(e.key, config, distinctId ?? \"\", preview);\n const url = e.variants.find((v) => v.id === variant)?.url;\n const to = url ? go(url, running ? `${e.key}:${variant}` : undefined) : undefined;\n return running ? { to, experiment: e.key, variant } : to ? { to } : null;\n }\n return null;\n};\n\n/** The test and variant a redirect test's `ck_x` names, when the config has them; null otherwise. */\nexport const exposureFrom = (config: CockpitConfig | null, value: string | null | undefined) => {\n const [key, variant] = (value ?? \"\").split(\":\");\n const e = config?.experiments.find((x) => x.key === key);\n return e && e.variants.some((v) => v.id === variant) ? { experiment: key, variant } : null;\n};\n\n/**\n * The MRRocket API host from `NEXT_PUBLIC_MRROCKET_HOST`. Written as a literal property access on purpose: Next.js\n * inlines `process.env.NEXT_PUBLIC_*` at build time, in the browser bundle and in the server bundle (also on\n * Cloudflare Workers), and only replaces the literal form. Without a bundler (or a `process`) it is undefined.\n */\nexport const envHost = (): string | undefined => {\n try {\n return process.env.NEXT_PUBLIC_MRROCKET_HOST || undefined;\n } catch {\n return undefined;\n }\n};\n\n/** The public key from `NEXT_PUBLIC_MRROCKET_KEY`, the default for the `apiKey` prop. Same literal-access rule as `envHost`. */\nexport const envKey = (): string | undefined => {\n try {\n return process.env.NEXT_PUBLIC_MRROCKET_KEY || undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Where the API lives: the `host` prop, else `NEXT_PUBLIC_MRROCKET_HOST`, else \"\" (the page's own origin, which is how\n * MRRocket's own demo pages call it). Without a trailing slash.\n */\nexport const resolveHost = (host?: string) => (host ?? envHost() ?? \"\").trim().replace(/\\/+$/, \"\");\n\n/** A random visitor id. */\nexport const newDistinctId = () =>\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto ? crypto.randomUUID() : `ck_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n","/**\n * The SDK's fetch client and the shapes it reads, without React, so the script tag's widgets (src/script) use it too.\n * `./api` re-exports all of it with the `useApi` hook.\n */\nexport type PostStatus = \"review\" | \"planned\" | \"progress\" | \"shipped\";\n\nexport const STATUS_LABEL: Record<PostStatus, string> = {\n review: \"Under review\",\n planned: \"Planned\",\n progress: \"In progress\",\n shipped: \"Shipped\",\n};\n\nexport interface FeedbackBoardInfo {\n id: string;\n label: string;\n}\n\nexport interface FeedbackPost {\n id: string;\n title: string;\n body: string;\n board: string;\n status: PostStatus;\n votes: number;\n comments: number;\n voted: boolean;\n createdAt: string;\n /** \"Lena K.\", \"Anonymous\" or \"Team\". Missing from servers before SDK 0.6. */\n author?: string;\n}\n\n/** The product's public face for the board's header. */\nexport interface FeedbackProduct {\n name: string;\n logo: string | null;\n /** The domain's favicon, tried when `logo` does not load. Older servers leave it out. */\n logoFallback?: string | null;\n}\n\nexport interface FeedbackList {\n boards: FeedbackBoardInfo[];\n posts: FeedbackPost[];\n product?: FeedbackProduct;\n}\n\nexport interface FeedbackRoadmap {\n /** `review` (Backlog) comes from servers of SDK 0.6 on. */\n columns: { review?: FeedbackPost[]; planned: FeedbackPost[]; progress: FeedbackPost[]; shipped: FeedbackPost[] };\n}\n\nexport interface ChangelogEntry {\n id: string;\n title: string;\n body: string;\n publishedAt: string;\n}\n\nexport interface FeedbackComment {\n id: string;\n body: string;\n author: string;\n isTeam: boolean;\n postedAt: string;\n}\n\nexport type SurveyQuestionKind = \"nps\" | \"rating\" | \"single\" | \"multi\" | \"text\";\n\nexport interface SurveyQuestion {\n key: string;\n kind: SurveyQuestionKind;\n title: string;\n description?: string;\n required: boolean;\n options?: string[];\n scale?: number;\n low?: string;\n high?: string;\n placeholder?: string;\n}\n\nexport interface SurveyDefinition {\n id: string;\n name: string;\n type: string;\n thanks: string;\n questions: SurveyQuestion[];\n}\n\nexport type SurveyAnswer = number | string | string[];\n\n/** One message of the messenger's chat. \"visitor\" is the person on the site; the rest come from the product's team. */\nexport interface ChatMessage {\n id: string;\n from: \"visitor\" | \"team\" | \"ai\" | \"auto\";\n body: string;\n at: string;\n /** Help articles an answer drew on (servers from SDK 0.9 on). */\n articles?: { id: string; title: string }[];\n}\n\n/** A published help article in a list (the messenger's Help tab). */\nexport interface ArticleSummary {\n id: string;\n title: string;\n collection: string;\n excerpt: string;\n updatedAt: string;\n}\n\n/** A run of text inside an article block. Links are http(s), mailto or tel only. */\nexport interface ArticleSpan {\n text: string;\n href?: string;\n bold?: boolean;\n italic?: boolean;\n code?: boolean;\n}\n\n/** An article's content as blocks, written with textContent (never parsed as HTML). */\nexport type ArticleBlock =\n | { type: \"h2\" | \"h3\" | \"p\" | \"quote\"; spans: ArticleSpan[] }\n | { type: \"ul\" | \"ol\"; items: ArticleSpan[][] }\n | { type: \"code\"; text: string }\n | { type: \"hr\" };\n\nexport interface Article {\n id: string;\n title: string;\n collection: string;\n updatedAt: string;\n blocks: ArticleBlock[];\n}\n\n/** The messenger's look and texts as set in MRRocket › Support › Messenger (servers from SDK 0.9 on). */\nexport interface MessengerLook {\n accent: string;\n theme: \"light\" | \"dark\" | \"auto\";\n position: \"bottom-right\" | \"bottom-left\";\n title: string;\n greeting: string;\n label: string;\n /** How soon the team usually answers (MRRocket from 0.10; older servers leave it out). */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** A round chat button in the app (React Native) too. */\n appLauncher?: boolean;\n help: boolean;\n sound: boolean;\n preview: boolean;\n askEmail: boolean;\n}\n\n/** The line under \"Send us a message\" and in the chat's head. */\nexport const replyLine = (t: MessengerLook[\"replyTime\"]) =>\n t === \"minutes\" ? \"We usually reply in a few minutes\" : t === \"day\" ? \"We usually reply within a day\" : \"We usually reply in a few hours\";\n\n/** Black or white, whichever reads better on the accent (a light custom color gets dark text). */\nexport const inkOn = (hex: string) => {\n const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex);\n if (!m) return \"#ffffff\";\n const [r, g, b] = [m[1], m[2], m[3]].map((x) => {\n const c = parseInt(x, 16) / 255;\n return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.45 ? \"#111214\" : \"#ffffff\";\n};\n\n/** The visitor's newest chat (open or closed) and its messages. */\nexport interface ChatThread {\n conversation: { id: string; status: \"open\" | \"solved\" } | null;\n messages: ChatMessage[];\n /** The visitor gave an email already: the messenger stops asking. */\n hasEmail: boolean;\n}\n\nexport class ApiError extends Error {\n status: number;\n constructor(message: string, status: number) {\n super(message);\n this.status = status;\n }\n}\n\ninterface Conn {\n host: string;\n apiKey: string;\n distinctId: string;\n user?: { id?: string; [key: string]: unknown };\n}\n\n// Not URLSearchParams: React Native's lacks `set` in older versions, and the apps use this client too.\nconst qs = (params: Record<string, string | undefined>) =>\n Object.entries(params)\n .filter((e): e is [string, string] => !!e[1])\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n\nconst call = async <T>(url: string, init: RequestInit | undefined, signal?: AbortSignal): Promise<T> => {\n let res: Response;\n try {\n res = await fetch(url, {\n ...init,\n signal,\n headers: init?.body ? { \"content-type\": \"application/json\" } : undefined,\n });\n } catch (e) {\n if ((e as Error).name === \"AbortError\") throw e;\n throw new ApiError(\"Could not reach the server. Check your connection and try again.\", 0);\n }\n if (!res.ok) {\n let detail = \"\";\n try {\n detail = ((await res.json()) as { error?: string }).error ?? \"\";\n } catch {\n // Not JSON; the status is enough.\n }\n throw new ApiError(detail || (res.status === 429 ? \"Too many requests. Try again in a minute.\" : \"Something went wrong. Please try again.\"), res.status);\n }\n return (await res.json()) as T;\n};\n\n/** The small fetch client behind the widgets. Every read takes an AbortSignal so unmounting cancels it. */\nexport const createApi = (c: Conn) => {\n const base = `${c.host}/api/sdk`;\n const who = { key: c.apiKey, distinctId: c.distinctId, user: c.user };\n const post = <T>(path: string, body: Record<string, unknown>, signal?: AbortSignal) =>\n call<T>(`${base}${path}`, { method: \"POST\", body: JSON.stringify({ ...who, ...body }) }, signal);\n return {\n list: (o: { board?: string; sort?: \"top\" | \"new\"; q?: string }, signal?: AbortSignal) =>\n call<FeedbackList>(`${base}/feedback?${qs({ key: c.apiKey, distinctId: c.distinctId, board: o.board, sort: o.sort, q: o.q })}`, undefined, signal),\n post: (id: string, signal?: AbortSignal) =>\n call<FeedbackPost>(`${base}/feedback/${encodeURIComponent(id)}?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n roadmap: (signal?: AbortSignal) => call<FeedbackRoadmap>(`${base}/feedback/roadmap?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n changelog: (signal?: AbortSignal) => call<{ entries: ChangelogEntry[] }>(`${base}/feedback/changelog?${qs({ key: c.apiKey })}`, undefined, signal),\n submit: (p: { title: string; body?: string; board: string }) => post<FeedbackPost>(\"/feedback\", p),\n vote: (id: string) => post<{ voted: boolean; votes: number }>(`/feedback/${encodeURIComponent(id)}/vote`, {}),\n comments: (id: string, signal?: AbortSignal) =>\n call<{ comments: FeedbackComment[] }>(`${base}/feedback/${encodeURIComponent(id)}/comments?${qs({ key: c.apiKey })}`, undefined, signal),\n comment: (id: string, body: string) => post<FeedbackComment>(`/feedback/${encodeURIComponent(id)}/comments`, { body }),\n survey: (url: string, signal?: AbortSignal) =>\n call<{ survey: SurveyDefinition | null }>(`${base}/surveys?${qs({ key: c.apiKey, distinctId: c.distinctId, url })}`, undefined, signal),\n seen: (id: string) => post<unknown>(`/surveys/${encodeURIComponent(id)}/seen`, { user: undefined }),\n respond: (id: string, r: { answers: Record<string, SurveyAnswer>; completed: boolean; seconds: number }) =>\n post<unknown>(`/surveys/${encodeURIComponent(id)}/respond`, r),\n chat: (signal?: AbortSignal) => call<ChatThread>(`${base}/messages?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n sendChat: (m: { body: string; email?: string; url?: string }) => post<ChatThread>(\"/messages\", m),\n articles: (q?: string, signal?: AbortSignal) => call<{ articles: ArticleSummary[] }>(`${base}/articles?${qs({ key: c.apiKey, q })}`, undefined, signal),\n article: (id: string, signal?: AbortSignal) =>\n call<Article>(`${base}/articles/${encodeURIComponent(id)}?${qs({ key: c.apiKey, distinctId: c.distinctId })}`, undefined, signal),\n messengerLook: (signal?: AbortSignal) => call<MessengerLook>(`${base}/messenger?${qs({ key: c.apiKey })}`, undefined, signal),\n rateArticle: (id: string, helpful: boolean) => post<{ counted: boolean }>(`/articles/${encodeURIComponent(id)}/rate`, { helpful }),\n };\n};\n\nexport type Api = ReturnType<typeof createApi>;\n","/**\n * How events go over the wire to `POST /api/sdk/events`, shared by every runtime (Next.js, the script tag, React\n * Native): request bodies of at most 100 events each, under the server's 64 KB. No React, no browser APIs, no\n * TextEncoder (Hermes on older React Native lacks it), so it runs anywhere.\n */\nimport type { CockpitEvent } from \"./core\";\n\n/** The server takes at most 100 events and 64 KB per request; stay a little under the size. */\nexport const MAX_BATCH = 100;\nexport const MAX_BYTES = 60_000;\n\n/** What a batch says about the SDK that sent it (Build › Errors and Feature flags show it). */\nexport interface SdkInfo {\n v: string;\n errors: boolean;\n /** \"web\" (script tag), \"ios\" or \"android\" (React Native). Missing from the Next.js provider. */\n platform?: string;\n}\n\n/** UTF-8 length of a string, the way TextEncoder counts it (a lone surrogate becomes U+FFFD, three bytes). */\nexport const byteLength = (s: string) => {\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) n += 1;\n else if (c < 0x800) n += 2;\n else if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {\n n += 4;\n i++;\n } else n += 3;\n }\n return n;\n};\n\n/** One request: its body and the events in it (so a client can keep the ones that did not arrive). */\nexport interface BatchRequest<E> {\n body: string;\n events: E[];\n}\n\n/**\n * Splits events into request bodies of at most 100 events each, under the size limit. An event too large on its own is\n * dropped (it is in no request).\n */\nexport const batchRequests = <E extends CockpitEvent>(key: string, events: E[], sdk: SdkInfo): BatchRequest<E>[] => {\n const head = `{\"key\":${JSON.stringify(key)},\"sdk\":${JSON.stringify(sdk)},\"events\":[`;\n const empty = byteLength(head) + 2;\n const out: BatchRequest<E>[] = [];\n let chunk: string[] = [];\n let items: E[] = [];\n let size = empty;\n const close = () => {\n if (chunk.length) out.push({ body: `${head}${chunk.join(\",\")}]}`, events: items });\n chunk = [];\n items = [];\n size = empty;\n };\n for (const event of events) {\n const json = JSON.stringify(event);\n const n = byteLength(json) + 1;\n if (empty + n > MAX_BYTES) continue;\n if (chunk.length === MAX_BATCH || size + n > MAX_BYTES) close();\n chunk.push(json);\n items.push(event);\n size += n;\n }\n close();\n return out;\n};\n\n/**\n * Request bodies of at most 100 events each, under the size limit. An event too large on its own is dropped. `sdk` tells\n * MRRocket which SDK the site runs and whether it reports errors (Build › Errors and Feature flags show it).\n */\nexport const bodies = (key: string, events: CockpitEvent[], sdk: SdkInfo) => batchRequests(key, events, sdk).map((r) => r.body);\n","/**\n * Error tracking: uncaught errors and unhandled promise rejections of the page (and `captureError` for ones you\n * catch), sent to `POST /api/sdk/errors`, where MRRocket groups them into issues for Build › Errors. Independent of\n * session recordings. Only the error itself, the page URL and the last pages and clicks go along (no typed text, no\n * network bodies), under the same consent as analytics.\n *\n * Limits on the page: the same error is sent once per page load, at most 20 errors per page load, in batches every\n * 2 seconds and with `sendBeacon` when the page hides.\n */\nimport type { ErrorReport } from \"./core\";\n\nconst MAX_STACK = 8 * 1024;\nconst MAX_PER_PAGE = 20;\nconst MAX_CRUMBS = 20;\nconst FLUSH_MS = 2000;\n\nexport interface ErrorCapture {\n /** An error you caught yourself; `handled` is true. */\n capture: (error: unknown, mechanism?: ErrorReport[\"mechanism\"]) => void;\n /** A page view or a click for the breadcrumbs. */\n crumb: (type: \"navigation\" | \"click\" | \"lifecycle\", message: string) => void;\n stop: () => void;\n}\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}…` : s);\n\n/** Type, message and stack of anything thrown. */\nexport const describeError = (error: unknown): { type: string; message: string; stack?: string } => {\n if (error instanceof Error) return { type: error.name || \"Error\", message: clip(error.message || String(error), 1000), stack: error.stack ? clip(error.stack, MAX_STACK) : undefined };\n if (typeof error === \"string\") return { type: \"Error\", message: clip(error, 1000) };\n try {\n return { type: \"Error\", message: clip(JSON.stringify(error) ?? String(error), 1000) };\n } catch {\n return { type: \"Error\", message: String(error) };\n }\n};\n\nexport const startErrorCapture = (opts: {\n host: string;\n apiKey: string;\n release?: string;\n /** Read when an error happens: whether to send at all (consent), and who and which session. */\n context: () => { send: boolean; distinctId?: string; sessionId?: string };\n warn: (message: string) => void;\n}): ErrorCapture => {\n const queue: ErrorReport[] = [];\n const crumbs: NonNullable<ErrorReport[\"crumbs\"]> = [];\n const seen = new Set<string>();\n let sent = 0;\n const url = `${opts.host}/api/sdk/errors`;\n\n const flush = (beacon = false) => {\n // At most four reports per request: four full stacks stay under the server's 64 KB.\n while (queue.length) {\n const body = JSON.stringify({ key: opts.apiKey, errors: queue.splice(0, 4) });\n const ok = beacon && typeof navigator !== \"undefined\" && \"sendBeacon\" in navigator && navigator.sendBeacon(url, body);\n if (!ok)\n fetch(url, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body, keepalive: true })\n .then((r) => {\n if (!r.ok && r.status !== 429) opts.warn(`Error reports were rejected with ${r.status}. Check the public key and NEXT_PUBLIC_MRROCKET_HOST.`);\n })\n .catch(() => {});\n }\n };\n\n const capture = (error: unknown, mechanism: ErrorReport[\"mechanism\"] = \"manual\") => {\n const ctx = opts.context();\n if (!ctx.send || sent >= MAX_PER_PAGE) return;\n const d = describeError(error);\n // Our own reports failing must never report themselves.\n if (/\\/api\\/sdk\\/errors/.test(d.message)) return;\n const mark = `${d.type}:${d.message}`;\n if (seen.has(mark)) return;\n seen.add(mark);\n sent++;\n queue.push({\n ...d,\n mechanism,\n handled: mechanism === \"manual\",\n url: window.location.href,\n ts: Date.now(),\n crumbs: crumbs.slice(),\n ...(opts.release ? { release: opts.release } : {}),\n ...(ctx.distinctId ? { distinctId: ctx.distinctId } : {}),\n ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),\n });\n };\n\n const onError = (e: ErrorEvent) => {\n // \"Script error.\" from a cross-origin script carries nothing useful.\n if (!e.error && (!e.message || e.message === \"Script error.\")) return;\n capture(e.error ?? new Error(e.message), \"onerror\");\n };\n const onRejection = (e: PromiseRejectionEvent) => capture(e.reason ?? new Error(\"Unhandled promise rejection\"), \"onunhandledrejection\");\n const onHide = () => flush(true);\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n window.addEventListener(\"pagehide\", onHide);\n const timer = window.setInterval(() => flush(), FLUSH_MS);\n\n return {\n capture,\n crumb: (type, message) => {\n crumbs.push({ ts: Date.now(), type, message: clip(message, 120) });\n if (crumbs.length > MAX_CRUMBS) crumbs.shift();\n },\n stop: () => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n window.removeEventListener(\"pagehide\", onHide);\n window.clearInterval(timer);\n flush(true);\n },\n };\n};\n","/**\n * The cancel flow, onboarding and in-app messages (SDK 0.7.0): what MRRocket's config and `GET /api/sdk/inapp` serve,\n * and one controller that decides what shows when and records what the person did. No DOM and no React: the web\n * renderer (flows-ui.ts, loaded only when something shows) and the React Native one (native/flows-view.ts) draw\n * `view()` and call the actions.\n *\n * What it records, as normal events under the SDK's analytics consent (nothing with consent \"off\"):\n * - `$cancel_flow` `{action: \"shown\" | \"answered\" | \"offer\" | \"finished\", run, version, …}`. MRRocket turns a\n * `finished` with `outcome: \"saved\"` into a save and with `outcome: \"cancelled\"` into a cancellation on the Churn page.\n * MRRocket never changes a subscription: an accepted offer goes to the app's `onSave`, a confirmed cancel to its\n * `onCancel`, and only after they succeed is the outcome recorded.\n * - `$onboarding` `{flow, step?, action: \"started\" | \"shown\" | \"completed\" | \"dismissed\"}`; since 0.11.0 a wait records\n * \"shown\" when the person reaches it and \"completed\" when it is over, a condition `{action: \"answered\", answer: \"yes\"\n * | \"no\"}` once it is decided.\n * - `$inapp` `{message, journey, action: \"shown\" | \"clicked\" | \"dismissed\"}`; the journey moves the person on.\n */\nimport type { CockpitConfig } from \"./core\";\n\nexport const CANCEL_EVENT = \"$cancel_flow\";\nexport const ONBOARDING_EVENT = \"$onboarding\";\nexport const INAPP_EVENT = \"$inapp\";\n\nexport type CancelOfferKind = \"discount\" | \"pause\" | \"downgrade\" | \"contact\";\n\n/** What one answer of the survey offers before the confirmation. An answer without one goes straight to it. */\nexport interface CancelOffer {\n kind: CancelOfferKind;\n headline: string;\n /** Discount: percent off. */\n percent?: number;\n /** Discount: for how many months; pause: up to how many months. */\n months?: number;\n /** Downgrade: the plan to switch to, as MRRocket knows it from the payment provider. */\n plan?: string;\n planName?: string;\n}\n\n/** The product's live cancel flow (MRRocket › Churn › Cancel flow). */\nexport interface CancelFlowConfig {\n /** Grows with every publish. */\n version: number;\n question: string;\n /** The survey's answers, in order. */\n reasons: { id: string; label: string }[];\n /** The offer per answer id. */\n offers: Record<string, CancelOffer>;\n confirm: { title: string; body: string; button: string };\n /**\n * Who gets the survey and the offers: business customers only. Anyone else (a consumer, or a customer the app does\n * not say) gets the plain confirmation, with nothing in the way of cancelling (§ 312k BGB).\n */\n offersFor: \"business\";\n}\n\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\";\n\nexport interface OnboardingStep {\n id: string;\n kind: OnboardingStepKind;\n title: string;\n body?: string;\n button?: string;\n /** Tour steps: the element they point at, marked `data-ck-target=\"<target>\"` in the app. Without it: a card. */\n target?: string;\n /** Checklist items: the event that ticks them (`track(\"<event>\")`). Without it the person ticks it themselves. */\n event?: string;\n}\n\n/** A pause in a flow (0.11.0): the next step shows this long after the one before was done. */\nexport interface OnboardingWait {\n id: string;\n kind: \"wait\";\n amount: number;\n unit: \"hours\" | \"days\";\n}\n\n/**\n * A fork in a flow (0.11.0): \"Did <event> happen?\" (the person's events, here and on MRRocket) or \"Is on <page>?\" (the\n * page they are on when they reach it; `*` at the end for everything below). Decided once, when the person reaches it;\n * like a journey's branch it ends its line, the rest of the flow lives in its two paths.\n */\nexport interface OnboardingCondition {\n id: string;\n kind: \"condition\";\n event?: string;\n page?: string;\n yes: OnboardingNode[];\n no: OnboardingNode[];\n}\n\nexport type OnboardingNode = OnboardingStep | OnboardingWait | OnboardingCondition;\n\n/** A live onboarding flow's in-app steps (MRRocket › Conversion › Onboarding); its emails go out from MRRocket. */\nexport interface OnboardingFlow {\n id: string;\n name: string;\n /** When it starts: an event's words (\"Signed up\", \"First export\"), or \"First launch\" / \"First visit\". */\n trigger: string;\n /** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */\n steps: OnboardingStep[];\n /** 0.11.0+: the whole flow with its waits and conditions. Read instead of `steps` when it is there. */\n nodes?: OnboardingNode[];\n}\n\n/** An in-app message a Lifecycle journey has for this person. */\nexport interface InAppMessage {\n id: string;\n journey?: string;\n title: string;\n body?: string;\n button?: string;\n /** Where the button goes (http(s) or a path of the app). */\n url?: string;\n style: \"banner\" | \"modal\";\n}\n\n/** One flow's progress: the steps done, whether the person closed it, and (0.11.0) its decided conditions and times. */\nexport interface FlowProgress {\n done: string[];\n dismissed?: boolean;\n /** Each decided condition's path. */\n answers?: Record<string, \"yes\" | \"no\">;\n /** When each step was done and each wait was reached (ms since 1970). */\n at?: Record<string, number>;\n reached?: Record<string, number>;\n}\n\n/** What `GET /api/sdk/inapp` answers for one signed-in person. */\nexport interface InAppState {\n /** Progress per onboarding flow: the steps done and whether the person closed it. */\n onboarding: Record<string, FlowProgress>;\n messages: InAppMessage[];\n /** 0.11.0: the events the flows' conditions ask about that this person did (as `eventSlug`s). */\n events?: string[];\n}\n\nexport interface CancelFlowResult {\n /** \"cancelled\": confirmed; \"saved\": took the offer; \"kept\": closed the dialog without cancelling. */\n outcome: \"cancelled\" | \"saved\" | \"kept\";\n reason?: string;\n reasonLabel?: string;\n offer?: CancelOffer;\n /** What the customer wrote on the confirmation, if anything. */\n comment?: string;\n /** This run's id, the same as in the events. */\n run: string;\n}\n\nexport interface CancelFlowOptions {\n /**\n * \"business\" shows the survey and the offers; anything else (the default) only the plain confirmation, so a\n * consumer can always cancel in one step (§ 312k BGB).\n */\n customer?: \"business\" | \"consumer\";\n /** The customer's current price, to show what a discount costs (`{ amount: 29, currency: \"EUR\" }`). */\n price?: { amount: number; currency: string; interval?: \"month\" | \"year\" };\n /** The customer confirmed: cancel the subscription in your code. Throwing keeps the dialog open with an error. */\n onCancel?: (result: CancelFlowResult) => unknown;\n /** The customer took an offer: apply it in your code (coupon, pause, plan change). Throwing keeps the dialog open. */\n onSave?: (result: CancelFlowResult) => unknown;\n /** Closed without cancelling or taking an offer. */\n onClose?: (result: CancelFlowResult) => void;\n}\n\n/** What a renderer draws. */\nexport type FlowView =\n | {\n type: \"cancel\";\n screen: \"survey\" | \"offer\" | \"confirm\";\n flow: CancelFlowConfig;\n /** The answer picked on the survey. */\n reason?: string;\n offer?: CancelOffer;\n price?: CancelFlowOptions[\"price\"];\n busy: boolean;\n error?: string;\n /** The step for the dots, 1 to `steps`. */\n step: number;\n steps: number;\n }\n | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean }\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean }[] }\n | { type: \"message\"; message: InAppMessage };\n\nexport interface FlowsEnv {\n /** Records an event under the SDK's consent (the normal queue). */\n track(event: string, props?: Record<string, unknown>): void;\n /** Whose messages and progress these are: the identify() id; undefined while nobody is signed in. */\n personId(): string | undefined;\n /** `GET /api/sdk/inapp` for that person; null when it fails. */\n fetchInApp(personId: string): Promise<InAppState | null>;\n /** Keeps onboarding progress on the device; only while the consent lets the SDK store something. */\n storage?: () => { get(key: string): string | null | Promise<string | null>; set(key: string, value: string): void } | null;\n /** Opens a message's link. */\n openUrl?: (url: string) => void;\n /** Start onboarding flows by their trigger on its own (default true). */\n auto?: boolean;\n /** The page the person is on (a path), for \"Is on <page>?\" conditions; without it they answer no. */\n path?: () => string | undefined;\n /** The clock, for tests. */\n now?: () => number;\n}\n\nexport interface FlowsController {\n setConfig(config: CockpitConfig | null): void;\n /** The person changed (identify, reset, consent): loads their messages and onboarding progress. */\n refresh(): Promise<void>;\n /** An event the app recorded: starts flows whose trigger it is and ticks checklist items. */\n onEvent(name: string): void;\n openCancelFlow(options?: CancelFlowOptions): Promise<CancelFlowResult>;\n /** Starts an onboarding flow now (the first live one without an id). False when there is none to start. */\n startOnboarding(id?: string): boolean;\n view(): FlowView | null;\n subscribe(listener: () => void): () => void;\n /** `accept(comment)`: a \"Talk to us\" offer sends what the customer wrote with it. */\n cancel: { pick(reason: string): void; next(): void; accept(comment?: string): void; decline(): void; confirm(comment?: string): void; close(): void };\n onboarding: { next(): void; check(stepId: string): void; dismiss(): void };\n message: { click(): void; dismiss(): void };\n}\n\n/** The plain confirmation, when the product has no live cancel flow (or MRRocket was not reachable). */\nexport const PLAIN_CANCEL: CancelFlowConfig = {\n version: 0,\n question: \"\",\n reasons: [],\n offers: {},\n confirm: { title: \"Cancel your subscription?\", body: \"You keep access until the end of the billing period.\", button: \"Cancel subscription\" },\n offersFor: \"business\",\n};\n\nconst FAILED = \"Something went wrong. Please try again.\";\nconst PROGRESS_KEY = \"mrrocket:onboarding\";\n\n/** `\"Signed up\"` → `signed_up`, the way MRRocket names events from words. */\nexport const eventSlug = (s: string) =>\n s\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst SIGNUP = new Set([\"signed_up\", \"signup\", \"sign_up\", \"registered\", \"account_created\", \"user_signed_up\"]);\n\n/** Whether recording `event` is the trigger's moment (\"Signed up\" is any of the usual signup event names). */\nexport const matchesTrigger = (trigger: string, event: string) => {\n const t = eventSlug(trigger);\n const e = eventSlug(event);\n if (!t || !e) return false;\n return t === e || (SIGNUP.has(t) && SIGNUP.has(e));\n};\n\n/** Triggers that mean \"the first time the person opens the app\": the flow starts on load until it is done. */\nexport const startsOnLoad = (trigger: string) =>\n /^(first (launch|visit|open|session|login|sign ?in|app open)|app (opened|launched)|on load|every visit|always)?$/i.test(trigger.trim());\n\n/** A random id for one cancel flow run. */\nexport const runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;\n\n/** The money a discount leaves: `29 EUR` at 30 % → `20.30`. */\nexport const discounted = (amount: number, percent: number) => Math.round(amount * (1 - percent / 100) * 100) / 100;\n\n/** \"€20.30\" in the customer's own currency, without a library. */\nexport const money = (amount: number, currency: string) => {\n try {\n return new Intl.NumberFormat(undefined, { style: \"currency\", currency }).format(amount);\n } catch {\n return `${amount.toFixed(2)} ${currency}`;\n }\n};\n\n/** The button of an offer. */\nexport const offerButton = (o: CancelOffer) =>\n o.kind === \"contact\" ? \"Send to the team\" : o.kind === \"pause\" ? \"Pause instead\" : o.kind === \"downgrade\" ? \"Switch plan\" : \"Accept offer\";\n\n/** A link a message may open: http(s), or a path of the app. Nothing else (no `javascript:`). */\nexport const safeUrl = (url: string | undefined) => {\n const u = (url ?? \"\").trim();\n return /^https?:\\/\\//i.test(u) || /^\\/(?!\\/)/.test(u) ? u : undefined;\n};\n\ninterface Progress {\n done: Set<string>;\n dismissed: boolean;\n answers: Map<string, boolean>;\n at: Map<string, number>;\n reached: Map<string, number>;\n}\n\n/** The flow's nodes: the whole tree (0.11.0 config), or the plain steps of an older one. */\nexport const nodesOf = (f: OnboardingFlow): OnboardingNode[] => f.nodes ?? f.steps;\n\n/** How long a wait lasts. */\nexport const waitMs = (w: Pick<OnboardingWait, \"amount\" | \"unit\">) => Math.max(0, w.amount) * (w.unit === \"hours\" ? 3_600_000 : 86_400_000);\n\n/** Whether a path matches a condition's page: the same path, or below it for a pattern ending in `*`. */\nexport const pageMatches = (pattern: string, path: string) => {\n const p = pattern.trim();\n const at = (path.split(/[?#]/)[0] || \"/\").replace(/\\/+$/, \"\") || \"/\";\n if (!p) return false;\n if (p.endsWith(\"*\")) {\n const base = p.slice(0, -1).replace(/\\/+$/, \"\");\n return !base || at === base || at.startsWith(`${base}/`);\n }\n return at === (p.replace(/\\/+$/, \"\") || \"/\");\n};\n\n/** Every in-app step of a tree, in reading order (for ticking checklist items by their event). */\nconst stepsIn = (nodes: OnboardingNode[]): OnboardingStep[] =>\n nodes.flatMap((n) => (n.kind === \"condition\" ? [...stepsIn(n.yes), ...stepsIn(n.no)] : n.kind === \"wait\" ? [] : [n]));\n\ntype Walked =\n | { at: \"step\"; step: OnboardingStep; line: OnboardingNode[]; index: number; before: number }\n | { at: \"wait\"; until: number }\n | { at: \"pending\" }\n | { at: \"end\" };\n\ninterface CancelRun {\n flow: CancelFlowConfig;\n options: CancelFlowOptions;\n plain: boolean;\n screen: \"survey\" | \"offer\" | \"confirm\";\n reason?: string;\n run: string;\n busy: boolean;\n error?: string;\n resolve: (r: CancelFlowResult) => void;\n promise: Promise<CancelFlowResult>;\n}\n\nexport const createFlows = (env: FlowsEnv): FlowsController => {\n let config: CockpitConfig | null = null;\n let cancel: CancelRun | null = null;\n let active: string | null = null;\n let messages: InAppMessage[] = [];\n let known = false;\n let loading: Promise<void> | null = null;\n let loadedFor: string | undefined;\n let progressFor: string | undefined | null = null;\n const progress = new Map<string, Progress>();\n const handled = new Set<string>();\n const shown = new Set<string>();\n const listeners = new Set<() => void>();\n const auto = env.auto !== false;\n /** Events the person did (as slugs), for \"Did <event> happen?\": from MRRocket and from this device. */\n const seenEvents = new Set<string>();\n const now = () => env.now?.() ?? Date.now();\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const flows = () => config?.onboarding ?? [];\n const flowById = (id: string | null) => (id ? flows().find((f) => f.id === id) : undefined);\n const prog = (id: string) => {\n let p = progress.get(id);\n if (!p) progress.set(id, (p = { done: new Set(), dismissed: false, answers: new Map(), at: new Map(), reached: new Map() }));\n return p;\n };\n\n let dirty = false;\n const record = (props: Record<string, unknown>) => {\n env.track(ONBOARDING_EVENT, props);\n dirty = true;\n };\n const markDone = (p: Progress, id: string) => {\n p.done.add(id);\n p.at.set(id, now());\n };\n\n /** A condition's answer for this person, or undefined while what it asks is not known yet. */\n const decide = (c: OnboardingCondition): boolean | undefined => {\n if (c.page?.trim()) {\n const path = env.path?.();\n return path === undefined ? false : pageMatches(c.page, path);\n }\n if (c.event?.trim()) {\n // The person's events from MRRocket arrive with their progress: before that, wait.\n if (!known) return undefined;\n for (const e of seenEvents) if (matchesTrigger(c.event, e)) return true;\n return false;\n }\n return false;\n };\n\n /**\n * Where the person is in a line of the flow. `live`: it is their flow now, so reaching a wait starts it, a decided\n * condition is kept and both are recorded; otherwise nothing changes (to ask whether a flow is finished).\n */\n const walkLine = (flow: OnboardingFlow, line: OnboardingNode[], p: Progress, live: boolean, before = 0, last?: number): Walked => {\n for (let i = 0; i < line.length; i++) {\n const n = line[i];\n if (n.kind === \"wait\") {\n if (p.done.has(n.id)) {\n last = p.at.get(n.id) ?? last;\n continue;\n }\n let since = p.reached.get(n.id);\n if (since === undefined) {\n if (!live) return { at: \"pending\" };\n // Counted from when the step before was done; a flow that opens with a wait counts from now.\n since = last ?? now();\n p.reached.set(n.id, since);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"shown\" });\n }\n const until = since + waitMs(n);\n if (now() < until) return { at: \"wait\", until };\n if (!live) return { at: \"pending\" };\n markDone(p, n.id);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"completed\" });\n last = until;\n continue;\n }\n if (n.kind === \"condition\") {\n let answer = p.answers.get(n.id);\n if (answer === undefined) {\n if (!live) return { at: \"pending\" };\n answer = decide(n);\n if (answer === undefined) return { at: \"pending\" };\n p.answers.set(n.id, answer);\n record({ flow: flow.id, step: n.id, kind: \"condition\", action: \"answered\", answer: answer ? \"yes\" : \"no\" });\n }\n return walkLine(flow, answer ? n.yes : n.no, p, live, before, last);\n }\n if (!p.done.has(n.id)) return { at: \"step\", step: n, line, index: i, before };\n last = p.at.get(n.id) ?? last;\n before++;\n }\n return { at: \"end\" };\n };\n\n const finished = (f: OnboardingFlow) => {\n const p = progress.get(f.id);\n return !!p && (p.dismissed || walkLine(f, nodesOf(f), p, false).at === \"end\");\n };\n\n const keyOf = (pid: string | undefined) => `${PROGRESS_KEY}:${pid ?? \"visitor\"}`;\n const eventsKeyOf = (pid: string | undefined) => `${PROGRESS_KEY}:events:${pid ?? \"visitor\"}`;\n\n const save = () => {\n dirty = false;\n const store = env.storage?.();\n if (!store) return;\n const out: Record<string, FlowProgress> = {};\n for (const [id, p] of progress)\n out[id] = {\n done: [...p.done],\n ...(p.dismissed ? { dismissed: true } : {}),\n ...(p.answers.size ? { answers: Object.fromEntries([...p.answers].map(([k, v]) => [k, v ? \"yes\" : \"no\"])) } : {}),\n ...(p.at.size ? { at: Object.fromEntries(p.at) } : {}),\n ...(p.reached.size ? { reached: Object.fromEntries(p.reached) } : {}),\n };\n try {\n store.set(keyOf(env.personId()), JSON.stringify(out));\n if (seenEvents.size) store.set(eventsKeyOf(env.personId()), JSON.stringify([...seenEvents].slice(-200)));\n } catch {\n // Storage full or gone: progress stays in memory.\n }\n };\n\n const merge = (state: InAppState[\"onboarding\"] | undefined) => {\n for (const [id, s] of Object.entries(state ?? {})) {\n const p = prog(id);\n for (const d of s.done ?? []) p.done.add(d);\n if (s.dismissed) p.dismissed = true;\n // A condition decided elsewhere keeps its path; the earliest time wins for waits.\n for (const [k, v] of Object.entries(s.answers ?? {})) if (!p.answers.has(k)) p.answers.set(k, v === \"yes\");\n for (const [k, v] of Object.entries(s.at ?? {})) if (typeof v === \"number\" && !p.at.has(k)) p.at.set(k, v);\n for (const [k, v] of Object.entries(s.reached ?? {})) if (typeof v === \"number\" && (!p.reached.has(k) || v < p.reached.get(k)!)) p.reached.set(k, v);\n }\n };\n\n // ---------- What shows ----------\n\n /** Comes back when a short wait is over, so the next step shows without a reload (long waits wait for the next visit). */\n const wakeAt = (until: number) => {\n if (timer) clearTimeout(timer);\n timer = null;\n const ms = until - now();\n if (ms > 0 && ms <= 86_400_000) {\n timer = setTimeout(() => ((timer = null), emit()), ms + 50);\n // Never what keeps a process alive (tests, server rendering).\n (timer as { unref?: () => void }).unref?.();\n }\n };\n\n /** The active flow waits (a wait step, or a condition whose answer is not known yet): it stays the active one. */\n let holding = false;\n\n const onboardingView = (): FlowView | null => {\n holding = false;\n const flow = flowById(active);\n if (!flow) return null;\n const p = prog(flow.id);\n if (p.dismissed) return null;\n const w = walkLine(flow, nodesOf(flow), p, true);\n if (dirty) save();\n if (w.at === \"wait\") wakeAt(w.until);\n holding = w.at === \"wait\" || w.at === \"pending\";\n if (w.at !== \"step\") return null;\n const { step, line, index } = w;\n const isStep = (n: OnboardingNode | undefined): n is OnboardingStep => !!n && n.kind !== \"wait\" && n.kind !== \"condition\";\n if (step.kind === \"checklist\") {\n let from = index;\n while (from > 0 && isStep(line[from - 1]) && line[from - 1].kind === \"checklist\") from--;\n let to = index;\n while (to + 1 < line.length && isStep(line[to + 1]) && line[to + 1].kind === \"checklist\") to++;\n const items = line.slice(from, to + 1).filter(isStep);\n for (const i of items)\n if (!p.done.has(i.id) && !shown.has(`s:${i.id}`)) {\n shown.add(`s:${i.id}`);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: i.id, kind: \"checklist\", action: \"shown\" });\n }\n return { type: \"checklist\", flow, items: items.map((s) => ({ step: s, done: p.done.has(s.id) })) };\n }\n if (!shown.has(`s:${step.id}`)) {\n shown.add(`s:${step.id}`);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: step.id, kind: step.kind, action: \"shown\" });\n }\n // The dots: the steps behind on the person's path, this one, and the ones left on its line before any fork.\n const rest = line.slice(index + 1);\n const fork = rest.findIndex((n) => n.kind === \"condition\");\n const ahead = (fork < 0 ? rest : rest.slice(0, fork)).filter(isStep).length;\n return { type: \"step\", flow, step, index: w.before, total: w.before + 1 + ahead, last: !ahead && fork < 0 };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const offer = cancel.reason ? cancel.flow.offers[cancel.reason] : undefined;\n return {\n type: \"cancel\",\n screen: cancel.screen,\n flow: cancel.flow,\n reason: cancel.reason,\n offer: cancel.screen === \"offer\" ? offer : undefined,\n price: cancel.options.price,\n busy: cancel.busy,\n error: cancel.error,\n step: cancel.plain ? 1 : cancel.screen === \"survey\" ? 1 : cancel.screen === \"offer\" ? 2 : 3,\n steps: cancel.plain ? 1 : 3,\n };\n }\n const ob = onboardingView();\n if (ob) return ob;\n // A flow that just ended lets the next thing show; one that waits keeps its place.\n if (active && !holding) active = null;\n const m = messages.find((x) => !handled.has(x.id));\n return m ? { type: \"message\", message: m } : null;\n };\n\n /** Tells the renderers, and records what became visible (once per step or message per page load). */\n const emit = () => {\n // Onboarding steps record their \"shown\" where they are worked out (onboardingView), so a step a wait let through\n // counts also when nothing else changed.\n const v = view();\n if (v?.type === \"message\" && !shown.has(`m:${v.message.id}`)) {\n shown.add(`m:${v.message.id}`);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"shown\" });\n }\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n\n const start = (flow: OnboardingFlow) => {\n if (active === flow.id) return true;\n if (active && flowById(active) && !finished(flowById(active)!)) return false;\n active = flow.id;\n env.track(ONBOARDING_EVENT, { flow: flow.id, action: \"started\" });\n emit();\n return true;\n };\n\n /** Flows whose trigger is \"the first launch\" start once their progress is known (never twice for a done flow). */\n const autoStart = () => {\n if (!auto || active || !known) return;\n // Without an id or storage a \"first launch\" could not be told from any other: no automatic start then.\n if (!env.personId() && !env.storage?.()) return;\n const next = flows().find((f) => startsOnLoad(f.trigger) && nodesOf(f).length && !finished(f));\n if (next) start(next);\n };\n\n const refresh = () => {\n const pid = env.personId();\n // Another person on this device: nothing of the one before carries over.\n if (progressFor !== null && progressFor !== pid) {\n progress.clear();\n seenEvents.clear();\n handled.clear();\n active = null;\n loadedFor = undefined;\n }\n progressFor = pid;\n const run = (async () => {\n const store = env.storage?.();\n if (store) {\n try {\n const raw = await store.get(keyOf(pid));\n if (raw) merge(JSON.parse(raw) as InAppState[\"onboarding\"]);\n const seen = await store.get(eventsKeyOf(pid));\n if (seen) for (const e of JSON.parse(seen) as string[]) if (typeof e === \"string\") seenEvents.add(e);\n } catch {\n // A damaged entry is ignored.\n }\n }\n const wants = flows().length > 0 || !!config?.messages;\n if (pid && wants && loadedFor !== pid) {\n loadedFor = pid;\n const state = await env.fetchInApp(pid).catch(() => null);\n if (state && env.personId() === pid) {\n merge(state.onboarding);\n for (const e of state.events ?? []) if (typeof e === \"string\") seenEvents.add(eventSlug(e));\n messages = (state.messages ?? []).filter((m) => m && m.id && m.title);\n }\n }\n if (!pid) messages = [];\n known = true;\n autoStart();\n emit();\n })();\n loading = run.finally(() => {\n if (loading === run) loading = null;\n });\n return loading;\n };\n\n // ---------- Cancel flow ----------\n\n const result = (c: CancelRun, outcome: CancelFlowResult[\"outcome\"], comment?: string): CancelFlowResult => {\n const offer = c.reason ? c.flow.offers[c.reason] : undefined;\n return {\n outcome,\n run: c.run,\n ...(c.reason ? { reason: c.reason, reasonLabel: c.flow.reasons.find((r) => r.id === c.reason)?.label } : {}),\n ...(outcome === \"saved\" && offer ? { offer } : {}),\n ...(comment?.trim() ? { comment: comment.trim().slice(0, 500) } : {}),\n };\n };\n\n const finish = (c: CancelRun, r: CancelFlowResult) => {\n env.track(CANCEL_EVENT, {\n action: \"finished\",\n run: c.run,\n version: c.flow.version,\n outcome: r.outcome,\n customer: c.options.customer ?? \"consumer\",\n ...(r.reason ? { reason: r.reason } : {}),\n ...(r.offer ? { offer: r.offer.kind } : {}),\n ...(r.comment ? { comment: r.comment } : {}),\n });\n if (cancel === c) cancel = null;\n c.resolve(r);\n emit();\n };\n\n /** Runs the app's callback; the outcome is recorded only once it went through. */\n const settle = (c: CancelRun, outcome: \"saved\" | \"cancelled\", comment?: string) => {\n if (c.busy) return;\n const r = result(c, outcome, comment);\n const fn = outcome === \"saved\" ? c.options.onSave : c.options.onCancel;\n c.busy = true;\n c.error = undefined;\n emit();\n Promise.resolve()\n .then(() => fn?.(r))\n .then(\n () => finish(c, r),\n () => {\n c.busy = false;\n c.error = FAILED;\n emit();\n },\n );\n };\n\n const openCancelFlow = (options: CancelFlowOptions = {}) => {\n if (cancel) return cancel.promise;\n const flow = config?.cancelFlow ?? PLAIN_CANCEL;\n const plain = options.customer !== \"business\" || flow.reasons.length < 2;\n let resolve: (r: CancelFlowResult) => void = () => {};\n const promise = new Promise<CancelFlowResult>((r) => (resolve = r));\n const c: CancelRun = { flow, options, plain, screen: plain ? \"confirm\" : \"survey\", run: runId(), busy: false, resolve, promise };\n cancel = c;\n env.track(CANCEL_EVENT, { action: \"shown\", run: c.run, version: flow.version, customer: options.customer ?? \"consumer\", plain });\n emit();\n return promise;\n };\n\n const controller: FlowsController = {\n setConfig: (c) => {\n config = c;\n if (active && !flowById(active)) active = null;\n emit();\n },\n refresh,\n onEvent: (name) => {\n if (!name || name.startsWith(\"$\")) return;\n // Remembered for \"Did <event> happen?\" conditions the person reaches later.\n const slug = eventSlug(name);\n const fresh = !!slug && !seenEvents.has(slug);\n if (fresh) seenEvents.add(slug);\n const flow = flowById(active);\n let ticked = false;\n if (flow) {\n const p = prog(flow.id);\n for (const s of stepsIn(nodesOf(flow)))\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n markDone(p, s.id);\n ticked = true;\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n }\n if (ticked || (fresh && flow)) {\n save();\n emit();\n } else if (fresh) save();\n // Like the first-launch start: only for someone whose progress is kept, so nobody gets a flow twice.\n if (!auto || (!env.personId() && !env.storage?.())) return;\n const next = flows().find((f) => nodesOf(f).length && matchesTrigger(f.trigger, name) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !finished(x));\n if (!f || !nodesOf(f).length) return false;\n const p = prog(f.id);\n // Started by hand: a flow the person closed before shows again.\n p.dismissed = false;\n return start(f);\n },\n view,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n cancel: {\n pick: (reason) => {\n if (!cancel || cancel.busy || !cancel.flow.reasons.some((r) => r.id === reason)) return;\n cancel.reason = reason;\n cancel.error = undefined;\n emit();\n },\n next: () => {\n const c = cancel;\n if (!c || c.screen !== \"survey\" || !c.reason) return;\n env.track(CANCEL_EVENT, { action: \"answered\", run: c.run, version: c.flow.version, reason: c.reason });\n c.screen = c.flow.offers[c.reason] ? \"offer\" : \"confirm\";\n emit();\n },\n accept: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || !c.reason) return;\n const offer = c.flow.offers[c.reason];\n if (!c.busy)\n env.track(CANCEL_EVENT, {\n action: \"offer\",\n run: c.run,\n version: c.flow.version,\n reason: c.reason,\n offer: offer?.kind,\n outcome: \"accepted\",\n });\n settle(c, \"saved\", comment);\n },\n decline: () => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || c.busy) return;\n env.track(CANCEL_EVENT, {\n action: \"offer\",\n run: c.run,\n version: c.flow.version,\n reason: c.reason,\n offer: c.reason ? c.flow.offers[c.reason]?.kind : undefined,\n outcome: \"declined\",\n });\n c.screen = \"confirm\";\n c.error = undefined;\n emit();\n },\n confirm: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"confirm\") return;\n settle(c, \"cancelled\", comment);\n },\n close: () => {\n const c = cancel;\n if (!c || c.busy) return;\n const r = result(c, \"kept\");\n c.options.onClose?.(r);\n finish(c, r);\n },\n },\n onboarding: {\n next: () => {\n const v = onboardingView();\n if (v?.type !== \"step\") return;\n markDone(prog(v.flow.id), v.step.id);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: \"completed\" });\n save();\n emit();\n },\n check: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return;\n const item = v.items.find((i) => i.step.id === stepId);\n if (!item || item.done) return;\n markDone(prog(v.flow.id), stepId);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"completed\" });\n save();\n emit();\n },\n dismiss: () => {\n const v = onboardingView();\n if (!v || (v.type !== \"step\" && v.type !== \"checklist\")) return;\n prog(v.flow.id).dismissed = true;\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, ...(v.type === \"step\" ? { step: v.step.id } : {}), action: \"dismissed\" });\n active = null;\n save();\n emit();\n },\n },\n message: {\n click: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"clicked\" });\n const url = safeUrl(v.message.url);\n emit();\n if (url) env.openUrl?.(url);\n },\n dismiss: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"dismissed\" });\n emit();\n },\n },\n };\n return controller;\n};\n","/** Rage clicks without the DOM, so the web SDK and the apps (taps) count them the same. */\n\n/**\n * Three or more clicks within one second on the same spot (30 pixels) are a rage click. `push` answers true once per\n * burst, on the third click.\n */\nexport class RageDetector {\n private clicks: { x: number; y: number; t: number }[] = [];\n private fired = false;\n constructor(\n private readonly windowMs = 1000,\n private readonly radius = 30,\n private readonly count = 3,\n ) {}\n push(x: number, y: number, t: number) {\n const near = this.clicks.filter((c) => t - c.t <= this.windowMs && Math.hypot(c.x - x, c.y - y) <= this.radius);\n if (near.length !== this.clicks.length) this.fired = false;\n this.clicks = [...near, { x, y, t }];\n if (this.clicks.length >= this.count && !this.fired) {\n this.fired = true;\n return true;\n }\n return false;\n }\n}\n","/**\n * Session recordings in apps: about once a second, while the app is open and the screen changed, a small JPEG of the\n * screen (react-native-view-shot's `captureScreen`, an optional peer), sent in chunks to `/api/sdk/replay` as\n * `enc: \"frames\"` with the screens, taps, rage taps and errors as marks. MRRocket plays them in Sessions.\n *\n * It records only with the person's own replay consent (`replay` on the provider, `setReplay(true)`), never while the\n * consent is off, and only while the product's recordings are on. Privacy on the device: no frame while the keyboard is\n * open (what someone types is never on a frame), and every view wrapped in `<MRRocketMask>` goes as a rectangle that the\n * server paints black before it stores the frame (src/server/replay/frames.ts in the app).\n *\n * Like the web: a session in the product's sample rate uploads from its start; any other keeps the last minute in\n * memory and uploads it when a rage tap or an error happens (then keeps recording). At most 30 minutes per recording.\n */\nimport type { AppContext, ReplayConfig } from \"../core\";\n\nexport interface Frame {\n t: number;\n w: number;\n h: number;\n img: string;\n /** Masked areas in the frame's pixels: [x, y, w, h]. */\n masks: [number, number, number, number][];\n}\n\nexport interface Mark {\n t: number;\n kind: \"pageview\" | \"click\" | \"rage\" | \"error\";\n path: string;\n label?: string;\n x?: number;\n y?: number;\n vw?: number;\n}\n\nexport interface RecorderDeps {\n now: () => number;\n setInterval: (fn: () => void, ms: number) => unknown;\n clearInterval: (id: unknown) => void;\n /** The screen as a JPEG of about `width` pixels wide, base64, or null (no view-shot, or it failed). */\n capture: (width: number) => Promise<{ img: string; w: number; h: number } | null>;\n keyboardOpen: () => boolean;\n /** The masked views' rectangles in screen points; null when one could not be measured (the frame is then skipped). */\n masks: () => Promise<[number, number, number, number][] | null>;\n /** The screen size in points. */\n screen: () => { w: number; h: number } | undefined;\n send: (body: string) => Promise<number>;\n}\n\nexport interface RecorderState {\n /** May record now: the person's replay consent, tracking on, a key. */\n allowed: () => boolean;\n config: () => ReplayConfig | undefined;\n session: () => string;\n who: () => { distinctId?: string; identified: boolean };\n apiKey: string;\n app: AppContext;\n}\n\nconst FRAME_MS = 1000;\nconst WIDTH = 360;\nconst BUFFER_MS = 60_000;\nconst CHUNK_FRAMES = 12;\nconst CHUNK_CHARS = 700_000;\nconst MAX_MS = 30 * 60_000;\n\n/** A stable share in [0, 1) for a session, so its sample decision holds for the whole session. */\nconst shareOf = (s: string) => {\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) h = Math.imul(h ^ s.charCodeAt(i), 16777619);\n return (h >>> 0) / 4294967296;\n};\n\nexport const createRecorder = (deps: RecorderDeps, st: RecorderState) => {\n let timer: unknown = null;\n let busy = false;\n let last = \"\";\n // The current recording: its session, start, next chunk, and whether it uploads (else it buffers).\n let rec: { session: string; start: number; seq: number; uploading: boolean; trigger: string; stopped: boolean } | null = null;\n let frames: Frame[] = [];\n let marks: Mark[] = [];\n\n const ensure = () => {\n const session = st.session();\n const cfg = st.config();\n if (!rec || rec.session !== session) {\n frames = [];\n marks = [];\n last = \"\";\n const sampled = !!cfg && shareOf(session) < (cfg.sampleRate ?? 0.1);\n rec = { session, start: deps.now(), seq: 0, uploading: sampled, trigger: \"sample\", stopped: false };\n }\n return rec;\n };\n\n const send = async (r: NonNullable<typeof rec>) => {\n if (!frames.length || r.stopped) return;\n const batch = frames.splice(0, frames.length);\n const ms = marks.splice(0, marks.length);\n const size = deps.screen();\n const { distinctId, identified } = st.who();\n const body = JSON.stringify({\n key: st.apiKey,\n consent: { replay: true },\n sessionId: r.session,\n start: r.start,\n seq: r.seq++,\n enc: \"frames\",\n data: JSON.stringify(batch),\n meta: { first: batch[0].t, last: batch[batch.length - 1].t, vw: size ? Math.round(size.w) : null, vh: size ? Math.round(size.h) : null, marks: ms },\n distinctId,\n identified,\n trigger: r.trigger,\n app: st.app,\n });\n const status = await deps.send(body);\n // Refused for good (no consent on the server's side, recordings off, too long or too big): stop this recording.\n if (status === 403 || status === 409 || status === 413) r.stopped = true;\n };\n\n const tick = async () => {\n if (busy || !st.allowed() || !st.config()) return;\n const r = ensure();\n if (r.stopped || deps.now() - r.start > MAX_MS) return;\n // Typing is never recorded: no frame while the keyboard is up.\n if (deps.keyboardOpen()) return;\n busy = true;\n try {\n const shot = await deps.capture(WIDTH);\n if (!shot || shot.img === last) return;\n last = shot.img;\n const size = deps.screen();\n const scale = size && size.w ? shot.w / size.w : 1;\n const measured = await deps.masks();\n // A masked view that could not be measured: no frame at all rather than one without its mask.\n if (measured === null) {\n last = \"\";\n return;\n }\n const masks = measured.map(([x, y, w, h]) => [x * scale, y * scale, w * scale, h * scale].map(Math.round) as Frame[\"masks\"][number]);\n frames.push({ t: deps.now(), w: shot.w, h: shot.h, img: shot.img, masks });\n if (!r.uploading) {\n // Buffering: only the last minute stays.\n const since = deps.now() - BUFFER_MS;\n frames = frames.filter((f) => f.t >= since);\n marks = marks.filter((m) => m.t >= since);\n return;\n }\n const chars = frames.reduce((a, f) => a + f.img.length, 0);\n if (frames.length >= CHUNK_FRAMES || chars >= CHUNK_CHARS) await send(r);\n } catch {\n // A failed frame is skipped; recording must never disturb the app.\n } finally {\n busy = false;\n }\n };\n\n return {\n /** Starts or stops the frame loop to match the app state (active) and whether recording is allowed. */\n sync(active: boolean) {\n const on = active && st.allowed() && !!st.config();\n if (on && timer === null) timer = deps.setInterval(() => void tick(), FRAME_MS);\n if (!on && timer !== null) {\n deps.clearInterval(timer);\n timer = null;\n if (rec?.uploading) void send(rec);\n }\n },\n /** A screen, tap, rage tap or error, for the timeline. */\n mark(m: Omit<Mark, \"t\">) {\n if (!st.allowed() || !st.config()) return;\n ensure();\n marks.push({ t: deps.now(), ...m });\n if (marks.length > 300) marks.splice(0, marks.length - 300);\n },\n /** A rage tap or an error: a buffering recording uploads its last minute and keeps recording. */\n trigger(kind: \"rage\" | \"error\") {\n if (!rec || rec.uploading || rec.stopped || !st.allowed()) return;\n rec.uploading = true;\n rec.trigger = kind;\n void send(rec);\n },\n /** Sends what waits (going to the background). */\n flush() {\n if (rec?.uploading) return send(rec);\n return Promise.resolve();\n },\n /** Consent withdrawn: forget everything not sent. */\n drop() {\n frames = [];\n marks = [];\n rec = null;\n last = \"\";\n },\n /** For tests: one frame now. */\n tick,\n };\n};\n\nexport type Recorder = ReturnType<typeof createRecorder>;\n\n// ---------- Masked views ----------\n\nexport interface Measurable {\n measureInWindow(cb: (x: number, y: number, w: number, h: number) => void): void;\n}\n\n/** The views wrapped in `<MRRocketMask>` that are on screen now. */\nexport const maskedViews = new Set<{ current: Measurable | null }>();\n\n/** Their rectangles in screen points; null when one did not answer within 100 ms (that frame is not taken). */\nexport const measureMasks = (): Promise<[number, number, number, number][] | null> =>\n Promise.all(\n [...maskedViews].map(\n (ref) =>\n new Promise<[number, number, number, number] | \"none\" | \"failed\">((resolve) => {\n const v = ref.current;\n // Not mounted (yet or any more): nothing on screen to hide.\n if (!v) return resolve(\"none\");\n const t = setTimeout(() => resolve(\"failed\"), 100);\n try {\n v.measureInWindow((x, y, w, h) => {\n clearTimeout(t);\n resolve(w > 0 && h > 0 ? [x, y, w, h] : \"none\");\n });\n } catch {\n clearTimeout(t);\n resolve(\"failed\");\n }\n }),\n ),\n ).then((rs) => (rs.includes(\"failed\") ? null : rs.filter((r): r is [number, number, number, number] => Array.isArray(r))));\n","/**\n * Affiliate referrals, after Rewardful's and Dub's client scripts. A partner's tracked link (`<mrrocket>/r/<code>`)\n * counts the click on MRRocket and sends the visitor to your site with `?mrr_ref=<code>&mrr_click=<clickId>`; a direct\n * link is `https://your.site/?ref=<code>`. The provider reads either on page load, keeps the referral for the program's\n * cookie days in a FIRST-PARTY cookie on your domain (`mrr_ref`) plus localStorage, and sends a click beacon for direct\n * links. MRRocket never sets a cookie for you: its domain is not yours.\n *\n * Storage follows consent (see the README): with `attribution=\"consent\"` (default) the referral is only stored when\n * the provider's consent is \"cookies\"; otherwise it lives in memory for the page load. `attribution=\"always\"` stores\n * it whatever the consent (your legal call), `\"off\"` ignores referrals.\n *\n * Plain functions, no React: `getReferral()` and `referralForCheckout()` work in any client code, and on the server\n * with the cookie's value (`readReferralCookie`).\n */\n\nexport interface Referral {\n /** The partner's code. */\n code: string;\n /** The click MRRocket counted (tracked link or beacon); null when it was not counted. */\n clickId: string | null;\n /** When the visitor arrived through the partner, ms. */\n at: number;\n}\n\n/** What to pass to Stripe Checkout (`stripe.checkout.sessions.create({ ..., ...referralForCheckout() })`). */\nexport interface CheckoutReferral {\n client_reference_id: string;\n metadata: { mrr_ref: string; mrr_click: string };\n}\n\nexport type AttributionMode = \"consent\" | \"always\" | \"off\";\n\nexport const REFERRAL_COOKIE = \"mrr_ref\";\nexport const REFERRAL_STORAGE_KEY = \"mrr_ref\";\nexport const REF_PARAM = \"mrr_ref\";\nexport const CLICK_PARAM = \"mrr_click\";\nexport const DEFAULT_REFERRAL_DAYS = 60;\n\nconst CODE = /^[A-Za-z0-9_-]{1,64}$/;\nconst DAY_MS = 86_400_000;\n\n/** The referral in the landing URL: the tracked link's markers first, else the direct-link parameter (`ref`). */\nexport const readReferralParams = (search: string, param = \"ref\"): { code: string; clickId: string | null; direct: boolean } | null => {\n const q = new URLSearchParams(search);\n return referralFrom((k) => q.get(k), param);\n};\n\n/** The same from a parameter lookup, for runtimes without `URLSearchParams` (React Native deep links). */\nexport const referralFrom = (get: (name: string) => string | null | undefined, param = \"ref\"): { code: string; clickId: string | null; direct: boolean } | null => {\n const marked = get(REF_PARAM);\n if (marked && CODE.test(marked)) {\n const click = get(CLICK_PARAM);\n return { code: marked, clickId: click && CODE.test(click) ? click : null, direct: false };\n }\n const direct = get(param);\n return direct && CODE.test(direct) ? { code: direct, clickId: null, direct: true } : null;\n};\n\n/** `code.clickId.at`: dots never occur in a code or a click id. */\nexport const encodeReferral = (r: Referral) => `${r.code}.${r.clickId ?? \"\"}.${r.at}`;\n\n/** A stored referral, or null when it is malformed or older than `maxDays`. */\nexport const decodeReferral = (value: string | null | undefined, maxDays = DEFAULT_REFERRAL_DAYS, now = Date.now()): Referral | null => {\n if (!value) return null;\n const [code, click, at] = value.split(\".\");\n const t = Number(at);\n if (!code || !CODE.test(code) || !Number.isFinite(t) || (click && !CODE.test(click))) return null;\n if (now - t > maxDays * DAY_MS || t > now + DAY_MS) return null;\n return { code, clickId: click || null, at: t };\n};\n\n/** The referral for a Stripe Checkout Session: `client_reference_id` and `metadata`. Null without a referral. */\nexport const referralForCheckout = (r: Referral | null = getReferral()): CheckoutReferral | null =>\n r ? { client_reference_id: `mrr_ref:${r.code}:${r.clickId ?? \"\"}`, metadata: { mrr_ref: r.code, mrr_click: r.clickId ?? \"\" } } : null;\n\n/**\n * A Stripe Payment Link (or Pricing Table URL) with the referral as `client_reference_id`. Payment Links only accept\n * letters, digits, `-` and `_` there, so the form is `mrr_ref__<code>__<clickId>`. Without a referral the URL is unchanged.\n */\nexport const referralLink = (url: string, r: Referral | null = getReferral()) => {\n if (!r) return url;\n try {\n const u = new URL(url);\n u.searchParams.set(\"client_reference_id\", `mrr_ref__${r.code}__${r.clickId ?? \"\"}`);\n return u.toString();\n } catch {\n return url;\n }\n};\n\n// ---------- The browser side ----------\n\nlet current: Referral | null = null;\n\nconst hasDocument = () => typeof document !== \"undefined\";\n\nconst readCookie = (name: string) => {\n if (!hasDocument()) return undefined;\n const raw = document.cookie\n .split(\"; \")\n .find((c) => c.startsWith(`${name}=`))\n ?.slice(name.length + 1);\n try {\n return raw ? decodeURIComponent(raw) : undefined;\n } catch {\n return raw;\n }\n};\n\nconst storage = () => {\n try {\n return typeof localStorage === \"undefined\" ? null : localStorage;\n } catch {\n return null;\n }\n};\n\n/** The visitor's referral: this page load's, else the stored one. Null on the server (use `readReferralCookie` there). */\nexport const getReferral = (): Referral | null => {\n if (current) return current;\n if (!hasDocument()) return null;\n return decodeReferral(readCookie(REFERRAL_COOKIE), 3650) ?? decodeReferral(storage()?.getItem(REFERRAL_STORAGE_KEY), 3650);\n};\n\n/** The referral from the `mrr_ref` cookie's value, for server code (a route that creates the Checkout Session). */\nexport const readReferralCookie = (value: string | null | undefined) => decodeReferral(value, 3650);\n\n/** Writes the referral to the first-party cookie and localStorage for `days`. */\nexport const storeReferral = (r: Referral, days: number) => {\n if (!hasDocument()) return;\n const maxAge = Math.max(1, Math.round(days)) * 86_400;\n const secure = typeof location !== \"undefined\" && location.protocol === \"https:\" ? \"; secure\" : \"\";\n document.cookie = `${REFERRAL_COOKIE}=${encodeURIComponent(encodeReferral(r))}; path=/; max-age=${maxAge}; samesite=lax${secure}`;\n try {\n storage()?.setItem(REFERRAL_STORAGE_KEY, encodeReferral(r));\n } catch {\n // Storage full or blocked: the cookie is enough.\n }\n};\n\n/** Deletes what was stored (consent withdrawn); the referral of this page load stays in memory. */\nexport const forgetStoredReferral = () => {\n if (!hasDocument()) return;\n document.cookie = `${REFERRAL_COOKIE}=; path=/; max-age=0; samesite=lax`;\n try {\n storage()?.removeItem(REFERRAL_STORAGE_KEY);\n } catch {\n // Nothing stored.\n }\n};\n\n/** For tests and `consent=\"off\"`: forget the page load's referral too. */\nexport const resetReferral = () => {\n current = null;\n};\n\nexport interface CaptureOptions {\n /** `location.search` of the landing page. */\n search: string;\n /** The direct-link parameter, default `ref`. */\n param?: string;\n /** May the referral be stored (consent)? */\n store: boolean;\n /** Days to keep it. */\n days: number;\n /** Sends the click beacon; answers the click id MRRocket counted (or confirmed). */\n beacon?: (body: { code: string; clickId: string | null }) => Promise<string | null>;\n now?: number;\n}\n\n/**\n * Reads the referral of a page load: a new one from the URL (sent to the beacon and stored when allowed) or the stored\n * one. A new link replaces an older referral (last click within the window wins). Returns the referral in effect.\n */\nexport const captureReferral = async (o: CaptureOptions): Promise<Referral | null> => {\n const found = readReferralParams(o.search, o.param);\n const now = o.now ?? Date.now();\n if (!found) {\n if (!current && o.store) {\n current = decodeReferral(readCookie(REFERRAL_COOKIE), o.days, now) ?? decodeReferral(storage()?.getItem(REFERRAL_STORAGE_KEY), o.days, now);\n if (!current) forgetStoredReferral();\n }\n return current;\n }\n current = { code: found.code, clickId: found.clickId, at: now };\n if (o.store) storeReferral(current, o.days);\n if (o.beacon) {\n try {\n const id = await o.beacon({ code: found.code, clickId: found.clickId });\n if (id && current && current.code === found.code && !current.clickId) {\n current = { ...current, clickId: id };\n if (o.store) storeReferral(current, o.days);\n }\n } catch {\n // The referral still counts for checkout without a click id.\n }\n }\n return current;\n};\n\n/** Events that carry the referral: identify, signup and your own events (not page views or exposures). */\nexport const carriesReferral = (event: string) => event === \"$identify\" || !event.startsWith(\"$\");\n","/**\n * The React Native client without React: the event queue (batched, persisted for offline use, retried with backoff),\n * the app lifecycle (`$app_open`, `$app_background`, a new session after 30 minutes away), screens, identity and\n * consent, the cached config for flags and experiments, install attribution from the first open's deep link, and error\n * capture. Everything the platform gives (storage, AppState, ErrorUtils, device info, fetch) comes in as `deps`, so\n * it runs in tests without React Native; `platform.ts` builds the real ones.\n */\nimport { type Api, createApi } from \"../api-client\";\nimport { type SdkInfo, batchRequests } from \"../batch\";\nimport {\n type AppContext,\n type CockpitConfig,\n type CockpitEvent,\n type ErrorReport,\n SDK_VERSION,\n SESSION_TIMEOUT_MS,\n type UtmKey,\n type VariantId,\n experimentsOfText,\n flagFor,\n newDistinctId,\n parseQuery,\n resolveVariant,\n textChanges,\n utmFrom,\n} from \"../core\";\nimport { describeError } from \"../errors\";\nimport { type CancelFlowOptions, type CancelFlowResult, type FlowsController, type InAppState, createFlows } from \"../flows\";\nimport { RageDetector } from \"../rage\";\nimport { type Recorder, type RecorderDeps, createRecorder } from \"./recorder\";\nimport { carriesReferral, referralFrom } from \"../referral\";\n\n/**\n * What the app may send and store.\n * - \"anonymous\" (default): no id is stored on the device. Events go without a person id until `identify()` (MRRocket\n * counts visitors by its daily hash); flags and experiments use a random id that lives until the app is closed.\n * - \"persistent\": a random install id is stored on the device (removed with the app) and sent with every event.\n * - \"off\": nothing is sent, and what the SDK stored is deleted.\n */\nexport type NativeConsent = \"anonymous\" | \"persistent\" | \"off\";\n\nexport interface MRRocketOptions {\n /** The product's public key (MRRocket › Settings › Products), the same as on the website. */\n apiKey: string;\n /** Where MRRocket runs. Default `https://app.mrrocket.dev`. */\n host?: string;\n /** Default \"anonymous\". The SDK does not remember it: pass it on every start (from your consent screen's stored answer). */\n consent?: NativeConsent;\n /** Uncaught JavaScript errors and `captureError` go to Build › Errors (default true). */\n errors?: boolean;\n /** Your release, for Build › Errors. Default: the app version and build, like \"1.4.0 (42)\". */\n release?: string;\n /** `$app_open` and `$app_background` events (default true). */\n lifecycle?: boolean;\n /** Read UTM and referral parameters of the deep link that opened the app the first time, sent with `$install` (default true). */\n attribution?: boolean;\n /** How often the queue is sent while the app is open, in ms (default 10 000). It is also sent when the app goes to the background. */\n flushIntervalMs?: number;\n /** At most this many events wait on the device; the oldest go first (default 1,000). */\n maxQueue?: number;\n /** Log what the SDK does to the console. */\n debug?: boolean;\n /** Onboarding flows start on their own when the person does their trigger (default true). False: only `startOnboarding()`. */\n onboarding?: boolean;\n /** Taps go to Heatmaps as clicks on the screen they happened on (default true; `MRRocketProvider` captures them). */\n heatmaps?: boolean;\n /**\n * The person agreed to session recordings (default false; ask them first). Needs `react-native-view-shot` and the\n * product's recordings switched on in MRRocket. No frame while the keyboard is open; wrap private views in\n * `<MRRocketMask>`. Change it later with `setReplay`.\n */\n replay?: boolean;\n}\n\n/** AsyncStorage's shape. */\nexport interface KeyValueStorage {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n/** React Native's AppState. */\nexport interface AppStateLike {\n currentState?: string | null;\n addEventListener(type: \"change\", listener: (state: string) => void): { remove(): void } | undefined;\n}\n\n/** React Native's global ErrorUtils. */\nexport interface ErrorUtilsLike {\n getGlobalHandler(): ((error: unknown, isFatal?: boolean) => void) | undefined;\n setGlobalHandler(handler: (error: unknown, isFatal?: boolean) => void): void;\n}\n\nexport type FetchLike = (\n url: string,\n init: { method?: string; headers?: Record<string, string>; body?: string; signal?: AbortSignal },\n) => Promise<{ ok: boolean; status: number; json(): Promise<unknown> }>;\n\nexport interface NativeDeps {\n /** Null: everything stays in memory (no offline queue, no install attribution). */\n storage: KeyValueStorage | null;\n fetch: FetchLike;\n appState: AppStateLike | null;\n errorUtils: ErrorUtilsLike | null;\n /** The app and device, read once at start. */\n context: () => AppContext;\n /** The app's id (bundle id), for the `app://<id>/<screen>` address of events. */\n appId?: string;\n /** The screen size in points. */\n screen?: () => { w: number; h: number } | undefined;\n /** The deep link that opened the app (`Linking.getInitialURL`). */\n initialUrl?: () => Promise<string | null>;\n /** Opens an in-app message's link (`Linking.openURL`). */\n openUrl?: (url: string) => void;\n /** Push notifications through `expo-notifications`, when the app has it installed. */\n push?: PushDeps | null;\n /** Screen frames for session recordings, when the app has `react-native-view-shot` (platform.ts). */\n recorder?: Pick<RecorderDeps, \"capture\" | \"keyboardOpen\" | \"masks\"> | null;\n now?: () => number;\n setInterval?: (fn: () => void, ms: number) => unknown;\n clearInterval?: (id: unknown) => void;\n setTimeout?: (fn: () => void, ms: number) => unknown;\n clearTimeout?: (id: unknown) => void;\n log?: (message: string) => void;\n}\n\n/** What a journey's push step carries in the notification's data, so an open is counted on the step. */\nexport interface PushData {\n mrrocket?: { id?: string; url?: string };\n}\n\n/** What `registerForPush` needs of `expo-notifications` (platform.ts wraps it; tests pass a fake). */\nexport interface PushDeps {\n /** The permission now, after asking when `ask` and it was not decided yet. */\n permission(ask: boolean): Promise<\"granted\" | \"denied\" | \"undetermined\">;\n /** The Expo push token (`ExponentPushToken[…]`), or null when the device has none (a simulator). */\n token(projectId?: string): Promise<string | null>;\n /** Calls `listener` with the data of every notification the person opens; returns the unsubscribe. */\n onOpen(listener: (data: PushData) => void): () => void;\n /** The notification that opened the app from a cold start, if any. */\n lastOpen?(): Promise<PushData | null>;\n}\n\nexport interface RegisterForPushOptions {\n /** Ask for the permission when it was not decided yet (default true). False: only register when already allowed. */\n ask?: boolean;\n /** Your EAS project id; default: the one in your app config (`expo-constants`). */\n projectId?: string;\n}\n\nexport type NativePushStatus = \"registered\" | \"denied\" | \"not-asked\" | \"unavailable\" | \"not-signed-in\" | \"error\";\n\nexport interface NativePushResult {\n status: NativePushStatus;\n /** The Expo push token, once registered. */\n token?: string;\n /** Why it is unavailable or failed. */\n reason?: string;\n}\n\n/** What the app (and the React hooks) use. */\nexport interface MRRocketClient {\n track(event: string, props?: Record<string, unknown>): void;\n /** A screen view: a route name (\"Settings\") or an Expo Router path (\"/settings\"). */\n screen(name: string, props?: Record<string, unknown>): void;\n /** A tap at screen points (x, y) for Heatmaps, on the current screen; `MRRocketProvider` calls it. */\n tap(x: number, y: number): void;\n /** The person's answer to session recordings (`replay` in the options); false stops and forgets what was not sent. */\n setReplay(on: boolean): void;\n identify(id: string, props?: Record<string, unknown>): void;\n /** Forgets the signed-in person (sign-out): a new anonymous id and a new session. */\n reset(): void;\n setConsent(consent: NativeConsent): void;\n captureError(error: unknown): void;\n getFlag(key: string): boolean;\n getFlagVariant(key: string): string | null;\n /** The variant of an experiment (\"control\" until the config is known); records the exposure once per screen. */\n getVariant(key: string): VariantId;\n /** The variant without recording anything (render code); pair it with `expose`. */\n peekVariant(key: string): VariantId;\n /** Records that the person saw `variant` of `key`, once per screen. */\n expose(key: string, variant: VariantId): void;\n /**\n * The copy for text `id` as published in MRRocket (a paywall's `paywall.<placement>.headline`, an onboarding title …)\n * with this person's experiment variant applied on top, the same rules as `<Text id>` on the web; `fallback` (your\n * own words) while nothing is published or the config is unknown. Records the exposure to every test that changes\n * `id`, once per screen.\n */\n getText(id: string, fallback: string): string;\n /** The text without recording anything (render code); undefined when MRRocket has none. Pair it with `exposeText`. */\n peekText(id: string): string | undefined;\n /** Records that the person saw text `id`: an exposure to each test that changes it, once per screen. */\n exposeText(id: string): void;\n /**\n * Shows the cancel flow built in MRRocket › Churn (drawn by `<MRRocketProvider>`), resolves with what the customer\n * did. MRRocket never changes the subscription: your `onCancel` and `onSave` do.\n */\n openCancelFlow(options?: CancelFlowOptions): Promise<CancelFlowResult>;\n /** Starts an onboarding flow now (the first live one without an id). False when there is none. */\n startOnboarding(id?: string): boolean;\n /**\n * Push notifications from your Lifecycle journeys for the signed-in person (call `identify` first). Asks the\n * permission (unless `ask: false`), gets the Expo push token and sends it to MRRocket. Needs `expo-notifications`.\n * Safe to call on every start: an existing token is sent again without asking. Opens of MRRocket's notifications\n * are counted from then on.\n */\n registerForPush(options?: RegisterForPushOptions): Promise<NativePushResult>;\n /** Removes this device's token for the signed-in person (sign-out does it on its own in `reset`). */\n unregisterForPush(): Promise<boolean>;\n /** The cancel flow, onboarding and messages for a renderer (the provider's, or your own). */\n flows: FlowsController;\n /** Sends what is queued now. */\n flush(): Promise<void>;\n /** Resolves once stored state and the config (cached or fetched) are known. */\n ready: Promise<void>;\n isReady(): boolean;\n getDistinctId(): string;\n getConsent(): NativeConsent;\n /**\n * The client of the SDK's widget API (surveys, feedback, the messenger) for the person now: their id, and the name and\n * email given to identify (or `as`, typed into a widget). Null while the consent is off or without a key.\n */\n api(as?: { name?: string; email?: string }): Api | null;\n /** The signed-in person (identify): their id, and the name and email given there. Undefined before identify. */\n getUser(): { id: string; name?: string; email?: string } | undefined;\n /** Surveys answered or closed on this device: not shown again (kept on the device only with \"persistent\"). */\n isSurveyDone(id: string): boolean;\n markSurveyDone(id: string): void;\n getConfig(): CockpitConfig | null;\n /** For React: called after every change flags, variants or the consent depend on. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void;\n /** Grows with every such change (useSyncExternalStore's snapshot). */\n getVersion(): number;\n /** Stops timers and listeners and sends what is queued (tests, or an app that tears the SDK down). */\n close(): Promise<void>;\n /** For tests: what waits to be sent. */\n queued(): readonly CockpitEvent[];\n}\n\nexport const DEFAULT_HOST = \"https://app.mrrocket.dev\";\n/** Storage keys. */\nexport const KEYS = {\n id: \"mrrocket:id\",\n queue: \"mrrocket:queue\",\n config: \"mrrocket:config\",\n installed: \"mrrocket:installed\",\n referral: \"mrrocket:referral\",\n surveys: \"mrrocket:surveys\",\n} as const;\n\nconst MAX_ERRORS = 20;\nconst MAX_CRUMBS = 20;\nconst MAX_BACKOFF_MS = 5 * 60 * 1000;\nconst REQUEST_TIMEOUT_MS = 15_000;\n/** A batch is sent early once this many events wait. */\nconst EAGER_COUNT = 20;\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}…` : s);\n\nexport const createClient = (options: MRRocketOptions, deps: NativeDeps): MRRocketClient => {\n const apiKey = (options.apiKey ?? \"\").trim();\n const host = (options.host ?? DEFAULT_HOST).trim().replace(/\\/+$/, \"\");\n const now = deps.now ?? (() => Date.now());\n const setIntervalFn = deps.setInterval ?? ((fn, ms) => setInterval(fn, ms));\n const clearIntervalFn = deps.clearInterval ?? ((id) => clearInterval(id as ReturnType<typeof setInterval>));\n const setTimeoutFn = deps.setTimeout ?? ((fn, ms) => setTimeout(fn, ms));\n const clearTimeoutFn = deps.clearTimeout ?? ((id) => clearTimeout(id as ReturnType<typeof setTimeout>));\n const flushEvery = Math.max(1000, options.flushIntervalMs ?? 10_000);\n const maxQueue = Math.max(10, options.maxQueue ?? 1000);\n const errorsOn = options.errors !== false;\n const storage = deps.storage;\n\n const warned = new Set<string>();\n const warn = (message: string) => {\n if (warned.has(message)) return;\n warned.add(message);\n (deps.log ?? ((m: string) => console.warn(m)))(`[MRRocket] ${message}`);\n };\n const debug = (message: string) => {\n if (options.debug) (deps.log ?? ((m: string) => console.log(m)))(`[MRRocket] ${message}`);\n };\n if (!apiKey) warn(\"No public key. Pass apiKey to MRRocketProvider; nothing is sent until then.\");\n\n let context: AppContext = { platform: \"unknown\" };\n try {\n context = deps.context();\n } catch {\n // Device details are optional.\n }\n const appId = (deps.appId || \"app\").replace(/[^A-Za-z0-9._-]/g, \"\") || \"app\";\n const release = options.release ?? (context.appVersion ? `${context.appVersion}${context.build ? ` (${context.build})` : \"\"}` : undefined);\n const sdk: SdkInfo = { v: SDK_VERSION, errors: errorsOn, platform: context.platform };\n\n let consent: NativeConsent = options.consent ?? \"anonymous\";\n let installId: string | null = null;\n let memoryId = newDistinctId();\n let identified: string | undefined;\n let person: Record<string, unknown> | undefined;\n let config: CockpitConfig | null = null;\n let queue: CockpitEvent[] = [];\n let session: { id: string; last: number } | null = null;\n // The first open's campaign rides on the events of its session only.\n let utm: { session: string; values: Partial<Record<UtmKey, string>> } | null = null;\n let referral: { code: string; clickId: string | null } | null = null;\n let currentScreen: string | undefined;\n let loaded = false;\n let closed = false;\n let isReady = false;\n let version = 0;\n let failures = 0;\n let backoffUntil = 0;\n let inFlight: Promise<void> | null = null;\n let persistTimer: unknown = null;\n let flushTimer: unknown = null;\n let errorTimer: unknown = null;\n let appState = deps.appState?.currentState ?? \"active\";\n let backgroundSince: number | null = null;\n const early: (() => void)[] = [];\n const exposed = new Set<string>();\n const surveysDone = new Set<string>();\n const rage = new RageDetector();\n // The texts for this config and person, recomputed only when either changes.\n let textsFor: { config: CockpitConfig | null; id: string; texts: Record<string, string> } | null = null;\n const texts = () => {\n const id = distinctId();\n if (!textsFor || textsFor.config !== config || textsFor.id !== id) textsFor = { config, id, texts: textChanges(config, id, {}) };\n return textsFor.texts;\n };\n const listeners = new Set<() => void>();\n const crumbs: NonNullable<ErrorReport[\"crumbs\"]> = [];\n const errorQueue: ErrorReport[] = [];\n const errorsSeen = new Set<string>();\n let errorsSent = 0;\n\n // The cancel flow, onboarding and in-app messages (../flows.ts); `<MRRocketProvider>` draws them.\n const flows = createFlows({\n track: (event, props) => record(event, props),\n personId: () => (consent !== \"off\" ? identified : undefined),\n auto: options.onboarding !== false,\n storage: () =>\n storage && consent === \"persistent\"\n ? {\n get: (k: string) => get(k),\n set: (k: string, v: string) => void set(k, v),\n }\n : null,\n openUrl: deps.openUrl,\n fetchInApp: async (id) => {\n if (!apiKey) return null;\n const r = await deps.fetch(`${host}/api/sdk/inapp?key=${encodeURIComponent(apiKey)}&distinctId=${encodeURIComponent(id)}`, { method: \"GET\" });\n return r.ok ? ((await r.json()) as InAppState) : null;\n },\n });\n const refreshFlows = () => {\n if (!isReady || closed) return;\n flows.setConfig(config);\n void flows.refresh();\n };\n\n // Created below once sending is defined; `changed` keeps its frame loop in step with consent and config.\n let recorder: Recorder | null = null;\n const changed = () => {\n version++;\n recorder?.sync(appState === \"active\");\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // A listener must not stop the others.\n }\n }\n };\n\n const crumb = (type: \"navigation\" | \"click\" | \"lifecycle\", message: string) => {\n crumbs.push({ ts: now(), type, message: clip(message, 120) });\n if (crumbs.length > MAX_CRUMBS) crumbs.shift();\n };\n\n // ---------- Storage (every call may fail: storage full, native module missing) ----------\n\n const get = async (key: string) => {\n if (!storage) return null;\n try {\n return await storage.getItem(key);\n } catch {\n return null;\n }\n };\n const set = async (key: string, value: string) => {\n if (!storage) return;\n try {\n await storage.setItem(key, value);\n } catch {\n warn(\"Could not write to the device storage; events wait in memory only.\");\n }\n };\n const remove = async (key: string) => {\n if (!storage) return;\n try {\n await storage.removeItem(key);\n } catch {\n // Nothing stored.\n }\n };\n\n const persistQueue = async () => {\n if (persistTimer !== null) {\n clearTimeoutFn(persistTimer);\n persistTimer = null;\n }\n if (!storage || consent === \"off\") return;\n if (queue.length) await set(KEYS.queue, JSON.stringify(queue));\n else await remove(KEYS.queue);\n };\n const schedulePersist = () => {\n if (!storage || persistTimer !== null) return;\n persistTimer = setTimeoutFn(() => {\n persistTimer = null;\n void persistQueue();\n }, 1000);\n };\n\n // ---------- Identity and session ----------\n\n const distinctId = () => identified ?? (consent === \"persistent\" && installId ? installId : memoryId);\n // Without the persistent id, events carry an id only after identify(); the server counts everyone else by its daily hash.\n const sendId = () => (consent === \"persistent\" ? distinctId() : identified);\n\n const touchSession = () => {\n const t = now();\n if (!session || t - session.last >= SESSION_TIMEOUT_MS) session = { id: newDistinctId(), last: t };\n else session.last = t;\n return session.id;\n };\n\n const urlOf = (path = currentScreen) => `app://${appId}${path ?? \"/\"}`;\n\n // ---------- Recording ----------\n\n const record = (event: string, props?: Record<string, unknown>, ts = now()) => {\n if (closed) return;\n if (!loaded) {\n early.push(() => record(event, props, ts));\n return;\n }\n if (consent === \"off\" || !apiKey) return;\n const sessionId = touchSession();\n const ref = referral && carriesReferral(event) ? referral : null;\n const size = deps.screen?.();\n queue.push({\n event,\n props: ref ? { ...props, $referral: ref } : props,\n distinctId: sendId(),\n sessionId,\n ts,\n url: urlOf(),\n ...(utm && utm.session === sessionId ? utm.values : {}),\n ...(size ? { screen: { w: Math.round(size.w), h: Math.round(size.h) } } : {}),\n app: context,\n });\n if (queue.length > maxQueue) queue.splice(0, queue.length - maxQueue);\n schedulePersist();\n if (queue.length >= EAGER_COUNT) void flush();\n };\n\n // ---------- Sending ----------\n\n const post = async (path: string, body: string): Promise<number> => {\n const ctl = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ctl ? setTimeoutFn(() => ctl.abort(), REQUEST_TIMEOUT_MS) : null;\n try {\n const r = await deps.fetch(`${host}${path}`, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body, signal: ctl?.signal });\n return r.status;\n } catch {\n return 0;\n } finally {\n if (timer !== null) clearTimeoutFn(timer);\n }\n };\n\n const sendQueue = async () => {\n if (!queue.length || consent === \"off\" || !apiKey) return;\n if (now() < backoffUntil) return;\n const snapshot = queue.slice();\n const requests = batchRequests(apiKey, snapshot, sdk);\n const included = new Set(requests.flatMap((r) => r.events));\n const done = new Set<CockpitEvent>();\n for (const r of requests) {\n const status = await post(\"/api/sdk/events\", r.body);\n if (status >= 200 && status < 300) {\n r.events.forEach((e) => done.add(e));\n failures = 0;\n backoffUntil = 0;\n } else if (status >= 400 && status < 500 && status !== 408 && status !== 429) {\n // Will never be accepted (a wrong key, a malformed event): drop instead of retrying forever.\n r.events.forEach((e) => done.add(e));\n warn(`Events were rejected with ${status}. Check the public key (MRRocket › Settings › Products) and the host.`);\n } else {\n failures++;\n backoffUntil = now() + Math.min(MAX_BACKOFF_MS, 1000 * 2 ** failures);\n debug(`Sending failed (${status || \"offline\"}); next try in ${Math.round((backoffUntil - now()) / 1000)} s.`);\n break;\n }\n }\n // Sent, rejected, or too large to ever fit in a request: out of the queue. Newer events stay.\n queue = queue.filter((e) => !done.has(e) && (included.has(e) || !snapshot.includes(e)));\n await persistQueue();\n };\n\n // A flush asked for while one runs follows it, so events queued meanwhile go too.\n let nextFlush: Promise<void> | null = null;\n const flush = (): Promise<void> => {\n if (inFlight)\n return (nextFlush ??= inFlight.then(() => {\n nextFlush = null;\n return flush();\n }));\n inFlight = sendQueue().finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n\n const startTimer = () => {\n if (flushTimer !== null || closed) return;\n flushTimer = setIntervalFn(() => void flush(), flushEvery);\n };\n const stopTimer = () => {\n if (flushTimer === null) return;\n clearIntervalFn(flushTimer);\n flushTimer = null;\n };\n\n // ---------- Errors ----------\n\n const sendErrors = async () => {\n if (errorTimer !== null) {\n clearTimeoutFn(errorTimer);\n errorTimer = null;\n }\n while (errorQueue.length) {\n // Four full stacks stay under the server's 64 KB.\n const batch = errorQueue.splice(0, 4);\n const status = await post(\"/api/sdk/errors\", JSON.stringify({ key: apiKey, sdk, errors: batch }));\n if (status >= 400 && status < 500 && status !== 429) warn(`Error reports were rejected with ${status}. Check the public key and the host.`);\n }\n };\n\n const capture = (error: unknown, mechanism: ErrorReport[\"mechanism\"], fatal = false) => {\n if (!errorsOn || closed || consent === \"off\" || !apiKey || errorsSent >= MAX_ERRORS) return;\n const d = describeError(error);\n if (/\\/api\\/sdk\\/errors/.test(d.message)) return;\n const mark = `${d.type}:${d.message}`;\n if (errorsSeen.has(mark)) return;\n errorsSeen.add(mark);\n errorsSent++;\n const who = sendId();\n errorQueue.push({\n ...d,\n mechanism,\n handled: mechanism === \"manual\",\n url: urlOf(),\n ts: now(),\n crumbs: crumbs.slice(),\n ...(release ? { release } : {}),\n ...(who ? { distinctId: who } : {}),\n ...(session ? { sessionId: session.id } : {}),\n });\n recorder?.mark({ kind: \"error\", path: currentScreen ?? \"/\", label: clip(d.message, 120) });\n recorder?.trigger(\"error\");\n // A fatal error ends the app: send at once (it may still not make it); others wait for company.\n if (fatal) void sendErrors();\n else if (errorTimer === null) errorTimer = setTimeoutFn(() => void sendErrors(), 2000);\n };\n\n let previousHandler: ((error: unknown, isFatal?: boolean) => void) | undefined;\n let handlerInstalled = false;\n const installErrorHandler = () => {\n if (!errorsOn || !deps.errorUtils || handlerInstalled) return;\n handlerInstalled = true;\n previousHandler = deps.errorUtils.getGlobalHandler();\n deps.errorUtils.setGlobalHandler((error, isFatal) => {\n try {\n capture(error, \"onerror\", !!isFatal);\n } catch {\n // Reporting must never change how the app handles its error.\n }\n previousHandler?.(error, isFatal);\n });\n };\n\n // ---------- Session recordings ----------\n\n let replayOn = options.replay === true;\n recorder = deps.recorder\n ? createRecorder(\n {\n now,\n setInterval: setIntervalFn,\n clearInterval: clearIntervalFn,\n capture: deps.recorder.capture,\n keyboardOpen: deps.recorder.keyboardOpen,\n masks: deps.recorder.masks,\n screen: () => deps.screen?.(),\n send: (body) => post(\"/api/sdk/replay\", body),\n },\n {\n allowed: () => replayOn && loaded && !closed && consent !== \"off\" && !!apiKey,\n config: () => config?.replay,\n session: () => session?.id ?? touchSession(),\n who: () => ({ distinctId: sendId(), identified: !!identified }),\n apiKey,\n app: context,\n },\n )\n : null;\n if (options.replay && !deps.recorder) warn(\"Session recordings need react-native-view-shot: npx expo install react-native-view-shot\");\n\n // ---------- Lifecycle ----------\n\n let appStateSub: { remove(): void } | undefined;\n const onAppState = (next: string) => {\n if (closed) return;\n const prev = appState;\n appState = next;\n recorder?.sync(next === \"active\");\n if (next === \"active\" && prev !== \"active\") {\n startTimer();\n if (backgroundSince !== null) {\n // Back from the background: a new session after 30 minutes away (the session rule does it by itself).\n backgroundSince = null;\n crumb(\"lifecycle\", \"app_open\");\n if (options.lifecycle !== false) record(\"$app_open\", { cold: false });\n }\n } else if (next === \"background\" && prev !== \"background\") {\n backgroundSince = now();\n crumb(\"lifecycle\", \"app_background\");\n if (options.lifecycle !== false) record(\"$app_background\");\n stopTimer();\n void recorder?.flush();\n // The system gives a few seconds in the background: send now, and keep the rest on the device.\n void persistQueue();\n void flush();\n if (errorQueue.length) void sendErrors();\n }\n };\n\n // ---------- Config ----------\n\n const fetchConfig = async () => {\n if (!apiKey) return;\n try {\n const r = await deps.fetch(`${host}/api/sdk/config?key=${encodeURIComponent(apiKey)}`, { method: \"GET\" });\n if (!r.ok) {\n warn(`Config request answered ${r.status}. Check the public key and the host.`);\n return;\n }\n const c = (await r.json()) as CockpitConfig | null;\n if (c && Array.isArray(c.experiments)) {\n config = c;\n if (consent !== \"off\") await set(KEYS.config, JSON.stringify(c));\n changed();\n }\n } catch {\n debug(\"Config not reachable; using the cached one.\");\n }\n };\n\n // ---------- Push ----------\n\n // The token this run registered, and for whom, so sign-out (`reset`) can take it back.\n let pushToken: string | null = null;\n let pushFor: string | undefined;\n let pushOff: (() => void) | null = null;\n const opened = new Set<string>();\n\n /** A MRRocket notification the person opened: counted on its journey step, its link opened when it is a full address. */\n const onPushOpen = (data: PushData | null | undefined) => {\n const m = data?.mrrocket;\n if (!m?.id || opened.has(m.id)) return;\n opened.add(m.id);\n record(\"$push\", { action: \"opened\", message: m.id });\n if (m.url && /^[a-z][a-z0-9+.-]*:/i.test(m.url)) deps.openUrl?.(m.url);\n };\n const listenForOpens = () => {\n if (pushOff || !deps.push || closed) return;\n try {\n pushOff = deps.push.onOpen(onPushOpen);\n void deps.push\n .lastOpen?.()\n .then(onPushOpen)\n .catch(() => undefined);\n } catch {\n pushOff = null;\n }\n };\n\n const loadedNow = () =>\n loaded\n ? Promise.resolve()\n : new Promise<void>((resolve) => {\n early.push(resolve);\n });\n\n const registerForPush = async (o: RegisterForPushOptions = {}): Promise<NativePushResult> => {\n if (!deps.push) return { status: \"unavailable\", reason: \"Install expo-notifications to receive push notifications.\" };\n await loadedNow();\n if (!apiKey || consent === \"off\") return { status: \"error\", reason: !apiKey ? \"No public key.\" : \"The consent is off.\" };\n if (!identified) return { status: \"not-signed-in\" };\n const who = identified;\n try {\n const permission = await deps.push.permission(o.ask !== false);\n if (permission !== \"granted\") return { status: permission === \"denied\" ? \"denied\" : \"not-asked\" };\n const token = await deps.push.token(o.projectId);\n if (!token) return { status: \"unavailable\", reason: \"This device has no push token (a simulator, or no EAS project id).\" };\n const status = await post(\"/api/sdk/push\", JSON.stringify({ key: apiKey, distinctId: who, platform: \"expo\", token, app: context }));\n if (status < 200 || status >= 300) {\n warn(`Push registration was rejected with ${status || \"no answer\"}. Check the public key and the host.`);\n return { status: \"error\", reason: `MRRocket answered ${status || \"nothing\"}.` };\n }\n pushToken = token;\n pushFor = who;\n listenForOpens();\n debug(\"Registered for push.\");\n return { status: \"registered\", token };\n } catch (e) {\n return { status: \"error\", reason: e instanceof Error ? e.message : String(e) };\n }\n };\n\n const unregisterForPush = async () => {\n const token = pushToken;\n if (!token || !apiKey) return false;\n pushToken = null;\n const status = await post(\"/api/sdk/push\", JSON.stringify({ key: apiKey, distinctId: pushFor, platform: \"expo\", token, remove: true }));\n return status >= 200 && status < 300;\n };\n\n // ---------- Start ----------\n\n let resolveReady: () => void = () => {};\n const ready = new Promise<void>((r) => {\n resolveReady = r;\n });\n const markReady = () => {\n if (isReady) return;\n isReady = true;\n resolveReady();\n changed();\n };\n\n const start = async () => {\n let firstOpen = false;\n if (consent !== \"off\") {\n const [id, stored, cached, installed, ref, surveys] = await Promise.all([\n get(KEYS.id),\n get(KEYS.queue),\n get(KEYS.config),\n get(KEYS.installed),\n get(KEYS.referral),\n get(KEYS.surveys),\n ]);\n if (consent === \"persistent\") {\n installId = id || newDistinctId();\n if (!id) await set(KEYS.id, installId);\n } else if (id) await remove(KEYS.id);\n try {\n const old = stored ? (JSON.parse(stored) as CockpitEvent[]) : [];\n if (Array.isArray(old)) queue = [...old.filter((e) => e && typeof e.event === \"string\"), ...queue].slice(-maxQueue);\n } catch {\n await remove(KEYS.queue);\n }\n try {\n const c = cached ? (JSON.parse(cached) as CockpitConfig) : null;\n if (c && Array.isArray(c.experiments) && !config) config = c;\n } catch {\n await remove(KEYS.config);\n }\n try {\n const r = ref && consent === \"persistent\" ? (JSON.parse(ref) as { code: string; clickId: string | null }) : null;\n if (r && typeof r.code === \"string\") referral = r;\n } catch {\n // Ignore a damaged referral.\n }\n try {\n const done = surveys && consent === \"persistent\" ? (JSON.parse(surveys) as unknown) : null;\n if (Array.isArray(done)) for (const x of done) if (typeof x === \"string\") surveysDone.add(x);\n } catch {\n await remove(KEYS.surveys);\n }\n // Without storage there is no telling a first open from any other: no $install then.\n firstOpen = !!storage && !installed;\n if (firstOpen) await set(KEYS.installed, String(now()));\n } else {\n await Promise.all(Object.values(KEYS).map(remove));\n }\n if (closed) return;\n loaded = true;\n if (config) markReady();\n\n // The first open: the deep link's campaign and referral (no store data, no advertising id).\n let install: Record<string, unknown> | null = null;\n if (firstOpen) {\n install = {};\n if (options.attribution !== false && deps.initialUrl) {\n const url = await deps.initialUrl().catch(() => null);\n if (url) {\n const q = parseQuery(url);\n const values = utmFrom((k) => q[k]);\n if (Object.keys(values).length) utm = { session: touchSession(), values };\n const found = referralFrom((k) => q[k]);\n if (found) {\n referral = { code: found.code, clickId: found.clickId };\n install.$referral = referral;\n if (consent === \"persistent\") await set(KEYS.referral, JSON.stringify(referral));\n }\n install.link = clip(url.split(\"?\")[0], 300);\n }\n }\n }\n\n crumb(\"lifecycle\", \"app_open\");\n if (options.lifecycle !== false) record(\"$app_open\", { cold: true });\n if (install) record(\"$install\", install);\n for (const run of early.splice(0)) run();\n\n if (deps.appState) appStateSub = deps.appState.addEventListener(\"change\", onAppState);\n installErrorHandler();\n // Opens of MRRocket's notifications count from the first start, also the one that opened the app.\n listenForOpens();\n if (appState === \"active\" || !deps.appState) startTimer();\n if (queue.length) void flush();\n\n await fetchConfig();\n markReady();\n refreshFlows();\n };\n void start().catch(() => {\n loaded = true;\n markReady();\n });\n\n // ---------- The API ----------\n\n const client: MRRocketClient = {\n track: (event, props) => {\n if (typeof event !== \"string\" || !event) return;\n record(event, props);\n flows.onEvent(event);\n },\n tap: (x, y) => {\n if (options.heatmaps === false || consent === \"off\") return;\n const size = deps.screen?.();\n if (!size || !Number.isFinite(x) || !Number.isFinite(y)) return;\n // In the shape of the web's clicks (capture.ts): x and y in points, the screen as viewport and page.\n const props = { x: Math.round(x), y: Math.round(y), vw: Math.round(size.w), vh: Math.round(size.h), docH: Math.round(size.h), selector: \"\", label: \"\", dead: false };\n record(\"$click\", props);\n recorder?.mark({ kind: \"click\", path: currentScreen ?? \"/\", x: props.x, y: props.y, vw: props.vw });\n if (rage.push(x, y, now())) {\n record(\"$rageclick\", props);\n recorder?.mark({ kind: \"rage\", path: currentScreen ?? \"/\", x: props.x, y: props.y, vw: props.vw });\n recorder?.trigger(\"rage\");\n }\n },\n setReplay: (on) => {\n replayOn = on;\n if (!on) recorder?.drop();\n recorder?.sync(appState === \"active\");\n },\n screen: (name, props) => {\n if (typeof name !== \"string\" || !name.trim()) return;\n const path = (name.startsWith(\"/\") ? name : `/${name}`).slice(0, 300);\n if (path === currentScreen && !props) return;\n const previous = currentScreen;\n currentScreen = path;\n crumb(\"navigation\", path);\n record(\"$screen\", { ...props, path, screen: name, ...(previous ? { previous } : {}) });\n recorder?.mark({ kind: \"pageview\", path });\n },\n identify: (id, props) => {\n if (typeof id !== \"string\" || !id) return;\n if (!loaded) {\n early.push(() => client.identify(id, props));\n return;\n }\n const previous = sendId();\n identified = id;\n person = { ...props, id };\n record(\"$identify\", { ...props, id, ...(previous && previous !== id ? { previousId: previous } : {}) });\n if (consent === \"persistent\") void set(KEYS.id, id);\n changed();\n refreshFlows();\n },\n reset: () => {\n if (!loaded) {\n early.push(() => client.reset());\n return;\n }\n // Signed out: this device stops getting the person's notifications.\n if (pushToken) void unregisterForPush();\n identified = undefined;\n person = undefined;\n session = null;\n utm = null;\n exposed.clear();\n memoryId = newDistinctId();\n if (consent === \"persistent\") {\n installId = newDistinctId();\n void set(KEYS.id, installId);\n }\n changed();\n refreshFlows();\n },\n setConsent: (next) => {\n if (next !== \"anonymous\" && next !== \"persistent\" && next !== \"off\") {\n warn(`setConsent: \"${String(next)}\" is not a consent mode. Use \"anonymous\", \"persistent\" or \"off\".`);\n return;\n }\n if (!loaded) {\n early.push(() => client.setConsent(next));\n return;\n }\n if (next === consent) return;\n const before = consent;\n consent = next;\n if (next === \"off\") {\n recorder?.drop();\n queue = [];\n session = null;\n errorQueue.length = 0;\n void Promise.all(Object.values(KEYS).map(remove));\n } else if (next === \"anonymous\") {\n installId = null;\n void remove(KEYS.id);\n void remove(KEYS.referral);\n void remove(KEYS.surveys);\n } else {\n installId = identified ?? newDistinctId();\n void set(KEYS.id, installId);\n if (referral) void set(KEYS.referral, JSON.stringify(referral));\n if (surveysDone.size) void set(KEYS.surveys, JSON.stringify([...surveysDone]));\n }\n // Switching tracking on records the screen the person is on.\n if (before === \"off\" && currentScreen && loaded) record(\"$screen\", { path: currentScreen, screen: currentScreen });\n changed();\n refreshFlows();\n },\n captureError: (error) => capture(error, \"manual\"),\n getFlag: (key) => flagFor(key, config, distinctId(), { ...person }) !== false,\n getFlagVariant: (key) => {\n const v = flagFor(key, config, distinctId(), { ...person });\n return typeof v === \"string\" ? v : null;\n },\n getVariant: (key) => {\n const variant = resolveVariant(key, config, distinctId(), {});\n client.expose(key, variant);\n return variant;\n },\n peekVariant: (key) => resolveVariant(key, config, distinctId(), {}),\n expose: (key, variant) => {\n if (!config || consent === \"off\") return;\n const mark = `${currentScreen ?? \"/\"}|${key}`;\n if (exposed.has(mark)) return;\n exposed.add(mark);\n record(\"$exposure\", { experiment: key, variant });\n },\n getText: (id, fallback) => {\n client.exposeText(id);\n return client.peekText(id) ?? fallback;\n },\n peekText: (id) => texts()[id],\n exposeText: (id) => {\n // Showing a text a running test changes is an exposure to that test, whichever variant the person has.\n for (const key of experimentsOfText(config, id)) client.expose(key, resolveVariant(key, config, distinctId(), {}));\n },\n openCancelFlow: (o) => flows.openCancelFlow(o),\n startOnboarding: (id) => flows.startOnboarding(id),\n registerForPush,\n unregisterForPush,\n flows,\n flush,\n ready,\n isReady: () => isReady,\n getDistinctId: distinctId,\n getConsent: () => consent,\n getUser: () => {\n if (!identified) return undefined;\n const p = person as { name?: unknown; email?: unknown } | undefined;\n return { id: identified, ...(typeof p?.name === \"string\" ? { name: p.name } : {}), ...(typeof p?.email === \"string\" ? { email: p.email } : {}) };\n },\n api: (as) => {\n if (!apiKey || consent === \"off\") return null;\n const known = client.getUser();\n // A name and email the person typed into a widget, for this request only.\n const user = as?.name || as?.email ? { ...known, ...(as.name ? { name: as.name } : {}), ...(as.email ? { email: as.email } : {}) } : known;\n return createApi({ host, apiKey, distinctId: distinctId(), user });\n },\n isSurveyDone: (id) => surveysDone.has(id),\n markSurveyDone: (id) => {\n surveysDone.add(id);\n if (consent === \"persistent\") void set(KEYS.surveys, JSON.stringify([...surveysDone].slice(-100)));\n },\n getConfig: () => config,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getVersion: () => version,\n close: async () => {\n if (closed) return;\n stopTimer();\n recorder?.sync(false);\n appStateSub?.remove();\n pushOff?.();\n pushOff = null;\n if (handlerInstalled && deps.errorUtils && previousHandler) deps.errorUtils.setGlobalHandler(previousHandler);\n await flush();\n await sendErrors();\n await persistQueue();\n closed = true;\n },\n queued: () => queue,\n };\n return client;\n};\n\n/** The name of the screen a React Navigation state shows: the focused route, followed into nested navigators. */\nexport const activeRouteName = (state: unknown): string | undefined => {\n let s = state as { index?: number; routes?: { name?: string; state?: unknown }[] } | undefined;\n let name: string | undefined;\n for (let depth = 0; s && Array.isArray(s.routes) && s.routes.length && depth < 20; depth++) {\n const route = s.routes[typeof s.index === \"number\" ? s.index : s.routes.length - 1];\n if (!route) break;\n name = route.name ?? name;\n s = route.state as typeof s;\n }\n return name;\n};\n","/**\n * The React Native renderer of the cancel flow, onboarding and in-app messages (../flows.ts), drawn by\n * `<MRRocketProvider>` next to the app (`flows={false}` switches it off, e.g. to draw `client.flows` yourself).\n * Dialogs (the cancel flow, modal and tour steps, modal messages) use React Native's `Modal`; a checklist and a banner\n * float over the app as absolutely placed views, so the provider should sit at the root, like a toast library.\n *\n * Themeable with `appearance={{ theme: \"light\" | \"dark\" | \"auto\", accent: \"#0f766e\" }}`. Tour steps show as a card at\n * the bottom (no pointing at elements in apps yet).\n */\nimport { type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FlowsController, discounted, money, offerButton } from \"../flows\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ntype Any = (props: Record<string, unknown>) => ReactNode;\ninterface RNModule {\n Modal: Any;\n View: Any;\n Text: Any;\n Pressable: Any;\n TextInput: Any;\n ScrollView: Any;\n useColorScheme?: () => string | null | undefined;\n}\nconst RN = require(\"react-native\") as RNModule;\n\nexport interface NativeAppearance {\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n}\n\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nexport const LIGHT = { bg: \"#ffffff\", fg: \"#1c1d20\", muted: \"#5d6068\", soft: \"#f4f5f7\", line: \"#e4e5e8\" };\nexport const DARK = { bg: \"#17181b\", fg: \"#f1f2f4\", muted: \"#a9acb3\", soft: \"#232428\", line: \"#2e2f35\" };\n\nconst months = (n: number) => `${n} ${n === 1 ? \"month\" : \"months\"}`;\n\nexport const MRRocketFlows = ({ flows, appearance = {} }: { flows: FlowsController; appearance?: NativeAppearance }) => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n // Re-render on every change of the controller.\n const [, setTick] = useState(0);\n useEffect(() => flows.subscribe(() => setTick((t) => t + 1)), [flows]);\n const v = flows.view();\n const [comment, setComment] = useState(\"\");\n const screen = v?.type === \"cancel\" ? v.screen : null;\n useEffect(() => {\n if (!screen) setComment(\"\");\n }, [screen]);\n if (!v) return null;\n\n const text = (children: ReactNode, style: Record<string, unknown> = {}) => h(RN.Text, { style: { color: p.fg, fontSize: 15, ...style } }, children);\n const muted = (children: ReactNode, style: Record<string, unknown> = {}) => text(children, { color: p.muted, fontSize: 13, ...style });\n const title = (children: ReactNode) => h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 18, fontWeight: \"700\" } }, children);\n const btn = (label: string, kind: \"primary\" | \"danger\" | \"secondary\" | \"quiet\", onPress: () => void, disabled = false) =>\n h(\n RN.Pressable,\n {\n key: label,\n onPress,\n disabled,\n accessibilityRole: \"button\",\n accessibilityState: { disabled },\n style: {\n height: kind === \"quiet\" ? 36 : 44,\n borderRadius: 10,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: disabled ? 0.55 : 1,\n backgroundColor: kind === \"primary\" ? p.accent : kind === \"danger\" ? p.danger : kind === \"secondary\" ? p.bg : \"transparent\",\n borderWidth: kind === \"secondary\" ? 1 : 0,\n borderColor: p.line,\n },\n },\n text(label, {\n color: kind === \"primary\" || kind === \"danger\" ? \"#ffffff\" : kind === \"quiet\" ? p.muted : p.fg,\n fontWeight: kind === \"quiet\" ? \"500\" : \"600\",\n }),\n );\n const close = (label: string, onPress: () => void) =>\n h(\n RN.Pressable,\n { onPress, accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 12, style: { marginLeft: \"auto\", padding: 4 } },\n text(\"×\", { fontSize: 22, color: p.muted }),\n );\n const card = (children: ReactNode[], style: Record<string, unknown> = {}) =>\n h(\n RN.View,\n {\n style: {\n backgroundColor: p.bg,\n borderRadius: 16,\n padding: 20,\n gap: 12,\n shadowColor: \"#000\",\n shadowOpacity: 0.18,\n shadowRadius: 20,\n elevation: 8,\n ...style,\n },\n },\n ...children,\n );\n const sheet = (children: ReactNode[], onClose: () => void) =>\n h(\n RN.Modal,\n { visible: true, transparent: true, animationType: \"fade\", onRequestClose: onClose },\n h(\n RN.View,\n { style: { flex: 1, backgroundColor: \"rgba(0,0,0,0.4)\", justifyContent: \"flex-end\" } },\n card(children, { borderBottomLeftRadius: 0, borderBottomRightRadius: 0, paddingBottom: 34 }),\n ),\n );\n const input = (placeholder: string) =>\n h(RN.TextInput, {\n value: comment,\n onChangeText: setComment,\n placeholder,\n placeholderTextColor: p.muted,\n multiline: true,\n maxLength: 500,\n accessibilityLabel: placeholder,\n style: { minHeight: 72, borderWidth: 1, borderColor: p.line, borderRadius: 10, padding: 10, color: p.fg, textAlignVertical: \"top\" },\n });\n\n if (v.type === \"cancel\") {\n const top = h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(v.steps > 1\n ? Array.from({ length: v.steps }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i < v.step ? p.accent : p.line } }),\n )\n : []),\n close(\"Close\", flows.cancel.close),\n );\n const error = v.error ? text(v.error, { color: p.danger, fontSize: 13 }) : null;\n let body: ReactNode[] = [];\n if (v.screen === \"survey\")\n body = [\n title(v.flow.question || \"Why are you leaving?\"),\n h(\n RN.ScrollView,\n { style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...v.flow.reasons.map((r) =>\n h(\n RN.Pressable,\n {\n key: r.id,\n onPress: () => flows.cancel.pick(r.id),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: v.reason === r.id },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: v.reason === r.id ? p.accent : p.line,\n backgroundColor: v.reason === r.id ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(r.label, { fontWeight: \"500\" }),\n ),\n ),\n ),\n btn(\"Continue\", \"primary\", flows.cancel.next, !v.reason),\n btn(\"Never mind, keep my plan\", \"quiet\", flows.cancel.close),\n ];\n else if (v.screen === \"offer\" && v.offer) {\n const o = v.offer;\n const label = v.flow.reasons.find((r) => r.id === v.reason)?.label;\n const detail =\n o.kind === \"discount\" && o.percent\n ? v.price\n ? `${money(discounted(v.price.amount, o.percent), v.price.currency)} instead of ${money(v.price.amount, v.price.currency)}${o.months ? ` for ${months(o.months)}` : \"\"}`\n : `${o.percent}% off${o.months ? ` for ${months(o.months)}` : \"\"}`\n : o.kind === \"pause\" && o.months\n ? `Pause for up to ${months(o.months)}. Your data stays.`\n : o.kind === \"downgrade\" && o.planName\n ? o.planName\n : null;\n body = [\n label ? muted(`You said: ${label}`) : null,\n title(o.headline),\n detail ? h(RN.View, { style: { backgroundColor: p.soft, borderRadius: 10, padding: 12 } }, text(detail, { fontWeight: \"600\" })) : null,\n o.kind === \"contact\" ? input(\"What would make you stay?\") : null,\n btn(v.busy ? \"One moment…\" : offerButton(o), \"primary\", () => flows.cancel.accept(comment), v.busy),\n btn(\"No thanks, continue cancelling\", \"quiet\", flows.cancel.decline, v.busy),\n ];\n } else\n body = [\n title(v.flow.confirm.title),\n v.flow.confirm.body ? muted(v.flow.confirm.body, { fontSize: 15 }) : null,\n v.steps > 1 ? input(\"Anything else we should know? (optional)\") : null,\n btn(v.busy ? \"One moment…\" : v.flow.confirm.button, \"danger\", () => flows.cancel.confirm(comment), v.busy),\n btn(\"Keep my plan\", \"secondary\", flows.cancel.close, v.busy),\n ];\n return sheet([top, ...body, error], flows.cancel.close);\n }\n\n if (v.type === \"step\")\n return sheet(\n [\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\" } },\n v.total > 1 ? muted(`Step ${v.index + 1} of ${v.total}`) : null,\n close(\"Close the tour\", flows.onboarding.dismiss),\n ),\n title(v.step.title),\n v.step.body ? muted(v.step.body, { fontSize: 15 }) : null,\n btn(v.step.button || (v.last ? \"Done\" : \"Next\"), \"primary\", flows.onboarding.next),\n ],\n flows.onboarding.dismiss,\n );\n\n if (v.type === \"checklist\") {\n const done = v.items.filter((i) => i.done).length;\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, bottom: 28 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\" } },\n title(v.flow.name),\n close(\"Hide the checklist\", flows.onboarding.dismiss),\n ),\n muted(`${done} of ${v.items.length} done`),\n ...v.items.map(({ step, done: d }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n disabled: d || !!step.event,\n onPress: () => flows.onboarding.check(step.id),\n accessibilityRole: \"checkbox\",\n accessibilityState: { checked: d },\n style: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\", paddingVertical: 6 },\n },\n h(\n RN.View,\n {\n style: {\n width: 20,\n height: 20,\n borderRadius: 10,\n borderWidth: 1.5,\n borderColor: d ? p.accent : p.line,\n backgroundColor: d ? p.accent : \"transparent\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n },\n d ? text(\"✓\", { color: \"#fff\", fontSize: 12 }) : null,\n ),\n h(\n RN.View,\n { style: { flex: 1 } },\n text(step.title, { fontWeight: \"600\", color: d ? p.muted : p.fg, textDecorationLine: d ? \"line-through\" : \"none\" }),\n step.body ? muted(step.body) : null,\n ),\n ),\n ),\n ]),\n );\n }\n\n const m = v.message;\n if (m.style === \"banner\")\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, top: 56 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8 } },\n h(RN.View, { style: { flex: 1 } }, text(m.title, { fontWeight: \"700\" }), m.body ? muted(m.body) : null),\n close(\"Dismiss\", flows.message.dismiss),\n ),\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ]),\n );\n return sheet(\n [\n h(RN.View, { key: \"t\", style: { flexDirection: \"row\" } }, close(\"Dismiss\", flows.message.dismiss)),\n title(m.title),\n m.body ? muted(m.body, { fontSize: 15 }) : null,\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ],\n flows.message.dismiss,\n );\n};\n","/**\n * The real platform for the React Native client: React Native itself, plus optional modules the app may have installed.\n * Each optional `require` sits directly in its own `try` block: that is how Metro knows the module is optional and\n * bundles the app without it when it is not installed (and how the CommonJS build keeps the call literal).\n *\n * - `@react-native-async-storage/async-storage`: the offline queue, the install id (\"persistent\" consent), the cached\n * config and the first-open marker. Without it everything stays in memory for the app's run.\n * - `expo-device`, `expo-application`, `expo-localization`: model, OS version, app version and build, locale.\n * Without them the SDK falls back to what React Native knows (platform, OS version, the JS locale).\n * - `expo-notifications` (with `expo-constants` for the EAS project id): push notifications, `registerForPush()`.\n * Without it `registerForPush` answers \"unavailable\".\n */\nimport type { AppContext } from \"../core\";\nimport type { AppStateLike, ErrorUtilsLike, FetchLike, KeyValueStorage, NativeDeps, PushData, PushDeps } from \"./client\";\nimport { measureMasks } from \"./recorder\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ninterface ReactNativeModule {\n Platform: { OS: string; Version?: string | number; isPad?: boolean; constants?: { Model?: string; Manufacturer?: string } };\n AppState: AppStateLike;\n Linking: { getInitialURL(): Promise<string | null>; openURL(url: string): Promise<unknown> };\n Dimensions: { get(dim: \"screen\" | \"window\"): { width: number; height: number } };\n Keyboard: { addListener(event: \"keyboardDidShow\" | \"keyboardDidHide\" | \"keyboardWillShow\", l: () => void): { remove(): void } };\n}\n\ninterface ViewShot {\n captureScreen?: (o: { format: \"jpg\"; quality: number; result: \"base64\"; width?: number; height?: number }) => Promise<string>;\n}\n\ninterface ExpoDevice {\n modelName?: string | null;\n osVersion?: string | null;\n deviceType?: number | null;\n}\ninterface ExpoApplication {\n nativeApplicationVersion?: string | null;\n nativeBuildVersion?: string | null;\n applicationId?: string | null;\n}\ninterface ExpoLocalization {\n getLocales?: () => { languageTag?: string }[];\n}\n\nconst RN = require(\"react-native\") as ReactNativeModule;\n\nlet asyncStorageModule: unknown = null;\ntry {\n asyncStorageModule = require(\"@react-native-async-storage/async-storage\");\n} catch {\n asyncStorageModule = null;\n}\nlet expoDevice: ExpoDevice | null = null;\ntry {\n expoDevice = require(\"expo-device\") as ExpoDevice;\n} catch {\n expoDevice = null;\n}\nlet expoApplication: ExpoApplication | null = null;\ntry {\n expoApplication = require(\"expo-application\") as ExpoApplication;\n} catch {\n expoApplication = null;\n}\nlet expoLocalization: ExpoLocalization | null = null;\ntry {\n expoLocalization = require(\"expo-localization\") as ExpoLocalization;\n} catch {\n expoLocalization = null;\n}\nlet viewShot: ViewShot | null = null;\ntry {\n viewShot = require(\"react-native-view-shot\") as ViewShot;\n} catch {\n viewShot = null;\n}\nlet expoNotifications: ExpoNotifications | null = null;\ntry {\n expoNotifications = require(\"expo-notifications\") as ExpoNotifications;\n} catch {\n expoNotifications = null;\n}\nlet expoConstants: { default?: ExpoConstants } & ExpoConstants = {};\ntry {\n expoConstants = require(\"expo-constants\") as typeof expoConstants;\n} catch {\n expoConstants = {};\n}\n\ninterface NotificationResponse {\n notification?: { request?: { content?: { data?: unknown } } };\n}\ninterface ExpoNotifications {\n getPermissionsAsync(): Promise<{ status?: string; granted?: boolean }>;\n requestPermissionsAsync(): Promise<{ status?: string; granted?: boolean }>;\n getExpoPushTokenAsync(o?: { projectId?: string }): Promise<{ data?: string }>;\n setNotificationChannelAsync?(id: string, o: Record<string, unknown>): Promise<unknown>;\n addNotificationResponseReceivedListener(fn: (r: NotificationResponse) => void): { remove(): void };\n getLastNotificationResponseAsync?(): Promise<NotificationResponse | null>;\n AndroidImportance?: { DEFAULT?: number; HIGH?: number };\n}\ninterface ExpoConstants {\n expoConfig?: { extra?: { eas?: { projectId?: string } } } | null;\n easConfig?: { projectId?: string } | null;\n}\n\nconst dataOf = (r: NotificationResponse | null | undefined) => (r?.notification?.request?.content?.data ?? null) as PushData | null;\n\n/** Push through `expo-notifications`; null when the app does not have it. */\nconst expoPush = (): PushDeps | null => {\n const n = expoNotifications;\n if (!n || typeof n.getExpoPushTokenAsync !== \"function\") return null;\n const constants = expoConstants.default ?? expoConstants;\n return {\n permission: async (ask) => {\n const now = await n.getPermissionsAsync();\n if (now.granted || now.status === \"granted\") return \"granted\";\n if (now.status === \"denied\" || !ask) return now.status === \"denied\" ? \"denied\" : \"undetermined\";\n const asked = await n.requestPermissionsAsync();\n return asked.granted || asked.status === \"granted\" ? \"granted\" : asked.status === \"denied\" ? \"denied\" : \"undetermined\";\n },\n token: async (projectId) => {\n // Android shows nothing without a channel.\n if (RN.Platform.OS === \"android\" && n.setNotificationChannelAsync)\n await n.setNotificationChannelAsync(\"default\", { name: \"Default\", importance: n.AndroidImportance?.HIGH ?? 4 });\n const id = projectId ?? constants.expoConfig?.extra?.eas?.projectId ?? constants.easConfig?.projectId;\n const t = await n.getExpoPushTokenAsync(id ? { projectId: id } : undefined);\n return typeof t?.data === \"string\" && t.data ? t.data : null;\n },\n onOpen: (listener) => {\n const sub = n.addNotificationResponseReceivedListener((r) => listener(dataOf(r) ?? {}));\n return () => sub.remove();\n },\n lastOpen: async () => dataOf(await n.getLastNotificationResponseAsync?.()),\n };\n};\n\n/** AsyncStorage's default export, or null when it is not installed. */\nconst asyncStorage = (): KeyValueStorage | null => {\n const m = asyncStorageModule as { default?: KeyValueStorage } & Partial<KeyValueStorage>;\n const s = (m?.default ?? m) as Partial<KeyValueStorage> | null;\n return s && typeof s.getItem === \"function\" && typeof s.setItem === \"function\" && typeof s.removeItem === \"function\" ? (s as KeyValueStorage) : null;\n};\n\nconst DEVICE_TYPES: Record<number, string> = { 1: \"phone\", 2: \"tablet\", 3: \"desktop\", 4: \"tv\" };\n\nconst text = (v: unknown, max = 80) => (typeof v === \"string\" && v.trim() ? v.trim().slice(0, max) : typeof v === \"number\" ? String(v) : undefined);\n\n/** The app and device, from the Expo modules when installed, else from React Native. Nothing that identifies a person. */\nexport const readContext = (): AppContext => {\n const p = RN.Platform;\n let locale: string | undefined;\n try {\n locale = text(expoLocalization?.getLocales?.()[0]?.languageTag, 35);\n } catch {\n locale = undefined;\n }\n if (!locale) {\n try {\n locale = text(Intl.DateTimeFormat().resolvedOptions().locale, 35);\n } catch {\n locale = undefined;\n }\n }\n const ctx: AppContext = {\n platform: p.OS,\n appVersion: text(expoApplication?.nativeApplicationVersion),\n build: text(expoApplication?.nativeBuildVersion),\n osVersion: text(expoDevice?.osVersion) ?? text(p.Version),\n deviceModel: text(expoDevice?.modelName) ?? text(p.constants?.Model),\n deviceType: (expoDevice?.deviceType ? DEVICE_TYPES[expoDevice.deviceType] : undefined) ?? (p.isPad ? \"tablet\" : undefined),\n locale,\n };\n for (const k of Object.keys(ctx) as (keyof AppContext)[]) if (ctx[k] === undefined) delete ctx[k];\n return ctx;\n};\n\n/**\n * Frames for session recordings: the whole screen (with modals) as a JPEG about 360 pixels wide, through\n * react-native-view-shot when the app has it. The keyboard's state comes from its own events; `keyboardWillShow`\n * (iOS) stops frames before it is on screen.\n */\nconst recorderDeps = (): NativeDeps[\"recorder\"] => {\n const capture = viewShot?.captureScreen;\n if (!capture) return null;\n let keyboard = false;\n try {\n RN.Keyboard.addListener(\"keyboardWillShow\", () => (keyboard = true));\n RN.Keyboard.addListener(\"keyboardDidShow\", () => (keyboard = true));\n RN.Keyboard.addListener(\"keyboardDidHide\", () => (keyboard = false));\n } catch {\n // Without keyboard events no frame can be taken safely.\n return null;\n }\n return {\n capture: async (width) => {\n const s = RN.Dimensions.get(\"screen\");\n if (!s?.width) return null;\n const w = Math.round(width);\n const h = Math.round((s.height / s.width) * width);\n const img = await capture({ format: \"jpg\", quality: 0.5, result: \"base64\", width: w, height: h });\n return img ? { img: img.replace(/^data:image\\/\\w+;base64,/, \"\"), w, h } : null;\n },\n keyboardOpen: () => keyboard,\n masks: measureMasks,\n };\n};\n\n/** The dependencies of the client on a real device. `storage` overrides AsyncStorage (pass null for memory only). */\nexport const nativeDeps = (overrides: { storage?: KeyValueStorage | null } = {}): NativeDeps => ({\n storage: overrides.storage !== undefined ? overrides.storage : asyncStorage(),\n fetch: ((url, init) => fetch(url, init)) as FetchLike,\n appState: RN.AppState,\n errorUtils: ((globalThis as { ErrorUtils?: ErrorUtilsLike }).ErrorUtils ?? null) as ErrorUtilsLike | null,\n context: readContext,\n appId: text(expoApplication?.applicationId, 150),\n screen: () => {\n const s = RN.Dimensions.get(\"screen\");\n return s ? { w: s.width, h: s.height } : undefined;\n },\n initialUrl: () => RN.Linking.getInitialURL(),\n openUrl: (url) => void RN.Linking.openURL(url).catch(() => undefined),\n push: expoPush(),\n recorder: recorderDeps(),\n});\n\n/** Whether the optional modules were found (for the debug log and the docs' checklist). */\nexport const optionalModules = () => ({\n asyncStorage: !!asyncStorage(),\n expoDevice: !!expoDevice,\n expoApplication: !!expoApplication,\n expoLocalization: !!expoLocalization,\n expoNotifications: !!expoNotifications,\n viewShot: !!viewShot?.captureScreen,\n});\n","/**\n * The React Native widgets of the web SDK's survey, feedback widget and messenger, on the same API (../api-client.ts),\n * drawn by `<MRRocketProvider>` next to the app:\n * - surveys: the live in-app survey MRRocket picks for the person shows as a sheet a few seconds after start (on by\n * default; `surveys={false}` switches it off),\n * - feedback: `useFeedback().open()` shows the top requests with votes and a form to suggest one,\n * - messenger: `useMessenger().open()` shows Home, Messages (the chat with the team, MRRocket › Support) and Help (the\n * product's published help articles); `messenger={{ launcher: true }}` (or \"Chat button in the app\" in MRRocket ›\n * Support › Messenger) adds a round button. Home has the accent head of the web messenger; its line icons need\n * react-native-svg (text glyphs without it). While it is closed and the person waits for an answer, it checks now\n * and then; a new answer shows as a banner at the top with a light haptic (expo-haptics, when installed; apps play\n * no sound of their own).\n * Same look as the flows (`appearance`). Nothing loads before it shows, except one survey request after start.\n */\nimport { type ReactNode, createElement as h, useCallback, useEffect, useRef, useState } from \"react\";\nimport { inkOn, replyLine } from \"../api-client\";\nimport type { Api, Article, ArticleSpan, ArticleSummary, ChatMessage, MessengerLook, ChatThread, FeedbackBoardInfo, FeedbackPost, SurveyAnswer, SurveyDefinition, SurveyQuestion } from \"../api-client\";\nimport type { MRRocketClient } from \"./client\";\nimport { DARK, LIGHT, type NativeAppearance } from \"./flows-view\";\n\n/* eslint-disable @typescript-eslint/no-require-imports */\ndeclare const require: (id: string) => unknown;\n\ntype Any = (props: Record<string, unknown>) => ReactNode;\ninterface RNModule {\n Modal: Any;\n View: Any;\n Text: Any;\n Pressable: Any;\n TextInput: Any;\n ScrollView: Any;\n KeyboardAvoidingView: Any;\n Platform: { OS: string };\n Linking: { openURL(url: string): Promise<unknown> };\n AppState: { currentState: string; addEventListener(type: \"change\", l: (s: string) => void): { remove(): void } };\n useColorScheme?: () => string | null | undefined;\n}\nconst RN = require(\"react-native\") as RNModule;\n\ntype Style = Record<string, unknown>;\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nconst usePalette = (appearance: NativeAppearance = {}): Palette => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n return { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n};\n\n/** Small building blocks in the flows' look. */\nconst kit = (p: Palette) => {\n const text = (children: ReactNode, style: Style = {}) => h(RN.Text, { style: { color: p.fg, fontSize: 15, ...style } }, children);\n const muted = (children: ReactNode, style: Style = {}) => text(children, { color: p.muted, fontSize: 13, ...style });\n const title = (children: ReactNode) => h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 17, fontWeight: \"700\", flex: 1 } }, children);\n const btn = (label: string, kind: \"primary\" | \"secondary\", onPress: () => void, disabled = false, style: Style = {}) =>\n h(\n RN.Pressable,\n {\n key: label,\n onPress,\n disabled,\n accessibilityRole: \"button\",\n accessibilityState: { disabled },\n style: {\n height: 44,\n paddingHorizontal: 16,\n borderRadius: 10,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: disabled ? 0.55 : 1,\n backgroundColor: kind === \"primary\" ? p.accent : p.bg,\n borderWidth: kind === \"secondary\" ? 1 : 0,\n borderColor: p.line,\n ...style,\n },\n },\n text(label, { color: kind === \"primary\" ? \"#ffffff\" : p.fg, fontWeight: \"600\" }),\n );\n const closeX = (label: string, onPress: () => void) =>\n h(RN.Pressable, { onPress, accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 12, style: { padding: 4 } }, text(\"×\", { fontSize: 24, color: p.muted }));\n const field = (o: { value: string; onChange: (v: string) => void; placeholder: string; multiline?: boolean; max?: number; email?: boolean; style?: Style; onSubmit?: () => void }) =>\n h(RN.TextInput, {\n value: o.value,\n onChangeText: o.onChange,\n placeholder: o.placeholder,\n placeholderTextColor: p.muted,\n multiline: !!o.multiline,\n maxLength: o.max ?? 2000,\n accessibilityLabel: o.placeholder,\n ...(o.email ? { keyboardType: \"email-address\", autoCapitalize: \"none\", autoComplete: \"email\", textContentType: \"emailAddress\" } : {}),\n ...(o.onSubmit ? { onSubmitEditing: o.onSubmit, returnKeyType: \"send\" } : {}),\n style: {\n minHeight: o.multiline ? 72 : 44,\n borderWidth: 1,\n borderColor: p.line,\n borderRadius: 10,\n paddingHorizontal: 12,\n paddingVertical: 10,\n color: p.fg,\n backgroundColor: p.bg,\n textAlignVertical: o.multiline ? \"top\" : \"center\",\n ...o.style,\n },\n });\n const chip = (label: string, on: boolean, onPress: () => void, key = label) =>\n h(\n RN.Pressable,\n {\n key,\n onPress,\n accessibilityRole: \"button\",\n accessibilityState: { selected: on },\n style: { paddingHorizontal: 12, height: 32, borderRadius: 16, justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.soft : p.bg },\n },\n text(label, { fontSize: 13, fontWeight: \"600\", color: on ? p.accent : p.fg }),\n );\n /** A full-height sheet (pageSheet on iOS) with a title row and the keyboard kept off the bottom. */\n const page = (heading: string, onClose: () => void, children: ReactNode[]) =>\n h(\n RN.Modal,\n { visible: true, animationType: \"slide\", presentationStyle: \"pageSheet\", onRequestClose: onClose },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: p.bg } },\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", paddingHorizontal: 16, paddingTop: 16, paddingBottom: 12, borderBottomWidth: 1, borderBottomColor: p.line } },\n title(heading),\n closeX(\"Close\", onClose),\n ),\n ...children,\n ),\n );\n return { text, muted, title, btn, closeX, field, chip, page };\n};\n\nconst timeAgo = (iso: string) => {\n const t = new Date(iso).getTime();\n if (Number.isNaN(t)) return \"\";\n const d = Math.max(0, Date.now() - t) / 1000;\n if (d < 60) return \"just now\";\n if (d < 3600) return `${Math.floor(d / 60)}m ago`;\n if (d < 86400) return `${Math.floor(d / 3600)}h ago`;\n return `${Math.floor(d / 86400)}d ago`;\n};\n\n/** Open state shared by a hook and the view the provider draws. */\nconst opener = () => {\n let open = false;\n const listeners = new Set<(v: boolean) => void>();\n const set = (v: boolean) => {\n open = v;\n listeners.forEach((l) => l(v));\n };\n const useOpen = () => {\n const [v, setV] = useState(open);\n useEffect(() => {\n listeners.add(setV);\n setV(open);\n return () => {\n listeners.delete(setV);\n };\n }, []);\n return v;\n };\n return { set, get: () => open, useOpen };\n};\n\n// ---------- Surveys ----------\n\nconst isAnswered = (a: SurveyAnswer | undefined) => (Array.isArray(a) ? a.length > 0 : typeof a === \"number\" ? true : !!a?.trim());\n\nconst SurveySheet = ({ survey, api, p, onDone }: { survey: SurveyDefinition; api: Api; p: Palette; onDone: () => void }) => {\n const k = kit(p);\n const [step, setStep] = useState(0);\n const [answers, setAnswers] = useState<Record<string, SurveyAnswer>>({});\n const [done, setDone] = useState(false);\n const [error, setError] = useState(\"\");\n const started = useRef(Date.now());\n const finished = useRef(false);\n const q: SurveyQuestion = survey.questions[step];\n const last = step === survey.questions.length - 1;\n const value = answers[q.key];\n\n useEffect(() => {\n api.seen(survey.id).catch(() => undefined);\n }, [api, survey.id]);\n useEffect(() => {\n if (!done) return;\n const t = setTimeout(onDone, 2500);\n return () => clearTimeout(t);\n }, [done, onDone]);\n\n const finish = (completed: boolean, all = answers) => {\n if (finished.current) return;\n finished.current = true;\n api.respond(survey.id, { answers: all, completed, seconds: Math.round((Date.now() - started.current) / 1000) }).catch(() => undefined);\n };\n const dismiss = () => {\n // Partial answers still count, so nothing the person typed is lost.\n if (Object.values(answers).some(isAnswered)) finish(false);\n onDone();\n };\n const next = () => {\n if (q.required && !isAnswered(value)) return setError(\"Please answer this question.\");\n setError(\"\");\n if (!last) return setStep(step + 1);\n finish(true);\n setDone(true);\n };\n const pick = (v: SurveyAnswer) => {\n setAnswers((a) => ({ ...a, [q.key]: v }));\n setError(\"\");\n };\n\n let input: ReactNode;\n if (q.kind === \"nps\" || q.kind === \"rating\") {\n const scale = q.kind === \"nps\" ? 11 : Math.min(Math.max(q.scale ?? 5, 2), 10);\n const start = q.kind === \"nps\" ? 0 : 1;\n input = h(\n RN.View,\n { style: { gap: 6 } },\n h(\n RN.View,\n { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 }, accessibilityRole: \"radiogroup\", accessibilityLabel: q.title },\n ...Array.from({ length: scale }, (_, i) => {\n const n = i + start;\n const on = value === n;\n return h(\n RN.Pressable,\n {\n key: n,\n onPress: () => pick(n),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: on },\n accessibilityLabel: `${n} of ${scale - 1 + start}`,\n style: { width: 40, height: 40, borderRadius: 8, alignItems: \"center\", justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.accent : p.bg },\n },\n k.text(String(n), { color: on ? \"#ffffff\" : p.fg, fontWeight: \"600\" }),\n );\n }),\n ),\n q.low || q.high || q.kind === \"nps\"\n ? h(RN.View, { style: { flexDirection: \"row\", justifyContent: \"space-between\" } }, k.muted(q.low ?? (q.kind === \"nps\" ? \"Not likely\" : \"\")), k.muted(q.high ?? (q.kind === \"nps\" ? \"Very likely\" : \"\")))\n : null,\n );\n } else if (q.kind === \"single\" || q.kind === \"multi\") {\n const multi = q.kind === \"multi\";\n const picked = multi ? ((value as string[] | undefined) ?? []) : [];\n input = h(\n RN.View,\n { style: { gap: 6 } },\n ...(q.options ?? []).map((o) => {\n const on = multi ? picked.includes(o) : value === o;\n return h(\n RN.Pressable,\n {\n key: o,\n onPress: () => pick(multi ? (on ? picked.filter((x) => x !== o) : [...picked, o]) : o),\n accessibilityRole: multi ? \"checkbox\" : \"radio\",\n accessibilityState: { checked: on },\n style: { minHeight: 44, paddingHorizontal: 12, borderRadius: 10, justifyContent: \"center\", borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.soft : p.bg },\n },\n k.text(o, { fontWeight: \"500\" }),\n );\n }),\n );\n } else input = k.field({ value: (value as string | undefined) ?? \"\", onChange: pick, placeholder: q.placeholder ?? \"Type your answer\", multiline: true });\n\n const body = done\n ? [k.text(survey.thanks || \"Thanks for your feedback.\", { fontWeight: \"600\", textAlign: \"center\", paddingVertical: 16 })]\n : [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...survey.questions.map((x, i) => h(RN.View, { key: x.key, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= step ? p.accent : p.line } })),\n h(RN.View, { style: { flex: 1 } }),\n k.closeX(\"Close survey\", dismiss),\n ),\n h(RN.Text, { key: \"q\", accessibilityRole: \"header\", style: { color: p.fg, fontSize: 17, fontWeight: \"700\" } }, q.title, q.required ? \"\" : h(RN.Text, { style: { color: p.muted, fontSize: 13, fontWeight: \"400\" } }, \" optional\")),\n q.description ? k.muted(q.description) : null,\n input,\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n k.btn(last ? \"Send\" : \"Next\", \"primary\", next),\n ];\n\n return h(\n RN.Modal,\n { visible: true, transparent: true, animationType: \"slide\", onRequestClose: dismiss },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: \"rgba(0,0,0,0.35)\", justifyContent: \"flex-end\" } },\n h(\n RN.View,\n {\n accessibilityViewIsModal: true,\n accessibilityLabel: survey.name,\n style: { backgroundColor: p.bg, borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 20, paddingBottom: 34, gap: 12 },\n },\n ...body,\n ),\n ),\n );\n};\n\n/** Asks the person the survey MRRocket picks for them, a few seconds after start and again for a new person. */\nexport const MRRocketSurveys = ({ client, appearance }: { client: MRRocketClient; appearance?: NativeAppearance }) => {\n const p = usePalette(appearance);\n const [survey, setSurvey] = useState<{ s: SurveyDefinition; api: Api } | null>(null);\n const [who, setWho] = useState(() => client.getDistinctId());\n useEffect(() => client.subscribe(() => setWho(client.getDistinctId())), [client]);\n\n useEffect(() => {\n let stop = false;\n const ctrl = new AbortController();\n const timer = setTimeout(() => {\n void client.ready.then(() => {\n const api = client.api();\n if (stop || !api) return;\n api.survey(\"\", ctrl.signal)\n .then((r) => {\n const s = r.survey;\n if (stop || !s || !s.questions.length || client.isSurveyDone(s.id)) return;\n setSurvey({ s, api });\n })\n .catch(() => undefined);\n });\n }, 3000);\n return () => {\n stop = true;\n clearTimeout(timer);\n ctrl.abort();\n };\n }, [client, who]);\n\n const done = useCallback(() => {\n setSurvey((cur) => {\n if (cur) client.markSurveyDone(cur.s.id);\n return null;\n });\n }, [client]);\n if (!survey) return null;\n return h(SurveySheet, { key: survey.s.id, survey: survey.s, api: survey.api, p, onDone: done });\n};\n\n// ---------- Feedback ----------\n\nconst feedbackOpen = opener();\n\n/** Opens the feedback sheet: the top requests with votes, and a form to suggest one. */\nexport const useFeedback = () => ({ open: () => feedbackOpen.set(true), close: () => feedbackOpen.set(false) });\n\nexport interface NativeFeedbackOptions {\n /** The sheet's title. Default \"Feedback\". */\n title?: string;\n}\n\nconst FeedbackSheet = ({ client, p, title }: { client: MRRocketClient; p: Palette; title: string }) => {\n const k = kit(p);\n const [tab, setTab] = useState<\"top\" | \"new\">(\"top\");\n const [posts, setPosts] = useState<FeedbackPost[] | null>(null);\n const [boards, setBoards] = useState<FeedbackBoardInfo[]>([]);\n const [error, setError] = useState(\"\");\n const [board, setBoard] = useState(\"feature\");\n const [subject, setSubject] = useState(\"\");\n const [details, setDetails] = useState(\"\");\n const [name, setName] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const close = () => feedbackOpen.set(false);\n const user = client.getUser();\n\n useEffect(() => {\n const api = client.api();\n if (!api) return setError(\"Feedback is off while tracking is off.\");\n const ctrl = new AbortController();\n api.list({ sort: \"top\" }, ctrl.signal)\n .then((l) => {\n setPosts(l.posts);\n setBoards(l.boards);\n if (l.boards.length && !l.boards.some((b) => b.id === \"feature\")) setBoard(l.boards[0].id);\n })\n .catch((e: Error) => e.name !== \"AbortError\" && setError(e.message));\n return () => ctrl.abort();\n }, [client]);\n\n const vote = (post: FeedbackPost) => {\n const api = client.api();\n if (!api) return;\n // At once on screen; the server's count replaces it.\n setPosts((all) => all?.map((x) => (x.id === post.id ? { ...x, voted: !x.voted, votes: x.votes + (x.voted ? -1 : 1) } : x)) ?? null);\n api.vote(post.id)\n .then((r) => setPosts((all) => all?.map((x) => (x.id === post.id ? { ...x, voted: r.voted, votes: r.votes } : x)) ?? null))\n .catch((e: Error) => {\n setError(e.message);\n setPosts((all) => all?.map((x) => (x.id === post.id ? post : x)) ?? null);\n });\n };\n\n const submit = () => {\n const api = client.api({ name: name.trim(), email: email.trim() });\n if (!api || subject.trim().length < 3 || sending) return;\n setSending(true);\n setError(\"\");\n api.submit({ title: subject.trim(), body: details.trim() || undefined, board })\n .then((post) => {\n setPosts((all) => [post, ...(all ?? [])]);\n setSubject(\"\");\n setDetails(\"\");\n setSent(true);\n })\n .catch((e: Error) => setError(e.message))\n .finally(() => setSending(false));\n };\n\n const tabs = h(\n RN.View,\n { style: { flexDirection: \"row\", gap: 8, paddingHorizontal: 16, paddingTop: 12 } },\n k.chip(\"Top requests\", tab === \"top\", () => setTab(\"top\")),\n k.chip(\"Suggest\", tab === \"new\", () => {\n setTab(\"new\");\n setSent(false);\n }),\n );\n\n const list = h(\n RN.ScrollView,\n { style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 10 } },\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n posts === null && !error ? k.muted(\"Loading…\") : null,\n posts?.length === 0 ? k.muted(\"No requests yet. Be the first to suggest one.\") : null,\n ...(posts ?? []).map((post) =>\n h(\n RN.View,\n { key: post.id, style: { flexDirection: \"row\", gap: 12, alignItems: \"flex-start\", paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: p.line } },\n h(\n RN.Pressable,\n {\n onPress: () => vote(post),\n accessibilityRole: \"button\",\n accessibilityState: { selected: post.voted },\n accessibilityLabel: `${post.voted ? \"Remove your vote from\" : \"Upvote\"} ${post.title}. ${post.votes} votes`,\n style: { width: 44, minHeight: 48, borderRadius: 10, alignItems: \"center\", justifyContent: \"center\", borderWidth: 1, borderColor: post.voted ? p.accent : p.line },\n },\n k.text(\"▲\", { fontSize: 11, color: post.voted ? p.accent : p.muted }),\n k.text(String(post.votes), { fontWeight: \"700\", fontSize: 14, color: post.voted ? p.accent : p.fg }),\n ),\n h(RN.View, { style: { flex: 1, gap: 2 } }, k.text(post.title, { fontWeight: \"600\" }), post.body ? k.muted(post.body.slice(0, 160)) : null),\n ),\n ),\n );\n\n const form = h(\n RN.ScrollView,\n { style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 10 }, keyboardShouldPersistTaps: \"handled\" },\n sent ? k.text(\"Thanks! Your request is on the board.\", { fontWeight: \"600\" }) : null,\n boards.length > 1 ? h(RN.View, { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 } }, ...boards.map((b) => k.chip(b.label, board === b.id, () => setBoard(b.id), b.id))) : null,\n k.field({ value: subject, onChange: setSubject, placeholder: \"Short title\", max: 120 }),\n k.field({ value: details, onChange: setDetails, placeholder: \"Details (optional)\", multiline: true }),\n ...(user?.email\n ? []\n : [\n k.muted(\"Your name and email are optional; they let the team follow up.\"),\n k.field({ value: name, onChange: setName, placeholder: \"Your name (optional)\", max: 100 }),\n k.field({ value: email, onChange: setEmail, placeholder: \"Your email (optional)\", max: 200, email: true }),\n ]),\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n k.btn(sending ? \"Sending…\" : \"Send request\", \"primary\", submit, subject.trim().length < 3 || sending),\n );\n\n return k.page(title, close, [tabs, tab === \"top\" ? list : form]);\n};\n\nexport const MRRocketFeedback = ({ client, appearance, options = {} }: { client: MRRocketClient; appearance?: NativeAppearance; options?: NativeFeedbackOptions }) => {\n const p = usePalette(appearance);\n const open = feedbackOpen.useOpen();\n return open ? h(FeedbackSheet, { client, p, title: options.title ?? \"Feedback\" }) : null;\n};\n\n// ---------- Messenger ----------\n\nconst POLL_OPEN_MS = 4000;\nconst POLL_WAITING_MS = 8000;\nconst POLL_IDLE_MS = 30000;\nconst WAITING_FOR_MS = 10 * 60_000;\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst whoLabel: Record<ChatMessage[\"from\"], string> = { visitor: \"You\", team: \"Team\", ai: \"AI agent\", auto: \"Team\" };\n\ntype MsgView = \"home\" | \"messages\" | \"help\" | { article: string };\nlet msgView: MsgView = \"home\";\nconst messengerOpen = opener();\nconst openAt = (v: MsgView = \"home\") => {\n msgView = v;\n messengerOpen.set(true);\n};\n\n/** Opens (on Home, a tab or `{ article: id }`), closes or toggles the messenger. */\nexport const useMessenger = () => ({\n open: (view?: MsgView) => openAt(view),\n close: () => messengerOpen.set(false),\n toggle: () => (messengerOpen.get() ? messengerOpen.set(false) : openAt()),\n});\n\nexport interface NativeMessengerOptions {\n /** A round chat button (default false: open it with `useMessenger().open()` from your own button). */\n launcher?: boolean;\n /** Where the chat button sits (default bottom right). */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Text beside the chat button's icon; empty: the round button. */\n label?: string;\n title?: string;\n /** The big line on Home and the first line of an empty chat. */\n greeting?: string;\n /** How soon the team usually answers, said under \"Send us a message\" and in the chat's head. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** Ask people the app did not identify with an email for an email (optional for them). Default true. */\n askEmail?: boolean;\n /** The Help tab with your published help articles (default true; hidden while there are none). */\n help?: boolean;\n /** A banner at the top when an answer arrives while the messenger is closed (default true). */\n preview?: boolean;\n /** A light haptic when an answer arrives (default true; needs expo-haptics). */\n haptics?: boolean;\n}\n\ninterface ExpoHaptics {\n notificationAsync?: (t: unknown) => Promise<void>;\n NotificationFeedbackType?: { Success: unknown };\n}\nlet haptics: ExpoHaptics | null = null;\ntry {\n haptics = require(\"expo-haptics\") as ExpoHaptics;\n} catch {\n haptics = null;\n}\nconst buzz = () => {\n try {\n void haptics?.notificationAsync?.(haptics.NotificationFeedbackType?.Success)?.catch(() => undefined);\n } catch {\n // No haptics.\n }\n};\n\nconst teamOf = (t: ChatThread | null) => (t?.messages ?? []).filter((m) => m.from !== \"visitor\");\n\ninterface SvgModule {\n Svg?: Any;\n default?: Any;\n Path: Any;\n}\nlet svg: SvgModule | null = null;\ntry {\n svg = require(\"react-native-svg\") as SvgModule;\n} catch {\n svg = null;\n}\n/** The web messenger's line icons (16-unit paths), drawn with react-native-svg when the app has it, else a text glyph. */\nconst GLYPH = {\n chat: \"M2.5 4.5a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v4.5a2 2 0 0 1-2 2H7l-3 2.5V11a2 2 0 0 1-1.5-2z\",\n home: \"M2.5 7 8 2.5 13.5 7v6a1 1 0 0 1-1 1h-3v-4h-3v4h-3a1 1 0 0 1-1-1z\",\n help: \"M8 14.5A6.5 6.5 0 1 0 8 1.5a6.5 6.5 0 0 0 0 13zM6.2 6.2a1.9 1.9 0 1 1 2.6 1.8c-.5.2-.8.6-.8 1.1v.4M8 11.6v.1\",\n send: \"M2.5 8h10M8.5 3.5 13 8l-4.5 4.5\",\n up: \"M8 13V3M3.5 7.5 8 3l4.5 4.5\",\n next: \"M6 3.5 10.5 8 6 12.5\",\n search: \"M7 11.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9zM10.5 10.5l3 3\",\n cross: \"m4 4 8 8M12 4l-8 8\",\n};\nconst FALLBACK: Record<keyof typeof GLYPH, string> = { chat: \"💬\", home: \"⌂\", help: \"?\", send: \"→\", up: \"↑\", next: \"›\", search: \"⌕\", cross: \"×\" };\nconst glyph = (name: keyof typeof GLYPH, color: string, size = 20) => {\n const Svg = svg?.Svg ?? svg?.default;\n if (!svg || !Svg) return h(RN.Text, { style: { color, fontSize: Math.round(size * 0.85), lineHeight: size + 2, textAlign: \"center\", minWidth: size } }, FALLBACK[name]);\n return h(Svg, { width: size, height: size, viewBox: \"0 0 16 16\", fill: \"none\" }, h(svg.Path, { d: GLYPH[name], stroke: color, strokeWidth: 1.7, strokeLinecap: \"round\", strokeLinejoin: \"round\", fill: \"none\" }));\n};\n/** \"#rrggbb\" with an opacity, for the accent's soft fills. */\nconst alpha = (hex: string, a: number) => (/^#[0-9a-f]{6}$/i.test(hex) ? `${hex}${Math.round(a * 255).toString(16).padStart(2, \"0\")}` : hex);\n/** The team's mark: the title's first letter on the accent (or the accent on the ink, over the colored head). */\nconst teamMark = (title: string, bg: string, fg: string, size = 36) =>\n h(\n RN.View,\n { style: { width: size, height: size, borderRadius: size / 2, backgroundColor: bg, alignItems: \"center\", justifyContent: \"center\" } },\n h(RN.Text, { style: { color: fg, fontSize: Math.round(size * 0.42), fontWeight: \"700\" } }, (title.trim()[0] ?? \"?\").toUpperCase()),\n );\nconst lift = { shadowColor: \"#101218\", shadowOpacity: 0.07, shadowRadius: 14, shadowOffset: { width: 0, height: 4 }, elevation: 2 };\n\n/** The chat's state, kept while the sheet is closed so answers count and preview. */\nconst useChat = (client: MRRocketClient, o: NativeMessengerOptions, open: boolean, view: MsgView) => {\n const [thread, setThread] = useState<ChatThread | null>(null);\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState(\"\");\n const [unseen, setUnseen] = useState<ChatMessage[]>([]);\n const known = useRef<string | null>(null);\n const watching = open && view === \"messages\";\n const watch = useRef(watching);\n watch.current = watching;\n const [active, setActive] = useState(RN.AppState.currentState === \"active\");\n useEffect(() => {\n const sub = RN.AppState.addEventListener(\"change\", (st) => setActive(st === \"active\"));\n return () => sub.remove();\n }, []);\n\n const take = useCallback(\n (t: ChatThread) => {\n const team = teamOf(t);\n if (known.current !== null) {\n const i = team.findIndex((m) => m.id === known.current);\n const fresh = team.slice(i + 1).filter((m) => m.from !== \"auto\");\n if (fresh.length) {\n if (o.haptics !== false) buzz();\n if (!watch.current) setUnseen((u) => [...u, ...fresh]);\n }\n }\n known.current = team.at(-1)?.id ?? \"\";\n setThread(t);\n },\n [o.haptics],\n );\n\n useEffect(() => {\n if (watching) setUnseen([]);\n }, [watching]);\n\n // Reads: often while the chat is on screen, now and then while the person waits for an answer, never in the background.\n useEffect(() => {\n if (!active) return;\n let stop = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let ctrl: AbortController | null = null;\n const tick = async () => {\n const api = client.api();\n if (!api) {\n setLoaded(true);\n return;\n }\n ctrl = new AbortController();\n let t: ChatThread | null = null;\n try {\n await client.ready;\n t = await api.chat(ctrl.signal);\n if (stop) return;\n take(t);\n setError(\"\");\n } catch (e) {\n if ((e as Error).name === \"AbortError\" || stop) return;\n if (watch.current) setError((e as Error).message);\n }\n setLoaded(true);\n const waiting = !!t?.messages.some((m) => m.from === \"visitor\") && t?.conversation?.status !== \"solved\";\n const wrote = (t?.messages ?? []).filter((m) => m.from === \"visitor\").at(-1)?.at;\n const recent = !!wrote && Date.now() - new Date(wrote).getTime() < WAITING_FOR_MS;\n const ms = watch.current ? POLL_OPEN_MS : waiting && recent ? POLL_WAITING_MS : waiting || open ? POLL_IDLE_MS : 0;\n if (!stop && ms) timer = setTimeout(tick, ms);\n };\n void tick();\n return () => {\n stop = true;\n ctrl?.abort();\n clearTimeout(timer);\n };\n }, [client, take, active, open, watching]);\n\n return { thread, loaded, error, setError, unseen, take };\n};\n\nconst useArticles = (client: MRRocketClient, on: boolean, query: string) => {\n const [list, setList] = useState<ArticleSummary[] | null>(null);\n const [any, setAny] = useState<boolean | null>(null);\n useEffect(() => {\n if (!on) return;\n let stop = false;\n const t = setTimeout(\n () =>\n void client.ready.then(() =>\n client\n .api()\n ?.articles(query.trim() || undefined)\n .then((r) => {\n if (stop) return;\n setList(r.articles);\n if (!query.trim()) setAny(r.articles.length > 0);\n })\n .catch(() => !stop && setList((l) => l ?? [])),\n ),\n query ? 250 : 0,\n );\n return () => {\n stop = true;\n clearTimeout(t);\n };\n }, [client, on, query]);\n return { list, any };\n};\n\nconst spansOf = (p: Palette, spans: ArticleSpan[], base: Style) =>\n spans.map((s, i) =>\n h(\n RN.Text,\n {\n key: i,\n onPress: s.href ? () => void RN.Linking.openURL(s.href!).catch(() => undefined) : undefined,\n accessibilityRole: s.href ? \"link\" : undefined,\n style: {\n ...base,\n ...(s.bold ? { fontWeight: \"700\" } : {}),\n ...(s.italic ? { fontStyle: \"italic\" } : {}),\n ...(s.code ? { fontFamily: RN.Platform.OS === \"ios\" ? \"Menlo\" : \"monospace\", backgroundColor: p.soft } : {}),\n ...(s.href ? { color: p.accent, textDecorationLine: \"underline\" } : {}),\n },\n },\n s.text,\n ),\n );\n\nconst ArticleView = ({ client, p, id, onAsk }: { client: MRRocketClient; p: Palette; id: string; onAsk: () => void }) => {\n const k = kit(p);\n const [a, setA] = useState<Article | null>(null);\n const [error, setError] = useState(\"\");\n const [rated, setRated] = useState(false);\n useEffect(() => {\n const ctrl = new AbortController();\n client\n .api()\n ?.article(id, ctrl.signal)\n .then(setA)\n .catch((e: Error) => e.name !== \"AbortError\" && setError(e.message));\n return () => ctrl.abort();\n }, [client, id]);\n if (error) return k.text(error, { color: p.danger });\n if (!a) return k.muted(\"Loading…\");\n const base = { color: p.fg, fontSize: 15, lineHeight: 22 };\n const blocks = a.blocks.map((b, i) => {\n if (b.type === \"h2\" || b.type === \"h3\") return h(RN.Text, { key: i, accessibilityRole: \"header\", style: { ...base, fontSize: b.type === \"h2\" ? 17 : 16, fontWeight: \"700\", marginTop: 8 } }, ...spansOf(p, b.spans, {}));\n if (b.type === \"p\") return h(RN.Text, { key: i, style: base }, ...spansOf(p, b.spans, {}));\n if (b.type === \"quote\") return h(RN.View, { key: i, style: { borderLeftWidth: 3, borderLeftColor: p.line, paddingLeft: 10 } }, h(RN.Text, { style: { ...base, color: p.muted } }, ...spansOf(p, b.spans, {})));\n if (b.type === \"ul\" || b.type === \"ol\")\n return h(\n RN.View,\n { key: i, style: { gap: 4 } },\n ...b.items.map((it, j) => h(RN.View, { key: j, style: { flexDirection: \"row\", gap: 8 } }, k.text(b.type === \"ol\" ? `${j + 1}.` : \"•\", base), h(RN.Text, { style: { ...base, flex: 1 } }, ...spansOf(p, it, {})))),\n );\n if (b.type === \"code\") return h(RN.View, { key: i, style: { backgroundColor: p.soft, borderRadius: 8, padding: 10 } }, k.text(b.text, { fontFamily: RN.Platform.OS === \"ios\" ? \"Menlo\" : \"monospace\", fontSize: 13 }));\n return h(RN.View, { key: i, style: { height: 1, backgroundColor: p.line } });\n });\n const rate = (helpful: boolean) => {\n setRated(true);\n client\n .api()\n ?.rateArticle(id, helpful)\n .catch(() => undefined);\n if (!helpful) onAsk();\n };\n return h(\n RN.View,\n { style: { gap: 10 } },\n k.muted(a.collection),\n h(RN.Text, { accessibilityRole: \"header\", style: { color: p.fg, fontSize: 20, fontWeight: \"700\" } }, a.title),\n ...blocks,\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, padding: 12, borderRadius: 10, backgroundColor: p.soft, marginTop: 8 } },\n rated ? k.muted(\"Thanks for letting us know.\") : k.muted(\"Did this answer your question?\", { flex: 1 }),\n rated ? null : k.btn(\"Yes\", \"secondary\", () => rate(true), false, { height: 34 }),\n rated ? null : k.btn(\"No\", \"secondary\", () => rate(false), false, { height: 34 }),\n ),\n k.btn(\"Still need help? Send us a message\", \"secondary\", onAsk),\n );\n};\n\nconst MessengerSheet = ({\n client,\n p,\n o,\n chat,\n view,\n setView,\n}: {\n client: MRRocketClient;\n p: Palette;\n o: NativeMessengerOptions;\n chat: ReturnType<typeof useChat>;\n view: MsgView;\n setView: (v: MsgView) => void;\n}) => {\n const k = kit(p);\n const [body, setBody] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n const [pending, setPending] = useState<ChatMessage | null>(null);\n const [query, setQuery] = useState(\"\");\n const helpOn = o.help !== false;\n const arts = useArticles(client, helpOn, query);\n const scroll = useRef<{ scrollToEnd?: (o: { animated: boolean }) => void } | null>(null);\n const close = () => messengerOpen.set(false);\n const greeting = o.greeting ?? \"Hi! How can we help?\";\n const { thread } = chat;\n\n const count = (thread?.messages.length ?? 0) + (pending ? 1 : 0);\n useEffect(() => {\n if (view === \"messages\") setTimeout(() => scroll.current?.scrollToEnd?.({ animated: true }), 50);\n }, [count, view]);\n\n const needEmail = (o.askEmail ?? true) && !thread?.hasEmail && !client.getUser()?.email;\n const emailOk = !email.trim() || EMAIL.test(email.trim());\n const send = async () => {\n const text = body.trim();\n const api = client.api();\n if (!text || pending || !emailOk || !api) return;\n setPending({ id: \"pending\", from: \"visitor\", body: text, at: new Date().toISOString() });\n setBody(\"\");\n chat.setError(\"\");\n try {\n chat.take(await api.sendChat({ body: text, email: needEmail && email.trim() ? email.trim() : undefined }));\n } catch (e) {\n setBody(text);\n chat.setError((e as Error).message);\n } finally {\n setPending(null);\n }\n };\n\n const ink = inkOn(p.accent);\n const dark = p.bg === DARK.bg;\n // Light: white cards on a soft gray; dark: lighter cards on the dark ground.\n const canvas = dark ? p.bg : p.soft;\n const raised = dark ? p.soft : p.bg;\n const title = o.title ?? \"Chat with us\";\n const reply = replyLine(o.replyTime);\n\n const bubble = (m: ChatMessage, isPending = false) => {\n const mine = m.from === \"visitor\";\n return h(\n RN.View,\n { key: m.id, style: { alignSelf: mine ? \"flex-end\" : \"flex-start\", maxWidth: \"82%\", gap: 4 } },\n h(\n RN.View,\n {\n style: {\n backgroundColor: mine ? p.accent : dark ? p.soft : \"#eeeff1\",\n borderRadius: 18,\n borderBottomRightRadius: mine ? 6 : 18,\n borderBottomLeftRadius: mine ? 18 : 6,\n paddingHorizontal: 14,\n paddingVertical: 9,\n opacity: isPending ? 0.7 : 1,\n },\n },\n k.text(m.body, { color: mine ? ink : p.fg }),\n ),\n ...(m.articles ?? []).map((a) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"link\", style: { borderWidth: 1, borderColor: p.line, borderRadius: 12, paddingHorizontal: 10, paddingVertical: 7 } },\n k.text(`📄 ${a.title}`, { fontSize: 13 }),\n ),\n ),\n m.at ? k.muted(`${mine ? \"\" : `${whoLabel[m.from]} · `}${isPending ? \"Sending…\" : timeAgo(m.at)}`, { fontSize: 11, textAlign: mine ? \"right\" : \"left\", paddingHorizontal: 6 }) : null,\n );\n };\n const row = (a: ArticleSummary) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"button\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingVertical: 11, paddingHorizontal: 8 } },\n k.text(a.title, { flex: 1 }),\n glyph(\"next\", p.accent, 14),\n );\n const card = (children: ReactNode[], style: Style = {}) => h(RN.View, { style: { backgroundColor: raised, borderRadius: 16, padding: 16, ...(dark ? { borderWidth: 1, borderColor: p.line } : lift), ...style } }, ...children);\n const searchRow = (onPress: () => void) =>\n h(\n RN.Pressable,\n { key: \"s\", onPress, accessibilityRole: \"search\", style: { flexDirection: \"row\", alignItems: \"center\", height: 44, borderRadius: 12, paddingHorizontal: 14, backgroundColor: canvas } },\n k.muted(\"Search for help\", { flex: 1, fontSize: 15 }),\n glyph(\"search\", p.accent, 16),\n );\n const search = k.field({ value: query, onChange: setQuery, placeholder: \"Search for help\", max: 200, style: { borderWidth: 0, borderRadius: 12, backgroundColor: raised, ...(dark ? {} : lift) } });\n\n const last = thread?.messages.at(-1);\n const showHelp = helpOn && arts.any !== false;\n let content: ReactNode;\n if (view === \"home\")\n content = h(\n RN.ScrollView,\n { key: \"home\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { paddingBottom: 24 }, keyboardShouldPersistTaps: \"handled\" },\n h(RN.View, { style: { backgroundColor: p.accent, paddingHorizontal: 22, paddingTop: 4, paddingBottom: 64 } }, h(RN.Text, { style: { color: ink, fontSize: 28, fontWeight: \"700\", letterSpacing: -0.4, lineHeight: 34 } }, greeting)),\n h(\n RN.View,\n { style: { marginTop: -48, paddingHorizontal: 16, gap: 12 } },\n last\n ? h(\n RN.Pressable,\n { key: \"recent\", onPress: () => setView(\"messages\"), accessibilityRole: \"button\" },\n card([\n k.muted(\"Recent message\", { fontSize: 12, fontWeight: \"600\", marginBottom: 10 }),\n h(\n RN.View,\n { key: \"r\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 12 } },\n teamMark(title, p.accent, ink),\n h(RN.View, { style: { flex: 1, gap: 2 } }, h(RN.Text, { numberOfLines: 1, style: { color: p.fg, fontSize: 15 } }, last.body), k.muted(`${last.from === \"visitor\" ? \"You\" : whoLabel[last.from]} · ${timeAgo(last.at)}`, { fontSize: 12 })),\n chat.unseen.length\n ? h(RN.View, { style: { minWidth: 20, height: 20, borderRadius: 10, paddingHorizontal: 6, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\" } }, k.text(String(chat.unseen.length), { color: \"#fff\", fontSize: 12, fontWeight: \"700\" }))\n : glyph(\"next\", p.muted, 14),\n ),\n ]),\n )\n : null,\n h(\n RN.Pressable,\n { key: \"send\", onPress: () => setView(\"messages\"), accessibilityRole: \"button\" },\n card(\n [\n h(RN.View, { key: \"t\", style: { flex: 1, gap: 2 } }, k.text(\"Send us a message\", { fontWeight: \"700\", fontSize: 16 }), k.muted(reply)),\n h(RN.View, { key: \"g\", style: { width: 36, height: 36, borderRadius: 18, backgroundColor: alpha(p.accent, 0.12), alignItems: \"center\", justifyContent: \"center\" } }, glyph(\"send\", p.accent, 18)),\n ],\n { flexDirection: \"row\", alignItems: \"center\", gap: 12 },\n ),\n ),\n showHelp ? card([searchRow(() => setView(\"help\")), ...(arts.list ?? []).slice(0, 4).map(row)], { padding: 8, gap: 2 }) : null,\n ),\n );\n else if (view === \"messages\")\n content = h(\n RN.View,\n { key: \"messages\", style: { flex: 1, backgroundColor: p.bg } },\n h(\n RN.ScrollView,\n { ref: scroll, style: { flex: 1 }, contentContainerStyle: { padding: 16, gap: 12 } },\n bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }),\n !chat.loaded ? k.muted(\"Loading…\") : null,\n ...(thread?.messages ?? []).map((m) => bubble(m)),\n pending ? bubble(pending, true) : null,\n thread?.conversation?.status === \"solved\" && !pending ? k.muted(\"This conversation is closed. Write to start a new one.\", { textAlign: \"center\" }) : null,\n ),\n h(\n RN.View,\n { style: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 10, gap: 8 } },\n chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,\n needEmail\n ? k.field({ value: email, onChange: setEmail, placeholder: \"Your email (optional), so we can follow up\", email: true, max: 200, style: { borderWidth: emailOk ? 0 : 1, borderColor: p.danger, borderRadius: 12, backgroundColor: canvas } })\n : null,\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, borderWidth: 1, borderColor: p.line, borderRadius: 22, paddingVertical: 5, paddingRight: 5, paddingLeft: 16, backgroundColor: p.bg } },\n k.field({ value: body, onChange: setBody, placeholder: \"Write a message…\", multiline: true, max: 4000, style: { flex: 1, minHeight: 34, maxHeight: 120, borderWidth: 0, paddingHorizontal: 0, paddingVertical: 7, backgroundColor: \"transparent\" } }),\n h(\n RN.Pressable,\n {\n onPress: () => void send(),\n disabled: !body.trim() || !!pending || !emailOk,\n accessibilityRole: \"button\",\n accessibilityLabel: \"Send\",\n style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\", backgroundColor: !body.trim() || !!pending || !emailOk ? p.line : p.accent },\n },\n glyph(\"up\", !body.trim() || !!pending || !emailOk ? p.muted : ink, 18),\n ),\n ),\n ),\n );\n else if (view === \"help\") {\n const groups = new Map<string, ArticleSummary[]>();\n for (const a of arts.list ?? []) groups.set(a.collection, [...(groups.get(a.collection) ?? []), a]);\n content = h(\n RN.ScrollView,\n { key: \"help\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { padding: 16, gap: 12 }, keyboardShouldPersistTaps: \"handled\" },\n search,\n arts.list === null ? k.muted(\"Loading…\") : null,\n arts.list?.length === 0\n ? h(RN.View, { style: { gap: 10, alignItems: \"center\", paddingVertical: 24 } }, k.muted(query.trim() ? `Nothing found for “${query.trim()}”.` : \"No help articles yet.\"), k.btn(\"Send us a message\", \"primary\", () => setView(\"messages\")))\n : null,\n ...(query.trim()\n ? arts.list?.length\n ? [card((arts.list ?? []).map(row), { padding: 8 })]\n : []\n : [...groups].map(([name, items]) => h(RN.View, { key: name, style: { gap: 6 } }, k.muted(`${name} · ${items.length}`, { fontSize: 12, fontWeight: \"600\", paddingHorizontal: 2 }), card(items.map(row), { padding: 8 })))),\n );\n } else\n content = h(\n RN.ScrollView,\n { key: `a-${view.article}`, style: { flex: 1 }, contentContainerStyle: { padding: 16, paddingBottom: 32 } },\n h(ArticleView, { client, p, id: view.article, onAsk: () => setView(\"messages\") }),\n );\n\n const current = typeof view === \"string\" ? view : \"help\";\n const tab = (v: \"home\" | \"messages\" | \"help\", name: string, icon: keyof typeof GLYPH, badge = 0) =>\n h(\n RN.Pressable,\n { key: v, onPress: () => setView(v), accessibilityRole: \"tab\", accessibilityState: { selected: current === v }, style: { flex: 1, alignItems: \"center\", paddingTop: 8, paddingBottom: 6, gap: 3 } },\n glyph(icon, current === v ? p.accent : p.muted, 22),\n k.text(name, { fontSize: 12, fontWeight: \"600\", color: current === v ? p.accent : p.muted }),\n badge ? h(RN.View, { style: { position: \"absolute\", top: 4, right: \"28%\", minWidth: 18, height: 18, borderRadius: 9, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\" } }, k.text(String(Math.min(badge, 9)), { color: \"#fff\", fontSize: 11, fontWeight: \"700\" })) : null,\n );\n // The head: on Home in the accent with the team's mark, in the chat with the reply time, in Help plain.\n const onHome = view === \"home\";\n const headFg = onHome ? ink : p.fg;\n const head = h(\n RN.View,\n { key: \"head\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 10, paddingLeft: 16, paddingRight: 12, paddingTop: 16, paddingBottom: 12, backgroundColor: onHome ? p.accent : p.bg, borderBottomWidth: onHome ? 0 : 1, borderBottomColor: p.line } },\n typeof view !== \"string\"\n ? h(RN.Pressable, { key: \"back\", onPress: () => setView(\"help\"), accessibilityRole: \"button\", hitSlop: 10 }, k.text(\"‹ All articles\", { color: p.accent, fontWeight: \"600\" }))\n : view === \"help\"\n ? null\n : teamMark(title, onHome ? ink : p.accent, onHome ? p.accent : ink, onHome ? 28 : 36),\n h(\n RN.View,\n { style: { flex: 1, minWidth: 0 } },\n typeof view !== \"string\" ? null : h(RN.Text, { accessibilityRole: \"header\", numberOfLines: 1, style: { color: headFg, fontSize: 17, fontWeight: \"700\" } }, view === \"help\" ? \"Help\" : title),\n view === \"messages\" ? k.muted(reply, { fontSize: 12 }) : null,\n ),\n h(RN.Pressable, { onPress: close, accessibilityRole: \"button\", accessibilityLabel: \"Close\", hitSlop: 12, style: { width: 32, height: 32, borderRadius: 10, alignItems: \"center\", justifyContent: \"center\" } }, glyph(\"cross\", onHome ? ink : p.muted, 18)),\n );\n return h(\n RN.Modal,\n { visible: true, animationType: \"slide\", presentationStyle: \"pageSheet\", onRequestClose: close },\n h(\n RN.KeyboardAvoidingView,\n { behavior: RN.Platform.OS === \"ios\" ? \"padding\" : undefined, style: { flex: 1, backgroundColor: p.bg } },\n head,\n content,\n h(\n RN.View,\n { key: \"tabs\", accessibilityRole: \"tablist\", style: { flexDirection: \"row\", borderTopWidth: 1, borderTopColor: p.line, paddingHorizontal: 8, paddingBottom: 22, backgroundColor: p.bg } },\n tab(\"home\", \"Home\", \"home\"),\n tab(\"messages\", \"Messages\", \"chat\", view === \"messages\" ? 0 : chat.unseen.length),\n showHelp ? tab(\"help\", \"Help\", \"help\") : null,\n ),\n ),\n );\n};\n\nexport const MRRocketMessenger = ({ client, appearance, options: given = {} }: { client: MRRocketClient; appearance?: NativeAppearance; options?: NativeMessengerOptions }) => {\n // The look from MRRocket › Support › Messenger under what the app passes.\n const [look, setLook] = useState<MessengerLook | null>(null);\n useEffect(() => {\n const ctrl = new AbortController();\n void client.ready.then(() =>\n client\n .api()\n ?.messengerLook(ctrl.signal)\n .then(setLook)\n .catch(() => undefined),\n );\n return () => ctrl.abort();\n }, [client]);\n const defined = Object.fromEntries(Object.entries(given).filter(([, v]) => v !== undefined)) as NativeMessengerOptions;\n const options: NativeMessengerOptions = look\n ? {\n title: look.title,\n greeting: look.greeting,\n replyTime: look.replyTime,\n launcher: look.appLauncher ?? false,\n position: look.position,\n label: look.label,\n help: look.help,\n preview: look.preview,\n askEmail: look.askEmail,\n haptics: look.sound,\n ...defined,\n }\n : given;\n const p = usePalette({ theme: appearance?.theme ?? look?.theme, accent: appearance?.accent ?? look?.accent });\n const k = kit(p);\n const open = messengerOpen.useOpen();\n const [view, setViewState] = useState<MsgView>(msgView);\n const [banner, setBanner] = useState<ChatMessage | null>(null);\n useEffect(() => {\n if (open) setViewState(msgView);\n }, [open]);\n const setView = (v: MsgView) => {\n msgView = v;\n setViewState(v);\n };\n const chat = useChat(client, options, open, view);\n\n // A new answer while closed: a banner at the top for a few seconds (tap to open the chat).\n const latest = chat.unseen.at(-1);\n useEffect(() => {\n if (!latest || open || options.preview === false) return;\n setBanner(latest);\n const t = setTimeout(() => setBanner(null), 6000);\n return () => clearTimeout(t);\n }, [latest, open, options.preview]);\n useEffect(() => {\n if (open) setBanner(null);\n }, [open]);\n\n const unseen = chat.unseen.length;\n const ink = inkOn(p.accent);\n const label = options.label?.trim() ?? \"\";\n const side = options.position === \"bottom-left\" ? { left: 20 } : { right: 20 };\n const launcher = options.launcher\n ? h(\n RN.Pressable,\n {\n key: \"launcher\",\n onPress: () => openAt(unseen ? \"messages\" : \"home\"),\n accessibilityRole: \"button\",\n accessibilityLabel: unseen ? `Open chat, ${unseen} new` : \"Open chat\",\n style: {\n position: \"absolute\",\n ...side,\n bottom: 34,\n height: label ? 50 : 56,\n minWidth: label ? 0 : 56,\n paddingHorizontal: label ? 18 : 0,\n borderRadius: 28,\n flexDirection: \"row\",\n gap: 8,\n backgroundColor: p.accent,\n alignItems: \"center\",\n justifyContent: \"center\",\n shadowColor: p.accent,\n shadowOpacity: 0.4,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n elevation: 6,\n },\n },\n glyph(\"chat\", ink, label ? 20 : 26),\n label ? k.text(label, { color: ink, fontWeight: \"700\" }) : null,\n unseen\n ? h(RN.View, { style: { position: \"absolute\", top: -2, right: -2, minWidth: 20, height: 20, borderRadius: 10, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\", borderWidth: 2, borderColor: p.bg } }, k.text(String(Math.min(unseen, 9)), { color: \"#fff\", fontSize: 11, fontWeight: \"700\" }))\n : null,\n )\n : null;\n const toast = banner\n ? h(\n RN.Pressable,\n {\n key: \"banner\",\n onPress: () => openAt(\"messages\"),\n accessibilityRole: \"button\",\n accessibilityLiveRegion: \"polite\",\n style: { position: \"absolute\", top: 54, left: 16, right: 16, flexDirection: \"row\", alignItems: \"flex-start\", gap: 12, backgroundColor: p.bg, borderRadius: 18, padding: 14, borderWidth: 1, borderColor: p.line, shadowColor: \"#000\", shadowOpacity: 0.16, shadowRadius: 18, shadowOffset: { width: 0, height: 8 }, elevation: 8 },\n },\n teamMark(options.title ?? \"Chat with us\", p.accent, ink),\n h(\n RN.View,\n { style: { flex: 1, gap: 2 } },\n k.muted(`${whoLabel[banner.from]}${unseen > 1 ? ` · ${unseen} new` : \"\"}`, { fontWeight: \"600\", fontSize: 12 }),\n h(RN.Text, { numberOfLines: 3, style: { color: p.fg, fontSize: 15 } }, banner.body),\n ),\n )\n : null;\n if (!launcher && !toast && !open) return null;\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", top: 0, left: 0, right: 0, bottom: 0 } },\n launcher,\n toast,\n open ? h(MessengerSheet, { client, p, o: options, chat, view, setView }) : null,\n );\n};\n"],"mappings":"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","names":["import_react","h","h","clip","text","h","RN","h","import_react","RN","text","h","RN","text"]}