@mrrocket/sdk 0.18.0 → 0.22.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.
- package/CHANGELOG.md +29 -0
- package/README.md +36 -1
- package/dist/api-client.d.ts +28 -4
- package/dist/api-client.js +30 -13
- package/dist/api-client.js.map +1 -1
- package/dist/browser/mrrocket-flows.js +8 -3
- package/dist/browser/mrrocket-messenger.js +38 -5
- package/dist/browser/mrrocket.js +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -1
- package/dist/browser.js.map +1 -1
- package/dist/client.d.ts +17 -1
- package/dist/client.js +25 -5
- package/dist/client.js.map +1 -1
- package/dist/core.d.ts +5 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/feedback.js +161 -119
- package/dist/feedback.js.map +1 -1
- package/dist/flows-ui.d.ts +1 -1
- package/dist/flows-ui.js +100 -72
- package/dist/flows-ui.js.map +1 -1
- package/dist/flows-web.js +2 -1
- package/dist/flows-web.js.map +1 -1
- package/dist/flows.d.ts +38 -6
- package/dist/flows.js +51 -17
- package/dist/flows.js.map +1 -1
- package/dist/i18n.d.ts +22 -0
- package/dist/i18n.js +74 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/messenger-ui.d.ts +9 -3
- package/dist/messenger-ui.js +324 -152
- package/dist/messenger-ui.js.map +1 -1
- package/dist/messenger.d.ts +3 -1
- package/dist/messenger.js +3 -2
- package/dist/messenger.js.map +1 -1
- package/dist/onboarding-report.d.ts +19 -0
- package/dist/onboarding-report.js +23 -0
- package/dist/onboarding-report.js.map +1 -0
- package/dist/onboarding-state.d.ts +3 -0
- package/dist/onboarding-state.js +7 -1
- package/dist/onboarding-state.js.map +1 -1
- package/dist/paywall.js +2 -1
- package/dist/paywall.js.map +1 -1
- package/dist/react-native/index.d.cts +93 -8
- package/dist/react-native/index.d.ts +93 -8
- package/dist/react-native/index.js +819 -511
- package/dist/react-native/index.js.map +1 -1
- package/dist/server.d.ts +4 -2
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/styles-css.d.ts +1 -1
- package/dist/styles-css.js +35 -2
- package/dist/styles-css.js.map +1 -1
- package/dist/survey.js +18 -14
- package/dist/survey.js.map +1 -1
- package/dist/ui.d.ts +2 -0
- package/dist/ui.js +15 -12
- package/dist/ui.js.map +1 -1
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/native/index.tsx","../../src/core.ts","../../src/onboarding-state.ts","../../src/identity.ts","../../src/api-client.ts","../../src/batch.ts","../../src/errors.ts","../../src/flows.ts","../../src/paywall.ts","../../src/rage.ts","../../src/native/recorder.ts","../../src/referral.ts","../../src/native/client.ts","../../src/native/flows-view.ts","../../src/icons.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 UseOnboarding, useOnboardingItem } from \"../onboarding-state\";\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, FlowMedia, TourPlacement, TaskOpens, FlowIcon, FinishAnimation, OnboardingQuestion, OnboardingItemState } from \"../flows\";\nexport type { UseOnboarding } from \"../onboarding-state\";\nexport { MRRocketFlows, type NativeAppearance };\nexport type { PaywallConfig, PaywallOptions, PaywallPage, PaywallPlan, PaywallResult } from \"../paywall\";\nexport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, useFeedback, useMessenger, type NativeFeedbackOptions, type NativeMessengerOptions };\nexport type { ChatMessage, ChatThread, FeedbackPost, SurveyDefinition } from \"../api-client\";\nexport type { IdentifyOptions } from \"../identity\";\nexport type { KeyValueStorage, MRRocketClient, MRRocketOptions, NativeConsent, NativePushResult, NativePushStatus, NativeReviewResult, 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, paywall: client.paywall, 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/**\n * The paywalls built in MRRocket › Paywalls, page by page; the provider draws them. The last page hands the chosen plan\n * to `onPurchase`, where your code buys it. MRRocket never takes a payment.\n *\n * const paywall = usePaywall();\n * paywall.open(\"onboarding_end\", { plans: storePlans, onPurchase: (plan) => Purchases.purchasePackage(packages[plan.id]) });\n */\nexport const usePaywall = (): { open: MRRocketClient[\"openPaywall\"] } => {\n const client = useClient();\n return { open: client.openPaywall };\n};\n\n/**\n * 0.16.0: store reviews from a review request in MRRocket › Reviews › Requests (needs `expo-store-review`). Call\n * `request()` at the moment the request names (after the third finished challenge, a 7-day streak …): MRRocket says\n * whether this signed-in person may be asked now, and the App Store's or Google Play's own rating dialog opens.\n *\n * const review = useReview();\n * if (challengesDone === 3) void review.request();\n */\nexport const useReview = (): { request: MRRocketClient[\"requestReview\"] } => {\n const client = useClient();\n return { request: client.requestReview };\n};\n\n/**\n * `start(id?)` starts an onboarding flow now (the first live one without an id), whatever its trigger. 0.18.0: with an\n * id, also the item you draw yourself (\"Shown by: your code\" in MRRocket): `item`, `steps` (each with `done`), `done`,\n * `complete(stepId)`, `dismiss()` and `answer(question, value)`; MRRocket still counts it and keeps the answers on the\n * contact.\n *\n * const { item, steps, done, complete } = useOnboarding(\"flow_123\");\n * if (!item || done) return null;\n */\nexport const useOnboarding = (id?: string): UseOnboarding => {\n const client = useClient();\n return useOnboardingItem(client.flows, id, 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\";\nimport type { PaywallConfig } from \"./paywall\";\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.18.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 /** The product's brand color (\"#rrggbb\") for the onboarding dialogs when the app passes no accent. SDK 0.18.0+. */\n onboardingAccent?: string;\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 /** Published paywalls with their pages, per placement (MRRocket › Conversion › Paywalls), for `paywall.open()`. SDK 0.14.0+. */\n paywalls?: PaywallConfig[];\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 * 0.18.0: `useOnboarding(id)` for an onboarding item the app draws itself (\"Shown by: your code\" in MRRocket): its\n * content and the person's progress, and the calls that report what they did. Shared by the Next.js provider and React\n * Native (only React here). The SDK draws nothing for such an item and never starts it; what the app reports still\n * reaches MRRocket (who saw it, who finished it, the answers on the contact), and the item after it follows as usual.\n *\n * const { item, steps, done, complete, dismiss, answer } = useOnboarding(\"flow_123\");\n * if (!item || done) return null;\n * return steps.map((s) => <Task key={s.id} title={s.title} done={s.done} onPress={() => complete(s.id)} />);\n */\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { FlowsController, OnboardingFlow, OnboardingItemState } from \"./flows\";\n\nexport interface UseOnboarding {\n /** The item as MRRocket published it, or null while the config is loading, or when it is not live. */\n item: OnboardingFlow | null;\n /** Its steps (a tour's steps, a checklist's tasks, the questions), each with `done` (and a question's `answer`). */\n steps: OnboardingItemState[\"steps\"];\n /** Every step is done. */\n done: boolean;\n /** The person closed it. */\n dismissed: boolean;\n /** Its moment has come for this person (the trigger MRRocket set, and who it is for). */\n eligible: boolean;\n /** Marks a step done (a tour step, a task). */\n complete(stepId: string): void;\n /** The person closed it; the item after it follows. */\n dismiss(): void;\n /** Answers a question (its step id or its key) with an option's id or a text; it is kept on the contact. */\n answer(question: string, value: string): void;\n /** Starts an item the SDK draws (the first live one without an id). */\n start(id?: string): boolean;\n}\n\nconst none: OnboardingItemState[\"steps\"] = [];\n\n/** The hook behind `useOnboarding` on both platforms. */\nexport const useOnboardingItem = (flows: FlowsController | null | undefined, id: string | undefined, start: (id?: string) => boolean): UseOnboarding => {\n const [state, setState] = useState<OnboardingItemState | null>(() => (flows && id ? flows.onboarding.item(id) : null));\n useEffect(() => {\n if (!flows || !id) {\n setState(null);\n return;\n }\n const up = () => {\n const s = flows.onboarding.item(id);\n setState(s);\n // Asked for by the app: counted as seen (started, and its first open steps), once per page.\n if (s && !s.done && !s.dismissed) flows.onboarding.seen(id);\n };\n up();\n return flows.subscribe(up);\n }, [flows, id]);\n return useMemo(\n () => ({\n item: state?.item ?? null,\n steps: state?.steps ?? none,\n done: !!state?.done,\n dismissed: !!state?.dismissed,\n eligible: !!state?.eligible,\n complete: (stepId: string) => {\n if (flows && id) flows.onboarding.complete(id, stepId);\n },\n dismiss: () => {\n if (flows && id) flows.onboarding.dismissItem(id);\n },\n answer: (question: string, value: string) => {\n if (flows && id) flows.onboarding.answerItem(id, question, value);\n },\n start,\n }),\n [state, flows, id, start],\n );\n};\n","/**\n * Identity verification (0.16.0), the browser and app side. After `identify(id)` the SDK's id is your app's own user\n * id, and that id is no secret (a Clerk id shows in URLs and logs), so on its own it proves nothing: anyone who knows it\n * could read that person's support chat or post as them. Your server signs the id with the product's server key\n * (`userHash(user.id)` from `@mrrocket/sdk/next/server`) and you hand the result to `identify(id, props, { hash })`.\n * From then on every request for that id carries it as `userHash` (a JSON field, a query parameter or a form field), and\n * MRRocket checks it.\n *\n * The hash belongs to one id: it is forgotten on `reset()` (sign-out) and when `identify` is called for another id\n * without a hash, so it never goes out with someone else's id (MRRocket refuses a hash that does not match with 401).\n * Shared by the Next.js provider, the script tag and React Native: no React, no browser APIs.\n */\n\n/** The third argument of `identify`. */\nexport interface IdentifyOptions {\n /**\n * The id signed by your server: `await userHash(user.id)` from `@mrrocket/sdk/next/server` (or the same HMAC in any\n * language). Needed when MRRocket › Settings › Products › Sign-in › \"Only signed users\" is on.\n */\n hash?: string;\n}\n\n/** The id the SDK holds a hash for, and the hash. */\nexport interface Signed {\n id: string;\n hash: string;\n}\n\n/** What to do when MRRocket refuses a request for want of a hash (once per page, in the console). Short: sdk.js has a size budget. */\nexport const UNSIGNED_HELP = \"401: sign the user id on your server with userHash(id) from @mrrocket/sdk/next/server and pass identify(id, props, { hash }).\";\n\n/** Says once per page (or app run) why MRRocket answered 401; other statuses say nothing. */\nexport const warnUnsigned = (status: number, log: (message: string) => void = (m) => console.warn(m)) => {\n const g = globalThis as { __mrrocketUnsigned?: boolean };\n if (status !== 401 || g.__mrrocketUnsigned) return;\n g.__mrrocketUnsigned = true;\n log(`[MRRocket] ${UNSIGNED_HELP}`);\n};\n\n/**\n * The signed id after `identify(id, …, { hash })`: a new hash replaces the old one, the same id without a hash keeps\n * the one it has, another id without a hash drops it. A hash that is not 64 hex characters (a typo, the server key\n * itself) is ignored with a warning instead of being sent.\n */\nexport const nextSigned = (signed: Signed | null, id: string, hash: unknown, log: (message: string) => void = (m) => console.warn(m)): Signed | null => {\n const h = typeof hash === \"string\" ? hash.trim().toLowerCase() : \"\";\n if (/^[0-9a-f]{64}$/.test(h)) return { id, hash: h };\n if (h) log(\"[MRRocket] identify: that hash is no userHash(id); not sent.\");\n return signed && signed.id === id ? signed : null;\n};\n\n/** The hash for `id`, when the SDK holds one for exactly that id. */\nexport const hashFor = (signed: Signed | null | undefined, id: string | undefined) => (signed && id && signed.id === id ? signed.hash : undefined);\n\n/**\n * The hash for a request that carries several items with their own ids (error reports): only when every item that\n * names someone names the signed id, so a report of an earlier visitor never goes out under this person's hash.\n */\nexport const hashForAll = (signed: Signed | null | undefined, ids: (string | undefined)[]) =>\n signed && ids.some((id) => id === signed.id) && ids.every((id) => !id || id === signed.id) ? signed.hash : undefined;\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 */\nimport { warnUnsigned } from \"./identity\";\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/** A file in the messenger's chat: a screenshot, a photo or a PDF the visitor sent (servers from SDK 0.15 on). */\nexport interface ChatFile {\n /** From an upload: the signed id a message sends. In a message: the file's own id (`attachmentUrl` reads it). */\n id: string;\n name: string;\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" | \"image/gif\" | \"application/pdf\";\n /** Bytes. */\n size: number;\n}\n\n/** What the messenger can send: pictures and PDFs, at most 10 MB each, 4 per message. */\nexport const CHAT_FILE_TYPES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\", \"application/pdf\"] as const;\nexport const CHAT_FILE_MAX_BYTES = 10 * 1024 * 1024;\nexport const CHAT_FILES_PER_MESSAGE = 4;\n\n/** A file to upload: a Blob or File on the web, the image picker's `{ uri, name, type }` in React Native. */\nexport type ChatUpload = Blob | { uri: string; name: string; type: string };\n\n/** The bug context a visitor message carries; the server fills browser and system from the user agent when left out. */\nexport interface ChatContext {\n browser?: string;\n os?: string;\n /** \"1440×900\". */\n viewport?: string;\n}\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 /** Files sent with it (servers from SDK 0.15 on). */\n attachments?: ChatFile[];\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/** Where the chat button sits: a corner, the middle of the top or bottom edge, or the middle of a side. */\nexport type MessengerPosition = \"top-left\" | \"top-center\" | \"top-right\" | \"middle-left\" | \"middle-right\" | \"bottom-left\" | \"bottom-center\" | \"bottom-right\";\n\n/** How round the messenger is. */\nexport type MessengerCorners = \"round\" | \"soft\" | \"square\";\n\n/** The radii per corner style, in px: the panel or sheet, message bubbles (and their tail), cards, fields and buttons. */\nexport const CORNERS: Record<MessengerCorners, { panel: number; bubble: number; tail: number; card: number; field: number }> = {\n round: { panel: 22, bubble: 18, tail: 6, card: 16, field: 20 },\n soft: { panel: 14, bubble: 12, tail: 4, card: 10, field: 10 },\n square: { panel: 6, bubble: 6, tail: 2, card: 4, field: 4 },\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 /** Up to two more colors blended into Home's background glow (MRRocket from 0.16; older servers leave it out). */\n glow?: string[];\n theme: \"light\" | \"dark\" | \"auto\";\n position: MessengerPosition;\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 /** How round panel, bubbles, cards and fields are (MRRocket from 0.15; older servers leave it out: round). */\n corners?: MessengerCorners;\n /** The site's own font (the default) or the system's (web only; from 0.15). */\n font?: \"site\" | \"system\";\n /** Home's top: plain like the rest, or in the accent color (from 0.15; older servers leave it out: plain). */\n header?: \"plain\" | \"color\";\n /** \"Powered by MRRocket\" at the bottom; the server sends false only on plans that may hide it (from 0.15). */\n branding?: boolean;\n /** The logo at the top left of Home: the one uploaded in MRRocket, else the product's favicon; without it the title's first letter. */\n logo?: string;\n /** The product's favicon, the round mark in the chat's head (from 0.17; without it the title's first letter). */\n icon?: string;\n /** The AI agent's name on its answers (from 0.17; empty or left out: \"AI agent\"). */\n agentName?: string;\n /** The AI agent's picture beside its answers (from 0.17). */\n agentPhoto?: string;\n}\n\n/** The link behind \"Powered by MRRocket\". */\nexport const BRAND_URL = \"https://mrrocket.dev/?utm_source=messenger&utm_medium=powered-by\";\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 * The identity hash of `distinctId` (0.16.0, see identity.ts), sent with every request that names the visitor: a\n * JSON field next to `distinctId`, a query parameter, a form field. Leave it out for any other id.\n */\n userHash?: string;\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 // A form (a file upload) sets its own multipart type with the boundary.\n headers: typeof init?.body === \"string\" ? { \"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 // A missing or wrong identity hash: the console says once how to sign the user id.\n warnUnsigned(res.status);\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, userHash: c.userHash };\n // Every query that names the visitor names its hash too.\n const me = { key: c.apiKey, distinctId: c.distinctId, userHash: c.userHash };\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({ ...me, 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(me)}`, undefined, signal),\n roadmap: (signal?: AbortSignal) => call<FeedbackRoadmap>(`${base}/feedback/roadmap?${qs(me)}`, 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({ ...me, 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(me)}`, undefined, signal),\n /** A message; `attachments` are upload ids from `uploadChatFile` (then the body may be empty). */\n sendChat: (m: { body: string; email?: string; url?: string; attachments?: string[]; context?: ChatContext }) => post<ChatThread>(\"/messages\", m),\n /** Uploads one picked file for the next message (pictures and PDFs, at most 10 MB); answers its upload id. */\n uploadChatFile: (file: ChatUpload, signal?: AbortSignal) => {\n const form = new FormData();\n form.append(\"key\", c.apiKey);\n form.append(\"distinctId\", c.distinctId);\n if (c.userHash) form.append(\"userHash\", c.userHash);\n if (\"uri\" in file) form.append(\"file\", file as unknown as Blob);\n else form.append(\"file\", file, (file as Blob & { name?: string }).name || \"file\");\n return call<ChatFile>(`${base}/messages/attachments`, { method: \"POST\", body: form }, signal);\n },\n /** Where a sent file of this visitor's chat is read (an image's src, a PDF's link). */\n attachmentUrl: (id: string) => `${base}/messages/attachments/${encodeURIComponent(id)}?${qs(me)}`,\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(me)}`, 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). `userHash` (0.16.0) is the identity hash of the signed-in person: one per request, and\n * MRRocket checks it against each event's `distinctId`, so only that person's events count as verified.\n */\nexport const batchRequests = <E extends CockpitEvent>(key: string, events: E[], sdk: SdkInfo, userHash?: string): BatchRequest<E>[] => {\n const head = `{\"key\":${JSON.stringify(key)},${userHash ? `\"userHash\":${JSON.stringify(userHash)},` : \"\"}\"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); `userHash`\n * as in `batchRequests`.\n */\nexport const bodies = (key: string, events: CockpitEvent[], sdk: SdkInfo, userHash?: string) => batchRequests(key, events, sdk, userHash).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\";\nimport { hashForAll, warnUnsigned } from \"./identity\";\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 /**\n * Read when an error happens: whether to send at all (consent), and who and which session. `userHash` is the identity\n * hash of `distinctId` (0.16.0); read again when sending, and sent only with reports of that id.\n */\n context: () => { send: boolean; distinctId?: string; sessionId?: string; userHash?: 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 reports = queue.splice(0, 4);\n const now = opts.context();\n const signed = now.distinctId && now.userHash ? { id: now.distinctId, hash: now.userHash } : null;\n const userHash = hashForAll(signed, reports.map((r) => r.distinctId));\n const body = JSON.stringify({ key: opts.apiKey, ...(userHash ? { userHash } : {}), errors: reports });\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.status === 401) warnUnsigned(401);\n else 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; since 0.17.0 a tour a checklist task started records `{action: \"started\", from}` with\n * the checklist's id; since 0.18.0 a question records `{kind: \"question\", action: \"completed\", question, answer,\n * label}` (the question's key, the option's id or the typed text, the option's words), which MRRocket keeps on the\n * contact, and a checklist task that opens something `{action: \"opened\", opens}`.\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/** 0.16.0: the app asked the store's rating dialog for a review request (or found none on the device). */\nexport const REVIEW_EVENT = \"$review_prompt\";\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/** 0.15.0: a second question after an answer (\"What would be a fair price?\"); no answers means a free text. */\nexport interface CancelFollowUp {\n question: string;\n /** The choices, in order; empty for a free text. */\n answers: string[];\n}\n\n/**\n * 0.15.0: a different offer for some customers of one answer. Every condition that is set must hold; the first rule\n * that matches wins, else the answer's own offer. `offer: null` means no offer (straight to the confirmation).\n */\nexport interface CancelRule {\n when: {\n /** The follow-up's answer, as written. */\n answer?: string;\n /** The customer's plan: its id or name as MRRocket knows it from the payment provider (any of a list). */\n plan?: string | string[];\n /** A customer for fewer than this many months. */\n tenureUnder?: number;\n /** A customer for at least this many months. */\n tenureOver?: number;\n };\n offer: CancelOffer | null;\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 /** 0.15.0: the follow-up question per answer id. */\n followUps?: Record<string, CancelFollowUp>;\n /** 0.15.0: the rules per answer id, checked in order before its offer. */\n rules?: Record<string, CancelRule[]>;\n /** 0.15.0: what one answer offers after its first offer was declined. */\n second?: 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\n/** \"question\" (0.18.0): one question of a Questions item, a slide of its window. */\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\" | \"question\";\n\n/**\n * 0.18.0: what a checklist task opens. `page`: a path or address on the web, a deep link (`myapp://…`) or a screen name\n * in an app, handed to the app's `onNavigate` when it passes one; `tour` / `modal`: another item of the config, after\n * which the checklist comes back; `code`: the app's `onTask(taskId, item)`.\n */\nexport type TaskOpens = { kind: \"page\"; target: string } | { kind: \"tour\"; id: string } | { kind: \"modal\"; id: string } | { kind: \"code\" };\n\n/**\n * 0.18.0: a small picture beside a checklist task or above a modal's or the questions' heading: one of the SDK's own\n * line icons (`FLOW_ICON_NAMES`, icons.ts), an emoji, or a picture (http(s)).\n */\nexport type FlowIcon = { kind: \"builtin\"; name: string } | { kind: \"emoji\"; value: string } | { kind: \"image\"; url: string };\n\n/** 0.18.0: what plays when someone finishes a checklist, a tour or the questions. */\nexport type FinishAnimation = \"none\" | \"confetti\" | \"fireworks\" | \"stars\";\n\n/** 0.18.0: one question of a Questions item: one choice of 2 to 6 options, or a short text. */\nexport interface OnboardingQuestion {\n /** The answer's name on the contact (`onboarding.<key>`) and in \"People who answered …\". */\n key: string;\n type: \"choice\" | \"text\";\n /** Choice: the options, in order; `id` is what is stored, `label` what people read. */\n options?: { id: string; label: string }[];\n /** Text: the field's hint. */\n placeholder?: string;\n}\n\n/** 0.17.0: where a tour bubble sits next to its element; \"auto\" (and no value) puts it below, else above, as before. */\nexport type TourPlacement = \"auto\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n\n/**\n * 0.17.0: a picture or a video above a tour step's or a modal's text. A video is a YouTube, Vimeo or Loom link (shown\n * through their privacy-friendly players, see `videoEmbed`) or a video file (mp4, webm).\n */\nexport interface FlowMedia {\n kind: \"image\" | \"video\";\n url: string;\n alt?: string;\n}\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 /** 0.17.0, tour steps: which side of the element the bubble takes (flips when there is no room). */\n placement?: TourPlacement;\n /** 0.17.0, tour steps and modals: a picture or a video above the text. */\n media?: FlowMedia;\n /** 0.17.0, modals: where the button goes (http(s) or a path of the app). */\n url?: string;\n /** 0.17.0, checklist items: the id of a tour (another flow) the item starts; finishing the tour ticks the item. */\n startsTour?: string;\n /** 0.18.0, checklist items: what the task opens (read before `startsTour`, which MRRocket still sends for a tour). */\n opens?: TaskOpens;\n /** 0.18.0, checklist items: the task's icon. */\n icon?: FlowIcon;\n /** 0.18.0, question steps: the question (the step's `title` is what people read). */\n question?: OnboardingQuestion;\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 /** A checklist's heading; for tours and modals the name MRRocket knows them by. */\n name: string;\n /**\n * When it starts: an event's words (\"Signed up\", \"First export\"), \"First launch\" / \"First visit\", since 0.17.0 a page\n * of the app (\"/settings\", \"/projects/*\"), or \"From a checklist\" (only a checklist task starts it).\n */\n trigger: string;\n /**\n * 0.17.0: \"signed_in\" starts it on its own only for someone the app identified. 0.18.0: \"answered\" only for someone\n * who gave `answered.option` to the question `answered.question` (its key).\n */\n audience?: \"signed_in\" | \"answered\";\n /** 0.18.0: with `audience: \"answered\"`, the question's key and the option's id (or the typed text). */\n answered?: { question: string; option: string };\n /** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */\n steps: OnboardingStep[];\n /** 0.18.0: the icon above a modal's or the questions' heading. */\n icon?: FlowIcon;\n /** 0.18.0: what plays when the person finishes it (a checklist, a tour, the questions). */\n finish?: FinishAnimation;\n /**\n * 0.18.0: \"code\": the app draws it itself (`useOnboarding(id)`, `mrrocket.onboarding.get(id)`); the SDK draws\n * nothing for it, never starts it, and still records what the app reports. Such an item's `trigger` is\n * \"From your code\" (older versions never start it).\n */\n shownBy?: \"code\";\n /**\n * 0.18.0: the item's real moment (read instead of `trigger`, see `momentOf`) when `trigger` is one older versions\n * never start: \"From your code\", or `NEEDS_NEWER` for questions and items that follow another or ask for an answer.\n */\n when?: string;\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 /** 0.18.0: the person's answers to onboarding questions, by the question's key (an option's id or the text). */\n answers?: Record<string, string>;\n /**\n * 0.16.0: a live review request may ask this person now. The React Native client's `requestReview()` opens the\n * store's own rating dialog (expo-store-review) and reports `$review_prompt`; websites have no store dialog.\n */\n review?: { campaign: string; store: 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 /** 0.15.0: the answer to the follow-up question. */\n answer?: 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 /** 0.15.0: the customer's plan (its id or name in your billing), for offers that depend on it. */\n plan?: string;\n /** 0.15.0: since when they pay (a date, ISO string or ms), for offers that depend on how long. */\n customerSince?: Date | string | number;\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\" | \"followup\" | \"offer\" | \"confirm\";\n flow: CancelFlowConfig;\n /** The answer picked on the survey. */\n reason?: string;\n /** 0.15.0: the follow-up question on its screen, and its answer so far. */\n followUp?: CancelFollowUp;\n answer?: string;\n offer?: CancelOffer;\n /** 0.15.0: 2 for the offer after a declined one. */\n round?: 1 | 2;\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 /** `answer` (0.18.0): a question's answer so far (an option's id or the typed text); `back`: an earlier question to go back to. */\n | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean; answer?: string; back?: boolean }\n /**\n * `tour`: the tour the item starts (0.17.0), when the config has it. `opens` (0.18.0): what tapping the task opens\n * (a tour or modal only when the config has it); `target` the item it opens.\n */\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean; tour?: OnboardingFlow; opens?: TaskOpens; target?: OnboardingFlow }[] }\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 /**\n * 0.18.0: opens what a checklist task's \"page or screen\" names (a path, an address, a deep link, a screen name).\n * The web and React Native clients pass the app's `onNavigate`, else their own default.\n */\n navigate?: (target: string) => void;\n /** 0.18.0: a checklist task that runs the app's own code (`onTask(taskId, item)`). */\n task?: (taskId: string, item: OnboardingFlow) => void;\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 /** `answer(text)`: the follow-up's choice or free text (0.15.0); `next()` moves on from the survey and the follow-up. */\n cancel: {\n pick(reason: string): void;\n answer(text: string): void;\n next(): void;\n accept(comment?: string): void;\n decline(): void;\n confirm(comment?: string): void;\n close(): void;\n };\n /**\n * `startTour(stepId)` (0.17.0): the tour a checklist item starts; the checklist comes back when it ends.\n * 0.18.0: `open(stepId)` does what the task opens (a page, a tour, a modal, the app's code); `answer(value)` picks an\n * option or types the text of the question on screen, `back()` returns to the question before. `item(id)` and the\n * calls after it are for an item the app draws itself (`shownBy: \"code\"`).\n */\n onboarding: {\n next(): void;\n check(stepId: string): void;\n dismiss(): void;\n startTour(stepId: string): boolean;\n open(stepId: string): boolean;\n answer(value: string): void;\n back(): void;\n item(id: string): OnboardingItemState | null;\n seen(id: string): void;\n complete(id: string, stepId: string): void;\n dismissItem(id: string): void;\n answerItem(id: string, question: string, value: string): void;\n };\n message: { click(): void; dismiss(): void };\n /** 0.18.0: the animation to play now that someone finished an item (a new `key` each time), or null. */\n finale(): { kind: Exclude<FinishAnimation, \"none\">; key: string } | null;\n /** 0.18.0: the product's brand color from MRRocket, for the dialogs when the app passes no accent of its own. */\n accent(): string | undefined;\n /** 0.18.0: the person's answers to onboarding questions, by key. */\n answers(): Record<string, string>;\n}\n\n/** 0.18.0: an item the app draws itself (`shownBy: \"code\"`), with the person's progress. */\nexport interface OnboardingItemState {\n item: OnboardingFlow;\n /** Its steps (a tour's steps, a checklist's tasks, the questions), each with whether the person did it. */\n steps: (OnboardingStep & { done: boolean; answer?: string })[];\n /** Every step is done. */\n done: boolean;\n /** The person closed it. */\n dismissed: boolean;\n /** Its moment has come for this person (the trigger MRRocket set, and who it is for); your code may ignore it. */\n eligible: boolean;\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/** 0.17.0: the trigger of a tour only a checklist task starts. */\nexport const FROM_CHECKLIST = \"From a checklist\";\n\n/** 0.17.0: a trigger that is a page of the app (\"/settings\", \"/projects/*\"): the flow starts when the person opens it. */\nexport const isPageTrigger = (trigger: string) => trigger.trim().startsWith(\"/\");\n\n/** 0.18.0: the trigger of an item the app draws itself (`shownBy: \"code\"`); older versions never start it. */\nexport const FROM_CODE = \"From your code\";\n\n/**\n * 0.18.0: the trigger MRRocket sends for an item older versions could not show right (questions, \"After <item> ends\",\n * \"People who answered …\"), so they never start it; its real moment is in `when`.\n */\nexport const NEEDS_NEWER = \"Needs tracking code 0.18.0\";\n\n/** An item's moment: `when` (0.18.0) where MRRocket sent one, else its trigger. */\nexport const momentOf = (f: Pick<OnboardingFlow, \"trigger\" | \"when\">) => f.when ?? f.trigger;\n\n/** A \"From a checklist\" tour (and an item the app draws, 0.18.0) never starts on its own. */\nconst manual = (trigger: string) => eventSlug(trigger) === \"from_a_checklist\" || eventSlug(trigger) === \"from_your_code\" || eventSlug(trigger) === eventSlug(NEEDS_NEWER);\n\n/** 0.18.0: the trigger \"after:<item id>\": the item starts once that item ended (finished or closed). */\nexport const AFTER_PREFIX = \"after:\";\n\n/** The item an \"after:<id>\" trigger follows, or null. */\nexport const afterOf = (trigger: string | undefined) => {\n const t = (trigger ?? \"\").trim();\n return t.toLowerCase().startsWith(AFTER_PREFIX) ? t.slice(AFTER_PREFIX.length).trim() || null : null;\n};\n\n/** 0.18.0: what a task opens; a 0.17.0 `startsTour` reads as opening that tour. */\nexport const opensOf = (step: Pick<OnboardingStep, \"opens\" | \"startsTour\">): TaskOpens | undefined =>\n step.opens ?? (step.startsTour ? { kind: \"tour\", id: step.startsTour } : undefined);\n\n/** 0.18.0: a usable answer to a question: one of its options' ids, or a text of 1 to 500 characters. */\nexport const answerOk = (q: OnboardingQuestion | undefined, value: string | undefined) => {\n if (!q || value == null) return false;\n if (q.type === \"choice\") return (q.options ?? []).some((o) => o.id === value);\n return value.trim().length > 0 && value.length <= 500;\n};\n\n/** The option's words for an answer (a text answer is its own words). */\nexport const answerLabel = (q: OnboardingQuestion | undefined, value: string) =>\n q?.type === \"choice\" ? (q.options?.find((o) => o.id === value)?.label ?? value) : value.trim();\n\n/**\n * 0.17.0: how a video link plays. YouTube, Vimeo and Loom through their players without tracking cookies\n * (youtube-nocookie.com, Vimeo's `dnt=1`), a file (mp4, webm, mov, or an upload in MRRocket) in a plain video element;\n * anything else is not shown. Regular expressions only, so React Native can use it too.\n */\nexport const videoEmbed = (url: string | undefined): { kind: \"iframe\" | \"file\"; src: string } | null => {\n const u = (url ?? \"\").trim();\n if (!/^https?:\\/\\//i.test(u)) return null;\n let m = u.match(/^https?:\\/\\/(?:www\\.|m\\.)?(?:youtube\\.com\\/(?:watch\\?(?:.*&)?v=|embed\\/|shorts\\/|live\\/)|youtu\\.be\\/|youtube-nocookie\\.com\\/embed\\/)([\\w-]{6,20})/i);\n if (m) return { kind: \"iframe\", src: `https://www.youtube-nocookie.com/embed/${m[1]}?rel=0` };\n m = u.match(/^https?:\\/\\/(?:www\\.|player\\.)?vimeo\\.com\\/(?:video\\/)?(\\d{4,12})/i);\n if (m) return { kind: \"iframe\", src: `https://player.vimeo.com/video/${m[1]}?dnt=1` };\n m = u.match(/^https?:\\/\\/(?:www\\.)?loom\\.com\\/(?:share|embed)\\/([\\w-]{8,64})/i);\n if (m) return { kind: \"iframe\", src: `https://www.loom.com/embed/${m[1]}` };\n if (/\\.(mp4|webm|mov|m4v)(\\?|#|$)/i.test(u) || /\\/media\\/uploads\\//.test(u)) return { kind: \"file\", src: u };\n return null;\n};\n\n/** 0.17.0: a step's picture or video when the dialogs may load it (http(s), a video they can play), else undefined. */\nexport const mediaOf = (step: Pick<OnboardingStep, \"media\">): FlowMedia | undefined => {\n const m = step.media;\n if (!m || (m.kind !== \"image\" && m.kind !== \"video\") || !/^https?:\\/\\//i.test(m.url ?? \"\")) return undefined;\n return m.kind === \"video\" && !videoEmbed(m.url) ? undefined : m;\n};\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\n/** Whole months since a date the app passed (NaN without one, which no tenure condition holds for). */\nexport const monthsSince = (since: CancelFlowOptions[\"customerSince\"], now = Date.now()) =>\n since == null || since === \"\" ? NaN : Math.floor((now - new Date(since).getTime()) / 2_630_016_000);\n\nconst low = (x?: string) => x?.trim().toLowerCase();\n\n/** Whether a rule holds for this customer; a condition about something the app did not pass does not hold. */\nexport const ruleMatches = ({ when: w = {} }: CancelRule, c: { answer?: string; plan?: string; months: number }) =>\n (w.answer == null || low(w.answer) === low(c.answer)) &&\n (w.plan == null || [w.plan].flat().some((x) => low(x) === low(c.plan))) &&\n !(c.months >= w.tenureUnder!) &&\n !(c.months < w.tenureOver!) &&\n (w.tenureUnder == null || c.months >= 0) &&\n (w.tenureOver == null || c.months >= 0);\n\ninterface CancelRun {\n flow: CancelFlowConfig;\n options: CancelFlowOptions;\n plain: boolean;\n screen: \"survey\" | \"followup\" | \"offer\" | \"confirm\";\n reason?: string;\n answer?: string;\n /** The offer on the offer screen, which rule picked it, and which round it is. */\n offer?: CancelOffer;\n rule?: number;\n round: 1 | 2;\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 /** 0.17.0: the checklist (and its item) a running tour was started from; it comes back when the tour ends. */\n let returnTo: { flow: string; step: string } | null = null;\n /** 0.18.0: the person's answers by question key, the answers typed so far on screen (by step), and the finale. */\n const answers = new Map<string, string>();\n const drafts = new Map<string, string>();\n const celebrated = new Set<string>();\n let finaleNow: { kind: Exclude<FinishAnimation, \"none\">; key: string } | null = null;\n\n const flows = () => config?.onboarding ?? [];\n /** The items the SDK draws (0.18.0: not those the app draws itself). */\n const drawn = () => flows().filter((f) => f.shownBy !== \"code\");\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 const answersKeyOf = (pid: string | undefined) => `${PROGRESS_KEY}:answers:${pid ?? \"visitor\"}`;\n\n /** 0.18.0: an item the person just finished (not closed) plays its finish animation, once per page. */\n const celebrate = (f: OnboardingFlow) => {\n if (!f.finish || f.finish === \"none\" || f.shownBy === \"code\" || celebrated.has(f.id)) return;\n const p = progress.get(f.id);\n if (!p || p.dismissed || walkLine(f, nodesOf(f), p, false).at !== \"end\") return;\n celebrated.add(f.id);\n finaleNow = { kind: f.finish, key: `${f.id}:${now()}` };\n };\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 (answers.size) store.set(answersKeyOf(env.personId()), JSON.stringify(Object.fromEntries(answers)));\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 {\n type: \"checklist\",\n flow,\n items: items.map((s) => {\n // 0.18.0: what the task opens; a tour or modal only when the config has it and the SDK draws it.\n const o = opensOf(s);\n const t = o && (o.kind === \"tour\" || o.kind === \"modal\") && o.id !== flow.id ? flowById(o.id) : undefined;\n const target = t && t.shownBy !== \"code\" && nodesOf(t).length ? t : undefined;\n const opens = o && (o.kind === \"page\" ? !!o.target.trim() : o.kind === \"code\" || !!target) ? o : undefined;\n return {\n step: s,\n done: p.done.has(s.id),\n ...(target && o?.kind === \"tour\" ? { tour: target } : {}),\n ...(opens ? { opens } : {}),\n ...(target ? { target } : {}),\n };\n }),\n };\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 {\n type: \"step\",\n flow,\n step,\n index: w.before,\n total: w.before + 1 + ahead,\n last: !ahead && fork < 0,\n // 0.18.0: a question's answer so far, and whether there is one before it to go back to.\n ...(step.kind === \"question\" ? { answer: drafts.get(step.id) ?? (step.question ? answers.get(step.question.key) : undefined), back: w.before > 0 } : {}),\n };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const c = cancel;\n const followUp = c.flow.followUps?.[c.reason!];\n // The dots: the survey, a follow-up, one or two offers, the confirmation.\n const f = followUp ? 1 : 0;\n const steps = c.plain ? 1 : 3 + f + (c.flow.second?.[c.reason!] ? 1 : 0);\n return {\n type: \"cancel\",\n screen: c.screen,\n flow: c.flow,\n reason: c.reason,\n ...(c.screen === \"followup\" && followUp ? { followUp, answer: c.answer } : {}),\n offer: c.screen === \"offer\" ? c.offer : undefined,\n ...(c.screen === \"offer\" ? { round: c.round } : {}),\n price: c.options.price,\n busy: c.busy,\n error: c.error,\n step: c.screen === \"survey\" ? 1 : c.screen === \"followup\" ? 2 : c.screen === \"offer\" ? 1 + f + c.round : steps,\n steps,\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) {\n const back = returnTo;\n const ended = active;\n returnTo = null;\n active = null;\n const list = back ? flowById(back.flow) : undefined;\n if (back && list) {\n // The tour a checklist item started is over: the checklist comes back, and a finished tour ticks an item\n // that has no event of its own (a closed one does not).\n const item = stepsIn(nodesOf(list)).find((s) => s.id === back.step);\n const p = prog(list.id);\n if (item && !item.event && !progress.get(ended)?.dismissed && !p.done.has(item.id)) {\n markDone(p, item.id);\n record({ flow: list.id, step: item.id, kind: \"checklist\", action: \"completed\" });\n celebrate(list);\n }\n active = list.id;\n const again = onboardingView();\n if (again) return again;\n if (!holding) active = null;\n } else if (known) {\n // 0.17.0: the next flow whose moment has come (another \"First launch\", this page's, or one of the same\n // trigger as the one that ended) follows right away.\n const was = flowById(ended);\n const after = was ? momentOf(was) : undefined;\n Promise.resolve().then(() => autoStart(after));\n }\n }\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 /**\n * 0.17.0: a flow for signed-in people starts on its own only for someone the app identified; 0.18.0: one for the\n * people who gave an answer only for them.\n */\n const allowed = (f: OnboardingFlow) =>\n f.audience === \"answered\" ? !!f.answered && answers.get(f.answered.question) === f.answered.option : f.audience !== \"signed_in\" || !!env.personId();\n\n /** 0.18.0: an \"after:<id>\" item's moment: that item ended (finished or closed), or it is not live (then like the first launch). */\n const predecessorEnded = (id: string) => {\n const g = flowById(id);\n return !g || finished(g);\n };\n\n /** Whether the item's own moment has come now (its trigger), apart from who it is for. */\n const due = (f: OnboardingFlow, trigger = momentOf(f)) => {\n const path = env.path?.();\n const pred = afterOf(trigger);\n if (pred) return predecessorEnded(pred);\n if (manual(trigger)) return false;\n if (isPageTrigger(trigger)) return path !== undefined && pageMatches(trigger, path);\n if (startsOnLoad(trigger)) return true;\n for (const e of seenEvents) if (matchesTrigger(trigger, e)) return true;\n return false;\n };\n\n /**\n * Flows whose trigger is \"the first launch\" (or, 0.17.0, the page the person is on) start once their progress is\n * known (never twice for a done flow). `after`: the trigger of a flow that just ended, whose next unfinished flow\n * follows it (onboarding items made from one older flow share its trigger).\n */\n const autoStart = (after?: string) => {\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 path = env.path?.();\n const same = after && !manual(after) ? eventSlug(after) : \"\";\n const next = drawn().find(\n (f) =>\n (afterOf(momentOf(f))\n ? predecessorEnded(afterOf(momentOf(f))!)\n : isPageTrigger(momentOf(f))\n ? path !== undefined && pageMatches(momentOf(f), path)\n : startsOnLoad(momentOf(f)) || (!!same && eventSlug(momentOf(f)) === same)) &&\n allowed(f) &&\n nodesOf(f).length &&\n !finished(f),\n );\n if (next) start(next);\n };\n\n /**\n * 0.17.0/0.18.0: a checklist task opens another item (a tour or a modal): from its first step, also when the person\n * saw or closed it before; the checklist comes back when it ends.\n */\n const openItem = (list: OnboardingFlow, stepId: string, target: OnboardingFlow) => {\n const p = prog(target.id);\n p.done.clear();\n p.at.clear();\n p.dismissed = false;\n returnTo = { flow: list.id, step: stepId };\n active = target.id;\n env.track(ONBOARDING_EVENT, { flow: target.id, action: \"started\", from: list.id });\n save();\n emit();\n };\n\n /** 0.18.0: one question answered: kept for the person (`answers`), done, and recorded with its key and words. */\n const answerStep = (flow: OnboardingFlow, step: OnboardingStep, raw: string) => {\n const q = step.question!;\n const value = q.type === \"text\" ? raw.trim().slice(0, 500) : raw;\n answers.set(q.key, value);\n drafts.delete(step.id);\n markDone(prog(flow.id), step.id);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: step.id, kind: \"question\", action: \"completed\", question: q.key, answer: value, label: answerLabel(q, value) });\n celebrate(flow);\n save();\n };\n\n /** 0.18.0: something changed on an item the app draws: saved, and the next item may follow it. */\n const ended = (f: OnboardingFlow) => {\n save();\n if (finished(f)) Promise.resolve().then(() => autoStart());\n emit();\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 answers.clear();\n drafts.clear();\n handled.clear();\n active = null;\n returnTo = 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 const said = await store.get(answersKeyOf(pid));\n if (said) for (const [k, v] of Object.entries(JSON.parse(said) as Record<string, unknown>)) if (typeof v === \"string\") answers.set(k, v);\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 // 0.18.0: answers given on another device; an answer given here stays.\n for (const [k, v] of Object.entries(state.answers ?? {})) if (typeof v === \"string\" && !answers.has(k)) answers.set(k, v);\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 /** Which offer of the answer was on screen, for MRRocket to know what was saved: a rule's or the second. */\n const offerAt = (c: CancelRun) => (c.round > 1 ? { round: 2 } : c.rule! >= 0 ? { rule: c.rule } : {});\n\n /** Into the offer screen with the answer's first offer (the first rule that holds, else its own), or the confirmation. */\n const toOffer = (c: CancelRun) => {\n const who = { answer: c.answer, plan: c.options.plan, months: monthsSince(c.options.customerSince, env.now?.()) };\n const rules = c.flow.rules?.[c.reason!] ?? [];\n c.rule = rules.findIndex((r) => ruleMatches(r, who));\n c.offer = c.rule < 0 ? c.flow.offers[c.reason!] : (rules[c.rule].offer ?? undefined);\n c.round = 1;\n c.screen = c.offer ? \"offer\" : \"confirm\";\n };\n\n const result = (c: CancelRun, outcome: CancelFlowResult[\"outcome\"], comment?: string): CancelFlowResult => {\n const offer = c.screen === \"offer\" ? c.offer : 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 ...(c.answer ? { answer: c.answer } : {}),\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.answer ? { answer: r.answer } : {}),\n ...(r.offer ? { offer: r.offer.kind, ...offerAt(c) } : {}),\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\", round: 1, 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 // 0.17.0: a page view may be the moment of a flow with a page trigger.\n if (name === \"$pageview\") autoStart();\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 // The checklist on screen, and (0.18.0) those the app draws itself, tick their tasks by their event.\n const lists = [...(flow ? [flow] : []), ...flows().filter((f) => f.shownBy === \"code\" && f.id !== flow?.id)];\n for (const l of lists) {\n const p = prog(l.id);\n let here = false;\n for (const s of stepsIn(nodesOf(l)))\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n markDone(p, s.id);\n here = true;\n env.track(ONBOARDING_EVENT, { flow: l.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n if (here) {\n ticked = true;\n celebrate(l);\n }\n }\n if (ticked || (fresh && (flow || lists.length))) {\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 = drawn().find((f) => nodesOf(f).length && !manual(momentOf(f)) && matchesTrigger(momentOf(f), name) && allowed(f) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : drawn().find((x) => nodesOf(x).length && !manual(momentOf(x)) && !afterOf(momentOf(x)) && !finished(x));\n // An item the app draws itself (0.18.0) is never started here.\n if (!f || !nodesOf(f).length || f.shownBy === \"code\") 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.screen !== \"survey\" || !cancel.flow.reasons.some((r) => r.id === reason)) return;\n if (cancel.reason !== reason) cancel.answer = undefined;\n cancel.reason = reason;\n cancel.error = undefined;\n emit();\n },\n answer: (text) => {\n const c = cancel;\n if (!c || c.busy || c.screen !== \"followup\") return;\n const t = text.slice(0, 500);\n c.answer = t.trim() ? t : undefined;\n emit();\n },\n next: () => {\n const c = cancel;\n if (!c || !c.reason) return;\n // The follow-up's answer rides along on the finished event.\n if (c.screen === \"survey\") {\n env.track(CANCEL_EVENT, { action: \"answered\", run: c.run, version: c.flow.version, reason: c.reason });\n if (c.flow.followUps?.[c.reason]) c.screen = \"followup\";\n else toOffer(c);\n } else if (c.screen === \"followup\") {\n c.answer = c.answer?.trim();\n toOffer(c);\n } else return;\n emit();\n },\n accept: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || !c.reason) return;\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: c.offer?.kind,\n ...offerAt(c),\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.offer?.kind,\n ...offerAt(c),\n outcome: \"declined\",\n });\n // A second offer once, then the confirmation.\n const second = c.round === 1 && c.reason ? c.flow.second?.[c.reason] : undefined;\n if (second) {\n c.offer = second;\n c.rule = undefined;\n c.round = 2;\n } else 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 if (v.step.kind === \"question\") {\n // 0.18.0: only with an answer; it is kept for the person and goes to MRRocket with the step.\n const q = v.step.question;\n const a = drafts.get(v.step.id) ?? (q ? answers.get(q.key) : undefined);\n if (!q || !answerOk(q, a)) return;\n answerStep(v.flow, v.step, a!);\n emit();\n return;\n }\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 celebrate(v.flow);\n save();\n emit();\n // 0.17.0: a modal's button may lead somewhere.\n const url = v.step.kind === \"modal\" ? safeUrl(v.step.url) : undefined;\n if (url) env.openUrl?.(url);\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 celebrate(v.flow);\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 // A tour started from a checklist was closed: the checklist comes back, its item stays open.\n active = returnTo && returnTo.flow !== v.flow.id && flowById(returnTo.flow) ? returnTo.flow : null;\n returnTo = null;\n save();\n emit();\n },\n startTour: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return false;\n const target = v.items.find((i) => i.step.id === stepId)?.target;\n if (!target) return false;\n openItem(v.flow, stepId, target);\n return true;\n },\n open: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return false;\n const it = v.items.find((i) => i.step.id === stepId);\n const o = it?.opens;\n if (!it || !o) return false;\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"opened\", opens: o.kind });\n if ((o.kind === \"tour\" || o.kind === \"modal\") && it.target) {\n openItem(v.flow, stepId, it.target);\n return true;\n }\n // A page or the app's code: a task without an event of its own is done once it is opened (saved before a\n // page change can unload this one).\n if (!it.done && !it.step.event) {\n markDone(prog(v.flow.id), stepId);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"completed\" });\n celebrate(v.flow);\n }\n save();\n emit();\n if (o.kind === \"page\") env.navigate?.(o.target.trim());\n else env.task?.(stepId, v.flow);\n return true;\n },\n answer: (value) => {\n const v = onboardingView();\n if (v?.type !== \"step\" || v.step.kind !== \"question\") return;\n drafts.set(v.step.id, String(value).slice(0, 500));\n emit();\n },\n back: () => {\n const v = onboardingView();\n if (v?.type !== \"step\" || v.step.kind !== \"question\" || !v.back) return;\n // The question before on the person's way through the item is open again, with its answer filled in.\n const line = stepsIn(nodesOf(v.flow));\n const at = line.findIndex((s) => s.id === v.step.id);\n const p = prog(v.flow.id);\n for (let i = at - 1; i >= 0; i--)\n if (p.done.has(line[i].id)) {\n p.done.delete(line[i].id);\n p.at.delete(line[i].id);\n break;\n }\n save();\n emit();\n },\n item: (id) => {\n const f = flowById(id);\n if (!f) return null;\n const p = progress.get(f.id);\n const steps = stepsIn(nodesOf(f)).map((s) => {\n const a = s.question ? answers.get(s.question.key) : undefined;\n return { ...s, done: !!p?.done.has(s.id), ...(a !== undefined ? { answer: a } : {}) };\n });\n const done = steps.length > 0 && steps.every((s) => s.done);\n const dismissed = !!p?.dismissed;\n return { item: f, steps, done, dismissed, eligible: !done && !dismissed && allowed(f) && due(f) };\n },\n seen: (id) => {\n const f = flowById(id);\n if (!f || f.shownBy !== \"code\" || !known) return;\n if (!shown.has(`f:${f.id}`)) {\n shown.add(`f:${f.id}`);\n env.track(ONBOARDING_EVENT, { flow: f.id, action: \"started\" });\n }\n const p = progress.get(f.id);\n for (const s of stepsIn(nodesOf(f)))\n if (!p?.done.has(s.id) && !shown.has(`s:${s.id}`)) {\n shown.add(`s:${s.id}`);\n env.track(ONBOARDING_EVENT, { flow: f.id, step: s.id, kind: s.kind, action: \"shown\" });\n // A tour or the questions show one step at a time: only the first open one counts as seen.\n if (s.kind !== \"checklist\") break;\n }\n },\n complete: (id, stepId) => {\n const f = flowById(id);\n const s = f && stepsIn(nodesOf(f)).find((x) => x.id === stepId);\n if (!f || !s || s.kind === \"question\") return;\n const p = prog(f.id);\n if (p.done.has(s.id)) return;\n markDone(p, s.id);\n env.track(ONBOARDING_EVENT, { flow: f.id, step: s.id, kind: s.kind, action: \"completed\" });\n ended(f);\n },\n dismissItem: (id) => {\n const f = flowById(id);\n if (!f) return;\n const p = prog(f.id);\n if (p.dismissed) return;\n p.dismissed = true;\n env.track(ONBOARDING_EVENT, { flow: f.id, action: \"dismissed\" });\n if (active === f.id) active = null;\n ended(f);\n },\n answerItem: (id, question, value) => {\n const f = flowById(id);\n const s = f && stepsIn(nodesOf(f)).find((x) => x.kind === \"question\" && (x.id === question || x.question?.key === question));\n if (!f || !s?.question || !answerOk(s.question, value)) return;\n answerStep(f, s, value);\n ended(f);\n },\n },\n finale: () => finaleNow,\n accent: () => config?.onboardingAccent,\n answers: () => Object.fromEntries(answers),\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","/**\n * Paywalls with several pages (SDK 0.14.0): what MRRocket's config serves under `paywalls` (one per placement, built\n * in MRRocket › Conversion › Paywalls) and a small controller that walks the person through its pages, page after page,\n * until the last one hands the chosen plan to the app. No DOM and no React: the web renderer (`mountPaywall` in\n * flows-ui.ts, loaded only when a paywall opens) and the React Native one (native/flows-view.ts) draw `view()` and\n * call the actions.\n *\n * MRRocket never takes a payment. The last page's button calls the app's `onPurchase(plan)`, which buys through the\n * app's own store code (StoreKit or Play through RevenueCat or Adapty, or Stripe Checkout on the web); only when it\n * resolves is the purchase recorded. It throwing keeps the paywall open with an error, resolving `false` (the person\n * closed the store sheet) keeps it open without one.\n *\n * A running test on the paywall (`experiment`) gives each person their variant's pages, by the same stable hash as\n * every other test (`assign`), and records `$exposure` when the paywall opens. What it records, as normal events under\n * the SDK's analytics consent:\n * - `$paywall` `{paywall, placement, variant, page, index, action: \"page\"}` the first time each page shows in a run,\n * so MRRocket shows how many reach page 2 and 3;\n * - `{action: \"purchased\", plan}` after `onPurchase` went through (a test's purchase goal counts it), and\n * `{action: \"closed\", index}` when the person closed it.\n */\nimport { type CockpitConfig, type VariantId, assign } from \"./core\";\n\nexport const PAYWALL_EVENT = \"$paywall\";\n\n/** One page of a paywall. Plans pages list the plans and buy; the others say why and go on. */\nexport interface PaywallPage {\n id: string;\n /** \"benefits\": a list of what the person gets; \"proof\": quotes of happy customers; \"plans\": the plans and the buy button. */\n kind: \"benefits\" | \"proof\" | \"plans\";\n title: string;\n body?: string;\n /** Benefits: one line each. */\n items?: string[];\n /** Proof: what customers said, and who. */\n quotes?: { text: string; by?: string }[];\n /** The button: \"Continue\" on the way, the buy button on the plans page (\"Start free trial\"). */\n button?: string;\n}\n\n/** A plan the paywall offers. `id` is what the app buys: the store product id or the Stripe price, as set in MRRocket. */\nexport interface PaywallPlan {\n id: string;\n name: string;\n /** As shown (\"€59.99 / year\"). The app's own store prices win when it passes `plans`. */\n price: string;\n /** A line under it (\"€5 a month\", \"7 days free\"). */\n note?: string;\n}\n\n/** A published paywall as the config serves it. */\nexport interface PaywallConfig {\n id: string;\n /** The placement's key (`onboarding_end`), what the app opens: `paywall.open(\"onboarding_end\")`. */\n placement: string;\n /** The running test on it, a key of `experiments`; each of its variants has pages under `variants`. */\n experiment?: string;\n /** Control (the live paywall) first. */\n variants: { id: VariantId; pages: PaywallPage[] }[];\n plans: PaywallPlan[];\n /** The plan picked before the person picks one. */\n highlight?: string;\n}\n\nexport interface PaywallResult {\n /**\n * \"purchased\": `onPurchase` went through; \"chosen\": the person picked a plan and there is no `onPurchase`, so the app\n * buys it now (the store's purchase still counts for a test through RevenueCat or Adapty); \"closed\": the person\n * closed it (or there was no paywall).\n */\n outcome: \"purchased\" | \"chosen\" | \"closed\";\n plan?: PaywallPlan;\n paywall?: string;\n variant?: VariantId;\n /** The page the person was on, from 0. */\n index: number;\n}\n\nexport interface PaywallOptions {\n /**\n * Buy the plan in your code (RevenueCat `purchasePackage`, Adapty `makePurchase`, Stripe Checkout). Throwing keeps\n * the paywall open with an error; `false` keeps it open without one (the person cancelled the store sheet).\n */\n onPurchase?: (plan: PaywallPlan) => unknown;\n /** Your store's plans with their local prices, by the same ids; they replace what MRRocket has for them. */\n plans?: PaywallPlan[];\n onClose?: (result: PaywallResult) => void;\n}\n\nexport interface PaywallView {\n paywall: PaywallConfig;\n variant: VariantId;\n page: PaywallPage;\n index: number;\n total: number;\n last: boolean;\n plans: PaywallPlan[];\n /** The picked plan's id. */\n plan?: string;\n busy: boolean;\n error?: string;\n}\n\nexport interface PaywallEnv {\n config: () => CockpitConfig | null;\n distinctId: () => string;\n /** Records an event under the SDK's consent. */\n track: (event: string, props?: Record<string, unknown>) => void;\n}\n\nexport interface PaywallHost {\n /** Opens the paywall of a placement; resolves when it is bought or closed (at once with \"closed\" when there is none). */\n open(placement: string, options?: PaywallOptions): Promise<PaywallResult>;\n view(): PaywallView | null;\n subscribe(listener: () => void): () => void;\n next(): void;\n back(): void;\n pick(planId: string): void;\n close(): void;\n}\n\n/** The pages of a person's variant: the test's when it runs (or shipped), else control's. */\nexport const paywallPages = (config: CockpitConfig | null, w: PaywallConfig, distinctId: string) => {\n const e = w.experiment ? config?.experiments.find((x) => x.key === w.experiment) : undefined;\n const id = e ? assign(e, distinctId) : w.variants[0]?.id;\n const v = w.variants.find((x) => x.id === id) ?? w.variants[0];\n return v ? { variant: v.id, pages: v.pages, test: e?.status === \"running\" && !e.winner ? e.key : undefined } : null;\n};\n\nexport const createPaywallHost = (env: PaywallEnv): PaywallHost => {\n let run: {\n w: PaywallConfig;\n variant: VariantId;\n pages: PaywallPage[];\n plans: PaywallPlan[];\n index: number;\n plan?: string;\n busy: boolean;\n error?: string;\n seen: Set<number>;\n options: PaywallOptions;\n resolve: (r: PaywallResult) => void;\n promise: Promise<PaywallResult>;\n } | null = null;\n const listeners = new Set<() => void>();\n const emit = () => {\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n const base = () => (run ? { paywall: run.w.id, placement: run.w.placement, variant: run.variant } : {});\n const show = () => {\n if (run && !run.seen.has(run.index)) {\n run.seen.add(run.index);\n env.track(PAYWALL_EVENT, { ...base(), page: run.pages[run.index].id, index: run.index, action: \"page\" });\n }\n emit();\n };\n const end = (r: PaywallResult) => {\n const c = run;\n if (!c) return;\n run = null;\n if (r.outcome === \"closed\") c.options.onClose?.(r);\n c.resolve(r);\n emit();\n };\n const result = (outcome: PaywallResult[\"outcome\"]): PaywallResult => ({\n outcome,\n index: run?.index ?? 0,\n ...(run ? { paywall: run.w.id, variant: run.variant } : {}),\n ...(outcome !== \"closed\" && run ? { plan: run.plans.find((p) => p.id === run!.plan) } : {}),\n });\n\n const buy = () => {\n const c = run;\n const plan = c?.plans.find((p) => p.id === c.plan);\n if (!c || !plan || c.busy) return;\n if (!c.options.onPurchase) return end(result(\"chosen\"));\n c.busy = true;\n c.error = undefined;\n emit();\n Promise.resolve()\n .then(() => c.options.onPurchase?.(plan))\n .then(\n (ok) => {\n c.busy = false;\n if (run !== c) return;\n if (ok === false) return emit();\n env.track(PAYWALL_EVENT, { ...base(), page: c.pages[c.index].id, index: c.index, plan: plan.id, action: \"purchased\" });\n end(result(\"purchased\"));\n },\n () => {\n c.busy = false;\n c.error = \"The purchase did not go through. Please try again.\";\n emit();\n },\n );\n };\n\n return {\n open: (placement, options = {}) => {\n if (run) return run.promise;\n const config = env.config();\n const w = config?.paywalls?.find((x) => x.placement === placement);\n const picked = w ? paywallPages(config, w, env.distinctId()) : null;\n if (!w || !picked?.pages.length) return Promise.resolve({ outcome: \"closed\", index: 0 });\n // The app's store prices replace MRRocket's for the same plans.\n const own = new Map((options.plans ?? []).map((p) => [p.id, p]));\n const plans = w.plans.map((p) => own.get(p.id) ?? p);\n let resolve: (r: PaywallResult) => void = () => {};\n const promise = new Promise<PaywallResult>((r) => (resolve = r));\n const plan = plans.some((p) => p.id === w.highlight) ? w.highlight : plans[0]?.id;\n run = { w, variant: picked.variant, pages: picked.pages, plans, index: 0, plan, busy: false, seen: new Set(), options, resolve, promise };\n if (picked.test) env.track(\"$exposure\", { experiment: picked.test, variant: picked.variant });\n show();\n return promise;\n },\n view: () =>\n run\n ? {\n paywall: run.w,\n variant: run.variant,\n page: run.pages[run.index],\n index: run.index,\n total: run.pages.length,\n last: run.index === run.pages.length - 1,\n plans: run.plans,\n plan: run.plan,\n busy: run.busy,\n error: run.error,\n }\n : null,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n next: () => {\n if (!run || run.busy) return;\n // A plans page or the last page buys; any other page goes on.\n if (run.pages[run.index].kind === \"plans\" || run.index === run.pages.length - 1) return buy();\n run.index++;\n run.error = undefined;\n show();\n },\n back: () => {\n if (!run || run.busy || !run.index) return;\n run.index--;\n run.error = undefined;\n emit();\n },\n pick: (id) => {\n if (!run || run.busy || !run.plans.some((p) => p.id === id)) return;\n run.plan = id;\n run.error = undefined;\n emit();\n },\n close: () => {\n if (!run || run.busy) return;\n env.track(PAYWALL_EVENT, { ...base(), index: run.index, action: \"closed\" });\n end(result(\"closed\"));\n },\n };\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 the frames are of; `userHash` is the identity hash of `distinctId` (0.16.0). */\n who: () => { distinctId?: string; identified: boolean; userHash?: string };\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, userHash } = 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 ...(userHash ? { userHash } : {}),\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, the identity hash missing\n // or wrong): stop this recording.\n if (status === 401 || 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 IdentifyOptions, type Signed, hashFor, hashForAll, nextSigned, warnUnsigned } from \"../identity\";\nimport { type CancelFlowOptions, type CancelFlowResult, type FlowsController, type InAppState, type OnboardingFlow, REVIEW_EVENT, createFlows } from \"../flows\";\nimport { type PaywallHost, type PaywallOptions, type PaywallResult, createPaywallHost } from \"../paywall\";\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 /**\n * 0.18.0: opens what a checklist task's \"Opens: page or screen\" names: a screen name or a path for your navigator\n * (`(target) => router.push(target)`). Without it only a deep link or an address (`myapp://…`, `https://…`) opens,\n * through `Linking`.\n */\n onNavigate?: (target: string) => void;\n /** 0.18.0: a checklist task set to \"Opens: your code\" was tapped: `(taskId, item) => …`. */\n onTask?: (taskId: string, item: OnboardingFlow) => void;\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 /**\n * 0.16.0: the store's own rating dialog through `expo-store-review` (StoreKit, Play In-App Review), when the app has\n * it installed. `request` resolves true once the dialog was asked for, false when this device has none.\n */\n storeReview?: { request(): Promise<boolean> } | 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\n/**\n * 0.16.0, what `requestReview()` did: \"requested\" the store's rating dialog was asked for (the store decides whether it\n * shows; Apple shows it at most three times a year); \"not-now\" no live review request may ask this person now (not a\n * customer, asked in the last 120 days, no request live); \"unavailable\" the device has no dialog or `expo-store-review`\n * is not installed; \"not-signed-in\" call `identify` first.\n */\nexport type NativeReviewResult = \"requested\" | \"not-now\" | \"unavailable\" | \"not-signed-in\";\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 /**\n * Who the person is once they sign in. `{ hash }` (0.16.0) is the id signed by your backend (`userHash(id)` from\n * `@mrrocket/sdk/next/server`, or the same HMAC in any language), fetched after sign-in; sent with every request for\n * that id so MRRocket knows it is really them. Needed with \"Only signed users\" (MRRocket › Settings › Products ›\n * Sign-in). Not stored on the device: call identify with it on every start.\n */\n identify(id: string, props?: Record<string, unknown>, options?: IdentifyOptions): void;\n /** Forgets the signed-in person and their hash (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 * Shows the paywall of a placement built in MRRocket › Paywalls page by page (drawn by `<MRRocketProvider>`). Its\n * last page hands the chosen plan to `onPurchase`, where your code buys it (RevenueCat, Adapty, StoreKit, Play);\n * MRRocket never takes a payment. Pass your store's `plans` to show their local prices.\n */\n openPaywall(placement: string, options?: PaywallOptions): Promise<PaywallResult>;\n /** The open paywall for a renderer (the provider's, or your own). */\n paywall: PaywallHost;\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 /**\n * 0.16.0: asks for a store review at the moment your app picked (the trigger of a review request in MRRocket ›\n * Reviews › Requests). MRRocket says whether this signed-in person may be asked now; if so the App Store's or Google\n * Play's own rating dialog opens (needs `expo-store-review`) and MRRocket counts the request. Never filtered by mood.\n */\n requestReview(): Promise<NativeReviewResult>;\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 // The id identify() signed and its hash (../identity.ts); in memory only.\n let signed: Signed | null = null;\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 // One person's onboarding progress, in-app messages and review permission (GET /api/sdk/inapp).\n const fetchInApp = async (id: string): Promise<InAppState | null> => {\n if (!apiKey) return null;\n const hash = hashOf(id);\n const r = await deps.fetch(`${host}/api/sdk/inapp?key=${encodeURIComponent(apiKey)}&distinctId=${encodeURIComponent(id)}${hash ? `&userHash=${hash}` : \"\"}`, { method: \"GET\" });\n warnUnsigned(r.status, deps.log);\n return r.ok ? ((await r.json()) as InAppState) : null;\n };\n\n // The cancel flow, onboarding and in-app messages (../flows.ts); `<MRRocketProvider>` draws them.\n const paywall = createPaywallHost({ config: () => config, distinctId: () => distinctId(), track: (event, props) => record(event, props) });\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: (id) => fetchInApp(id),\n // 0.18.0: a task's page or screen goes to the app's navigator; without one only a link with a scheme opens.\n navigate: (target) => {\n if (options.onNavigate) return options.onNavigate(target);\n if (/^[a-z][a-z0-9+.-]*:/i.test(target) && !/^(javascript|data|vbscript):/i.test(target)) deps.openUrl?.(target);\n else warn(`A checklist task opens \"${target}\": pass onNavigate to MRRocketProvider to open screens and paths.`);\n },\n task: (taskId, item) => options.onTask?.(taskId, item),\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 /** The identity hash for `id`, only when identify() signed exactly that id. */\n const hashOf = (id: string | undefined) => hashFor(signed, id);\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 warnUnsigned(r.status, deps.log);\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, hashOf(sendId()));\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 if (status !== 401) 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 userHash = hashForAll(signed, batch.map((r) => r.distinctId));\n const status = await post(\"/api/sdk/errors\", JSON.stringify({ key: apiKey, ...(userHash ? { userHash } : {}), sdk, errors: batch }));\n if (status >= 400 && status < 500 && status !== 429 && status !== 401) 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, userHash: hashOf(sendId()) }),\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 pushHash: 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 const userHash = hashOf(who);\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, userHash, 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 pushHash = userHash;\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, userHash: pushHash, platform: \"expo\", token, remove: true }));\n return status >= 200 && status < 300;\n };\n\n // ---------- Store reviews (0.16.0) ----------\n\n let reviewing = false;\n const requestReview = async (): Promise<NativeReviewResult> => {\n if (!deps.storeReview) return \"unavailable\";\n await loadedNow();\n if (!apiKey || consent === \"off\") return \"not-now\";\n if (!identified) return \"not-signed-in\";\n if (reviewing) return \"not-now\";\n reviewing = true;\n try {\n // Asked now, at the app's moment: whether a live request may ask this person (customer, limits, 120 days).\n const ask = (await fetchInApp(identified).catch(() => null))?.review;\n if (!ask) return \"not-now\";\n const asked = await deps.storeReview.request().catch(() => false);\n // Only a dialog the device asked for counts as a request in MRRocket (and starts the 120 days).\n record(REVIEW_EVENT, { campaign: ask.campaign, store: ask.store, action: asked ? \"requested\" : \"unavailable\" });\n void flush();\n return asked ? \"requested\" : \"unavailable\";\n } finally {\n reviewing = false;\n }\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, options) => {\n if (typeof id !== \"string\" || !id) return;\n if (!loaded) {\n early.push(() => client.identify(id, props, options));\n return;\n }\n const previous = sendId();\n // The hash belongs to this id; another id without one drops it.\n signed = nextSigned(signed, id, options?.hash, deps.log);\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 // What is queued for the person goes now, with their hash, before it is forgotten.\n void flush();\n identified = undefined;\n signed = null;\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 openPaywall: (placement, o) => paywall.open(placement, o),\n paywall,\n registerForPush,\n unregisterForPush,\n requestReview,\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, userHash: hashOf(distinctId()) });\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, so a step's side does not apply). A step's picture (0.17.0) shows\n * above its text; a video opens in the phone's player or browser from a \"Watch the video\" button.\n *\n * 0.18.0: the questions of a Questions item as slides with dots (choices or a text field, Back and Continue), task and\n * heading icons (react-native-svg when the app has it, else the icon's emoji), tasks that open a screen, a deep link, a\n * tour, a modal or the app's code, the finish animation (Animated views, skipped when the phone asks for less motion),\n * and the product's brand color from MRRocket when `appearance` sets no accent.\n */\nimport { Fragment, type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FinishAnimation, type FlowIcon, type FlowsController, type OnboardingStep, answerOk, discounted, mediaOf, money, offerButton, videoEmbed } from \"../flows\";\nimport { FLOW_ICONS, iconOf } from \"../icons\";\nimport type { PaywallHost, PaywallView } from \"../paywall\";\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 Image?: Any;\n Linking?: { openURL: (url: string) => Promise<unknown> };\n useColorScheme?: () => string | null | undefined;\n Animated?: {\n View: Any;\n Value: new (v: number) => AnimatedValue;\n timing: (v: AnimatedValue, c: { toValue: number; duration: number; delay?: number; useNativeDriver: boolean }) => AnimatedRun;\n parallel: (runs: AnimatedRun[]) => AnimatedRun;\n };\n AccessibilityInfo?: { isReduceMotionEnabled?: () => Promise<boolean> };\n}\ninterface AnimatedValue {\n interpolate: (c: { inputRange: number[]; outputRange: (number | string)[] }) => unknown;\n}\ninterface AnimatedRun {\n start: (done?: () => void) => void;\n stop: () => void;\n}\nconst RN = require(\"react-native\") as RNModule;\n\n/** react-native-svg, when the app has it (for the built-in icons); null otherwise. */\nconst svg = (() => {\n try {\n return require(\"react-native-svg\") as { Svg?: Any; default?: Any; Path: Any };\n } catch {\n return null;\n }\n})();\n\n/** 0.18.0: an icon at `size`: a built-in line icon (its emoji without react-native-svg), an emoji, or a picture. */\nconst iconNode = (icon: FlowIcon | undefined, size: number, color: string): ReactNode => {\n const i = iconOf(icon);\n if (!i) return null;\n if (i.kind === \"image\")\n return RN.Image ? h(RN.Image, { source: { uri: i.url }, accessibilityElementsHidden: true, style: { width: size, height: size, borderRadius: size / 4 } }) : null;\n const Svg = svg?.Svg ?? svg?.default;\n if (i.kind === \"builtin\" && Svg && svg?.Path)\n return h(\n Svg,\n { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", stroke: color, strokeWidth: 2, strokeLinecap: \"round\", strokeLinejoin: \"round\" },\n ...FLOW_ICONS[i.name].paths.map((d, k) => h(svg.Path, { key: k, d })),\n );\n return h(RN.Text, { style: { fontSize: size * 0.8, lineHeight: size, textAlign: \"center\", width: size } }, i.kind === \"emoji\" ? i.value : FLOW_ICONS[i.name].emoji);\n};\n\ninterface Bit {\n x: number;\n y: number;\n dx: number;\n dy: number;\n mid: number;\n size: number;\n rot: number;\n color: string;\n delay: number;\n life: number;\n shape: \"rect\" | \"dot\" | \"star\";\n}\n\nconst FINALE_COLORS = [\"#f59e0b\", \"#10b981\", \"#ef4444\", \"#8b5cf6\", \"#06b6d4\", \"#ec4899\"];\n\n/** The particles of a finish animation, placed in percent of the screen and moved in points. */\nconst finaleBits = (kind: Exclude<FinishAnimation, \"none\">, accent: string): Bit[] => {\n const rnd = (a: number, b: number) => a + Math.random() * (b - a);\n const colors = [accent, accent, ...FINALE_COLORS];\n const pick = () => colors[Math.floor(Math.random() * colors.length)];\n if (kind === \"confetti\")\n return Array.from({ length: 48 }, (_, i) => ({\n x: i % 2 ? 12 : 82,\n y: 92,\n dx: (i % 2 ? 1 : -1) * rnd(40, 200),\n mid: -rnd(380, 620),\n dy: -rnd(120, 300),\n size: rnd(7, 11),\n rot: rnd(-540, 540),\n color: pick(),\n delay: rnd(0, 160),\n life: rnd(1500, 2000),\n shape: \"rect\" as const,\n }));\n if (kind === \"fireworks\")\n return Array.from({ length: 3 }, (_, b) => {\n const x = rnd(20, 75);\n const y = rnd(18, 45);\n const color = pick();\n return Array.from({ length: 18 }, (_, i) => {\n const a = (Math.PI * 2 * i) / 18;\n const r = rnd(70, 130);\n return { x, y, dx: Math.cos(a) * r, mid: Math.sin(a) * r * 0.8, dy: Math.sin(a) * r + 40, size: 5, rot: 0, color, delay: b * 320, life: rnd(900, 1200), shape: \"dot\" as const };\n });\n }).flat();\n return Array.from({ length: 22 }, () => ({\n x: rnd(6, 88),\n y: rnd(20, 80),\n dx: 0,\n mid: -rnd(10, 25),\n dy: -rnd(30, 60),\n size: rnd(16, 28),\n rot: rnd(-40, 40),\n color: pick(),\n delay: rnd(0, 600),\n life: rnd(900, 1300),\n shape: \"star\" as const,\n }));\n};\n\n/** 0.18.0: the finish animation over the app, once, unless the phone asks for less motion. */\nconst Finale = ({ kind, accent }: { kind: Exclude<FinishAnimation, \"none\">; accent: string }) => {\n const A = RN.Animated;\n const [bits] = useState(() => finaleBits(kind, accent));\n const [values] = useState(() => (A ? bits.map(() => new A.Value(0)) : []));\n const [on, setOn] = useState(!!A);\n useEffect(() => {\n if (!A) return;\n let stopped = false;\n let run: AnimatedRun | null = null;\n const go = () => {\n if (stopped) return;\n run = A.parallel(values.map((v, i) => A.timing(v, { toValue: 1, duration: bits[i].life, delay: bits[i].delay, useNativeDriver: true })));\n run.start(() => !stopped && setOn(false));\n };\n Promise.resolve(RN.AccessibilityInfo?.isReduceMotionEnabled?.())\n .then((reduce) => (reduce ? !stopped && setOn(false) : go()))\n .catch(go);\n return () => {\n stopped = true;\n run?.stop();\n };\n }, [A, bits, values]);\n if (!on || !A) return null;\n return h(\n RN.View,\n { pointerEvents: \"none\", accessibilityElementsHidden: true, importantForAccessibility: \"no-hide-descendants\", style: { position: \"absolute\", left: 0, right: 0, top: 0, bottom: 0 } },\n ...bits.map((b, i) => {\n const t = values[i];\n const fade = t.interpolate({ inputRange: [0, 0.7, 1], outputRange: [1, 1, 0] });\n const scale = b.shape === \"star\" ? t.interpolate({ inputRange: [0, 0.25, 1], outputRange: [0.2, 1.15, 0.6] }) : 1;\n return h(\n A.View,\n {\n key: i,\n style: {\n position: \"absolute\",\n left: `${b.x}%`,\n top: `${b.y}%`,\n width: b.size,\n height: b.shape === \"rect\" ? b.size * 0.45 : b.size,\n borderRadius: b.shape === \"dot\" ? b.size / 2 : 2,\n backgroundColor: b.shape === \"star\" ? \"transparent\" : b.color,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: fade,\n transform: [\n { translateX: t.interpolate({ inputRange: [0, 1], outputRange: [0, b.dx] }) },\n { translateY: t.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0, b.mid, b.dy] }) },\n { rotate: t.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", `${b.rot}deg`] }) },\n { scale },\n ],\n },\n },\n b.shape === \"star\" ? h(RN.Text, { style: { color: b.color, fontSize: b.size, lineHeight: b.size } }, \"★\") : null,\n );\n }),\n );\n};\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\n/** The dialogs, and (0.18.0) the finish animation over the app when someone just finished an item. */\nexport const MRRocketFlows = (props: { flows: FlowsController; paywall?: PaywallHost; appearance?: NativeAppearance }) => {\n const [, setTick] = useState(0);\n useEffect(() => props.flows.subscribe(() => setTick((t) => t + 1)), [props.flows]);\n const fin = props.flows.finale?.() ?? null;\n const accent = props.appearance?.accent ?? props.flows.accent?.() ?? \"#3f76ff\";\n return h(Fragment, null, h(FlowsBody, props), fin ? h(Finale, { key: fin.key, kind: fin.kind, accent }) : null);\n};\n\nconst FlowsBody = ({ flows, paywall, appearance = {} }: { flows: FlowsController; paywall?: PaywallHost; appearance?: NativeAppearance }) => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n // 0.18.0: the product's brand color from MRRocket unless the app set its own accent.\n const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? flows.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 useEffect(() => paywall?.subscribe(() => setTick((t) => t + 1)), [paywall]);\n const pw = paywall?.view() ?? null;\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 && !pw) 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, value = comment, onChange: (t: string) => void = setComment) =>\n h(RN.TextInput, {\n value,\n onChangeText: onChange,\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 /** A paywall page: dots, title, text, its benefits, quotes or plans, the button and Back. */\n const paywallSheet = (w: PaywallView) => {\n const pg = w.page;\n const host = paywall!;\n return sheet(\n [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(w.total > 1\n ? Array.from({ length: w.total }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= w.index ? p.accent : p.line } }),\n )\n : []),\n close(\"Close\", host.close),\n ),\n title(pg.title),\n pg.body ? muted(pg.body, { fontSize: 15 }) : null,\n ...(pg.kind === \"benefits\"\n ? (pg.items ?? []).map((item, i) =>\n h(\n RN.View,\n { key: `b${i}`, style: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\" } },\n text(\"✓\", { color: p.accent, fontWeight: \"700\" }),\n text(item, { flex: 1 }),\n ),\n )\n : []),\n ...(pg.kind === \"proof\"\n ? (pg.quotes ?? []).map((q, i) =>\n h(RN.View, { key: `q${i}`, style: { backgroundColor: p.soft, borderRadius: 12, padding: 12, gap: 6 } }, text(q.text), q.by ? muted(q.by) : null),\n )\n : []),\n pg.kind === \"plans\"\n ? h(\n RN.View,\n { key: \"plans\", accessibilityRole: \"radiogroup\", style: { gap: 6 } },\n ...w.plans.map((plan) =>\n h(\n RN.Pressable,\n {\n key: plan.id,\n onPress: () => host.pick(plan.id),\n accessibilityRole: \"radio\",\n accessibilityLabel: `${plan.name}, ${plan.price}`,\n accessibilityState: { checked: w.plan === plan.id },\n style: {\n minHeight: 52,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: w.plan === plan.id ? p.accent : p.line,\n backgroundColor: w.plan === plan.id ? p.soft : p.bg,\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n },\n },\n h(RN.View, { style: { flex: 1 } }, text(plan.name, { fontWeight: \"600\" }), plan.note ? muted(plan.note) : null),\n text(plan.price, { fontWeight: \"700\" }),\n ),\n ),\n )\n : null,\n w.error ? text(w.error, { color: p.danger, fontSize: 13 }) : null,\n btn(w.busy ? \"One moment…\" : pg.button || \"Continue\", \"primary\", host.next, w.busy || (pg.kind === \"plans\" && !w.plan)),\n w.index ? btn(\"Back\", \"quiet\", host.back, w.busy) : null,\n ],\n host.close,\n );\n };\n\n if (pw) return paywallSheet(pw);\n if (!v) return null;\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 /** One choice of a list (the survey's answers, a follow-up's). */\n const choices = (items: { key: string; label: string; on: boolean; press: () => void }[]) =>\n h(\n RN.ScrollView,\n { style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...items.map((c) =>\n h(\n RN.Pressable,\n {\n key: c.key,\n onPress: c.press,\n accessibilityRole: \"radio\",\n accessibilityState: { checked: c.on },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: c.on ? p.accent : p.line,\n backgroundColor: c.on ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(c.label, { fontWeight: \"500\" }),\n ),\n ),\n );\n if (v.screen === \"survey\")\n body = [\n title(v.flow.question || \"Why are you leaving?\"),\n choices(v.flow.reasons.map((r) => ({ key: r.id, label: r.label, on: v.reason === r.id, press: () => flows.cancel.pick(r.id) }))),\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 === \"followup\" && v.followUp) {\n const f = v.followUp;\n const label = v.flow.reasons.find((r) => r.id === v.reason)?.label;\n body = [\n label ? muted(`You said: ${label}`) : null,\n title(f.question),\n f.answers.length\n ? choices(f.answers.map((a, i) => ({ key: String(i), label: a, on: v.answer === a, press: () => flows.cancel.answer(a) })))\n : input(\"Your answer (optional)\", v.answer ?? \"\", flows.cancel.answer),\n btn(\"Continue\", \"primary\", flows.cancel.next),\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 /** 0.17.0: the step's picture, or a button that opens its video. */\n const media = (s: OnboardingStep) => {\n const m = mediaOf(s);\n if (!m) return null;\n if (m.kind === \"image\")\n return RN.Image\n ? h(RN.Image, {\n key: \"media\",\n source: { uri: m.url },\n accessibilityLabel: m.alt,\n resizeMode: \"cover\",\n style: { width: \"100%\", aspectRatio: 16 / 9, borderRadius: 10, backgroundColor: p.soft },\n })\n : null;\n const v = videoEmbed(m.url);\n const open = v?.kind === \"file\" ? v.src : m.url;\n return RN.Linking ? btn(\"▶ Watch the video\", \"secondary\", () => void RN.Linking?.openURL(open).catch(() => {})) : null;\n };\n\n if (v.type === \"step\" && v.step.kind === \"question\") {\n // 0.18.0: one question as a slide: dots, the options or a text field, Back and Continue.\n const s = v.step;\n const q = s.question;\n const ok = answerOk(q, v.answer);\n return sheet(\n [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(v.total > 1\n ? Array.from({ length: v.total }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= v.index ? p.accent : p.line } }),\n )\n : []),\n close(\"Close\", flows.onboarding.dismiss),\n ),\n v.index === 0 && v.flow.icon ? h(RN.View, { key: \"icon\" }, iconNode(v.flow.icon, 36, p.accent)) : null,\n title(s.title),\n s.body ? muted(s.body, { fontSize: 15 }) : null,\n q?.type === \"choice\"\n ? h(\n RN.ScrollView,\n { key: \"opts\", style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...(q.options ?? []).map((o) =>\n h(\n RN.Pressable,\n {\n key: o.id,\n onPress: () => flows.onboarding.answer(o.id),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: v.answer === o.id },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: v.answer === o.id ? p.accent : p.line,\n backgroundColor: v.answer === o.id ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(o.label, { fontWeight: \"500\" }),\n ),\n ),\n )\n : q\n ? h(RN.TextInput, {\n key: \"answer\",\n value: v.answer ?? \"\",\n onChangeText: (t: string) => flows.onboarding.answer(t),\n onSubmitEditing: flows.onboarding.next,\n placeholder: q.placeholder || \"Your answer\",\n placeholderTextColor: p.muted,\n maxLength: 500,\n accessibilityLabel: s.title,\n style: { height: 44, borderWidth: 1, borderColor: p.line, borderRadius: 10, paddingHorizontal: 12, color: p.fg },\n })\n : null,\n btn(s.button || (v.last ? \"Done\" : \"Continue\"), \"primary\", flows.onboarding.next, !ok),\n v.back ? btn(\"Back\", \"quiet\", flows.onboarding.back) : null,\n ],\n flows.onboarding.dismiss,\n );\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 v.step.kind === \"modal\" && v.flow.icon ? h(RN.View, { key: \"icon\" }, iconNode(v.flow.icon, 36, p.accent)) : null,\n media(v.step),\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, opens }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n // 0.17.0/0.18.0: a task that opens something (a tour, a modal, a screen, the app's code) does it;\n // a finished tour or modal ticks it, a screen or the app's code once opened (unless an event does).\n disabled: d || (!!step.event && !opens),\n onPress: () => (opens ? flows.onboarding.open(step.id) : flows.onboarding.check(step.id)),\n accessibilityRole: opens && !d ? \"button\" : \"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 step.icon ? iconNode(step.icon, 20, p.accent) : null,\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 * 0.18.0: the SDK's own small line icons for checklist tasks and the heading of a modal or the questions\n * (`FlowIcon { kind: \"builtin\", name }`). Drawn by the SDK itself (an inline SVG on the web, react-native-svg in apps,\n * the emoji when an app has no react-native-svg), and by MRRocket's editor from this same list, so what the owner picks\n * is what people see. Each is a 24×24 outline, stroked at 2 with round ends, in the text color or the accent.\n */\n\nexport interface BuiltinIcon {\n /** What the editor calls it. */\n label: string;\n /** Path data, drawn stroked (no fill), on a 24×24 grid. */\n paths: string[];\n /** Shown instead in an app without react-native-svg. */\n emoji: string;\n}\n\nexport const FLOW_ICONS: Record<string, BuiltinIcon> = {\n check: { label: \"Check\", paths: [\"M5 12.5l4.5 4.5L19 7.5\"], emoji: \"✅\" },\n star: { label: \"Star\", paths: [\"M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.9l-5.2 2.7 1-5.8-4.3-4.1 5.9-.9z\"], emoji: \"⭐\" },\n rocket: {\n label: \"Rocket\",\n paths: [\"M12 3c3 2 4.5 5.5 4 10l-2 3h-4l-2-3c-.5-4.5 1-8 4-10z\", \"M8 13.5l-3 3 3.5.5\", \"M16 13.5l3 3-3.5.5\", \"M13.5 9.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z\", \"M11 19.5v1.5M13 19.5v1.5\"],\n emoji: \"🚀\",\n },\n user: { label: \"Person\", paths: [\"M15.5 8a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z\", \"M5 20c.8-3.5 3.6-5.5 7-5.5s6.2 2 7 5.5\"], emoji: \"👤\" },\n users: {\n label: \"Team\",\n paths: [\"M13 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z\", \"M3.5 19c.6-3 3-4.8 6.5-4.8s5.9 1.8 6.5 4.8\", \"M16 5.2a3 3 0 0 1 0 5.6\", \"M18 14.6c1.5.6 2.4 2 2.7 4.4\"],\n emoji: \"👥\",\n },\n settings: {\n label: \"Settings\",\n paths: [\"M12 2.8v2.4M12 18.8v2.4M2.8 12h2.4M18.8 12h2.4M5.5 5.5l1.7 1.7M16.8 16.8l1.7 1.7M5.5 18.5l1.7-1.7M16.8 7.2l1.7-1.7\", \"M17 12a5 5 0 1 1-10 0 5 5 0 0 1 10 0z\", \"M14 12a2 2 0 1 1-4 0 2 2 0 0 1 4 0z\"],\n emoji: \"⚙️\",\n },\n bell: { label: \"Bell\", paths: [\"M6 16v-5a6 6 0 0 1 12 0v5l1.5 2h-15z\", \"M10 20.5a2 2 0 0 0 4 0\"], emoji: \"🔔\" },\n mail: { label: \"Mail\", paths: [\"M4 6h16v12H4z\", \"M4 7l8 6 8-6\"], emoji: \"✉️\" },\n chat: { label: \"Chat\", paths: [\"M4 5h16v11H9l-5 4z\"], emoji: \"💬\" },\n heart: { label: \"Heart\", paths: [\"M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z\"], emoji: \"❤️\" },\n flag: { label: \"Flag\", paths: [\"M5 21V4\", \"M5 4h11l-2 4 2 4H5\"], emoji: \"🚩\" },\n bolt: { label: \"Bolt\", paths: [\"M13 3L5 13.5h6L10 21l8-10.5h-6z\"], emoji: \"⚡\" },\n book: { label: \"Book\", paths: [\"M4 5.5C6.5 4 9.5 4 12 6c2.5-2 5.5-2 8-.5V19c-2.5-1.5-5.5-1.5-8 .5-2.5-2-5.5-2-8-.5z\", \"M12 6v13.5\"], emoji: \"📖\" },\n calendar: { label: \"Calendar\", paths: [\"M4 6h16v14H4z\", \"M4 10h16\", \"M8 3.5v4M16 3.5v4\"], emoji: \"📅\" },\n camera: { label: \"Camera\", paths: [\"M4 8h3.5L9 5.5h6L16.5 8H20v11H4z\", \"M15.5 13a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z\"], emoji: \"📷\" },\n cart: { label: \"Cart\", paths: [\"M3.5 4.5H6l2 10h10l2-7H7\", \"M9.5 19.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z\", \"M18.5 19.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z\"], emoji: \"🛒\" },\n chart: { label: \"Chart\", paths: [\"M4 20h16\", \"M7 16v-4M12 16V8M17 16V9\"], emoji: \"📊\" },\n gift: { label: \"Gift\", paths: [\"M4 10h16v10H4z\", \"M3 7h18v3H3z\", \"M12 7v13\", \"M12 7c-1.5-3-5-3-5-1s3.5 1 5 1z\", \"M12 7c1.5-3 5-3 5-1s-3.5 1-5 1z\"], emoji: \"🎁\" },\n home: { label: \"Home\", paths: [\"M4 11l8-7 8 7\", \"M6 9.5V20h12V9.5\", \"M10 20v-6h4v6\"], emoji: \"🏠\" },\n link: { label: \"Link\", paths: [\"M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1\", \"M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1\"], emoji: \"🔗\" },\n lock: { label: \"Lock\", paths: [\"M6 11h12v9H6z\", \"M8.5 11V8a3.5 3.5 0 0 1 7 0v3\"], emoji: \"🔒\" },\n pencil: { label: \"Pencil\", paths: [\"M4 20l1-4L16 5l3 3L8 19z\", \"M14 7l3 3\"], emoji: \"✏️\" },\n plus: { label: \"Plus\", paths: [\"M12 5v14M5 12h14\"], emoji: \"➕\" },\n search: { label: \"Search\", paths: [\"M16 10.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\", \"M14.5 14.5L20 20\"], emoji: \"🔍\" },\n upload: { label: \"Upload\", paths: [\"M12 15V4\", \"M7.5 8.5L12 4l4.5 4.5\", \"M4 15v5h16v-5\"], emoji: \"⬆️\" },\n play: { label: \"Play\", paths: [\"M8 5l11 7-11 7z\"], emoji: \"▶️\" },\n sparkle: { label: \"Sparkle\", paths: [\"M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z\", \"M19 16l.7 2 2 .7-2 .7-.7 2-.7-2-2-.7 2-.7z\"], emoji: \"✨\" },\n globe: {\n label: \"Globe\",\n paths: [\"M20 12a8 8 0 1 1-16 0 8 8 0 0 1 16 0z\", \"M4 12h16\", \"M12 4c2.2 2.2 3.3 4.9 3.3 8s-1.1 5.8-3.3 8c-2.2-2.2-3.3-4.9-3.3-8S9.8 6.2 12 4z\"],\n emoji: \"🌐\",\n },\n};\n\n/** The built-in icons' names, in the editor's order. */\nexport const FLOW_ICON_NAMES = Object.keys(FLOW_ICONS);\n\n/** An icon as it may be shown: a known built-in, an emoji (up to 8 code points, so joined ones fit), or an http(s) picture; else undefined. */\nexport const iconOf = <T extends { kind: string; name?: string; value?: string; url?: string }>(icon: T | undefined): T | undefined => {\n if (!icon) return undefined;\n if (icon.kind === \"builtin\") return icon.name && FLOW_ICONS[icon.name] ? icon : undefined;\n if (icon.kind === \"emoji\") return icon.value && icon.value.trim() && [...icon.value.trim()].length <= 8 ? icon : undefined;\n if (icon.kind === \"image\") return icon.url && /^https?:\\/\\//i.test(icon.url) ? icon : undefined;\n return undefined;\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 * - `expo-store-review` (0.16.0): the store's own rating dialog, `requestReview()`. Without it that 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}\ninterface ExpoStoreReview {\n isAvailableAsync?: () => Promise<boolean>;\n requestReview?: () => Promise<void>;\n}\nlet expoStoreReview: ExpoStoreReview | null = null;\ntry {\n expoStoreReview = require(\"expo-store-review\") as ExpoStoreReview;\n} catch {\n expoStoreReview = 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 store's rating dialog, when expo-store-review is installed: false when the device has none (a simulator, no store). */\nconst storeReview = (): NativeDeps[\"storeReview\"] => {\n const m = expoStoreReview;\n if (!m?.requestReview) return null;\n return {\n request: async () => {\n if (m.isAvailableAsync && !(await m.isAvailableAsync())) return false;\n await m.requestReview!();\n return true;\n },\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 storeReview: storeReview(),\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 expoStoreReview: !!expoStoreReview?.requestReview,\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 in one of eight places. Home is plain like the web messenger's (or on the\n * accent with `header: \"color\"`), corners follow `corners`; its line icons need react-native-svg (text glyphs\n * without it). While it is closed and the person waits for an answer, it checks now and then; a new answer shows as\n * a banner at the top with a light haptic (expo-haptics, when installed; apps play 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 { BRAND_URL, CHAT_FILES_PER_MESSAGE, CHAT_FILE_MAX_BYTES, CORNERS, inkOn } from \"../api-client\";\nimport type {\n Api,\n Article,\n ArticleSpan,\n ArticleSummary,\n ChatFile,\n ChatMessage,\n MessengerCorners,\n MessengerLook,\n MessengerPosition,\n ChatThread,\n FeedbackBoardInfo,\n FeedbackPost,\n SurveyAnswer,\n SurveyDefinition,\n SurveyQuestion,\n} 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; Version?: string | number };\n Linking: { openURL(url: string): Promise<unknown> };\n Image: Any;\n Dimensions: { get(dim: \"screen\" | \"window\"): { width: number; height: number } };\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/** Who wrote a message; the AI agent by the name set in MRRocket. */\nconst who = (from: ChatMessage[\"from\"], agentName?: string) => (from === \"ai\" && agentName?.trim()) || whoLabel[from];\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: a corner, the middle of the top or bottom edge, or the middle of a side (default bottom right). */\n position?: MessengerPosition;\n /** Text beside the chat button's icon; empty: the round button. */\n label?: string;\n /** The name beside the team's mark at the top of Home (MRRocket fills in the product's name). */\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 on Home. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** How round bubbles, cards and fields are (default round; the sheet itself keeps the system's corners). */\n corners?: MessengerCorners;\n /** Home's top: plain like the rest (default), or in the accent color with raised cards. */\n header?: \"plain\" | \"color\";\n /** The logo at the top left of Home (MRRocket sends the uploaded logo, else the product's favicon). */\n logo?: string;\n /** The AI agent's name on its answers (default \"AI agent\"). */\n agentName?: string;\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\n/** expo-image-picker, when the app has it: the paperclip in the chat picks photos (screenshots included) with it. */\ninterface ImagePickerAsset {\n uri: string;\n fileName?: string | null;\n mimeType?: string | null;\n fileSize?: number | null;\n}\ninterface ExpoImagePicker {\n launchImageLibraryAsync?: (o: Record<string, unknown>) => Promise<{ canceled?: boolean; cancelled?: boolean; assets?: ImagePickerAsset[] | null }>;\n}\nlet imagePicker: ExpoImagePicker | null = null;\ntry {\n imagePicker = require(\"expo-image-picker\") as ExpoImagePicker;\n} catch {\n imagePicker = null;\n}\nconst PHOTO_TYPES: Record<string, ChatFile[\"type\"]> = { jpg: \"image/jpeg\", jpeg: \"image/jpeg\", png: \"image/png\", webp: \"image/webp\", gif: \"image/gif\" };\n\n/** A photo picked for the next message, uploading or uploaded. */\ninterface PickedPhoto {\n key: string;\n uri: string;\n name: string;\n type: ChatFile[\"type\"];\n size: number;\n id?: string;\n up: Promise<void>;\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 clip: \"m14.3 7.4-6.1 6.1a4 4 0 0 1-5.7-5.7l5.7-5.7a2.7 2.7 0 0 1 3.8 3.8L6.3 11.6a1.3 1.3 0 0 1-1.9-1.9l5.7-5.6\",\n};\nconst FALLBACK: Record<keyof typeof GLYPH, string> = { chat: \"💬\", home: \"⌂\", help: \"?\", send: \"→\", up: \"↑\", next: \"›\", search: \"⌕\", cross: \"×\", clip: \"📎\" };\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 );\n/** The messenger sheet like the web messenger: a white sheet, gray fills without shadows, a pill tab switch with the current tab raised. */\nconst HU = {\n light: { bg: \"#ffffff\", surface: \"#f4f4f5\", def: \"#ececee\", segment: \"#ffffff\", fg: \"#18181b\", muted: \"#71717a\" },\n dark: { bg: \"#111113\", surface: \"#1c1c1f\", def: \"#26262a\", segment: \"#3a3a40\", fg: \"#fafafa\", muted: \"#a1a1aa\" },\n};\nconst hairline = { shadowColor: \"#000\", shadowOpacity: 0.07, shadowRadius: 3, shadowOffset: { width: 0, height: 1 }, elevation: 1 };\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 brand,\n}: {\n client: MRRocketClient;\n p: Palette;\n o: NativeMessengerOptions;\n chat: ReturnType<typeof useChat>;\n view: MsgView;\n setView: (v: MsgView) => void;\n /** \"Powered by MRRocket\" above the tab bar. */\n brand: boolean;\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 // A message on its way reads \"just now\" like a sent one; \"Sending…\" only once the server is slow to take it.\n const [slow, setSlow] = useState(false);\n useEffect(() => {\n setSlow(false);\n if (!pending) return;\n const t = setTimeout(() => setSlow(true), 1500);\n return () => clearTimeout(t);\n }, [pending]);\n const [photos, setPhotos] = useState<PickedPhoto[]>([]);\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 // Photos for the next message, picked with expo-image-picker (the paperclip shows only when the app has it). Each\n // uploads at once; Send waits for the uploads. People take a screenshot with the phone and pick it here.\n const pickPhotos = async () => {\n const api = client.api();\n if (!api || !imagePicker?.launchImageLibraryAsync || pending) return;\n const room = CHAT_FILES_PER_MESSAGE - photos.length;\n if (room <= 0) return chat.setError(`Up to ${CHAT_FILES_PER_MESSAGE} files per message.`);\n let res: Awaited<ReturnType<NonNullable<ExpoImagePicker[\"launchImageLibraryAsync\"]>>>;\n try {\n res = await imagePicker.launchImageLibraryAsync({ allowsMultipleSelection: room > 1, selectionLimit: room, quality: 0.8, exif: false });\n } catch (e) {\n return chat.setError((e as Error).message || \"The photos could not be opened.\");\n }\n if (res.canceled || res.cancelled || !res.assets?.length) return;\n chat.setError(\"\");\n const added: PickedPhoto[] = [];\n for (const a of res.assets.slice(0, room)) {\n const name = a.fileName || a.uri.split(\"/\").pop() || \"photo.jpg\";\n const type = (a.mimeType && Object.values(PHOTO_TYPES).includes(a.mimeType as ChatFile[\"type\"]) ? a.mimeType : PHOTO_TYPES[name.split(\".\").pop()?.toLowerCase() ?? \"\"]) as ChatFile[\"type\"] | undefined;\n if (!type) {\n chat.setError(\"Only pictures (PNG, JPEG, WebP, GIF) can be sent.\");\n continue;\n }\n if (a.fileSize && a.fileSize > CHAT_FILE_MAX_BYTES) {\n chat.setError(`${name} is larger than 10 MB.`);\n continue;\n }\n const ph: PickedPhoto = { key: `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`, uri: a.uri, name, type, size: a.fileSize ?? 0, up: Promise.resolve() };\n ph.up = api.uploadChatFile({ uri: a.uri, name, type }).then(\n (r) => {\n ph.id = r.id;\n setPhotos((list) => list.map((x) => (x.key === ph.key ? { ...ph } : x)));\n },\n (e: Error) => {\n setPhotos((list) => list.filter((x) => x.key !== ph.key));\n chat.setError(`${name}: ${e.message}`);\n },\n );\n added.push(ph);\n }\n setPhotos((list) => [...list, ...added]);\n };\n const canSend = (!!body.trim() || photos.length > 0) && !pending && emailOk;\n const send = async () => {\n const text = body.trim();\n const api = client.api();\n const files = photos;\n if ((!text && !files.length) || pending || !emailOk || !api) return;\n setPending({\n id: \"pending\",\n from: \"visitor\",\n body: text,\n at: new Date().toISOString(),\n ...(files.length ? { attachments: files.map((f) => ({ id: f.key, name: f.name, type: f.type, size: f.size })) } : {}),\n });\n setBody(\"\");\n setPhotos([]);\n chat.setError(\"\");\n try {\n await Promise.all(files.map((f) => f.up));\n const ids = files.filter((f) => f.id).map((f) => f.id!);\n if (!text && !ids.length) throw new Error(\"The photo could not be sent.\");\n // The screen, not the app's window: check-dist keeps the word \"window\" out of the bundle (no browser APIs).\n const win = RN.Dimensions.get(\"screen\");\n chat.take(\n await api.sendChat({\n body: text,\n email: needEmail && email.trim() ? email.trim() : undefined,\n ...(ids.length ? { attachments: ids } : {}),\n // A little context for a bug report: the system and the screen size.\n context: { os: `${RN.Platform.OS === \"ios\" ? \"iOS\" : RN.Platform.OS === \"android\" ? \"Android\" : RN.Platform.OS} ${RN.Platform.Version ?? \"\"}`.trim(), browser: \"App\", viewport: `${Math.round(win.width)}×${Math.round(win.height)}` },\n }),\n );\n } catch (e) {\n setBody(text);\n setPhotos(files.filter((f) => f.id));\n chat.setError((e as Error).message);\n } finally {\n setPending(null);\n }\n };\n /** Where a file of the chat is read: the photo on this device while it is on its way, else the server's. */\n const localUris = useRef(new Map<string, string>());\n for (const f of photos) localUris.current.set(f.key, f.uri);\n const fileUrl = (id: string) => localUris.current.get(id) ?? client.api()?.attachmentUrl(id) ?? \"\";\n\n const ink = inkOn(p.accent);\n const dark = p.bg === DARK.bg;\n const r = CORNERS[o.corners ?? \"round\"];\n // White surfaces on HeroUI's gray ground; Home's top plain (the default) or in the accent color.\n const plain = o.header !== \"color\";\n const hu = dark ? HU.dark : HU.light;\n // Fills carry no shadow; only the current tab is raised.\n const surf = {};\n const segLift = dark ? {} : hairline;\n const canvas = hu.bg;\n const raised = hu.surface;\n const title = o.title?.trim() ?? \"\";\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 // Sent photos as themselves (a tap opens the full size), a PDF as a chip.\n ...(m.attachments ?? []).map((f) =>\n h(\n RN.Pressable,\n {\n key: f.id,\n onPress: () => void RN.Linking.openURL(fileUrl(f.id)).catch(() => undefined),\n accessibilityRole: \"imagebutton\",\n accessibilityLabel: f.name,\n style: { alignSelf: mine ? \"flex-end\" : \"flex-start\", opacity: isPending ? 0.7 : 1 },\n },\n f.type.startsWith(\"image/\")\n ? h(RN.Image, { source: { uri: fileUrl(f.id) }, resizeMode: \"cover\", style: { width: 200, height: 150, borderRadius: r.bubble, backgroundColor: p.soft } })\n : h(RN.View, { style: { backgroundColor: p.soft, borderRadius: r.card, paddingHorizontal: 10, paddingVertical: 7 } }, k.text(`📄 ${f.name}`, { fontSize: 13 })),\n ),\n ),\n !m.body && m.attachments?.length\n ? null\n : h(\n RN.View,\n {\n style: {\n backgroundColor: mine ? p.accent : hu.surface,\n ...(mine ? {} : surf),\n borderRadius: r.bubble,\n borderBottomRightRadius: mine ? r.tail : r.bubble,\n borderBottomLeftRadius: mine ? r.bubble : r.tail,\n paddingHorizontal: 14,\n paddingVertical: 9,\n opacity: isPending ? 0.7 : 1,\n },\n },\n k.text(m.body, { color: mine ? ink : hu.fg }),\n ),\n ...(m.articles ?? []).map((a) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"link\", style: { backgroundColor: p.soft, borderRadius: r.card, paddingHorizontal: 10, paddingVertical: 7 } },\n k.text(`📄 ${a.title}`, { fontSize: 13 }),\n ),\n ),\n m.at ? k.muted(`${mine ? \"\" : `${who(m.from, o.agentName)} · `}${isPending && slow ? \"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 = {}) =>\n h(RN.View, { style: { backgroundColor: raised, borderRadius: r.card, padding: 16, ...surf, ...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: r.field, paddingHorizontal: 14, backgroundColor: hu.def } },\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: r.field, backgroundColor: raised, ...surf } });\n // Home's top like the site's: \"Hi, Lukas 👋\" over the greeting in gray (without its own \"Hi!\", said above).\n const first = client.getUser()?.name?.trim().split(/\\s+/)[0];\n const rest = greeting.replace(/^(hi|hello|hey|hallo)( there)?\\s*[!,.]*\\s*/i, \"\").trim() || \"How can we help you today?\";\n const hero = (fg: string, sub: string) =>\n h(\n RN.Text,\n { key: \"hero\", accessibilityRole: \"header\", style: { color: fg, fontSize: 25, fontWeight: \"600\", letterSpacing: -0.6, lineHeight: 30 } },\n first ? `Hi, ${first} 👋\\n` : \"Hi there 👋\\n\",\n h(RN.Text, { style: { color: sub, fontWeight: \"500\" } }, rest),\n );\n\n const last = thread?.messages.at(-1);\n const showHelp = helpOn && arts.any !== false;\n let content: ReactNode;\n if (view === \"home\") {\n const cards = [\n // \"Ask a question\": the words go into the chat's field and are sent as the chat opens.\n h(\n RN.View,\n { key: \"ask\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, height: 48, borderRadius: 24, paddingLeft: 18, paddingRight: 6, backgroundColor: hu.surface, ...surf } },\n k.field({ value: body, onChange: setBody, placeholder: \"Ask a question\", max: 4000, style: { flex: 1, borderWidth: 0, paddingHorizontal: 0, backgroundColor: \"transparent\" } }),\n h(\n RN.Pressable,\n {\n onPress: () => {\n setView(\"messages\");\n if (body.trim()) void send();\n },\n accessibilityRole: \"button\",\n accessibilityLabel: \"Send\",\n style: { width: 36, height: 36, borderRadius: 18, alignItems: \"center\", justifyContent: \"center\", backgroundColor: body.trim() ? p.accent : hu.def },\n },\n glyph(\"up\", body.trim() ? ink : hu.muted, 18),\n ),\n ),\n last\n ? h(\n RN.Pressable,\n { key: \"recent\", onPress: () => setView(\"messages\"), accessibilityRole: \"button\" },\n card([\n h(\n RN.View,\n { key: \"r\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 10 } },\n title ? teamMark(title, alpha(p.accent, 0.16), p.accent, 26) : null,\n h(RN.View, { style: { flex: 1, gap: 1 } }, h(RN.Text, { numberOfLines: 1, style: { color: hu.fg, fontSize: 14, fontWeight: \"500\" } }, last.body || (last.attachments?.length ? `Sent ${last.attachments.length === 1 ? last.attachments[0].name : `${last.attachments.length} files`}` : \"\")), k.muted(`${last.from === \"visitor\" ? \"You\" : who(last.from, o.agentName)} · ${timeAgo(last.at)}`, { fontSize: 11.5 })),\n chat.unseen.length\n ? h(RN.View, { style: { width: 8, height: 8, borderRadius: 4, backgroundColor: p.danger } })\n : glyph(\"next\", p.muted, 14),\n ),\n ], { paddingVertical: 10, paddingHorizontal: 12 }),\n )\n : null,\n showHelp ? card([searchRow(() => setView(\"help\")), ...(arts.list ?? []).slice(0, 4).map(row)], { padding: 8, gap: 2 }) : null,\n ];\n content = plain\n ? h(\n RN.ScrollView,\n { key: \"home\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 24, gap: 12 }, keyboardShouldPersistTaps: \"handled\" },\n h(RN.View, { key: \"top\", style: { paddingHorizontal: 6, paddingBottom: 10 } }, hero(p.fg, p.muted)),\n ...cards,\n )\n : 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 } }, hero(ink, alpha(ink, 0.8))),\n h(RN.View, { style: { marginTop: -48, paddingHorizontal: 16, gap: 12 } }, ...cards),\n );\n } else if (view === \"messages\")\n content = h(\n RN.View,\n { key: \"messages\", style: { flex: 1, backgroundColor: hu.bg } },\n h(\n RN.ScrollView,\n { ref: scroll, style: { flex: 1 }, contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 16, gap: 12 } },\n // The greeting opens an empty chat only, never above the visitor's first words (2026-10-30).\n !thread?.messages.length && !pending ? bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }) : null,\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: 6, gap: 8 } },\n chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,\n // Photos picked for the next message, each with a way to take it out again.\n photos.length\n ? h(\n RN.View,\n { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 10, paddingTop: 6, paddingHorizontal: 2 } },\n ...photos.map((f) =>\n h(\n RN.View,\n { key: f.key, style: { width: 56, height: 56 } },\n h(RN.Image, { source: { uri: f.uri }, resizeMode: \"cover\", accessibilityLabel: f.id ? f.name : `${f.name}, uploading`, style: { width: 56, height: 56, borderRadius: Math.max(4, r.card - 4), backgroundColor: p.soft, opacity: f.id ? 1 : 0.5 } }),\n h(\n RN.Pressable,\n {\n onPress: () => setPhotos((list) => list.filter((x) => x.key !== f.key)),\n accessibilityRole: \"button\",\n accessibilityLabel: `Remove ${f.name}`,\n hitSlop: 8,\n style: { position: \"absolute\", top: -7, right: -7, width: 22, height: 22, borderRadius: 11, borderWidth: 2, borderColor: p.bg, backgroundColor: p.fg, alignItems: \"center\", justifyContent: \"center\" },\n },\n glyph(\"cross\", p.bg, 10),\n ),\n ),\n ),\n )\n : null,\n // The message field on top, the paperclip (when the app has expo-image-picker) and the send button under it.\n h(\n RN.View,\n { style: { gap: 2, borderRadius: 20, paddingTop: 10, paddingBottom: 6, paddingRight: 6, paddingLeft: 16, backgroundColor: hu.surface, ...surf } },\n // The optional email: the box's first line, under a hairline the message follows.\n needEmail\n ? k.field({\n value: email,\n onChange: setEmail,\n placeholder: \"Email for our reply (optional)\",\n email: true,\n max: 200,\n style: { minHeight: 0, marginRight: 10, marginBottom: 4, paddingHorizontal: 0, paddingTop: 0, paddingBottom: 8, borderWidth: 0, borderRadius: 0, borderBottomWidth: 1, borderBottomColor: emailOk ? p.line : p.danger, backgroundColor: \"transparent\", fontSize: 13.5 },\n })\n : null,\n k.field({ value: body, onChange: setBody, placeholder: \"Write a message…\", multiline: true, max: 4000, style: { minHeight: 28, maxHeight: 120, borderWidth: 0, paddingHorizontal: 0, paddingVertical: 4, backgroundColor: \"transparent\" } }),\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", marginLeft: -8 } },\n imagePicker?.launchImageLibraryAsync\n ? h(\n RN.Pressable,\n { onPress: () => void pickPhotos(), disabled: !!pending, accessibilityRole: \"button\", accessibilityLabel: \"Attach a photo or screenshot\", hitSlop: 6, style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\" } },\n glyph(\"clip\", hu.muted, 19),\n )\n : null,\n h(RN.View, { style: { flex: 1 } }),\n h(\n RN.Pressable,\n {\n onPress: () => void send(),\n disabled: !canSend,\n accessibilityRole: \"button\",\n accessibilityLabel: \"Send\",\n style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\", backgroundColor: canSend ? p.accent : hu.def },\n },\n glyph(\"up\", canSend ? ink : hu.muted, 18),\n ),\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: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 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: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 32 } },\n h(ArticleView, { client, p, id: view.article, onAsk: () => setView(\"messages\") }),\n );\n\n const current = typeof view === \"string\" ? view : \"help\";\n // The tabs as HeroUI's Tabs: a gray pill with the current tab on a raised white one.\n const tab = (v: \"home\" | \"messages\" | \"help\", name: string, icon: keyof typeof GLYPH, badge = 0) => {\n const on = current === v;\n return h(\n RN.Pressable,\n {\n key: v,\n onPress: () => setView(v),\n accessibilityRole: \"tab\",\n accessibilityLabel: name,\n accessibilityState: { selected: on },\n // Only the open tab carries its name; the others are icons, so the bar fits a narrow phone.\n style: { ...(on ? { flex: 1 } : { width: 48 }), flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\", gap: 6, height: 36, borderRadius: 18, ...(on ? { backgroundColor: hu.segment, ...segLift } : {}) },\n },\n glyph(icon, on ? hu.fg : hu.muted, 17),\n on ? k.text(name, { fontSize: 13.5, fontWeight: \"500\", color: hu.fg }) : null,\n badge ? h(RN.View, { style: { position: \"absolute\", top: 7, right: 12, width: 8, height: 8, borderRadius: 4, backgroundColor: p.danger } }) : null,\n );\n };\n // The head is only the close button (and the way back on an article), on the ground of what is below it.\n const onAccent = view === \"home\" && !plain;\n const ground = onAccent ? p.accent : hu.bg;\n const back = (to: MsgView, label: string) =>\n h(\n RN.Pressable,\n { key: \"back\", onPress: () => setView(to), accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 10, style: { width: 32, height: 32, alignItems: \"center\", justifyContent: \"center\", transform: [{ rotate: \"180deg\" }] } },\n glyph(\"next\", hu.fg, 18),\n );\n const head = h(\n RN.View,\n { key: \"head\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingLeft: 12, paddingRight: 12, paddingTop: 12, paddingBottom: 6, backgroundColor: ground } },\n typeof view !== \"string\"\n ? back(\"help\", \"All articles\")\n : view === \"messages\"\n ? back(\"home\", \"Back to home\")\n : view === \"home\" && (o.logo || title)\n ? o.logo\n ? h(RN.Image, { key: \"logo\", source: { uri: o.logo }, accessibilityIgnoresInvertColors: true, resizeMode: \"contain\", style: { height: 28, aspectRatio: 1, maxWidth: 132, borderRadius: 8, marginLeft: 4 } })\n : teamMark(title, alpha(p.accent, 0.16), p.accent, 28)\n : null,\n // In the chat: who answers, in the middle.\n view === \"messages\" && title\n ? h(\n RN.View,\n { style: { flex: 1, flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\", gap: 8 } },\n teamMark(title, alpha(p.accent, 0.16), p.accent, 28),\n h(RN.Text, { numberOfLines: 1, style: { flexShrink: 1, color: hu.fg, fontSize: 15, fontWeight: \"600\" } }, title),\n )\n : h(RN.View, { style: { flex: 1 } }),\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\", onAccent ? ink : p.muted, 18)),\n );\n // One quiet line above the tab bar, unless the plan lets the product hide it.\n const powered = brand\n ? h(\n RN.View,\n { key: \"brand\", style: { paddingTop: 2, paddingBottom: 6, alignItems: \"center\", backgroundColor: hu.bg } },\n h(\n RN.Text,\n { onPress: () => void RN.Linking.openURL(BRAND_URL).catch(() => undefined), accessibilityRole: \"link\", hitSlop: 8, style: { color: p.muted, fontSize: 11.5 } },\n \"Powered by \",\n h(RN.Text, { style: { fontWeight: \"600\" } }, \"MRRocket\"),\n ),\n )\n : null;\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: hu.bg } },\n head,\n content,\n view === \"messages\" ? null : h(\n RN.View,\n { key: \"tabs\", accessibilityRole: \"tablist\", style: { flexDirection: \"row\", marginHorizontal: 12, marginTop: 6, marginBottom: 6, padding: 4, borderRadius: 22, backgroundColor: hu.surface } },\n tab(\"home\", \"Home\", \"home\"),\n tab(\"messages\", \"Messages\", \"chat\", chat.unseen.length),\n showHelp ? tab(\"help\", \"Help\", \"help\") : null,\n ),\n powered,\n h(RN.View, { style: { height: 16 } }),\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 corners: look.corners,\n header: look.header,\n logo: look.logo,\n agentName: look.agentName,\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 r = CORNERS[options.corners ?? \"round\"];\n // The chat button's place: top, middle or bottom, and left, center or right.\n const [edge, side] = (options.position ?? \"bottom-right\").split(\"-\") as [\"top\" | \"middle\" | \"bottom\", \"left\" | \"center\" | \"right\"];\n const place: Style = {\n ...(edge === \"top\" ? { top: 60 } : edge === \"bottom\" ? { bottom: 34 } : { top: 0, bottom: 0, justifyContent: \"center\" }),\n ...(side === \"left\" ? { left: 20 } : side === \"right\" ? { right: 20 } : { left: 0, right: 0, alignItems: \"center\" }),\n };\n const launcher = options.launcher\n ? h(\n RN.View,\n { key: \"launcher\", pointerEvents: \"box-none\", style: { position: \"absolute\", ...place } },\n h(\n RN.Pressable,\n {\n onPress: () => openAt(unseen ? \"messages\" : \"home\"),\n accessibilityRole: \"button\",\n accessibilityLabel: unseen ? `Open chat, ${unseen} new` : \"Open chat\",\n style: {\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 )\n : null;\n // The banner: who answered and the first lines, on a card with a soft shadow.\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: {\n position: \"absolute\",\n top: 54,\n left: 16,\n right: 16,\n gap: 3,\n backgroundColor: p.bg === DARK.bg ? p.soft : p.bg,\n borderRadius: r.card + 2,\n paddingHorizontal: 16,\n paddingVertical: 13,\n shadowColor: \"#101218\",\n shadowOpacity: 0.14,\n shadowRadius: 18,\n shadowOffset: { width: 0, height: 8 },\n elevation: 6,\n },\n },\n k.muted(`${who(banner.from, options.agentName)}${unseen > 1 ? ` · ${unseen} new` : \"\"}`, { fontWeight: \"600\", fontSize: 12 }),\n h(RN.Text, { numberOfLines: 3, style: { color: p.fg, fontSize: 15, lineHeight: 20 } }, banner.body),\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, brand: look?.branding !== false }) : null,\n );\n};\n"],"mappings":"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","names":["import_react","h","h","who","ended","same","who","text","h","clip","who","options","import_react","h","_","text","m","v","RN","h","import_react","RN","text","h","who","svg","r","RN","text"]}
|
|
1
|
+
{"version":3,"sources":["../../src/native/index.tsx","../../src/i18n.ts","../../src/core.ts","../../src/onboarding-state.ts","../../src/flows.ts","../../src/onboarding-report.ts","../../src/identity.ts","../../src/api-client.ts","../../src/batch.ts","../../src/errors.ts","../../src/paywall.ts","../../src/rage.ts","../../src/native/recorder.ts","../../src/referral.ts","../../src/native/client.ts","../../src/native/flows-view.ts","../../src/icons.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 { onWords, setLocale, wordsVersion } from \"../i18n\";\nimport { type CockpitConfig, SDK_VERSION, type VariantId } from \"../core\";\nimport type { CancelFlowOptions, CancelFlowResult } from \"../flows\";\nimport type { OnboardingReport, OnboardingReportOptions } from \"../onboarding-report\";\nimport { type UseOnboarding, useOnboardingItem, useReportWith } from \"../onboarding-state\";\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, FlowMedia, TourPlacement, TaskOpens, FlowIcon, FinishAnimation, OnboardingQuestion, OnboardingItemState } from \"../flows\";\nexport type { UseOnboarding } from \"../onboarding-state\";\nexport type { OnboardingReport, OnboardingReportOptions, OnboardingReportType } from \"../onboarding-report\";\nexport { MRRocketFlows, type NativeAppearance };\nexport type { PaywallConfig, PaywallOptions, PaywallPage, PaywallPlan, PaywallResult } from \"../paywall\";\nexport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, useFeedback, useMessenger, type NativeFeedbackOptions, type NativeMessengerOptions };\nexport type { ChatMessage, ChatThread, FeedbackPost, SurveyDefinition } from \"../api-client\";\nexport type { IdentifyOptions } from \"../identity\";\nexport type { KeyValueStorage, MRRocketClient, MRRocketOptions, NativeConsent, NativePushResult, NativePushStatus, NativeReviewResult, RegisterForPushOptions } from \"./client\";\nexport { SDK_VERSION, activeRouteName };\n/** 0.21.0: the language of the SDK's words, for an app with its own language switch. */\nexport { currentLocale, setLocale } from \"../i18n\";\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 // New words or another language: the dialogs and widgets below draw again.\n useSyncExternalStore(onWords, wordsVersion, wordsVersion);\n useEffect(() => {\n if (options.locale) setLocale(options.locale);\n }, [options.locale]);\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, paywall: client.paywall, 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/**\n * The paywalls built in MRRocket › Paywalls, page by page; the provider draws them. The last page hands the chosen plan\n * to `onPurchase`, where your code buys it. MRRocket never takes a payment.\n *\n * const paywall = usePaywall();\n * paywall.open(\"onboarding_end\", { plans: storePlans, onPurchase: (plan) => Purchases.purchasePackage(packages[plan.id]) });\n */\nexport const usePaywall = (): { open: MRRocketClient[\"openPaywall\"] } => {\n const client = useClient();\n return { open: client.openPaywall };\n};\n\n/**\n * 0.16.0: store reviews from a review request in MRRocket › Reviews › Requests (needs `expo-store-review`). Call\n * `request()` at the moment the request names (after the third finished challenge, a 7-day streak …): MRRocket says\n * whether this signed-in person may be asked now, and the App Store's or Google Play's own rating dialog opens.\n *\n * const review = useReview();\n * if (challengesDone === 3) void review.request();\n */\nexport const useReview = (): { request: MRRocketClient[\"requestReview\"] } => {\n const client = useClient();\n return { request: client.requestReview };\n};\n\n/**\n * `start(id?)` starts an onboarding flow now (the first live one without an id), whatever its trigger. 0.18.0: with an\n * id, also the item you draw yourself (\"Shown by: your code\" in MRRocket): `item`, `steps` (each with `done`), `done`,\n * `complete(stepId)`, `dismiss()` and `answer(question, value)`; MRRocket still counts it and keeps the answers on the\n * contact.\n *\n * const { item, steps, done, complete } = useOnboarding(\"flow_123\");\n * if (!item || done) return null;\n */\nexport const useOnboarding = (id?: string): UseOnboarding => {\n const client = useClient();\n return useOnboardingItem(client.flows, id, client.startOnboarding);\n};\n\n/**\n * 0.22.0: for an onboarding that lives in your own code. Nothing to set up in MRRocket: the first report makes the item\n * under Onboarding, and MRRocket shows who saw each step and what they answered. It follows the person's consent.\n *\n * const report = useOnboardingReport(\"Welcome questions\", { order: [\"goal\", \"role\"] });\n * report.saw(\"goal\", \"What brings you here?\");\n * report.answered(\"goal\", \"dream\", \"Dream game\");\n */\nexport const useOnboardingReport = (name: string, options?: OnboardingReportOptions): OnboardingReport => useReportWith(useClient().track, name, options);\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 SDK's own words in the visitor's language. English is the source: `t(\"Send\")` answers the translation the config\n * brought, or \"Send\". Plurals are separate source words (\"1 reply\", \"{n} replies\"), never glued together. Every literal\n * passed to `t` and `tf` is listed in words.ts for the server (scripts/check-words.mjs keeps the two equal).\n *\n * The state sits on `globalThis` because the script tag's files (sdk.js, sdk-flows.js, sdk-messenger.js) are separate\n * bundles: the words sdk.js read must reach the dialogs it loads later. Only the browser and the app write to it: on\n * a server this object is shared by all requests.\n */\ninterface Shared {\n words?: Record<string, string>;\n /** The language the server chose, like \"de\". */\n lang?: string;\n /** The app's own choice (`setLocale`, the `locale` option). */\n locale?: string;\n /** React Native: the phone's language. */\n device?: string;\n version: number;\n onWords: Set<() => void>;\n onLocale: Set<() => void>;\n}\n\nconst g = globalThis as unknown as { __mrrocketI18n?: Shared };\nconst s: Shared = (g.__mrrocketI18n ??= { version: 0, onWords: new Set(), onLocale: new Set() });\n\nconst tell = (listeners: Set<() => void>) => {\n for (const fn of [...listeners]) {\n try {\n fn();\n } catch {\n // One renderer must not stop another.\n }\n }\n};\n\n/** The translation, or the English word. */\nexport const t = (word: string): string => s.words?.[word] || word;\n\n/** The same, then fills `{n}`-style placeholders. */\nexport const tf = (word: string, vars: Record<string, string | number>): string => t(word).replace(/\\{(\\w+)\\}/g, (all, k: string) => (k in vars ? String(vars[k]) : all));\n\n/** Replaces the dictionary; `lang` is the language it is in. */\nexport const setWords = (words?: Record<string, string>, lang?: string) => {\n const same = s.lang === lang && JSON.stringify(s.words ?? {}) === JSON.stringify(words ?? {});\n s.words = words;\n s.lang = lang;\n if (same) return;\n s.version++;\n tell(s.onWords);\n};\n\n/** \"de_AT\" reads as \"de-AT\"; something that is no language tag counts as none (dates would throw on it). */\nconst tidy = (locale?: string) => {\n const tag = locale?.trim().replace(/_/g, \"-\");\n if (!tag) return undefined;\n try {\n return Intl.getCanonicalLocales(tag)[0];\n } catch (e) {\n return e instanceof RangeError ? undefined : tag;\n }\n};\n\n/** An app with its own language switch says the language here; undefined goes back to the device's. Re-reads the config. */\nexport const setLocale = (locale?: string) => {\n const next = tidy(locale);\n if (next === s.locale) return;\n s.locale = next;\n s.version++;\n tell(s.onWords);\n tell(s.onLocale);\n};\n\n/** React Native: the phone's language, used unless the app chose one. */\nexport const setDeviceLocale = (locale?: string) => {\n s.device = tidy(locale);\n};\n\n/** The app's choice, else the phone's (React Native), else the browser's. */\nexport const currentLocale = (): string | undefined => s.locale ?? s.device ?? ((typeof navigator !== \"undefined\" && navigator.language) || undefined);\n\n/** `&lang=de-AT` for a URL that already has a query, or nothing while no language is known. */\nexport const langParam = () => {\n const l = currentLocale();\n return l ? `&lang=${encodeURIComponent(l)}` : \"\";\n};\n\n/** The language the words on screen are in, for `lang` on the SDK's own root elements. */\nexport const wordsLang = () => s.lang;\n\n/** Grows whenever the words or the language change. */\nexport const wordsVersion = () => s.version;\n\n/** Runs when the words or the language changed: what is on screen draws again. Returns how to stop. */\nexport const onWords = (fn: () => void) => {\n s.onWords.add(fn);\n return () => {\n s.onWords.delete(fn);\n };\n};\n\n/** Runs when the app chose another language: the config is read again. Returns how to stop. */\nexport const onLocale = (fn: () => void) => {\n s.onLocale.add(fn);\n return () => {\n s.onLocale.delete(fn);\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\";\nimport type { PaywallConfig } from \"./paywall\";\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.22.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 /** The language the server chose for the words below, like \"de\" (`lang` on the request). SDK 0.21.0+. */\n lang?: string;\n /** The SDK's own words: English source word to translation (see words.ts). Absent for English. SDK 0.21.0+. */\n words?: Record<string, 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 /** The product's brand color (\"#rrggbb\") for the onboarding dialogs when the app passes no accent. SDK 0.18.0+. */\n onboardingAccent?: string;\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 /** Published paywalls with their pages, per placement (MRRocket › Conversion › Paywalls), for `paywall.open()`. SDK 0.14.0+. */\n paywalls?: PaywallConfig[];\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 * 0.18.0: `useOnboarding(id)` for an onboarding item the app draws itself (\"Shown by: your code\" in MRRocket): its\n * content and the person's progress, and the calls that report what they did. Shared by the Next.js provider and React\n * Native (only React here). The SDK draws nothing for such an item and never starts it; what the app reports still\n * reaches MRRocket (who saw it, who finished it, the answers on the contact), and the item after it follows as usual.\n *\n * const { item, steps, done, complete, dismiss, answer } = useOnboarding(\"flow_123\");\n * if (!item || done) return null;\n * return steps.map((s) => <Task key={s.id} title={s.title} done={s.done} onPress={() => complete(s.id)} />);\n */\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { FlowsController, OnboardingFlow, OnboardingItemState } from \"./flows\";\nimport { type OnboardingReport, type OnboardingReportOptions, createOnboardingReport } from \"./onboarding-report\";\n\nexport interface UseOnboarding {\n /** The item as MRRocket published it, or null while the config is loading, or when it is not live. */\n item: OnboardingFlow | null;\n /** Its steps (a tour's steps, a checklist's tasks, the questions), each with `done` (and a question's `answer`). */\n steps: OnboardingItemState[\"steps\"];\n /** Every step is done. */\n done: boolean;\n /** The person closed it. */\n dismissed: boolean;\n /** Its moment has come for this person (the trigger MRRocket set, and who it is for). */\n eligible: boolean;\n /** Marks a step done (a tour step, a task). */\n complete(stepId: string): void;\n /** The person closed it; the item after it follows. */\n dismiss(): void;\n /** Answers a question (its step id or its key) with an option's id or a text; it is kept on the contact. */\n answer(question: string, value: string): void;\n /** Starts an item the SDK draws (the first live one without an id). */\n start(id?: string): boolean;\n}\n\nconst none: OnboardingItemState[\"steps\"] = [];\n\n/** The hook behind `useOnboarding` on both platforms. */\nexport const useOnboardingItem = (flows: FlowsController | null | undefined, id: string | undefined, start: (id?: string) => boolean): UseOnboarding => {\n const [state, setState] = useState<OnboardingItemState | null>(() => (flows && id ? flows.onboarding.item(id) : null));\n useEffect(() => {\n if (!flows || !id) {\n setState(null);\n return;\n }\n const up = () => {\n const s = flows.onboarding.item(id);\n setState(s);\n // Asked for by the app: counted as seen (started, and its first open steps), once per page.\n if (s && !s.done && !s.dismissed) flows.onboarding.seen(id);\n };\n up();\n return flows.subscribe(up);\n }, [flows, id]);\n return useMemo(\n () => ({\n item: state?.item ?? null,\n steps: state?.steps ?? none,\n done: !!state?.done,\n dismissed: !!state?.dismissed,\n eligible: !!state?.eligible,\n complete: (stepId: string) => {\n if (flows && id) flows.onboarding.complete(id, stepId);\n },\n dismiss: () => {\n if (flows && id) flows.onboarding.dismissItem(id);\n },\n answer: (question: string, value: string) => {\n if (flows && id) flows.onboarding.answerItem(id, question, value);\n },\n start,\n }),\n [state, flows, id, start],\n );\n};\n\n/** 0.22.0: the hook behind `useOnboardingReport` on both platforms: one report per name and options. */\nexport const useReportWith = (track: (event: string, props?: Record<string, unknown>) => void, name: string, options?: OnboardingReportOptions): OnboardingReport => {\n const key = JSON.stringify(options ?? null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => createOnboardingReport(track, name, options), [track, name, key]);\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; since 0.17.0 a tour a checklist task started records `{action: \"started\", from}` with\n * the checklist's id; since 0.18.0 a question records `{kind: \"question\", action: \"completed\", question, answer,\n * label}` (the question's key, the option's id or the typed text, the option's words), which MRRocket keeps on the\n * contact, and a checklist task that opens something `{action: \"opened\", opens}`.\n * - `$inapp` `{message, journey, action: \"shown\" | \"clicked\" | \"dismissed\"}`; the journey moves the person on.\n */\nimport type { CockpitConfig } from \"./core\";\nimport { currentLocale, t, tf } from \"./i18n\";\n\nexport const CANCEL_EVENT = \"$cancel_flow\";\nexport const ONBOARDING_EVENT = \"$onboarding\";\nexport const INAPP_EVENT = \"$inapp\";\n/** 0.16.0: the app asked the store's rating dialog for a review request (or found none on the device). */\nexport const REVIEW_EVENT = \"$review_prompt\";\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/** 0.15.0: a second question after an answer (\"What would be a fair price?\"); no answers means a free text. */\nexport interface CancelFollowUp {\n question: string;\n /** The choices, in order; empty for a free text. What is recorded and what rules compare, whatever the language. */\n answers: string[];\n /** 0.21.0: what each choice says in the visitor's language, parallel to `answers`; shown instead of them. */\n answerLabels?: string[];\n}\n\n/**\n * 0.15.0: a different offer for some customers of one answer. Every condition that is set must hold; the first rule\n * that matches wins, else the answer's own offer. `offer: null` means no offer (straight to the confirmation).\n */\nexport interface CancelRule {\n when: {\n /** The follow-up's answer, as written. */\n answer?: string;\n /** The customer's plan: its id or name as MRRocket knows it from the payment provider (any of a list). */\n plan?: string | string[];\n /** A customer for fewer than this many months. */\n tenureUnder?: number;\n /** A customer for at least this many months. */\n tenureOver?: number;\n };\n offer: CancelOffer | null;\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 /** 0.15.0: the follow-up question per answer id. */\n followUps?: Record<string, CancelFollowUp>;\n /** 0.15.0: the rules per answer id, checked in order before its offer. */\n rules?: Record<string, CancelRule[]>;\n /** 0.15.0: what one answer offers after its first offer was declined. */\n second?: 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\n/** \"question\" (0.18.0): one question of a Questions item, a slide of its window. */\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\" | \"question\";\n\n/**\n * 0.18.0: what a checklist task opens. `page`: a path or address on the web, a deep link (`myapp://…`) or a screen name\n * in an app, handed to the app's `onNavigate` when it passes one; `tour` / `modal`: another item of the config, after\n * which the checklist comes back; `code`: the app's `onTask(taskId, item)`.\n */\nexport type TaskOpens = { kind: \"page\"; target: string } | { kind: \"tour\"; id: string } | { kind: \"modal\"; id: string } | { kind: \"code\" };\n\n/**\n * 0.18.0: a small picture beside a checklist task or above a modal's or the questions' heading: one of the SDK's own\n * line icons (`FLOW_ICON_NAMES`, icons.ts), an emoji, or a picture (http(s)).\n */\nexport type FlowIcon = { kind: \"builtin\"; name: string } | { kind: \"emoji\"; value: string } | { kind: \"image\"; url: string };\n\n/** 0.18.0: what plays when someone finishes a checklist, a tour or the questions. */\nexport type FinishAnimation = \"none\" | \"confetti\" | \"fireworks\" | \"stars\";\n\n/**\n * 0.18.0: one question of a Questions item: one choice of 2 to 6 options, or a short text. 0.21.0: a number scale, an\n * \"Other\" with the person's own words, and a Skip button. An older app shows a scale as a text field, leaves \"Other\"\n * out, and offers no Skip (its close button still ends the window).\n */\nexport interface OnboardingQuestion {\n /** The answer's name on the contact (`onboarding.<key>`) and in \"People who answered …\". */\n key: string;\n type: \"choice\" | \"text\" | \"scale\";\n /** Choice: the options, in order; `id` is what is stored, `label` what people read. */\n options?: { id: string; label: string }[];\n /** Text: the field's hint. */\n placeholder?: string;\n /** 0.21.0, choice: one more option where people type their own words, stored as `other:<words>`. */\n other?: boolean;\n /** 0.21.0: the words of that option; \"Other\" when unset. */\n otherLabel?: string;\n /** 0.21.0, scale: the lowest and highest number, and the words under both ends. */\n min?: number;\n max?: number;\n lowLabel?: string;\n highLabel?: string;\n /** 0.21.0: people may go on without answering. */\n optional?: boolean;\n /** 0.21.0: the words of that button; \"Skip\" when unset. */\n skipLabel?: string;\n}\n\n/** 0.17.0: where a tour bubble sits next to its element; \"auto\" (and no value) puts it below, else above, as before. */\nexport type TourPlacement = \"auto\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n\n/**\n * 0.17.0: a picture or a video above a tour step's or a modal's text. A video is a YouTube, Vimeo or Loom link (shown\n * through their privacy-friendly players, see `videoEmbed`) or a video file (mp4, webm).\n */\nexport interface FlowMedia {\n kind: \"image\" | \"video\";\n url: string;\n alt?: string;\n}\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 /** 0.17.0, tour steps: which side of the element the bubble takes (flips when there is no room). */\n placement?: TourPlacement;\n /** 0.17.0, tour steps and modals: a picture or a video above the text. */\n media?: FlowMedia;\n /** 0.17.0, modals: where the button goes (http(s) or a path of the app). */\n url?: string;\n /** 0.17.0, checklist items: the id of a tour (another flow) the item starts; finishing the tour ticks the item. */\n startsTour?: string;\n /** 0.18.0, checklist items: what the task opens (read before `startsTour`, which MRRocket still sends for a tour). */\n opens?: TaskOpens;\n /** 0.18.0, checklist items: the task's icon. */\n icon?: FlowIcon;\n /** 0.18.0, question steps: the question (the step's `title` is what people read). */\n question?: OnboardingQuestion;\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 /** A checklist's heading; for tours and modals the name MRRocket knows them by. */\n name: string;\n /**\n * When it starts: an event's words (\"Signed up\", \"First export\"), \"First launch\" / \"First visit\", since 0.17.0 a page\n * of the app (\"/settings\", \"/projects/*\"), or \"From a checklist\" (only a checklist task starts it).\n */\n trigger: string;\n /**\n * 0.17.0: \"signed_in\" starts it on its own only for someone the app identified. 0.18.0: \"answered\" only for someone\n * who gave `answered.option` to the question `answered.question` (its key).\n */\n audience?: \"signed_in\" | \"answered\";\n /** 0.18.0: with `audience: \"answered\"`, the question's key and the option's id (or the typed text). */\n answered?: { question: string; option: string };\n /** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */\n steps: OnboardingStep[];\n /** 0.18.0: the icon above a modal's or the questions' heading. */\n icon?: FlowIcon;\n /** 0.18.0: what plays when the person finishes it (a checklist, a tour, the questions). */\n finish?: FinishAnimation;\n /**\n * 0.18.0: \"code\": the app draws it itself (`useOnboarding(id)`, `mrrocket.onboarding.get(id)`); the SDK draws\n * nothing for it, never starts it, and still records what the app reports. Such an item's `trigger` is\n * \"From your code\" (older versions never start it).\n */\n shownBy?: \"code\";\n /**\n * 0.18.0: the item's real moment (read instead of `trigger`, see `momentOf`) when `trigger` is one older versions\n * never start: \"From your code\", or `NEEDS_NEWER` for questions and items that follow another or ask for an answer.\n */\n when?: string;\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 /** 0.18.0: the person's answers to onboarding questions, by the question's key (an option's id or the text). */\n answers?: Record<string, string>;\n /**\n * 0.16.0: a live review request may ask this person now. The React Native client's `requestReview()` opens the\n * store's own rating dialog (expo-store-review) and reports `$review_prompt`; websites have no store dialog.\n */\n review?: { campaign: string; store: 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 /** 0.15.0: the answer to the follow-up question. */\n answer?: 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 /** 0.15.0: the customer's plan (its id or name in your billing), for offers that depend on it. */\n plan?: string;\n /** 0.15.0: since when they pay (a date, ISO string or ms), for offers that depend on how long. */\n customerSince?: Date | string | number;\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\" | \"followup\" | \"offer\" | \"confirm\";\n flow: CancelFlowConfig;\n /** The answer picked on the survey. */\n reason?: string;\n /** 0.15.0: the follow-up question on its screen, and its answer so far. */\n followUp?: CancelFollowUp;\n answer?: string;\n offer?: CancelOffer;\n /** 0.15.0: 2 for the offer after a declined one. */\n round?: 1 | 2;\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 /** `answer` (0.18.0): a question's answer so far (an option's id or the typed text); `back`: an earlier question to go back to. */\n | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean; answer?: string; back?: boolean }\n /**\n * `tour`: the tour the item starts (0.17.0), when the config has it. `opens` (0.18.0): what tapping the task opens\n * (a tour or modal only when the config has it); `target` the item it opens.\n */\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean; tour?: OnboardingFlow; opens?: TaskOpens; target?: OnboardingFlow }[] }\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 /**\n * 0.18.0: opens what a checklist task's \"page or screen\" names (a path, an address, a deep link, a screen name).\n * The web and React Native clients pass the app's `onNavigate`, else their own default.\n */\n navigate?: (target: string) => void;\n /** 0.18.0: a checklist task that runs the app's own code (`onTask(taskId, item)`). */\n task?: (taskId: string, item: OnboardingFlow) => void;\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 /** `answer(text)`: the follow-up's choice or free text (0.15.0); `next()` moves on from the survey and the follow-up. */\n cancel: {\n pick(reason: string): void;\n answer(text: string): void;\n next(): void;\n accept(comment?: string): void;\n decline(): void;\n confirm(comment?: string): void;\n close(): void;\n };\n /**\n * `startTour(stepId)` (0.17.0): the tour a checklist item starts; the checklist comes back when it ends.\n * 0.18.0: `open(stepId)` does what the task opens (a page, a tour, a modal, the app's code); `answer(value)` picks an\n * option or types the text of the question on screen, `back()` returns to the question before. `item(id)` and the\n * calls after it are for an item the app draws itself (`shownBy: \"code\"`).\n */\n onboarding: {\n next(): void;\n check(stepId: string): void;\n dismiss(): void;\n startTour(stepId: string): boolean;\n open(stepId: string): boolean;\n answer(value: string): void;\n /** 0.21.0: goes on from an optional question without an answer. */\n skip(): void;\n back(): void;\n item(id: string): OnboardingItemState | null;\n seen(id: string): void;\n complete(id: string, stepId: string): void;\n dismissItem(id: string): void;\n answerItem(id: string, question: string, value: string): void;\n };\n message: { click(): void; dismiss(): void };\n /** 0.18.0: the animation to play now that someone finished an item (a new `key` each time), or null. */\n finale(): { kind: Exclude<FinishAnimation, \"none\">; key: string } | null;\n /** 0.18.0: the product's brand color from MRRocket, for the dialogs when the app passes no accent of its own. */\n accent(): string | undefined;\n /** 0.18.0: the person's answers to onboarding questions, by key. */\n answers(): Record<string, string>;\n}\n\n/** 0.18.0: an item the app draws itself (`shownBy: \"code\"`), with the person's progress. */\nexport interface OnboardingItemState {\n item: OnboardingFlow;\n /** Its steps (a tour's steps, a checklist's tasks, the questions), each with whether the person did it. */\n steps: (OnboardingStep & { done: boolean; answer?: string })[];\n /** Every step is done. */\n done: boolean;\n /** The person closed it. */\n dismissed: boolean;\n /** Its moment has come for this person (the trigger MRRocket set, and who it is for); your code may ignore it. */\n eligible: boolean;\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 // Read when it is shown, so it follows the visitor's language.\n get confirm() {\n return { title: t(\"Cancel your subscription?\"), body: t(\"You keep access until the end of the billing period.\"), button: t(\"Cancel subscription\") };\n },\n offersFor: \"business\",\n};\n\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/** 0.17.0: the trigger of a tour only a checklist task starts. */\nexport const FROM_CHECKLIST = \"From a checklist\";\n\n/** 0.17.0: a trigger that is a page of the app (\"/settings\", \"/projects/*\"): the flow starts when the person opens it. */\nexport const isPageTrigger = (trigger: string) => trigger.trim().startsWith(\"/\");\n\n/** 0.18.0: the trigger of an item the app draws itself (`shownBy: \"code\"`); older versions never start it. */\nexport const FROM_CODE = \"From your code\";\n\n/**\n * 0.18.0: the trigger MRRocket sends for an item older versions could not show right (questions, \"After <item> ends\",\n * \"People who answered …\"), so they never start it; its real moment is in `when`.\n */\nexport const NEEDS_NEWER = \"Needs tracking code 0.18.0\";\n\n/** An item's moment: `when` (0.18.0) where MRRocket sent one, else its trigger. */\nexport const momentOf = (f: Pick<OnboardingFlow, \"trigger\" | \"when\">) => f.when ?? f.trigger;\n\n/** A \"From a checklist\" tour (and an item the app draws, 0.18.0) never starts on its own. */\nconst manual = (trigger: string) => eventSlug(trigger) === \"from_a_checklist\" || eventSlug(trigger) === \"from_your_code\" || eventSlug(trigger) === eventSlug(NEEDS_NEWER);\n\n/** 0.18.0: the trigger \"after:<item id>\": the item starts once that item ended (finished or closed). */\nexport const AFTER_PREFIX = \"after:\";\n\n/** The item an \"after:<id>\" trigger follows, or null. */\nexport const afterOf = (trigger: string | undefined) => {\n const t = (trigger ?? \"\").trim();\n return t.toLowerCase().startsWith(AFTER_PREFIX) ? t.slice(AFTER_PREFIX.length).trim() || null : null;\n};\n\n/** 0.18.0: what a task opens; a 0.17.0 `startsTour` reads as opening that tour. */\nexport const opensOf = (step: Pick<OnboardingStep, \"opens\" | \"startsTour\">): TaskOpens | undefined =>\n step.opens ?? (step.startsTour ? { kind: \"tour\", id: step.startsTour } : undefined);\n\n/** 0.21.0: how a choice answer in the person's own words starts. */\nexport const OTHER_PREFIX = \"other:\";\n\n/** 0.21.0: the numbers of a scale question, low to high. */\nexport const scaleOf = (q: OnboardingQuestion | undefined) => {\n const min = q?.min ?? 0;\n const max = q?.max ?? 10;\n return Array.from({ length: Math.max(0, Math.min(max - min, 20) + 1) }, (_, i) => min + i);\n};\n\n/**\n * 0.18.0: a usable answer to a question: one of its options' ids, or a text of 1 to 500 characters. 0.21.0: the words\n * of \"Other\", or a number of the scale.\n */\nexport const answerOk = (q: OnboardingQuestion | undefined, value: string | undefined) => {\n if (!q || value == null) return false;\n if (q.type === \"choice\") {\n if (q.other && value.startsWith(OTHER_PREFIX)) return value.slice(OTHER_PREFIX.length).trim().length > 0;\n return (q.options ?? []).some((o) => o.id === value);\n }\n if (q.type === \"scale\") return scaleOf(q).some((n) => String(n) === value);\n return value.trim().length > 0 && value.length <= 500;\n};\n\n/** The option's words for an answer (a text answer is its own words, \"Other\" the words typed, a number itself). */\nexport const answerLabel = (q: OnboardingQuestion | undefined, value: string) => {\n if (q?.type !== \"choice\") return value.trim();\n if (q.other && value.startsWith(OTHER_PREFIX)) return value.slice(OTHER_PREFIX.length).trim();\n return q.options?.find((o) => o.id === value)?.label ?? value;\n};\n\n/**\n * 0.17.0: how a video link plays. YouTube, Vimeo and Loom through their players without tracking cookies\n * (youtube-nocookie.com, Vimeo's `dnt=1`), a file (mp4, webm, mov, or an upload in MRRocket) in a plain video element;\n * anything else is not shown. Regular expressions only, so React Native can use it too.\n */\nexport const videoEmbed = (url: string | undefined): { kind: \"iframe\" | \"file\"; src: string } | null => {\n const u = (url ?? \"\").trim();\n if (!/^https?:\\/\\//i.test(u)) return null;\n let m = u.match(/^https?:\\/\\/(?:www\\.|m\\.)?(?:youtube\\.com\\/(?:watch\\?(?:.*&)?v=|embed\\/|shorts\\/|live\\/)|youtu\\.be\\/|youtube-nocookie\\.com\\/embed\\/)([\\w-]{6,20})/i);\n if (m) return { kind: \"iframe\", src: `https://www.youtube-nocookie.com/embed/${m[1]}?rel=0` };\n m = u.match(/^https?:\\/\\/(?:www\\.|player\\.)?vimeo\\.com\\/(?:video\\/)?(\\d{4,12})/i);\n if (m) return { kind: \"iframe\", src: `https://player.vimeo.com/video/${m[1]}?dnt=1` };\n m = u.match(/^https?:\\/\\/(?:www\\.)?loom\\.com\\/(?:share|embed)\\/([\\w-]{8,64})/i);\n if (m) return { kind: \"iframe\", src: `https://www.loom.com/embed/${m[1]}` };\n if (/\\.(mp4|webm|mov|m4v)(\\?|#|$)/i.test(u) || /\\/media\\/uploads\\//.test(u)) return { kind: \"file\", src: u };\n return null;\n};\n\n/** 0.17.0: a step's picture or video when the dialogs may load it (http(s), a video they can play), else undefined. */\nexport const mediaOf = (step: Pick<OnboardingStep, \"media\">): FlowMedia | undefined => {\n const m = step.media;\n if (!m || (m.kind !== \"image\" && m.kind !== \"video\") || !/^https?:\\/\\//i.test(m.url ?? \"\")) return undefined;\n return m.kind === \"video\" && !videoEmbed(m.url) ? undefined : m;\n};\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(currentLocale(), { 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\" ? t(\"Send to the team\") : o.kind === \"pause\" ? t(\"Pause instead\") : o.kind === \"downgrade\" ? t(\"Switch plan\") : t(\"Accept offer\");\n\n/** \"3 months\". */\nexport const monthsWord = (n: number) => (n === 1 ? t(\"1 month\") : tf(\"{n} months\", { n }));\n/** \"for 3 months\". */\nexport const forMonths = (n: number) => tf(\"for {months}\", { months: monthsWord(n) });\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\n/** Whole months since a date the app passed (NaN without one, which no tenure condition holds for). */\nexport const monthsSince = (since: CancelFlowOptions[\"customerSince\"], now = Date.now()) =>\n since == null || since === \"\" ? NaN : Math.floor((now - new Date(since).getTime()) / 2_630_016_000);\n\nconst low = (x?: string) => x?.trim().toLowerCase();\n\n/** Whether a rule holds for this customer; a condition about something the app did not pass does not hold. */\nexport const ruleMatches = ({ when: w = {} }: CancelRule, c: { answer?: string; plan?: string; months: number }) =>\n (w.answer == null || low(w.answer) === low(c.answer)) &&\n (w.plan == null || [w.plan].flat().some((x) => low(x) === low(c.plan))) &&\n !(c.months >= w.tenureUnder!) &&\n !(c.months < w.tenureOver!) &&\n (w.tenureUnder == null || c.months >= 0) &&\n (w.tenureOver == null || c.months >= 0);\n\ninterface CancelRun {\n flow: CancelFlowConfig;\n options: CancelFlowOptions;\n plain: boolean;\n screen: \"survey\" | \"followup\" | \"offer\" | \"confirm\";\n reason?: string;\n answer?: string;\n /** The offer on the offer screen, which rule picked it, and which round it is. */\n offer?: CancelOffer;\n rule?: number;\n round: 1 | 2;\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 /** 0.17.0: the checklist (and its item) a running tour was started from; it comes back when the tour ends. */\n let returnTo: { flow: string; step: string } | null = null;\n /** 0.18.0: the person's answers by question key, the answers typed so far on screen (by step), and the finale. */\n const answers = new Map<string, string>();\n const drafts = new Map<string, string>();\n const celebrated = new Set<string>();\n let finaleNow: { kind: Exclude<FinishAnimation, \"none\">; key: string } | null = null;\n\n const flows = () => config?.onboarding ?? [];\n /** The items the SDK draws (0.18.0: not those the app draws itself). */\n const drawn = () => flows().filter((f) => f.shownBy !== \"code\");\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 const answersKeyOf = (pid: string | undefined) => `${PROGRESS_KEY}:answers:${pid ?? \"visitor\"}`;\n\n /** 0.18.0: an item the person just finished (not closed) plays its finish animation, once per page. */\n const celebrate = (f: OnboardingFlow) => {\n if (!f.finish || f.finish === \"none\" || f.shownBy === \"code\" || celebrated.has(f.id)) return;\n const p = progress.get(f.id);\n if (!p || p.dismissed || walkLine(f, nodesOf(f), p, false).at !== \"end\") return;\n celebrated.add(f.id);\n finaleNow = { kind: f.finish, key: `${f.id}:${now()}` };\n };\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 (answers.size) store.set(answersKeyOf(env.personId()), JSON.stringify(Object.fromEntries(answers)));\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 {\n type: \"checklist\",\n flow,\n items: items.map((s) => {\n // 0.18.0: what the task opens; a tour or modal only when the config has it and the SDK draws it.\n const o = opensOf(s);\n const t = o && (o.kind === \"tour\" || o.kind === \"modal\") && o.id !== flow.id ? flowById(o.id) : undefined;\n const target = t && t.shownBy !== \"code\" && nodesOf(t).length ? t : undefined;\n const opens = o && (o.kind === \"page\" ? !!o.target.trim() : o.kind === \"code\" || !!target) ? o : undefined;\n return {\n step: s,\n done: p.done.has(s.id),\n ...(target && o?.kind === \"tour\" ? { tour: target } : {}),\n ...(opens ? { opens } : {}),\n ...(target ? { target } : {}),\n };\n }),\n };\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 {\n type: \"step\",\n flow,\n step,\n index: w.before,\n total: w.before + 1 + ahead,\n last: !ahead && fork < 0,\n // 0.18.0: a question's answer so far, and whether there is one before it to go back to.\n ...(step.kind === \"question\" ? { answer: drafts.get(step.id) ?? (step.question ? answers.get(step.question.key) : undefined), back: w.before > 0 } : {}),\n };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const c = cancel;\n const followUp = c.flow.followUps?.[c.reason!];\n // The dots: the survey, a follow-up, one or two offers, the confirmation.\n const f = followUp ? 1 : 0;\n const steps = c.plain ? 1 : 3 + f + (c.flow.second?.[c.reason!] ? 1 : 0);\n return {\n type: \"cancel\",\n screen: c.screen,\n flow: c.flow,\n reason: c.reason,\n ...(c.screen === \"followup\" && followUp ? { followUp, answer: c.answer } : {}),\n offer: c.screen === \"offer\" ? c.offer : undefined,\n ...(c.screen === \"offer\" ? { round: c.round } : {}),\n price: c.options.price,\n busy: c.busy,\n error: c.error,\n step: c.screen === \"survey\" ? 1 : c.screen === \"followup\" ? 2 : c.screen === \"offer\" ? 1 + f + c.round : steps,\n steps,\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) {\n const back = returnTo;\n const ended = active;\n returnTo = null;\n active = null;\n const list = back ? flowById(back.flow) : undefined;\n if (back && list) {\n // The tour a checklist item started is over: the checklist comes back, and a finished tour ticks an item\n // that has no event of its own (a closed one does not).\n const item = stepsIn(nodesOf(list)).find((s) => s.id === back.step);\n const p = prog(list.id);\n if (item && !item.event && !progress.get(ended)?.dismissed && !p.done.has(item.id)) {\n markDone(p, item.id);\n record({ flow: list.id, step: item.id, kind: \"checklist\", action: \"completed\" });\n celebrate(list);\n }\n active = list.id;\n const again = onboardingView();\n if (again) return again;\n if (!holding) active = null;\n } else if (known) {\n // 0.17.0: the next flow whose moment has come (another \"First launch\", this page's, or one of the same\n // trigger as the one that ended) follows right away.\n const was = flowById(ended);\n const after = was ? momentOf(was) : undefined;\n Promise.resolve().then(() => autoStart(after));\n }\n }\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 /**\n * 0.17.0: a flow for signed-in people starts on its own only for someone the app identified; 0.18.0: one for the\n * people who gave an answer only for them.\n */\n const allowed = (f: OnboardingFlow) =>\n f.audience === \"answered\" ? !!f.answered && answers.get(f.answered.question) === f.answered.option : f.audience !== \"signed_in\" || !!env.personId();\n\n /** 0.18.0: an \"after:<id>\" item's moment: that item ended (finished or closed), or it is not live (then like the first launch). */\n const predecessorEnded = (id: string) => {\n const g = flowById(id);\n return !g || finished(g);\n };\n\n /** Whether the item's own moment has come now (its trigger), apart from who it is for. */\n const due = (f: OnboardingFlow, trigger = momentOf(f)) => {\n const path = env.path?.();\n const pred = afterOf(trigger);\n if (pred) return predecessorEnded(pred);\n if (manual(trigger)) return false;\n if (isPageTrigger(trigger)) return path !== undefined && pageMatches(trigger, path);\n if (startsOnLoad(trigger)) return true;\n for (const e of seenEvents) if (matchesTrigger(trigger, e)) return true;\n return false;\n };\n\n /**\n * Flows whose trigger is \"the first launch\" (or, 0.17.0, the page the person is on) start once their progress is\n * known (never twice for a done flow). `after`: the trigger of a flow that just ended, whose next unfinished flow\n * follows it (onboarding items made from one older flow share its trigger).\n */\n const autoStart = (after?: string) => {\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 path = env.path?.();\n const same = after && !manual(after) ? eventSlug(after) : \"\";\n const next = drawn().find(\n (f) =>\n (afterOf(momentOf(f))\n ? predecessorEnded(afterOf(momentOf(f))!)\n : isPageTrigger(momentOf(f))\n ? path !== undefined && pageMatches(momentOf(f), path)\n : startsOnLoad(momentOf(f)) || (!!same && eventSlug(momentOf(f)) === same)) &&\n allowed(f) &&\n nodesOf(f).length &&\n !finished(f),\n );\n if (next) start(next);\n };\n\n /**\n * 0.17.0/0.18.0: a checklist task opens another item (a tour or a modal): from its first step, also when the person\n * saw or closed it before; the checklist comes back when it ends.\n */\n const openItem = (list: OnboardingFlow, stepId: string, target: OnboardingFlow) => {\n const p = prog(target.id);\n p.done.clear();\n p.at.clear();\n p.dismissed = false;\n returnTo = { flow: list.id, step: stepId };\n active = target.id;\n env.track(ONBOARDING_EVENT, { flow: target.id, action: \"started\", from: list.id });\n save();\n emit();\n };\n\n /** 0.18.0: one question answered: kept for the person (`answers`), done, and recorded with its key and words. */\n const answerStep = (flow: OnboardingFlow, step: OnboardingStep, raw: string) => {\n const q = step.question!;\n const value = q.type === \"text\" ? raw.trim().slice(0, 500) : raw.startsWith(OTHER_PREFIX) ? OTHER_PREFIX + raw.slice(OTHER_PREFIX.length).trim().slice(0, 490) : raw;\n answers.set(q.key, value);\n drafts.delete(step.id);\n markDone(prog(flow.id), step.id);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: step.id, kind: \"question\", action: \"completed\", question: q.key, answer: value, label: answerLabel(q, value) });\n celebrate(flow);\n save();\n };\n\n /** 0.18.0: something changed on an item the app draws: saved, and the next item may follow it. */\n const ended = (f: OnboardingFlow) => {\n save();\n if (finished(f)) Promise.resolve().then(() => autoStart());\n emit();\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 answers.clear();\n drafts.clear();\n handled.clear();\n active = null;\n returnTo = 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 const said = await store.get(answersKeyOf(pid));\n if (said) for (const [k, v] of Object.entries(JSON.parse(said) as Record<string, unknown>)) if (typeof v === \"string\") answers.set(k, v);\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 // 0.18.0: answers given on another device; an answer given here stays.\n for (const [k, v] of Object.entries(state.answers ?? {})) if (typeof v === \"string\" && !answers.has(k)) answers.set(k, v);\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 /** Which offer of the answer was on screen, for MRRocket to know what was saved: a rule's or the second. */\n const offerAt = (c: CancelRun) => (c.round > 1 ? { round: 2 } : c.rule! >= 0 ? { rule: c.rule } : {});\n\n /** Into the offer screen with the answer's first offer (the first rule that holds, else its own), or the confirmation. */\n const toOffer = (c: CancelRun) => {\n const who = { answer: c.answer, plan: c.options.plan, months: monthsSince(c.options.customerSince, env.now?.()) };\n const rules = c.flow.rules?.[c.reason!] ?? [];\n c.rule = rules.findIndex((r) => ruleMatches(r, who));\n c.offer = c.rule < 0 ? c.flow.offers[c.reason!] : (rules[c.rule].offer ?? undefined);\n c.round = 1;\n c.screen = c.offer ? \"offer\" : \"confirm\";\n };\n\n const result = (c: CancelRun, outcome: CancelFlowResult[\"outcome\"], comment?: string): CancelFlowResult => {\n const offer = c.screen === \"offer\" ? c.offer : 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 ...(c.answer ? { answer: c.answer } : {}),\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.answer ? { answer: r.answer } : {}),\n ...(r.offer ? { offer: r.offer.kind, ...offerAt(c) } : {}),\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 = t(\"Something went wrong. Please try again.\");\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\", round: 1, 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 // 0.17.0: a page view may be the moment of a flow with a page trigger.\n if (name === \"$pageview\") autoStart();\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 // The checklist on screen, and (0.18.0) those the app draws itself, tick their tasks by their event.\n const lists = [...(flow ? [flow] : []), ...flows().filter((f) => f.shownBy === \"code\" && f.id !== flow?.id)];\n for (const l of lists) {\n const p = prog(l.id);\n let here = false;\n for (const s of stepsIn(nodesOf(l)))\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n markDone(p, s.id);\n here = true;\n env.track(ONBOARDING_EVENT, { flow: l.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n if (here) {\n ticked = true;\n celebrate(l);\n }\n }\n if (ticked || (fresh && (flow || lists.length))) {\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 = drawn().find((f) => nodesOf(f).length && !manual(momentOf(f)) && matchesTrigger(momentOf(f), name) && allowed(f) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : drawn().find((x) => nodesOf(x).length && !manual(momentOf(x)) && !afterOf(momentOf(x)) && !finished(x));\n // An item the app draws itself (0.18.0) is never started here.\n if (!f || !nodesOf(f).length || f.shownBy === \"code\") 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.screen !== \"survey\" || !cancel.flow.reasons.some((r) => r.id === reason)) return;\n if (cancel.reason !== reason) cancel.answer = undefined;\n cancel.reason = reason;\n cancel.error = undefined;\n emit();\n },\n answer: (text) => {\n const c = cancel;\n if (!c || c.busy || c.screen !== \"followup\") return;\n const t = text.slice(0, 500);\n c.answer = t.trim() ? t : undefined;\n emit();\n },\n next: () => {\n const c = cancel;\n if (!c || !c.reason) return;\n // The follow-up's answer rides along on the finished event.\n if (c.screen === \"survey\") {\n env.track(CANCEL_EVENT, { action: \"answered\", run: c.run, version: c.flow.version, reason: c.reason });\n if (c.flow.followUps?.[c.reason]) c.screen = \"followup\";\n else toOffer(c);\n } else if (c.screen === \"followup\") {\n c.answer = c.answer?.trim();\n toOffer(c);\n } else return;\n emit();\n },\n accept: (comment) => {\n const c = cancel;\n if (!c || c.screen !== \"offer\" || !c.reason) return;\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: c.offer?.kind,\n ...offerAt(c),\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.offer?.kind,\n ...offerAt(c),\n outcome: \"declined\",\n });\n // A second offer once, then the confirmation.\n const second = c.round === 1 && c.reason ? c.flow.second?.[c.reason] : undefined;\n if (second) {\n c.offer = second;\n c.rule = undefined;\n c.round = 2;\n } else 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 if (v.step.kind === \"question\") {\n // 0.18.0: only with an answer; it is kept for the person and goes to MRRocket with the step.\n const q = v.step.question;\n const a = drafts.get(v.step.id) ?? (q ? answers.get(q.key) : undefined);\n if (!q || !answerOk(q, a)) return;\n answerStep(v.flow, v.step, a!);\n emit();\n return;\n }\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 celebrate(v.flow);\n save();\n emit();\n // 0.17.0: a modal's button may lead somewhere.\n const url = v.step.kind === \"modal\" ? safeUrl(v.step.url) : undefined;\n if (url) env.openUrl?.(url);\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 celebrate(v.flow);\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 // A tour started from a checklist was closed: the checklist comes back, its item stays open.\n active = returnTo && returnTo.flow !== v.flow.id && flowById(returnTo.flow) ? returnTo.flow : null;\n returnTo = null;\n save();\n emit();\n },\n startTour: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return false;\n const target = v.items.find((i) => i.step.id === stepId)?.target;\n if (!target) return false;\n openItem(v.flow, stepId, target);\n return true;\n },\n open: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return false;\n const it = v.items.find((i) => i.step.id === stepId);\n const o = it?.opens;\n if (!it || !o) return false;\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"opened\", opens: o.kind });\n if ((o.kind === \"tour\" || o.kind === \"modal\") && it.target) {\n openItem(v.flow, stepId, it.target);\n return true;\n }\n // A page or the app's code: a task without an event of its own is done once it is opened (saved before a\n // page change can unload this one).\n if (!it.done && !it.step.event) {\n markDone(prog(v.flow.id), stepId);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"completed\" });\n celebrate(v.flow);\n }\n save();\n emit();\n if (o.kind === \"page\") env.navigate?.(o.target.trim());\n else env.task?.(stepId, v.flow);\n return true;\n },\n answer: (value) => {\n const v = onboardingView();\n if (v?.type !== \"step\" || v.step.kind !== \"question\") return;\n drafts.set(v.step.id, String(value).slice(0, 500));\n emit();\n },\n skip: () => {\n const v = onboardingView();\n const q = v?.type === \"step\" && v.step.kind === \"question\" ? v.step.question : undefined;\n if (v?.type !== \"step\" || !q?.optional) return;\n drafts.delete(v.step.id);\n markDone(prog(v.flow.id), v.step.id);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: \"question\", action: \"completed\", question: q.key, skipped: true });\n celebrate(v.flow);\n save();\n emit();\n },\n back: () => {\n const v = onboardingView();\n if (v?.type !== \"step\" || v.step.kind !== \"question\" || !v.back) return;\n // The question before on the person's way through the item is open again, with its answer filled in.\n const line = stepsIn(nodesOf(v.flow));\n const at = line.findIndex((s) => s.id === v.step.id);\n const p = prog(v.flow.id);\n for (let i = at - 1; i >= 0; i--)\n if (p.done.has(line[i].id)) {\n p.done.delete(line[i].id);\n p.at.delete(line[i].id);\n break;\n }\n save();\n emit();\n },\n item: (id) => {\n const f = flowById(id);\n if (!f) return null;\n const p = progress.get(f.id);\n const steps = stepsIn(nodesOf(f)).map((s) => {\n const a = s.question ? answers.get(s.question.key) : undefined;\n return { ...s, done: !!p?.done.has(s.id), ...(a !== undefined ? { answer: a } : {}) };\n });\n const done = steps.length > 0 && steps.every((s) => s.done);\n const dismissed = !!p?.dismissed;\n return { item: f, steps, done, dismissed, eligible: !done && !dismissed && allowed(f) && due(f) };\n },\n seen: (id) => {\n const f = flowById(id);\n if (!f || f.shownBy !== \"code\" || !known) return;\n if (!shown.has(`f:${f.id}`)) {\n shown.add(`f:${f.id}`);\n env.track(ONBOARDING_EVENT, { flow: f.id, action: \"started\" });\n }\n const p = progress.get(f.id);\n for (const s of stepsIn(nodesOf(f)))\n if (!p?.done.has(s.id) && !shown.has(`s:${s.id}`)) {\n shown.add(`s:${s.id}`);\n env.track(ONBOARDING_EVENT, { flow: f.id, step: s.id, kind: s.kind, action: \"shown\" });\n // A tour or the questions show one step at a time: only the first open one counts as seen.\n if (s.kind !== \"checklist\") break;\n }\n },\n complete: (id, stepId) => {\n const f = flowById(id);\n const s = f && stepsIn(nodesOf(f)).find((x) => x.id === stepId);\n if (!f || !s || s.kind === \"question\") return;\n const p = prog(f.id);\n if (p.done.has(s.id)) return;\n markDone(p, s.id);\n env.track(ONBOARDING_EVENT, { flow: f.id, step: s.id, kind: s.kind, action: \"completed\" });\n ended(f);\n },\n dismissItem: (id) => {\n const f = flowById(id);\n if (!f) return;\n const p = prog(f.id);\n if (p.dismissed) return;\n p.dismissed = true;\n env.track(ONBOARDING_EVENT, { flow: f.id, action: \"dismissed\" });\n if (active === f.id) active = null;\n ended(f);\n },\n answerItem: (id, question, value) => {\n const f = flowById(id);\n const s = f && stepsIn(nodesOf(f)).find((x) => x.kind === \"question\" && (x.id === question || x.question?.key === question));\n if (!f || !s?.question || !answerOk(s.question, value)) return;\n answerStep(f, s, value);\n ended(f);\n },\n },\n finale: () => finaleNow,\n accent: () => config?.onboardingAccent,\n answers: () => Object.fromEntries(answers),\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","/**\n * 0.22.0: an onboarding the app keeps in its own code. There is nothing to set up in MRRocket: the app reports its\n * steps by name, and the first report makes the item (Win customers › Onboarding, \"From your code\"). MRRocket then shows\n * who saw each step, who did it and what they answered, and keeps the answers on the contact. It never draws such an\n * item and has no say in when it shows; that stays in the app.\n *\n * const report = useOnboardingReport(\"Welcome questions\", { order: [\"goal\", \"role\", \"source\"] });\n * report.saw(\"goal\", \"What brings you here?\");\n * report.answered(\"goal\", \"dream\", \"Dream game\");\n * report.closed(\"goal\"); // the person skipped the rest\n *\n * Everything goes through `track`, so it follows the visitor's consent like any other event. Report the words in one\n * language, whatever the visitor reads: the ids count the people, the words only name them in MRRocket.\n */\nimport { ONBOARDING_EVENT, eventSlug } from \"./flows\";\n\nexport type OnboardingReportType = \"questions\" | \"checklist\" | \"tour\";\n\nexport interface OnboardingReportOptions {\n /** Every step's id in the order people meet them, so a step only some people see keeps its place. */\n order?: string[];\n /** \"questions\" (the default), a \"checklist\" or a \"tour\". */\n type?: OnboardingReportType;\n}\n\nexport interface OnboardingReport {\n /** The person sees this step; `title` is its name in MRRocket. Sent once per step and page. */\n saw(step: string, title: string): void;\n /** The person answered a question with one of its options: its id, and its words in MRRocket. */\n answered(question: string, answer: string, label?: string): void;\n /** The person did this task or tour step. */\n done(step: string): void;\n /** The person closed it or skipped the rest, at this step if you name one. */\n closed(step?: string): void;\n}\n\nconst KIND = { questions: \"question\", checklist: \"checklist\", tour: \"tour\" } as const;\n\n/** The report behind `useOnboardingReport` and the script tag's `onboarding.report`, over the SDK's `track`. */\nexport const createOnboardingReport = (track: (event: string, props?: Record<string, unknown>) => void, name: string, options: OnboardingReportOptions = {}): OnboardingReport => {\n const type = options.type ?? \"questions\";\n const kind = KIND[type] ?? \"question\";\n const seen = new Set<string>();\n const send = (props: Record<string, unknown>) =>\n track(ONBOARDING_EVENT, { code: eventSlug(name), name, type, ...(options.order?.length ? { order: options.order } : {}), ...props });\n return {\n saw: (step, title) => {\n if (seen.has(step)) return;\n seen.add(step);\n send({ step, title, kind, action: \"shown\" });\n },\n answered: (question, answer, label) => send({ step: question, kind: \"question\", action: \"completed\", question, answer, label: label ?? answer }),\n done: (step) => send({ step, kind, action: \"completed\" }),\n closed: (step) => send({ ...(step ? { step } : {}), kind, action: \"dismissed\" }),\n };\n};\n","/**\n * Identity verification (0.16.0), the browser and app side. After `identify(id)` the SDK's id is your app's own user\n * id, and that id is no secret (a Clerk id shows in URLs and logs), so on its own it proves nothing: anyone who knows it\n * could read that person's support chat or post as them. Your server signs the id with the product's server key\n * (`userHash(user.id)` from `@mrrocket/sdk/next/server`) and you hand the result to `identify(id, props, { hash })`.\n * From then on every request for that id carries it as `userHash` (a JSON field, a query parameter or a form field), and\n * MRRocket checks it.\n *\n * The hash belongs to one id: it is forgotten on `reset()` (sign-out) and when `identify` is called for another id\n * without a hash, so it never goes out with someone else's id (MRRocket refuses a hash that does not match with 401).\n * Shared by the Next.js provider, the script tag and React Native: no React, no browser APIs.\n */\n\n/** The third argument of `identify`. */\nexport interface IdentifyOptions {\n /**\n * The id signed by your server: `await userHash(user.id)` from `@mrrocket/sdk/next/server` (or the same HMAC in any\n * language). Needed when MRRocket › Settings › Products › Sign-in › \"Only signed users\" is on.\n */\n hash?: string;\n}\n\n/** The id the SDK holds a hash for, and the hash. */\nexport interface Signed {\n id: string;\n hash: string;\n}\n\n/** What to do when MRRocket refuses a request for want of a hash (once per page, in the console). Short: sdk.js has a size budget. */\nexport const UNSIGNED_HELP = \"401: sign the user id on your server with userHash(id) from @mrrocket/sdk/next/server and pass identify(id, props, { hash }).\";\n\n/** Says once per page (or app run) why MRRocket answered 401; other statuses say nothing. */\nexport const warnUnsigned = (status: number, log: (message: string) => void = (m) => console.warn(m)) => {\n const g = globalThis as { __mrrocketUnsigned?: boolean };\n if (status !== 401 || g.__mrrocketUnsigned) return;\n g.__mrrocketUnsigned = true;\n log(`[MRRocket] ${UNSIGNED_HELP}`);\n};\n\n/**\n * The signed id after `identify(id, …, { hash })`: a new hash replaces the old one, the same id without a hash keeps\n * the one it has, another id without a hash drops it. A hash that is not 64 hex characters (a typo, the server key\n * itself) is ignored with a warning instead of being sent.\n */\nexport const nextSigned = (signed: Signed | null, id: string, hash: unknown, log: (message: string) => void = (m) => console.warn(m)): Signed | null => {\n const h = typeof hash === \"string\" ? hash.trim().toLowerCase() : \"\";\n if (/^[0-9a-f]{64}$/.test(h)) return { id, hash: h };\n if (h) log(\"[MRRocket] identify: that hash is no userHash(id); not sent.\");\n return signed && signed.id === id ? signed : null;\n};\n\n/** The hash for `id`, when the SDK holds one for exactly that id. */\nexport const hashFor = (signed: Signed | null | undefined, id: string | undefined) => (signed && id && signed.id === id ? signed.hash : undefined);\n\n/**\n * The hash for a request that carries several items with their own ids (error reports): only when every item that\n * names someone names the signed id, so a report of an earlier visitor never goes out under this person's hash.\n */\nexport const hashForAll = (signed: Signed | null | undefined, ids: (string | undefined)[]) =>\n signed && ids.some((id) => id === signed.id) && ids.every((id) => !id || id === signed.id) ? signed.hash : undefined;\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 */\nimport { warnUnsigned } from \"./identity\";\nimport { currentLocale, t } from \"./i18n\";\n\nexport type PostStatus = \"review\" | \"planned\" | \"progress\" | \"shipped\";\n\n/** Read at the moment it is shown, so it follows the visitor's language. */\nexport const STATUS_LABEL: Record<PostStatus, string> = {\n get review() {\n return t(\"Under review\");\n },\n get planned() {\n return t(\"Planned\");\n },\n get progress() {\n return t(\"In progress\");\n },\n get shipped() {\n return t(\"Shipped\");\n },\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 /**\n * 0.21.0: what each option says in the visitor's language, parallel to `options`. An answer is still recorded as the\n * `options` value, so rules and numbers do not split by language.\n */\n labels?: 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/** A file in the messenger's chat: a screenshot, a photo or a PDF the visitor sent (servers from SDK 0.15 on). */\nexport interface ChatFile {\n /** From an upload: the signed id a message sends. In a message: the file's own id (`attachmentUrl` reads it). */\n id: string;\n name: string;\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" | \"image/gif\" | \"application/pdf\";\n /** Bytes. */\n size: number;\n}\n\n/** What the messenger can send: pictures and PDFs, at most 10 MB each, 4 per message. */\nexport const CHAT_FILE_TYPES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\", \"application/pdf\"] as const;\nexport const CHAT_FILE_MAX_BYTES = 10 * 1024 * 1024;\nexport const CHAT_FILES_PER_MESSAGE = 4;\n\n/** A file to upload: a Blob or File on the web, the image picker's `{ uri, name, type }` in React Native. */\nexport type ChatUpload = Blob | { uri: string; name: string; type: string };\n\n/** The bug context a visitor message carries; the server fills browser and system from the user agent when left out. */\nexport interface ChatContext {\n browser?: string;\n os?: string;\n /** \"1440×900\". */\n viewport?: string;\n}\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 /** Files sent with it (servers from SDK 0.15 on). */\n attachments?: ChatFile[];\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/** Where the chat button sits: a corner, the middle of the top or bottom edge, or the middle of a side. */\nexport type MessengerPosition = \"top-left\" | \"top-center\" | \"top-right\" | \"middle-left\" | \"middle-right\" | \"bottom-left\" | \"bottom-center\" | \"bottom-right\";\n\n/** How round the messenger is. */\nexport type MessengerCorners = \"round\" | \"soft\" | \"square\";\n\n/** The radii per corner style, in px: the panel or sheet, message bubbles (and their tail), cards, fields and buttons. */\nexport const CORNERS: Record<MessengerCorners, { panel: number; bubble: number; tail: number; card: number; field: number }> = {\n round: { panel: 22, bubble: 18, tail: 6, card: 16, field: 20 },\n soft: { panel: 14, bubble: 12, tail: 4, card: 10, field: 10 },\n square: { panel: 6, bubble: 6, tail: 2, card: 4, field: 4 },\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 /** Up to two more colors blended into Home's background glow (MRRocket from 0.16; older servers leave it out). */\n glow?: string[];\n theme: \"light\" | \"dark\" | \"auto\";\n position: MessengerPosition;\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 /** The Updates tab with the published changelog (MRRocket from 0.22; older servers leave it out). */\n updates?: boolean;\n sound: boolean;\n preview: boolean;\n askEmail: boolean;\n /** How round panel, bubbles, cards and fields are (MRRocket from 0.15; older servers leave it out: round). */\n corners?: MessengerCorners;\n /** The site's own font (the default) or the system's (web only; from 0.15). */\n font?: \"site\" | \"system\";\n /** Home's top: plain like the rest, or in the accent color (from 0.15; older servers leave it out: plain). */\n header?: \"plain\" | \"color\";\n /** \"Powered by MRRocket\" at the bottom; the server sends false only on plans that may hide it (from 0.15). */\n branding?: boolean;\n /** The logo at the top left of Home: the one uploaded in MRRocket, else the product's favicon; without it the title's first letter. */\n logo?: string;\n /** The product's favicon, the round mark in the chat's head (from 0.17; without it the title's first letter). */\n icon?: string;\n /** The AI agent's name on its answers (from 0.17; empty or left out: \"AI agent\"). */\n agentName?: string;\n /** The AI agent's picture beside its answers (from 0.17). */\n agentPhoto?: string;\n}\n\n/** The link behind \"Powered by MRRocket\". */\nexport const BRAND_URL = \"https://mrrocket.dev/?utm_source=messenger&utm_medium=powered-by\";\n\n/** The line under \"Send us a message\" and in the chat's head. */\nexport const replyLine = (time: MessengerLook[\"replyTime\"]) =>\n time === \"minutes\" ? t(\"We usually reply in a few minutes\") : time === \"day\" ? t(\"We usually reply within a day\") : t(\"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/** One of the visitor's conversations in their list (0.19). */\nexport interface ChatSummary {\n id: string;\n status: \"open\" | \"solved\";\n /** The visitor's first words. */\n subject: string;\n /** The newest message, its body cut to a preview. */\n last: ChatMessage | null;\n}\n\n/** One chat (the one asked for, else the visitor's newest, open or closed) and its messages. */\nexport interface ChatThread {\n conversation: { id: string; status: \"open\" | \"solved\" } | null;\n messages: ChatMessage[];\n /** All the visitor's conversations, the latest activity first (0.19). */\n conversations?: ChatSummary[];\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 * The identity hash of `distinctId` (0.16.0, see identity.ts), sent with every request that names the visitor: a\n * JSON field next to `distinctId`, a query parameter, a form field. Leave it out for any other id.\n */\n userHash?: string;\n}\n\n// Not URLSearchParams: React Native's lacks `set` in older versions, and the apps use this client too.\n// `lang` goes along so the answer's words can be in the visitor's language; \"\" leaves it out.\nconst qs = (params: Record<string, string | undefined>, lang = currentLocale()) =>\n Object.entries({ ...params, lang })\n .filter((e): e is [string, string] => !!e[1])\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n\n/** A POST's address: its body names the visitor, the query only the language of the words in its answer. */\nconst withLang = (url: string) => {\n const q = qs({});\n return q ? `${url}?${q}` : url;\n};\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 // A form (a file upload) sets its own multipart type with the boundary.\n headers: typeof init?.body === \"string\" ? { \"content-type\": \"application/json\" } : undefined,\n });\n } catch (e) {\n if ((e as Error).name === \"AbortError\") throw e;\n throw new ApiError(t(\"Could not reach the server. Check your connection and try again.\"), 0);\n }\n if (!res.ok) {\n // A missing or wrong identity hash: the console says once how to sign the user id.\n warnUnsigned(res.status);\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 ? t(\"Too many requests. Try again in a minute.\") : t(\"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, userHash: c.userHash };\n // Every query that names the visitor names its hash too.\n const me = { key: c.apiKey, distinctId: c.distinctId, userHash: c.userHash };\n const post = <T>(path: string, body: Record<string, unknown>, signal?: AbortSignal) =>\n call<T>(withLang(`${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({ ...me, 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(me)}`, undefined, signal),\n roadmap: (signal?: AbortSignal) => call<FeedbackRoadmap>(`${base}/feedback/roadmap?${qs(me)}`, 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({ ...me, 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 /** One chat by id, else the visitor's newest; `conversations` lists them all. */\n chat: (signal?: AbortSignal, conversation?: string) => call<ChatThread>(`${base}/messages?${qs({ ...me, conversation })}`, undefined, signal),\n /**\n * A message; `attachments` are upload ids from `uploadChatFile` (then the body may be empty). `conversation` is\n * the chat it answers, or \"new\" to start one; without it, the running chat or else a new one.\n */\n sendChat: (m: { body: string; conversation?: string; email?: string; url?: string; attachments?: string[]; context?: ChatContext }) => post<ChatThread>(\"/messages\", m),\n /** Uploads one picked file for the next message (pictures and PDFs, at most 10 MB); answers its upload id. */\n uploadChatFile: (file: ChatUpload, signal?: AbortSignal) => {\n const form = new FormData();\n form.append(\"key\", c.apiKey);\n form.append(\"distinctId\", c.distinctId);\n if (c.userHash) form.append(\"userHash\", c.userHash);\n if (\"uri\" in file) form.append(\"file\", file as unknown as Blob);\n else form.append(\"file\", file, (file as Blob & { name?: string }).name || \"file\");\n return call<ChatFile>(withLang(`${base}/messages/attachments`), { method: \"POST\", body: form }, signal);\n },\n /** Where a sent file of this visitor's chat is read (an image's src, a PDF's link). */\n attachmentUrl: (id: string) => `${base}/messages/attachments/${encodeURIComponent(id)}?${qs(me, \"\")}`,\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(me)}`, 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). `userHash` (0.16.0) is the identity hash of the signed-in person: one per request, and\n * MRRocket checks it against each event's `distinctId`, so only that person's events count as verified.\n */\nexport const batchRequests = <E extends CockpitEvent>(key: string, events: E[], sdk: SdkInfo, userHash?: string): BatchRequest<E>[] => {\n const head = `{\"key\":${JSON.stringify(key)},${userHash ? `\"userHash\":${JSON.stringify(userHash)},` : \"\"}\"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); `userHash`\n * as in `batchRequests`.\n */\nexport const bodies = (key: string, events: CockpitEvent[], sdk: SdkInfo, userHash?: string) => batchRequests(key, events, sdk, userHash).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\";\nimport { hashForAll, warnUnsigned } from \"./identity\";\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 /**\n * Read when an error happens: whether to send at all (consent), and who and which session. `userHash` is the identity\n * hash of `distinctId` (0.16.0); read again when sending, and sent only with reports of that id.\n */\n context: () => { send: boolean; distinctId?: string; sessionId?: string; userHash?: 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 reports = queue.splice(0, 4);\n const now = opts.context();\n const signed = now.distinctId && now.userHash ? { id: now.distinctId, hash: now.userHash } : null;\n const userHash = hashForAll(signed, reports.map((r) => r.distinctId));\n const body = JSON.stringify({ key: opts.apiKey, ...(userHash ? { userHash } : {}), errors: reports });\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.status === 401) warnUnsigned(401);\n else 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 * Paywalls with several pages (SDK 0.14.0): what MRRocket's config serves under `paywalls` (one per placement, built\n * in MRRocket › Conversion › Paywalls) and a small controller that walks the person through its pages, page after page,\n * until the last one hands the chosen plan to the app. No DOM and no React: the web renderer (`mountPaywall` in\n * flows-ui.ts, loaded only when a paywall opens) and the React Native one (native/flows-view.ts) draw `view()` and\n * call the actions.\n *\n * MRRocket never takes a payment. The last page's button calls the app's `onPurchase(plan)`, which buys through the\n * app's own store code (StoreKit or Play through RevenueCat or Adapty, or Stripe Checkout on the web); only when it\n * resolves is the purchase recorded. It throwing keeps the paywall open with an error, resolving `false` (the person\n * closed the store sheet) keeps it open without one.\n *\n * A running test on the paywall (`experiment`) gives each person their variant's pages, by the same stable hash as\n * every other test (`assign`), and records `$exposure` when the paywall opens. What it records, as normal events under\n * the SDK's analytics consent:\n * - `$paywall` `{paywall, placement, variant, page, index, action: \"page\"}` the first time each page shows in a run,\n * so MRRocket shows how many reach page 2 and 3;\n * - `{action: \"purchased\", plan}` after `onPurchase` went through (a test's purchase goal counts it), and\n * `{action: \"closed\", index}` when the person closed it.\n */\nimport { type CockpitConfig, type VariantId, assign } from \"./core\";\nimport { t } from \"./i18n\";\n\nexport const PAYWALL_EVENT = \"$paywall\";\n\n/** One page of a paywall. Plans pages list the plans and buy; the others say why and go on. */\nexport interface PaywallPage {\n id: string;\n /** \"benefits\": a list of what the person gets; \"proof\": quotes of happy customers; \"plans\": the plans and the buy button. */\n kind: \"benefits\" | \"proof\" | \"plans\";\n title: string;\n body?: string;\n /** Benefits: one line each. */\n items?: string[];\n /** Proof: what customers said, and who. */\n quotes?: { text: string; by?: string }[];\n /** The button: \"Continue\" on the way, the buy button on the plans page (\"Start free trial\"). */\n button?: string;\n}\n\n/** A plan the paywall offers. `id` is what the app buys: the store product id or the Stripe price, as set in MRRocket. */\nexport interface PaywallPlan {\n id: string;\n name: string;\n /** As shown (\"€59.99 / year\"). The app's own store prices win when it passes `plans`. */\n price: string;\n /** A line under it (\"€5 a month\", \"7 days free\"). */\n note?: string;\n}\n\n/** A published paywall as the config serves it. */\nexport interface PaywallConfig {\n id: string;\n /** The placement's key (`onboarding_end`), what the app opens: `paywall.open(\"onboarding_end\")`. */\n placement: string;\n /** The running test on it, a key of `experiments`; each of its variants has pages under `variants`. */\n experiment?: string;\n /** Control (the live paywall) first. */\n variants: { id: VariantId; pages: PaywallPage[] }[];\n plans: PaywallPlan[];\n /** The plan picked before the person picks one. */\n highlight?: string;\n}\n\nexport interface PaywallResult {\n /**\n * \"purchased\": `onPurchase` went through; \"chosen\": the person picked a plan and there is no `onPurchase`, so the app\n * buys it now (the store's purchase still counts for a test through RevenueCat or Adapty); \"closed\": the person\n * closed it (or there was no paywall).\n */\n outcome: \"purchased\" | \"chosen\" | \"closed\";\n plan?: PaywallPlan;\n paywall?: string;\n variant?: VariantId;\n /** The page the person was on, from 0. */\n index: number;\n}\n\nexport interface PaywallOptions {\n /**\n * Buy the plan in your code (RevenueCat `purchasePackage`, Adapty `makePurchase`, Stripe Checkout). Throwing keeps\n * the paywall open with an error; `false` keeps it open without one (the person cancelled the store sheet).\n */\n onPurchase?: (plan: PaywallPlan) => unknown;\n /** Your store's plans with their local prices, by the same ids; they replace what MRRocket has for them. */\n plans?: PaywallPlan[];\n onClose?: (result: PaywallResult) => void;\n}\n\nexport interface PaywallView {\n paywall: PaywallConfig;\n variant: VariantId;\n page: PaywallPage;\n index: number;\n total: number;\n last: boolean;\n plans: PaywallPlan[];\n /** The picked plan's id. */\n plan?: string;\n busy: boolean;\n error?: string;\n}\n\nexport interface PaywallEnv {\n config: () => CockpitConfig | null;\n distinctId: () => string;\n /** Records an event under the SDK's consent. */\n track: (event: string, props?: Record<string, unknown>) => void;\n}\n\nexport interface PaywallHost {\n /** Opens the paywall of a placement; resolves when it is bought or closed (at once with \"closed\" when there is none). */\n open(placement: string, options?: PaywallOptions): Promise<PaywallResult>;\n view(): PaywallView | null;\n subscribe(listener: () => void): () => void;\n next(): void;\n back(): void;\n pick(planId: string): void;\n close(): void;\n}\n\n/** The pages of a person's variant: the test's when it runs (or shipped), else control's. */\nexport const paywallPages = (config: CockpitConfig | null, w: PaywallConfig, distinctId: string) => {\n const e = w.experiment ? config?.experiments.find((x) => x.key === w.experiment) : undefined;\n const id = e ? assign(e, distinctId) : w.variants[0]?.id;\n const v = w.variants.find((x) => x.id === id) ?? w.variants[0];\n return v ? { variant: v.id, pages: v.pages, test: e?.status === \"running\" && !e.winner ? e.key : undefined } : null;\n};\n\nexport const createPaywallHost = (env: PaywallEnv): PaywallHost => {\n let run: {\n w: PaywallConfig;\n variant: VariantId;\n pages: PaywallPage[];\n plans: PaywallPlan[];\n index: number;\n plan?: string;\n busy: boolean;\n error?: string;\n seen: Set<number>;\n options: PaywallOptions;\n resolve: (r: PaywallResult) => void;\n promise: Promise<PaywallResult>;\n } | null = null;\n const listeners = new Set<() => void>();\n const emit = () => {\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n const base = () => (run ? { paywall: run.w.id, placement: run.w.placement, variant: run.variant } : {});\n const show = () => {\n if (run && !run.seen.has(run.index)) {\n run.seen.add(run.index);\n env.track(PAYWALL_EVENT, { ...base(), page: run.pages[run.index].id, index: run.index, action: \"page\" });\n }\n emit();\n };\n const end = (r: PaywallResult) => {\n const c = run;\n if (!c) return;\n run = null;\n if (r.outcome === \"closed\") c.options.onClose?.(r);\n c.resolve(r);\n emit();\n };\n const result = (outcome: PaywallResult[\"outcome\"]): PaywallResult => ({\n outcome,\n index: run?.index ?? 0,\n ...(run ? { paywall: run.w.id, variant: run.variant } : {}),\n ...(outcome !== \"closed\" && run ? { plan: run.plans.find((p) => p.id === run!.plan) } : {}),\n });\n\n const buy = () => {\n const c = run;\n const plan = c?.plans.find((p) => p.id === c.plan);\n if (!c || !plan || c.busy) return;\n if (!c.options.onPurchase) return end(result(\"chosen\"));\n c.busy = true;\n c.error = undefined;\n emit();\n Promise.resolve()\n .then(() => c.options.onPurchase?.(plan))\n .then(\n (ok) => {\n c.busy = false;\n if (run !== c) return;\n if (ok === false) return emit();\n env.track(PAYWALL_EVENT, { ...base(), page: c.pages[c.index].id, index: c.index, plan: plan.id, action: \"purchased\" });\n end(result(\"purchased\"));\n },\n () => {\n c.busy = false;\n c.error = t(\"The purchase did not go through. Please try again.\");\n emit();\n },\n );\n };\n\n return {\n open: (placement, options = {}) => {\n if (run) return run.promise;\n const config = env.config();\n const w = config?.paywalls?.find((x) => x.placement === placement);\n const picked = w ? paywallPages(config, w, env.distinctId()) : null;\n if (!w || !picked?.pages.length) return Promise.resolve({ outcome: \"closed\", index: 0 });\n // The app's store prices replace MRRocket's for the same plans.\n const own = new Map((options.plans ?? []).map((p) => [p.id, p]));\n const plans = w.plans.map((p) => own.get(p.id) ?? p);\n let resolve: (r: PaywallResult) => void = () => {};\n const promise = new Promise<PaywallResult>((r) => (resolve = r));\n const plan = plans.some((p) => p.id === w.highlight) ? w.highlight : plans[0]?.id;\n run = { w, variant: picked.variant, pages: picked.pages, plans, index: 0, plan, busy: false, seen: new Set(), options, resolve, promise };\n if (picked.test) env.track(\"$exposure\", { experiment: picked.test, variant: picked.variant });\n show();\n return promise;\n },\n view: () =>\n run\n ? {\n paywall: run.w,\n variant: run.variant,\n page: run.pages[run.index],\n index: run.index,\n total: run.pages.length,\n last: run.index === run.pages.length - 1,\n plans: run.plans,\n plan: run.plan,\n busy: run.busy,\n error: run.error,\n }\n : null,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n next: () => {\n if (!run || run.busy) return;\n // A plans page or the last page buys; any other page goes on.\n if (run.pages[run.index].kind === \"plans\" || run.index === run.pages.length - 1) return buy();\n run.index++;\n run.error = undefined;\n show();\n },\n back: () => {\n if (!run || run.busy || !run.index) return;\n run.index--;\n run.error = undefined;\n emit();\n },\n pick: (id) => {\n if (!run || run.busy || !run.plans.some((p) => p.id === id)) return;\n run.plan = id;\n run.error = undefined;\n emit();\n },\n close: () => {\n if (!run || run.busy) return;\n env.track(PAYWALL_EVENT, { ...base(), index: run.index, action: \"closed\" });\n end(result(\"closed\"));\n },\n };\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 the frames are of; `userHash` is the identity hash of `distinctId` (0.16.0). */\n who: () => { distinctId?: string; identified: boolean; userHash?: string };\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, userHash } = 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 ...(userHash ? { userHash } : {}),\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, the identity hash missing\n // or wrong): stop this recording.\n if (status === 401 || 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 { langParam, onLocale, setDeviceLocale, setLocale, setWords } from \"../i18n\";\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 IdentifyOptions, type Signed, hashFor, hashForAll, nextSigned, warnUnsigned } from \"../identity\";\nimport { type CancelFlowOptions, type CancelFlowResult, type FlowsController, type InAppState, type OnboardingFlow, REVIEW_EVENT, createFlows } from \"../flows\";\nimport { type PaywallHost, type PaywallOptions, type PaywallResult, createPaywallHost } from \"../paywall\";\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 /**\n * 0.21.0: the language of the SDK's words and of what the server answers, like \"de-AT\", for an app with its own\n * language switch. Default: the phone's. `setLocale` does the same from anywhere.\n */\n locale?: string;\n /** Onboarding flows start on their own when the person does their trigger (default true). False: only `startOnboarding()`. */\n onboarding?: boolean;\n /**\n * 0.18.0: opens what a checklist task's \"Opens: page or screen\" names: a screen name or a path for your navigator\n * (`(target) => router.push(target)`). Without it only a deep link or an address (`myapp://…`, `https://…`) opens,\n * through `Linking`.\n */\n onNavigate?: (target: string) => void;\n /** 0.18.0: a checklist task set to \"Opens: your code\" was tapped: `(taskId, item) => …`. */\n onTask?: (taskId: string, item: OnboardingFlow) => void;\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 /**\n * 0.16.0: the store's own rating dialog through `expo-store-review` (StoreKit, Play In-App Review), when the app has\n * it installed. `request` resolves true once the dialog was asked for, false when this device has none.\n */\n storeReview?: { request(): Promise<boolean> } | 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\n/**\n * 0.16.0, what `requestReview()` did: \"requested\" the store's rating dialog was asked for (the store decides whether it\n * shows; Apple shows it at most three times a year); \"not-now\" no live review request may ask this person now (not a\n * customer, asked in the last 120 days, no request live); \"unavailable\" the device has no dialog or `expo-store-review`\n * is not installed; \"not-signed-in\" call `identify` first.\n */\nexport type NativeReviewResult = \"requested\" | \"not-now\" | \"unavailable\" | \"not-signed-in\";\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 /**\n * Who the person is once they sign in. `{ hash }` (0.16.0) is the id signed by your backend (`userHash(id)` from\n * `@mrrocket/sdk/next/server`, or the same HMAC in any language), fetched after sign-in; sent with every request for\n * that id so MRRocket knows it is really them. Needed with \"Only signed users\" (MRRocket › Settings › Products ›\n * Sign-in). Not stored on the device: call identify with it on every start.\n */\n identify(id: string, props?: Record<string, unknown>, options?: IdentifyOptions): void;\n /** Forgets the signed-in person and their hash (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 * Shows the paywall of a placement built in MRRocket › Paywalls page by page (drawn by `<MRRocketProvider>`). Its\n * last page hands the chosen plan to `onPurchase`, where your code buys it (RevenueCat, Adapty, StoreKit, Play);\n * MRRocket never takes a payment. Pass your store's `plans` to show their local prices.\n */\n openPaywall(placement: string, options?: PaywallOptions): Promise<PaywallResult>;\n /** The open paywall for a renderer (the provider's, or your own). */\n paywall: PaywallHost;\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 /**\n * 0.16.0: asks for a store review at the moment your app picked (the trigger of a review request in MRRocket ›\n * Reviews › Requests). MRRocket says whether this signed-in person may be asked now; if so the App Store's or Google\n * Play's own rating dialog opens (needs `expo-store-review`) and MRRocket counts the request. Never filtered by mood.\n */\n requestReview(): Promise<NativeReviewResult>;\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 setDeviceLocale(context.locale);\n if (options.locale) setLocale(options.locale);\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 // The id identify() signed and its hash (../identity.ts); in memory only.\n let signed: Signed | null = null;\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 // One person's onboarding progress, in-app messages and review permission (GET /api/sdk/inapp).\n const fetchInApp = async (id: string): Promise<InAppState | null> => {\n if (!apiKey) return null;\n const hash = hashOf(id);\n const r = await deps.fetch(`${host}/api/sdk/inapp?key=${encodeURIComponent(apiKey)}&distinctId=${encodeURIComponent(id)}${hash ? `&userHash=${hash}` : \"\"}${langParam()}`, { method: \"GET\" });\n warnUnsigned(r.status, deps.log);\n return r.ok ? ((await r.json()) as InAppState) : null;\n };\n\n // The cancel flow, onboarding and in-app messages (../flows.ts); `<MRRocketProvider>` draws them.\n const paywall = createPaywallHost({ config: () => config, distinctId: () => distinctId(), track: (event, props) => record(event, props) });\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: (id) => fetchInApp(id),\n // 0.18.0: a task's page or screen goes to the app's navigator; without one only a link with a scheme opens.\n navigate: (target) => {\n if (options.onNavigate) return options.onNavigate(target);\n if (/^[a-z][a-z0-9+.-]*:/i.test(target) && !/^(javascript|data|vbscript):/i.test(target)) deps.openUrl?.(target);\n else warn(`A checklist task opens \"${target}\": pass onNavigate to MRRocketProvider to open screens and paths.`);\n },\n task: (taskId, item) => options.onTask?.(taskId, item),\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 /** The identity hash for `id`, only when identify() signed exactly that id. */\n const hashOf = (id: string | undefined) => hashFor(signed, id);\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 warnUnsigned(r.status, deps.log);\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, hashOf(sendId()));\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 if (status !== 401) 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 userHash = hashForAll(signed, batch.map((r) => r.distinctId));\n const status = await post(\"/api/sdk/errors\", JSON.stringify({ key: apiKey, ...(userHash ? { userHash } : {}), sdk, errors: batch }));\n if (status >= 400 && status < 500 && status !== 429 && status !== 401) 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, userHash: hashOf(sendId()) }),\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)}${langParam()}`, { 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 setWords(c.words, c.lang);\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 pushHash: 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 const userHash = hashOf(who);\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, userHash, 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 pushHash = userHash;\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, userHash: pushHash, platform: \"expo\", token, remove: true }));\n return status >= 200 && status < 300;\n };\n\n // ---------- Store reviews (0.16.0) ----------\n\n let reviewing = false;\n const requestReview = async (): Promise<NativeReviewResult> => {\n if (!deps.storeReview) return \"unavailable\";\n await loadedNow();\n if (!apiKey || consent === \"off\") return \"not-now\";\n if (!identified) return \"not-signed-in\";\n if (reviewing) return \"not-now\";\n reviewing = true;\n try {\n // Asked now, at the app's moment: whether a live request may ask this person (customer, limits, 120 days).\n const ask = (await fetchInApp(identified).catch(() => null))?.review;\n if (!ask) return \"not-now\";\n const asked = await deps.storeReview.request().catch(() => false);\n // Only a dialog the device asked for counts as a request in MRRocket (and starts the 120 days).\n record(REVIEW_EVENT, { campaign: ask.campaign, store: ask.store, action: asked ? \"requested\" : \"unavailable\" });\n void flush();\n return asked ? \"requested\" : \"unavailable\";\n } finally {\n reviewing = false;\n }\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) {\n config = c;\n setWords(c.words, c.lang);\n }\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 // The app switched its language: the words again.\n onLocale(() => {\n void fetchConfig().then(refreshFlows);\n });\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, options) => {\n if (typeof id !== \"string\" || !id) return;\n if (!loaded) {\n early.push(() => client.identify(id, props, options));\n return;\n }\n const previous = sendId();\n // The hash belongs to this id; another id without one drops it.\n signed = nextSigned(signed, id, options?.hash, deps.log);\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 // What is queued for the person goes now, with their hash, before it is forgotten.\n void flush();\n identified = undefined;\n signed = null;\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 openPaywall: (placement, o) => paywall.open(placement, o),\n paywall,\n registerForPush,\n unregisterForPush,\n requestReview,\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, userHash: hashOf(distinctId()) });\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, so a step's side does not apply). A step's picture (0.17.0) shows\n * above its text; a video opens in the phone's player or browser from a \"Watch the video\" button.\n *\n * 0.18.0: the questions of a Questions item as slides with dots (choices or a text field, Back and Continue), task and\n * heading icons (react-native-svg when the app has it, else the icon's emoji), tasks that open a screen, a deep link, a\n * tour, a modal or the app's code, the finish animation (Animated views, skipped when the phone asks for less motion),\n * and the product's brand color from MRRocket when `appearance` sets no accent.\n */\nimport { Fragment, type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FinishAnimation, type FlowIcon, type FlowsController, OTHER_PREFIX, type OnboardingStep, answerOk, forMonths, monthsWord, scaleOf, discounted, mediaOf, money, offerButton, videoEmbed } from \"../flows\";\nimport { t, tf } from \"../i18n\";\nimport { FLOW_ICONS, iconOf } from \"../icons\";\nimport type { PaywallHost, PaywallView } from \"../paywall\";\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 Image?: Any;\n Linking?: { openURL: (url: string) => Promise<unknown> };\n useColorScheme?: () => string | null | undefined;\n Animated?: {\n View: Any;\n Value: new (v: number) => AnimatedValue;\n timing: (v: AnimatedValue, c: { toValue: number; duration: number; delay?: number; useNativeDriver: boolean }) => AnimatedRun;\n parallel: (runs: AnimatedRun[]) => AnimatedRun;\n };\n AccessibilityInfo?: { isReduceMotionEnabled?: () => Promise<boolean> };\n}\ninterface AnimatedValue {\n interpolate: (c: { inputRange: number[]; outputRange: (number | string)[] }) => unknown;\n}\ninterface AnimatedRun {\n start: (done?: () => void) => void;\n stop: () => void;\n}\nconst RN = require(\"react-native\") as RNModule;\n\n/** react-native-svg, when the app has it (for the built-in icons); null otherwise. */\nconst svg = (() => {\n try {\n return require(\"react-native-svg\") as { Svg?: Any; default?: Any; Path: Any };\n } catch {\n return null;\n }\n})();\n\n/** 0.18.0: an icon at `size`: a built-in line icon (its emoji without react-native-svg), an emoji, or a picture. */\nconst iconNode = (icon: FlowIcon | undefined, size: number, color: string): ReactNode => {\n const i = iconOf(icon);\n if (!i) return null;\n if (i.kind === \"image\")\n return RN.Image ? h(RN.Image, { source: { uri: i.url }, accessibilityElementsHidden: true, style: { width: size, height: size, borderRadius: size / 4 } }) : null;\n const Svg = svg?.Svg ?? svg?.default;\n if (i.kind === \"builtin\" && Svg && svg?.Path)\n return h(\n Svg,\n { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", stroke: color, strokeWidth: 2, strokeLinecap: \"round\", strokeLinejoin: \"round\" },\n ...FLOW_ICONS[i.name].paths.map((d, k) => h(svg.Path, { key: k, d })),\n );\n return h(RN.Text, { style: { fontSize: size * 0.8, lineHeight: size, textAlign: \"center\", width: size } }, i.kind === \"emoji\" ? i.value : FLOW_ICONS[i.name].emoji);\n};\n\ninterface Bit {\n x: number;\n y: number;\n dx: number;\n dy: number;\n mid: number;\n size: number;\n rot: number;\n color: string;\n delay: number;\n life: number;\n shape: \"rect\" | \"dot\" | \"star\";\n}\n\nconst FINALE_COLORS = [\"#f59e0b\", \"#10b981\", \"#ef4444\", \"#8b5cf6\", \"#06b6d4\", \"#ec4899\"];\n\n/** The particles of a finish animation, placed in percent of the screen and moved in points. */\nconst finaleBits = (kind: Exclude<FinishAnimation, \"none\">, accent: string): Bit[] => {\n const rnd = (a: number, b: number) => a + Math.random() * (b - a);\n const colors = [accent, accent, ...FINALE_COLORS];\n const pick = () => colors[Math.floor(Math.random() * colors.length)];\n if (kind === \"confetti\")\n return Array.from({ length: 48 }, (_, i) => ({\n x: i % 2 ? 12 : 82,\n y: 92,\n dx: (i % 2 ? 1 : -1) * rnd(40, 200),\n mid: -rnd(380, 620),\n dy: -rnd(120, 300),\n size: rnd(7, 11),\n rot: rnd(-540, 540),\n color: pick(),\n delay: rnd(0, 160),\n life: rnd(1500, 2000),\n shape: \"rect\" as const,\n }));\n if (kind === \"fireworks\")\n return Array.from({ length: 3 }, (_, b) => {\n const x = rnd(20, 75);\n const y = rnd(18, 45);\n const color = pick();\n return Array.from({ length: 18 }, (_, i) => {\n const a = (Math.PI * 2 * i) / 18;\n const r = rnd(70, 130);\n return { x, y, dx: Math.cos(a) * r, mid: Math.sin(a) * r * 0.8, dy: Math.sin(a) * r + 40, size: 5, rot: 0, color, delay: b * 320, life: rnd(900, 1200), shape: \"dot\" as const };\n });\n }).flat();\n return Array.from({ length: 22 }, () => ({\n x: rnd(6, 88),\n y: rnd(20, 80),\n dx: 0,\n mid: -rnd(10, 25),\n dy: -rnd(30, 60),\n size: rnd(16, 28),\n rot: rnd(-40, 40),\n color: pick(),\n delay: rnd(0, 600),\n life: rnd(900, 1300),\n shape: \"star\" as const,\n }));\n};\n\n/** 0.18.0: the finish animation over the app, once, unless the phone asks for less motion. */\nconst Finale = ({ kind, accent }: { kind: Exclude<FinishAnimation, \"none\">; accent: string }) => {\n const A = RN.Animated;\n const [bits] = useState(() => finaleBits(kind, accent));\n const [values] = useState(() => (A ? bits.map(() => new A.Value(0)) : []));\n const [on, setOn] = useState(!!A);\n useEffect(() => {\n if (!A) return;\n let stopped = false;\n let run: AnimatedRun | null = null;\n const go = () => {\n if (stopped) return;\n run = A.parallel(values.map((v, i) => A.timing(v, { toValue: 1, duration: bits[i].life, delay: bits[i].delay, useNativeDriver: true })));\n run.start(() => !stopped && setOn(false));\n };\n Promise.resolve(RN.AccessibilityInfo?.isReduceMotionEnabled?.())\n .then((reduce) => (reduce ? !stopped && setOn(false) : go()))\n .catch(go);\n return () => {\n stopped = true;\n run?.stop();\n };\n }, [A, bits, values]);\n if (!on || !A) return null;\n return h(\n RN.View,\n { pointerEvents: \"none\", accessibilityElementsHidden: true, importantForAccessibility: \"no-hide-descendants\", style: { position: \"absolute\", left: 0, right: 0, top: 0, bottom: 0 } },\n ...bits.map((b, i) => {\n const t = values[i];\n const fade = t.interpolate({ inputRange: [0, 0.7, 1], outputRange: [1, 1, 0] });\n const scale = b.shape === \"star\" ? t.interpolate({ inputRange: [0, 0.25, 1], outputRange: [0.2, 1.15, 0.6] }) : 1;\n return h(\n A.View,\n {\n key: i,\n style: {\n position: \"absolute\",\n left: `${b.x}%`,\n top: `${b.y}%`,\n width: b.size,\n height: b.shape === \"rect\" ? b.size * 0.45 : b.size,\n borderRadius: b.shape === \"dot\" ? b.size / 2 : 2,\n backgroundColor: b.shape === \"star\" ? \"transparent\" : b.color,\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: fade,\n transform: [\n { translateX: t.interpolate({ inputRange: [0, 1], outputRange: [0, b.dx] }) },\n { translateY: t.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0, b.mid, b.dy] }) },\n { rotate: t.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", `${b.rot}deg`] }) },\n { scale },\n ],\n },\n },\n b.shape === \"star\" ? h(RN.Text, { style: { color: b.color, fontSize: b.size, lineHeight: b.size } }, \"★\") : null,\n );\n }),\n );\n};\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\n/** The dialogs, and (0.18.0) the finish animation over the app when someone just finished an item. */\nexport const MRRocketFlows = (props: { flows: FlowsController; paywall?: PaywallHost; appearance?: NativeAppearance }) => {\n const [, setTick] = useState(0);\n useEffect(() => props.flows.subscribe(() => setTick((t) => t + 1)), [props.flows]);\n const fin = props.flows.finale?.() ?? null;\n const accent = props.appearance?.accent ?? props.flows.accent?.() ?? \"#3f76ff\";\n return h(Fragment, null, h(FlowsBody, props), fin ? h(Finale, { key: fin.key, kind: fin.kind, accent }) : null);\n};\n\nconst FlowsBody = ({ flows, paywall, appearance = {} }: { flows: FlowsController; paywall?: PaywallHost; appearance?: NativeAppearance }) => {\n const scheme = RN.useColorScheme?.();\n const dark = appearance.theme === \"dark\" || ((appearance.theme ?? \"auto\") === \"auto\" && scheme === \"dark\");\n // 0.18.0: the product's brand color from MRRocket unless the app set its own accent.\n const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? flows.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 useEffect(() => paywall?.subscribe(() => setTick((t) => t + 1)), [paywall]);\n const pw = paywall?.view() ?? null;\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 && !pw) 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, value = comment, onChange: (t: string) => void = setComment) =>\n h(RN.TextInput, {\n value,\n onChangeText: onChange,\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 /** A paywall page: dots, title, text, its benefits, quotes or plans, the button and Back. */\n const paywallSheet = (w: PaywallView) => {\n const pg = w.page;\n const host = paywall!;\n return sheet(\n [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(w.total > 1\n ? Array.from({ length: w.total }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= w.index ? p.accent : p.line } }),\n )\n : []),\n close(t(\"Close\"), host.close),\n ),\n title(pg.title),\n pg.body ? muted(pg.body, { fontSize: 15 }) : null,\n ...(pg.kind === \"benefits\"\n ? (pg.items ?? []).map((item, i) =>\n h(\n RN.View,\n { key: `b${i}`, style: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\" } },\n text(\"✓\", { color: p.accent, fontWeight: \"700\" }),\n text(item, { flex: 1 }),\n ),\n )\n : []),\n ...(pg.kind === \"proof\"\n ? (pg.quotes ?? []).map((q, i) =>\n h(RN.View, { key: `q${i}`, style: { backgroundColor: p.soft, borderRadius: 12, padding: 12, gap: 6 } }, text(q.text), q.by ? muted(q.by) : null),\n )\n : []),\n pg.kind === \"plans\"\n ? h(\n RN.View,\n { key: \"plans\", accessibilityRole: \"radiogroup\", style: { gap: 6 } },\n ...w.plans.map((plan) =>\n h(\n RN.Pressable,\n {\n key: plan.id,\n onPress: () => host.pick(plan.id),\n accessibilityRole: \"radio\",\n accessibilityLabel: `${plan.name}, ${plan.price}`,\n accessibilityState: { checked: w.plan === plan.id },\n style: {\n minHeight: 52,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: w.plan === plan.id ? p.accent : p.line,\n backgroundColor: w.plan === plan.id ? p.soft : p.bg,\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n },\n },\n h(RN.View, { style: { flex: 1 } }, text(plan.name, { fontWeight: \"600\" }), plan.note ? muted(plan.note) : null),\n text(plan.price, { fontWeight: \"700\" }),\n ),\n ),\n )\n : null,\n w.error ? text(w.error, { color: p.danger, fontSize: 13 }) : null,\n btn(w.busy ? t(\"One moment…\") : pg.button || t(\"Continue\"), \"primary\", host.next, w.busy || (pg.kind === \"plans\" && !w.plan)),\n w.index ? btn(t(\"Back\"), \"quiet\", host.back, w.busy) : null,\n ],\n host.close,\n );\n };\n\n if (pw) return paywallSheet(pw);\n if (!v) return null;\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(t(\"Close\"), flows.cancel.close),\n );\n const error = v.error ? text(v.error, { color: p.danger, fontSize: 13 }) : null;\n let body: ReactNode[] = [];\n /** One choice of a list (the survey's answers, a follow-up's). */\n const choices = (items: { key: string; label: string; on: boolean; press: () => void }[]) =>\n h(\n RN.ScrollView,\n { style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...items.map((c) =>\n h(\n RN.Pressable,\n {\n key: c.key,\n onPress: c.press,\n accessibilityRole: \"radio\",\n accessibilityState: { checked: c.on },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: c.on ? p.accent : p.line,\n backgroundColor: c.on ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(c.label, { fontWeight: \"500\" }),\n ),\n ),\n );\n if (v.screen === \"survey\")\n body = [\n title(v.flow.question || t(\"Why are you leaving?\")),\n choices(v.flow.reasons.map((r) => ({ key: r.id, label: r.label, on: v.reason === r.id, press: () => flows.cancel.pick(r.id) }))),\n btn(t(\"Continue\"), \"primary\", flows.cancel.next, !v.reason),\n btn(t(\"Never mind, keep my plan\"), \"quiet\", flows.cancel.close),\n ];\n else if (v.screen === \"followup\" && v.followUp) {\n const f = v.followUp;\n const label = v.flow.reasons.find((r) => r.id === v.reason)?.label;\n body = [\n label ? muted(tf(\"You said: {label}\", { label })) : null,\n title(f.question),\n f.answers.length\n ? choices(f.answers.map((a, i) => ({ key: String(i), label: f.answerLabels?.[i] || a, on: v.answer === a, press: () => flows.cancel.answer(a) })))\n : input(t(\"Your answer (optional)\"), v.answer ?? \"\", flows.cancel.answer),\n btn(t(\"Continue\"), \"primary\", flows.cancel.next),\n btn(t(\"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 ? `${tf(\"{price} instead of {old}\", { price: money(discounted(v.price.amount, o.percent), v.price.currency), old: money(v.price.amount, v.price.currency) })}${o.months ? ` ${forMonths(o.months)}` : \"\"}`\n : `${tf(\"{percent}% off\", { percent: o.percent })}${o.months ? ` ${forMonths(o.months)}` : \"\"}`\n : o.kind === \"pause\" && o.months\n ? tf(\"Pause for up to {months}. Your data stays.\", { months: monthsWord(o.months) })\n : o.kind === \"downgrade\" && o.planName\n ? o.planName\n : null;\n body = [\n label ? muted(tf(\"You said: {label}\", { 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(t(\"What would make you stay?\")) : null,\n btn(v.busy ? t(\"One moment…\") : offerButton(o), \"primary\", () => flows.cancel.accept(comment), v.busy),\n btn(t(\"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(t(\"Anything else we should know? (optional)\")) : null,\n btn(v.busy ? t(\"One moment…\") : v.flow.confirm.button, \"danger\", () => flows.cancel.confirm(comment), v.busy),\n btn(t(\"Keep my plan\"), \"secondary\", flows.cancel.close, v.busy),\n ];\n return sheet([top, ...body, error], flows.cancel.close);\n }\n\n /** 0.17.0: the step's picture, or a button that opens its video. */\n const media = (s: OnboardingStep) => {\n const m = mediaOf(s);\n if (!m) return null;\n if (m.kind === \"image\")\n return RN.Image\n ? h(RN.Image, {\n key: \"media\",\n source: { uri: m.url },\n accessibilityLabel: m.alt,\n resizeMode: \"cover\",\n style: { width: \"100%\", aspectRatio: 16 / 9, borderRadius: 10, backgroundColor: p.soft },\n })\n : null;\n const v = videoEmbed(m.url);\n const open = v?.kind === \"file\" ? v.src : m.url;\n return RN.Linking ? btn(`▶ ${t(\"Watch the video\")}`, \"secondary\", () => void RN.Linking?.openURL(open).catch(() => {})) : null;\n };\n\n if (v.type === \"step\" && v.step.kind === \"question\") {\n // 0.18.0: one question as a slide: dots, the options or a text field, Back and Continue.\n const s = v.step;\n const q = s.question;\n const ok = answerOk(q, v.answer);\n return sheet(\n [\n h(\n RN.View,\n { key: \"top\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 4 } },\n ...(v.total > 1\n ? Array.from({ length: v.total }, (_, i) =>\n h(RN.View, { key: i, style: { width: 16, height: 4, borderRadius: 4, backgroundColor: i <= v.index ? p.accent : p.line } }),\n )\n : []),\n close(t(\"Close\"), flows.onboarding.dismiss),\n ),\n v.index === 0 && v.flow.icon ? h(RN.View, { key: \"icon\" }, iconNode(v.flow.icon, 36, p.accent)) : null,\n title(s.title),\n s.body ? muted(s.body, { fontSize: 15 }) : null,\n q?.type === \"choice\"\n ? h(\n RN.ScrollView,\n { key: \"opts\", style: { maxHeight: 320 }, contentContainerStyle: { gap: 6 }, accessibilityRole: \"radiogroup\" },\n ...[...(q.options ?? []), ...(q.other ? [{ id: OTHER_PREFIX, label: q.otherLabel || t(\"Other\") }] : [])].map((o) => {\n const isOther = o.id === OTHER_PREFIX;\n const on = isOther ? !!v.answer?.startsWith(OTHER_PREFIX) : v.answer === o.id;\n return h(\n RN.Pressable,\n {\n key: o.id,\n onPress: () => (isOther && on ? undefined : flows.onboarding.answer(o.id)),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: on },\n style: {\n minHeight: 44,\n paddingHorizontal: 12,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: on ? p.accent : p.line,\n backgroundColor: on ? p.soft : p.bg,\n justifyContent: \"center\",\n },\n },\n text(o.label, { fontWeight: \"500\" }),\n );\n }),\n q.other && v.answer?.startsWith(OTHER_PREFIX)\n ? h(RN.TextInput, {\n key: \"other\",\n value: v.answer.slice(OTHER_PREFIX.length),\n onChangeText: (t: string) => flows.onboarding.answer(OTHER_PREFIX + t),\n onSubmitEditing: flows.onboarding.next,\n placeholder: t(\"Your answer\"),\n placeholderTextColor: p.muted,\n maxLength: 490,\n accessibilityLabel: q.otherLabel || t(\"Other\"),\n style: { height: 44, borderWidth: 1, borderColor: p.line, borderRadius: 10, paddingHorizontal: 12, color: p.fg },\n })\n : null,\n )\n : q?.type === \"scale\"\n ? h(\n RN.View,\n { key: \"scale\", style: { gap: 6 } },\n h(\n RN.View,\n { style: { flexDirection: \"row\", gap: 4 }, accessibilityRole: \"radiogroup\" },\n ...scaleOf(q).map((n) => {\n const on = v.answer === String(n);\n return h(\n RN.Pressable,\n {\n key: n,\n onPress: () => flows.onboarding.answer(String(n)),\n accessibilityRole: \"radio\",\n accessibilityState: { checked: on },\n style: { flex: 1, height: 44, borderRadius: 8, borderWidth: 1, borderColor: on ? p.accent : p.line, backgroundColor: on ? p.accent : p.bg, alignItems: \"center\", justifyContent: \"center\" },\n },\n text(String(n), { fontWeight: \"500\", color: on ? \"#fff\" : p.fg }),\n );\n }),\n ),\n q.lowLabel || q.highLabel\n ? h(RN.View, { style: { flexDirection: \"row\", justifyContent: \"space-between\" } }, muted(q.lowLabel || \"\"), muted(q.highLabel || \"\"))\n : null,\n )\n : q\n ? h(RN.TextInput, {\n key: \"answer\",\n value: v.answer ?? \"\",\n onChangeText: (t: string) => flows.onboarding.answer(t),\n onSubmitEditing: flows.onboarding.next,\n placeholder: q.placeholder || t(\"Your answer\"),\n placeholderTextColor: p.muted,\n maxLength: 500,\n accessibilityLabel: s.title,\n style: { height: 44, borderWidth: 1, borderColor: p.line, borderRadius: 10, paddingHorizontal: 12, color: p.fg },\n })\n : null,\n btn(s.button || (v.last ? t(\"Done\") : t(\"Continue\")), \"primary\", flows.onboarding.next, !ok),\n q?.optional ? btn(q.skipLabel || t(\"Skip\"), \"quiet\", flows.onboarding.skip) : null,\n v.back ? btn(t(\"Back\"), \"quiet\", flows.onboarding.back) : null,\n ],\n flows.onboarding.dismiss,\n );\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(tf(\"Step {n} of {total}\", { n: v.index + 1, total: v.total })) : null,\n close(t(\"Close the tour\"), flows.onboarding.dismiss),\n ),\n v.step.kind === \"modal\" && v.flow.icon ? h(RN.View, { key: \"icon\" }, iconNode(v.flow.icon, 36, p.accent)) : null,\n media(v.step),\n title(v.step.title),\n v.step.body ? muted(v.step.body, { fontSize: 15 }) : null,\n btn(v.step.button || (v.last ? t(\"Done\") : t(\"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(t(\"Hide the checklist\"), flows.onboarding.dismiss),\n ),\n muted(tf(\"{done} of {total} done\", { done, total: v.items.length })),\n ...v.items.map(({ step, done: d, opens }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n // 0.17.0/0.18.0: a task that opens something (a tour, a modal, a screen, the app's code) does it;\n // a finished tour or modal ticks it, a screen or the app's code once opened (unless an event does).\n disabled: d || (!!step.event && !opens),\n onPress: () => (opens ? flows.onboarding.open(step.id) : flows.onboarding.check(step.id)),\n accessibilityRole: opens && !d ? \"button\" : \"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 step.icon ? iconNode(step.icon, 20, p.accent) : null,\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(t(\"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(t(\"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 * 0.18.0: the SDK's own small line icons for checklist tasks and the heading of a modal or the questions\n * (`FlowIcon { kind: \"builtin\", name }`). Drawn by the SDK itself (an inline SVG on the web, react-native-svg in apps,\n * the emoji when an app has no react-native-svg), and by MRRocket's editor from this same list, so what the owner picks\n * is what people see. Each is a 24×24 outline, stroked at 2 with round ends, in the text color or the accent.\n */\n\nexport interface BuiltinIcon {\n /** What the editor calls it. */\n label: string;\n /** Path data, drawn stroked (no fill), on a 24×24 grid. */\n paths: string[];\n /** Shown instead in an app without react-native-svg. */\n emoji: string;\n}\n\nexport const FLOW_ICONS: Record<string, BuiltinIcon> = {\n check: { label: \"Check\", paths: [\"M5 12.5l4.5 4.5L19 7.5\"], emoji: \"✅\" },\n star: { label: \"Star\", paths: [\"M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.9l-5.2 2.7 1-5.8-4.3-4.1 5.9-.9z\"], emoji: \"⭐\" },\n rocket: {\n label: \"Rocket\",\n paths: [\"M12 3c3 2 4.5 5.5 4 10l-2 3h-4l-2-3c-.5-4.5 1-8 4-10z\", \"M8 13.5l-3 3 3.5.5\", \"M16 13.5l3 3-3.5.5\", \"M13.5 9.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z\", \"M11 19.5v1.5M13 19.5v1.5\"],\n emoji: \"🚀\",\n },\n user: { label: \"Person\", paths: [\"M15.5 8a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z\", \"M5 20c.8-3.5 3.6-5.5 7-5.5s6.2 2 7 5.5\"], emoji: \"👤\" },\n users: {\n label: \"Team\",\n paths: [\"M13 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z\", \"M3.5 19c.6-3 3-4.8 6.5-4.8s5.9 1.8 6.5 4.8\", \"M16 5.2a3 3 0 0 1 0 5.6\", \"M18 14.6c1.5.6 2.4 2 2.7 4.4\"],\n emoji: \"👥\",\n },\n settings: {\n label: \"Settings\",\n paths: [\"M12 2.8v2.4M12 18.8v2.4M2.8 12h2.4M18.8 12h2.4M5.5 5.5l1.7 1.7M16.8 16.8l1.7 1.7M5.5 18.5l1.7-1.7M16.8 7.2l1.7-1.7\", \"M17 12a5 5 0 1 1-10 0 5 5 0 0 1 10 0z\", \"M14 12a2 2 0 1 1-4 0 2 2 0 0 1 4 0z\"],\n emoji: \"⚙️\",\n },\n bell: { label: \"Bell\", paths: [\"M6 16v-5a6 6 0 0 1 12 0v5l1.5 2h-15z\", \"M10 20.5a2 2 0 0 0 4 0\"], emoji: \"🔔\" },\n mail: { label: \"Mail\", paths: [\"M4 6h16v12H4z\", \"M4 7l8 6 8-6\"], emoji: \"✉️\" },\n chat: { label: \"Chat\", paths: [\"M4 5h16v11H9l-5 4z\"], emoji: \"💬\" },\n heart: { label: \"Heart\", paths: [\"M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z\"], emoji: \"❤️\" },\n flag: { label: \"Flag\", paths: [\"M5 21V4\", \"M5 4h11l-2 4 2 4H5\"], emoji: \"🚩\" },\n bolt: { label: \"Bolt\", paths: [\"M13 3L5 13.5h6L10 21l8-10.5h-6z\"], emoji: \"⚡\" },\n book: { label: \"Book\", paths: [\"M4 5.5C6.5 4 9.5 4 12 6c2.5-2 5.5-2 8-.5V19c-2.5-1.5-5.5-1.5-8 .5-2.5-2-5.5-2-8-.5z\", \"M12 6v13.5\"], emoji: \"📖\" },\n calendar: { label: \"Calendar\", paths: [\"M4 6h16v14H4z\", \"M4 10h16\", \"M8 3.5v4M16 3.5v4\"], emoji: \"📅\" },\n camera: { label: \"Camera\", paths: [\"M4 8h3.5L9 5.5h6L16.5 8H20v11H4z\", \"M15.5 13a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z\"], emoji: \"📷\" },\n cart: { label: \"Cart\", paths: [\"M3.5 4.5H6l2 10h10l2-7H7\", \"M9.5 19.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z\", \"M18.5 19.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z\"], emoji: \"🛒\" },\n chart: { label: \"Chart\", paths: [\"M4 20h16\", \"M7 16v-4M12 16V8M17 16V9\"], emoji: \"📊\" },\n gift: { label: \"Gift\", paths: [\"M4 10h16v10H4z\", \"M3 7h18v3H3z\", \"M12 7v13\", \"M12 7c-1.5-3-5-3-5-1s3.5 1 5 1z\", \"M12 7c1.5-3 5-3 5-1s-3.5 1-5 1z\"], emoji: \"🎁\" },\n home: { label: \"Home\", paths: [\"M4 11l8-7 8 7\", \"M6 9.5V20h12V9.5\", \"M10 20v-6h4v6\"], emoji: \"🏠\" },\n link: { label: \"Link\", paths: [\"M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1\", \"M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1\"], emoji: \"🔗\" },\n lock: { label: \"Lock\", paths: [\"M6 11h12v9H6z\", \"M8.5 11V8a3.5 3.5 0 0 1 7 0v3\"], emoji: \"🔒\" },\n pencil: { label: \"Pencil\", paths: [\"M4 20l1-4L16 5l3 3L8 19z\", \"M14 7l3 3\"], emoji: \"✏️\" },\n plus: { label: \"Plus\", paths: [\"M12 5v14M5 12h14\"], emoji: \"➕\" },\n search: { label: \"Search\", paths: [\"M16 10.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\", \"M14.5 14.5L20 20\"], emoji: \"🔍\" },\n upload: { label: \"Upload\", paths: [\"M12 15V4\", \"M7.5 8.5L12 4l4.5 4.5\", \"M4 15v5h16v-5\"], emoji: \"⬆️\" },\n play: { label: \"Play\", paths: [\"M8 5l11 7-11 7z\"], emoji: \"▶️\" },\n sparkle: { label: \"Sparkle\", paths: [\"M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z\", \"M19 16l.7 2 2 .7-2 .7-.7 2-.7-2-2-.7 2-.7z\"], emoji: \"✨\" },\n globe: {\n label: \"Globe\",\n paths: [\"M20 12a8 8 0 1 1-16 0 8 8 0 0 1 16 0z\", \"M4 12h16\", \"M12 4c2.2 2.2 3.3 4.9 3.3 8s-1.1 5.8-3.3 8c-2.2-2.2-3.3-4.9-3.3-8S9.8 6.2 12 4z\"],\n emoji: \"🌐\",\n },\n};\n\n/** The built-in icons' names, in the editor's order. */\nexport const FLOW_ICON_NAMES = Object.keys(FLOW_ICONS);\n\n/** An icon as it may be shown: a known built-in, an emoji (up to 8 code points, so joined ones fit), or an http(s) picture; else undefined. */\nexport const iconOf = <T extends { kind: string; name?: string; value?: string; url?: string }>(icon: T | undefined): T | undefined => {\n if (!icon) return undefined;\n if (icon.kind === \"builtin\") return icon.name && FLOW_ICONS[icon.name] ? icon : undefined;\n if (icon.kind === \"emoji\") return icon.value && icon.value.trim() && [...icon.value.trim()].length <= 8 ? icon : undefined;\n if (icon.kind === \"image\") return icon.url && /^https?:\\/\\//i.test(icon.url) ? icon : undefined;\n return undefined;\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 * - `expo-store-review` (0.16.0): the store's own rating dialog, `requestReview()`. Without it that answers \"unavailable\".\n */\nimport type { AppContext } from \"../core\";\nimport type { AppStateLike, ErrorUtilsLike, FetchLike, KeyValueStorage, NativeDeps, PushData, PushDeps } from \"./client\";\nimport { measureMasks } from \"./recorder\";\nimport { t } from \"../i18n\";\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}\ninterface ExpoStoreReview {\n isAvailableAsync?: () => Promise<boolean>;\n requestReview?: () => Promise<void>;\n}\nlet expoStoreReview: ExpoStoreReview | null = null;\ntry {\n expoStoreReview = require(\"expo-store-review\") as ExpoStoreReview;\n} catch {\n expoStoreReview = 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: t(\"Default\"), importance: n.AndroidImportance?.HIGH ?? 4 });\n const id = projectId ?? constants.expoConfig?.extra?.eas?.projectId ?? constants.easConfig?.projectId;\n const push = await n.getExpoPushTokenAsync(id ? { projectId: id } : undefined);\n return typeof push?.data === \"string\" && push.data ? push.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 store's rating dialog, when expo-store-review is installed: false when the device has none (a simulator, no store). */\nconst storeReview = (): NativeDeps[\"storeReview\"] => {\n const m = expoStoreReview;\n if (!m?.requestReview) return null;\n return {\n request: async () => {\n if (m.isAvailableAsync && !(await m.isAvailableAsync())) return false;\n await m.requestReview!();\n return true;\n },\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 storeReview: storeReview(),\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 expoStoreReview: !!expoStoreReview?.requestReview,\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 in one of eight places. Home is plain like the web messenger's (or on the\n * accent with `header: \"color\"`), corners follow `corners`; its line icons need react-native-svg (text glyphs\n * without it). While it is closed and the person waits for an answer, it checks now and then; a new answer shows as\n * a banner at the top with a light haptic (expo-haptics, when installed; apps play no sound of their own). A person\n * can have several conversations, as on the web (../messenger-ui.ts): Home's \"Ask a question\" starts a new one, the\n * field inside a chat answers in that chat, and Home and Messages list them with new answers counted per conversation.\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 { BRAND_URL, CHAT_FILES_PER_MESSAGE, CHAT_FILE_MAX_BYTES, CORNERS, inkOn } from \"../api-client\";\nimport { t, tf, wordsVersion } from \"../i18n\";\nimport type {\n Api,\n Article,\n ArticleSpan,\n ArticleSummary,\n ChatFile,\n ChatMessage,\n ChatSummary,\n MessengerCorners,\n MessengerLook,\n MessengerPosition,\n ChatThread,\n FeedbackBoardInfo,\n FeedbackPost,\n SurveyAnswer,\n SurveyDefinition,\n SurveyQuestion,\n} 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; Version?: string | number };\n Linking: { openURL(url: string): Promise<unknown> };\n Image: Any;\n Dimensions: { get(dim: \"screen\" | \"window\"): { width: number; height: number } };\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(t(\"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 at = new Date(iso).getTime();\n if (Number.isNaN(at)) return \"\";\n const d = Math.max(0, Date.now() - at) / 1000;\n if (d < 60) return t(\"just now\");\n if (d < 3600) return tf(\"{n}m ago\", { n: Math.floor(d / 60) });\n if (d < 86400) return tf(\"{n}h ago\", { n: Math.floor(d / 3600) });\n return tf(\"{n}d ago\", { n: Math.floor(d / 86400) });\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(t(\"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: tf(\"{n} of {total}\", { n, total: 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\" ? t(\"Not likely\") : \"\")), k.muted(q.high ?? (q.kind === \"nps\" ? t(\"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, i) => {\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 // The label in the person's language; what is recorded stays the option itself.\n k.text(q.labels?.[i] || o, { fontWeight: \"500\" }),\n );\n }),\n );\n } else input = k.field({ value: (value as string | undefined) ?? \"\", onChange: pick, placeholder: q.placeholder ?? t(\"Type your answer\"), multiline: true });\n\n const body = done\n ? [k.text(survey.thanks || t(\"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(t(\"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\" } }, ` ${t(\"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 ? t(\"Send\") : t(\"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(t(\"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(t(\"Top requests\"), tab === \"top\", () => setTab(\"top\")),\n k.chip(t(\"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(t(\"Loading…\")) : null,\n posts?.length === 0 ? k.muted(t(\"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\n ? tf(\"Remove your vote from {title}. {votes}\", { title: post.title, votes: post.votes === 1 ? t(\"1 vote\") : tf(\"{n} votes\", { n: post.votes }) })\n : tf(\"Upvote {title}. {votes}\", { title: post.title, votes: post.votes === 1 ? t(\"1 vote\") : tf(\"{n} votes\", { n: post.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(t(\"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: t(\"Short title\"), max: 120 }),\n k.field({ value: details, onChange: setDetails, placeholder: t(\"Details (optional)\"), multiline: true }),\n ...(user?.email\n ? []\n : [\n k.muted(t(\"Your name and email are optional; they let the team follow up.\")),\n k.field({ value: name, onChange: setName, placeholder: t(\"Your name (optional)\"), max: 100 }),\n k.field({ value: email, onChange: setEmail, placeholder: t(\"Your email (optional)\"), max: 200, email: true }),\n ]),\n error ? k.text(error, { color: p.danger, fontSize: 13 }) : null,\n k.btn(sending ? t(\"Sending…\") : t(\"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 ?? t(\"Feedback\") }) : null;\n};\n\n// ---------- Messenger ----------\n\nconst POLL_OPEN_MS = 4000;\nconst POLL_WAITING_MS = 8000;\nconst POLL_IDLE_MS = 30000;\n/** Nothing to wait for, app in front: a slow read, so a message the team starts reaches a signed-in person (as on the web). */\nconst POLL_QUIET_MS = 60000;\nconst WAITING_FOR_MS = 10 * 60_000;\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst whoLabel = (from: ChatMessage[\"from\"]) => (from === \"visitor\" ? t(\"You\") : from === \"ai\" ? t(\"AI agent\") : t(\"Team\"));\n/** Who wrote a message; the AI agent by the name set in MRRocket. */\nconst who = (from: ChatMessage[\"from\"], agentName?: string) => (from === \"ai\" && agentName?.trim()) || whoLabel(from);\n\ntype MsgView = \"home\" | \"messages\" | \"help\" | { article: string };\nlet msgView: MsgView = \"home\";\n/** The conversation Messages opens on; null: the list, or the one chat of a person with a single conversation. */\nlet msgChat: string | null = null;\nconst messengerOpen = opener();\nconst openAt = (v: MsgView = \"home\", chatId: string | null = null) => {\n msgView = v;\n msgChat = chatId;\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: a corner, the middle of the top or bottom edge, or the middle of a side (default bottom right). */\n position?: MessengerPosition;\n /** Text beside the chat button's icon; empty: the round button. */\n label?: string;\n /** The name beside the team's mark at the top of Home (MRRocket fills in the product's name). */\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 on Home. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** How round bubbles, cards and fields are (default round; the sheet itself keeps the system's corners). */\n corners?: MessengerCorners;\n /** Home's top: plain like the rest (default), or in the accent color with raised cards. */\n header?: \"plain\" | \"color\";\n /** The logo at the top left of Home (MRRocket sends the uploaded logo, else the product's favicon). */\n logo?: string;\n /** The AI agent's name on its answers (default \"AI agent\"). */\n agentName?: string;\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\n/** expo-image-picker, when the app has it: the paperclip in the chat picks photos (screenshots included) with it. */\ninterface ImagePickerAsset {\n uri: string;\n fileName?: string | null;\n mimeType?: string | null;\n fileSize?: number | null;\n}\ninterface ExpoImagePicker {\n launchImageLibraryAsync?: (o: Record<string, unknown>) => Promise<{ canceled?: boolean; cancelled?: boolean; assets?: ImagePickerAsset[] | null }>;\n}\nlet imagePicker: ExpoImagePicker | null = null;\ntry {\n imagePicker = require(\"expo-image-picker\") as ExpoImagePicker;\n} catch {\n imagePicker = null;\n}\nconst PHOTO_TYPES: Record<string, ChatFile[\"type\"]> = { jpg: \"image/jpeg\", jpeg: \"image/jpeg\", png: \"image/png\", webp: \"image/webp\", gif: \"image/gif\" };\n\n/** A photo picked for the next message, uploading or uploaded. */\ninterface PickedPhoto {\n key: string;\n uri: string;\n name: string;\n type: ChatFile[\"type\"];\n size: number;\n id?: string;\n up: Promise<void>;\n}\n\n/** Where a message goes and what Messages shows: a conversation, a new one being written, or (neither) the tab's own view. */\ninterface ChatPlace {\n chatId: string | null;\n fresh: boolean;\n}\nconst samePlace = (a: ChatPlace, b: ChatPlace) => a.chatId === b.chatId && a.fresh === b.fresh;\n/** The conversation on screen, if one is: not while the list or a new conversation shows. */\nconst shownChat = (at: ChatPlace, chats: ChatSummary[]) => (at.fresh ? null : (at.chatId ?? (chats.length === 1 ? chats[0].id : null)));\nconst isAnswer = (m: ChatMessage) => m.from === \"team\" || m.from === \"ai\";\n/** A message in one line: its words, else what it sent. */\nconst lineOf = (m: ChatMessage) => m.body || (m.attachments?.length === 1 ? tf(\"Sent {name}\", { name: m.attachments[0].name }) : m.attachments?.length ? tf(\"Sent {n} files\", { n: m.attachments.length }) : \"\");\n/** A new answer and the conversation it belongs to. */\ntype UnseenAnswer = ChatMessage & { chat: string };\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 clip: \"m14.3 7.4-6.1 6.1a4 4 0 0 1-5.7-5.7l5.7-5.7a2.7 2.7 0 0 1 3.8 3.8L6.3 11.6a1.3 1.3 0 0 1-1.9-1.9l5.7-5.6\",\n};\nconst FALLBACK: Record<keyof typeof GLYPH, string> = { chat: \"💬\", home: \"⌂\", help: \"?\", send: \"→\", up: \"↑\", next: \"›\", search: \"⌕\", cross: \"×\", clip: \"📎\" };\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 );\n/** The messenger sheet like the web messenger: a white sheet, gray fills without shadows, a pill tab switch with the current tab raised. */\nconst HU = {\n light: { bg: \"#ffffff\", surface: \"#f4f4f5\", def: \"#ececee\", segment: \"#ffffff\", fg: \"#18181b\", muted: \"#71717a\" },\n dark: { bg: \"#111113\", surface: \"#1c1c1f\", def: \"#26262a\", segment: \"#3a3a40\", fg: \"#fafafa\", muted: \"#a1a1aa\" },\n};\nconst hairline = { shadowColor: \"#000\", shadowOpacity: 0.07, shadowRadius: 3, shadowOffset: { width: 0, height: 1 }, elevation: 1 };\n\n/** The conversations' 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 [chats, setChats] = useState<ChatSummary[]>([]);\n const [hasEmail, setHasEmail] = useState(false);\n const [place, setPlace] = useState<ChatPlace>({ chatId: null, fresh: false });\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState(\"\");\n const [unseen, setUnseen] = useState<UnseenAnswer[]>([]);\n /** The time of the newest message known per conversation since the app started: answers after it are new. */\n const known = useRef(new Map<string, string>());\n const seeded = useRef(false);\n const watching = open && view === \"messages\";\n const watch = useRef(watching);\n watch.current = watching;\n // What a read that comes back must go by, ahead of the next render.\n const at = useRef(place);\n const list = useRef(chats);\n const readFailed = useRef(false);\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 /** Puts a place on screen; a read on its way for another one must not arrive here. */\n const enter = useCallback((chatId: string | null, fresh = false) => {\n const next = { chatId, fresh };\n if (samePlace(at.current, next)) return;\n at.current = next;\n setPlace(next);\n setThread(null);\n setError(\"\");\n }, []);\n\n const take = useCallback(\n (t: ChatThread) => {\n const read = t.conversation;\n const last = t.messages.at(-1);\n // A server without the list: the one chat it read.\n const all = t.conversations ?? (read && last ? [{ id: read.id, status: read.status, subject: lineOf(t.messages[0]), last }] : []);\n const fresh: UnseenAnswer[] = [];\n /**\n * The list brings only a conversation's newest message. What the first read finds is not news; a conversation that\n * appears after it is, since the team may have started it (0.20).\n */\n const learn = (chat: string, answers: ChatMessage[], newest: string | undefined) => {\n const was = known.current.get(chat);\n const since = was ?? (seeded.current ? \"\" : undefined);\n if (since !== undefined) fresh.push(...answers.filter((m) => m.at > since).map((m) => ({ ...m, chat })));\n known.current.set(chat, newest ?? was ?? \"\");\n };\n for (const c of all) if (c.id !== read?.id) learn(c.id, c.last && isAnswer(c.last) ? [c.last] : [], c.last?.at);\n if (read) learn(read.id, t.messages.filter(isAnswer), last?.at);\n seeded.current = true;\n if (fresh.length && o.haptics !== false) buzz();\n const shown = shownChat(at.current, all);\n const counted = fresh.filter((m) => !watch.current || m.chat !== shown);\n // A conversation the team archived leaves the list and takes its count along.\n setUnseen((u) => [...u.filter((m) => all.some((c) => c.id === m.chat)), ...counted]);\n list.current = all;\n setChats(all);\n setHasEmail(t.hasEmail);\n if (at.current.chatId === null || read?.id === at.current.chatId) setThread(t);\n },\n [o.haptics],\n );\n\n /** What the server took: a place still on screen moves to the conversation it went into (new, or new after a closed one). */\n const arrived = useCallback(\n (from: ChatPlace, t: ChatThread) => {\n const went = t.conversation?.id;\n if (went && samePlace(at.current, from)) {\n at.current = { chatId: went, fresh: false };\n setPlace(at.current);\n }\n take(t);\n },\n [take],\n );\n\n const shown = shownChat(place, chats);\n useEffect(() => {\n if (watching && shown) setUnseen((u) => u.filter((m) => m.chat !== shown));\n }, [watching, shown]);\n\n // Reads: often while the chat is on screen, now and then while the person waits for an answer, slowly else, 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 /** The server refused the read (a signed-in user without a valid hash): no slow reads until the next start. */\n let refused = false;\n const tick = async () => {\n const api = client.api();\n if (!api) {\n setLoaded(true);\n return;\n }\n ctrl = new AbortController();\n try {\n await client.ready;\n const t = await api.chat(ctrl.signal, place.chatId ?? undefined);\n if (stop) return;\n take(t);\n // Only a read's own error: what a send said stays until the next send.\n if (readFailed.current) setError(\"\");\n readFailed.current = false;\n } catch (e) {\n if ((e as Error).name === \"AbortError\" || stop) return;\n refused = [401, 403].includes((e as { status?: number }).status ?? 0);\n // A chat that is gone (the team archived it): back to what is left.\n if ((e as { status?: number }).status === 404 && place.chatId) enter(null);\n else if (watch.current) {\n readFailed.current = true;\n setError((e as Error).message);\n }\n }\n setLoaded(true);\n const running = list.current.filter((c) => c.status !== \"solved\");\n const recent = running.some((c) => c.last && Date.now() - new Date(c.last.at).getTime() < WAITING_FOR_MS);\n const ms = watch.current ? POLL_OPEN_MS : running.length && recent ? POLL_WAITING_MS : running.length || open ? POLL_IDLE_MS : 0;\n if (!stop && ms) timer = setTimeout(tick, ms);\n else if (!stop) timer = setTimeout(quiet, POLL_QUIET_MS);\n };\n // A slow turn without anyone to reach reads nothing; whoever signs in later is read from the next one on.\n const quiet = () => {\n if (client.getUser() && !refused) void tick();\n else timer = setTimeout(quiet, POLL_QUIET_MS);\n };\n void tick();\n return () => {\n stop = true;\n ctrl?.abort();\n clearTimeout(timer);\n };\n }, [client, take, enter, active, open, watching, place]);\n\n return {\n // A new conversation has nothing to show yet; polls keep reading the newest for the list.\n thread: place.fresh ? null : thread,\n chats,\n hasEmail,\n place,\n /** Messages shows the list: several conversations and none chosen. */\n listing: place.chatId === null && !place.fresh && chats.length > 1,\n enter,\n loaded,\n error,\n setError,\n unseen,\n arrived,\n };\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(t(\"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(t(\"Thanks for letting us know.\")) : k.muted(t(\"Did this answer your question?\"), { flex: 1 }),\n rated ? null : k.btn(t(\"Yes\"), \"secondary\", () => rate(true), false, { height: 34 }),\n rated ? null : k.btn(t(\"No\"), \"secondary\", () => rate(false), false, { height: 34 }),\n ),\n k.btn(t(\"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 brand,\n}: {\n client: MRRocketClient;\n p: Palette;\n o: NativeMessengerOptions;\n chat: ReturnType<typeof useChat>;\n view: MsgView;\n setView: (v: MsgView) => void;\n /** \"Powered by MRRocket\" above the tab bar. */\n brand: boolean;\n}) => {\n const k = kit(p);\n const [body, setBody] = useState(\"\");\n /** Home's \"Ask a question\": its own words, never what is being written in a chat. */\n const [asked, setAsked] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n const [pending, setPending] = useState<(ChatMessage & { to: ChatPlace }) | null>(null);\n // A message on its way reads \"just now\" like a sent one; \"Sending…\" only once the server is slow to take it.\n const [slow, setSlow] = useState(false);\n useEffect(() => {\n setSlow(false);\n if (!pending) return;\n const t = setTimeout(() => setSlow(true), 1500);\n return () => clearTimeout(t);\n }, [pending]);\n const [photos, setPhotos] = useState<PickedPhoto[]>([]);\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 ?? t(\"Hi! How can we help?\");\n const { thread, place } = chat;\n /** On its way into what is on screen; the visitor may have gone to another conversation meanwhile. */\n const pendingHere = pending && samePlace(pending.to, place) ? pending : null;\n\n const count = (thread?.messages.length ?? 0) + (pendingHere ? 1 : 0);\n useEffect(() => {\n if (view === \"messages\") setTimeout(() => scroll.current?.scrollToEnd?.({ animated: true }), 50);\n }, [count, view, place]);\n\n const needEmail = (o.askEmail ?? true) && !chat.hasEmail && !client.getUser()?.email;\n const emailOk = !email.trim() || EMAIL.test(email.trim());\n // Photos for the next message, picked with expo-image-picker (the paperclip shows only when the app has it). Each\n // uploads at once; Send waits for the uploads. People take a screenshot with the phone and pick it here.\n const pickPhotos = async () => {\n const api = client.api();\n if (!api || !imagePicker?.launchImageLibraryAsync || pending) return;\n const room = CHAT_FILES_PER_MESSAGE - photos.length;\n if (room <= 0) return chat.setError(tf(\"Up to {n} files per message.\", { n: CHAT_FILES_PER_MESSAGE }));\n let res: Awaited<ReturnType<NonNullable<ExpoImagePicker[\"launchImageLibraryAsync\"]>>>;\n try {\n res = await imagePicker.launchImageLibraryAsync({ allowsMultipleSelection: room > 1, selectionLimit: room, quality: 0.8, exif: false });\n } catch (e) {\n return chat.setError((e as Error).message || t(\"The photos could not be opened.\"));\n }\n if (res.canceled || res.cancelled || !res.assets?.length) return;\n chat.setError(\"\");\n const added: PickedPhoto[] = [];\n for (const a of res.assets.slice(0, room)) {\n const name = a.fileName || a.uri.split(\"/\").pop() || \"photo.jpg\";\n const type = (a.mimeType && Object.values(PHOTO_TYPES).includes(a.mimeType as ChatFile[\"type\"]) ? a.mimeType : PHOTO_TYPES[name.split(\".\").pop()?.toLowerCase() ?? \"\"]) as ChatFile[\"type\"] | undefined;\n if (!type) {\n chat.setError(t(\"Only pictures (PNG, JPEG, WebP, GIF) can be sent.\"));\n continue;\n }\n if (a.fileSize && a.fileSize > CHAT_FILE_MAX_BYTES) {\n chat.setError(tf(\"{name} is larger than 10 MB.\", { name }));\n continue;\n }\n const ph: PickedPhoto = { key: `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`, uri: a.uri, name, type, size: a.fileSize ?? 0, up: Promise.resolve() };\n ph.up = api.uploadChatFile({ uri: a.uri, name, type }).then(\n (r) => {\n ph.id = r.id;\n setPhotos((list) => list.map((x) => (x.key === ph.key ? { ...ph } : x)));\n },\n (e: Error) => {\n setPhotos((list) => list.filter((x) => x.key !== ph.key));\n chat.setError(`${name}: ${e.message}`);\n },\n );\n added.push(ph);\n }\n setPhotos((list) => [...list, ...added]);\n };\n const canSend = (!!body.trim() || photos.length > 0) && !pending && emailOk;\n /** Sends into `to`; what fails comes back into the field of the chat it was written for. */\n const deliver = async (text: string, files: PickedPhoto[], to: ChatPlace) => {\n const api = client.api();\n if (!api) return;\n setPending({\n id: \"pending\",\n from: \"visitor\",\n body: text,\n at: new Date().toISOString(),\n to,\n ...(files.length ? { attachments: files.map((f) => ({ id: f.key, name: f.name, type: f.type, size: f.size })) } : {}),\n });\n chat.setError(\"\");\n try {\n await Promise.all(files.map((f) => f.up));\n const ids = files.filter((f) => f.id).map((f) => f.id!);\n if (!text && !ids.length) throw new Error(t(\"The photo could not be sent.\"));\n // The screen, not the app's window: check-dist keeps the word \"window\" out of the bundle (no browser APIs).\n const win = RN.Dimensions.get(\"screen\");\n // The chat on screen by name, so a message goes where it was written even with another chat running.\n const conversation = to.fresh ? \"new\" : (to.chatId ?? thread?.conversation?.id);\n chat.arrived(\n to,\n await api.sendChat({\n body: text,\n ...(conversation ? { conversation } : {}),\n email: needEmail && email.trim() ? email.trim() : undefined,\n ...(ids.length ? { attachments: ids } : {}),\n // A little context for a bug report: the system and the screen size.\n context: { os: `${RN.Platform.OS === \"ios\" ? \"iOS\" : RN.Platform.OS === \"android\" ? \"Android\" : RN.Platform.OS} ${RN.Platform.Version ?? \"\"}`.trim(), browser: \"App\", viewport: `${Math.round(win.width)}×${Math.round(win.height)}` },\n }),\n );\n } catch (e) {\n const gone = (e as { status?: number }).status === 404;\n chat.enter(gone ? null : to.chatId, gone || to.fresh);\n setBody((typed) => [text, typed.trim()].filter(Boolean).join(\"\\n\"));\n setPhotos((list) => [...files.filter((f) => f.id), ...list]);\n chat.setError(gone ? t(\"This conversation is no longer available. Your message is still here to send as a new one.\") : (e as Error).message);\n } finally {\n setPending(null);\n }\n };\n /** The field inside a chat answers in that chat (a new one while one is being written). */\n const send = () => {\n const text = body.trim();\n const files = photos;\n if ((!text && !files.length) || pending || !emailOk || !client.api()) return;\n setBody(\"\");\n setPhotos([]);\n void deliver(text, files, place);\n };\n /** Messages from a tab or Home: the list once there are several conversations, else the one chat. */\n const openMessages = () => {\n chat.enter(null);\n setView(\"messages\");\n };\n const openChat = (id: string) => {\n chat.enter(id);\n setView(\"messages\");\n };\n const startChat = () => {\n chat.enter(null, true);\n setView(\"messages\");\n };\n /** Home's field: what is typed there starts a new conversation and is sent; empty, it opens Messages. */\n const ask = () => {\n const text = asked.trim();\n if (!text) return openMessages();\n if (pending || !client.api()) return;\n setAsked(\"\");\n startChat();\n // An email that needs correcting is in the chat's field: the words wait there with it.\n if (emailOk) void deliver(text, [], { chatId: null, fresh: true });\n else setBody((typed) => [text, typed.trim()].filter(Boolean).join(\"\\n\"));\n };\n /** Where a file of the chat is read: the photo on this device while it is on its way, else the server's. */\n const localUris = useRef(new Map<string, string>());\n for (const f of photos) localUris.current.set(f.key, f.uri);\n const fileUrl = (id: string) => localUris.current.get(id) ?? client.api()?.attachmentUrl(id) ?? \"\";\n\n const ink = inkOn(p.accent);\n const dark = p.bg === DARK.bg;\n const r = CORNERS[o.corners ?? \"round\"];\n // White surfaces on HeroUI's gray ground; Home's top plain (the default) or in the accent color.\n const plain = o.header !== \"color\";\n const hu = dark ? HU.dark : HU.light;\n // Fills carry no shadow; only the current tab is raised.\n const surf = {};\n const segLift = dark ? {} : hairline;\n const canvas = hu.bg;\n const raised = hu.surface;\n const title = o.title?.trim() ?? \"\";\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 // Sent photos as themselves (a tap opens the full size), a PDF as a chip.\n ...(m.attachments ?? []).map((f) =>\n h(\n RN.Pressable,\n {\n key: f.id,\n onPress: () => void RN.Linking.openURL(fileUrl(f.id)).catch(() => undefined),\n accessibilityRole: \"imagebutton\",\n accessibilityLabel: f.name,\n style: { alignSelf: mine ? \"flex-end\" : \"flex-start\", opacity: isPending ? 0.7 : 1 },\n },\n f.type.startsWith(\"image/\")\n ? h(RN.Image, { source: { uri: fileUrl(f.id) }, resizeMode: \"cover\", style: { width: 200, height: 150, borderRadius: r.bubble, backgroundColor: p.soft } })\n : h(RN.View, { style: { backgroundColor: p.soft, borderRadius: r.card, paddingHorizontal: 10, paddingVertical: 7 } }, k.text(`📄 ${f.name}`, { fontSize: 13 })),\n ),\n ),\n !m.body && m.attachments?.length\n ? null\n : h(\n RN.View,\n {\n style: {\n backgroundColor: mine ? p.accent : hu.surface,\n ...(mine ? {} : surf),\n borderRadius: r.bubble,\n borderBottomRightRadius: mine ? r.tail : r.bubble,\n borderBottomLeftRadius: mine ? r.bubble : r.tail,\n paddingHorizontal: 14,\n paddingVertical: 9,\n opacity: isPending ? 0.7 : 1,\n },\n },\n k.text(m.body, { color: mine ? ink : hu.fg }),\n ),\n ...(m.articles ?? []).map((a) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"link\", style: { backgroundColor: p.soft, borderRadius: r.card, paddingHorizontal: 10, paddingVertical: 7 } },\n k.text(`📄 ${a.title}`, { fontSize: 13 }),\n ),\n ),\n m.at ? k.muted(`${mine ? \"\" : `${who(m.from, o.agentName)} · `}${isPending && slow ? t(\"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 = {}) =>\n h(RN.View, { style: { backgroundColor: raised, borderRadius: r.card, padding: 16, ...surf, ...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: r.field, paddingHorizontal: 14, backgroundColor: hu.def } },\n k.muted(t(\"Search for help\"), { flex: 1, fontSize: 15 }),\n glyph(\"search\", p.accent, 16),\n );\n const search = k.field({ value: query, onChange: setQuery, placeholder: t(\"Search for help\"), max: 200, style: { borderWidth: 0, borderRadius: r.field, backgroundColor: raised, ...surf } });\n // Home's top like the site's: \"Hi, Lukas 👋\" over the greeting in gray (without its own \"Hi!\", said above).\n const first = client.getUser()?.name?.trim().split(/\\s+/)[0];\n const rest = (o.greeting !== undefined ? greeting.replace(/^(hi|hello|hey|hallo|moin|servus|bonjour|salut|hola|ciao|salve|hoi|ol[áa]|cze[śs][ćc]|hej|こんにちは)( there)?\\s*[!,.!、。]*\\s*/i, \"\").trim() : t(\"How can we help?\")) || t(\"How can we help you today?\");\n const hero = (fg: string, sub: string) =>\n h(\n RN.Text,\n { key: \"hero\", accessibilityRole: \"header\", style: { color: fg, fontSize: 25, fontWeight: \"600\", letterSpacing: -0.6, lineHeight: 30 } },\n `${first ? tf(\"Hi, {name}\", { name: first }) : t(\"Hi there\")} 👋\\n`,\n h(RN.Text, { style: { color: sub, fontWeight: \"500\" } }, rest),\n );\n\n /** One conversation as a card: what it was about, where it stands, a count of new answers. */\n const chatRow = (c: ChatSummary) => {\n const m = c.last;\n const n = chat.unseen.filter((u) => u.chat === c.id).length;\n const closed = c.status === \"solved\" ? ` · ${t(\"Closed\")}` : \"\";\n const subject = c.subject || (m ? lineOf(m) : \"\");\n const line = m ? lineOf(m) : \"\";\n return h(\n RN.Pressable,\n { key: c.id, onPress: () => openChat(c.id), accessibilityRole: \"button\", accessibilityLabel: `${tf(\"Conversation: {subject}\", { subject })}${closed}${n ? `, ${tf(\"{n} new\", { n })}` : \"\"}` },\n card(\n [\n h(\n RN.View,\n { key: \"r\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 10 } },\n title ? teamMark(title, alpha(p.accent, 0.16), p.accent, 26) : null,\n h(\n RN.View,\n { style: { flex: 1, gap: 1 } },\n h(RN.Text, { numberOfLines: 1, style: { color: hu.fg, fontSize: 14, fontWeight: \"500\" } }, subject),\n m && line !== subject ? h(RN.Text, { numberOfLines: 1, style: { color: hu.muted, fontSize: 13 } }, line) : null,\n m ? k.muted(`${who(m.from, o.agentName)} · ${timeAgo(m.at)}${closed}`, { fontSize: 11.5 }) : null,\n ),\n n\n ? h(RN.View, { style: { minWidth: 20, height: 20, paddingHorizontal: 5, borderRadius: 10, backgroundColor: p.danger, alignItems: \"center\", justifyContent: \"center\" } }, k.text(String(Math.min(n, 9)), { color: \"#fff\", fontSize: 11, fontWeight: \"700\" }))\n : glyph(\"next\", p.muted, 14),\n ),\n ],\n { paddingVertical: 10, paddingHorizontal: 12 },\n ),\n );\n };\n const showHelp = helpOn && arts.any !== false;\n let content: ReactNode;\n if (view === \"home\") {\n // The conversations still open (a closed one only while there is nothing else); the rest behind \"All\".\n const running = chat.chats.filter((c) => c.status !== \"solved\");\n const rows = (running.length ? running : chat.chats).slice(0, 2);\n const cards = [\n // \"Ask a question\": its own field; the words start a new conversation.\n h(\n RN.View,\n { key: \"ask\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, height: 48, borderRadius: 24, paddingLeft: 18, paddingRight: 6, backgroundColor: hu.surface, ...surf } },\n k.field({ value: asked, onChange: setAsked, placeholder: t(\"Ask a question\"), max: 4000, onSubmit: ask, style: { flex: 1, borderWidth: 0, paddingHorizontal: 0, backgroundColor: \"transparent\" } }),\n h(\n RN.Pressable,\n {\n onPress: ask,\n accessibilityRole: \"button\",\n accessibilityLabel: t(\"Send\"),\n style: { width: 36, height: 36, borderRadius: 18, alignItems: \"center\", justifyContent: \"center\", backgroundColor: asked.trim() ? p.accent : hu.def },\n },\n glyph(\"up\", asked.trim() ? ink : hu.muted, 18),\n ),\n ),\n ...rows.map(chatRow),\n chat.chats.length > rows.length\n ? h(\n RN.Pressable,\n { key: \"all\", onPress: openMessages, accessibilityRole: \"button\", accessibilityLabel: tf(\"All conversations ({n})\", { n: chat.chats.length }), style: { flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\", gap: 4, paddingVertical: 6 } },\n k.muted(tf(\"All conversations ({n})\", { n: chat.chats.length }), { fontSize: 13, fontWeight: \"500\" }),\n glyph(\"next\", p.muted, 12),\n )\n : null,\n showHelp ? card([searchRow(() => setView(\"help\")), ...(arts.list ?? []).slice(0, 4).map(row)], { padding: 8, gap: 2 }) : null,\n ];\n content = plain\n ? h(\n RN.ScrollView,\n { key: \"home\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 24, gap: 12 }, keyboardShouldPersistTaps: \"handled\" },\n h(RN.View, { key: \"top\", style: { paddingHorizontal: 6, paddingBottom: 10 } }, hero(p.fg, p.muted)),\n ...cards,\n )\n : 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 } }, hero(ink, alpha(ink, 0.8))),\n h(RN.View, { style: { marginTop: -48, paddingHorizontal: 16, gap: 12 } }, ...cards),\n );\n } else if (view === \"messages\" && chat.listing)\n content = h(\n RN.ScrollView,\n { key: \"chats\", style: { flex: 1, backgroundColor: canvas }, contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 16, gap: 12 } },\n ...chat.chats.map(chatRow),\n k.btn(t(\"New conversation\"), \"primary\", startChat),\n );\n else if (view === \"messages\")\n content = h(\n RN.View,\n { key: \"messages\", style: { flex: 1, backgroundColor: hu.bg } },\n h(\n RN.ScrollView,\n { ref: scroll, style: { flex: 1 }, contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 16, gap: 12 } },\n // The greeting opens an empty chat only, never above the visitor's first words (2026-10-30).\n !thread?.messages.length && !pendingHere && !place.chatId ? bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }) : null,\n (!chat.loaded && !place.fresh && !pendingHere) || (place.chatId && !thread) ? k.muted(t(\"Loading…\")) : null,\n ...(thread?.messages ?? []).map((m) => bubble(m)),\n pendingHere ? bubble(pendingHere, true) : null,\n thread?.conversation?.status === \"solved\" && !pendingHere ? k.muted(t(\"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: 6, gap: 8 } },\n chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,\n // Photos picked for the next message, each with a way to take it out again.\n photos.length\n ? h(\n RN.View,\n { style: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 10, paddingTop: 6, paddingHorizontal: 2 } },\n ...photos.map((f) =>\n h(\n RN.View,\n { key: f.key, style: { width: 56, height: 56 } },\n h(RN.Image, { source: { uri: f.uri }, resizeMode: \"cover\", accessibilityLabel: f.id ? f.name : tf(\"{name}, uploading\", { name: f.name }), style: { width: 56, height: 56, borderRadius: Math.max(4, r.card - 4), backgroundColor: p.soft, opacity: f.id ? 1 : 0.5 } }),\n h(\n RN.Pressable,\n {\n onPress: () => setPhotos((list) => list.filter((x) => x.key !== f.key)),\n accessibilityRole: \"button\",\n accessibilityLabel: tf(\"Remove {name}\", { name: f.name }),\n hitSlop: 8,\n style: { position: \"absolute\", top: -7, right: -7, width: 22, height: 22, borderRadius: 11, borderWidth: 2, borderColor: p.bg, backgroundColor: p.fg, alignItems: \"center\", justifyContent: \"center\" },\n },\n glyph(\"cross\", p.bg, 10),\n ),\n ),\n ),\n )\n : null,\n // The message field on top, the paperclip (when the app has expo-image-picker) and the send button under it.\n h(\n RN.View,\n { style: { gap: 2, borderRadius: 20, paddingTop: 10, paddingBottom: 6, paddingRight: 6, paddingLeft: 16, backgroundColor: hu.surface, ...surf } },\n // The optional email: the box's first line, under a hairline the message follows.\n needEmail\n ? k.field({\n value: email,\n onChange: setEmail,\n placeholder: t(\"Email for our reply (optional)\"),\n email: true,\n max: 200,\n style: { minHeight: 0, marginRight: 10, marginBottom: 4, paddingHorizontal: 0, paddingTop: 0, paddingBottom: 8, borderWidth: 0, borderRadius: 0, borderBottomWidth: 1, borderBottomColor: emailOk ? p.line : p.danger, backgroundColor: \"transparent\", fontSize: 13.5 },\n })\n : null,\n k.field({ value: body, onChange: setBody, placeholder: t(\"Write a message…\"), multiline: true, max: 4000, style: { minHeight: 28, maxHeight: 120, borderWidth: 0, paddingHorizontal: 0, paddingVertical: 4, backgroundColor: \"transparent\" } }),\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\", marginLeft: -8 } },\n imagePicker?.launchImageLibraryAsync\n ? h(\n RN.Pressable,\n { onPress: () => void pickPhotos(), disabled: !!pending, accessibilityRole: \"button\", accessibilityLabel: t(\"Attach a photo or screenshot\"), hitSlop: 6, style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\" } },\n glyph(\"clip\", hu.muted, 19),\n )\n : null,\n h(RN.View, { style: { flex: 1 } }),\n h(\n RN.Pressable,\n {\n onPress: send,\n disabled: !canSend,\n accessibilityRole: \"button\",\n accessibilityLabel: t(\"Send\"),\n style: { width: 34, height: 34, borderRadius: 17, alignItems: \"center\", justifyContent: \"center\", backgroundColor: canSend ? p.accent : hu.def },\n },\n glyph(\"up\", canSend ? ink : hu.muted, 18),\n ),\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: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 16, gap: 12 }, keyboardShouldPersistTaps: \"handled\" },\n search,\n arts.list === null ? k.muted(t(\"Loading…\")) : null,\n arts.list?.length === 0\n ? h(RN.View, { style: { gap: 10, alignItems: \"center\", paddingVertical: 24 } }, k.muted(query.trim() ? tf(\"Nothing found for “{q}”.\", { q: query.trim() }) : t(\"No help articles yet.\")), k.btn(t(\"Send us a message\"), \"primary\", startChat))\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: { paddingHorizontal: 16, paddingTop: 4, paddingBottom: 32 } },\n h(ArticleView, { client, p, id: view.article, onAsk: startChat }),\n );\n\n const current = typeof view === \"string\" ? view : \"help\";\n // The tabs as HeroUI's Tabs: a gray pill with the current tab on a raised white one.\n const tab = (v: \"home\" | \"messages\" | \"help\", name: string, icon: keyof typeof GLYPH, badge = 0) => {\n const on = current === v;\n return h(\n RN.Pressable,\n {\n key: v,\n onPress: () => (v === \"messages\" ? openMessages() : setView(v)),\n accessibilityRole: \"tab\",\n accessibilityLabel: name,\n accessibilityState: { selected: on },\n // Only the open tab carries its name; the others are icons, so the bar fits a narrow phone.\n style: { ...(on ? { flex: 1 } : { width: 48 }), flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\", gap: 6, height: 36, borderRadius: 18, ...(on ? { backgroundColor: hu.segment, ...segLift } : {}) },\n },\n glyph(icon, on ? hu.fg : hu.muted, 17),\n on ? k.text(name, { fontSize: 13.5, fontWeight: \"500\", color: hu.fg }) : null,\n badge ? h(RN.View, { style: { position: \"absolute\", top: 7, right: 12, width: 8, height: 8, borderRadius: 4, backgroundColor: p.danger } }) : null,\n );\n };\n // The head is only the close button (and the way back on an article), on the ground of what is below it.\n const onAccent = view === \"home\" && !plain;\n const ground = onAccent ? p.accent : hu.bg;\n const back = (to: () => void, label: string) =>\n h(\n RN.Pressable,\n { key: \"back\", onPress: to, accessibilityRole: \"button\", accessibilityLabel: label, hitSlop: 10, style: { width: 32, height: 32, alignItems: \"center\", justifyContent: \"center\", transform: [{ rotate: \"180deg\" }] } },\n glyph(\"next\", hu.fg, 18),\n );\n const head = h(\n RN.View,\n { key: \"head\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingLeft: 12, paddingRight: 12, paddingTop: 12, paddingBottom: 6, backgroundColor: ground } },\n typeof view !== \"string\"\n ? back(() => setView(\"help\"), t(\"All articles\"))\n : view === \"messages\" && !chat.listing && chat.chats.length > 1\n ? back(openMessages, t(\"All conversations\"))\n : view === \"messages\"\n ? back(() => setView(\"home\"), t(\"Back to home\"))\n : view === \"home\" && (o.logo || title)\n ? o.logo\n ? h(RN.Image, { key: \"logo\", source: { uri: o.logo }, accessibilityIgnoresInvertColors: true, resizeMode: \"contain\", style: { height: 28, aspectRatio: 1, maxWidth: 132, borderRadius: 8, marginLeft: 4 } })\n : teamMark(title, alpha(p.accent, 0.16), p.accent, 28)\n : null,\n // In the chat: who answers, in the middle; over the list its name.\n view === \"messages\" && chat.listing\n ? h(RN.View, { style: { flex: 1, alignItems: \"center\" } }, k.text(t(\"Messages\"), { color: hu.fg, fontSize: 15, fontWeight: \"600\" }))\n : view === \"messages\" && title\n ? h(\n RN.View,\n { style: { flex: 1, flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\", gap: 8 } },\n teamMark(title, alpha(p.accent, 0.16), p.accent, 28),\n h(RN.Text, { numberOfLines: 1, style: { flexShrink: 1, color: hu.fg, fontSize: 15, fontWeight: \"600\" } }, title),\n )\n : h(RN.View, { style: { flex: 1 } }),\n h(RN.Pressable, { onPress: close, accessibilityRole: \"button\", accessibilityLabel: t(\"Close\"), hitSlop: 12, style: { width: 32, height: 32, borderRadius: 10, alignItems: \"center\", justifyContent: \"center\" } }, glyph(\"cross\", onAccent ? ink : p.muted, 18)),\n );\n // One quiet line above the tab bar, unless the plan lets the product hide it.\n const powered = brand\n ? h(\n RN.View,\n { key: \"brand\", style: { paddingTop: 2, paddingBottom: 6, alignItems: \"center\", backgroundColor: hu.bg } },\n h(\n RN.Text,\n { onPress: () => void RN.Linking.openURL(BRAND_URL).catch(() => undefined), accessibilityRole: \"link\", hitSlop: 8, style: { color: p.muted, fontSize: 11.5 } },\n t(\"Powered by {brand}\").split(\"{brand}\")[0],\n h(RN.Text, { style: { fontWeight: \"600\" } }, \"MRRocket\"),\n t(\"Powered by {brand}\").split(\"{brand}\")[1],\n ),\n )\n : null;\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: hu.bg } },\n head,\n content,\n view === \"messages\" && !chat.listing ? null : h(\n RN.View,\n { key: \"tabs\", accessibilityRole: \"tablist\", style: { flexDirection: \"row\", marginHorizontal: 12, marginTop: 6, marginBottom: 6, padding: 4, borderRadius: 22, backgroundColor: hu.surface } },\n tab(\"home\", t(\"Home\"), \"home\"),\n tab(\"messages\", t(\"Messages\"), \"chat\", chat.unseen.length),\n showHelp ? tab(\"help\", t(\"Help\"), \"help\") : null,\n ),\n powered,\n h(RN.View, { style: { height: 16 } }),\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 // Another language: the look's words again (the provider draws this anew when the words change).\n }, [client, wordsVersion()]);\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 corners: look.corners,\n header: look.header,\n logo: look.logo,\n agentName: look.agentName,\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<UnseenAnswer | null>(null);\n const setView = (v: MsgView) => {\n msgView = v;\n setViewState(v);\n };\n const chat = useChat(client, options, open, view);\n const { enter } = chat;\n useEffect(() => {\n if (!open) return;\n setViewState(msgView);\n if (msgView === \"messages\") enter(msgChat);\n }, [open, enter]);\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 news = latest?.chat ?? null;\n const ink = inkOn(p.accent);\n const label = options.label?.trim() ?? \"\";\n const r = CORNERS[options.corners ?? \"round\"];\n // The chat button's place: top, middle or bottom, and left, center or right.\n const [edge, side] = (options.position ?? \"bottom-right\").split(\"-\") as [\"top\" | \"middle\" | \"bottom\", \"left\" | \"center\" | \"right\"];\n const place: Style = {\n ...(edge === \"top\" ? { top: 60 } : edge === \"bottom\" ? { bottom: 34 } : { top: 0, bottom: 0, justifyContent: \"center\" }),\n ...(side === \"left\" ? { left: 20 } : side === \"right\" ? { right: 20 } : { left: 0, right: 0, alignItems: \"center\" }),\n };\n const launcher = options.launcher\n ? h(\n RN.View,\n { key: \"launcher\", pointerEvents: \"box-none\", style: { position: \"absolute\", ...place } },\n h(\n RN.Pressable,\n {\n onPress: () => openAt(news ? \"messages\" : \"home\", news),\n accessibilityRole: \"button\",\n accessibilityLabel: unseen === 1 ? t(\"Open chat, 1 new reply\") : unseen ? tf(\"Open chat, {n} new replies\", { n: unseen }) : t(\"Open chat\"),\n style: {\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 )\n : null;\n // The banner: who answered and the first lines, on a card with a soft shadow.\n const toast = banner\n ? h(\n RN.Pressable,\n {\n key: \"banner\",\n onPress: () => openAt(\"messages\", banner.chat),\n accessibilityRole: \"button\",\n accessibilityLiveRegion: \"polite\",\n style: {\n position: \"absolute\",\n top: 54,\n left: 16,\n right: 16,\n gap: 3,\n backgroundColor: p.bg === DARK.bg ? p.soft : p.bg,\n borderRadius: r.card + 2,\n paddingHorizontal: 16,\n paddingVertical: 13,\n shadowColor: \"#101218\",\n shadowOpacity: 0.14,\n shadowRadius: 18,\n shadowOffset: { width: 0, height: 8 },\n elevation: 6,\n },\n },\n k.muted(`${who(banner.from, options.agentName)}${unseen > 1 ? ` · ${tf(\"{n} new\", { n: unseen })}` : \"\"}`, { fontWeight: \"600\", fontSize: 12 }),\n h(RN.Text, { numberOfLines: 3, style: { color: p.fg, fontSize: 15, lineHeight: 20 } }, banner.body),\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, brand: look?.branding !== false }) : null,\n );\n};\n"],"mappings":"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","names":["import_react","same","s","s","h","s","t","t","s","ended","g","same","who","text","s","g","h","g","who","s","s","t","s","h","t","clip","s","t","who","options","import_react","h","_","t","text","s","m","v","RN","s","h","import_react","RN","text","h","t","who","s","svg","shown","r","RN","text"]}
|