@mrrocket/sdk 0.16.0 → 0.17.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 +19 -0
- package/README.md +11 -2
- package/dist/api-client.d.ts +7 -1
- package/dist/api-client.js.map +1 -1
- package/dist/browser/mrrocket-flows.js +9 -2
- package/dist/browser/mrrocket-messenger.js +42 -43
- package/dist/browser/mrrocket.js +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/flows-ui.d.ts +1 -1
- package/dist/flows-ui.js +64 -14
- package/dist/flows-ui.js.map +1 -1
- package/dist/flows.d.ts +49 -3
- package/dist/flows.js +86 -7
- package/dist/flows.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/messenger-ui.d.ts +10 -2
- package/dist/messenger-ui.js +57 -46
- package/dist/messenger-ui.js.map +1 -1
- package/dist/react-native/index.d.cts +46 -7
- package/dist/react-native/index.d.ts +46 -7
- package/dist/react-native/index.js +135 -31
- package/dist/react-native/index.js.map +1 -1
- package/dist/styles-css.d.ts +1 -1
- package/dist/styles-css.js +40 -41
- package/dist/styles-css.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/native/index.tsx","../../src/core.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/native/platform.ts","../../src/native/widgets-view.ts"],"sourcesContent":["/**\n * `@mrrocket/sdk/react-native`: the MRRocket SDK for React Native and Expo apps.\n *\n * // app/_layout.tsx (Expo Router)\n * import { MRRocketProvider, useExpoRouterTracking } from \"@mrrocket/sdk/react-native\";\n *\n * function Screens() {\n * useExpoRouterTracking();\n * return <Stack />;\n * }\n *\n * export default function RootLayout() {\n * return (\n * <MRRocketProvider apiKey=\"mrr_pub_…\">\n * <Screens />\n * </MRRocketProvider>\n * );\n * }\n *\n * No DOM, no \"use client\", no session recorder: Metro bundles it as is. See the README for what it sends.\n */\nimport { type ReactNode, createContext, createElement, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { type CockpitConfig, SDK_VERSION, type VariantId } from \"../core\";\nimport type { CancelFlowOptions, CancelFlowResult } from \"../flows\";\nimport { type KeyValueStorage, type MRRocketClient, type MRRocketOptions, activeRouteName, createClient } from \"./client\";\nimport { MRRocketFlows, type NativeAppearance } from \"./flows-view\";\nimport { nativeDeps, optionalModules } from \"./platform\";\nimport { type Measurable, maskedViews } from \"./recorder\";\nimport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, type NativeFeedbackOptions, type NativeMessengerOptions, useFeedback, useMessenger } from \"./widgets-view\";\n\nexport type { AppContext, CockpitConfig, FlagConfig, VariantId } from \"../core\";\nexport type { CancelFlowConfig, CancelFlowOptions, CancelFlowResult, CancelOffer, FlowView, InAppMessage, OnboardingFlow, OnboardingStep } from \"../flows\";\nexport { MRRocketFlows, type NativeAppearance };\nexport 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/** Starts an onboarding flow now (the first live one without an id), whatever its trigger. */\nexport const useOnboarding = (): { start: (id?: string) => boolean } => {\n const client = useClient();\n return { start: client.startOnboarding };\n};\n\n/** A feature flag from MRRocket › Build › Feature flags: true while it is on for this person; false while off, unknown or loading. */\nexport const useFlag = (key: string): boolean => {\n const client = useClient();\n useVersion(client);\n return client.getFlag(key);\n};\n\n/** The variant of a multivariate flag (\"control\", \"test\" …), or null while it is off. */\nexport const useFlagVariant = (key: string): string | null => {\n const client = useClient();\n useVersion(client);\n return client.getFlagVariant(key);\n};\n\n/**\n * The variant of an experiment this person sees (\"control\" until the config is known; the cached config is used on a\n * cold start, so the first screen is already stable). Records the exposure once per screen.\n */\nexport const useVariant = (key: string): VariantId => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const variant = client.peekVariant(key);\n useEffect(() => {\n if (config) client.expose(key, variant);\n }, [client, config, key, variant]);\n return variant;\n};\n\n/**\n * Copy MRRocket can change without an app update: the text published for `id` (a paywall's\n * `paywall.<placement>.headline`, `.body`, `.cta`), with this person's variant of a running text test on top,\n * the same rules as `<Text id>` on the web. Write your own words as `fallback`: they show while nothing is published\n * and on a first start before the config arrives. Records the exposure to every test that changes `id`, once per screen.\n *\n * const headline = useText(\"paywall.onboarding.headline\", \"Unlock everything\");\n * <Text style={styles.title}>{headline}</Text>\n */\nexport const useText = (id: string, fallback: string): string => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const text = client.peekText(id);\n const person = client.getDistinctId();\n useEffect(() => {\n if (config) client.exposeText(id);\n }, [client, config, id, person]);\n return text ?? fallback;\n};\n\ntype ExpoRouterModule = { usePathname: () => string };\nlet expoRouter: ExpoRouterModule | null | undefined;\nconst loadExpoRouter = (): ExpoRouterModule | null => {\n if (expoRouter !== undefined) return expoRouter;\n try {\n expoRouter = require(\"expo-router\") as ExpoRouterModule;\n } catch {\n expoRouter = null;\n }\n return expoRouter;\n};\nconst noPathname = () => undefined;\nlet routerWarned = false;\n\n/**\n * Screen views for Expo Router: one `$screen` per path (\"/settings\", \"/product/[id]\" as its real path). Call it in a\n * component inside both the router and MRRocketProvider, for example the root layout's child.\n */\nexport const useExpoRouterTracking = () => {\n const client = useClient();\n const router = loadExpoRouter();\n if (router === null && !routerWarned) {\n routerWarned = true;\n console.warn(\"[MRRocket] useExpoRouterTracking needs expo-router. With React Navigation use useNavigationTracking.\");\n }\n const pathname = (router?.usePathname ?? noPathname)();\n useEffect(() => {\n if (pathname) client.screen(pathname);\n }, [client, pathname]);\n};\n\n/**\n * Screen views for React Navigation: pass the result to the container's `onStateChange`, and call it once in `onReady`\n * with the root state, so the first screen counts too.\n *\n * const ref = useNavigationContainerRef();\n * const onStateChange = useNavigationTracking();\n * <NavigationContainer ref={ref} onReady={() => onStateChange(ref.getRootState())} onStateChange={onStateChange}>\n */\nexport const useNavigationTracking = () => {\n const client = useClient();\n return useCallback(\n (state: unknown) => {\n const name = activeRouteName(state);\n if (name) client.screen(name);\n },\n [client],\n );\n};\n","/**\n * The part of the SDK that runs anywhere: experiment config, variant assignment, preview links and event shapes.\n * No React, no browser APIs, so the server helper, the proxy helper and the client share it.\n */\nimport type { CancelFlowConfig, OnboardingFlow } from \"./flows\";\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.16.0\";\n\n/** One variant of an experiment. `changes` replaces texts that the page marks with `<Text id>`. */\nexport interface VariantConfig {\n id: VariantId;\n /** Share of traffic, 0 to 1. The weights of an experiment add up to 1. */\n weight: number;\n changes?: Record<string, string>;\n /**\n * A redirect test: where this variant sends the visitor instead of the test's page (a path like \"/pricing-b\" or a\n * full address). Control has none and stays. SDK 0.7.0+.\n */\n url?: string;\n}\n\nexport interface ExperimentConfig {\n /** The experiment's key, the same as in Cockpit. */\n key: string;\n status: \"running\" | \"draft\" | \"stopped\";\n /** Control first. */\n variants: VariantConfig[];\n /** A winner that shipped: everyone gets it, and nobody is assigned anymore. */\n winner?: VariantId;\n /** A redirect test: the path of the page it runs on (\"/pricing\"). Visitors there are sent to their variant's `url`. */\n path?: string;\n}\n\n/** A page redirect set in MRRocket (Conversion › Landing pages › Redirect): everyone on `from` goes to `to`. SDK 0.7.0+. */\nexport interface RedirectConfig {\n /** A path of the site, like \"/old-pricing\". */\n from: string;\n /** A path or a full address. */\n to: string;\n}\n\nexport interface CockpitConfig {\n /** The product the public key belongs to. */\n project: string;\n experiments: ExperimentConfig[];\n /** The product's affiliate program: how many days a partner's referral is kept. Missing without a program. */\n referral?: { cookieDays: number };\n /** Session recordings: present only while the product records (Cockpit › Sessions). See `ReplayConfig`. */\n replay?: ReplayConfig;\n /** Feature flags of the product in Production (MRRocket › Build › Feature flags), evaluated by `useFlag` and `getFlag`. */\n flags?: FlagConfig[];\n /**\n * Published copy for texts the site marks (`<Text id>`, `data-ck-text`): a landing page's headline, subheadline and\n * button (`pricing.headline` …) and a paywall's (`paywall.<placement>.headline` …) as published in MRRocket. A\n * running test's variant changes them on top. Missing when nothing is published. SDK 0.5.0+.\n */\n texts?: Record<string, string>;\n /** The product's live cancel flow (MRRocket › Churn › Cancel flow), for `cancelFlow.open()`. SDK 0.7.0+. */\n cancelFlow?: CancelFlowConfig;\n /** The in-app steps of live onboarding flows (tours, checklists, modals). SDK 0.7.0+. */\n onboarding?: OnboardingFlow[];\n /** A live Lifecycle journey has in-app messages: signed-in people ask `/api/sdk/inapp` for theirs. SDK 0.7.0+. */\n messages?: boolean;\n /** Page redirects set in MRRocket; the SDK sends visitors on before the page shows (`redirectFor`). SDK 0.7.0+. */\n redirects?: RedirectConfig[];\n /** 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 * 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 product's icon (its favicon) at the top left of Home; without it the title's first letter. */\n logo?: 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.\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\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\";\n\nexport interface OnboardingStep {\n id: string;\n kind: OnboardingStepKind;\n title: string;\n body?: string;\n button?: string;\n /** Tour steps: the element they point at, marked `data-ck-target=\"<target>\"` in the app. Without it: a card. */\n target?: string;\n /** Checklist items: the event that ticks them (`track(\"<event>\")`). Without it the person ticks it themselves. */\n event?: string;\n}\n\n/** A pause in a flow (0.11.0): the next step shows this long after the one before was done. */\nexport interface OnboardingWait {\n id: string;\n kind: \"wait\";\n amount: number;\n unit: \"hours\" | \"days\";\n}\n\n/**\n * A fork in a flow (0.11.0): \"Did <event> happen?\" (the person's events, here and on MRRocket) or \"Is on <page>?\" (the\n * page they are on when they reach it; `*` at the end for everything below). Decided once, when the person reaches it;\n * like a journey's branch it ends its line, the rest of the flow lives in its two paths.\n */\nexport interface OnboardingCondition {\n id: string;\n kind: \"condition\";\n event?: string;\n page?: string;\n yes: OnboardingNode[];\n no: OnboardingNode[];\n}\n\nexport type OnboardingNode = OnboardingStep | OnboardingWait | OnboardingCondition;\n\n/** A live onboarding flow's in-app steps (MRRocket › Conversion › Onboarding); its emails go out from MRRocket. */\nexport interface OnboardingFlow {\n id: string;\n name: string;\n /** When it starts: an event's words (\"Signed up\", \"First export\"), or \"First launch\" / \"First visit\". */\n trigger: string;\n /** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */\n steps: OnboardingStep[];\n /** 0.11.0+: the whole flow with its waits and conditions. Read instead of `steps` when it is there. */\n nodes?: OnboardingNode[];\n}\n\n/** An in-app message a Lifecycle journey has for this person. */\nexport interface InAppMessage {\n id: string;\n journey?: string;\n title: string;\n body?: string;\n button?: string;\n /** Where the button goes (http(s) or a path of the app). */\n url?: string;\n style: \"banner\" | \"modal\";\n}\n\n/** One flow's progress: the steps done, whether the person closed it, and (0.11.0) its decided conditions and times. */\nexport interface FlowProgress {\n done: string[];\n dismissed?: boolean;\n /** Each decided condition's path. */\n answers?: Record<string, \"yes\" | \"no\">;\n /** When each step was done and each wait was reached (ms since 1970). */\n at?: Record<string, number>;\n reached?: Record<string, number>;\n}\n\n/** What `GET /api/sdk/inapp` answers for one signed-in person. */\nexport interface InAppState {\n /** Progress per onboarding flow: the steps done and whether the person closed it. */\n onboarding: Record<string, FlowProgress>;\n messages: InAppMessage[];\n /** 0.11.0: the events the flows' conditions ask about that this person did (as `eventSlug`s). */\n events?: string[];\n /**\n * 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 | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean }\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean }[] }\n | { type: \"message\"; message: InAppMessage };\n\nexport interface FlowsEnv {\n /** Records an event under the SDK's consent (the normal queue). */\n track(event: string, props?: Record<string, unknown>): void;\n /** Whose messages and progress these are: the identify() id; undefined while nobody is signed in. */\n personId(): string | undefined;\n /** `GET /api/sdk/inapp` for that person; null when it fails. */\n fetchInApp(personId: string): Promise<InAppState | null>;\n /** Keeps onboarding progress on the device; only while the consent lets the SDK store something. */\n storage?: () => { get(key: string): string | null | Promise<string | null>; set(key: string, value: string): void } | null;\n /** Opens a message's link. */\n openUrl?: (url: string) => void;\n /** Start onboarding flows by their trigger on its own (default true). */\n auto?: boolean;\n /** The page the person is on (a path), for \"Is on <page>?\" conditions; without it they answer no. */\n path?: () => string | undefined;\n /** The clock, for tests. */\n now?: () => number;\n}\n\nexport interface FlowsController {\n setConfig(config: CockpitConfig | null): void;\n /** The person changed (identify, reset, consent): loads their messages and onboarding progress. */\n refresh(): Promise<void>;\n /** An event the app recorded: starts flows whose trigger it is and ticks checklist items. */\n onEvent(name: string): void;\n openCancelFlow(options?: CancelFlowOptions): Promise<CancelFlowResult>;\n /** Starts an onboarding flow now (the first live one without an id). False when there is none to start. */\n startOnboarding(id?: string): boolean;\n view(): FlowView | null;\n subscribe(listener: () => void): () => void;\n /** `accept(comment)`: a \"Talk to us\" offer sends what the customer wrote with it. */\n /** `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 onboarding: { next(): void; check(stepId: string): void; dismiss(): void };\n message: { click(): void; dismiss(): void };\n}\n\n/** The plain confirmation, when the product has no live cancel flow (or MRRocket was not reachable). */\nexport const PLAIN_CANCEL: CancelFlowConfig = {\n version: 0,\n question: \"\",\n reasons: [],\n offers: {},\n confirm: { title: \"Cancel your subscription?\", body: \"You keep access until the end of the billing period.\", button: \"Cancel subscription\" },\n offersFor: \"business\",\n};\n\nconst FAILED = \"Something went wrong. Please try again.\";\nconst PROGRESS_KEY = \"mrrocket:onboarding\";\n\n/** `\"Signed up\"` → `signed_up`, the way MRRocket names events from words. */\nexport const eventSlug = (s: string) =>\n s\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst SIGNUP = new Set([\"signed_up\", \"signup\", \"sign_up\", \"registered\", \"account_created\", \"user_signed_up\"]);\n\n/** Whether recording `event` is the trigger's moment (\"Signed up\" is any of the usual signup event names). */\nexport const matchesTrigger = (trigger: string, event: string) => {\n const t = eventSlug(trigger);\n const e = eventSlug(event);\n if (!t || !e) return false;\n return t === e || (SIGNUP.has(t) && SIGNUP.has(e));\n};\n\n/** Triggers that mean \"the first time the person opens the app\": the flow starts on load until it is done. */\nexport const startsOnLoad = (trigger: string) =>\n /^(first (launch|visit|open|session|login|sign ?in|app open)|app (opened|launched)|on load|every visit|always)?$/i.test(trigger.trim());\n\n/** A random id for one cancel flow run. */\nexport const runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;\n\n/** The money a discount leaves: `29 EUR` at 30 % → `20.30`. */\nexport const discounted = (amount: number, percent: number) => Math.round(amount * (1 - percent / 100) * 100) / 100;\n\n/** \"€20.30\" in the customer's own currency, without a library. */\nexport const money = (amount: number, currency: string) => {\n try {\n return new Intl.NumberFormat(undefined, { style: \"currency\", currency }).format(amount);\n } catch {\n return `${amount.toFixed(2)} ${currency}`;\n }\n};\n\n/** The button of an offer. */\nexport const offerButton = (o: CancelOffer) =>\n o.kind === \"contact\" ? \"Send to the team\" : o.kind === \"pause\" ? \"Pause instead\" : o.kind === \"downgrade\" ? \"Switch plan\" : \"Accept offer\";\n\n/** A link a message may open: http(s), or a path of the app. Nothing else (no `javascript:`). */\nexport const safeUrl = (url: string | undefined) => {\n const u = (url ?? \"\").trim();\n return /^https?:\\/\\//i.test(u) || /^\\/(?!\\/)/.test(u) ? u : undefined;\n};\n\ninterface Progress {\n done: Set<string>;\n dismissed: boolean;\n answers: Map<string, boolean>;\n at: Map<string, number>;\n reached: Map<string, number>;\n}\n\n/** The flow's nodes: the whole tree (0.11.0 config), or the plain steps of an older one. */\nexport const nodesOf = (f: OnboardingFlow): OnboardingNode[] => f.nodes ?? f.steps;\n\n/** How long a wait lasts. */\nexport const waitMs = (w: Pick<OnboardingWait, \"amount\" | \"unit\">) => Math.max(0, w.amount) * (w.unit === \"hours\" ? 3_600_000 : 86_400_000);\n\n/** Whether a path matches a condition's page: the same path, or below it for a pattern ending in `*`. */\nexport const pageMatches = (pattern: string, path: string) => {\n const p = pattern.trim();\n const at = (path.split(/[?#]/)[0] || \"/\").replace(/\\/+$/, \"\") || \"/\";\n if (!p) return false;\n if (p.endsWith(\"*\")) {\n const base = p.slice(0, -1).replace(/\\/+$/, \"\");\n return !base || at === base || at.startsWith(`${base}/`);\n }\n return at === (p.replace(/\\/+$/, \"\") || \"/\");\n};\n\n/** Every in-app step of a tree, in reading order (for ticking checklist items by their event). */\nconst stepsIn = (nodes: OnboardingNode[]): OnboardingStep[] =>\n nodes.flatMap((n) => (n.kind === \"condition\" ? [...stepsIn(n.yes), ...stepsIn(n.no)] : n.kind === \"wait\" ? [] : [n]));\n\ntype Walked =\n | { at: \"step\"; step: OnboardingStep; line: OnboardingNode[]; index: number; before: number }\n | { at: \"wait\"; until: number }\n | { at: \"pending\" }\n | { at: \"end\" };\n\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\n const flows = () => config?.onboarding ?? [];\n const flowById = (id: string | null) => (id ? flows().find((f) => f.id === id) : undefined);\n const prog = (id: string) => {\n let p = progress.get(id);\n if (!p) progress.set(id, (p = { done: new Set(), dismissed: false, answers: new Map(), at: new Map(), reached: new Map() }));\n return p;\n };\n\n let dirty = false;\n const record = (props: Record<string, unknown>) => {\n env.track(ONBOARDING_EVENT, props);\n dirty = true;\n };\n const markDone = (p: Progress, id: string) => {\n p.done.add(id);\n p.at.set(id, now());\n };\n\n /** A condition's answer for this person, or undefined while what it asks is not known yet. */\n const decide = (c: OnboardingCondition): boolean | undefined => {\n if (c.page?.trim()) {\n const path = env.path?.();\n return path === undefined ? false : pageMatches(c.page, path);\n }\n if (c.event?.trim()) {\n // The person's events from MRRocket arrive with their progress: before that, wait.\n if (!known) return undefined;\n for (const e of seenEvents) if (matchesTrigger(c.event, e)) return true;\n return false;\n }\n return false;\n };\n\n /**\n * Where the person is in a line of the flow. `live`: it is their flow now, so reaching a wait starts it, a decided\n * condition is kept and both are recorded; otherwise nothing changes (to ask whether a flow is finished).\n */\n const walkLine = (flow: OnboardingFlow, line: OnboardingNode[], p: Progress, live: boolean, before = 0, last?: number): Walked => {\n for (let i = 0; i < line.length; i++) {\n const n = line[i];\n if (n.kind === \"wait\") {\n if (p.done.has(n.id)) {\n last = p.at.get(n.id) ?? last;\n continue;\n }\n let since = p.reached.get(n.id);\n if (since === undefined) {\n if (!live) return { at: \"pending\" };\n // Counted from when the step before was done; a flow that opens with a wait counts from now.\n since = last ?? now();\n p.reached.set(n.id, since);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"shown\" });\n }\n const until = since + waitMs(n);\n if (now() < until) return { at: \"wait\", until };\n if (!live) return { at: \"pending\" };\n markDone(p, n.id);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"completed\" });\n last = until;\n continue;\n }\n if (n.kind === \"condition\") {\n let answer = p.answers.get(n.id);\n if (answer === undefined) {\n if (!live) return { at: \"pending\" };\n answer = decide(n);\n if (answer === undefined) return { at: \"pending\" };\n p.answers.set(n.id, answer);\n record({ flow: flow.id, step: n.id, kind: \"condition\", action: \"answered\", answer: answer ? \"yes\" : \"no\" });\n }\n return walkLine(flow, answer ? n.yes : n.no, p, live, before, last);\n }\n if (!p.done.has(n.id)) return { at: \"step\", step: n, line, index: i, before };\n last = p.at.get(n.id) ?? last;\n before++;\n }\n return { at: \"end\" };\n };\n\n const finished = (f: OnboardingFlow) => {\n const p = progress.get(f.id);\n return !!p && (p.dismissed || walkLine(f, nodesOf(f), p, false).at === \"end\");\n };\n\n const keyOf = (pid: string | undefined) => `${PROGRESS_KEY}:${pid ?? \"visitor\"}`;\n const eventsKeyOf = (pid: string | undefined) => `${PROGRESS_KEY}:events:${pid ?? \"visitor\"}`;\n\n const save = () => {\n dirty = false;\n const store = env.storage?.();\n if (!store) return;\n const out: Record<string, FlowProgress> = {};\n for (const [id, p] of progress)\n out[id] = {\n done: [...p.done],\n ...(p.dismissed ? { dismissed: true } : {}),\n ...(p.answers.size ? { answers: Object.fromEntries([...p.answers].map(([k, v]) => [k, v ? \"yes\" : \"no\"])) } : {}),\n ...(p.at.size ? { at: Object.fromEntries(p.at) } : {}),\n ...(p.reached.size ? { reached: Object.fromEntries(p.reached) } : {}),\n };\n try {\n store.set(keyOf(env.personId()), JSON.stringify(out));\n if (seenEvents.size) store.set(eventsKeyOf(env.personId()), JSON.stringify([...seenEvents].slice(-200)));\n } catch {\n // Storage full or gone: progress stays in memory.\n }\n };\n\n const merge = (state: InAppState[\"onboarding\"] | undefined) => {\n for (const [id, s] of Object.entries(state ?? {})) {\n const p = prog(id);\n for (const d of s.done ?? []) p.done.add(d);\n if (s.dismissed) p.dismissed = true;\n // A condition decided elsewhere keeps its path; the earliest time wins for waits.\n for (const [k, v] of Object.entries(s.answers ?? {})) if (!p.answers.has(k)) p.answers.set(k, v === \"yes\");\n for (const [k, v] of Object.entries(s.at ?? {})) if (typeof v === \"number\" && !p.at.has(k)) p.at.set(k, v);\n for (const [k, v] of Object.entries(s.reached ?? {})) if (typeof v === \"number\" && (!p.reached.has(k) || v < p.reached.get(k)!)) p.reached.set(k, v);\n }\n };\n\n // ---------- What shows ----------\n\n /** Comes back when a short wait is over, so the next step shows without a reload (long waits wait for the next visit). */\n const wakeAt = (until: number) => {\n if (timer) clearTimeout(timer);\n timer = null;\n const ms = until - now();\n if (ms > 0 && ms <= 86_400_000) {\n timer = setTimeout(() => ((timer = null), emit()), ms + 50);\n // Never what keeps a process alive (tests, server rendering).\n (timer as { unref?: () => void }).unref?.();\n }\n };\n\n /** The active flow waits (a wait step, or a condition whose answer is not known yet): it stays the active one. */\n let holding = false;\n\n const onboardingView = (): FlowView | null => {\n holding = false;\n const flow = flowById(active);\n if (!flow) return null;\n const p = prog(flow.id);\n if (p.dismissed) return null;\n const w = walkLine(flow, nodesOf(flow), p, true);\n if (dirty) save();\n if (w.at === \"wait\") wakeAt(w.until);\n holding = w.at === \"wait\" || w.at === \"pending\";\n if (w.at !== \"step\") return null;\n const { step, line, index } = w;\n const isStep = (n: OnboardingNode | undefined): n is OnboardingStep => !!n && n.kind !== \"wait\" && n.kind !== \"condition\";\n if (step.kind === \"checklist\") {\n let from = index;\n while (from > 0 && isStep(line[from - 1]) && line[from - 1].kind === \"checklist\") from--;\n let to = index;\n while (to + 1 < line.length && isStep(line[to + 1]) && line[to + 1].kind === \"checklist\") to++;\n const items = line.slice(from, to + 1).filter(isStep);\n for (const i of items)\n if (!p.done.has(i.id) && !shown.has(`s:${i.id}`)) {\n shown.add(`s:${i.id}`);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: i.id, kind: \"checklist\", action: \"shown\" });\n }\n return { type: \"checklist\", flow, items: items.map((s) => ({ step: s, done: p.done.has(s.id) })) };\n }\n if (!shown.has(`s:${step.id}`)) {\n shown.add(`s:${step.id}`);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: step.id, kind: step.kind, action: \"shown\" });\n }\n // The dots: the steps behind on the person's path, this one, and the ones left on its line before any fork.\n const rest = line.slice(index + 1);\n const fork = rest.findIndex((n) => n.kind === \"condition\");\n const ahead = (fork < 0 ? rest : rest.slice(0, fork)).filter(isStep).length;\n return { type: \"step\", flow, step, index: w.before, total: w.before + 1 + ahead, last: !ahead && fork < 0 };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const 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) active = null;\n const m = messages.find((x) => !handled.has(x.id));\n return m ? { type: \"message\", message: m } : null;\n };\n\n /** Tells the renderers, and records what became visible (once per step or message per page load). */\n const emit = () => {\n // Onboarding steps record their \"shown\" where they are worked out (onboardingView), so a step a wait let through\n // counts also when nothing else changed.\n const v = view();\n if (v?.type === \"message\" && !shown.has(`m:${v.message.id}`)) {\n shown.add(`m:${v.message.id}`);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"shown\" });\n }\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n\n const start = (flow: OnboardingFlow) => {\n if (active === flow.id) return true;\n if (active && flowById(active) && !finished(flowById(active)!)) return false;\n active = flow.id;\n env.track(ONBOARDING_EVENT, { flow: flow.id, action: \"started\" });\n emit();\n return true;\n };\n\n /** Flows whose trigger is \"the first launch\" start once their progress is known (never twice for a done flow). */\n const autoStart = () => {\n if (!auto || active || !known) return;\n // Without an id or storage a \"first launch\" could not be told from any other: no automatic start then.\n if (!env.personId() && !env.storage?.()) return;\n const next = flows().find((f) => startsOnLoad(f.trigger) && nodesOf(f).length && !finished(f));\n if (next) start(next);\n };\n\n const refresh = () => {\n const pid = env.personId();\n // Another person on this device: nothing of the one before carries over.\n if (progressFor !== null && progressFor !== pid) {\n progress.clear();\n seenEvents.clear();\n handled.clear();\n active = null;\n loadedFor = undefined;\n }\n progressFor = pid;\n const run = (async () => {\n const store = env.storage?.();\n if (store) {\n try {\n const raw = await store.get(keyOf(pid));\n if (raw) merge(JSON.parse(raw) as InAppState[\"onboarding\"]);\n const seen = await store.get(eventsKeyOf(pid));\n if (seen) for (const e of JSON.parse(seen) as string[]) if (typeof e === \"string\") seenEvents.add(e);\n } catch {\n // A damaged entry is ignored.\n }\n }\n const wants = flows().length > 0 || !!config?.messages;\n if (pid && wants && loadedFor !== pid) {\n loadedFor = pid;\n const state = await env.fetchInApp(pid).catch(() => null);\n if (state && env.personId() === pid) {\n merge(state.onboarding);\n for (const e of state.events ?? []) if (typeof e === \"string\") seenEvents.add(eventSlug(e));\n messages = (state.messages ?? []).filter((m) => m && m.id && m.title);\n }\n }\n if (!pid) messages = [];\n known = true;\n autoStart();\n emit();\n })();\n loading = run.finally(() => {\n if (loading === run) loading = null;\n });\n return loading;\n };\n\n // ---------- Cancel flow ----------\n\n /** 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 if (!name || name.startsWith(\"$\")) return;\n // Remembered for \"Did <event> happen?\" conditions the person reaches later.\n const slug = eventSlug(name);\n const fresh = !!slug && !seenEvents.has(slug);\n if (fresh) seenEvents.add(slug);\n const flow = flowById(active);\n let ticked = false;\n if (flow) {\n const p = prog(flow.id);\n for (const s of stepsIn(nodesOf(flow)))\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n markDone(p, s.id);\n ticked = true;\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n }\n if (ticked || (fresh && flow)) {\n save();\n emit();\n } else if (fresh) save();\n // Like the first-launch start: only for someone whose progress is kept, so nobody gets a flow twice.\n if (!auto || (!env.personId() && !env.storage?.())) return;\n const next = flows().find((f) => nodesOf(f).length && matchesTrigger(f.trigger, name) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !finished(x));\n if (!f || !nodesOf(f).length) return false;\n const p = prog(f.id);\n // Started by hand: a flow the person closed before shows again.\n p.dismissed = false;\n return start(f);\n },\n view,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n cancel: {\n pick: (reason) => {\n if (!cancel || cancel.busy || cancel.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 markDone(prog(v.flow.id), v.step.id);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: \"completed\" });\n save();\n emit();\n },\n check: (stepId) => {\n const v = onboardingView();\n if (v?.type !== \"checklist\") return;\n const item = v.items.find((i) => i.step.id === stepId);\n if (!item || item.done) return;\n markDone(prog(v.flow.id), stepId);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: stepId, kind: \"checklist\", action: \"completed\" });\n save();\n emit();\n },\n dismiss: () => {\n const v = onboardingView();\n if (!v || (v.type !== \"step\" && v.type !== \"checklist\")) return;\n prog(v.flow.id).dismissed = true;\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, ...(v.type === \"step\" ? { step: v.step.id } : {}), action: \"dismissed\" });\n active = null;\n save();\n emit();\n },\n },\n message: {\n click: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"clicked\" });\n const url = safeUrl(v.message.url);\n emit();\n if (url) env.openUrl?.(url);\n },\n dismiss: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"dismissed\" });\n emit();\n },\n },\n };\n return controller;\n};\n","/**\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, 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 /** 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 });\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).\n */\nimport { type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FlowsController, discounted, money, offerButton } from \"../flows\";\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 useColorScheme?: () => string | null | undefined;\n}\nconst RN = require(\"react-native\") as RNModule;\n\nexport interface NativeAppearance {\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n}\n\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nexport const LIGHT = { bg: \"#ffffff\", fg: \"#1c1d20\", muted: \"#5d6068\", soft: \"#f4f5f7\", line: \"#e4e5e8\" };\nexport const DARK = { bg: \"#17181b\", fg: \"#f1f2f4\", muted: \"#a9acb3\", soft: \"#232428\", line: \"#2e2f35\" };\n\nconst months = (n: number) => `${n} ${n === 1 ? \"month\" : \"months\"}`;\n\nexport const MRRocketFlows = ({ flows, 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 const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n // Re-render on every change of the controller.\n const [, setTick] = useState(0);\n useEffect(() => flows.subscribe(() => setTick((t) => t + 1)), [flows]);\n 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 if (v.type === \"step\")\n return sheet(\n [\n h(\n RN.View,\n { style: { flexDirection: \"row\", alignItems: \"center\" } },\n v.total > 1 ? muted(`Step ${v.index + 1} of ${v.total}`) : null,\n close(\"Close the tour\", flows.onboarding.dismiss),\n ),\n title(v.step.title),\n v.step.body ? muted(v.step.body, { fontSize: 15 }) : null,\n btn(v.step.button || (v.last ? \"Done\" : \"Next\"), \"primary\", flows.onboarding.next),\n ],\n flows.onboarding.dismiss,\n );\n\n if (v.type === \"checklist\") {\n const done = v.items.filter((i) => i.done).length;\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, bottom: 28 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\" } },\n title(v.flow.name),\n close(\"Hide the checklist\", flows.onboarding.dismiss),\n ),\n muted(`${done} of ${v.items.length} done`),\n ...v.items.map(({ step, done: d }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n disabled: d || !!step.event,\n onPress: () => flows.onboarding.check(step.id),\n accessibilityRole: \"checkbox\",\n accessibilityState: { checked: d },\n style: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\", paddingVertical: 6 },\n },\n h(\n RN.View,\n {\n style: {\n width: 20,\n height: 20,\n borderRadius: 10,\n borderWidth: 1.5,\n borderColor: d ? p.accent : p.line,\n backgroundColor: d ? p.accent : \"transparent\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n },\n d ? text(\"✓\", { color: \"#fff\", fontSize: 12 }) : null,\n ),\n h(\n RN.View,\n { style: { flex: 1 } },\n text(step.title, { fontWeight: \"600\", color: d ? p.muted : p.fg, textDecorationLine: d ? \"line-through\" : \"none\" }),\n step.body ? muted(step.body) : null,\n ),\n ),\n ),\n ]),\n );\n }\n\n const m = v.message;\n if (m.style === \"banner\")\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, top: 56 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8 } },\n h(RN.View, { style: { flex: 1 } }, text(m.title, { fontWeight: \"700\" }), m.body ? muted(m.body) : null),\n close(\"Dismiss\", flows.message.dismiss),\n ),\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ]),\n );\n return sheet(\n [\n h(RN.View, { key: \"t\", style: { flexDirection: \"row\" } }, close(\"Dismiss\", flows.message.dismiss)),\n title(m.title),\n m.body ? muted(m.body, { fontSize: 15 }) : null,\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ],\n flows.message.dismiss,\n );\n};\n","/**\n * The real platform for the React Native client: React Native itself, plus optional modules the app may have installed.\n * Each optional `require` sits directly in its own `try` block: that is how Metro knows the module is optional and\n * bundles the app without it when it is not installed (and how the CommonJS build keeps the call literal).\n *\n * - `@react-native-async-storage/async-storage`: the offline queue, the install id (\"persistent\" consent), the cached\n * config and the first-open marker. Without it everything stays in memory for the app's run.\n * - `expo-device`, `expo-application`, `expo-localization`: model, OS version, app version and build, locale.\n * Without them the SDK falls back to what React Native knows (platform, OS version, the JS locale).\n * - `expo-notifications` (with `expo-constants` for the EAS project id): push notifications, `registerForPush()`.\n * Without it `registerForPush` answers \"unavailable\".\n * - `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\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 product's icon at the top left of Home (MRRocket sends the product's favicon). */\n logo?: 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 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 ? \"\" : `${whoLabel[m.from]} · `}${isPending ? \"Sending…\" : timeAgo(m.at)}`, { fontSize: 11, textAlign: mine ? \"right\" : \"left\", paddingHorizontal: 6 }) : null,\n );\n };\n const row = (a: ArticleSummary) =>\n h(\n RN.Pressable,\n { key: a.id, onPress: () => setView({ article: a.id }), accessibilityRole: \"button\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingVertical: 11, paddingHorizontal: 8 } },\n k.text(a.title, { flex: 1 }),\n glyph(\"next\", p.accent, 14),\n );\n const card = (children: ReactNode[], style: Style = {}) =>\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\" : whoLabel[last.from]} · ${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 bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }),\n !chat.loaded ? k.muted(\"Loading…\") : null,\n ...(thread?.messages ?? []).map((m) => bubble(m)),\n pending ? bubble(pending, true) : null,\n thread?.conversation?.status === \"solved\" && !pending ? k.muted(\"This conversation is closed. Write to start a new one.\", { textAlign: \"center\" }) : null,\n ),\n h(\n RN.View,\n { style: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 6, gap: 8 } },\n chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,\n needEmail\n ? k.field({ value: email, onChange: setEmail, placeholder: \"Your email (optional), so we can follow up\", email: true, max: 200, style: { borderWidth: emailOk ? 0 : 1, borderColor: p.danger, borderRadius: r.field, paddingHorizontal: 16, backgroundColor: hu.surface, ...surf } })\n : 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 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 accessibilityState: { selected: on },\n style: { flex: 1, 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 k.text(name, { fontSize: 13.5, fontWeight: \"500\", color: on ? hu.fg : hu.muted }),\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, style: { width: 28, height: 28, 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 ...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(`${whoLabel[banner.from]}${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":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,IAAAA,gBAAyI;;;ACXlI,IAAM,cAAc;AA2F3B,IAAM,SAAS,CAAC,QAAoB,SAAiB;AACjD,QAAM,OAAO,KAAK,KAAK,EAAE,YAAY;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,EAAG,KAAI,EAAE,YAAY,MAAM,KAAM,QAAO;AAClF,SAAO;AACX;AAGA,IAAM,OAAO,CAAC,QAAgB,UAAkB;AAC5C,QAAM,IAAI,OAAO,KAAK,EAAE,YAAY;AACpC,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,SAAO,EAAE,WAAW,GAAG,IAAI,EAAE,SAAS,CAAC,IAAI,MAAM;AACrD;AAEA,IAAM,mBAAmB,CAAC,GAAkB,WAAuB;AAE/D,MAAI,EAAE,OAAO,YAAa,QAAO;AACjC,QAAM,MAAM,OAAO,QAAQ,EAAE,QAAQ;AACrC,QAAM,SAAS,QAAQ,UAAa,QAAQ,OAAO,KAAK,OAAO,GAAG;AAClE,MAAI,EAAE,OAAO,UAAK;AACd,UAAM,IAAI,OAAO,MAAM;AACvB,UAAM,IAAI,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5B,WAAO,WAAW,MAAM,OAAO,SAAS,CAAC,KAAK,OAAO,SAAS,CAAC,KAAK,KAAK;AAAA,EAC7E;AACA,QAAM,MAAM,WAAW,MAAM,EAAE,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;AACjE,SAAO,EAAE,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,CAAC;AACnD;AAMO,IAAM,eAAe,CAAC,MAAkB,YAAoB,SAAqB,CAAC,MAAwB;AAC7G,MAAI,CAAC,KAAK,GAAI,QAAO;AACrB,QAAM,UAAU,EAAE,IAAI,YAAY,GAAG,OAAO;AAC5C,QAAM,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,SAAS,IAAI;AAC/I,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,SAAS,GAAG,KAAK,GAAG,YAAY,UAAU,EAAE,IAAI,OAAO,IAAI,QAAS,QAAO;AAC/E,MAAI,CAAC,KAAK,UAAU,OAAQ,QAAO;AACnC,QAAM,IAAI,SAAS,GAAG,KAAK,GAAG,YAAY,UAAU,EAAE,IAAI;AAC1D,MAAI,MAAM;AACV,aAAW,KAAK,KAAK,UAAU;AAC3B,WAAO,EAAE;AACT,QAAI,IAAI,IAAK,QAAO,EAAE;AAAA,EAC1B;AACA,SAAO,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC,EAAE;AACnD;AAGO,IAAM,UAAU,CAAC,KAAa,QAA8B,YAAoB,SAAqB,CAAC,MAAM;AAC/G,QAAM,OAAO,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AACrD,SAAO,OAAO,aAAa,MAAM,YAAY,MAAM,IAAI;AAC3D;AAsDO,IAAM,WAAW,CAAC,cAAc,cAAc,gBAAgB,YAAY,aAAa;AAsDvF,IAAM,qBAAqB,KAAK,KAAK;AAGrC,IAAM,UAAU,CAAC,QAAsF;AAC1G,QAAM,MAAuC,CAAC;AAC9C,aAAW,OAAO,UAAU;AACxB,UAAM,QAAQ,IAAI,GAAG,GAAG,KAAK;AAC7B,QAAI,MAAO,KAAI,GAAG,IAAI,MAAM,MAAM,GAAG,GAAG;AAAA,EAC5C;AACA,SAAO;AACX;AAYO,IAAM,aAAa,CAAC,QAAwC;AAC/D,QAAM,MAA8B,CAAC;AACrC,QAAM,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC;AAC1B,QAAM,KAAK,EAAE,QAAQ,GAAG;AACxB,MAAI,KAAK,EAAG,QAAO;AACnB,QAAM,MAAM,CAAC,MAAc;AACvB,QAAI;AACA,aAAO,mBAAmB,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA,IACnD,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AACA,aAAW,QAAQ,EAAE,MAAM,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG;AAC3C,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,UAAM,IAAI,IAAI,KAAK,IAAI,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAC/C,QAAI,KAAK,EAAE,KAAK,KAAM,KAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,EACvE;AACA,SAAO;AACX;AAGO,IAAM,WAAW,CAAC,UAAkB;AACvC,MAAIC,KAAI;AACR,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,IAAAA,MAAK,MAAM,WAAW,CAAC;AACvB,IAAAA,KAAI,KAAK,KAAKA,IAAG,QAAU;AAAA,EAC/B;AACA,UAAQA,OAAM,KAAK;AACvB;AAMO,IAAM,WAAW,CAAC,UAAkB;AACvC,MAAIA,KAAI;AACR,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,IAAAA,MAAK,MAAM,WAAW,CAAC;AACvB,IAAAA,KAAI,KAAK,KAAKA,IAAG,QAAU;AAAA,EAC/B;AACA,EAAAA,MAAKA,OAAM;AACX,EAAAA,KAAI,KAAK,KAAKA,IAAG,UAAU;AAC3B,EAAAA,MAAKA,OAAM;AACX,EAAAA,KAAI,KAAK,KAAKA,IAAG,UAAU;AAC3B,EAAAA,MAAKA,OAAM;AACX,UAAQA,OAAM,KAAK;AACvB;AAGO,IAAM,SAAS,CAAC,YAA8B,eAAkC;AACnF,QAAM,UAAU,WAAW,SAAS,CAAC,GAAG,MAAM;AAC9C,MAAI,WAAW,OAAQ,QAAO,WAAW;AACzC,MAAI,WAAW,WAAW,UAAW,QAAO;AAC5C,QAAM,IAAI,SAAS,GAAG,WAAW,GAAG,IAAI,UAAU,EAAE;AACpD,MAAI,MAAM;AACV,aAAW,KAAK,WAAW,UAAU;AACjC,WAAO,EAAE;AACT,QAAI,IAAI,IAAK,QAAO,EAAE;AAAA,EAC1B;AACA,SAAO,WAAW,SAAS,WAAW,SAAS,SAAS,CAAC,GAAG,MAAM;AACtE;AA4BO,IAAM,oBAAoB,CAAC,QAA8B,QAC3D,QAAQ,eAAe,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAE7G,IAAM,iBAAiB,CAAC,KAAa,QAA8B,YAAoB,YAAkD;AAC5I,MAAI,QAAQ,GAAG,EAAG,QAAO,QAAQ,GAAG;AACpC,QAAM,aAAa,QAAQ,YAAY,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AAChE,SAAO,aAAa,OAAO,YAAY,UAAU,IAAI;AACzD;AAOO,IAAM,cAAc,CAAC,QAA8B,YAAoB,YAAuC;AACjH,QAAM,MAA8B,EAAE,GAAI,QAAQ,SAAS,CAAC,EAAG;AAC/D,aAAW,cAAc,QAAQ,eAAe,CAAC,GAAG;AAChD,UAAM,KAAK,eAAe,WAAW,KAAK,QAAQ,YAAY,OAAO;AACrE,QAAI,QAAQ,WAAW,SAAS,CAAC,GAAG,MAAM,WAAY;AACtD,WAAO,OAAO,KAAK,WAAW,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,CAAC;AAAA,EAClF;AACA,SAAO;AACX;AA0GO,IAAM,gBAAgB,MACzB,OAAO,WAAW,eAAe,gBAAgB,SAAS,OAAO,WAAW,IAAI,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;;;ACvdhJ,IAAM,gBAAgB;AAGtB,IAAM,eAAe,CAAC,QAAgB,MAAiC,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM;AACrG,QAAM,IAAI;AACV,MAAI,WAAW,OAAO,EAAE,mBAAoB;AAC5C,IAAE,qBAAqB;AACvB,MAAI,cAAc,aAAa,EAAE;AACrC;AAOO,IAAM,aAAa,CAAC,QAAuB,IAAY,MAAe,MAAiC,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAqB;AACpJ,QAAMC,KAAI,OAAO,SAAS,WAAW,KAAK,KAAK,EAAE,YAAY,IAAI;AACjE,MAAI,iBAAiB,KAAKA,EAAC,EAAG,QAAO,EAAE,IAAI,MAAMA,GAAE;AACnD,MAAIA,GAAG,KAAI,8DAA8D;AACzE,SAAO,UAAU,OAAO,OAAO,KAAK,SAAS;AACjD;AAGO,IAAM,UAAU,CAAC,QAAmC,OAA4B,UAAU,MAAM,OAAO,OAAO,KAAK,OAAO,OAAO;AAMjI,IAAM,aAAa,CAAC,QAAmC,QAC1D,UAAU,IAAI,KAAK,CAAC,OAAO,OAAO,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO;;;AC8CxG,IAAM,sBAAsB,KAAK,OAAO;AACxC,IAAM,yBAAyB;AAiE/B,IAAM,UAAkH;AAAA,EAC3H,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,MAAM,GAAG,MAAM,IAAI,OAAO,GAAG;AAAA,EAC7D,MAAM,EAAE,OAAO,IAAI,QAAQ,IAAI,MAAM,GAAG,MAAM,IAAI,OAAO,GAAG;AAAA,EAC5D,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE;AAC9D;AAiCO,IAAM,YAAY;AAOlB,IAAM,QAAQ,CAAC,QAAgB;AAClC,QAAM,IAAI,8CAA8C,KAAK,GAAG;AAChE,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM;AAC5C,UAAM,IAAI,SAAS,GAAG,EAAE,IAAI;AAC5B,WAAO,KAAK,UAAU,IAAI,UAAU,IAAI,SAAS,UAAU;AAAA,EAC/D,CAAC;AACD,SAAO,SAAS,IAAI,SAAS,IAAI,SAAS,IAAI,OAAO,YAAY;AACrE;AAUO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAEhC,YAAY,SAAiB,QAAgB;AACzC,UAAM,OAAO;AAFjB;AAGI,SAAK,SAAS;AAAA,EAClB;AACJ;AAeA,IAAM,KAAK,CAAC,WACR,OAAO,QAAQ,MAAM,EAChB,OAAO,CAAC,MAA6B,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,mBAAmB,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,EACnE,KAAK,GAAG;AAEjB,IAAM,OAAO,OAAU,KAAa,MAA+B,WAAqC;AACpG,MAAI;AACJ,MAAI;AACA,UAAM,MAAM,MAAM,KAAK;AAAA,MACnB,GAAG;AAAA,MACH;AAAA;AAAA,MAEA,SAAS,OAAO,MAAM,SAAS,WAAW,EAAE,gBAAgB,mBAAmB,IAAI;AAAA,IACvF,CAAC;AAAA,EACL,SAAS,GAAG;AACR,QAAK,EAAY,SAAS,aAAc,OAAM;AAC9C,UAAM,IAAI,SAAS,oEAAoE,CAAC;AAAA,EAC5F;AACA,MAAI,CAAC,IAAI,IAAI;AAET,iBAAa,IAAI,MAAM;AACvB,QAAI,SAAS;AACb,QAAI;AACA,gBAAW,MAAM,IAAI,KAAK,GAA0B,SAAS;AAAA,IACjE,QAAQ;AAAA,IAER;AACA,UAAM,IAAI,SAAS,WAAW,IAAI,WAAW,MAAM,8CAA8C,4CAA4C,IAAI,MAAM;AAAA,EAC3J;AACA,SAAQ,MAAM,IAAI,KAAK;AAC3B;AAGO,IAAM,YAAY,CAAC,MAAY;AAClC,QAAM,OAAO,GAAG,EAAE,IAAI;AACtB,QAAM,MAAM,EAAE,KAAK,EAAE,QAAQ,YAAY,EAAE,YAAY,MAAM,EAAE,MAAM,UAAU,EAAE,SAAS;AAE1F,QAAM,KAAK,EAAE,KAAK,EAAE,QAAQ,YAAY,EAAE,YAAY,UAAU,EAAE,SAAS;AAC3E,QAAM,OAAO,CAAI,MAAc,MAA+B,WAC1D,KAAQ,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC,EAAE,GAAG,MAAM;AACnG,SAAO;AAAA,IACH,MAAM,CAAC,GAAyD,WAC5D,KAAmB,GAAG,IAAI,aAAa,GAAG,EAAE,GAAG,IAAI,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IACnH,MAAM,CAAC,IAAY,WACf,KAAmB,GAAG,IAAI,aAAa,mBAAmB,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,QAAW,MAAM;AAAA,IAChG,SAAS,CAAC,WAAyB,KAAsB,GAAG,IAAI,qBAAqB,GAAG,EAAE,CAAC,IAAI,QAAW,MAAM;AAAA,IAChH,WAAW,CAAC,WAAyB,KAAoC,GAAG,IAAI,uBAAuB,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IACjJ,QAAQ,CAAC,MAAuD,KAAmB,aAAa,CAAC;AAAA,IACjG,MAAM,CAAC,OAAe,KAAwC,aAAa,mBAAmB,EAAE,CAAC,SAAS,CAAC,CAAC;AAAA,IAC5G,UAAU,CAAC,IAAY,WACnB,KAAsC,GAAG,IAAI,aAAa,mBAAmB,EAAE,CAAC,aAAa,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IAC3I,SAAS,CAAC,IAAY,SAAiB,KAAsB,aAAa,mBAAmB,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC;AAAA,IACrH,QAAQ,CAAC,KAAa,WAClB,KAA0C,GAAG,IAAI,YAAY,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IACxG,MAAM,CAAC,OAAe,KAAc,YAAY,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,OAAU,CAAC;AAAA,IAClG,SAAS,CAAC,IAAY,MAClB,KAAc,YAAY,mBAAmB,EAAE,CAAC,YAAY,CAAC;AAAA,IACjE,MAAM,CAAC,WAAyB,KAAiB,GAAG,IAAI,aAAa,GAAG,EAAE,CAAC,IAAI,QAAW,MAAM;AAAA;AAAA,IAEhG,UAAU,CAAC,MAAqG,KAAiB,aAAa,CAAC;AAAA;AAAA,IAE/I,gBAAgB,CAAC,MAAkB,WAAyB;AACxD,YAAM,OAAO,IAAI,SAAS;AAC1B,WAAK,OAAO,OAAO,EAAE,MAAM;AAC3B,WAAK,OAAO,cAAc,EAAE,UAAU;AACtC,UAAI,EAAE,SAAU,MAAK,OAAO,YAAY,EAAE,QAAQ;AAClD,UAAI,SAAS,KAAM,MAAK,OAAO,QAAQ,IAAuB;AAAA,UACzD,MAAK,OAAO,QAAQ,MAAO,KAAkC,QAAQ,MAAM;AAChF,aAAO,KAAe,GAAG,IAAI,yBAAyB,EAAE,QAAQ,QAAQ,MAAM,KAAK,GAAG,MAAM;AAAA,IAChG;AAAA;AAAA,IAEA,eAAe,CAAC,OAAe,GAAG,IAAI,yBAAyB,mBAAmB,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC;AAAA,IAC/F,UAAU,CAAC,GAAY,WAAyB,KAAqC,GAAG,IAAI,aAAa,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IACtJ,SAAS,CAAC,IAAY,WAClB,KAAc,GAAG,IAAI,aAAa,mBAAmB,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,QAAW,MAAM;AAAA,IAC3F,eAAe,CAAC,WAAyB,KAAoB,GAAG,IAAI,cAAc,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,QAAW,MAAM;AAAA,IAC5H,aAAa,CAAC,IAAY,YAAqB,KAA2B,aAAa,mBAAmB,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;AAAA,EACrI;AACJ;;;ACrUO,IAAM,YAAY;AAClB,IAAM,YAAY;AAWlB,IAAM,aAAa,CAAC,MAAc;AACrC,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AAC/B,UAAM,IAAI,EAAE,WAAW,CAAC;AACxB,QAAI,IAAI,IAAM,MAAK;AAAA,aACV,IAAI,KAAO,MAAK;AAAA,aAChB,KAAK,SAAU,KAAK,SAAU,IAAI,IAAI,EAAE,WAAW,EAAE,WAAW,IAAI,CAAC,IAAI,WAAY,OAAQ;AAClG,WAAK;AACL;AAAA,IACJ,MAAO,MAAK;AAAA,EAChB;AACA,SAAO;AACX;AAaO,IAAM,gBAAgB,CAAyB,KAAa,QAAa,KAAc,aAAyC;AACnI,QAAM,OAAO,UAAU,KAAK,UAAU,GAAG,CAAC,IAAI,WAAW,cAAc,KAAK,UAAU,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,UAAU,GAAG,CAAC;AACnI,QAAM,QAAQ,WAAW,IAAI,IAAI;AACjC,QAAM,MAAyB,CAAC;AAChC,MAAI,QAAkB,CAAC;AACvB,MAAI,QAAa,CAAC;AAClB,MAAI,OAAO;AACX,QAAM,QAAQ,MAAM;AAChB,QAAI,MAAM,OAAQ,KAAI,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,MAAM,CAAC;AACjF,YAAQ,CAAC;AACT,YAAQ,CAAC;AACT,WAAO;AAAA,EACX;AACA,aAAW,SAAS,QAAQ;AACxB,UAAM,OAAO,KAAK,UAAU,KAAK;AACjC,UAAM,IAAI,WAAW,IAAI,IAAI;AAC7B,QAAI,QAAQ,IAAI,UAAW;AAC3B,QAAI,MAAM,WAAW,aAAa,OAAO,IAAI,UAAW,OAAM;AAC9D,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,KAAK;AAChB,YAAQ;AAAA,EACZ;AACA,QAAM;AACN,SAAO;AACX;;;ACzDA,IAAM,YAAY,IAAI;AAatB,IAAM,OAAO,CAAC,GAAW,MAAe,EAAE,SAAS,IAAI,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,WAAM;AAG1E,IAAM,gBAAgB,CAAC,UAAsE;AAChG,MAAI,iBAAiB,MAAO,QAAO,EAAE,MAAM,MAAM,QAAQ,SAAS,SAAS,KAAK,MAAM,WAAW,OAAO,KAAK,GAAG,GAAI,GAAG,OAAO,MAAM,QAAQ,KAAK,MAAM,OAAO,SAAS,IAAI,OAAU;AACrL,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,MAAM,SAAS,SAAS,KAAK,OAAO,GAAI,EAAE;AAClF,MAAI;AACA,WAAO,EAAE,MAAM,SAAS,SAAS,KAAK,KAAK,UAAU,KAAK,KAAK,OAAO,KAAK,GAAG,GAAI,EAAE;AAAA,EACxF,QAAQ;AACJ,WAAO,EAAE,MAAM,SAAS,SAAS,OAAO,KAAK,EAAE;AAAA,EACnD;AACJ;;;AClBO,IAAM,eAAe;AACrB,IAAM,mBAAmB;AACzB,IAAM,cAAc;AAEpB,IAAM,eAAe;AAiQrB,IAAM,eAAiC;AAAA,EAC1C,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS,CAAC;AAAA,EACV,QAAQ,CAAC;AAAA,EACT,SAAS,EAAE,OAAO,6BAA6B,MAAM,wDAAwD,QAAQ,sBAAsB;AAAA,EAC3I,WAAW;AACf;AAEA,IAAM,SAAS;AACf,IAAM,eAAe;AAGd,IAAM,YAAY,CAAC,MACtB,EACK,KAAK,EACL,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAE/B,IAAM,SAAS,oBAAI,IAAI,CAAC,aAAa,UAAU,WAAW,cAAc,mBAAmB,gBAAgB,CAAC;AAGrG,IAAM,iBAAiB,CAAC,SAAiB,UAAkB;AAC9D,QAAM,IAAI,UAAU,OAAO;AAC3B,QAAM,IAAI,UAAU,KAAK;AACzB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,SAAO,MAAM,KAAM,OAAO,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC;AACpD;AAGO,IAAM,eAAe,CAAC,YACzB,mHAAmH,KAAK,QAAQ,KAAK,CAAC;AAGnI,IAAM,QAAQ,MAAM,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAG3F,IAAM,aAAa,CAAC,QAAgB,YAAoB,KAAK,MAAM,UAAU,IAAI,UAAU,OAAO,GAAG,IAAI;AAGzG,IAAM,QAAQ,CAAC,QAAgB,aAAqB;AACvD,MAAI;AACA,WAAO,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,YAAY,SAAS,CAAC,EAAE,OAAO,MAAM;AAAA,EAC1F,QAAQ;AACJ,WAAO,GAAG,OAAO,QAAQ,CAAC,CAAC,IAAI,QAAQ;AAAA,EAC3C;AACJ;AAGO,IAAM,cAAc,CAAC,MACxB,EAAE,SAAS,YAAY,qBAAqB,EAAE,SAAS,UAAU,kBAAkB,EAAE,SAAS,cAAc,gBAAgB;AAGzH,IAAM,UAAU,CAAC,QAA4B;AAChD,QAAM,KAAK,OAAO,IAAI,KAAK;AAC3B,SAAO,gBAAgB,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,IAAI;AAChE;AAWO,IAAM,UAAU,CAAC,MAAwC,EAAE,SAAS,EAAE;AAGtE,IAAM,SAAS,CAAC,MAA+C,KAAK,IAAI,GAAG,EAAE,MAAM,KAAK,EAAE,SAAS,UAAU,OAAY;AAGzH,IAAM,cAAc,CAAC,SAAiB,SAAiB;AAC1D,QAAM,IAAI,QAAQ,KAAK;AACvB,QAAM,MAAM,KAAK,MAAM,MAAM,EAAE,CAAC,KAAK,KAAK,QAAQ,QAAQ,EAAE,KAAK;AACjE,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,EAAE,SAAS,GAAG,GAAG;AACjB,UAAM,OAAO,EAAE,MAAM,GAAG,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC9C,WAAO,CAAC,QAAQ,OAAO,QAAQ,GAAG,WAAW,GAAG,IAAI,GAAG;AAAA,EAC3D;AACA,SAAO,QAAQ,EAAE,QAAQ,QAAQ,EAAE,KAAK;AAC5C;AAGA,IAAM,UAAU,CAAC,UACb,MAAM,QAAQ,CAAC,MAAO,EAAE,SAAS,cAAc,CAAC,GAAG,QAAQ,EAAE,GAAG,GAAG,GAAG,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,SAAS,CAAC,IAAI,CAAC,CAAC,CAAE;AASjH,IAAM,cAAc,CAAC,OAA2C,MAAM,KAAK,IAAI,MAClF,SAAS,QAAQ,UAAU,KAAK,MAAM,KAAK,OAAO,MAAM,IAAI,KAAK,KAAK,EAAE,QAAQ,KAAK,SAAa;AAEtG,IAAM,MAAM,CAAC,MAAe,GAAG,KAAK,EAAE,YAAY;AAG3C,IAAM,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,GAAe,OACrD,EAAE,UAAU,QAAQ,IAAI,EAAE,MAAM,MAAM,IAAI,EAAE,MAAM,OAClD,EAAE,QAAQ,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,CAAC,MACrE,EAAE,EAAE,UAAU,EAAE,gBAChB,EAAE,EAAE,SAAS,EAAE,gBACd,EAAE,eAAe,QAAQ,EAAE,UAAU,OACrC,EAAE,cAAc,QAAQ,EAAE,UAAU;AAoBlC,IAAM,cAAc,CAAC,QAAmC;AAC3D,MAAI,SAA+B;AACnC,MAAI,SAA2B;AAC/B,MAAI,SAAwB;AAC5B,MAAI,WAA2B,CAAC;AAChC,MAAI,QAAQ;AACZ,MAAI,UAAgC;AACpC,MAAI;AACJ,MAAI,cAAyC;AAC7C,QAAM,WAAW,oBAAI,IAAsB;AAC3C,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,OAAO,IAAI,SAAS;AAE1B,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,MAAM,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI;AAC1C,MAAI,QAA8C;AAElD,QAAM,QAAQ,MAAM,QAAQ,cAAc,CAAC;AAC3C,QAAM,WAAW,CAAC,OAAuB,KAAK,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI;AACjF,QAAM,OAAO,CAAC,OAAe;AACzB,QAAI,IAAI,SAAS,IAAI,EAAE;AACvB,QAAI,CAAC,EAAG,UAAS,IAAI,IAAK,IAAI,EAAE,MAAM,oBAAI,IAAI,GAAG,WAAW,OAAO,SAAS,oBAAI,IAAI,GAAG,IAAI,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE,CAAE;AAC3H,WAAO;AAAA,EACX;AAEA,MAAI,QAAQ;AACZ,QAAM,SAAS,CAAC,UAAmC;AAC/C,QAAI,MAAM,kBAAkB,KAAK;AACjC,YAAQ;AAAA,EACZ;AACA,QAAM,WAAW,CAAC,GAAa,OAAe;AAC1C,MAAE,KAAK,IAAI,EAAE;AACb,MAAE,GAAG,IAAI,IAAI,IAAI,CAAC;AAAA,EACtB;AAGA,QAAM,SAAS,CAAC,MAAgD;AAC5D,QAAI,EAAE,MAAM,KAAK,GAAG;AAChB,YAAM,OAAO,IAAI,OAAO;AACxB,aAAO,SAAS,SAAY,QAAQ,YAAY,EAAE,MAAM,IAAI;AAAA,IAChE;AACA,QAAI,EAAE,OAAO,KAAK,GAAG;AAEjB,UAAI,CAAC,MAAO,QAAO;AACnB,iBAAW,KAAK,WAAY,KAAI,eAAe,EAAE,OAAO,CAAC,EAAG,QAAO;AACnE,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAMA,QAAM,WAAW,CAAC,MAAsB,MAAwB,GAAa,MAAe,SAAS,GAAG,SAA0B;AAC9H,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AAClC,YAAM,IAAI,KAAK,CAAC;AAChB,UAAI,EAAE,SAAS,QAAQ;AACnB,YAAI,EAAE,KAAK,IAAI,EAAE,EAAE,GAAG;AAClB,iBAAO,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK;AACzB;AAAA,QACJ;AACA,YAAI,QAAQ,EAAE,QAAQ,IAAI,EAAE,EAAE;AAC9B,YAAI,UAAU,QAAW;AACrB,cAAI,CAAC,KAAM,QAAO,EAAE,IAAI,UAAU;AAElC,kBAAQ,QAAQ,IAAI;AACpB,YAAE,QAAQ,IAAI,EAAE,IAAI,KAAK;AACzB,iBAAO,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAAA,QACvE;AACA,cAAM,QAAQ,QAAQ,OAAO,CAAC;AAC9B,YAAI,IAAI,IAAI,MAAO,QAAO,EAAE,IAAI,QAAQ,MAAM;AAC9C,YAAI,CAAC,KAAM,QAAO,EAAE,IAAI,UAAU;AAClC,iBAAS,GAAG,EAAE,EAAE;AAChB,eAAO,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,MAAM,QAAQ,QAAQ,YAAY,CAAC;AACvE,eAAO;AACP;AAAA,MACJ;AACA,UAAI,EAAE,SAAS,aAAa;AACxB,YAAI,SAAS,EAAE,QAAQ,IAAI,EAAE,EAAE;AAC/B,YAAI,WAAW,QAAW;AACtB,cAAI,CAAC,KAAM,QAAO,EAAE,IAAI,UAAU;AAClC,mBAAS,OAAO,CAAC;AACjB,cAAI,WAAW,OAAW,QAAO,EAAE,IAAI,UAAU;AACjD,YAAE,QAAQ,IAAI,EAAE,IAAI,MAAM;AAC1B,iBAAO,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,MAAM,aAAa,QAAQ,YAAY,QAAQ,SAAS,QAAQ,KAAK,CAAC;AAAA,QAC9G;AACA,eAAO,SAAS,MAAM,SAAS,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM,QAAQ,IAAI;AAAA,MACtE;AACA,UAAI,CAAC,EAAE,KAAK,IAAI,EAAE,EAAE,EAAG,QAAO,EAAE,IAAI,QAAQ,MAAM,GAAG,MAAM,OAAO,GAAG,OAAO;AAC5E,aAAO,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK;AACzB;AAAA,IACJ;AACA,WAAO,EAAE,IAAI,MAAM;AAAA,EACvB;AAEA,QAAM,WAAW,CAAC,MAAsB;AACpC,UAAM,IAAI,SAAS,IAAI,EAAE,EAAE;AAC3B,WAAO,CAAC,CAAC,MAAM,EAAE,aAAa,SAAS,GAAG,QAAQ,CAAC,GAAG,GAAG,KAAK,EAAE,OAAO;AAAA,EAC3E;AAEA,QAAM,QAAQ,CAAC,QAA4B,GAAG,YAAY,IAAI,OAAO,SAAS;AAC9E,QAAM,cAAc,CAAC,QAA4B,GAAG,YAAY,WAAW,OAAO,SAAS;AAE3F,QAAM,OAAO,MAAM;AACf,YAAQ;AACR,UAAM,QAAQ,IAAI,UAAU;AAC5B,QAAI,CAAC,MAAO;AACZ,UAAM,MAAoC,CAAC;AAC3C,eAAW,CAAC,IAAI,CAAC,KAAK;AAClB,UAAI,EAAE,IAAI;AAAA,QACN,MAAM,CAAC,GAAG,EAAE,IAAI;AAAA,QAChB,GAAI,EAAE,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,QACzC,GAAI,EAAE,QAAQ,OAAO,EAAE,SAAS,OAAO,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,QAAQ,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC;AAAA,QAC/G,GAAI,EAAE,GAAG,OAAO,EAAE,IAAI,OAAO,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC;AAAA,QACpD,GAAI,EAAE,QAAQ,OAAO,EAAE,SAAS,OAAO,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACvE;AACJ,QAAI;AACA,YAAM,IAAI,MAAM,IAAI,SAAS,CAAC,GAAG,KAAK,UAAU,GAAG,CAAC;AACpD,UAAI,WAAW,KAAM,OAAM,IAAI,YAAY,IAAI,SAAS,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IAC3G,QAAQ;AAAA,IAER;AAAA,EACJ;AAEA,QAAM,QAAQ,CAAC,UAAgD;AAC3D,eAAW,CAAC,IAAI,CAAC,KAAK,OAAO,QAAQ,SAAS,CAAC,CAAC,GAAG;AAC/C,YAAM,IAAI,KAAK,EAAE;AACjB,iBAAW,KAAK,EAAE,QAAQ,CAAC,EAAG,GAAE,KAAK,IAAI,CAAC;AAC1C,UAAI,EAAE,UAAW,GAAE,YAAY;AAE/B,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAG,KAAI,CAAC,EAAE,QAAQ,IAAI,CAAC,EAAG,GAAE,QAAQ,IAAI,GAAG,MAAM,KAAK;AACzG,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAG,KAAI,OAAO,MAAM,YAAY,CAAC,EAAE,GAAG,IAAI,CAAC,EAAG,GAAE,GAAG,IAAI,GAAG,CAAC;AACzG,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAG,KAAI,OAAO,MAAM,aAAa,CAAC,EAAE,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,QAAQ,IAAI,CAAC,GAAK,GAAE,QAAQ,IAAI,GAAG,CAAC;AAAA,IACvJ;AAAA,EACJ;AAKA,QAAM,SAAS,CAAC,UAAkB;AAC9B,QAAI,MAAO,cAAa,KAAK;AAC7B,YAAQ;AACR,UAAM,KAAK,QAAQ,IAAI;AACvB,QAAI,KAAK,KAAK,MAAM,OAAY;AAC5B,cAAQ,WAAW,OAAQ,QAAQ,MAAO,KAAK,IAAI,KAAK,EAAE;AAE1D,MAAC,MAAiC,QAAQ;AAAA,IAC9C;AAAA,EACJ;AAGA,MAAI,UAAU;AAEd,QAAM,iBAAiB,MAAuB;AAC1C,cAAU;AACV,UAAM,OAAO,SAAS,MAAM;AAC5B,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,IAAI,KAAK,KAAK,EAAE;AACtB,QAAI,EAAE,UAAW,QAAO;AACxB,UAAM,IAAI,SAAS,MAAM,QAAQ,IAAI,GAAG,GAAG,IAAI;AAC/C,QAAI,MAAO,MAAK;AAChB,QAAI,EAAE,OAAO,OAAQ,QAAO,EAAE,KAAK;AACnC,cAAU,EAAE,OAAO,UAAU,EAAE,OAAO;AACtC,QAAI,EAAE,OAAO,OAAQ,QAAO;AAC5B,UAAM,EAAE,MAAM,MAAM,MAAM,IAAI;AAC9B,UAAM,SAAS,CAAC,MAAuD,CAAC,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,SAAS;AAC9G,QAAI,KAAK,SAAS,aAAa;AAC3B,UAAI,OAAO;AACX,aAAO,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,EAAE,SAAS,YAAa;AAClF,UAAI,KAAK;AACT,aAAO,KAAK,IAAI,KAAK,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,YAAa;AAC1F,YAAM,QAAQ,KAAK,MAAM,MAAM,KAAK,CAAC,EAAE,OAAO,MAAM;AACpD,iBAAW,KAAK;AACZ,YAAI,CAAC,EAAE,KAAK,IAAI,EAAE,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,EAAE,EAAE,EAAE,GAAG;AAC9C,gBAAM,IAAI,KAAK,EAAE,EAAE,EAAE;AACrB,cAAI,MAAM,kBAAkB,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,MAAM,aAAa,QAAQ,QAAQ,CAAC;AAAA,QACjG;AACJ,aAAO,EAAE,MAAM,aAAa,MAAM,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;AAAA,IACrG;AACA,QAAI,CAAC,MAAM,IAAI,KAAK,KAAK,EAAE,EAAE,GAAG;AAC5B,YAAM,IAAI,KAAK,KAAK,EAAE,EAAE;AACxB,UAAI,MAAM,kBAAkB,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK,MAAM,QAAQ,QAAQ,CAAC;AAAA,IAClG;AAEA,UAAM,OAAO,KAAK,MAAM,QAAQ,CAAC;AACjC,UAAM,OAAO,KAAK,UAAU,CAAC,MAAM,EAAE,SAAS,WAAW;AACzD,UAAM,SAAS,OAAO,IAAI,OAAO,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,EAAE;AACrE,WAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,OAAO,EAAE,QAAQ,OAAO,EAAE,SAAS,IAAI,OAAO,MAAM,CAAC,SAAS,OAAO,EAAE;AAAA,EAC9G;AAEA,QAAM,OAAO,MAAuB;AAChC,QAAI,QAAQ;AACR,YAAM,IAAI;AACV,YAAM,WAAW,EAAE,KAAK,YAAY,EAAE,MAAO;AAE7C,YAAM,IAAI,WAAW,IAAI;AACzB,YAAM,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,KAAK,SAAS,EAAE,MAAO,IAAI,IAAI;AACtE,aAAO;AAAA,QACH,MAAM;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,QACV,GAAI,EAAE,WAAW,cAAc,WAAW,EAAE,UAAU,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,QAC5E,OAAO,EAAE,WAAW,UAAU,EAAE,QAAQ;AAAA,QACxC,GAAI,EAAE,WAAW,UAAU,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAAA,QACjD,OAAO,EAAE,QAAQ;AAAA,QACjB,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,QACT,MAAM,EAAE,WAAW,WAAW,IAAI,EAAE,WAAW,aAAa,IAAI,EAAE,WAAW,UAAU,IAAI,IAAI,EAAE,QAAQ;AAAA,QACzG;AAAA,MACJ;AAAA,IACJ;AACA,UAAM,KAAK,eAAe;AAC1B,QAAI,GAAI,QAAO;AAEf,QAAI,UAAU,CAAC,QAAS,UAAS;AACjC,UAAM,IAAI,SAAS,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;AACjD,WAAO,IAAI,EAAE,MAAM,WAAW,SAAS,EAAE,IAAI;AAAA,EACjD;AAGA,QAAM,OAAO,MAAM;AAGf,UAAM,IAAI,KAAK;AACf,QAAI,GAAG,SAAS,aAAa,CAAC,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG;AAC1D,YAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,EAAE;AAC7B,UAAI,MAAM,aAAa,EAAE,SAAS,EAAE,QAAQ,IAAI,SAAS,EAAE,QAAQ,SAAS,QAAQ,QAAQ,CAAC;AAAA,IACjG;AACA,eAAW,KAAK,CAAC,GAAG,SAAS,GAAG;AAC5B,UAAI;AACA,UAAE;AAAA,MACN,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,QAAQ,CAAC,SAAyB;AACpC,QAAI,WAAW,KAAK,GAAI,QAAO;AAC/B,QAAI,UAAU,SAAS,MAAM,KAAK,CAAC,SAAS,SAAS,MAAM,CAAE,EAAG,QAAO;AACvE,aAAS,KAAK;AACd,QAAI,MAAM,kBAAkB,EAAE,MAAM,KAAK,IAAI,QAAQ,UAAU,CAAC;AAChE,SAAK;AACL,WAAO;AAAA,EACX;AAGA,QAAM,YAAY,MAAM;AACpB,QAAI,CAAC,QAAQ,UAAU,CAAC,MAAO;AAE/B,QAAI,CAAC,IAAI,SAAS,KAAK,CAAC,IAAI,UAAU,EAAG;AACzC,UAAM,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK,QAAQ,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;AAC7F,QAAI,KAAM,OAAM,IAAI;AAAA,EACxB;AAEA,QAAM,UAAU,MAAM;AAClB,UAAM,MAAM,IAAI,SAAS;AAEzB,QAAI,gBAAgB,QAAQ,gBAAgB,KAAK;AAC7C,eAAS,MAAM;AACf,iBAAW,MAAM;AACjB,cAAQ,MAAM;AACd,eAAS;AACT,kBAAY;AAAA,IAChB;AACA,kBAAc;AACd,UAAM,OAAO,YAAY;AACrB,YAAM,QAAQ,IAAI,UAAU;AAC5B,UAAI,OAAO;AACP,YAAI;AACA,gBAAM,MAAM,MAAM,MAAM,IAAI,MAAM,GAAG,CAAC;AACtC,cAAI,IAAK,OAAM,KAAK,MAAM,GAAG,CAA6B;AAC1D,gBAAM,OAAO,MAAM,MAAM,IAAI,YAAY,GAAG,CAAC;AAC7C,cAAI;AAAM,uBAAW,KAAK,KAAK,MAAM,IAAI,EAAe,KAAI,OAAO,MAAM,SAAU,YAAW,IAAI,CAAC;AAAA;AAAA,QACvG,QAAQ;AAAA,QAER;AAAA,MACJ;AACA,YAAM,QAAQ,MAAM,EAAE,SAAS,KAAK,CAAC,CAAC,QAAQ;AAC9C,UAAI,OAAO,SAAS,cAAc,KAAK;AACnC,oBAAY;AACZ,cAAM,QAAQ,MAAM,IAAI,WAAW,GAAG,EAAE,MAAM,MAAM,IAAI;AACxD,YAAI,SAAS,IAAI,SAAS,MAAM,KAAK;AACjC,gBAAM,MAAM,UAAU;AACtB,qBAAW,KAAK,MAAM,UAAU,CAAC,EAAG,KAAI,OAAO,MAAM,SAAU,YAAW,IAAI,UAAU,CAAC,CAAC;AAC1F,sBAAY,MAAM,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,EAAE,KAAK;AAAA,QACxE;AAAA,MACJ;AACA,UAAI,CAAC,IAAK,YAAW,CAAC;AACtB,cAAQ;AACR,gBAAU;AACV,WAAK;AAAA,IACT,GAAG;AACH,cAAU,IAAI,QAAQ,MAAM;AACxB,UAAI,YAAY,IAAK,WAAU;AAAA,IACnC,CAAC;AACD,WAAO;AAAA,EACX;AAKA,QAAM,UAAU,CAAC,MAAkB,EAAE,QAAQ,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAS,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAGnG,QAAM,UAAU,CAAC,MAAiB;AAC9B,UAAM,MAAM,EAAE,QAAQ,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM,QAAQ,YAAY,EAAE,QAAQ,eAAe,IAAI,MAAM,CAAC,EAAE;AAChH,UAAM,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAO,KAAK,CAAC;AAC5C,MAAE,OAAO,MAAM,UAAU,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AACnD,MAAE,QAAQ,EAAE,OAAO,IAAI,EAAE,KAAK,OAAO,EAAE,MAAO,IAAK,MAAM,EAAE,IAAI,EAAE,SAAS;AAC1E,MAAE,QAAQ;AACV,MAAE,SAAS,EAAE,QAAQ,UAAU;AAAA,EACnC;AAEA,QAAM,SAAS,CAAC,GAAc,SAAsC,YAAuC;AACvG,UAAM,QAAQ,EAAE,WAAW,UAAU,EAAE,QAAQ;AAC/C,WAAO;AAAA,MACH;AAAA,MACA,KAAK,EAAE;AAAA,MACP,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,aAAa,EAAE,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;AAAA,MAC1G,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,MACvC,GAAI,YAAY,WAAW,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MAChD,GAAI,SAAS,KAAK,IAAI,EAAE,SAAS,QAAQ,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;AAAA,IACvE;AAAA,EACJ;AAEA,QAAM,SAAS,CAAC,GAAc,MAAwB;AAClD,QAAI,MAAM,cAAc;AAAA,MACpB,QAAQ;AAAA,MACR,KAAK,EAAE;AAAA,MACP,SAAS,EAAE,KAAK;AAAA,MAChB,SAAS,EAAE;AAAA,MACX,UAAU,EAAE,QAAQ,YAAY;AAAA,MAChC,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,MACvC,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,MACvC,GAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,MACxD,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9C,CAAC;AACD,QAAI,WAAW,EAAG,UAAS;AAC3B,MAAE,QAAQ,CAAC;AACX,SAAK;AAAA,EACT;AAGA,QAAM,SAAS,CAAC,GAAc,SAAgC,YAAqB;AAC/E,QAAI,EAAE,KAAM;AACZ,UAAM,IAAI,OAAO,GAAG,SAAS,OAAO;AACpC,UAAM,KAAK,YAAY,UAAU,EAAE,QAAQ,SAAS,EAAE,QAAQ;AAC9D,MAAE,OAAO;AACT,MAAE,QAAQ;AACV,SAAK;AACL,YAAQ,QAAQ,EACX,KAAK,MAAM,KAAK,CAAC,CAAC,EAClB;AAAA,MACG,MAAM,OAAO,GAAG,CAAC;AAAA,MACjB,MAAM;AACF,UAAE,OAAO;AACT,UAAE,QAAQ;AACV,aAAK;AAAA,MACT;AAAA,IACJ;AAAA,EACR;AAEA,QAAM,iBAAiB,CAAC,UAA6B,CAAC,MAAM;AACxD,QAAI,OAAQ,QAAO,OAAO;AAC1B,UAAM,OAAO,QAAQ,cAAc;AACnC,UAAM,QAAQ,QAAQ,aAAa,cAAc,KAAK,QAAQ,SAAS;AACvE,QAAI,UAAyC,MAAM;AAAA,IAAC;AACpD,UAAM,UAAU,IAAI,QAA0B,CAAC,MAAO,UAAU,CAAE;AAClE,UAAM,IAAe,EAAE,MAAM,SAAS,OAAO,QAAQ,QAAQ,YAAY,UAAU,OAAO,GAAG,KAAK,MAAM,GAAG,MAAM,OAAO,SAAS,QAAQ;AACzI,aAAS;AACT,QAAI,MAAM,cAAc,EAAE,QAAQ,SAAS,KAAK,EAAE,KAAK,SAAS,KAAK,SAAS,UAAU,QAAQ,YAAY,YAAY,MAAM,CAAC;AAC/H,SAAK;AACL,WAAO;AAAA,EACX;AAEA,QAAM,aAA8B;AAAA,IAChC,WAAW,CAAC,MAAM;AACd,eAAS;AACT,UAAI,UAAU,CAAC,SAAS,MAAM,EAAG,UAAS;AAC1C,WAAK;AAAA,IACT;AAAA,IACA;AAAA,IACA,SAAS,CAAC,SAAS;AACf,UAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AAEnC,YAAM,OAAO,UAAU,IAAI;AAC3B,YAAM,QAAQ,CAAC,CAAC,QAAQ,CAAC,WAAW,IAAI,IAAI;AAC5C,UAAI,MAAO,YAAW,IAAI,IAAI;AAC9B,YAAM,OAAO,SAAS,MAAM;AAC5B,UAAI,SAAS;AACb,UAAI,MAAM;AACN,cAAM,IAAI,KAAK,KAAK,EAAE;AACtB,mBAAW,KAAK,QAAQ,QAAQ,IAAI,CAAC;AACjC,cAAI,EAAE,SAAS,eAAe,EAAE,SAAS,CAAC,EAAE,KAAK,IAAI,EAAE,EAAE,KAAK,eAAe,EAAE,OAAO,IAAI,GAAG;AACzF,qBAAS,GAAG,EAAE,EAAE;AAChB,qBAAS;AACT,gBAAI,MAAM,kBAAkB,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,MAAM,QAAQ,YAAY,CAAC;AAAA,UAChG;AAAA,MACR;AACA,UAAI,UAAW,SAAS,MAAO;AAC3B,aAAK;AACL,aAAK;AAAA,MACT,WAAW,MAAO,MAAK;AAEvB,UAAI,CAAC,QAAS,CAAC,IAAI,SAAS,KAAK,CAAC,IAAI,UAAU,EAAI;AACpD,YAAM,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,CAAC,EAAE,UAAU,eAAe,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;AACrG,UAAI,KAAM,OAAM,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,IACA,iBAAiB,CAAC,OAAO;AACrB,YAAM,IAAI,KAAK,SAAS,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;AACnF,UAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAQ,QAAO;AACrC,YAAM,IAAI,KAAK,EAAE,EAAE;AAEnB,QAAE,YAAY;AACd,aAAO,MAAM,CAAC;AAAA,IAClB;AAAA,IACA;AAAA,IACA,WAAW,CAAC,MAAM;AACd,gBAAU,IAAI,CAAC;AACf,aAAO,MAAM,UAAU,OAAO,CAAC;AAAA,IACnC;AAAA,IACA,QAAQ;AAAA,MACJ,MAAM,CAAC,WAAW;AACd,YAAI,CAAC,UAAU,OAAO,QAAQ,OAAO,WAAW,YAAY,CAAC,OAAO,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAG;AAC/G,YAAI,OAAO,WAAW,OAAQ,QAAO,SAAS;AAC9C,eAAO,SAAS;AAChB,eAAO,QAAQ;AACf,aAAK;AAAA,MACT;AAAA,MACA,QAAQ,CAACC,UAAS;AACd,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,WAAY;AAC7C,cAAM,IAAIA,MAAK,MAAM,GAAG,GAAG;AAC3B,UAAE,SAAS,EAAE,KAAK,IAAI,IAAI;AAC1B,aAAK;AAAA,MACT;AAAA,MACA,MAAM,MAAM;AACR,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,CAAC,EAAE,OAAQ;AAErB,YAAI,EAAE,WAAW,UAAU;AACvB,cAAI,MAAM,cAAc,EAAE,QAAQ,YAAY,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,QAAQ,EAAE,OAAO,CAAC;AACrG,cAAI,EAAE,KAAK,YAAY,EAAE,MAAM,EAAG,GAAE,SAAS;AAAA,cACxC,SAAQ,CAAC;AAAA,QAClB,WAAW,EAAE,WAAW,YAAY;AAChC,YAAE,SAAS,EAAE,QAAQ,KAAK;AAC1B,kBAAQ,CAAC;AAAA,QACb,MAAO;AACP,aAAK;AAAA,MACT;AAAA,MACA,QAAQ,CAAC,YAAY;AACjB,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,EAAE,WAAW,WAAW,CAAC,EAAE,OAAQ;AAC7C,YAAI,CAAC,EAAE;AACH,cAAI,MAAM,cAAc;AAAA,YACpB,QAAQ;AAAA,YACR,KAAK,EAAE;AAAA,YACP,SAAS,EAAE,KAAK;AAAA,YAChB,QAAQ,EAAE;AAAA,YACV,OAAO,EAAE,OAAO;AAAA,YAChB,GAAG,QAAQ,CAAC;AAAA,YACZ,SAAS;AAAA,UACb,CAAC;AACL,eAAO,GAAG,SAAS,OAAO;AAAA,MAC9B;AAAA,MACA,SAAS,MAAM;AACX,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,EAAE,WAAW,WAAW,EAAE,KAAM;AAC1C,YAAI,MAAM,cAAc;AAAA,UACpB,QAAQ;AAAA,UACR,KAAK,EAAE;AAAA,UACP,SAAS,EAAE,KAAK;AAAA,UAChB,QAAQ,EAAE;AAAA,UACV,OAAO,EAAE,OAAO;AAAA,UAChB,GAAG,QAAQ,CAAC;AAAA,UACZ,SAAS;AAAA,QACb,CAAC;AAED,cAAM,SAAS,EAAE,UAAU,KAAK,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,IAAI;AACvE,YAAI,QAAQ;AACR,YAAE,QAAQ;AACV,YAAE,OAAO;AACT,YAAE,QAAQ;AAAA,QACd,MAAO,GAAE,SAAS;AAClB,UAAE,QAAQ;AACV,aAAK;AAAA,MACT;AAAA,MACA,SAAS,CAAC,YAAY;AAClB,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,EAAE,WAAW,UAAW;AAClC,eAAO,GAAG,aAAa,OAAO;AAAA,MAClC;AAAA,MACA,OAAO,MAAM;AACT,cAAM,IAAI;AACV,YAAI,CAAC,KAAK,EAAE,KAAM;AAClB,cAAM,IAAI,OAAO,GAAG,MAAM;AAC1B,UAAE,QAAQ,UAAU,CAAC;AACrB,eAAO,GAAG,CAAC;AAAA,MACf;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,MACR,MAAM,MAAM;AACR,cAAM,IAAI,eAAe;AACzB,YAAI,GAAG,SAAS,OAAQ;AACxB,iBAAS,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE;AACnC,YAAI,MAAM,kBAAkB,EAAE,MAAM,EAAE,KAAK,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,EAAE,KAAK,MAAM,QAAQ,YAAY,CAAC;AACxG,aAAK;AACL,aAAK;AAAA,MACT;AAAA,MACA,OAAO,CAAC,WAAW;AACf,cAAM,IAAI,eAAe;AACzB,YAAI,GAAG,SAAS,YAAa;AAC7B,cAAM,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,KAAK,OAAO,MAAM;AACrD,YAAI,CAAC,QAAQ,KAAK,KAAM;AACxB,iBAAS,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM;AAChC,YAAI,MAAM,kBAAkB,EAAE,MAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,MAAM,aAAa,QAAQ,YAAY,CAAC;AACrG,aAAK;AACL,aAAK;AAAA,MACT;AAAA,MACA,SAAS,MAAM;AACX,cAAM,IAAI,eAAe;AACzB,YAAI,CAAC,KAAM,EAAE,SAAS,UAAU,EAAE,SAAS,YAAc;AACzD,aAAK,EAAE,KAAK,EAAE,EAAE,YAAY;AAC5B,YAAI,MAAM,kBAAkB,EAAE,MAAM,EAAE,KAAK,IAAI,GAAI,EAAE,SAAS,SAAS,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC,GAAI,QAAQ,YAAY,CAAC;AACvH,iBAAS;AACT,aAAK;AACL,aAAK;AAAA,MACT;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,MACL,OAAO,MAAM;AACT,cAAM,IAAI,KAAK;AACf,YAAI,GAAG,SAAS,UAAW;AAC3B,gBAAQ,IAAI,EAAE,QAAQ,EAAE;AACxB,YAAI,MAAM,aAAa,EAAE,SAAS,EAAE,QAAQ,IAAI,SAAS,EAAE,QAAQ,SAAS,QAAQ,UAAU,CAAC;AAC/F,cAAM,MAAM,QAAQ,EAAE,QAAQ,GAAG;AACjC,aAAK;AACL,YAAI,IAAK,KAAI,UAAU,GAAG;AAAA,MAC9B;AAAA,MACA,SAAS,MAAM;AACX,cAAM,IAAI,KAAK;AACf,YAAI,GAAG,SAAS,UAAW;AAC3B,gBAAQ,IAAI,EAAE,QAAQ,EAAE;AACxB,YAAI,MAAM,aAAa,EAAE,SAAS,EAAE,QAAQ,IAAI,SAAS,EAAE,QAAQ,SAAS,QAAQ,YAAY,CAAC;AACjG,aAAK;AAAA,MACT;AAAA,IACJ;AAAA,EACJ;AACA,SAAO;AACX;;;AC56BO,IAAM,gBAAgB;AAmGtB,IAAM,eAAe,CAAC,QAA8B,GAAkB,eAAuB;AAChG,QAAM,IAAI,EAAE,aAAa,QAAQ,YAAY,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,IAAI;AACnF,QAAM,KAAK,IAAI,OAAO,GAAG,UAAU,IAAI,EAAE,SAAS,CAAC,GAAG;AACtD,QAAM,IAAI,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC;AAC7D,SAAO,IAAI,EAAE,SAAS,EAAE,IAAI,OAAO,EAAE,OAAO,MAAM,GAAG,WAAW,aAAa,CAAC,EAAE,SAAS,EAAE,MAAM,OAAU,IAAI;AACnH;AAEO,IAAM,oBAAoB,CAAC,QAAiC;AAC/D,MAAI,MAaO;AACX,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,OAAO,MAAM;AACf,eAAW,KAAK,CAAC,GAAG,SAAS,GAAG;AAC5B,UAAI;AACA,UAAE;AAAA,MACN,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,EACJ;AACA,QAAM,OAAO,MAAO,MAAM,EAAE,SAAS,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE,WAAW,SAAS,IAAI,QAAQ,IAAI,CAAC;AACrG,QAAM,OAAO,MAAM;AACf,QAAI,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,GAAG;AACjC,UAAI,KAAK,IAAI,IAAI,KAAK;AACtB,UAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,MAAM,IAAI,MAAM,IAAI,KAAK,EAAE,IAAI,OAAO,IAAI,OAAO,QAAQ,OAAO,CAAC;AAAA,IAC3G;AACA,SAAK;AAAA,EACT;AACA,QAAM,MAAM,CAAC,MAAqB;AAC9B,UAAM,IAAI;AACV,QAAI,CAAC,EAAG;AACR,UAAM;AACN,QAAI,EAAE,YAAY,SAAU,GAAE,QAAQ,UAAU,CAAC;AACjD,MAAE,QAAQ,CAAC;AACX,SAAK;AAAA,EACT;AACA,QAAM,SAAS,CAAC,aAAsD;AAAA,IAClE;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,GAAI,MAAM,EAAE,SAAS,IAAI,EAAE,IAAI,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,IACzD,GAAI,YAAY,YAAY,MAAM,EAAE,MAAM,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,IAAK,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7F;AAEA,QAAM,MAAM,MAAM;AACd,UAAM,IAAI;AACV,UAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI;AACjD,QAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAM;AAC3B,QAAI,CAAC,EAAE,QAAQ,WAAY,QAAO,IAAI,OAAO,QAAQ,CAAC;AACtD,MAAE,OAAO;AACT,MAAE,QAAQ;AACV,SAAK;AACL,YAAQ,QAAQ,EACX,KAAK,MAAM,EAAE,QAAQ,aAAa,IAAI,CAAC,EACvC;AAAA,MACG,CAAC,OAAO;AACJ,UAAE,OAAO;AACT,YAAI,QAAQ,EAAG;AACf,YAAI,OAAO,MAAO,QAAO,KAAK;AAC9B,YAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,OAAO,MAAM,KAAK,IAAI,QAAQ,YAAY,CAAC;AACrH,YAAI,OAAO,WAAW,CAAC;AAAA,MAC3B;AAAA,MACA,MAAM;AACF,UAAE,OAAO;AACT,UAAE,QAAQ;AACV,aAAK;AAAA,MACT;AAAA,IACJ;AAAA,EACR;AAEA,SAAO;AAAA,IACH,MAAM,CAAC,WAAW,UAAU,CAAC,MAAM;AAC/B,UAAI,IAAK,QAAO,IAAI;AACpB,YAAM,SAAS,IAAI,OAAO;AAC1B,YAAM,IAAI,QAAQ,UAAU,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AACjE,YAAM,SAAS,IAAI,aAAa,QAAQ,GAAG,IAAI,WAAW,CAAC,IAAI;AAC/D,UAAI,CAAC,KAAK,CAAC,QAAQ,MAAM,OAAQ,QAAO,QAAQ,QAAQ,EAAE,SAAS,UAAU,OAAO,EAAE,CAAC;AAEvF,YAAM,MAAM,IAAI,KAAK,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC/D,YAAM,QAAQ,EAAE,MAAM,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC;AACnD,UAAI,UAAsC,MAAM;AAAA,MAAC;AACjD,YAAM,UAAU,IAAI,QAAuB,CAAC,MAAO,UAAU,CAAE;AAC/D,YAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,IAAI,EAAE,YAAY,MAAM,CAAC,GAAG;AAC/E,YAAM,EAAE,GAAG,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,OAAO,OAAO,GAAG,MAAM,MAAM,OAAO,MAAM,oBAAI,IAAI,GAAG,SAAS,SAAS,QAAQ;AACxI,UAAI,OAAO,KAAM,KAAI,MAAM,aAAa,EAAE,YAAY,OAAO,MAAM,SAAS,OAAO,QAAQ,CAAC;AAC5F,WAAK;AACL,aAAO;AAAA,IACX;AAAA,IACA,MAAM,MACF,MACM;AAAA,MACI,SAAS,IAAI;AAAA,MACb,SAAS,IAAI;AAAA,MACb,MAAM,IAAI,MAAM,IAAI,KAAK;AAAA,MACzB,OAAO,IAAI;AAAA,MACX,OAAO,IAAI,MAAM;AAAA,MACjB,MAAM,IAAI,UAAU,IAAI,MAAM,SAAS;AAAA,MACvC,OAAO,IAAI;AAAA,MACX,MAAM,IAAI;AAAA,MACV,MAAM,IAAI;AAAA,MACV,OAAO,IAAI;AAAA,IACf,IACA;AAAA,IACV,WAAW,CAAC,MAAM;AACd,gBAAU,IAAI,CAAC;AACf,aAAO,MAAM,UAAU,OAAO,CAAC;AAAA,IACnC;AAAA,IACA,MAAM,MAAM;AACR,UAAI,CAAC,OAAO,IAAI,KAAM;AAEtB,UAAI,IAAI,MAAM,IAAI,KAAK,EAAE,SAAS,WAAW,IAAI,UAAU,IAAI,MAAM,SAAS,EAAG,QAAO,IAAI;AAC5F,UAAI;AACJ,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,MAAM,MAAM;AACR,UAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,MAAO;AACpC,UAAI;AACJ,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,MAAM,CAAC,OAAO;AACV,UAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG;AAC7D,UAAI,OAAO;AACX,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,OAAO,MAAM;AACT,UAAI,CAAC,OAAO,IAAI,KAAM;AACtB,UAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,OAAO,IAAI,OAAO,QAAQ,SAAS,CAAC;AAC1E,UAAI,OAAO,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ;AACJ;;;ACnQO,IAAM,eAAN,MAAmB;AAAA,EAGtB,YACqB,WAAW,KACX,SAAS,IACT,QAAQ,GAC3B;AAHmB;AACA;AACA;AALrB,wBAAQ,UAAgD,CAAC;AACzD,wBAAQ,SAAQ;AAAA,EAKb;AAAA,EACH,KAAK,GAAW,GAAW,GAAW;AAClC,UAAM,OAAO,KAAK,OAAO,OAAO,CAAC,MAAM,IAAI,EAAE,KAAK,KAAK,YAAY,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,KAAK,KAAK,MAAM;AAC9G,QAAI,KAAK,WAAW,KAAK,OAAO,OAAQ,MAAK,QAAQ;AACrD,SAAK,SAAS,CAAC,GAAG,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;AACnC,QAAI,KAAK,OAAO,UAAU,KAAK,SAAS,CAAC,KAAK,OAAO;AACjD,WAAK,QAAQ;AACb,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AACJ;;;ACmCA,IAAM,WAAW;AACjB,IAAM,QAAQ;AACd,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,cAAc;AACpB,IAAM,SAAS,KAAK;AAGpB,IAAM,UAAU,CAAC,MAAc;AAC3B,MAAIC,KAAI;AACR,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAK,CAAAA,KAAI,KAAK,KAAKA,KAAI,EAAE,WAAW,CAAC,GAAG,QAAQ;AAC9E,UAAQA,OAAM,KAAK;AACvB;AAEO,IAAM,iBAAiB,CAAC,MAAoB,OAAsB;AACrE,MAAI,QAAiB;AACrB,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,MAAI,MAAqH;AACzH,MAAI,SAAkB,CAAC;AACvB,MAAI,QAAgB,CAAC;AAErB,QAAM,SAAS,MAAM;AACjB,UAAM,UAAU,GAAG,QAAQ;AAC3B,UAAM,MAAM,GAAG,OAAO;AACtB,QAAI,CAAC,OAAO,IAAI,YAAY,SAAS;AACjC,eAAS,CAAC;AACV,cAAQ,CAAC;AACT,aAAO;AACP,YAAM,UAAU,CAAC,CAAC,OAAO,QAAQ,OAAO,KAAK,IAAI,cAAc;AAC/D,YAAM,EAAE,SAAS,OAAO,KAAK,IAAI,GAAG,KAAK,GAAG,WAAW,SAAS,SAAS,UAAU,SAAS,MAAM;AAAA,IACtG;AACA,WAAO;AAAA,EACX;AAEA,QAAM,OAAO,OAAO,MAA+B;AAC/C,QAAI,CAAC,OAAO,UAAU,EAAE,QAAS;AACjC,UAAM,QAAQ,OAAO,OAAO,GAAG,OAAO,MAAM;AAC5C,UAAM,KAAK,MAAM,OAAO,GAAG,MAAM,MAAM;AACvC,UAAM,OAAO,KAAK,OAAO;AACzB,UAAM,EAAE,YAAY,YAAY,SAAS,IAAI,GAAG,IAAI;AACpD,UAAM,OAAO,KAAK,UAAU;AAAA,MACxB,KAAK,GAAG;AAAA,MACR,SAAS,EAAE,QAAQ,KAAK;AAAA,MACxB,WAAW,EAAE;AAAA,MACb,OAAO,EAAE;AAAA,MACT,KAAK,EAAE;AAAA,MACP,KAAK;AAAA,MACL,MAAM,KAAK,UAAU,KAAK;AAAA,MAC1B,MAAM,EAAE,OAAO,MAAM,CAAC,EAAE,GAAG,MAAM,MAAM,MAAM,SAAS,CAAC,EAAE,GAAG,IAAI,OAAO,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,IAAI,OAAO,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,OAAO,GAAG;AAAA,MAClJ;AAAA,MACA;AAAA,MACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,SAAS,EAAE;AAAA,MACX,KAAK,GAAG;AAAA,IACZ,CAAC;AACD,UAAM,SAAS,MAAM,KAAK,KAAK,IAAI;AAGnC,QAAI,WAAW,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,IAAK,GAAE,UAAU;AAAA,EAC1F;AAEA,QAAM,OAAO,YAAY;AACrB,QAAI,QAAQ,CAAC,GAAG,QAAQ,KAAK,CAAC,GAAG,OAAO,EAAG;AAC3C,UAAM,IAAI,OAAO;AACjB,QAAI,EAAE,WAAW,KAAK,IAAI,IAAI,EAAE,QAAQ,OAAQ;AAEhD,QAAI,KAAK,aAAa,EAAG;AACzB,WAAO;AACP,QAAI;AACA,YAAM,OAAO,MAAM,KAAK,QAAQ,KAAK;AACrC,UAAI,CAAC,QAAQ,KAAK,QAAQ,KAAM;AAChC,aAAO,KAAK;AACZ,YAAM,OAAO,KAAK,OAAO;AACzB,YAAM,QAAQ,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AACjD,YAAM,WAAW,MAAM,KAAK,MAAM;AAElC,UAAI,aAAa,MAAM;AACnB,eAAO;AACP;AAAA,MACJ;AACA,YAAM,QAAQ,SAAS,IAAI,CAAC,CAAC,GAAG,GAAG,GAAGA,EAAC,MAAM,CAAC,IAAI,OAAO,IAAI,OAAO,IAAI,OAAOA,KAAI,KAAK,EAAE,IAAI,KAAK,KAAK,CAA2B;AACnI,aAAO,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,KAAK,KAAK,KAAK,MAAM,CAAC;AACzE,UAAI,CAAC,EAAE,WAAW;AAEd,cAAM,QAAQ,KAAK,IAAI,IAAI;AAC3B,iBAAS,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,KAAK;AAC1C,gBAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,KAAK;AACxC;AAAA,MACJ;AACA,YAAM,QAAQ,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,IAAI,QAAQ,CAAC;AACzD,UAAI,OAAO,UAAU,gBAAgB,SAAS,YAAa,OAAM,KAAK,CAAC;AAAA,IAC3E,QAAQ;AAAA,IAER,UAAE;AACE,aAAO;AAAA,IACX;AAAA,EACJ;AAEA,SAAO;AAAA;AAAA,IAEH,KAAK,QAAiB;AAClB,YAAM,KAAK,UAAU,GAAG,QAAQ,KAAK,CAAC,CAAC,GAAG,OAAO;AACjD,UAAI,MAAM,UAAU,KAAM,SAAQ,KAAK,YAAY,MAAM,KAAK,KAAK,GAAG,QAAQ;AAC9E,UAAI,CAAC,MAAM,UAAU,MAAM;AACvB,aAAK,cAAc,KAAK;AACxB,gBAAQ;AACR,YAAI,KAAK,UAAW,MAAK,KAAK,GAAG;AAAA,MACrC;AAAA,IACJ;AAAA;AAAA,IAEA,KAAK,GAAoB;AACrB,UAAI,CAAC,GAAG,QAAQ,KAAK,CAAC,GAAG,OAAO,EAAG;AACnC,aAAO;AACP,YAAM,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,EAAE,CAAC;AAClC,UAAI,MAAM,SAAS,IAAK,OAAM,OAAO,GAAG,MAAM,SAAS,GAAG;AAAA,IAC9D;AAAA;AAAA,IAEA,QAAQ,MAAwB;AAC5B,UAAI,CAAC,OAAO,IAAI,aAAa,IAAI,WAAW,CAAC,GAAG,QAAQ,EAAG;AAC3D,UAAI,YAAY;AAChB,UAAI,UAAU;AACd,WAAK,KAAK,GAAG;AAAA,IACjB;AAAA;AAAA,IAEA,QAAQ;AACJ,UAAI,KAAK,UAAW,QAAO,KAAK,GAAG;AACnC,aAAO,QAAQ,QAAQ;AAAA,IAC3B;AAAA;AAAA,IAEA,OAAO;AACH,eAAS,CAAC;AACV,cAAQ,CAAC;AACT,YAAM;AACN,aAAO;AAAA,IACX;AAAA;AAAA,IAEA;AAAA,EACJ;AACJ;AAWO,IAAM,cAAc,oBAAI,IAAoC;AAG5D,IAAM,eAAe,MACxB,QAAQ;AAAA,EACJ,CAAC,GAAG,WAAW,EAAE;AAAA,IACb,CAAC,QACG,IAAI,QAA8D,CAAC,YAAY;AAC3E,YAAM,IAAI,IAAI;AAEd,UAAI,CAAC,EAAG,QAAO,QAAQ,MAAM;AAC7B,YAAM,IAAI,WAAW,MAAM,QAAQ,QAAQ,GAAG,GAAG;AACjD,UAAI;AACA,UAAE,gBAAgB,CAAC,GAAG,GAAG,GAAGA,OAAM;AAC9B,uBAAa,CAAC;AACd,kBAAQ,IAAI,KAAKA,KAAI,IAAI,CAAC,GAAG,GAAG,GAAGA,EAAC,IAAI,MAAM;AAAA,QAClD,CAAC;AAAA,MACL,QAAQ;AACJ,qBAAa,CAAC;AACd,gBAAQ,QAAQ;AAAA,MACpB;AAAA,IACJ,CAAC;AAAA,EACT;AACJ,EAAE,KAAK,CAAC,OAAQ,GAAG,SAAS,QAAQ,IAAI,OAAO,GAAG,OAAO,CAAC,MAA6C,MAAM,QAAQ,CAAC,CAAC,CAAE;;;ACvMtH,IAAM,YAAY;AAClB,IAAM,cAAc;AAG3B,IAAM,OAAO;AAUN,IAAM,eAAe,CAAC,KAAkD,QAAQ,UAA4E;AAC/J,QAAM,SAAS,IAAI,SAAS;AAC5B,MAAI,UAAU,KAAK,KAAK,MAAM,GAAG;AAC7B,UAAM,QAAQ,IAAI,WAAW;AAC7B,WAAO,EAAE,MAAM,QAAQ,SAAS,SAAS,KAAK,KAAK,KAAK,IAAI,QAAQ,MAAM,QAAQ,MAAM;AAAA,EAC5F;AACA,QAAM,SAAS,IAAI,KAAK;AACxB,SAAO,UAAU,KAAK,KAAK,MAAM,IAAI,EAAE,MAAM,QAAQ,SAAS,MAAM,QAAQ,KAAK,IAAI;AACzF;AAiJO,IAAM,kBAAkB,CAAC,UAAkB,UAAU,eAAe,CAAC,MAAM,WAAW,GAAG;;;ACyEzF,IAAM,eAAe;AAErB,IAAM,OAAO;AAAA,EAChB,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AACb;AAEA,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,iBAAiB,IAAI,KAAK;AAChC,IAAM,qBAAqB;AAE3B,IAAM,cAAc;AAEpB,IAAMC,QAAO,CAAC,GAAW,MAAe,EAAE,SAAS,IAAI,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,WAAM;AAE1E,IAAM,eAAe,CAAC,SAA0B,SAAqC;AACxF,QAAM,UAAU,QAAQ,UAAU,IAAI,KAAK;AAC3C,QAAM,QAAQ,QAAQ,QAAQ,cAAc,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACrE,QAAM,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;AACxC,QAAM,gBAAgB,KAAK,gBAAgB,CAAC,IAAI,OAAO,YAAY,IAAI,EAAE;AACzE,QAAM,kBAAkB,KAAK,kBAAkB,CAAC,OAAO,cAAc,EAAoC;AACzG,QAAM,eAAe,KAAK,eAAe,CAAC,IAAI,OAAO,WAAW,IAAI,EAAE;AACtE,QAAM,iBAAiB,KAAK,iBAAiB,CAAC,OAAO,aAAa,EAAmC;AACrG,QAAM,aAAa,KAAK,IAAI,KAAM,QAAQ,mBAAmB,GAAM;AACnE,QAAM,WAAW,KAAK,IAAI,IAAI,QAAQ,YAAY,GAAI;AACtD,QAAM,WAAW,QAAQ,WAAW;AACpC,QAAM,UAAU,KAAK;AAErB,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,OAAO,CAAC,YAAoB;AAC9B,QAAI,OAAO,IAAI,OAAO,EAAG;AACzB,WAAO,IAAI,OAAO;AAClB,KAAC,KAAK,QAAQ,CAAC,MAAc,QAAQ,KAAK,CAAC,IAAI,cAAc,OAAO,EAAE;AAAA,EAC1E;AACA,QAAM,QAAQ,CAAC,YAAoB;AAC/B,QAAI,QAAQ,MAAO,EAAC,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC,IAAI,cAAc,OAAO,EAAE;AAAA,EAC5F;AACA,MAAI,CAAC,OAAQ,MAAK,6EAA6E;AAE/F,MAAI,UAAsB,EAAE,UAAU,UAAU;AAChD,MAAI;AACA,cAAU,KAAK,QAAQ;AAAA,EAC3B,QAAQ;AAAA,EAER;AACA,QAAM,SAAS,KAAK,SAAS,OAAO,QAAQ,oBAAoB,EAAE,KAAK;AACvE,QAAM,UAAU,QAAQ,YAAY,QAAQ,aAAa,GAAG,QAAQ,UAAU,GAAG,QAAQ,QAAQ,KAAK,QAAQ,KAAK,MAAM,EAAE,KAAK;AAChI,QAAM,MAAe,EAAE,GAAG,aAAa,QAAQ,UAAU,UAAU,QAAQ,SAAS;AAEpF,MAAI,UAAyB,QAAQ,WAAW;AAChD,MAAI,YAA2B;AAC/B,MAAI,WAAW,cAAc;AAC7B,MAAI;AAEJ,MAAI,SAAwB;AAC5B,MAAI;AACJ,MAAI,SAA+B;AACnC,MAAI,QAAwB,CAAC;AAC7B,MAAI,UAA+C;AAEnD,MAAI,MAA2E;AAC/E,MAAI,WAA4D;AAChE,MAAI;AACJ,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,WAAW;AACf,MAAI,eAAe;AACnB,MAAI,WAAiC;AACrC,MAAI,eAAwB;AAC5B,MAAI,aAAsB;AAC1B,MAAI,aAAsB;AAC1B,MAAI,WAAW,KAAK,UAAU,gBAAgB;AAC9C,MAAI,kBAAiC;AACrC,QAAM,QAAwB,CAAC;AAC/B,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,OAAO,IAAI,aAAa;AAE9B,MAAI,WAA+F;AACnG,QAAM,QAAQ,MAAM;AAChB,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,YAAY,SAAS,WAAW,UAAU,SAAS,OAAO,GAAI,YAAW,EAAE,QAAQ,IAAI,OAAO,YAAY,QAAQ,IAAI,CAAC,CAAC,EAAE;AAC/H,WAAO,SAAS;AAAA,EACpB;AACA,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,SAA6C,CAAC;AACpD,QAAM,aAA4B,CAAC;AACnC,QAAM,aAAa,oBAAI,IAAY;AACnC,MAAI,aAAa;AAGjB,QAAM,aAAa,OAAO,OAA2C;AACjE,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,OAAO,OAAO,EAAE;AACtB,UAAM,IAAI,MAAM,KAAK,MAAM,GAAG,IAAI,sBAAsB,mBAAmB,MAAM,CAAC,eAAe,mBAAmB,EAAE,CAAC,GAAG,OAAO,aAAa,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,MAAM,CAAC;AAC9K,iBAAa,EAAE,QAAQ,KAAK,GAAG;AAC/B,WAAO,EAAE,KAAO,MAAM,EAAE,KAAK,IAAoB;AAAA,EACrD;AAGA,QAAM,UAAU,kBAAkB,EAAE,QAAQ,MAAM,QAAQ,YAAY,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,UAAU,OAAO,OAAO,KAAK,EAAE,CAAC;AACzI,QAAM,QAAQ,YAAY;AAAA,IACtB,OAAO,CAAC,OAAO,UAAU,OAAO,OAAO,KAAK;AAAA,IAC5C,UAAU,MAAO,YAAY,QAAQ,aAAa;AAAA,IAClD,MAAM,QAAQ,eAAe;AAAA,IAC7B,SAAS,MACL,WAAW,YAAY,eACjB;AAAA,MACI,KAAK,CAAC,MAAc,IAAI,CAAC;AAAA,MACzB,KAAK,CAAC,GAAW,MAAc,KAAK,IAAI,GAAG,CAAC;AAAA,IAChD,IACA;AAAA,IACV,SAAS,KAAK;AAAA,IACd,YAAY,CAAC,OAAO,WAAW,EAAE;AAAA,EACrC,CAAC;AACD,QAAM,eAAe,MAAM;AACvB,QAAI,CAAC,WAAW,OAAQ;AACxB,UAAM,UAAU,MAAM;AACtB,SAAK,MAAM,QAAQ;AAAA,EACvB;AAGA,MAAI,WAA4B;AAChC,QAAM,UAAU,MAAM;AAClB;AACA,cAAU,KAAK,aAAa,QAAQ;AACpC,eAAW,KAAK,CAAC,GAAG,SAAS,GAAG;AAC5B,UAAI;AACA,UAAE;AAAA,MACN,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,QAAQ,CAAC,MAA4C,YAAoB;AAC3E,WAAO,KAAK,EAAE,IAAI,IAAI,GAAG,MAAM,SAASA,MAAK,SAAS,GAAG,EAAE,CAAC;AAC5D,QAAI,OAAO,SAAS,WAAY,QAAO,MAAM;AAAA,EACjD;AAIA,QAAM,MAAM,OAAO,QAAgB;AAC/B,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI;AACA,aAAO,MAAM,QAAQ,QAAQ,GAAG;AAAA,IACpC,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AACA,QAAM,MAAM,OAAO,KAAa,UAAkB;AAC9C,QAAI,CAAC,QAAS;AACd,QAAI;AACA,YAAM,QAAQ,QAAQ,KAAK,KAAK;AAAA,IACpC,QAAQ;AACJ,WAAK,oEAAoE;AAAA,IAC7E;AAAA,EACJ;AACA,QAAM,SAAS,OAAO,QAAgB;AAClC,QAAI,CAAC,QAAS;AACd,QAAI;AACA,YAAM,QAAQ,WAAW,GAAG;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACJ;AAEA,QAAM,eAAe,YAAY;AAC7B,QAAI,iBAAiB,MAAM;AACvB,qBAAe,YAAY;AAC3B,qBAAe;AAAA,IACnB;AACA,QAAI,CAAC,WAAW,YAAY,MAAO;AACnC,QAAI,MAAM,OAAQ,OAAM,IAAI,KAAK,OAAO,KAAK,UAAU,KAAK,CAAC;AAAA,QACxD,OAAM,OAAO,KAAK,KAAK;AAAA,EAChC;AACA,QAAM,kBAAkB,MAAM;AAC1B,QAAI,CAAC,WAAW,iBAAiB,KAAM;AACvC,mBAAe,aAAa,MAAM;AAC9B,qBAAe;AACf,WAAK,aAAa;AAAA,IACtB,GAAG,GAAI;AAAA,EACX;AAIA,QAAM,aAAa,MAAM,eAAe,YAAY,gBAAgB,YAAY,YAAY;AAE5F,QAAM,SAAS,MAAO,YAAY,eAAe,WAAW,IAAI;AAEhE,QAAM,SAAS,CAAC,OAA2B,QAAQ,QAAQ,EAAE;AAE7D,QAAM,eAAe,MAAM;AACvB,UAAM,IAAI,IAAI;AACd,QAAI,CAAC,WAAW,IAAI,QAAQ,QAAQ,mBAAoB,WAAU,EAAE,IAAI,cAAc,GAAG,MAAM,EAAE;AAAA,QAC5F,SAAQ,OAAO;AACpB,WAAO,QAAQ;AAAA,EACnB;AAEA,QAAM,QAAQ,CAAC,OAAO,kBAAkB,SAAS,KAAK,GAAG,QAAQ,GAAG;AAIpE,QAAM,SAAS,CAAC,OAAe,OAAiC,KAAK,IAAI,MAAM;AAC3E,QAAI,OAAQ;AACZ,QAAI,CAAC,QAAQ;AACT,YAAM,KAAK,MAAM,OAAO,OAAO,OAAO,EAAE,CAAC;AACzC;AAAA,IACJ;AACA,QAAI,YAAY,SAAS,CAAC,OAAQ;AAClC,UAAM,YAAY,aAAa;AAC/B,UAAM,MAAM,YAAY,gBAAgB,KAAK,IAAI,WAAW;AAC5D,UAAM,OAAO,KAAK,SAAS;AAC3B,UAAM,KAAK;AAAA,MACP;AAAA,MACA,OAAO,MAAM,EAAE,GAAG,OAAO,WAAW,IAAI,IAAI;AAAA,MAC5C,YAAY,OAAO;AAAA,MACnB;AAAA,MACA;AAAA,MACA,KAAK,MAAM;AAAA,MACX,GAAI,OAAO,IAAI,YAAY,YAAY,IAAI,SAAS,CAAC;AAAA,MACrD,GAAI,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,MAAM,KAAK,CAAC,GAAG,GAAG,KAAK,MAAM,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC;AAAA,MAC3E,KAAK;AAAA,IACT,CAAC;AACD,QAAI,MAAM,SAAS,SAAU,OAAM,OAAO,GAAG,MAAM,SAAS,QAAQ;AACpE,oBAAgB;AAChB,QAAI,MAAM,UAAU,YAAa,MAAK,MAAM;AAAA,EAChD;AAIA,QAAM,OAAO,OAAO,MAAc,SAAkC;AAChE,UAAM,MAAM,OAAO,oBAAoB,cAAc,IAAI,gBAAgB,IAAI;AAC7E,UAAM,QAAQ,MAAM,aAAa,MAAM,IAAI,MAAM,GAAG,kBAAkB,IAAI;AAC1E,QAAI;AACA,YAAM,IAAI,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,QAAQ,QAAQ,SAAS,EAAE,gBAAgB,mBAAmB,GAAG,MAAM,QAAQ,KAAK,OAAO,CAAC;AAC3I,mBAAa,EAAE,QAAQ,KAAK,GAAG;AAC/B,aAAO,EAAE;AAAA,IACb,QAAQ;AACJ,aAAO;AAAA,IACX,UAAE;AACE,UAAI,UAAU,KAAM,gBAAe,KAAK;AAAA,IAC5C;AAAA,EACJ;AAEA,QAAM,YAAY,YAAY;AAC1B,QAAI,CAAC,MAAM,UAAU,YAAY,SAAS,CAAC,OAAQ;AACnD,QAAI,IAAI,IAAI,aAAc;AAC1B,UAAM,WAAW,MAAM,MAAM;AAC7B,UAAM,WAAW,cAAc,QAAQ,UAAU,KAAK,OAAO,OAAO,CAAC,CAAC;AACtE,UAAM,WAAW,IAAI,IAAI,SAAS,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;AAC1D,UAAM,OAAO,oBAAI,IAAkB;AACnC,eAAW,KAAK,UAAU;AACtB,YAAM,SAAS,MAAM,KAAK,mBAAmB,EAAE,IAAI;AACnD,UAAI,UAAU,OAAO,SAAS,KAAK;AAC/B,UAAE,OAAO,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AACnC,mBAAW;AACX,uBAAe;AAAA,MACnB,WAAW,UAAU,OAAO,SAAS,OAAO,WAAW,OAAO,WAAW,KAAK;AAE1E,UAAE,OAAO,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AACnC,YAAI,WAAW,IAAK,MAAK,6BAA6B,MAAM,iFAAuE;AAAA,MACvI,OAAO;AACH;AACA,uBAAe,IAAI,IAAI,KAAK,IAAI,gBAAgB,MAAO,KAAK,QAAQ;AACpE,cAAM,mBAAmB,UAAU,SAAS,kBAAkB,KAAK,OAAO,eAAe,IAAI,KAAK,GAAI,CAAC,KAAK;AAC5G;AAAA,MACJ;AAAA,IACJ;AAEA,YAAQ,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,SAAS,CAAC,EAAE;AACtF,UAAM,aAAa;AAAA,EACvB;AAGA,MAAI,YAAkC;AACtC,QAAM,QAAQ,MAAqB;AAC/B,QAAI;AACA,aAAQ,0BAAc,SAAS,KAAK,MAAM;AACtC,oBAAY;AACZ,eAAO,MAAM;AAAA,MACjB,CAAC;AACL,eAAW,UAAU,EAAE,QAAQ,MAAM;AACjC,iBAAW;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACX;AAEA,QAAM,aAAa,MAAM;AACrB,QAAI,eAAe,QAAQ,OAAQ;AACnC,iBAAa,cAAc,MAAM,KAAK,MAAM,GAAG,UAAU;AAAA,EAC7D;AACA,QAAM,YAAY,MAAM;AACpB,QAAI,eAAe,KAAM;AACzB,oBAAgB,UAAU;AAC1B,iBAAa;AAAA,EACjB;AAIA,QAAM,aAAa,YAAY;AAC3B,QAAI,eAAe,MAAM;AACrB,qBAAe,UAAU;AACzB,mBAAa;AAAA,IACjB;AACA,WAAO,WAAW,QAAQ;AAEtB,YAAM,QAAQ,WAAW,OAAO,GAAG,CAAC;AACpC,YAAM,WAAW,WAAW,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC;AAClE,YAAM,SAAS,MAAM,KAAK,mBAAmB,KAAK,UAAU,EAAE,KAAK,QAAQ,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,GAAI,KAAK,QAAQ,MAAM,CAAC,CAAC;AACnI,UAAI,UAAU,OAAO,SAAS,OAAO,WAAW,OAAO,WAAW,IAAK,MAAK,oCAAoC,MAAM,sCAAsC;AAAA,IAChK;AAAA,EACJ;AAEA,QAAM,UAAU,CAAC,OAAgB,WAAqC,QAAQ,UAAU;AACpF,QAAI,CAAC,YAAY,UAAU,YAAY,SAAS,CAAC,UAAU,cAAc,WAAY;AACrF,UAAM,IAAI,cAAc,KAAK;AAC7B,QAAI,qBAAqB,KAAK,EAAE,OAAO,EAAG;AAC1C,UAAM,OAAO,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO;AACnC,QAAI,WAAW,IAAI,IAAI,EAAG;AAC1B,eAAW,IAAI,IAAI;AACnB;AACA,UAAM,MAAM,OAAO;AACnB,eAAW,KAAK;AAAA,MACZ,GAAG;AAAA,MACH;AAAA,MACA,SAAS,cAAc;AAAA,MACvB,KAAK,MAAM;AAAA,MACX,IAAI,IAAI;AAAA,MACR,QAAQ,OAAO,MAAM;AAAA,MACrB,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,MAAM,EAAE,YAAY,IAAI,IAAI,CAAC;AAAA,MACjC,GAAI,UAAU,EAAE,WAAW,QAAQ,GAAG,IAAI,CAAC;AAAA,IAC/C,CAAC;AACD,cAAU,KAAK,EAAE,MAAM,SAAS,MAAM,iBAAiB,KAAK,OAAOA,MAAK,EAAE,SAAS,GAAG,EAAE,CAAC;AACzF,cAAU,QAAQ,OAAO;AAEzB,QAAI,MAAO,MAAK,WAAW;AAAA,aAClB,eAAe,KAAM,cAAa,aAAa,MAAM,KAAK,WAAW,GAAG,GAAI;AAAA,EACzF;AAEA,MAAI;AACJ,MAAI,mBAAmB;AACvB,QAAM,sBAAsB,MAAM;AAC9B,QAAI,CAAC,YAAY,CAAC,KAAK,cAAc,iBAAkB;AACvD,uBAAmB;AACnB,sBAAkB,KAAK,WAAW,iBAAiB;AACnD,SAAK,WAAW,iBAAiB,CAAC,OAAO,YAAY;AACjD,UAAI;AACA,gBAAQ,OAAO,WAAW,CAAC,CAAC,OAAO;AAAA,MACvC,QAAQ;AAAA,MAER;AACA,wBAAkB,OAAO,OAAO;AAAA,IACpC,CAAC;AAAA,EACL;AAIA,MAAI,WAAW,QAAQ,WAAW;AAClC,aAAW,KAAK,WACV;AAAA,IACI;AAAA,MACI;AAAA,MACA,aAAa;AAAA,MACb,eAAe;AAAA,MACf,SAAS,KAAK,SAAS;AAAA,MACvB,cAAc,KAAK,SAAS;AAAA,MAC5B,OAAO,KAAK,SAAS;AAAA,MACrB,QAAQ,MAAM,KAAK,SAAS;AAAA,MAC5B,MAAM,CAAC,SAAS,KAAK,mBAAmB,IAAI;AAAA,IAChD;AAAA,IACA;AAAA,MACI,SAAS,MAAM,YAAY,UAAU,CAAC,UAAU,YAAY,SAAS,CAAC,CAAC;AAAA,MACvE,QAAQ,MAAM,QAAQ;AAAA,MACtB,SAAS,MAAM,SAAS,MAAM,aAAa;AAAA,MAC3C,KAAK,OAAO,EAAE,YAAY,OAAO,GAAG,YAAY,CAAC,CAAC,YAAY,UAAU,OAAO,OAAO,CAAC,EAAE;AAAA,MACzF;AAAA,MACA,KAAK;AAAA,IACT;AAAA,EACJ,IACA;AACN,MAAI,QAAQ,UAAU,CAAC,KAAK,SAAU,MAAK,yFAAyF;AAIpI,MAAI;AACJ,QAAM,aAAa,CAAC,SAAiB;AACjC,QAAI,OAAQ;AACZ,UAAM,OAAO;AACb,eAAW;AACX,cAAU,KAAK,SAAS,QAAQ;AAChC,QAAI,SAAS,YAAY,SAAS,UAAU;AACxC,iBAAW;AACX,UAAI,oBAAoB,MAAM;AAE1B,0BAAkB;AAClB,cAAM,aAAa,UAAU;AAC7B,YAAI,QAAQ,cAAc,MAAO,QAAO,aAAa,EAAE,MAAM,MAAM,CAAC;AAAA,MACxE;AAAA,IACJ,WAAW,SAAS,gBAAgB,SAAS,cAAc;AACvD,wBAAkB,IAAI;AACtB,YAAM,aAAa,gBAAgB;AACnC,UAAI,QAAQ,cAAc,MAAO,QAAO,iBAAiB;AACzD,gBAAU;AACV,WAAK,UAAU,MAAM;AAErB,WAAK,aAAa;AAClB,WAAK,MAAM;AACX,UAAI,WAAW,OAAQ,MAAK,WAAW;AAAA,IAC3C;AAAA,EACJ;AAIA,QAAM,cAAc,YAAY;AAC5B,QAAI,CAAC,OAAQ;AACb,QAAI;AACA,YAAM,IAAI,MAAM,KAAK,MAAM,GAAG,IAAI,uBAAuB,mBAAmB,MAAM,CAAC,IAAI,EAAE,QAAQ,MAAM,CAAC;AACxG,UAAI,CAAC,EAAE,IAAI;AACP,aAAK,2BAA2B,EAAE,MAAM,sCAAsC;AAC9E;AAAA,MACJ;AACA,YAAM,IAAK,MAAM,EAAE,KAAK;AACxB,UAAI,KAAK,MAAM,QAAQ,EAAE,WAAW,GAAG;AACnC,iBAAS;AACT,YAAI,YAAY,MAAO,OAAM,IAAI,KAAK,QAAQ,KAAK,UAAU,CAAC,CAAC;AAC/D,gBAAQ;AAAA,MACZ;AAAA,IACJ,QAAQ;AACJ,YAAM,6CAA6C;AAAA,IACvD;AAAA,EACJ;AAKA,MAAI,YAA2B;AAC/B,MAAI;AACJ,MAAI;AACJ,MAAI,UAA+B;AACnC,QAAM,SAAS,oBAAI,IAAY;AAG/B,QAAM,aAAa,CAAC,SAAsC;AACtD,UAAM,IAAI,MAAM;AAChB,QAAI,CAAC,GAAG,MAAM,OAAO,IAAI,EAAE,EAAE,EAAG;AAChC,WAAO,IAAI,EAAE,EAAE;AACf,WAAO,SAAS,EAAE,QAAQ,UAAU,SAAS,EAAE,GAAG,CAAC;AACnD,QAAI,EAAE,OAAO,uBAAuB,KAAK,EAAE,GAAG,EAAG,MAAK,UAAU,EAAE,GAAG;AAAA,EACzE;AACA,QAAM,iBAAiB,MAAM;AACzB,QAAI,WAAW,CAAC,KAAK,QAAQ,OAAQ;AACrC,QAAI;AACA,gBAAU,KAAK,KAAK,OAAO,UAAU;AACrC,WAAK,KAAK,KACL,WAAW,EACX,KAAK,UAAU,EACf,MAAM,MAAM,MAAS;AAAA,IAC9B,QAAQ;AACJ,gBAAU;AAAA,IACd;AAAA,EACJ;AAEA,QAAM,YAAY,MACd,SACM,QAAQ,QAAQ,IAChB,IAAI,QAAc,CAAC,YAAY;AAC3B,UAAM,KAAK,OAAO;AAAA,EACtB,CAAC;AAEX,QAAM,kBAAkB,OAAO,IAA4B,CAAC,MAAiC;AACzF,QAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,eAAe,QAAQ,4DAA4D;AACpH,UAAM,UAAU;AAChB,QAAI,CAAC,UAAU,YAAY,MAAO,QAAO,EAAE,QAAQ,SAAS,QAAQ,CAAC,SAAS,mBAAmB,sBAAsB;AACvH,QAAI,CAAC,WAAY,QAAO,EAAE,QAAQ,gBAAgB;AAClD,UAAM,MAAM;AACZ,UAAM,WAAW,OAAO,GAAG;AAC3B,QAAI;AACA,YAAM,aAAa,MAAM,KAAK,KAAK,WAAW,EAAE,QAAQ,KAAK;AAC7D,UAAI,eAAe,UAAW,QAAO,EAAE,QAAQ,eAAe,WAAW,WAAW,YAAY;AAChG,YAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,EAAE,SAAS;AAC/C,UAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,QAAQ,qEAAqE;AACzH,YAAM,SAAS,MAAM,KAAK,iBAAiB,KAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,KAAK,UAAU,UAAU,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC;AAC5I,UAAI,SAAS,OAAO,UAAU,KAAK;AAC/B,aAAK,uCAAuC,UAAU,WAAW,sCAAsC;AACvG,eAAO,EAAE,QAAQ,SAAS,QAAQ,qBAAqB,UAAU,SAAS,IAAI;AAAA,MAClF;AACA,kBAAY;AACZ,gBAAU;AACV,iBAAW;AACX,qBAAe;AACf,YAAM,sBAAsB;AAC5B,aAAO,EAAE,QAAQ,cAAc,MAAM;AAAA,IACzC,SAAS,GAAG;AACR,aAAO,EAAE,QAAQ,SAAS,QAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,EAAE;AAAA,IACjF;AAAA,EACJ;AAEA,QAAM,oBAAoB,YAAY;AAClC,UAAM,QAAQ;AACd,QAAI,CAAC,SAAS,CAAC,OAAQ,QAAO;AAC9B,gBAAY;AACZ,UAAM,SAAS,MAAM,KAAK,iBAAiB,KAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,SAAS,UAAU,UAAU,UAAU,QAAQ,OAAO,QAAQ,KAAK,CAAC,CAAC;AAC1J,WAAO,UAAU,OAAO,SAAS;AAAA,EACrC;AAIA,MAAI,YAAY;AAChB,QAAM,gBAAgB,YAAyC;AAC3D,QAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,UAAM,UAAU;AAChB,QAAI,CAAC,UAAU,YAAY,MAAO,QAAO;AACzC,QAAI,CAAC,WAAY,QAAO;AACxB,QAAI,UAAW,QAAO;AACtB,gBAAY;AACZ,QAAI;AAEA,YAAM,OAAO,MAAM,WAAW,UAAU,EAAE,MAAM,MAAM,IAAI,IAAI;AAC9D,UAAI,CAAC,IAAK,QAAO;AACjB,YAAM,QAAQ,MAAM,KAAK,YAAY,QAAQ,EAAE,MAAM,MAAM,KAAK;AAEhE,aAAO,cAAc,EAAE,UAAU,IAAI,UAAU,OAAO,IAAI,OAAO,QAAQ,QAAQ,cAAc,cAAc,CAAC;AAC9G,WAAK,MAAM;AACX,aAAO,QAAQ,cAAc;AAAA,IACjC,UAAE;AACE,kBAAY;AAAA,IAChB;AAAA,EACJ;AAIA,MAAI,eAA2B,MAAM;AAAA,EAAC;AACtC,QAAM,QAAQ,IAAI,QAAc,CAAC,MAAM;AACnC,mBAAe;AAAA,EACnB,CAAC;AACD,QAAM,YAAY,MAAM;AACpB,QAAI,QAAS;AACb,cAAU;AACV,iBAAa;AACb,YAAQ;AAAA,EACZ;AAEA,QAAM,QAAQ,YAAY;AACtB,QAAI,YAAY;AAChB,QAAI,YAAY,OAAO;AACnB,YAAM,CAAC,IAAI,QAAQ,QAAQ,WAAW,KAAK,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,QACpE,IAAI,KAAK,EAAE;AAAA,QACX,IAAI,KAAK,KAAK;AAAA,QACd,IAAI,KAAK,MAAM;AAAA,QACf,IAAI,KAAK,SAAS;AAAA,QAClB,IAAI,KAAK,QAAQ;AAAA,QACjB,IAAI,KAAK,OAAO;AAAA,MACpB,CAAC;AACD,UAAI,YAAY,cAAc;AAC1B,oBAAY,MAAM,cAAc;AAChC,YAAI,CAAC,GAAI,OAAM,IAAI,KAAK,IAAI,SAAS;AAAA,MACzC,WAAW,GAAI,OAAM,OAAO,KAAK,EAAE;AACnC,UAAI;AACA,cAAM,MAAM,SAAU,KAAK,MAAM,MAAM,IAAuB,CAAC;AAC/D,YAAI,MAAM,QAAQ,GAAG,EAAG,SAAQ,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,UAAU,QAAQ,GAAG,GAAG,KAAK,EAAE,MAAM,CAAC,QAAQ;AAAA,MACtH,QAAQ;AACJ,cAAM,OAAO,KAAK,KAAK;AAAA,MAC3B;AACA,UAAI;AACA,cAAM,IAAI,SAAU,KAAK,MAAM,MAAM,IAAsB;AAC3D,YAAI,KAAK,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC,OAAQ,UAAS;AAAA,MAC/D,QAAQ;AACJ,cAAM,OAAO,KAAK,MAAM;AAAA,MAC5B;AACA,UAAI;AACA,cAAM,IAAI,OAAO,YAAY,eAAgB,KAAK,MAAM,GAAG,IAAiD;AAC5G,YAAI,KAAK,OAAO,EAAE,SAAS,SAAU,YAAW;AAAA,MACpD,QAAQ;AAAA,MAER;AACA,UAAI;AACA,cAAM,OAAO,WAAW,YAAY,eAAgB,KAAK,MAAM,OAAO,IAAgB;AACtF,YAAI,MAAM,QAAQ,IAAI;AAAG,qBAAW,KAAK,KAAM,KAAI,OAAO,MAAM,SAAU,aAAY,IAAI,CAAC;AAAA;AAAA,MAC/F,QAAQ;AACJ,cAAM,OAAO,KAAK,OAAO;AAAA,MAC7B;AAEA,kBAAY,CAAC,CAAC,WAAW,CAAC;AAC1B,UAAI,UAAW,OAAM,IAAI,KAAK,WAAW,OAAO,IAAI,CAAC,CAAC;AAAA,IAC1D,OAAO;AACH,YAAM,QAAQ,IAAI,OAAO,OAAO,IAAI,EAAE,IAAI,MAAM,CAAC;AAAA,IACrD;AACA,QAAI,OAAQ;AACZ,aAAS;AACT,QAAI,OAAQ,WAAU;AAGtB,QAAI,UAA0C;AAC9C,QAAI,WAAW;AACX,gBAAU,CAAC;AACX,UAAI,QAAQ,gBAAgB,SAAS,KAAK,YAAY;AAClD,cAAM,MAAM,MAAM,KAAK,WAAW,EAAE,MAAM,MAAM,IAAI;AACpD,YAAI,KAAK;AACL,gBAAM,IAAI,WAAW,GAAG;AACxB,gBAAM,SAAS,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAClC,cAAI,OAAO,KAAK,MAAM,EAAE,OAAQ,OAAM,EAAE,SAAS,aAAa,GAAG,OAAO;AACxE,gBAAM,QAAQ,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,cAAI,OAAO;AACP,uBAAW,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ;AACtD,oBAAQ,YAAY;AACpB,gBAAI,YAAY,aAAc,OAAM,IAAI,KAAK,UAAU,KAAK,UAAU,QAAQ,CAAC;AAAA,UACnF;AACA,kBAAQ,OAAOA,MAAK,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,GAAG;AAAA,QAC9C;AAAA,MACJ;AAAA,IACJ;AAEA,UAAM,aAAa,UAAU;AAC7B,QAAI,QAAQ,cAAc,MAAO,QAAO,aAAa,EAAE,MAAM,KAAK,CAAC;AACnE,QAAI,QAAS,QAAO,YAAY,OAAO;AACvC,eAAW,OAAO,MAAM,OAAO,CAAC,EAAG,KAAI;AAEvC,QAAI,KAAK,SAAU,eAAc,KAAK,SAAS,iBAAiB,UAAU,UAAU;AACpF,wBAAoB;AAEpB,mBAAe;AACf,QAAI,aAAa,YAAY,CAAC,KAAK,SAAU,YAAW;AACxD,QAAI,MAAM,OAAQ,MAAK,MAAM;AAE7B,UAAM,YAAY;AAClB,cAAU;AACV,iBAAa;AAAA,EACjB;AACA,OAAK,MAAM,EAAE,MAAM,MAAM;AACrB,aAAS;AACT,cAAU;AAAA,EACd,CAAC;AAID,QAAM,SAAyB;AAAA,IAC3B,OAAO,CAAC,OAAO,UAAU;AACrB,UAAI,OAAO,UAAU,YAAY,CAAC,MAAO;AACzC,aAAO,OAAO,KAAK;AACnB,YAAM,QAAQ,KAAK;AAAA,IACvB;AAAA,IACA,KAAK,CAAC,GAAG,MAAM;AACX,UAAI,QAAQ,aAAa,SAAS,YAAY,MAAO;AACrD,YAAM,OAAO,KAAK,SAAS;AAC3B,UAAI,CAAC,QAAQ,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,EAAG;AAEzD,YAAM,QAAQ,EAAE,GAAG,KAAK,MAAM,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,KAAK,MAAM,KAAK,CAAC,GAAG,IAAI,KAAK,MAAM,KAAK,CAAC,GAAG,MAAM,KAAK,MAAM,KAAK,CAAC,GAAG,UAAU,IAAI,OAAO,IAAI,MAAM,MAAM;AACnK,aAAO,UAAU,KAAK;AACtB,gBAAU,KAAK,EAAE,MAAM,SAAS,MAAM,iBAAiB,KAAK,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,MAAM,GAAG,CAAC;AAClG,UAAI,KAAK,KAAK,GAAG,GAAG,IAAI,CAAC,GAAG;AACxB,eAAO,cAAc,KAAK;AAC1B,kBAAU,KAAK,EAAE,MAAM,QAAQ,MAAM,iBAAiB,KAAK,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,MAAM,GAAG,CAAC;AACjG,kBAAU,QAAQ,MAAM;AAAA,MAC5B;AAAA,IACJ;AAAA,IACA,WAAW,CAAC,OAAO;AACf,iBAAW;AACX,UAAI,CAAC,GAAI,WAAU,KAAK;AACxB,gBAAU,KAAK,aAAa,QAAQ;AAAA,IACxC;AAAA,IACA,QAAQ,CAAC,MAAM,UAAU;AACrB,UAAI,OAAO,SAAS,YAAY,CAAC,KAAK,KAAK,EAAG;AAC9C,YAAM,QAAQ,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,IAAI,MAAM,GAAG,GAAG;AACpE,UAAI,SAAS,iBAAiB,CAAC,MAAO;AACtC,YAAM,WAAW;AACjB,sBAAgB;AAChB,YAAM,cAAc,IAAI;AACxB,aAAO,WAAW,EAAE,GAAG,OAAO,MAAM,QAAQ,MAAM,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AACrF,gBAAU,KAAK,EAAE,MAAM,YAAY,KAAK,CAAC;AAAA,IAC7C;AAAA,IACA,UAAU,CAAC,IAAI,OAAOC,aAAY;AAC9B,UAAI,OAAO,OAAO,YAAY,CAAC,GAAI;AACnC,UAAI,CAAC,QAAQ;AACT,cAAM,KAAK,MAAM,OAAO,SAAS,IAAI,OAAOA,QAAO,CAAC;AACpD;AAAA,MACJ;AACA,YAAM,WAAW,OAAO;AAExB,eAAS,WAAW,QAAQ,IAAIA,UAAS,MAAM,KAAK,GAAG;AACvD,mBAAa;AACb,eAAS,EAAE,GAAG,OAAO,GAAG;AACxB,aAAO,aAAa,EAAE,GAAG,OAAO,IAAI,GAAI,YAAY,aAAa,KAAK,EAAE,YAAY,SAAS,IAAI,CAAC,EAAG,CAAC;AACtG,UAAI,YAAY,aAAc,MAAK,IAAI,KAAK,IAAI,EAAE;AAClD,cAAQ;AACR,mBAAa;AAAA,IACjB;AAAA,IACA,OAAO,MAAM;AACT,UAAI,CAAC,QAAQ;AACT,cAAM,KAAK,MAAM,OAAO,MAAM,CAAC;AAC/B;AAAA,MACJ;AAEA,UAAI,UAAW,MAAK,kBAAkB;AAEtC,WAAK,MAAM;AACX,mBAAa;AACb,eAAS;AACT,eAAS;AACT,gBAAU;AACV,YAAM;AACN,cAAQ,MAAM;AACd,iBAAW,cAAc;AACzB,UAAI,YAAY,cAAc;AAC1B,oBAAY,cAAc;AAC1B,aAAK,IAAI,KAAK,IAAI,SAAS;AAAA,MAC/B;AACA,cAAQ;AACR,mBAAa;AAAA,IACjB;AAAA,IACA,YAAY,CAAC,SAAS;AAClB,UAAI,SAAS,eAAe,SAAS,gBAAgB,SAAS,OAAO;AACjE,aAAK,gBAAgB,OAAO,IAAI,CAAC,kEAAkE;AACnG;AAAA,MACJ;AACA,UAAI,CAAC,QAAQ;AACT,cAAM,KAAK,MAAM,OAAO,WAAW,IAAI,CAAC;AACxC;AAAA,MACJ;AACA,UAAI,SAAS,QAAS;AACtB,YAAM,SAAS;AACf,gBAAU;AACV,UAAI,SAAS,OAAO;AAChB,kBAAU,KAAK;AACf,gBAAQ,CAAC;AACT,kBAAU;AACV,mBAAW,SAAS;AACpB,aAAK,QAAQ,IAAI,OAAO,OAAO,IAAI,EAAE,IAAI,MAAM,CAAC;AAAA,MACpD,WAAW,SAAS,aAAa;AAC7B,oBAAY;AACZ,aAAK,OAAO,KAAK,EAAE;AACnB,aAAK,OAAO,KAAK,QAAQ;AACzB,aAAK,OAAO,KAAK,OAAO;AAAA,MAC5B,OAAO;AACH,oBAAY,cAAc,cAAc;AACxC,aAAK,IAAI,KAAK,IAAI,SAAS;AAC3B,YAAI,SAAU,MAAK,IAAI,KAAK,UAAU,KAAK,UAAU,QAAQ,CAAC;AAC9D,YAAI,YAAY,KAAM,MAAK,IAAI,KAAK,SAAS,KAAK,UAAU,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,MACjF;AAEA,UAAI,WAAW,SAAS,iBAAiB,OAAQ,QAAO,WAAW,EAAE,MAAM,eAAe,QAAQ,cAAc,CAAC;AACjH,cAAQ;AACR,mBAAa;AAAA,IACjB;AAAA,IACA,cAAc,CAAC,UAAU,QAAQ,OAAO,QAAQ;AAAA,IAChD,SAAS,CAAC,QAAQ,QAAQ,KAAK,QAAQ,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM;AAAA,IACxE,gBAAgB,CAAC,QAAQ;AACrB,YAAM,IAAI,QAAQ,KAAK,QAAQ,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC;AAC1D,aAAO,OAAO,MAAM,WAAW,IAAI;AAAA,IACvC;AAAA,IACA,YAAY,CAAC,QAAQ;AACjB,YAAM,UAAU,eAAe,KAAK,QAAQ,WAAW,GAAG,CAAC,CAAC;AAC5D,aAAO,OAAO,KAAK,OAAO;AAC1B,aAAO;AAAA,IACX;AAAA,IACA,aAAa,CAAC,QAAQ,eAAe,KAAK,QAAQ,WAAW,GAAG,CAAC,CAAC;AAAA,IAClE,QAAQ,CAAC,KAAK,YAAY;AACtB,UAAI,CAAC,UAAU,YAAY,MAAO;AAClC,YAAM,OAAO,GAAG,iBAAiB,GAAG,IAAI,GAAG;AAC3C,UAAI,QAAQ,IAAI,IAAI,EAAG;AACvB,cAAQ,IAAI,IAAI;AAChB,aAAO,aAAa,EAAE,YAAY,KAAK,QAAQ,CAAC;AAAA,IACpD;AAAA,IACA,SAAS,CAAC,IAAI,aAAa;AACvB,aAAO,WAAW,EAAE;AACpB,aAAO,OAAO,SAAS,EAAE,KAAK;AAAA,IAClC;AAAA,IACA,UAAU,CAAC,OAAO,MAAM,EAAE,EAAE;AAAA,IAC5B,YAAY,CAAC,OAAO;AAEhB,iBAAW,OAAO,kBAAkB,QAAQ,EAAE,EAAG,QAAO,OAAO,KAAK,eAAe,KAAK,QAAQ,WAAW,GAAG,CAAC,CAAC,CAAC;AAAA,IACrH;AAAA,IACA,gBAAgB,CAAC,MAAM,MAAM,eAAe,CAAC;AAAA,IAC7C,iBAAiB,CAAC,OAAO,MAAM,gBAAgB,EAAE;AAAA,IACjD,aAAa,CAAC,WAAW,MAAM,QAAQ,KAAK,WAAW,CAAC;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,MAAM;AAAA,IACf,eAAe;AAAA,IACf,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM;AACX,UAAI,CAAC,WAAY,QAAO;AACxB,YAAM,IAAI;AACV,aAAO,EAAE,IAAI,YAAY,GAAI,OAAO,GAAG,SAAS,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAI,GAAI,OAAO,GAAG,UAAU,WAAW,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAG;AAAA,IACnJ;AAAA,IACA,KAAK,CAAC,OAAO;AACT,UAAI,CAAC,UAAU,YAAY,MAAO,QAAO;AACzC,YAAM,QAAQ,OAAO,QAAQ;AAE7B,YAAM,OAAO,IAAI,QAAQ,IAAI,QAAQ,EAAE,GAAG,OAAO,GAAI,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,IAAI,CAAC,GAAI,GAAI,GAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC,EAAG,IAAI;AACrI,aAAO,UAAU,EAAE,MAAM,QAAQ,YAAY,WAAW,GAAG,MAAM,UAAU,OAAO,WAAW,CAAC,EAAE,CAAC;AAAA,IACrG;AAAA,IACA,cAAc,CAAC,OAAO,YAAY,IAAI,EAAE;AAAA,IACxC,gBAAgB,CAAC,OAAO;AACpB,kBAAY,IAAI,EAAE;AAClB,UAAI,YAAY,aAAc,MAAK,IAAI,KAAK,SAAS,KAAK,UAAU,CAAC,GAAG,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACrG;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,WAAW,CAAC,aAAa;AACrB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM,UAAU,OAAO,QAAQ;AAAA,IAC1C;AAAA,IACA,YAAY,MAAM;AAAA,IAClB,OAAO,YAAY;AACf,UAAI,OAAQ;AACZ,gBAAU;AACV,gBAAU,KAAK,KAAK;AACpB,mBAAa,OAAO;AACpB,gBAAU;AACV,gBAAU;AACV,UAAI,oBAAoB,KAAK,cAAc,gBAAiB,MAAK,WAAW,iBAAiB,eAAe;AAC5G,YAAM,MAAM;AACZ,YAAM,WAAW;AACjB,YAAM,aAAa;AACnB,eAAS;AAAA,IACb;AAAA,IACA,QAAQ,MAAM;AAAA,EAClB;AACA,SAAO;AACX;AAGO,IAAM,kBAAkB,CAAC,UAAuC;AACnE,MAAI,IAAI;AACR,MAAI;AACJ,WAAS,QAAQ,GAAG,KAAK,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,UAAU,QAAQ,IAAI,SAAS;AACxF,UAAM,QAAQ,EAAE,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,EAAE,OAAO,SAAS,CAAC;AAClF,QAAI,CAAC,MAAO;AACZ,WAAO,MAAM,QAAQ;AACrB,QAAI,MAAM;AAAA,EACd;AACA,SAAO;AACX;;;ACtlCA,mBAAwE;AAiBxE,IAAM,KAAK,QAAQ,cAAc;AAiB1B,IAAM,QAAQ,EAAE,IAAI,WAAW,IAAI,WAAW,OAAO,WAAW,MAAM,WAAW,MAAM,UAAU;AACjG,IAAM,OAAO,EAAE,IAAI,WAAW,IAAI,WAAW,OAAO,WAAW,MAAM,WAAW,MAAM,UAAU;AAEvG,IAAM,SAAS,CAAC,MAAc,GAAG,CAAC,IAAI,MAAM,IAAI,UAAU,QAAQ;AAE3D,IAAM,gBAAgB,CAAC,EAAE,OAAO,SAAS,aAAa,CAAC,EAAE,MAAwF;AACpJ,QAAM,SAAS,GAAG,iBAAiB;AACnC,QAAM,OAAO,WAAW,UAAU,WAAY,WAAW,SAAS,YAAY,UAAU,WAAW;AACnG,QAAM,IAAa,EAAE,GAAI,OAAO,OAAO,OAAQ,QAAQ,WAAW,UAAU,WAAW,QAAQ,UAAU;AAEzG,QAAM,CAAC,EAAE,OAAO,QAAI,uBAAS,CAAC;AAC9B,8BAAU,MAAM,MAAM,UAAU,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;AACrE,8BAAU,MAAM,SAAS,UAAU,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;AAC1E,QAAM,KAAK,SAAS,KAAK,KAAK;AAC9B,QAAM,IAAI,MAAM,KAAK;AACrB,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,EAAE;AACzC,QAAM,SAAS,GAAG,SAAS,WAAW,EAAE,SAAS;AACjD,8BAAU,MAAM;AACZ,QAAI,CAAC,OAAQ,YAAW,EAAE;AAAA,EAC9B,GAAG,CAAC,MAAM,CAAC;AACX,MAAI,CAAC,KAAK,CAAC,GAAI,QAAO;AAEtB,QAAMC,QAAO,CAAC,UAAqB,QAAiC,CAAC,UAAM,aAAAC,eAAE,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,GAAG,MAAM,EAAE,GAAG,QAAQ;AAClJ,QAAM,QAAQ,CAAC,UAAqB,QAAiC,CAAC,MAAMD,MAAK,UAAU,EAAE,OAAO,EAAE,OAAO,UAAU,IAAI,GAAG,MAAM,CAAC;AACrI,QAAM,QAAQ,CAAC,iBAAwB,aAAAC,eAAE,GAAG,MAAM,EAAE,mBAAmB,UAAU,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,QAAQ;AACpJ,QAAM,MAAM,CAAC,OAAe,MAAoD,SAAqB,WAAW,cAC5G,aAAAA;AAAA,IACI,GAAG;AAAA,IACH;AAAA,MACI,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,oBAAoB,EAAE,SAAS;AAAA,MAC/B,OAAO;AAAA,QACH,QAAQ,SAAS,UAAU,KAAK;AAAA,QAChC,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS,WAAW,OAAO;AAAA,QAC3B,iBAAiB,SAAS,YAAY,EAAE,SAAS,SAAS,WAAW,EAAE,SAAS,SAAS,cAAc,EAAE,KAAK;AAAA,QAC9G,aAAa,SAAS,cAAc,IAAI;AAAA,QACxC,aAAa,EAAE;AAAA,MACnB;AAAA,IACJ;AAAA,IACAD,MAAK,OAAO;AAAA,MACR,OAAO,SAAS,aAAa,SAAS,WAAW,YAAY,SAAS,UAAU,EAAE,QAAQ,EAAE;AAAA,MAC5F,YAAY,SAAS,UAAU,QAAQ;AAAA,IAC3C,CAAC;AAAA,EACL;AACJ,QAAM,QAAQ,CAAC,OAAe,gBAC1B,aAAAC;AAAA,IACI,GAAG;AAAA,IACH,EAAE,SAAS,mBAAmB,UAAU,oBAAoB,OAAO,SAAS,IAAI,OAAO,EAAE,YAAY,QAAQ,SAAS,EAAE,EAAE;AAAA,IAC1HD,MAAK,QAAK,EAAE,UAAU,IAAI,OAAO,EAAE,MAAM,CAAC;AAAA,EAC9C;AACJ,QAAM,OAAO,CAAC,UAAuB,QAAiC,CAAC,UACnE,aAAAC;AAAA,IACI,GAAG;AAAA,IACH;AAAA,MACI,OAAO;AAAA,QACH,iBAAiB,EAAE;AAAA,QACnB,cAAc;AAAA,QACd,SAAS;AAAA,QACT,KAAK;AAAA,QACL,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc;AAAA,QACd,WAAW;AAAA,QACX,GAAG;AAAA,MACP;AAAA,IACJ;AAAA,IACA,GAAG;AAAA,EACP;AACJ,QAAM,QAAQ,CAAC,UAAuB,gBAClC,aAAAA;AAAA,IACI,GAAG;AAAA,IACH,EAAE,SAAS,MAAM,aAAa,MAAM,eAAe,QAAQ,gBAAgB,QAAQ;AAAA,QACnF,aAAAA;AAAA,MACI,GAAG;AAAA,MACH,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,mBAAmB,gBAAgB,WAAW,EAAE;AAAA,MACrF,KAAK,UAAU,EAAE,wBAAwB,GAAG,yBAAyB,GAAG,eAAe,GAAG,CAAC;AAAA,IAC/F;AAAA,EACJ;AACJ,QAAM,QAAQ,CAAC,aAAqB,QAAQ,SAAS,WAAgC,mBACjF,aAAAA,eAAE,GAAG,WAAW;AAAA,IACZ;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA,sBAAsB,EAAE;AAAA,IACxB,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB;AAAA,IACpB,OAAO,EAAE,WAAW,IAAI,aAAa,GAAG,aAAa,EAAE,MAAM,cAAc,IAAI,SAAS,IAAI,OAAO,EAAE,IAAI,mBAAmB,MAAM;AAAA,EACtI,CAAC;AAGL,QAAM,eAAe,CAAC,MAAmB;AACrC,UAAM,KAAK,EAAE;AACb,UAAM,OAAO;AACb,WAAO;AAAA,MACH;AAAA,YACI,aAAAA;AAAA,UACI,GAAG;AAAA,UACH,EAAE,KAAK,OAAO,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,EAAE,EAAE;AAAA,UAC5E,GAAI,EAAE,QAAQ,IACR,MAAM;AAAA,YAAK,EAAE,QAAQ,EAAE,MAAM;AAAA,YAAG,CAAC,GAAG,UAChC,aAAAA,eAAE,GAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,IAAI,QAAQ,GAAG,cAAc,GAAG,iBAAiB,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAAA,UAC9H,IACA,CAAC;AAAA,UACP,MAAM,SAAS,KAAK,KAAK;AAAA,QAC7B;AAAA,QACA,MAAM,GAAG,KAAK;AAAA,QACd,GAAG,OAAO,MAAM,GAAG,MAAM,EAAE,UAAU,GAAG,CAAC,IAAI;AAAA,QAC7C,GAAI,GAAG,SAAS,cACT,GAAG,SAAS,CAAC,GAAG;AAAA,UAAI,CAAC,MAAM,UACxB,aAAAA;AAAA,YACI,GAAG;AAAA,YACH,EAAE,KAAK,IAAI,CAAC,IAAI,OAAO,EAAE,eAAe,OAAO,KAAK,IAAI,YAAY,aAAa,EAAE;AAAA,YACnFD,MAAK,UAAK,EAAE,OAAO,EAAE,QAAQ,YAAY,MAAM,CAAC;AAAA,YAChDA,MAAK,MAAM,EAAE,MAAM,EAAE,CAAC;AAAA,UAC1B;AAAA,QACJ,IACA,CAAC;AAAA,QACP,GAAI,GAAG,SAAS,WACT,GAAG,UAAU,CAAC,GAAG;AAAA,UAAI,CAAC,GAAG,UACtB,aAAAC,eAAE,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC,IAAI,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,IAAI,SAAS,IAAI,KAAK,EAAE,EAAE,GAAGD,MAAK,EAAE,IAAI,GAAG,EAAE,KAAK,MAAM,EAAE,EAAE,IAAI,IAAI;AAAA,QACnJ,IACA,CAAC;AAAA,QACP,GAAG,SAAS,cACN,aAAAC;AAAA,UACI,GAAG;AAAA,UACH,EAAE,KAAK,SAAS,mBAAmB,cAAc,OAAO,EAAE,KAAK,EAAE,EAAE;AAAA,UACnE,GAAG,EAAE,MAAM;AAAA,YAAI,CAAC,aACZ,aAAAA;AAAA,cACI,GAAG;AAAA,cACH;AAAA,gBACI,KAAK,KAAK;AAAA,gBACV,SAAS,MAAM,KAAK,KAAK,KAAK,EAAE;AAAA,gBAChC,mBAAmB;AAAA,gBACnB,oBAAoB,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,gBAC/C,oBAAoB,EAAE,SAAS,EAAE,SAAS,KAAK,GAAG;AAAA,gBAClD,OAAO;AAAA,kBACH,WAAW;AAAA,kBACX,mBAAmB;AAAA,kBACnB,cAAc;AAAA,kBACd,aAAa;AAAA,kBACb,aAAa,EAAE,SAAS,KAAK,KAAK,EAAE,SAAS,EAAE;AAAA,kBAC/C,iBAAiB,EAAE,SAAS,KAAK,KAAK,EAAE,OAAO,EAAE;AAAA,kBACjD,eAAe;AAAA,kBACf,YAAY;AAAA,kBACZ,KAAK;AAAA,gBACT;AAAA,cACJ;AAAA,kBACA,aAAAA,eAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAGD,MAAK,KAAK,MAAM,EAAE,YAAY,MAAM,CAAC,GAAG,KAAK,OAAO,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,cAC9GA,MAAK,KAAK,OAAO,EAAE,YAAY,MAAM,CAAC;AAAA,YAC1C;AAAA,UACJ;AAAA,QACJ,IACA;AAAA,QACN,EAAE,QAAQA,MAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,QAC7D,IAAI,EAAE,OAAO,qBAAgB,GAAG,UAAU,YAAY,WAAW,KAAK,MAAM,EAAE,QAAS,GAAG,SAAS,WAAW,CAAC,EAAE,IAAK;AAAA,QACtH,EAAE,QAAQ,IAAI,QAAQ,SAAS,KAAK,MAAM,EAAE,IAAI,IAAI;AAAA,MACxD;AAAA,MACA,KAAK;AAAA,IACT;AAAA,EACJ;AAEA,MAAI,GAAI,QAAO,aAAa,EAAE;AAC9B,MAAI,CAAC,EAAG,QAAO;AAEf,MAAI,EAAE,SAAS,UAAU;AACrB,UAAM,UAAM,aAAAC;AAAA,MACR,GAAG;AAAA,MACH,EAAE,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,EAAE,EAAE;AAAA,MAChE,GAAI,EAAE,QAAQ,IACR,MAAM;AAAA,QAAK,EAAE,QAAQ,EAAE,MAAM;AAAA,QAAG,CAAC,GAAG,UAChC,aAAAA,eAAE,GAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,IAAI,QAAQ,GAAG,cAAc,GAAG,iBAAiB,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAAA,MAC5H,IACA,CAAC;AAAA,MACP,MAAM,SAAS,MAAM,OAAO,KAAK;AAAA,IACrC;AACA,UAAM,QAAQ,EAAE,QAAQD,MAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAC3E,QAAI,OAAoB,CAAC;AAEzB,UAAM,UAAU,CAAC,cACb,aAAAC;AAAA,MACI,GAAG;AAAA,MACH,EAAE,OAAO,EAAE,WAAW,IAAI,GAAG,uBAAuB,EAAE,KAAK,EAAE,GAAG,mBAAmB,aAAa;AAAA,MAChG,GAAG,MAAM;AAAA,QAAI,CAAC,UACV,aAAAA;AAAA,UACI,GAAG;AAAA,UACH;AAAA,YACI,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,mBAAmB;AAAA,YACnB,oBAAoB,EAAE,SAAS,EAAE,GAAG;AAAA,YACpC,OAAO;AAAA,cACH,WAAW;AAAA,cACX,mBAAmB;AAAA,cACnB,cAAc;AAAA,cACd,aAAa;AAAA,cACb,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE;AAAA,cACjC,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE;AAAA,cACnC,gBAAgB;AAAA,YACpB;AAAA,UACJ;AAAA,UACAD,MAAK,EAAE,OAAO,EAAE,YAAY,MAAM,CAAC;AAAA,QACvC;AAAA,MACJ;AAAA,IACJ;AACJ,QAAI,EAAE,WAAW;AACb,aAAO;AAAA,QACH,MAAM,EAAE,KAAK,YAAY,sBAAsB;AAAA,QAC/C,QAAQ,EAAE,KAAK,QAAQ,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,OAAO,IAAI,EAAE,WAAW,EAAE,IAAI,OAAO,MAAM,MAAM,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;AAAA,QAC/H,IAAI,YAAY,WAAW,MAAM,OAAO,MAAM,CAAC,EAAE,MAAM;AAAA,QACvD,IAAI,4BAA4B,SAAS,MAAM,OAAO,KAAK;AAAA,MAC/D;AAAA,aACK,EAAE,WAAW,cAAc,EAAE,UAAU;AAC5C,YAAM,IAAI,EAAE;AACZ,YAAM,QAAQ,EAAE,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;AAC7D,aAAO;AAAA,QACH,QAAQ,MAAM,aAAa,KAAK,EAAE,IAAI;AAAA,QACtC,MAAM,EAAE,QAAQ;AAAA,QAChB,EAAE,QAAQ,SACJ,QAAQ,EAAE,QAAQ,IAAI,CAAC,GAAG,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,WAAW,GAAG,OAAO,MAAM,MAAM,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC,IACxH,MAAM,0BAA0B,EAAE,UAAU,IAAI,MAAM,OAAO,MAAM;AAAA,QACzE,IAAI,YAAY,WAAW,MAAM,OAAO,IAAI;AAAA,QAC5C,IAAI,4BAA4B,SAAS,MAAM,OAAO,KAAK;AAAA,MAC/D;AAAA,IACJ,WAAW,EAAE,WAAW,WAAW,EAAE,OAAO;AACxC,YAAM,IAAI,EAAE;AACZ,YAAM,QAAQ,EAAE,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;AAC7D,YAAM,SACF,EAAE,SAAS,cAAc,EAAE,UACrB,EAAE,QACE,GAAG,MAAM,WAAW,EAAE,MAAM,QAAQ,EAAE,OAAO,GAAG,EAAE,MAAM,QAAQ,CAAC,eAAe,MAAM,EAAE,MAAM,QAAQ,EAAE,MAAM,QAAQ,CAAC,GAAG,EAAE,SAAS,QAAQ,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,KACpK,GAAG,EAAE,OAAO,QAAQ,EAAE,SAAS,QAAQ,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,KAClE,EAAE,SAAS,WAAW,EAAE,SACtB,mBAAmB,OAAO,EAAE,MAAM,CAAC,uBACnC,EAAE,SAAS,eAAe,EAAE,WAC1B,EAAE,WACF;AACd,aAAO;AAAA,QACH,QAAQ,MAAM,aAAa,KAAK,EAAE,IAAI;AAAA,QACtC,MAAM,EAAE,QAAQ;AAAA,QAChB,aAAS,aAAAC,eAAE,GAAG,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,IAAI,SAAS,GAAG,EAAE,GAAGD,MAAK,QAAQ,EAAE,YAAY,MAAM,CAAC,CAAC,IAAI;AAAA,QAClI,EAAE,SAAS,YAAY,MAAM,2BAA2B,IAAI;AAAA,QAC5D,IAAI,EAAE,OAAO,qBAAgB,YAAY,CAAC,GAAG,WAAW,MAAM,MAAM,OAAO,OAAO,OAAO,GAAG,EAAE,IAAI;AAAA,QAClG,IAAI,kCAAkC,SAAS,MAAM,OAAO,SAAS,EAAE,IAAI;AAAA,MAC/E;AAAA,IACJ;AACI,aAAO;AAAA,QACH,MAAM,EAAE,KAAK,QAAQ,KAAK;AAAA,QAC1B,EAAE,KAAK,QAAQ,OAAO,MAAM,EAAE,KAAK,QAAQ,MAAM,EAAE,UAAU,GAAG,CAAC,IAAI;AAAA,QACrE,EAAE,QAAQ,IAAI,MAAM,0CAA0C,IAAI;AAAA,QAClE,IAAI,EAAE,OAAO,qBAAgB,EAAE,KAAK,QAAQ,QAAQ,UAAU,MAAM,MAAM,OAAO,QAAQ,OAAO,GAAG,EAAE,IAAI;AAAA,QACzG,IAAI,gBAAgB,aAAa,MAAM,OAAO,OAAO,EAAE,IAAI;AAAA,MAC/D;AACJ,WAAO,MAAM,CAAC,KAAK,GAAG,MAAM,KAAK,GAAG,MAAM,OAAO,KAAK;AAAA,EAC1D;AAEA,MAAI,EAAE,SAAS;AACX,WAAO;AAAA,MACH;AAAA,YACI,aAAAC;AAAA,UACI,GAAG;AAAA,UACH,EAAE,OAAO,EAAE,eAAe,OAAO,YAAY,SAAS,EAAE;AAAA,UACxD,EAAE,QAAQ,IAAI,MAAM,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI;AAAA,UAC3D,MAAM,kBAAkB,MAAM,WAAW,OAAO;AAAA,QACpD;AAAA,QACA,MAAM,EAAE,KAAK,KAAK;AAAA,QAClB,EAAE,KAAK,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,UAAU,GAAG,CAAC,IAAI;AAAA,QACrD,IAAI,EAAE,KAAK,WAAW,EAAE,OAAO,SAAS,SAAS,WAAW,MAAM,WAAW,IAAI;AAAA,MACrF;AAAA,MACA,MAAM,WAAW;AAAA,IACrB;AAEJ,MAAI,EAAE,SAAS,aAAa;AACxB,UAAM,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE;AAC3C,eAAO,aAAAA;AAAA,MACH,GAAG;AAAA,MACH,EAAE,eAAe,YAAY,OAAO,EAAE,UAAU,YAAY,MAAM,IAAI,OAAO,IAAI,QAAQ,GAAG,EAAE;AAAA,MAC9F,KAAK;AAAA,YACD,aAAAA;AAAA,UACI,GAAG;AAAA,UACH,EAAE,KAAK,KAAK,OAAO,EAAE,eAAe,OAAO,YAAY,SAAS,EAAE;AAAA,UAClE,MAAM,EAAE,KAAK,IAAI;AAAA,UACjB,MAAM,sBAAsB,MAAM,WAAW,OAAO;AAAA,QACxD;AAAA,QACA,MAAM,GAAG,IAAI,OAAO,EAAE,MAAM,MAAM,OAAO;AAAA,QACzC,GAAG,EAAE,MAAM;AAAA,UAAI,CAAC,EAAE,MAAM,MAAM,EAAE,UAC5B,aAAAA;AAAA,YACI,GAAG;AAAA,YACH;AAAA,cACI,KAAK,KAAK;AAAA,cACV,UAAU,KAAK,CAAC,CAAC,KAAK;AAAA,cACtB,SAAS,MAAM,MAAM,WAAW,MAAM,KAAK,EAAE;AAAA,cAC7C,mBAAmB;AAAA,cACnB,oBAAoB,EAAE,SAAS,EAAE;AAAA,cACjC,OAAO,EAAE,eAAe,OAAO,KAAK,IAAI,YAAY,cAAc,iBAAiB,EAAE;AAAA,YACzF;AAAA,gBACA,aAAAA;AAAA,cACI,GAAG;AAAA,cACH;AAAA,gBACI,OAAO;AAAA,kBACH,OAAO;AAAA,kBACP,QAAQ;AAAA,kBACR,cAAc;AAAA,kBACd,aAAa;AAAA,kBACb,aAAa,IAAI,EAAE,SAAS,EAAE;AAAA,kBAC9B,iBAAiB,IAAI,EAAE,SAAS;AAAA,kBAChC,YAAY;AAAA,kBACZ,gBAAgB;AAAA,gBACpB;AAAA,cACJ;AAAA,cACA,IAAID,MAAK,UAAK,EAAE,OAAO,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,YACrD;AAAA,gBACA,aAAAC;AAAA,cACI,GAAG;AAAA,cACH,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;AAAA,cACrBD,MAAK,KAAK,OAAO,EAAE,YAAY,OAAO,OAAO,IAAI,EAAE,QAAQ,EAAE,IAAI,oBAAoB,IAAI,iBAAiB,OAAO,CAAC;AAAA,cAClH,KAAK,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,YACnC;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ;AAEA,QAAM,IAAI,EAAE;AACZ,MAAI,EAAE,UAAU;AACZ,eAAO,aAAAC;AAAA,MACH,GAAG;AAAA,MACH,EAAE,eAAe,YAAY,OAAO,EAAE,UAAU,YAAY,MAAM,IAAI,OAAO,IAAI,KAAK,GAAG,EAAE;AAAA,MAC3F,KAAK;AAAA,YACD,aAAAA;AAAA,UACI,GAAG;AAAA,UACH,EAAE,KAAK,KAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,EAAE,EAAE;AAAA,cAC1E,aAAAA,eAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAGD,MAAK,EAAE,OAAO,EAAE,YAAY,MAAM,CAAC,GAAG,EAAE,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI;AAAA,UACtG,MAAM,WAAW,MAAM,QAAQ,OAAO;AAAA,QAC1C;AAAA,QACA,EAAE,SAAS,IAAI,EAAE,QAAQ,WAAW,MAAM,QAAQ,KAAK,IAAI;AAAA,MAC/D,CAAC;AAAA,IACL;AACJ,SAAO;AAAA,IACH;AAAA,UACI,aAAAC,eAAE,GAAG,MAAM,EAAE,KAAK,KAAK,OAAO,EAAE,eAAe,MAAM,EAAE,GAAG,MAAM,WAAW,MAAM,QAAQ,OAAO,CAAC;AAAA,MACjG,MAAM,EAAE,KAAK;AAAA,MACb,EAAE,OAAO,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,IAAI;AAAA,MAC3C,EAAE,SAAS,IAAI,EAAE,QAAQ,WAAW,MAAM,QAAQ,KAAK,IAAI;AAAA,IAC/D;AAAA,IACA,MAAM,QAAQ;AAAA,EAClB;AACJ;;;AC/VA,IAAMC,MAAK,QAAQ,cAAc;AAEjC,IAAI,qBAA8B;AAClC,IAAI;AACA,uBAAqB,QAAQ,2CAA2C;AAC5E,QAAQ;AACJ,uBAAqB;AACzB;AACA,IAAI,aAAgC;AACpC,IAAI;AACA,eAAa,QAAQ,aAAa;AACtC,QAAQ;AACJ,eAAa;AACjB;AACA,IAAI,kBAA0C;AAC9C,IAAI;AACA,oBAAkB,QAAQ,kBAAkB;AAChD,QAAQ;AACJ,oBAAkB;AACtB;AACA,IAAI,mBAA4C;AAChD,IAAI;AACA,qBAAmB,QAAQ,mBAAmB;AAClD,QAAQ;AACJ,qBAAmB;AACvB;AAKA,IAAI,kBAA0C;AAC9C,IAAI;AACA,oBAAkB,QAAQ,mBAAmB;AACjD,QAAQ;AACJ,oBAAkB;AACtB;AACA,IAAI,WAA4B;AAChC,IAAI;AACA,aAAW,QAAQ,wBAAwB;AAC/C,QAAQ;AACJ,aAAW;AACf;AACA,IAAI,oBAA8C;AAClD,IAAI;AACA,sBAAoB,QAAQ,oBAAoB;AACpD,QAAQ;AACJ,sBAAoB;AACxB;AACA,IAAI,gBAA6D,CAAC;AAClE,IAAI;AACA,kBAAgB,QAAQ,gBAAgB;AAC5C,QAAQ;AACJ,kBAAgB,CAAC;AACrB;AAmBA,IAAM,SAAS,CAAC,MAAgD,GAAG,cAAc,SAAS,SAAS,QAAQ;AAG3G,IAAM,WAAW,MAAuB;AACpC,QAAM,IAAI;AACV,MAAI,CAAC,KAAK,OAAO,EAAE,0BAA0B,WAAY,QAAO;AAChE,QAAM,YAAY,cAAc,WAAW;AAC3C,SAAO;AAAA,IACH,YAAY,OAAO,QAAQ;AACvB,YAAM,MAAM,MAAM,EAAE,oBAAoB;AACxC,UAAI,IAAI,WAAW,IAAI,WAAW,UAAW,QAAO;AACpD,UAAI,IAAI,WAAW,YAAY,CAAC,IAAK,QAAO,IAAI,WAAW,WAAW,WAAW;AACjF,YAAM,QAAQ,MAAM,EAAE,wBAAwB;AAC9C,aAAO,MAAM,WAAW,MAAM,WAAW,YAAY,YAAY,MAAM,WAAW,WAAW,WAAW;AAAA,IAC5G;AAAA,IACA,OAAO,OAAO,cAAc;AAExB,UAAIA,IAAG,SAAS,OAAO,aAAa,EAAE;AAClC,cAAM,EAAE,4BAA4B,WAAW,EAAE,MAAM,WAAW,YAAY,EAAE,mBAAmB,QAAQ,EAAE,CAAC;AAClH,YAAM,KAAK,aAAa,UAAU,YAAY,OAAO,KAAK,aAAa,UAAU,WAAW;AAC5F,YAAM,IAAI,MAAM,EAAE,sBAAsB,KAAK,EAAE,WAAW,GAAG,IAAI,MAAS;AAC1E,aAAO,OAAO,GAAG,SAAS,YAAY,EAAE,OAAO,EAAE,OAAO;AAAA,IAC5D;AAAA,IACA,QAAQ,CAAC,aAAa;AAClB,YAAM,MAAM,EAAE,wCAAwC,CAAC,MAAM,SAAS,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACtF,aAAO,MAAM,IAAI,OAAO;AAAA,IAC5B;AAAA,IACA,UAAU,YAAY,OAAO,MAAM,EAAE,mCAAmC,CAAC;AAAA,EAC7E;AACJ;AAGA,IAAM,eAAe,MAA8B;AAC/C,QAAM,IAAI;AACV,QAAM,IAAK,GAAG,WAAW;AACzB,SAAO,KAAK,OAAO,EAAE,YAAY,cAAc,OAAO,EAAE,YAAY,cAAc,OAAO,EAAE,eAAe,aAAc,IAAwB;AACpJ;AAEA,IAAM,eAAuC,EAAE,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK;AAE9F,IAAM,OAAO,CAAC,GAAY,MAAM,OAAQ,OAAO,MAAM,YAAY,EAAE,KAAK,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI;AAGlI,IAAM,cAAc,MAAkB;AACzC,QAAM,IAAIA,IAAG;AACb,MAAI;AACJ,MAAI;AACA,aAAS,KAAK,kBAAkB,aAAa,EAAE,CAAC,GAAG,aAAa,EAAE;AAAA,EACtE,QAAQ;AACJ,aAAS;AAAA,EACb;AACA,MAAI,CAAC,QAAQ;AACT,QAAI;AACA,eAAS,KAAK,KAAK,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE;AAAA,IACpE,QAAQ;AACJ,eAAS;AAAA,IACb;AAAA,EACJ;AACA,QAAM,MAAkB;AAAA,IACpB,UAAU,EAAE;AAAA,IACZ,YAAY,KAAK,iBAAiB,wBAAwB;AAAA,IAC1D,OAAO,KAAK,iBAAiB,kBAAkB;AAAA,IAC/C,WAAW,KAAK,YAAY,SAAS,KAAK,KAAK,EAAE,OAAO;AAAA,IACxD,aAAa,KAAK,YAAY,SAAS,KAAK,KAAK,EAAE,WAAW,KAAK;AAAA,IACnE,aAAa,YAAY,aAAa,aAAa,WAAW,UAAU,IAAI,YAAe,EAAE,QAAQ,WAAW;AAAA,IAChH;AAAA,EACJ;AACA,aAAW,KAAK,OAAO,KAAK,GAAG,EAA2B,KAAI,IAAI,CAAC,MAAM,OAAW,QAAO,IAAI,CAAC;AAChG,SAAO;AACX;AAOA,IAAM,eAAe,MAA8B;AAC/C,QAAM,UAAU,UAAU;AAC1B,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,WAAW;AACf,MAAI;AACA,IAAAA,IAAG,SAAS,YAAY,oBAAoB,MAAO,WAAW,IAAK;AACnE,IAAAA,IAAG,SAAS,YAAY,mBAAmB,MAAO,WAAW,IAAK;AAClE,IAAAA,IAAG,SAAS,YAAY,mBAAmB,MAAO,WAAW,KAAM;AAAA,EACvE,QAAQ;AAEJ,WAAO;AAAA,EACX;AACA,SAAO;AAAA,IACH,SAAS,OAAO,UAAU;AACtB,YAAM,IAAIA,IAAG,WAAW,IAAI,QAAQ;AACpC,UAAI,CAAC,GAAG,MAAO,QAAO;AACtB,YAAM,IAAI,KAAK,MAAM,KAAK;AAC1B,YAAMC,KAAI,KAAK,MAAO,EAAE,SAAS,EAAE,QAAS,KAAK;AACjD,YAAM,MAAM,MAAM,QAAQ,EAAE,QAAQ,OAAO,SAAS,KAAK,QAAQ,UAAU,OAAO,GAAG,QAAQA,GAAE,CAAC;AAChG,aAAO,MAAM,EAAE,KAAK,IAAI,QAAQ,4BAA4B,EAAE,GAAG,GAAG,GAAAA,GAAE,IAAI;AAAA,IAC9E;AAAA,IACA,cAAc,MAAM;AAAA,IACpB,OAAO;AAAA,EACX;AACJ;AAGA,IAAM,cAAc,MAAiC;AACjD,QAAM,IAAI;AACV,MAAI,CAAC,GAAG,cAAe,QAAO;AAC9B,SAAO;AAAA,IACH,SAAS,YAAY;AACjB,UAAI,EAAE,oBAAoB,CAAE,MAAM,EAAE,iBAAiB,EAAI,QAAO;AAChE,YAAM,EAAE,cAAe;AACvB,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;AAGO,IAAM,aAAa,CAAC,YAAkD,CAAC,OAAmB;AAAA,EAC7F,SAAS,UAAU,YAAY,SAAY,UAAU,UAAU,aAAa;AAAA,EAC5E,QAAQ,CAAC,KAAK,SAAS,MAAM,KAAK,IAAI;AAAA,EACtC,UAAUD,IAAG;AAAA,EACb,YAAc,WAA+C,cAAc;AAAA,EAC3E,SAAS;AAAA,EACT,OAAO,KAAK,iBAAiB,eAAe,GAAG;AAAA,EAC/C,QAAQ,MAAM;AACV,UAAM,IAAIA,IAAG,WAAW,IAAI,QAAQ;AACpC,WAAO,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI;AAAA,EAC7C;AAAA,EACA,YAAY,MAAMA,IAAG,QAAQ,cAAc;AAAA,EAC3C,SAAS,CAAC,QAAQ,KAAKA,IAAG,QAAQ,QAAQ,GAAG,EAAE,MAAM,MAAM,MAAS;AAAA,EACpE,MAAM,SAAS;AAAA,EACf,aAAa,YAAY;AAAA,EACzB,UAAU,aAAa;AAC3B;AAGO,IAAM,kBAAkB,OAAO;AAAA,EAClC,cAAc,CAAC,CAAC,aAAa;AAAA,EAC7B,YAAY,CAAC,CAAC;AAAA,EACd,iBAAiB,CAAC,CAAC;AAAA,EACnB,kBAAkB,CAAC,CAAC;AAAA,EACpB,mBAAmB,CAAC,CAAC;AAAA,EACrB,iBAAiB,CAAC,CAAC,iBAAiB;AAAA,EACpC,UAAU,CAAC,CAAC,UAAU;AAC1B;;;ACvPA,IAAAE,gBAA6F;AAyC7F,IAAMC,MAAK,QAAQ,cAAc;AAajC,IAAM,aAAa,CAAC,aAA+B,CAAC,MAAe;AAC/D,QAAM,SAASA,IAAG,iBAAiB;AACnC,QAAM,OAAO,WAAW,UAAU,WAAY,WAAW,SAAS,YAAY,UAAU,WAAW;AACnG,SAAO,EAAE,GAAI,OAAO,OAAO,OAAQ,QAAQ,WAAW,UAAU,WAAW,QAAQ,UAAU;AACjG;AAGA,IAAM,MAAM,CAAC,MAAe;AACxB,QAAMC,QAAO,CAAC,UAAqB,QAAe,CAAC,UAAM,cAAAC,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,GAAG,MAAM,EAAE,GAAG,QAAQ;AAChI,QAAM,QAAQ,CAAC,UAAqB,QAAe,CAAC,MAAMC,MAAK,UAAU,EAAE,OAAO,EAAE,OAAO,UAAU,IAAI,GAAG,MAAM,CAAC;AACnH,QAAM,QAAQ,CAAC,iBAAwB,cAAAC,eAAEF,IAAG,MAAM,EAAE,mBAAmB,UAAU,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,OAAO,MAAM,EAAE,EAAE,GAAG,QAAQ;AAC7J,QAAM,MAAM,CAAC,OAAe,MAA+B,SAAqB,WAAW,OAAO,QAAe,CAAC,UAC9G,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH;AAAA,MACI,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,oBAAoB,EAAE,SAAS;AAAA,MAC/B,OAAO;AAAA,QACH,QAAQ;AAAA,QACR,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS,WAAW,OAAO;AAAA,QAC3B,iBAAiB,SAAS,YAAY,EAAE,SAAS,EAAE;AAAA,QACnD,aAAa,SAAS,cAAc,IAAI;AAAA,QACxC,aAAa,EAAE;AAAA,QACf,GAAG;AAAA,MACP;AAAA,IACJ;AAAA,IACAC,MAAK,OAAO,EAAE,OAAO,SAAS,YAAY,YAAY,EAAE,IAAI,YAAY,MAAM,CAAC;AAAA,EACnF;AACJ,QAAM,SAAS,CAAC,OAAe,gBAC3B,cAAAC,eAAEF,IAAG,WAAW,EAAE,SAAS,mBAAmB,UAAU,oBAAoB,OAAO,SAAS,IAAI,OAAO,EAAE,SAAS,EAAE,EAAE,GAAGC,MAAK,QAAK,EAAE,UAAU,IAAI,OAAO,EAAE,MAAM,CAAC,CAAC;AACxK,QAAM,QAAQ,CAAC,UACX,cAAAC,eAAEF,IAAG,WAAW;AAAA,IACZ,OAAO,EAAE;AAAA,IACT,cAAc,EAAE;AAAA,IAChB,aAAa,EAAE;AAAA,IACf,sBAAsB,EAAE;AAAA,IACxB,WAAW,CAAC,CAAC,EAAE;AAAA,IACf,WAAW,EAAE,OAAO;AAAA,IACpB,oBAAoB,EAAE;AAAA,IACtB,GAAI,EAAE,QAAQ,EAAE,cAAc,iBAAiB,gBAAgB,QAAQ,cAAc,SAAS,iBAAiB,eAAe,IAAI,CAAC;AAAA,IACnI,GAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,eAAe,OAAO,IAAI,CAAC;AAAA,IAC3E,OAAO;AAAA,MACH,WAAW,EAAE,YAAY,KAAK;AAAA,MAC9B,aAAa;AAAA,MACb,aAAa,EAAE;AAAA,MACf,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,MACjB,OAAO,EAAE;AAAA,MACT,iBAAiB,EAAE;AAAA,MACnB,mBAAmB,EAAE,YAAY,QAAQ;AAAA,MACzC,GAAG,EAAE;AAAA,IACT;AAAA,EACJ,CAAC;AACL,QAAM,OAAO,CAAC,OAAe,IAAa,SAAqB,MAAM,cACjE,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH;AAAA,MACI;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,oBAAoB,EAAE,UAAU,GAAG;AAAA,MACnC,OAAO,EAAE,mBAAmB,IAAI,QAAQ,IAAI,cAAc,IAAI,gBAAgB,UAAU,aAAa,GAAG,aAAa,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,KAAK,EAAE,OAAO,EAAE,GAAG;AAAA,IACrL;AAAA,IACAC,MAAK,OAAO,EAAE,UAAU,IAAI,YAAY,OAAO,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC;AAAA,EAChF;AAEJ,QAAM,OAAO,CAAC,SAAiB,SAAqB,iBAChD,cAAAC;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,SAAS,MAAM,eAAe,SAAS,mBAAmB,aAAa,gBAAgB,QAAQ;AAAA,QACjG,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,UAAUA,IAAG,SAAS,OAAO,QAAQ,YAAY,QAAW,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,EAAE;AAAA,UACxG,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,mBAAmB,IAAI,YAAY,IAAI,eAAe,IAAI,mBAAmB,GAAG,mBAAmB,EAAE,KAAK,EAAE;AAAA,QACnK,MAAM,OAAO;AAAA,QACb,OAAO,SAAS,OAAO;AAAA,MAC3B;AAAA,MACA,GAAG;AAAA,IACP;AAAA,EACJ;AACJ,SAAO,EAAE,MAAAC,OAAM,OAAO,OAAO,KAAK,QAAQ,OAAO,MAAM,KAAK;AAChE;AAEA,IAAM,UAAU,CAAC,QAAgB;AAC7B,QAAM,IAAI,IAAI,KAAK,GAAG,EAAE,QAAQ;AAChC,MAAI,OAAO,MAAM,CAAC,EAAG,QAAO;AAC5B,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI;AACxC,MAAI,IAAI,GAAI,QAAO;AACnB,MAAI,IAAI,KAAM,QAAO,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAC1C,MAAI,IAAI,MAAO,QAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;AAC7C,SAAO,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC;AACnC;AAGA,IAAM,SAAS,MAAM;AACjB,MAAI,OAAO;AACX,QAAM,YAAY,oBAAI,IAA0B;AAChD,QAAM,MAAM,CAAC,MAAe;AACxB,WAAO;AACP,cAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,EACjC;AACA,QAAM,UAAU,MAAM;AAClB,UAAM,CAAC,GAAG,IAAI,QAAI,wBAAS,IAAI;AAC/B,iCAAU,MAAM;AACZ,gBAAU,IAAI,IAAI;AAClB,WAAK,IAAI;AACT,aAAO,MAAM;AACT,kBAAU,OAAO,IAAI;AAAA,MACzB;AAAA,IACJ,GAAG,CAAC,CAAC;AACL,WAAO;AAAA,EACX;AACA,SAAO,EAAE,KAAK,KAAK,MAAM,MAAM,QAAQ;AAC3C;AAIA,IAAM,aAAa,CAAC,MAAiC,MAAM,QAAQ,CAAC,IAAI,EAAE,SAAS,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,KAAK;AAEhI,IAAM,cAAc,CAAC,EAAE,QAAQ,KAAK,GAAG,OAAO,MAA8E;AACxH,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,CAAC;AAClC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAuC,CAAC,CAAC;AACvE,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,cAAU,sBAAO,KAAK,IAAI,CAAC;AACjC,QAAM,eAAW,sBAAO,KAAK;AAC7B,QAAM,IAAoB,OAAO,UAAU,IAAI;AAC/C,QAAM,OAAO,SAAS,OAAO,UAAU,SAAS;AAChD,QAAM,QAAQ,QAAQ,EAAE,GAAG;AAE3B,+BAAU,MAAM;AACZ,QAAI,KAAK,OAAO,EAAE,EAAE,MAAM,MAAM,MAAS;AAAA,EAC7C,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC;AACnB,+BAAU,MAAM;AACZ,QAAI,CAAC,KAAM;AACX,UAAM,IAAI,WAAW,QAAQ,IAAI;AACjC,WAAO,MAAM,aAAa,CAAC;AAAA,EAC/B,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,QAAM,SAAS,CAAC,WAAoB,MAAM,YAAY;AAClD,QAAI,SAAS,QAAS;AACtB,aAAS,UAAU;AACnB,QAAI,QAAQ,OAAO,IAAI,EAAE,SAAS,KAAK,WAAW,SAAS,KAAK,OAAO,KAAK,IAAI,IAAI,QAAQ,WAAW,GAAI,EAAE,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EACzI;AACA,QAAM,UAAU,MAAM;AAElB,QAAI,OAAO,OAAO,OAAO,EAAE,KAAK,UAAU,EAAG,QAAO,KAAK;AACzD,WAAO;AAAA,EACX;AACA,QAAM,OAAO,MAAM;AACf,QAAI,EAAE,YAAY,CAAC,WAAW,KAAK,EAAG,QAAO,SAAS,8BAA8B;AACpF,aAAS,EAAE;AACX,QAAI,CAAC,KAAM,QAAO,QAAQ,OAAO,CAAC;AAClC,WAAO,IAAI;AACX,YAAQ,IAAI;AAAA,EAChB;AACA,QAAM,OAAO,CAAC,MAAoB;AAC9B,eAAW,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE;AACxC,aAAS,EAAE;AAAA,EACf;AAEA,MAAI;AACJ,MAAI,EAAE,SAAS,SAAS,EAAE,SAAS,UAAU;AACzC,UAAM,QAAQ,EAAE,SAAS,QAAQ,KAAK,KAAK,IAAI,KAAK,IAAI,EAAE,SAAS,GAAG,CAAC,GAAG,EAAE;AAC5E,UAAM,QAAQ,EAAE,SAAS,QAAQ,IAAI;AACrC,gBAAQ,cAAAC;AAAA,MACJF,IAAG;AAAA,MACH,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;AAAA,UACpB,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,OAAO,EAAE,eAAe,OAAO,UAAU,QAAQ,KAAK,EAAE,GAAG,mBAAmB,cAAc,oBAAoB,EAAE,MAAM;AAAA,QAC1H,GAAG,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM;AACvC,gBAAM,IAAI,IAAI;AACd,gBAAM,KAAK,UAAU;AACrB,qBAAO,cAAAE;AAAA,YACHF,IAAG;AAAA,YACH;AAAA,cACI,KAAK;AAAA,cACL,SAAS,MAAM,KAAK,CAAC;AAAA,cACrB,mBAAmB;AAAA,cACnB,oBAAoB,EAAE,SAAS,GAAG;AAAA,cAClC,oBAAoB,GAAG,CAAC,OAAO,QAAQ,IAAI,KAAK;AAAA,cAChD,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,GAAG,YAAY,UAAU,gBAAgB,UAAU,aAAa,GAAG,aAAa,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,KAAK,EAAE,SAAS,EAAE,GAAG;AAAA,YAChM;AAAA,YACA,EAAE,KAAK,OAAO,CAAC,GAAG,EAAE,OAAO,KAAK,YAAY,EAAE,IAAI,YAAY,MAAM,CAAC;AAAA,UACzE;AAAA,QACJ,CAAC;AAAA,MACL;AAAA,MACA,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,YACxB,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,eAAe,OAAO,gBAAgB,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,QAAQ,eAAe,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,QAAQ,gBAAgB,GAAG,CAAC,IACrM;AAAA,IACV;AAAA,EACJ,WAAW,EAAE,SAAS,YAAY,EAAE,SAAS,SAAS;AAClD,UAAM,QAAQ,EAAE,SAAS;AACzB,UAAM,SAAS,QAAU,SAAkC,CAAC,IAAK,CAAC;AAClE,gBAAQ,cAAAE;AAAA,MACJF,IAAG;AAAA,MACH,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;AAAA,MACpB,IAAI,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM;AAC5B,cAAM,KAAK,QAAQ,OAAO,SAAS,CAAC,IAAI,UAAU;AAClD,mBAAO,cAAAE;AAAA,UACHF,IAAG;AAAA,UACH;AAAA,YACI,KAAK;AAAA,YACL,SAAS,MAAM,KAAK,QAAS,KAAK,OAAO,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAK,CAAC;AAAA,YACrF,mBAAmB,QAAQ,aAAa;AAAA,YACxC,oBAAoB,EAAE,SAAS,GAAG;AAAA,YAClC,OAAO,EAAE,WAAW,IAAI,mBAAmB,IAAI,cAAc,IAAI,gBAAgB,UAAU,aAAa,GAAG,aAAa,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,KAAK,EAAE,OAAO,EAAE,GAAG;AAAA,UACxL;AAAA,UACA,EAAE,KAAK,GAAG,EAAE,YAAY,MAAM,CAAC;AAAA,QACnC;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ,MAAO,SAAQ,EAAE,MAAM,EAAE,OAAQ,SAAgC,IAAI,UAAU,MAAM,aAAa,EAAE,eAAe,oBAAoB,WAAW,KAAK,CAAC;AAExJ,QAAM,OAAO,OACP,CAAC,EAAE,KAAK,OAAO,UAAU,6BAA6B,EAAE,YAAY,OAAO,WAAW,UAAU,iBAAiB,GAAG,CAAC,CAAC,IACtH;AAAA,QACI,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,KAAK,OAAO,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,EAAE,EAAE;AAAA,MAC5E,GAAG,OAAO,UAAU,IAAI,CAAC,GAAG,UAAM,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,IAAI,QAAQ,GAAG,cAAc,GAAG,iBAAiB,KAAK,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AAAA,UAC9J,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;AAAA,MACjC,EAAE,OAAO,gBAAgB,OAAO;AAAA,IACpC;AAAA,QACA,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,KAAK,mBAAmB,UAAU,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,SAAK,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,YAAY,CAAC;AAAA,IAClO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,IAAI;AAAA,IACzC;AAAA,IACA,QAAQ,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,IAC3D,EAAE,IAAI,OAAO,SAAS,QAAQ,WAAW,IAAI;AAAA,EACjD;AAEN,aAAO,cAAAE;AAAA,IACHF,IAAG;AAAA,IACH,EAAE,SAAS,MAAM,aAAa,MAAM,eAAe,SAAS,gBAAgB,QAAQ;AAAA,QACpF,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,UAAUA,IAAG,SAAS,OAAO,QAAQ,YAAY,QAAW,OAAO,EAAE,MAAM,GAAG,iBAAiB,oBAAoB,gBAAgB,WAAW,EAAE;AAAA,UAClJ,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH;AAAA,UACI,0BAA0B;AAAA,UAC1B,oBAAoB,OAAO;AAAA,UAC3B,OAAO,EAAE,iBAAiB,EAAE,IAAI,qBAAqB,IAAI,sBAAsB,IAAI,SAAS,IAAI,eAAe,IAAI,KAAK,GAAG;AAAA,QAC/H;AAAA,QACA,GAAG;AAAA,MACP;AAAA,IACJ;AAAA,EACJ;AACJ;AAGO,IAAM,kBAAkB,CAAC,EAAE,QAAQ,WAAW,MAAiE;AAClH,QAAM,IAAI,WAAW,UAAU;AAC/B,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAmD,IAAI;AACnF,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAS,MAAM,OAAO,cAAc,CAAC;AAC3D,+BAAU,MAAM,OAAO,UAAU,MAAM,OAAO,OAAO,cAAc,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;AAEhF,+BAAU,MAAM;AACZ,QAAI,OAAO;AACX,UAAM,OAAO,IAAI,gBAAgB;AACjC,UAAM,QAAQ,WAAW,MAAM;AAC3B,WAAK,OAAO,MAAM,KAAK,MAAM;AACzB,cAAM,MAAM,OAAO,IAAI;AACvB,YAAI,QAAQ,CAAC,IAAK;AAClB,YAAI,OAAO,IAAI,KAAK,MAAM,EACrB,KAAK,CAAC,MAAM;AACT,gBAAM,IAAI,EAAE;AACZ,cAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,UAAU,OAAO,aAAa,EAAE,EAAE,EAAG;AACpE,oBAAU,EAAE,GAAG,IAAI,CAAC;AAAA,QACxB,CAAC,EACA,MAAM,MAAM,MAAS;AAAA,MAC9B,CAAC;AAAA,IACL,GAAG,GAAI;AACP,WAAO,MAAM;AACT,aAAO;AACP,mBAAa,KAAK;AAClB,WAAK,MAAM;AAAA,IACf;AAAA,EACJ,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,QAAM,WAAO,2BAAY,MAAM;AAC3B,cAAU,CAAC,QAAQ;AACf,UAAI,IAAK,QAAO,eAAe,IAAI,EAAE,EAAE;AACvC,aAAO;AAAA,IACX,CAAC;AAAA,EACL,GAAG,CAAC,MAAM,CAAC;AACX,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAO,cAAAE,eAAE,aAAa,EAAE,KAAK,OAAO,EAAE,IAAI,QAAQ,OAAO,GAAG,KAAK,OAAO,KAAK,GAAG,QAAQ,KAAK,CAAC;AAClG;AAIA,IAAM,eAAe,OAAO;AAGrB,IAAM,cAAc,OAAO,EAAE,MAAM,MAAM,aAAa,IAAI,IAAI,GAAG,OAAO,MAAM,aAAa,IAAI,KAAK,EAAE;AAO7G,IAAM,gBAAgB,CAAC,EAAE,QAAQ,GAAG,MAAM,MAA6D;AACnG,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAwB,KAAK;AACnD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAgC,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAA8B,CAAC,CAAC;AAC5D,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,SAAS;AAC5C,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,EAAE;AACzC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,EAAE;AACzC,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,EAAE;AACnC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,KAAK;AACtC,QAAM,QAAQ,MAAM,aAAa,IAAI,KAAK;AAC1C,QAAM,OAAO,OAAO,QAAQ;AAE5B,+BAAU,MAAM;AACZ,UAAM,MAAM,OAAO,IAAI;AACvB,QAAI,CAAC,IAAK,QAAO,SAAS,wCAAwC;AAClE,UAAM,OAAO,IAAI,gBAAgB;AACjC,QAAI,KAAK,EAAE,MAAM,MAAM,GAAG,KAAK,MAAM,EAChC,KAAK,CAAC,MAAM;AACT,eAAS,EAAE,KAAK;AAChB,gBAAU,EAAE,MAAM;AAClB,UAAI,EAAE,OAAO,UAAU,CAAC,EAAE,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,EAAG,UAAS,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,IAC7F,CAAC,EACA,MAAM,CAAC,MAAa,EAAE,SAAS,gBAAgB,SAAS,EAAE,OAAO,CAAC;AACvE,WAAO,MAAM,KAAK,MAAM;AAAA,EAC5B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,OAAO,CAAC,SAAuB;AACjC,UAAM,MAAM,OAAO,IAAI;AACvB,QAAI,CAAC,IAAK;AAEV,aAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,EAAE,OAAO,OAAO,EAAE,SAAS,EAAE,QAAQ,KAAK,GAAG,IAAI,CAAE,KAAK,IAAI;AAClI,QAAI,KAAK,KAAK,EAAE,EACX,KAAK,CAAC,MAAM,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,KAAK,EAAE,GAAG,GAAG,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI,CAAE,KAAK,IAAI,CAAC,EACzH,MAAM,CAAC,MAAa;AACjB,eAAS,EAAE,OAAO;AAClB,eAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,KAAK,OAAO,CAAE,KAAK,IAAI;AAAA,IAC5E,CAAC;AAAA,EACT;AAEA,QAAM,SAAS,MAAM;AACjB,UAAM,MAAM,OAAO,IAAI,EAAE,MAAM,KAAK,KAAK,GAAG,OAAO,MAAM,KAAK,EAAE,CAAC;AACjE,QAAI,CAAC,OAAO,QAAQ,KAAK,EAAE,SAAS,KAAK,QAAS;AAClD,eAAW,IAAI;AACf,aAAS,EAAE;AACX,QAAI,OAAO,EAAE,OAAO,QAAQ,KAAK,GAAG,MAAM,QAAQ,KAAK,KAAK,QAAW,MAAM,CAAC,EACzE,KAAK,CAAC,SAAS;AACZ,eAAS,CAAC,QAAQ,CAAC,MAAM,GAAI,OAAO,CAAC,CAAE,CAAC;AACxC,iBAAW,EAAE;AACb,iBAAW,EAAE;AACb,cAAQ,IAAI;AAAA,IAChB,CAAC,EACA,MAAM,CAAC,MAAa,SAAS,EAAE,OAAO,CAAC,EACvC,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACxC;AAEA,QAAM,WAAO,cAAAA;AAAA,IACTF,IAAG;AAAA,IACH,EAAE,OAAO,EAAE,eAAe,OAAO,KAAK,GAAG,mBAAmB,IAAI,YAAY,GAAG,EAAE;AAAA,IACjF,EAAE,KAAK,gBAAgB,QAAQ,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,IACzD,EAAE,KAAK,WAAW,QAAQ,OAAO,MAAM;AACnC,aAAO,KAAK;AACZ,cAAQ,KAAK;AAAA,IACjB,CAAC;AAAA,EACL;AAEA,QAAM,WAAO,cAAAE;AAAA,IACTF,IAAG;AAAA,IACH,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAuB,EAAE,SAAS,IAAI,KAAK,GAAG,EAAE;AAAA,IACtE,QAAQ,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,IAC3D,UAAU,QAAQ,CAAC,QAAQ,EAAE,MAAM,eAAU,IAAI;AAAA,IACjD,OAAO,WAAW,IAAI,EAAE,MAAM,+CAA+C,IAAI;AAAA,IACjF,IAAI,SAAS,CAAC,GAAG;AAAA,MAAI,CAAC,aAClB,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,KAAK,KAAK,IAAI,OAAO,EAAE,eAAe,OAAO,KAAK,IAAI,YAAY,cAAc,iBAAiB,GAAG,mBAAmB,GAAG,mBAAmB,EAAE,KAAK,EAAE;AAAA,YACxJ,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH;AAAA,YACI,SAAS,MAAM,KAAK,IAAI;AAAA,YACxB,mBAAmB;AAAA,YACnB,oBAAoB,EAAE,UAAU,KAAK,MAAM;AAAA,YAC3C,oBAAoB,GAAG,KAAK,QAAQ,0BAA0B,QAAQ,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,YACnG,OAAO,EAAE,OAAO,IAAI,WAAW,IAAI,cAAc,IAAI,YAAY,UAAU,gBAAgB,UAAU,aAAa,GAAG,aAAa,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK;AAAA,UACrK;AAAA,UACA,EAAE,KAAK,UAAK,EAAE,UAAU,IAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC;AAAA,UACpE,EAAE,KAAK,OAAO,KAAK,KAAK,GAAG,EAAE,YAAY,OAAO,UAAU,IAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC;AAAA,QACvG;AAAA,YACA,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,KAAK,OAAO,EAAE,YAAY,MAAM,CAAC,GAAG,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,IAAI,IAAI;AAAA,MAC7I;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,WAAO,cAAAE;AAAA,IACTF,IAAG;AAAA,IACH,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAuB,EAAE,SAAS,IAAI,KAAK,GAAG,GAAG,2BAA2B,UAAU;AAAA,IAC5G,OAAO,EAAE,KAAK,yCAAyC,EAAE,YAAY,MAAM,CAAC,IAAI;AAAA,IAChF,OAAO,SAAS,QAAI,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,eAAe,OAAO,UAAU,QAAQ,KAAK,EAAE,EAAE,GAAG,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,UAAU,EAAE,IAAI,MAAM,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI;AAAA,IACnL,EAAE,MAAM,EAAE,OAAO,SAAS,UAAU,YAAY,aAAa,eAAe,KAAK,IAAI,CAAC;AAAA,IACtF,EAAE,MAAM,EAAE,OAAO,SAAS,UAAU,YAAY,aAAa,sBAAsB,WAAW,KAAK,CAAC;AAAA,IACpG,GAAI,MAAM,QACJ,CAAC,IACD;AAAA,MACI,EAAE,MAAM,gEAAgE;AAAA,MACxE,EAAE,MAAM,EAAE,OAAO,MAAM,UAAU,SAAS,aAAa,wBAAwB,KAAK,IAAI,CAAC;AAAA,MACzF,EAAE,MAAM,EAAE,OAAO,OAAO,UAAU,UAAU,aAAa,yBAAyB,KAAK,KAAK,OAAO,KAAK,CAAC;AAAA,IAC7G;AAAA,IACN,QAAQ,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,IAC3D,EAAE,IAAI,UAAU,kBAAa,gBAAgB,WAAW,QAAQ,QAAQ,KAAK,EAAE,SAAS,KAAK,OAAO;AAAA,EACxG;AAEA,SAAO,EAAE,KAAK,OAAO,OAAO,CAAC,MAAM,QAAQ,QAAQ,OAAO,IAAI,CAAC;AACnE;AAEO,IAAM,mBAAmB,CAAC,EAAE,QAAQ,YAAY,UAAU,CAAC,EAAE,MAAkG;AAClK,QAAM,IAAI,WAAW,UAAU;AAC/B,QAAM,OAAO,aAAa,QAAQ;AAClC,SAAO,WAAO,cAAAE,eAAE,eAAe,EAAE,QAAQ,GAAG,OAAO,QAAQ,SAAS,WAAW,CAAC,IAAI;AACxF;AAIA,IAAM,eAAe;AACrB,IAAM,kBAAkB;AACxB,IAAM,eAAe;AACrB,IAAM,iBAAiB,KAAK;AAC5B,IAAM,QAAQ;AACd,IAAM,WAAgD,EAAE,SAAS,OAAO,MAAM,QAAQ,IAAI,YAAY,MAAM,OAAO;AAGnH,IAAI,UAAmB;AACvB,IAAM,gBAAgB,OAAO;AAC7B,IAAM,SAAS,CAAC,IAAa,WAAW;AACpC,YAAU;AACV,gBAAc,IAAI,IAAI;AAC1B;AAGO,IAAM,eAAe,OAAO;AAAA,EAC/B,MAAM,CAAC,SAAmB,OAAO,IAAI;AAAA,EACrC,OAAO,MAAM,cAAc,IAAI,KAAK;AAAA,EACpC,QAAQ,MAAO,cAAc,IAAI,IAAI,cAAc,IAAI,KAAK,IAAI,OAAO;AAC3E;AAmCA,IAAI,UAA8B;AAClC,IAAI;AACA,YAAU,QAAQ,cAAc;AACpC,QAAQ;AACJ,YAAU;AACd;AACA,IAAM,OAAO,MAAM;AACf,MAAI;AACA,SAAK,SAAS,oBAAoB,QAAQ,0BAA0B,OAAO,GAAG,MAAM,MAAM,MAAS;AAAA,EACvG,QAAQ;AAAA,EAER;AACJ;AAYA,IAAI,cAAsC;AAC1C,IAAI;AACA,gBAAc,QAAQ,mBAAmB;AAC7C,QAAQ;AACJ,gBAAc;AAClB;AACA,IAAM,cAAgD,EAAE,KAAK,cAAc,MAAM,cAAc,KAAK,aAAa,MAAM,cAAc,KAAK,YAAY;AAatJ,IAAM,SAAS,CAAC,OAA0B,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS;AAO/F,IAAI,MAAwB;AAC5B,IAAI;AACA,QAAM,QAAQ,kBAAkB;AACpC,QAAQ;AACJ,QAAM;AACV;AAEA,IAAM,QAAQ;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AACV;AACA,IAAM,WAA+C,EAAE,MAAM,aAAM,MAAM,UAAK,MAAM,KAAK,MAAM,UAAK,IAAI,UAAK,MAAM,UAAK,QAAQ,UAAK,OAAO,QAAK,MAAM,YAAK;AAC5J,IAAM,QAAQ,CAAC,MAA0B,OAAe,OAAO,OAAO;AAClE,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,MAAI,CAAC,OAAO,CAAC,IAAK,YAAO,cAAAA,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,UAAU,KAAK,MAAM,OAAO,IAAI,GAAG,YAAY,OAAO,GAAG,WAAW,UAAU,UAAU,KAAK,EAAE,GAAG,SAAS,IAAI,CAAC;AACtK,aAAO,cAAAE,eAAE,KAAK,EAAE,OAAO,MAAM,QAAQ,MAAM,SAAS,aAAa,MAAM,OAAO,OAAG,cAAAA,eAAE,IAAI,MAAM,EAAE,GAAG,MAAM,IAAI,GAAG,QAAQ,OAAO,aAAa,KAAK,eAAe,SAAS,gBAAgB,SAAS,MAAM,OAAO,CAAC,CAAC;AACpN;AAEA,IAAM,QAAQ,CAAC,KAAa,MAAe,kBAAkB,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,KAAK;AAExI,IAAM,WAAW,CAAC,OAAe,IAAY,IAAY,OAAO,WAC5D,cAAAA;AAAA,EACIF,IAAG;AAAA,EACH,EAAE,OAAO,EAAE,OAAO,MAAM,QAAQ,MAAM,cAAc,OAAO,GAAG,iBAAiB,IAAI,YAAY,UAAU,gBAAgB,SAAS,EAAE;AAAA,MACpI,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,IAAI,UAAU,KAAK,MAAM,OAAO,IAAI,GAAG,YAAY,MAAM,EAAE,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK,KAAK,YAAY,CAAC;AACrI;AAEJ,IAAM,KAAK;AAAA,EACP,OAAO,EAAE,IAAI,WAAW,SAAS,WAAW,KAAK,WAAW,SAAS,WAAW,IAAI,WAAW,OAAO,UAAU;AAAA,EAChH,MAAM,EAAE,IAAI,WAAW,SAAS,WAAW,KAAK,WAAW,SAAS,WAAW,IAAI,WAAW,OAAO,UAAU;AACnH;AACA,IAAM,WAAW,EAAE,aAAa,QAAQ,eAAe,MAAM,cAAc,GAAG,cAAc,EAAE,OAAO,GAAG,QAAQ,EAAE,GAAG,WAAW,EAAE;AAGlI,IAAM,UAAU,CAAC,QAAwB,GAA2B,MAAe,SAAkB;AACjG,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAA4B,IAAI;AAC5D,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAS,KAAK;AAC1C,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAwB,CAAC,CAAC;AACtD,QAAM,YAAQ,sBAAsB,IAAI;AACxC,QAAM,WAAW,QAAQ,SAAS;AAClC,QAAM,YAAQ,sBAAO,QAAQ;AAC7B,QAAM,UAAU;AAChB,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAASA,IAAG,SAAS,iBAAiB,QAAQ;AAC1E,+BAAU,MAAM;AACZ,UAAM,MAAMA,IAAG,SAAS,iBAAiB,UAAU,CAAC,OAAO,UAAU,OAAO,QAAQ,CAAC;AACrF,WAAO,MAAM,IAAI,OAAO;AAAA,EAC5B,GAAG,CAAC,CAAC;AAEL,QAAM,WAAO;AAAA,IACT,CAAC,MAAkB;AACf,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,MAAM,YAAY,MAAM;AACxB,cAAM,IAAI,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM,OAAO;AACtD,cAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAC/D,YAAI,MAAM,QAAQ;AACd,cAAI,EAAE,YAAY,MAAO,MAAK;AAC9B,cAAI,CAAC,MAAM,QAAS,WAAU,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC;AAAA,QACzD;AAAA,MACJ;AACA,YAAM,UAAU,KAAK,GAAG,EAAE,GAAG,MAAM;AACnC,gBAAU,CAAC;AAAA,IACf;AAAA,IACA,CAAC,EAAE,OAAO;AAAA,EACd;AAEA,+BAAU,MAAM;AACZ,QAAI,SAAU,WAAU,CAAC,CAAC;AAAA,EAC9B,GAAG,CAAC,QAAQ,CAAC;AAGb,+BAAU,MAAM;AACZ,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO;AACX,QAAI;AACJ,QAAI,OAA+B;AACnC,UAAM,OAAO,YAAY;AACrB,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,KAAK;AACN,kBAAU,IAAI;AACd;AAAA,MACJ;AACA,aAAO,IAAI,gBAAgB;AAC3B,UAAI,IAAuB;AAC3B,UAAI;AACA,cAAM,OAAO;AACb,YAAI,MAAM,IAAI,KAAK,KAAK,MAAM;AAC9B,YAAI,KAAM;AACV,aAAK,CAAC;AACN,iBAAS,EAAE;AAAA,MACf,SAAS,GAAG;AACR,YAAK,EAAY,SAAS,gBAAgB,KAAM;AAChD,YAAI,MAAM,QAAS,UAAU,EAAY,OAAO;AAAA,MACpD;AACA,gBAAU,IAAI;AACd,YAAM,UAAU,CAAC,CAAC,GAAG,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,KAAK,GAAG,cAAc,WAAW;AAC/F,YAAM,SAAS,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,EAAE,GAAG;AAC9E,YAAM,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,QAAQ,IAAI;AACnE,YAAM,KAAK,MAAM,UAAU,eAAe,WAAW,SAAS,kBAAkB,WAAW,OAAO,eAAe;AACjH,UAAI,CAAC,QAAQ,GAAI,SAAQ,WAAW,MAAM,EAAE;AAAA,IAChD;AACA,SAAK,KAAK;AACV,WAAO,MAAM;AACT,aAAO;AACP,YAAM,MAAM;AACZ,mBAAa,KAAK;AAAA,IACtB;AAAA,EACJ,GAAG,CAAC,QAAQ,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAEzC,SAAO,EAAE,QAAQ,QAAQ,OAAO,UAAU,QAAQ,KAAK;AAC3D;AAEA,IAAM,cAAc,CAAC,QAAwB,IAAa,UAAkB;AACxE,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAkC,IAAI;AAC9D,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAyB,IAAI;AACnD,+BAAU,MAAM;AACZ,QAAI,CAAC,GAAI;AACT,QAAI,OAAO;AACX,UAAM,IAAI;AAAA,MACN,MACI,KAAK,OAAO,MAAM;AAAA,QAAK,MACnB,OACK,IAAI,GACH,SAAS,MAAM,KAAK,KAAK,MAAS,EACnC,KAAK,CAAC,MAAM;AACT,cAAI,KAAM;AACV,kBAAQ,EAAE,QAAQ;AAClB,cAAI,CAAC,MAAM,KAAK,EAAG,QAAO,EAAE,SAAS,SAAS,CAAC;AAAA,QACnD,CAAC,EACA,MAAM,MAAM,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;AAAA,MACrD;AAAA,MACJ,QAAQ,MAAM;AAAA,IAClB;AACA,WAAO,MAAM;AACT,aAAO;AACP,mBAAa,CAAC;AAAA,IAClB;AAAA,EACJ,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC;AACtB,SAAO,EAAE,MAAM,IAAI;AACvB;AAEA,IAAM,UAAU,CAAC,GAAY,OAAsB,SAC/C,MAAM;AAAA,EAAI,CAAC,GAAG,UACV,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH;AAAA,MACI,KAAK;AAAA,MACL,SAAS,EAAE,OAAO,MAAM,KAAKA,IAAG,QAAQ,QAAQ,EAAE,IAAK,EAAE,MAAM,MAAM,MAAS,IAAI;AAAA,MAClF,mBAAmB,EAAE,OAAO,SAAS;AAAA,MACrC,OAAO;AAAA,QACH,GAAG;AAAA,QACH,GAAI,EAAE,OAAO,EAAE,YAAY,MAAM,IAAI,CAAC;AAAA,QACtC,GAAI,EAAE,SAAS,EAAE,WAAW,SAAS,IAAI,CAAC;AAAA,QAC1C,GAAI,EAAE,OAAO,EAAE,YAAYA,IAAG,SAAS,OAAO,QAAQ,UAAU,aAAa,iBAAiB,EAAE,KAAK,IAAI,CAAC;AAAA,QAC1G,GAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,oBAAoB,YAAY,IAAI,CAAC;AAAA,MACzE;AAAA,IACJ;AAAA,IACA,EAAE;AAAA,EACN;AACJ;AAEJ,IAAM,cAAc,CAAC,EAAE,QAAQ,GAAG,IAAI,MAAM,MAA6E;AACrH,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,CAAC,GAAG,IAAI,QAAI,wBAAyB,IAAI;AAC/C,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,KAAK;AACxC,+BAAU,MAAM;AACZ,UAAM,OAAO,IAAI,gBAAgB;AACjC,WACK,IAAI,GACH,QAAQ,IAAI,KAAK,MAAM,EACxB,KAAK,IAAI,EACT,MAAM,CAAC,MAAa,EAAE,SAAS,gBAAgB,SAAS,EAAE,OAAO,CAAC;AACvE,WAAO,MAAM,KAAK,MAAM;AAAA,EAC5B,GAAG,CAAC,QAAQ,EAAE,CAAC;AACf,MAAI,MAAO,QAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;AACnD,MAAI,CAAC,EAAG,QAAO,EAAE,MAAM,eAAU;AACjC,QAAM,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,GAAG;AACzD,QAAM,SAAS,EAAE,OAAO,IAAI,CAAC,GAAG,MAAM;AAClC,QAAI,EAAE,SAAS,QAAQ,EAAE,SAAS,KAAM,YAAO,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,mBAAmB,UAAU,OAAO,EAAE,GAAG,MAAM,UAAU,EAAE,SAAS,OAAO,KAAK,IAAI,YAAY,OAAO,WAAW,EAAE,EAAE,GAAG,GAAG,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACvN,QAAI,EAAE,SAAS,IAAK,YAAO,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,OAAO,KAAK,GAAG,GAAG,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACzF,QAAI,EAAE,SAAS,QAAS,YAAO,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,MAAM,aAAa,GAAG,EAAE,OAAG,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7M,QAAI,EAAE,SAAS,QAAQ,EAAE,SAAS;AAC9B,iBAAO,cAAAE;AAAA,QACHF,IAAG;AAAA,QACH,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,EAAE;AAAA,QAC5B,GAAG,EAAE,MAAM,IAAI,CAAC,IAAI,UAAM,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,eAAe,OAAO,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,OAAO,GAAG,IAAI,CAAC,MAAM,UAAK,IAAI,OAAG,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,EAAE,GAAG,GAAG,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAAA,MACpN;AACJ,QAAI,EAAE,SAAS,OAAQ,YAAO,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,GAAG,SAAS,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,YAAYA,IAAG,SAAS,OAAO,QAAQ,UAAU,aAAa,UAAU,GAAG,CAAC,CAAC;AACrN,eAAO,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,iBAAiB,EAAE,KAAK,EAAE,CAAC;AAAA,EAC/E,CAAC;AACD,QAAM,OAAO,CAAC,YAAqB;AAC/B,aAAS,IAAI;AACb,WACK,IAAI,GACH,YAAY,IAAI,OAAO,EACxB,MAAM,MAAM,MAAS;AAC1B,QAAI,CAAC,QAAS,OAAM;AAAA,EACxB;AACA,aAAO,cAAAE;AAAA,IACHF,IAAG;AAAA,IACH,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE;AAAA,IACrB,EAAE,MAAM,EAAE,UAAU;AAAA,QACpB,cAAAE,eAAEF,IAAG,MAAM,EAAE,mBAAmB,UAAU,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,EAAE,KAAK;AAAA,IAC5G,GAAG;AAAA,QACH,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,GAAG,SAAS,IAAI,cAAc,IAAI,iBAAiB,EAAE,MAAM,WAAW,EAAE,EAAE;AAAA,MACtI,QAAQ,EAAE,MAAM,6BAA6B,IAAI,EAAE,MAAM,kCAAkC,EAAE,MAAM,EAAE,CAAC;AAAA,MACtG,QAAQ,OAAO,EAAE,IAAI,OAAO,aAAa,MAAM,KAAK,IAAI,GAAG,OAAO,EAAE,QAAQ,GAAG,CAAC;AAAA,MAChF,QAAQ,OAAO,EAAE,IAAI,MAAM,aAAa,MAAM,KAAK,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,CAAC;AAAA,IACpF;AAAA,IACA,EAAE,IAAI,sCAAsC,aAAa,KAAK;AAAA,EAClE;AACJ;AAEA,IAAM,iBAAiB,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,MASM;AACF,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,EAAE;AACnC,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAA6B,IAAI;AAC/D,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAwB,CAAC,CAAC;AACtD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,EAAE;AACrC,QAAM,SAAS,EAAE,SAAS;AAC1B,QAAM,OAAO,YAAY,QAAQ,QAAQ,KAAK;AAC9C,QAAM,aAAS,sBAAoE,IAAI;AACvF,QAAM,QAAQ,MAAM,cAAc,IAAI,KAAK;AAC3C,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,EAAE,OAAO,IAAI;AAEnB,QAAM,SAAS,QAAQ,SAAS,UAAU,MAAM,UAAU,IAAI;AAC9D,+BAAU,MAAM;AACZ,QAAI,SAAS,WAAY,YAAW,MAAM,OAAO,SAAS,cAAc,EAAE,UAAU,KAAK,CAAC,GAAG,EAAE;AAAA,EACnG,GAAG,CAAC,OAAO,IAAI,CAAC;AAEhB,QAAM,aAAa,EAAE,YAAY,SAAS,CAAC,QAAQ,YAAY,CAAC,OAAO,QAAQ,GAAG;AAClF,QAAM,UAAU,CAAC,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,CAAC;AAGxD,QAAM,aAAa,YAAY;AAC3B,UAAM,MAAM,OAAO,IAAI;AACvB,QAAI,CAAC,OAAO,CAAC,aAAa,2BAA2B,QAAS;AAC9D,UAAM,OAAO,yBAAyB,OAAO;AAC7C,QAAI,QAAQ,EAAG,QAAO,KAAK,SAAS,SAAS,sBAAsB,qBAAqB;AACxF,QAAI;AACJ,QAAI;AACA,YAAM,MAAM,YAAY,wBAAwB,EAAE,yBAAyB,OAAO,GAAG,gBAAgB,MAAM,SAAS,KAAK,MAAM,MAAM,CAAC;AAAA,IAC1I,SAAS,GAAG;AACR,aAAO,KAAK,SAAU,EAAY,WAAW,iCAAiC;AAAA,IAClF;AACA,QAAI,IAAI,YAAY,IAAI,aAAa,CAAC,IAAI,QAAQ,OAAQ;AAC1D,SAAK,SAAS,EAAE;AAChB,UAAM,QAAuB,CAAC;AAC9B,eAAW,KAAK,IAAI,OAAO,MAAM,GAAG,IAAI,GAAG;AACvC,YAAM,OAAO,EAAE,YAAY,EAAE,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK;AACrD,YAAM,OAAQ,EAAE,YAAY,OAAO,OAAO,WAAW,EAAE,SAAS,EAAE,QAA4B,IAAI,EAAE,WAAW,YAAY,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY,KAAK,EAAE;AACrK,UAAI,CAAC,MAAM;AACP,aAAK,SAAS,mDAAmD;AACjE;AAAA,MACJ;AACA,UAAI,EAAE,YAAY,EAAE,WAAW,qBAAqB;AAChD,aAAK,SAAS,GAAG,IAAI,wBAAwB;AAC7C;AAAA,MACJ;AACA,YAAM,KAAkB,EAAE,KAAK,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,EAAE,KAAK,MAAM,MAAM,MAAM,EAAE,YAAY,GAAG,IAAI,QAAQ,QAAQ,EAAE;AACjL,SAAG,KAAK,IAAI,eAAe,EAAE,KAAK,EAAE,KAAK,MAAM,KAAK,CAAC,EAAE;AAAA,QACnD,CAACG,OAAM;AACH,aAAG,KAAKA,GAAE;AACV,oBAAU,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,GAAG,IAAI,CAAE,CAAC;AAAA,QAC3E;AAAA,QACA,CAAC,MAAa;AACV,oBAAU,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,CAAC;AACxD,eAAK,SAAS,GAAG,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,QACzC;AAAA,MACJ;AACA,YAAM,KAAK,EAAE;AAAA,IACjB;AACA,cAAU,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAAA,EAC3C;AACA,QAAM,WAAW,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,SAAS,MAAM,CAAC,WAAW;AACpE,QAAM,OAAO,YAAY;AACrB,UAAMF,QAAO,KAAK,KAAK;AACvB,UAAM,MAAM,OAAO,IAAI;AACvB,UAAM,QAAQ;AACd,QAAK,CAACA,SAAQ,CAAC,MAAM,UAAW,WAAW,CAAC,WAAW,CAAC,IAAK;AAC7D,eAAW;AAAA,MACP,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAMA;AAAA,MACN,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC3B,GAAI,MAAM,SAAS,EAAE,aAAa,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC;AAAA,IACvH,CAAC;AACD,YAAQ,EAAE;AACV,cAAU,CAAC,CAAC;AACZ,SAAK,SAAS,EAAE;AAChB,QAAI;AACA,YAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACxC,YAAM,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,EAAG;AACtD,UAAI,CAACA,SAAQ,CAAC,IAAI,OAAQ,OAAM,IAAI,MAAM,8BAA8B;AAExE,YAAM,MAAMD,IAAG,WAAW,IAAI,QAAQ;AACtC,WAAK;AAAA,QACD,MAAM,IAAI,SAAS;AAAA,UACf,MAAMC;AAAA,UACN,OAAO,aAAa,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,UAClD,GAAI,IAAI,SAAS,EAAE,aAAa,IAAI,IAAI,CAAC;AAAA;AAAA,UAEzC,SAAS,EAAE,IAAI,GAAGD,IAAG,SAAS,OAAO,QAAQ,QAAQA,IAAG,SAAS,OAAO,YAAY,YAAYA,IAAG,SAAS,EAAE,IAAIA,IAAG,SAAS,WAAW,EAAE,GAAG,KAAK,GAAG,SAAS,OAAO,UAAU,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,OAAI,KAAK,MAAM,IAAI,MAAM,CAAC,GAAG;AAAA,QACzO,CAAC;AAAA,MACL;AAAA,IACJ,SAAS,GAAG;AACR,cAAQC,KAAI;AACZ,gBAAU,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AACnC,WAAK,SAAU,EAAY,OAAO;AAAA,IACtC,UAAE;AACE,iBAAW,IAAI;AAAA,IACnB;AAAA,EACJ;AAEA,QAAM,gBAAY,sBAAO,oBAAI,IAAoB,CAAC;AAClD,aAAW,KAAK,OAAQ,WAAU,QAAQ,IAAI,EAAE,KAAK,EAAE,GAAG;AAC1D,QAAM,UAAU,CAAC,OAAe,UAAU,QAAQ,IAAI,EAAE,KAAK,OAAO,IAAI,GAAG,cAAc,EAAE,KAAK;AAEhG,QAAM,MAAM,MAAM,EAAE,MAAM;AAC1B,QAAM,OAAO,EAAE,OAAO,KAAK;AAC3B,QAAM,IAAI,QAAQ,EAAE,WAAW,OAAO;AAEtC,QAAM,QAAQ,EAAE,WAAW;AAC3B,QAAM,KAAK,OAAO,GAAG,OAAO,GAAG;AAE/B,QAAM,OAAO,CAAC;AACd,QAAM,UAAU,OAAO,CAAC,IAAI;AAC5B,QAAM,SAAS,GAAG;AAClB,QAAM,SAAS,GAAG;AAClB,QAAM,QAAQ,EAAE,OAAO,KAAK,KAAK;AAEjC,QAAM,SAAS,CAAC,GAAgB,YAAY,UAAU;AAClD,UAAM,OAAO,EAAE,SAAS;AACxB,eAAO,cAAAC;AAAA,MACHF,IAAG;AAAA,MACH,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,WAAW,OAAO,aAAa,cAAc,UAAU,OAAO,KAAK,EAAE,EAAE;AAAA,MAE7F,IAAI,EAAE,eAAe,CAAC,GAAG;AAAA,QAAI,CAAC,UAC1B,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH;AAAA,YACI,KAAK,EAAE;AAAA,YACP,SAAS,MAAM,KAAKA,IAAG,QAAQ,QAAQ,QAAQ,EAAE,EAAE,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,YAC3E,mBAAmB;AAAA,YACnB,oBAAoB,EAAE;AAAA,YACtB,OAAO,EAAE,WAAW,OAAO,aAAa,cAAc,SAAS,YAAY,MAAM,EAAE;AAAA,UACvF;AAAA,UACA,EAAE,KAAK,WAAW,QAAQ,QACpB,cAAAE,eAAEF,IAAG,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,EAAE,EAAE,GAAG,YAAY,SAAS,OAAO,EAAE,OAAO,KAAK,QAAQ,KAAK,cAAc,EAAE,QAAQ,iBAAiB,EAAE,KAAK,EAAE,CAAC,QACxJ,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,EAAE,MAAM,mBAAmB,IAAI,iBAAiB,EAAE,EAAE,GAAG,EAAE,KAAK,aAAM,EAAE,IAAI,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,QACtK;AAAA,MACJ;AAAA,MACA,CAAC,EAAE,QAAQ,EAAE,aAAa,SACpB,WACA,cAAAE;AAAA,QACFF,IAAG;AAAA,QACH;AAAA,UACI,OAAO;AAAA,YACH,iBAAiB,OAAO,EAAE,SAAS,GAAG;AAAA,YACtC,GAAI,OAAO,CAAC,IAAI;AAAA,YAChB,cAAc,EAAE;AAAA,YAChB,yBAAyB,OAAO,EAAE,OAAO,EAAE;AAAA,YAC3C,wBAAwB,OAAO,EAAE,SAAS,EAAE;AAAA,YAC5C,mBAAmB;AAAA,YACnB,iBAAiB;AAAA,YACjB,SAAS,YAAY,MAAM;AAAA,UAC/B;AAAA,QACJ;AAAA,QACA,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,OAAO,MAAM,GAAG,GAAG,CAAC;AAAA,MAChD;AAAA,MACA,IAAI,EAAE,YAAY,CAAC,GAAG;AAAA,QAAI,CAAC,UACvB,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH,EAAE,KAAK,EAAE,IAAI,SAAS,MAAM,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,mBAAmB,QAAQ,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,EAAE,MAAM,mBAAmB,IAAI,iBAAiB,EAAE,EAAE;AAAA,UACvL,EAAE,KAAK,aAAM,EAAE,KAAK,IAAI,EAAE,UAAU,GAAG,CAAC;AAAA,QAC5C;AAAA,MACJ;AAAA,MACA,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,KAAK,GAAG,SAAS,EAAE,IAAI,CAAC,QAAK,GAAG,YAAY,kBAAa,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,IAAI,WAAW,OAAO,UAAU,QAAQ,mBAAmB,EAAE,CAAC,IAAI;AAAA,IACrL;AAAA,EACJ;AACA,QAAM,MAAM,CAAC,UACT,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,EAAE,IAAI,SAAS,MAAM,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,mBAAmB,UAAU,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,GAAG,iBAAiB,IAAI,mBAAmB,EAAE,EAAE;AAAA,IAC9L,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAAA,IAC3B,MAAM,QAAQ,EAAE,QAAQ,EAAE;AAAA,EAC9B;AACJ,QAAM,OAAO,CAAC,UAAuB,QAAe,CAAC,UACjD,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,iBAAiB,QAAQ,cAAc,EAAE,MAAM,SAAS,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,QAAQ;AACxH,QAAM,YAAY,CAAC,gBACf,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,KAAK,SAAS,mBAAmB,UAAU,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,QAAQ,IAAI,cAAc,EAAE,OAAO,mBAAmB,IAAI,iBAAiB,GAAG,IAAI,EAAE;AAAA,IAC3L,EAAE,MAAM,mBAAmB,EAAE,MAAM,GAAG,UAAU,GAAG,CAAC;AAAA,IACpD,MAAM,UAAU,EAAE,QAAQ,EAAE;AAAA,EAChC;AACJ,QAAM,SAAS,EAAE,MAAM,EAAE,OAAO,OAAO,UAAU,UAAU,aAAa,mBAAmB,KAAK,KAAK,OAAO,EAAE,aAAa,GAAG,cAAc,EAAE,OAAO,iBAAiB,QAAQ,GAAG,KAAK,EAAE,CAAC;AAEzL,QAAM,QAAQ,OAAO,QAAQ,GAAG,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC;AAC3D,QAAM,OAAO,SAAS,QAAQ,+CAA+C,EAAE,EAAE,KAAK,KAAK;AAC3F,QAAM,OAAO,CAAC,IAAY,YACtB,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,QAAQ,mBAAmB,UAAU,OAAO,EAAE,OAAO,IAAI,UAAU,IAAI,YAAY,OAAO,eAAe,MAAM,YAAY,GAAG,EAAE;AAAA,IACvI,QAAQ,OAAO,KAAK;AAAA,IAAU;AAAA,QAC9B,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,YAAY,MAAM,EAAE,GAAG,IAAI;AAAA,EACjE;AAEJ,QAAM,OAAO,QAAQ,SAAS,GAAG,EAAE;AACnC,QAAM,WAAW,UAAU,KAAK,QAAQ;AACxC,MAAI;AACJ,MAAI,SAAS,QAAQ;AACjB,UAAM,QAAQ;AAAA;AAAA,UAEV,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,KAAK,OAAO,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,GAAG,QAAQ,IAAI,cAAc,IAAI,aAAa,IAAI,cAAc,GAAG,iBAAiB,GAAG,SAAS,GAAG,KAAK,EAAE;AAAA,QAClL,EAAE,MAAM,EAAE,OAAO,MAAM,UAAU,SAAS,aAAa,kBAAkB,KAAK,KAAM,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,mBAAmB,GAAG,iBAAiB,cAAc,EAAE,CAAC;AAAA,YAC9K,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH;AAAA,YACI,SAAS,MAAM;AACX,sBAAQ,UAAU;AAClB,kBAAI,KAAK,KAAK,EAAG,MAAK,KAAK;AAAA,YAC/B;AAAA,YACA,mBAAmB;AAAA,YACnB,oBAAoB;AAAA,YACpB,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,IAAI,YAAY,UAAU,gBAAgB,UAAU,iBAAiB,KAAK,KAAK,IAAI,EAAE,SAAS,GAAG,IAAI;AAAA,UACvJ;AAAA,UACA,MAAM,MAAM,KAAK,KAAK,IAAI,MAAM,GAAG,OAAO,EAAE;AAAA,QAChD;AAAA,MACJ;AAAA,MACA,WACM,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,KAAK,UAAU,SAAS,MAAM,QAAQ,UAAU,GAAG,mBAAmB,SAAS;AAAA,QACjF,KAAK;AAAA,cACD,cAAAE;AAAA,YACIF,IAAG;AAAA,YACH,EAAE,KAAK,KAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,GAAG,EAAE;AAAA,YAC3E,QAAQ,SAAS,OAAO,MAAM,EAAE,QAAQ,IAAI,GAAG,EAAE,QAAQ,EAAE,IAAI;AAAA,gBAC/D,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,EAAE,OAAG,cAAAE,eAAEF,IAAG,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,OAAO,GAAG,IAAI,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,KAAK,SAAS,KAAK,aAAa,SAAS,QAAQ,KAAK,YAAY,WAAW,IAAI,KAAK,YAAY,CAAC,EAAE,OAAO,GAAG,KAAK,YAAY,MAAM,QAAQ,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,KAAK,SAAS,YAAY,QAAQ,SAAS,KAAK,IAAI,CAAC,SAAM,QAAQ,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,CAAC,CAAC;AAAA,YAC5Y,KAAK,OAAO,aACN,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,iBAAiB,EAAE,OAAO,EAAE,CAAC,IACzF,MAAM,QAAQ,EAAE,OAAO,EAAE;AAAA,UACnC;AAAA,QACJ,GAAG,EAAE,iBAAiB,IAAI,mBAAmB,GAAG,CAAC;AAAA,MACrD,IACA;AAAA,MACN,WAAW,KAAK,CAAC,UAAU,MAAM,QAAQ,MAAM,CAAC,GAAG,IAAI,KAAK,QAAQ,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,SAAS,GAAG,KAAK,EAAE,CAAC,IAAI;AAAA,IAC7H;AACA,cAAU,YACJ,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,iBAAiB,OAAO,GAAG,uBAAuB,EAAE,mBAAmB,IAAI,YAAY,GAAG,eAAe,IAAI,KAAK,GAAG,GAAG,2BAA2B,UAAU;AAAA,UAC9L,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,OAAO,OAAO,EAAE,mBAAmB,GAAG,eAAe,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;AAAA,MAClG,GAAG;AAAA,IACP,QACA,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,iBAAiB,OAAO,GAAG,uBAAuB,EAAE,eAAe,GAAG,GAAG,2BAA2B,UAAU;AAAA,UAC/I,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,mBAAmB,IAAI,YAAY,GAAG,eAAe,GAAG,EAAE,GAAG,KAAK,KAAK,MAAM,KAAK,GAAG,CAAC,CAAC;AAAA,UACxI,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,mBAAmB,IAAI,KAAK,GAAG,EAAE,GAAG,GAAG,KAAK;AAAA,IACtF;AAAA,EACV,WAAW,SAAS;AAChB,kBAAU,cAAAE;AAAA,MACNF,IAAG;AAAA,MACH,EAAE,KAAK,YAAY,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,GAAG,EAAE;AAAA,UAC9D,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,KAAK,QAAQ,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAuB,EAAE,mBAAmB,IAAI,YAAY,GAAG,eAAe,IAAI,KAAK,GAAG,EAAE;AAAA,QAC/H,OAAO,EAAE,IAAI,YAAY,MAAM,QAAQ,MAAM,UAAU,IAAI,GAAG,CAAC;AAAA,QAC/D,CAAC,KAAK,SAAS,EAAE,MAAM,eAAU,IAAI;AAAA,QACrC,IAAI,QAAQ,YAAY,CAAC,GAAG,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA,QAChD,UAAU,OAAO,SAAS,IAAI,IAAI;AAAA,QAClC,QAAQ,cAAc,WAAW,YAAY,CAAC,UAAU,EAAE,MAAM,0DAA0D,EAAE,WAAW,SAAS,CAAC,IAAI;AAAA,MACzJ;AAAA,UACA,cAAAE;AAAA,QACIF,IAAG;AAAA,QACH,EAAE,OAAO,EAAE,mBAAmB,IAAI,YAAY,GAAG,eAAe,GAAG,KAAK,EAAE,EAAE;AAAA,QAC5E,KAAK,QAAQ,EAAE,KAAK,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAU,GAAG,CAAC,IAAI;AAAA,QACrE,YACM,EAAE,MAAM,EAAE,OAAO,OAAO,UAAU,UAAU,aAAa,8CAA8C,OAAO,MAAM,KAAK,KAAK,OAAO,EAAE,aAAa,UAAU,IAAI,GAAG,aAAa,EAAE,QAAQ,cAAc,EAAE,OAAO,mBAAmB,IAAI,iBAAiB,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC,IAClR;AAAA;AAAA,QAEN,OAAO,aACD,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH,EAAE,OAAO,EAAE,eAAe,OAAO,UAAU,QAAQ,KAAK,IAAI,YAAY,GAAG,mBAAmB,EAAE,EAAE;AAAA,UAClG,GAAG,OAAO;AAAA,YAAI,CAAC,UACX,cAAAE;AAAA,cACIF,IAAG;AAAA,cACH,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,IAAI,QAAQ,GAAG,EAAE;AAAA,kBAC/C,cAAAE,eAAEF,IAAG,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAG,YAAY,SAAS,oBAAoB,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,IAAI,eAAe,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,KAAK,IAAI,GAAG,EAAE,OAAO,CAAC,GAAG,iBAAiB,EAAE,MAAM,SAAS,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;AAAA,kBAClP,cAAAE;AAAA,gBACIF,IAAG;AAAA,gBACH;AAAA,kBACI,SAAS,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC;AAAA,kBACtE,mBAAmB;AAAA,kBACnB,oBAAoB,UAAU,EAAE,IAAI;AAAA,kBACpC,SAAS;AAAA,kBACT,OAAO,EAAE,UAAU,YAAY,KAAK,IAAI,OAAO,IAAI,OAAO,IAAI,QAAQ,IAAI,cAAc,IAAI,aAAa,GAAG,aAAa,EAAE,IAAI,iBAAiB,EAAE,IAAI,YAAY,UAAU,gBAAgB,SAAS;AAAA,gBACzM;AAAA,gBACA,MAAM,SAAS,EAAE,IAAI,EAAE;AAAA,cAC3B;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ,IACA;AAAA;AAAA,YAEN,cAAAE;AAAA,UACIF,IAAG;AAAA,UACH,EAAE,OAAO,EAAE,KAAK,GAAG,cAAc,IAAI,YAAY,IAAI,eAAe,GAAG,cAAc,GAAG,aAAa,IAAI,iBAAiB,GAAG,SAAS,GAAG,KAAK,EAAE;AAAA,UAChJ,EAAE,MAAM,EAAE,OAAO,MAAM,UAAU,SAAS,aAAa,yBAAoB,WAAW,MAAM,KAAK,KAAM,OAAO,EAAE,WAAW,IAAI,WAAW,KAAK,aAAa,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,iBAAiB,cAAc,EAAE,CAAC;AAAA,cAC3O,cAAAE;AAAA,YACIF,IAAG;AAAA,YACH,EAAE,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,YAAY,GAAG,EAAE;AAAA,YACxE,aAAa,8BACP,cAAAE;AAAA,cACIF,IAAG;AAAA,cACH,EAAE,SAAS,MAAM,KAAK,WAAW,GAAG,UAAU,CAAC,CAAC,SAAS,mBAAmB,UAAU,oBAAoB,gCAAgC,SAAS,GAAG,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,IAAI,YAAY,UAAU,gBAAgB,SAAS,EAAE;AAAA,cACzP,MAAM,QAAQ,GAAG,OAAO,EAAE;AAAA,YAC9B,IACA;AAAA,gBACN,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;AAAA,gBACjC,cAAAE;AAAA,cACIF,IAAG;AAAA,cACH;AAAA,gBACI,SAAS,MAAM,KAAK,KAAK;AAAA,gBACzB,UAAU,CAAC;AAAA,gBACX,mBAAmB;AAAA,gBACnB,oBAAoB;AAAA,gBACpB,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,IAAI,YAAY,UAAU,gBAAgB,UAAU,iBAAiB,UAAU,EAAE,SAAS,GAAG,IAAI;AAAA,cACnJ;AAAA,cACA,MAAM,MAAM,UAAU,MAAM,GAAG,OAAO,EAAE;AAAA,YAC5C;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,WACK,SAAS,QAAQ;AACtB,UAAM,SAAS,oBAAI,IAA8B;AACjD,eAAW,KAAK,KAAK,QAAQ,CAAC,EAAG,QAAO,IAAI,EAAE,YAAY,CAAC,GAAI,OAAO,IAAI,EAAE,UAAU,KAAK,CAAC,GAAI,CAAC,CAAC;AAClG,kBAAU,cAAAE;AAAA,MACNF,IAAG;AAAA,MACH,EAAE,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,iBAAiB,OAAO,GAAG,uBAAuB,EAAE,mBAAmB,IAAI,YAAY,GAAG,eAAe,IAAI,KAAK,GAAG,GAAG,2BAA2B,UAAU;AAAA,MAC9L;AAAA,MACA,KAAK,SAAS,OAAO,EAAE,MAAM,eAAU,IAAI;AAAA,MAC3C,KAAK,MAAM,WAAW,QAChB,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,YAAY,UAAU,iBAAiB,GAAG,EAAE,GAAG,EAAE,MAAM,MAAM,KAAK,IAAI,2BAAsB,MAAM,KAAK,CAAC,YAAO,uBAAuB,GAAG,EAAE,IAAI,qBAAqB,WAAW,MAAM,QAAQ,UAAU,CAAC,CAAC,IACxO;AAAA,MACN,GAAI,MAAM,KAAK,IACT,KAAK,MAAM,SACP,CAAC,MAAM,KAAK,QAAQ,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,IACjD,CAAC,IACL,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,UAAM,cAAAE,eAAEF,IAAG,MAAM,EAAE,KAAK,MAAM,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,SAAM,MAAM,MAAM,IAAI,EAAE,UAAU,IAAI,YAAY,OAAO,mBAAmB,EAAE,CAAC,GAAG,KAAK,MAAM,IAAI,GAAG,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAAA,IAChO;AAAA,EACJ;AACI,kBAAU,cAAAE;AAAA,MACNF,IAAG;AAAA,MACH,EAAE,KAAK,KAAK,KAAK,OAAO,IAAI,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAuB,EAAE,mBAAmB,IAAI,YAAY,GAAG,eAAe,GAAG,EAAE;AAAA,UACnI,cAAAE,eAAE,aAAa,EAAE,QAAQ,GAAG,IAAI,KAAK,SAAS,OAAO,MAAM,QAAQ,UAAU,EAAE,CAAC;AAAA,IACpF;AAEJ,QAAM,UAAU,OAAO,SAAS,WAAW,OAAO;AAElD,QAAM,MAAM,CAAC,GAAiC,MAAc,MAA0B,QAAQ,MAAM;AAChG,UAAM,KAAK,YAAY;AACvB,eAAO,cAAAA;AAAA,MACHF,IAAG;AAAA,MACH;AAAA,QACI,KAAK;AAAA,QACL,SAAS,MAAM,QAAQ,CAAC;AAAA,QACxB,mBAAmB;AAAA,QACnB,oBAAoB,EAAE,UAAU,GAAG;AAAA,QACnC,OAAO,EAAE,MAAM,GAAG,eAAe,OAAO,YAAY,UAAU,gBAAgB,UAAU,KAAK,GAAG,QAAQ,IAAI,cAAc,IAAI,GAAI,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,QAAQ,IAAI,CAAC,EAAG;AAAA,MAC7L;AAAA,MACA,MAAM,MAAM,KAAK,GAAG,KAAK,GAAG,OAAO,EAAE;AAAA,MACrC,EAAE,KAAK,MAAM,EAAE,UAAU,MAAM,YAAY,OAAO,OAAO,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAAA,MAChF,YAAQ,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,UAAU,YAAY,KAAK,GAAG,OAAO,IAAI,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,iBAAiB,EAAE,OAAO,EAAE,CAAC,IAAI;AAAA,IAClJ;AAAA,EACJ;AAEA,QAAM,WAAW,SAAS,UAAU,CAAC;AACrC,QAAM,SAAS,WAAW,EAAE,SAAS,GAAG;AACxC,QAAM,OAAO,CAAC,IAAa,cACvB,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,QAAQ,SAAS,MAAM,QAAQ,EAAE,GAAG,mBAAmB,UAAU,oBAAoB,OAAO,SAAS,IAAI,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,YAAY,UAAU,gBAAgB,UAAU,WAAW,CAAC,EAAE,QAAQ,SAAS,CAAC,EAAE,EAAE;AAAA,IACpO,MAAM,QAAQ,GAAG,IAAI,EAAE;AAAA,EAC3B;AACJ,QAAM,WAAO,cAAAE;AAAA,IACTF,IAAG;AAAA,IACH,EAAE,KAAK,QAAQ,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,GAAG,aAAa,IAAI,cAAc,IAAI,YAAY,IAAI,eAAe,GAAG,iBAAiB,OAAO,EAAE;AAAA,IAC3K,OAAO,SAAS,WACV,KAAK,QAAQ,cAAc,IAC3B,SAAS,aACP,KAAK,QAAQ,cAAc,IAC3B,SAAS,WAAW,EAAE,QAAQ,SAC5B,EAAE,WACE,cAAAE,eAAEF,IAAG,OAAO,EAAE,KAAK,QAAQ,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,kCAAkC,MAAM,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,GAAG,YAAY,EAAE,EAAE,CAAC,IAC9J,SAAS,OAAO,MAAM,EAAE,QAAQ,IAAI,GAAG,EAAE,QAAQ,EAAE,IACvD;AAAA;AAAA,IAEV,SAAS,cAAc,YACjB,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,OAAO,YAAY,UAAU,gBAAgB,UAAU,KAAK,EAAE,EAAE;AAAA,MACnG,SAAS,OAAO,MAAM,EAAE,QAAQ,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,UACnD,cAAAE,eAAEF,IAAG,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI,UAAU,IAAI,YAAY,MAAM,EAAE,GAAG,KAAK;AAAA,IACnH,QACA,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;AAAA,QACvC,cAAAE,eAAEF,IAAG,WAAW,EAAE,SAAS,OAAO,mBAAmB,UAAU,oBAAoB,SAAS,SAAS,IAAI,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,cAAc,IAAI,YAAY,UAAU,gBAAgB,SAAS,EAAE,GAAG,MAAM,SAAS,WAAW,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EAC/P;AAEA,QAAM,UAAU,YACV,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,SAAS,OAAO,EAAE,YAAY,GAAG,eAAe,GAAG,YAAY,UAAU,iBAAiB,GAAG,GAAG,EAAE;AAAA,QACzG,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,SAAS,MAAM,KAAKA,IAAG,QAAQ,QAAQ,SAAS,EAAE,MAAM,MAAM,MAAS,GAAG,mBAAmB,QAAQ,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,UAAU,KAAK,EAAE;AAAA,MAC7J;AAAA,UACA,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,YAAY,MAAM,EAAE,GAAG,UAAU;AAAA,IAC3D;AAAA,EACJ,IACA;AACN,aAAO,cAAAE;AAAA,IACHF,IAAG;AAAA,IACH,EAAE,SAAS,MAAM,eAAe,SAAS,mBAAmB,aAAa,gBAAgB,MAAM;AAAA,QAC/F,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH,EAAE,UAAUA,IAAG,SAAS,OAAO,QAAQ,YAAY,QAAW,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,GAAG,EAAE;AAAA,MACzG;AAAA,MACA;AAAA,MACA,SAAS,aAAa,WAAO,cAAAE;AAAA,QACzBF,IAAG;AAAA,QACH,EAAE,KAAK,QAAQ,mBAAmB,WAAW,OAAO,EAAE,eAAe,OAAO,kBAAkB,IAAI,WAAW,GAAG,cAAc,GAAG,SAAS,GAAG,cAAc,IAAI,iBAAiB,GAAG,QAAQ,EAAE;AAAA,QAC7L,IAAI,QAAQ,QAAQ,MAAM;AAAA,QAC1B,IAAI,YAAY,YAAY,QAAQ,KAAK,OAAO,MAAM;AAAA,QACtD,WAAW,IAAI,QAAQ,QAAQ,MAAM,IAAI;AAAA,MAC7C;AAAA,MACA;AAAA,UACA,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,EAAE,CAAC;AAAA,IACxC;AAAA,EACJ;AACJ;AACO,IAAM,oBAAoB,CAAC,EAAE,QAAQ,YAAY,SAAS,QAAQ,CAAC,EAAE,MAAmG;AAE3K,QAAM,CAAC,MAAM,OAAO,QAAI,wBAA+B,IAAI;AAC3D,+BAAU,MAAM;AACZ,UAAM,OAAO,IAAI,gBAAgB;AACjC,SAAK,OAAO,MAAM;AAAA,MAAK,MACnB,OACK,IAAI,GACH,cAAc,KAAK,MAAM,EAC1B,KAAK,OAAO,EACZ,MAAM,MAAM,MAAS;AAAA,IAC9B;AACA,WAAO,MAAM,KAAK,MAAM;AAAA,EAC5B,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS,CAAC;AAC3F,QAAM,UAAkC,OAClC;AAAA,IACI,OAAO,KAAK;AAAA,IACZ,UAAU,KAAK;AAAA,IACf,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK,eAAe;AAAA,IAC9B,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,UAAU,KAAK;AAAA,IACf,SAAS,KAAK;AAAA,IACd,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,GAAG;AAAA,EACP,IACA;AACN,QAAM,IAAI,WAAW,EAAE,OAAO,YAAY,SAAS,MAAM,OAAO,QAAQ,YAAY,UAAU,MAAM,OAAO,CAAC;AAC5G,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,OAAO,cAAc,QAAQ;AACnC,QAAM,CAAC,MAAM,YAAY,QAAI,wBAAkB,OAAO;AACtD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAA6B,IAAI;AAC7D,+BAAU,MAAM;AACZ,QAAI,KAAM,cAAa,OAAO;AAAA,EAClC,GAAG,CAAC,IAAI,CAAC;AACT,QAAM,UAAU,CAAC,MAAe;AAC5B,cAAU;AACV,iBAAa,CAAC;AAAA,EAClB;AACA,QAAM,OAAO,QAAQ,QAAQ,SAAS,MAAM,IAAI;AAGhD,QAAM,SAAS,KAAK,OAAO,GAAG,EAAE;AAChC,+BAAU,MAAM;AACZ,QAAI,CAAC,UAAU,QAAQ,QAAQ,YAAY,MAAO;AAClD,cAAU,MAAM;AAChB,UAAM,IAAI,WAAW,MAAM,UAAU,IAAI,GAAG,GAAI;AAChD,WAAO,MAAM,aAAa,CAAC;AAAA,EAC/B,GAAG,CAAC,QAAQ,MAAM,QAAQ,OAAO,CAAC;AAClC,+BAAU,MAAM;AACZ,QAAI,KAAM,WAAU,IAAI;AAAA,EAC5B,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,SAAS,KAAK,OAAO;AAC3B,QAAM,MAAM,MAAM,EAAE,MAAM;AAC1B,QAAM,QAAQ,QAAQ,OAAO,KAAK,KAAK;AACvC,QAAM,IAAI,QAAQ,QAAQ,WAAW,OAAO;AAE5C,QAAM,CAAC,MAAM,IAAI,KAAK,QAAQ,YAAY,gBAAgB,MAAM,GAAG;AACnE,QAAM,QAAe;AAAA,IACjB,GAAI,SAAS,QAAQ,EAAE,KAAK,GAAG,IAAI,SAAS,WAAW,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,gBAAgB,SAAS;AAAA,IACtH,GAAI,SAAS,SAAS,EAAE,MAAM,GAAG,IAAI,SAAS,UAAU,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,SAAS;AAAA,EACtH;AACA,QAAM,WAAW,QAAQ,eACnB,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH,EAAE,KAAK,YAAY,eAAe,YAAY,OAAO,EAAE,UAAU,YAAY,GAAG,MAAM,EAAE;AAAA,QACxF,cAAAE;AAAA,MACIF,IAAG;AAAA,MACH;AAAA,QACI,SAAS,MAAM,OAAO,SAAS,aAAa,MAAM;AAAA,QAClD,mBAAmB;AAAA,QACnB,oBAAoB,SAAS,cAAc,MAAM,SAAS;AAAA,QAC1D,OAAO;AAAA,UACH,QAAQ,QAAQ,KAAK;AAAA,UACrB,UAAU,QAAQ,IAAI;AAAA,UACtB,mBAAmB,QAAQ,KAAK;AAAA,UAChC,cAAc;AAAA,UACd,eAAe;AAAA,UACf,KAAK;AAAA,UACL,iBAAiB,EAAE;AAAA,UACnB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,aAAa,EAAE;AAAA,UACf,eAAe;AAAA,UACf,cAAc;AAAA,UACd,cAAc,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,UACpC,WAAW;AAAA,QACf;AAAA,MACJ;AAAA,MACA,MAAM,QAAQ,KAAK,QAAQ,KAAK,EAAE;AAAA,MAClC,QAAQ,EAAE,KAAK,OAAO,EAAE,OAAO,KAAK,YAAY,MAAM,CAAC,IAAI;AAAA,MAC3D,aACM,cAAAE,eAAEF,IAAG,MAAM,EAAE,OAAO,EAAE,UAAU,YAAY,KAAK,IAAI,OAAO,IAAI,UAAU,IAAI,QAAQ,IAAI,cAAc,IAAI,iBAAiB,EAAE,QAAQ,YAAY,UAAU,gBAAgB,UAAU,aAAa,GAAG,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,OAAO,KAAK,IAAI,QAAQ,CAAC,CAAC,GAAG,EAAE,OAAO,QAAQ,UAAU,IAAI,YAAY,MAAM,CAAC,CAAC,IACrT;AAAA,IACV;AAAA,EACJ,IACA;AAEN,QAAM,QAAQ,aACR,cAAAE;AAAA,IACIF,IAAG;AAAA,IACH;AAAA,MACI,KAAK;AAAA,MACL,SAAS,MAAM,OAAO,UAAU;AAAA,MAChC,mBAAmB;AAAA,MACnB,yBAAyB;AAAA,MACzB,OAAO;AAAA,QACH,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,KAAK;AAAA,QACL,iBAAiB,EAAE,OAAO,KAAK,KAAK,EAAE,OAAO,EAAE;AAAA,QAC/C,cAAc,EAAE,OAAO;AAAA,QACvB,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc;AAAA,QACd,cAAc,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,QACpC,WAAW;AAAA,MACf;AAAA,IACJ;AAAA,IACA,EAAE,MAAM,GAAG,SAAS,OAAO,IAAI,CAAC,GAAG,SAAS,IAAI,SAAM,MAAM,SAAS,EAAE,IAAI,EAAE,YAAY,OAAO,UAAU,GAAG,CAAC;AAAA,QAC9G,cAAAE,eAAEF,IAAG,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,IAAI,YAAY,GAAG,EAAE,GAAG,OAAO,IAAI;AAAA,EACtG,IACA;AACN,MAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAM,QAAO;AACzC,aAAO,cAAAE;AAAA,IACHF,IAAG;AAAA,IACH,EAAE,eAAe,YAAY,OAAO,EAAE,UAAU,YAAY,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,EAAE,EAAE;AAAA,IACnG;AAAA,IACA;AAAA,IACA,WAAO,cAAAE,eAAE,gBAAgB,EAAE,QAAQ,GAAG,GAAG,SAAS,MAAM,MAAM,SAAS,OAAO,MAAM,aAAa,MAAM,CAAC,IAAI;AAAA,EAChH;AACJ;;;Ad52CA,IAAME,MAAK,QAAQ,cAAc;AAS1B,IAAM,eAAe,CAAC,EAAE,UAAU,MAAM,MAAiD;AAC5F,QAAM,UAAM,sBAA0B,IAAI;AAC1C,+BAAU,MAAM;AACZ,gBAAY,IAAI,GAAG;AACnB,WAAO,MAAM;AACT,kBAAY,OAAO,GAAG;AAAA,IAC1B;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,aAAO,6BAAcA,IAAG,MAAM,EAAE,KAAK,aAAa,OAAO,MAAM,GAAG,QAAQ;AAC9E;AAEA,IAAI,SAAgC;AACpC,IAAI,YAAY;AAMT,IAAM,iBAAiB,CAAC,YAAoF;AAC/G,MAAI,QAAQ;AACR,QAAI,cAAc,QAAQ,OAAQ,SAAQ,KAAK,gFAAgF;AAC/H,WAAO;AAAA,EACX;AACA,QAAM,EAAE,SAAS,GAAG,KAAK,IAAI;AAC7B,QAAM,OAAO,WAAW,EAAE,QAAQ,CAAC;AACnC,WAAS,aAAa,MAAM,IAAI;AAChC,cAAY,QAAQ;AACpB,MAAI,QAAQ,MAAO,SAAQ,IAAI,+BAA+B,KAAK,UAAU,gBAAgB,CAAC,CAAC;AAC/F,SAAO;AACX;AAGO,IAAM,cAAc,MAAM;AAEjC,IAAM,UAAM,6BAAqC,IAAI;AAmC9C,IAAM,mBAAmB,CAAC,EAAE,QAAQ,OAAO,UAAU,SAAS,QAAQ,MAAM,YAAY,UAAU,MAAM,YAAY,CAAC,GAAG,WAAW,CAAC,GAAG,WAAW,MAAM,GAAG,QAAQ,MAA6B;AACnM,QAAM,CAAC,MAAM,QAAI,wBAAS,MAAM,SAAS,eAAe,EAAE,GAAG,SAAS,QAAQ,CAAC,CAAC;AAChF,+BAAU,MAAM;AACZ,QAAI,QAAS,QAAO,WAAW,OAAO;AAAA,EAC1C,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,+BAAU,MAAM;AACZ,QAAI,QAAQ,WAAW,OAAW,QAAO,UAAU,QAAQ,MAAM;AAAA,EACrE,GAAG,CAAC,QAAQ,QAAQ,MAAM,CAAC;AAE3B,QAAM,YAAQ,sBAAmD,IAAI;AACrE,QAAM,QAAQ,CAAC,GAAsH,QAAiB;AAElJ,UAAM,IAAI,EAAE;AACZ,UAAM,IAAI,EAAE,SAAS,EAAE,iBAAiB,CAAC,GAAG;AAC5C,UAAM,IAAI,EAAE,SAAS,EAAE,iBAAiB,CAAC,GAAG;AAC5C,QAAI,MAAM,UAAa,MAAM,OAAW;AACxC,QAAI,CAAC,IAAK,OAAM,UAAU,EAAE,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE;AAAA,aACvC,MAAM,WAAW,KAAK,MAAM,IAAI,MAAM,QAAQ,GAAG,IAAI,MAAM,QAAQ,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,IAAI,IAAK,QAAO,IAAI,GAAG,CAAC;AAAA,EAC9I;AACA,aAAO;AAAA,IACH,IAAI;AAAA,IACJ,EAAE,OAAO,OAAO;AAAA,IAChB,eACM,6BAAcA,IAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,qBAAqB,CAAC,MAAa,MAAM,GAAG,KAAK,GAAG,mBAAmB,CAAC,MAAa,MAAM,GAAG,IAAI,EAAE,GAAG,QAAQ,IAC5J;AAAA,IACN,YAAQ,6BAAc,eAAe,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,SAAS,WAAW,CAAC,IAAI;AAAA,IACrG,cAAU,6BAAc,iBAAiB,EAAE,QAAQ,WAAW,CAAC,IAAI;AAAA,IACnE,eAAW,6BAAc,kBAAkB,EAAE,QAAQ,YAAY,SAAS,SAAS,CAAC,IAAI;AAAA,IACxF,gBAAY,6BAAc,mBAAmB,EAAE,QAAQ,YAAY,SAAS,UAAU,CAAC,IAAI;AAAA,EAC/F;AACJ;AAEA,IAAM,YAAY,MAAM;AACpB,QAAM,QAAI,0BAAW,GAAG;AACxB,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,8DAAyD;AACjF,SAAO;AACX;AAGA,IAAM,aAAa,CAAC,eAA2B,oCAAqB,OAAO,WAAW,OAAO,YAAY,OAAO,UAAU;AAMnH,IAAM,cAAc,MAAM;AAC7B,QAAM,SAAS,UAAU;AACzB,aAAW,MAAM;AACjB,SAAO;AAAA,IACH,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,cAAc,OAAO;AAAA,IACrB,OAAO,OAAO;AAAA,IACd,YAAY,OAAO,cAAc;AAAA,IACjC,SAAS,OAAO,WAAW;AAAA,IAC3B,OAAO,OAAO,QAAQ;AAAA,EAC1B;AACJ;AAUO,IAAM,gBAAgB,MAA4E;AACrG,QAAM,SAAS,UAAU;AACzB,SAAO,EAAE,MAAM,OAAO,eAAe;AACzC;AAUO,IAAM,UAAU,MAAwG;AAC3H,QAAM,SAAS,UAAU;AACzB,SAAO,EAAE,UAAU,OAAO,iBAAiB,YAAY,OAAO,kBAAkB;AACpF;AASO,IAAM,aAAa,MAA+C;AACrE,QAAM,SAAS,UAAU;AACzB,SAAO,EAAE,MAAM,OAAO,YAAY;AACtC;AAUO,IAAM,YAAY,MAAoD;AACzE,QAAM,SAAS,UAAU;AACzB,SAAO,EAAE,SAAS,OAAO,cAAc;AAC3C;AAGO,IAAM,gBAAgB,MAA2C;AACpE,QAAM,SAAS,UAAU;AACzB,SAAO,EAAE,OAAO,OAAO,gBAAgB;AAC3C;AAGO,IAAM,UAAU,CAAC,QAAyB;AAC7C,QAAM,SAAS,UAAU;AACzB,aAAW,MAAM;AACjB,SAAO,OAAO,QAAQ,GAAG;AAC7B;AAGO,IAAM,iBAAiB,CAAC,QAA+B;AAC1D,QAAM,SAAS,UAAU;AACzB,aAAW,MAAM;AACjB,SAAO,OAAO,eAAe,GAAG;AACpC;AAMO,IAAM,aAAa,CAAC,QAA2B;AAClD,QAAM,SAAS,UAAU;AACzB,aAAW,MAAM;AACjB,QAAM,SAA+B,OAAO,UAAU;AACtD,QAAM,UAAU,OAAO,YAAY,GAAG;AACtC,+BAAU,MAAM;AACZ,QAAI,OAAQ,QAAO,OAAO,KAAK,OAAO;AAAA,EAC1C,GAAG,CAAC,QAAQ,QAAQ,KAAK,OAAO,CAAC;AACjC,SAAO;AACX;AAWO,IAAM,UAAU,CAAC,IAAY,aAA6B;AAC7D,QAAM,SAAS,UAAU;AACzB,aAAW,MAAM;AACjB,QAAM,SAA+B,OAAO,UAAU;AACtD,QAAMC,QAAO,OAAO,SAAS,EAAE;AAC/B,QAAM,SAAS,OAAO,cAAc;AACpC,+BAAU,MAAM;AACZ,QAAI,OAAQ,QAAO,WAAW,EAAE;AAAA,EACpC,GAAG,CAAC,QAAQ,QAAQ,IAAI,MAAM,CAAC;AAC/B,SAAOA,SAAQ;AACnB;AAGA,IAAI;AACJ,IAAM,iBAAiB,MAA+B;AAClD,MAAI,eAAe,OAAW,QAAO;AACrC,MAAI;AACA,iBAAa,QAAQ,aAAa;AAAA,EACtC,QAAQ;AACJ,iBAAa;AAAA,EACjB;AACA,SAAO;AACX;AACA,IAAM,aAAa,MAAM;AACzB,IAAI,eAAe;AAMZ,IAAM,wBAAwB,MAAM;AACvC,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,eAAe;AAC9B,MAAI,WAAW,QAAQ,CAAC,cAAc;AAClC,mBAAe;AACf,YAAQ,KAAK,sGAAsG;AAAA,EACvH;AACA,QAAM,YAAY,QAAQ,eAAe,YAAY;AACrD,+BAAU,MAAM;AACZ,QAAI,SAAU,QAAO,OAAO,QAAQ;AAAA,EACxC,GAAG,CAAC,QAAQ,QAAQ,CAAC;AACzB;AAUO,IAAM,wBAAwB,MAAM;AACvC,QAAM,SAAS,UAAU;AACzB,aAAO;AAAA,IACH,CAAC,UAAmB;AAChB,YAAM,OAAO,gBAAgB,KAAK;AAClC,UAAI,KAAM,QAAO,OAAO,IAAI;AAAA,IAChC;AAAA,IACA,CAAC,MAAM;AAAA,EACX;AACJ;","names":["import_react","h","h","text","h","clip","options","text","h","RN","h","import_react","RN","text","h","r","RN","text"]}
|
|
1
|
+
{"version":3,"sources":["../../src/native/index.tsx","../../src/core.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/native/platform.ts","../../src/native/widgets-view.ts"],"sourcesContent":["/**\n * `@mrrocket/sdk/react-native`: the MRRocket SDK for React Native and Expo apps.\n *\n * // app/_layout.tsx (Expo Router)\n * import { MRRocketProvider, useExpoRouterTracking } from \"@mrrocket/sdk/react-native\";\n *\n * function Screens() {\n * useExpoRouterTracking();\n * return <Stack />;\n * }\n *\n * export default function RootLayout() {\n * return (\n * <MRRocketProvider apiKey=\"mrr_pub_…\">\n * <Screens />\n * </MRRocketProvider>\n * );\n * }\n *\n * No DOM, no \"use client\", no session recorder: Metro bundles it as is. See the README for what it sends.\n */\nimport { type ReactNode, createContext, createElement, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { type CockpitConfig, SDK_VERSION, type VariantId } from \"../core\";\nimport type { CancelFlowOptions, CancelFlowResult } from \"../flows\";\nimport { type KeyValueStorage, type MRRocketClient, type MRRocketOptions, activeRouteName, createClient } from \"./client\";\nimport { MRRocketFlows, type NativeAppearance } from \"./flows-view\";\nimport { nativeDeps, optionalModules } from \"./platform\";\nimport { type Measurable, maskedViews } from \"./recorder\";\nimport { MRRocketFeedback, MRRocketMessenger, MRRocketSurveys, type NativeFeedbackOptions, type NativeMessengerOptions, useFeedback, useMessenger } from \"./widgets-view\";\n\nexport type { AppContext, CockpitConfig, FlagConfig, VariantId } from \"../core\";\nexport type { CancelFlowConfig, CancelFlowOptions, CancelFlowResult, CancelOffer, FlowView, InAppMessage, OnboardingFlow, OnboardingStep, FlowMedia, TourPlacement } from \"../flows\";\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/** Starts an onboarding flow now (the first live one without an id), whatever its trigger. */\nexport const useOnboarding = (): { start: (id?: string) => boolean } => {\n const client = useClient();\n return { start: client.startOnboarding };\n};\n\n/** A feature flag from MRRocket › Build › Feature flags: true while it is on for this person; false while off, unknown or loading. */\nexport const useFlag = (key: string): boolean => {\n const client = useClient();\n useVersion(client);\n return client.getFlag(key);\n};\n\n/** The variant of a multivariate flag (\"control\", \"test\" …), or null while it is off. */\nexport const useFlagVariant = (key: string): string | null => {\n const client = useClient();\n useVersion(client);\n return client.getFlagVariant(key);\n};\n\n/**\n * The variant of an experiment this person sees (\"control\" until the config is known; the cached config is used on a\n * cold start, so the first screen is already stable). Records the exposure once per screen.\n */\nexport const useVariant = (key: string): VariantId => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const variant = client.peekVariant(key);\n useEffect(() => {\n if (config) client.expose(key, variant);\n }, [client, config, key, variant]);\n return variant;\n};\n\n/**\n * Copy MRRocket can change without an app update: the text published for `id` (a paywall's\n * `paywall.<placement>.headline`, `.body`, `.cta`), with this person's variant of a running text test on top,\n * the same rules as `<Text id>` on the web. Write your own words as `fallback`: they show while nothing is published\n * and on a first start before the config arrives. Records the exposure to every test that changes `id`, once per screen.\n *\n * const headline = useText(\"paywall.onboarding.headline\", \"Unlock everything\");\n * <Text style={styles.title}>{headline}</Text>\n */\nexport const useText = (id: string, fallback: string): string => {\n const client = useClient();\n useVersion(client);\n const config: CockpitConfig | null = client.getConfig();\n const text = client.peekText(id);\n const person = client.getDistinctId();\n useEffect(() => {\n if (config) client.exposeText(id);\n }, [client, config, id, person]);\n return text ?? fallback;\n};\n\ntype ExpoRouterModule = { usePathname: () => string };\nlet expoRouter: ExpoRouterModule | null | undefined;\nconst loadExpoRouter = (): ExpoRouterModule | null => {\n if (expoRouter !== undefined) return expoRouter;\n try {\n expoRouter = require(\"expo-router\") as ExpoRouterModule;\n } catch {\n expoRouter = null;\n }\n return expoRouter;\n};\nconst noPathname = () => undefined;\nlet routerWarned = false;\n\n/**\n * Screen views for Expo Router: one `$screen` per path (\"/settings\", \"/product/[id]\" as its real path). Call it in a\n * component inside both the router and MRRocketProvider, for example the root layout's child.\n */\nexport const useExpoRouterTracking = () => {\n const client = useClient();\n const router = loadExpoRouter();\n if (router === null && !routerWarned) {\n routerWarned = true;\n console.warn(\"[MRRocket] useExpoRouterTracking needs expo-router. With React Navigation use useNavigationTracking.\");\n }\n const pathname = (router?.usePathname ?? noPathname)();\n useEffect(() => {\n if (pathname) client.screen(pathname);\n }, [client, pathname]);\n};\n\n/**\n * Screen views for React Navigation: pass the result to the container's `onStateChange`, and call it once in `onReady`\n * with the root state, so the first screen counts too.\n *\n * const ref = useNavigationContainerRef();\n * const onStateChange = useNavigationTracking();\n * <NavigationContainer ref={ref} onReady={() => onStateChange(ref.getRootState())} onStateChange={onStateChange}>\n */\nexport const useNavigationTracking = () => {\n const client = useClient();\n return useCallback(\n (state: unknown) => {\n const name = activeRouteName(state);\n if (name) client.screen(name);\n },\n [client],\n );\n};\n","/**\n * The part of the SDK that runs anywhere: experiment config, variant assignment, preview links and event shapes.\n * No React, no browser APIs, so the server helper, the proxy helper and the client share it.\n */\nimport type { CancelFlowConfig, OnboardingFlow } from \"./flows\";\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.17.0\";\n\n/** One variant of an experiment. `changes` replaces texts that the page marks with `<Text id>`. */\nexport interface VariantConfig {\n id: VariantId;\n /** Share of traffic, 0 to 1. The weights of an experiment add up to 1. */\n weight: number;\n changes?: Record<string, string>;\n /**\n * A redirect test: where this variant sends the visitor instead of the test's page (a path like \"/pricing-b\" or a\n * full address). Control has none and stays. SDK 0.7.0+.\n */\n url?: string;\n}\n\nexport interface ExperimentConfig {\n /** The experiment's key, the same as in Cockpit. */\n key: string;\n status: \"running\" | \"draft\" | \"stopped\";\n /** Control first. */\n variants: VariantConfig[];\n /** A winner that shipped: everyone gets it, and nobody is assigned anymore. */\n winner?: VariantId;\n /** A redirect test: the path of the page it runs on (\"/pricing\"). Visitors there are sent to their variant's `url`. */\n path?: string;\n}\n\n/** A page redirect set in MRRocket (Conversion › Landing pages › Redirect): everyone on `from` goes to `to`. SDK 0.7.0+. */\nexport interface RedirectConfig {\n /** A path of the site, like \"/old-pricing\". */\n from: string;\n /** A path or a full address. */\n to: string;\n}\n\nexport interface CockpitConfig {\n /** The product the public key belongs to. */\n project: string;\n experiments: ExperimentConfig[];\n /** The product's affiliate program: how many days a partner's referral is kept. Missing without a program. */\n referral?: { cookieDays: number };\n /** Session recordings: present only while the product records (Cockpit › Sessions). See `ReplayConfig`. */\n replay?: ReplayConfig;\n /** Feature flags of the product in Production (MRRocket › Build › Feature flags), evaluated by `useFlag` and `getFlag`. */\n flags?: FlagConfig[];\n /**\n * Published copy for texts the site marks (`<Text id>`, `data-ck-text`): a landing page's headline, subheadline and\n * button (`pricing.headline` …) and a paywall's (`paywall.<placement>.headline` …) as published in MRRocket. A\n * running test's variant changes them on top. Missing when nothing is published. SDK 0.5.0+.\n */\n texts?: Record<string, string>;\n /** The product's live cancel flow (MRRocket › Churn › Cancel flow), for `cancelFlow.open()`. SDK 0.7.0+. */\n cancelFlow?: CancelFlowConfig;\n /** The in-app steps of live onboarding flows (tours, checklists, modals). SDK 0.7.0+. */\n onboarding?: OnboardingFlow[];\n /** A live Lifecycle journey has in-app messages: signed-in people ask `/api/sdk/inapp` for theirs. SDK 0.7.0+. */\n messages?: boolean;\n /** Page redirects set in MRRocket; the SDK sends visitors on before the page shows (`redirectFor`). SDK 0.7.0+. */\n redirects?: RedirectConfig[];\n /** 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 * 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.\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\nexport type OnboardingStepKind = \"tour\" | \"checklist\" | \"modal\";\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}\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 /** 0.17.0: \"signed_in\" starts it on its own only for someone the app identified. */\n audience?: \"signed_in\";\n /** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */\n steps: OnboardingStep[];\n /** 0.11.0+: the whole flow with its waits and conditions. Read instead of `steps` when it is there. */\n nodes?: OnboardingNode[];\n}\n\n/** An in-app message a Lifecycle journey has for this person. */\nexport interface InAppMessage {\n id: string;\n journey?: string;\n title: string;\n body?: string;\n button?: string;\n /** Where the button goes (http(s) or a path of the app). */\n url?: string;\n style: \"banner\" | \"modal\";\n}\n\n/** One flow's progress: the steps done, whether the person closed it, and (0.11.0) its decided conditions and times. */\nexport interface FlowProgress {\n done: string[];\n dismissed?: boolean;\n /** Each decided condition's path. */\n answers?: Record<string, \"yes\" | \"no\">;\n /** When each step was done and each wait was reached (ms since 1970). */\n at?: Record<string, number>;\n reached?: Record<string, number>;\n}\n\n/** What `GET /api/sdk/inapp` answers for one signed-in person. */\nexport interface InAppState {\n /** Progress per onboarding flow: the steps done and whether the person closed it. */\n onboarding: Record<string, FlowProgress>;\n messages: InAppMessage[];\n /** 0.11.0: the events the flows' conditions ask about that this person did (as `eventSlug`s). */\n events?: string[];\n /**\n * 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 | { type: \"step\"; flow: OnboardingFlow; step: OnboardingStep; index: number; total: number; last: boolean }\n /** `tour`: the tour the item starts (0.17.0), when the config has it. */\n | { type: \"checklist\"; flow: OnboardingFlow; items: { step: OnboardingStep; done: boolean; tour?: 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 /** 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 /** `startTour(stepId)` (0.17.0): the tour a checklist item starts; the checklist comes back when it ends. */\n onboarding: { next(): void; check(stepId: string): void; dismiss(): void; startTour(stepId: string): boolean };\n message: { click(): void; dismiss(): void };\n}\n\n/** The plain confirmation, when the product has no live cancel flow (or MRRocket was not reachable). */\nexport const PLAIN_CANCEL: CancelFlowConfig = {\n version: 0,\n question: \"\",\n reasons: [],\n offers: {},\n confirm: { title: \"Cancel your subscription?\", body: \"You keep access until the end of the billing period.\", button: \"Cancel subscription\" },\n offersFor: \"business\",\n};\n\nconst FAILED = \"Something went wrong. Please try again.\";\nconst PROGRESS_KEY = \"mrrocket:onboarding\";\n\n/** `\"Signed up\"` → `signed_up`, the way MRRocket names events from words. */\nexport const eventSlug = (s: string) =>\n s\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst SIGNUP = new Set([\"signed_up\", \"signup\", \"sign_up\", \"registered\", \"account_created\", \"user_signed_up\"]);\n\n/** Whether recording `event` is the trigger's moment (\"Signed up\" is any of the usual signup event names). */\nexport const matchesTrigger = (trigger: string, event: string) => {\n const t = eventSlug(trigger);\n const e = eventSlug(event);\n if (!t || !e) return false;\n return t === e || (SIGNUP.has(t) && SIGNUP.has(e));\n};\n\n/** Triggers that mean \"the first time the person opens the app\": the flow starts on load until it is done. */\nexport const startsOnLoad = (trigger: string) =>\n /^(first (launch|visit|open|session|login|sign ?in|app open)|app (opened|launched)|on load|every visit|always)?$/i.test(trigger.trim());\n\n/** 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/** A \"From a checklist\" tour never starts on its own. */\nconst manual = (trigger: string) => eventSlug(trigger) === \"from_a_checklist\";\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\n const flows = () => config?.onboarding ?? [];\n const flowById = (id: string | null) => (id ? flows().find((f) => f.id === id) : undefined);\n const prog = (id: string) => {\n let p = progress.get(id);\n if (!p) progress.set(id, (p = { done: new Set(), dismissed: false, answers: new Map(), at: new Map(), reached: new Map() }));\n return p;\n };\n\n let dirty = false;\n const record = (props: Record<string, unknown>) => {\n env.track(ONBOARDING_EVENT, props);\n dirty = true;\n };\n const markDone = (p: Progress, id: string) => {\n p.done.add(id);\n p.at.set(id, now());\n };\n\n /** A condition's answer for this person, or undefined while what it asks is not known yet. */\n const decide = (c: OnboardingCondition): boolean | undefined => {\n if (c.page?.trim()) {\n const path = env.path?.();\n return path === undefined ? false : pageMatches(c.page, path);\n }\n if (c.event?.trim()) {\n // The person's events from MRRocket arrive with their progress: before that, wait.\n if (!known) return undefined;\n for (const e of seenEvents) if (matchesTrigger(c.event, e)) return true;\n return false;\n }\n return false;\n };\n\n /**\n * Where the person is in a line of the flow. `live`: it is their flow now, so reaching a wait starts it, a decided\n * condition is kept and both are recorded; otherwise nothing changes (to ask whether a flow is finished).\n */\n const walkLine = (flow: OnboardingFlow, line: OnboardingNode[], p: Progress, live: boolean, before = 0, last?: number): Walked => {\n for (let i = 0; i < line.length; i++) {\n const n = line[i];\n if (n.kind === \"wait\") {\n if (p.done.has(n.id)) {\n last = p.at.get(n.id) ?? last;\n continue;\n }\n let since = p.reached.get(n.id);\n if (since === undefined) {\n if (!live) return { at: \"pending\" };\n // Counted from when the step before was done; a flow that opens with a wait counts from now.\n since = last ?? now();\n p.reached.set(n.id, since);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"shown\" });\n }\n const until = since + waitMs(n);\n if (now() < until) return { at: \"wait\", until };\n if (!live) return { at: \"pending\" };\n markDone(p, n.id);\n record({ flow: flow.id, step: n.id, kind: \"wait\", action: \"completed\" });\n last = until;\n continue;\n }\n if (n.kind === \"condition\") {\n let answer = p.answers.get(n.id);\n if (answer === undefined) {\n if (!live) return { at: \"pending\" };\n answer = decide(n);\n if (answer === undefined) return { at: \"pending\" };\n p.answers.set(n.id, answer);\n record({ flow: flow.id, step: n.id, kind: \"condition\", action: \"answered\", answer: answer ? \"yes\" : \"no\" });\n }\n return walkLine(flow, answer ? n.yes : n.no, p, live, before, last);\n }\n if (!p.done.has(n.id)) return { at: \"step\", step: n, line, index: i, before };\n last = p.at.get(n.id) ?? last;\n before++;\n }\n return { at: \"end\" };\n };\n\n const finished = (f: OnboardingFlow) => {\n const p = progress.get(f.id);\n return !!p && (p.dismissed || walkLine(f, nodesOf(f), p, false).at === \"end\");\n };\n\n const keyOf = (pid: string | undefined) => `${PROGRESS_KEY}:${pid ?? \"visitor\"}`;\n const eventsKeyOf = (pid: string | undefined) => `${PROGRESS_KEY}:events:${pid ?? \"visitor\"}`;\n\n const save = () => {\n dirty = false;\n const store = env.storage?.();\n if (!store) return;\n const out: Record<string, FlowProgress> = {};\n for (const [id, p] of progress)\n out[id] = {\n done: [...p.done],\n ...(p.dismissed ? { dismissed: true } : {}),\n ...(p.answers.size ? { answers: Object.fromEntries([...p.answers].map(([k, v]) => [k, v ? \"yes\" : \"no\"])) } : {}),\n ...(p.at.size ? { at: Object.fromEntries(p.at) } : {}),\n ...(p.reached.size ? { reached: Object.fromEntries(p.reached) } : {}),\n };\n try {\n store.set(keyOf(env.personId()), JSON.stringify(out));\n if (seenEvents.size) store.set(eventsKeyOf(env.personId()), JSON.stringify([...seenEvents].slice(-200)));\n } catch {\n // Storage full or gone: progress stays in memory.\n }\n };\n\n const merge = (state: InAppState[\"onboarding\"] | undefined) => {\n for (const [id, s] of Object.entries(state ?? {})) {\n const p = prog(id);\n for (const d of s.done ?? []) p.done.add(d);\n if (s.dismissed) p.dismissed = true;\n // A condition decided elsewhere keeps its path; the earliest time wins for waits.\n for (const [k, v] of Object.entries(s.answers ?? {})) if (!p.answers.has(k)) p.answers.set(k, v === \"yes\");\n for (const [k, v] of Object.entries(s.at ?? {})) if (typeof v === \"number\" && !p.at.has(k)) p.at.set(k, v);\n for (const [k, v] of Object.entries(s.reached ?? {})) if (typeof v === \"number\" && (!p.reached.has(k) || v < p.reached.get(k)!)) p.reached.set(k, v);\n }\n };\n\n // ---------- What shows ----------\n\n /** Comes back when a short wait is over, so the next step shows without a reload (long waits wait for the next visit). */\n const wakeAt = (until: number) => {\n if (timer) clearTimeout(timer);\n timer = null;\n const ms = until - now();\n if (ms > 0 && ms <= 86_400_000) {\n timer = setTimeout(() => ((timer = null), emit()), ms + 50);\n // Never what keeps a process alive (tests, server rendering).\n (timer as { unref?: () => void }).unref?.();\n }\n };\n\n /** The active flow waits (a wait step, or a condition whose answer is not known yet): it stays the active one. */\n let holding = false;\n\n const onboardingView = (): FlowView | null => {\n holding = false;\n const flow = flowById(active);\n if (!flow) return null;\n const p = prog(flow.id);\n if (p.dismissed) return null;\n const w = walkLine(flow, nodesOf(flow), p, true);\n if (dirty) save();\n if (w.at === \"wait\") wakeAt(w.until);\n holding = w.at === \"wait\" || w.at === \"pending\";\n if (w.at !== \"step\") return null;\n const { step, line, index } = w;\n const isStep = (n: OnboardingNode | undefined): n is OnboardingStep => !!n && n.kind !== \"wait\" && n.kind !== \"condition\";\n if (step.kind === \"checklist\") {\n let from = index;\n while (from > 0 && isStep(line[from - 1]) && line[from - 1].kind === \"checklist\") from--;\n let to = index;\n while (to + 1 < line.length && isStep(line[to + 1]) && line[to + 1].kind === \"checklist\") to++;\n const items = line.slice(from, to + 1).filter(isStep);\n for (const i of items)\n if (!p.done.has(i.id) && !shown.has(`s:${i.id}`)) {\n shown.add(`s:${i.id}`);\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: i.id, kind: \"checklist\", action: \"shown\" });\n }\n return {\n type: \"checklist\",\n flow,\n items: items.map((s) => {\n const tour = s.startsTour && s.startsTour !== flow.id ? flowById(s.startsTour) : undefined;\n return { step: s, done: p.done.has(s.id), ...(tour && nodesOf(tour).length ? { tour } : {}) };\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 { type: \"step\", flow, step, index: w.before, total: w.before + 1 + ahead, last: !ahead && fork < 0 };\n };\n\n const view = (): FlowView | null => {\n if (cancel) {\n const 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 }\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 after = flowById(ended)?.trigger;\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 /** 0.17.0: a flow for signed-in people starts on its own only for someone the app identified. */\n const allowed = (f: OnboardingFlow) => f.audience !== \"signed_in\" || !!env.personId();\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 = flows().find(\n (f) =>\n (isPageTrigger(f.trigger) ? path !== undefined && pageMatches(f.trigger, path) : startsOnLoad(f.trigger) || (!!same && eventSlug(f.trigger) === same)) &&\n allowed(f) &&\n nodesOf(f).length &&\n !finished(f),\n );\n if (next) start(next);\n };\n\n const refresh = () => {\n const pid = env.personId();\n // Another person on this device: nothing of the one before carries over.\n if (progressFor !== null && progressFor !== pid) {\n progress.clear();\n seenEvents.clear();\n handled.clear();\n active = null;\n 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 } catch {\n // A damaged entry is ignored.\n }\n }\n const wants = flows().length > 0 || !!config?.messages;\n if (pid && wants && loadedFor !== pid) {\n loadedFor = pid;\n const state = await env.fetchInApp(pid).catch(() => null);\n if (state && env.personId() === pid) {\n merge(state.onboarding);\n for (const e of state.events ?? []) if (typeof e === \"string\") seenEvents.add(eventSlug(e));\n messages = (state.messages ?? []).filter((m) => m && m.id && m.title);\n }\n }\n if (!pid) messages = [];\n known = true;\n autoStart();\n emit();\n })();\n loading = run.finally(() => {\n if (loading === run) loading = null;\n });\n return loading;\n };\n\n // ---------- Cancel flow ----------\n\n /** 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 if (flow) {\n const p = prog(flow.id);\n for (const s of stepsIn(nodesOf(flow)))\n if (s.kind === \"checklist\" && s.event && !p.done.has(s.id) && matchesTrigger(s.event, name)) {\n markDone(p, s.id);\n ticked = true;\n env.track(ONBOARDING_EVENT, { flow: flow.id, step: s.id, kind: s.kind, action: \"completed\" });\n }\n }\n if (ticked || (fresh && flow)) {\n save();\n emit();\n } else if (fresh) save();\n // Like the first-launch start: only for someone whose progress is kept, so nobody gets a flow twice.\n if (!auto || (!env.personId() && !env.storage?.())) return;\n const next = flows().find((f) => nodesOf(f).length && !manual(f.trigger) && matchesTrigger(f.trigger, name) && allowed(f) && !finished(f));\n if (next) start(next);\n },\n openCancelFlow,\n startOnboarding: (id) => {\n const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !manual(x.trigger) && !finished(x));\n if (!f || !nodesOf(f).length) return false;\n const p = prog(f.id);\n // Started by hand: a flow the person closed before shows again.\n p.dismissed = false;\n return start(f);\n },\n view,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n cancel: {\n pick: (reason) => {\n if (!cancel || cancel.busy || cancel.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 markDone(prog(v.flow.id), v.step.id);\n env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: \"completed\" });\n save();\n emit();\n // 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 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 tour = v.items.find((i) => i.step.id === stepId)?.tour;\n if (!tour) return false;\n // Started by hand: from its first step, also when the person saw or closed it before.\n const p = prog(tour.id);\n p.done.clear();\n p.at.clear();\n p.dismissed = false;\n returnTo = { flow: v.flow.id, step: stepId };\n active = tour.id;\n env.track(ONBOARDING_EVENT, { flow: tour.id, action: \"started\", from: v.flow.id });\n save();\n emit();\n return true;\n },\n },\n message: {\n click: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"clicked\" });\n const url = safeUrl(v.message.url);\n emit();\n if (url) env.openUrl?.(url);\n },\n dismiss: () => {\n const v = view();\n if (v?.type !== \"message\") return;\n handled.add(v.message.id);\n env.track(INAPP_EVENT, { message: v.message.id, journey: v.message.journey, action: \"dismissed\" });\n emit();\n },\n },\n };\n return controller;\n};\n","/**\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, 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 /** 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 });\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 */\nimport { type ReactNode, createElement as h, useEffect, useState } from \"react\";\nimport { type FlowsController, type OnboardingStep, discounted, mediaOf, money, offerButton, videoEmbed } from \"../flows\";\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}\nconst RN = require(\"react-native\") as RNModule;\n\nexport interface NativeAppearance {\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n}\n\ninterface Palette {\n accent: string;\n bg: string;\n fg: string;\n muted: string;\n soft: string;\n line: string;\n danger: string;\n}\n\nexport const LIGHT = { bg: \"#ffffff\", fg: \"#1c1d20\", muted: \"#5d6068\", soft: \"#f4f5f7\", line: \"#e4e5e8\" };\nexport const DARK = { bg: \"#17181b\", fg: \"#f1f2f4\", muted: \"#a9acb3\", soft: \"#232428\", line: \"#2e2f35\" };\n\nconst months = (n: number) => `${n} ${n === 1 ? \"month\" : \"months\"}`;\n\nexport const MRRocketFlows = ({ flows, 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 const p: Palette = { ...(dark ? DARK : LIGHT), accent: appearance.accent ?? \"#3f76ff\", danger: \"#d92d20\" };\n // Re-render on every change of the controller.\n const [, setTick] = useState(0);\n useEffect(() => flows.subscribe(() => setTick((t) => t + 1)), [flows]);\n 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\")\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 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, tour }) =>\n h(\n RN.Pressable,\n {\n key: step.id,\n // 0.17.0: an item that starts a tour opens it; finishing the tour ticks it.\n disabled: d || (!!step.event && !tour),\n onPress: () => (tour ? flows.onboarding.startTour(step.id) : flows.onboarding.check(step.id)),\n accessibilityRole: tour && !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 h(\n RN.View,\n { style: { flex: 1 } },\n text(step.title, { fontWeight: \"600\", color: d ? p.muted : p.fg, textDecorationLine: d ? \"line-through\" : \"none\" }),\n step.body ? muted(step.body) : null,\n ),\n ),\n ),\n ]),\n );\n }\n\n const m = v.message;\n if (m.style === \"banner\")\n return h(\n RN.View,\n { pointerEvents: \"box-none\", style: { position: \"absolute\", left: 12, right: 12, top: 56 } },\n card([\n h(\n RN.View,\n { key: \"t\", style: { flexDirection: \"row\", alignItems: \"center\", gap: 8 } },\n h(RN.View, { style: { flex: 1 } }, text(m.title, { fontWeight: \"700\" }), m.body ? muted(m.body) : null),\n close(\"Dismiss\", flows.message.dismiss),\n ),\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ]),\n );\n return sheet(\n [\n h(RN.View, { key: \"t\", style: { flexDirection: \"row\" } }, close(\"Dismiss\", flows.message.dismiss)),\n title(m.title),\n m.body ? muted(m.body, { fontSize: 15 }) : null,\n m.button ? btn(m.button, \"primary\", flows.message.click) : null,\n ],\n flows.message.dismiss,\n );\n};\n","/**\n * The real platform for the React Native client: React Native itself, plus optional modules the app may have installed.\n * Each optional `require` sits directly in its own `try` block: that is how Metro knows the module is optional and\n * bundles the app without it when it is not installed (and how the CommonJS build keeps the call literal).\n *\n * - `@react-native-async-storage/async-storage`: the offline queue, the install id (\"persistent\" consent), the cached\n * config and the first-open marker. Without it everything stays in memory for the app's run.\n * - `expo-device`, `expo-application`, `expo-localization`: model, OS version, app version and build, locale.\n * Without them the SDK falls back to what React Native knows (platform, OS version, the JS locale).\n * - `expo-notifications` (with `expo-constants` for the EAS project id): push notifications, `registerForPush()`.\n * Without it `registerForPush` answers \"unavailable\".\n * - `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 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 ? \"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 bubble({ id: \"greeting\", from: \"team\", body: greeting, at: \"\" }),\n !chat.loaded ? k.muted(\"Loading…\") : null,\n ...(thread?.messages ?? []).map((m) => bubble(m)),\n pending ? bubble(pending, true) : null,\n thread?.conversation?.status === \"solved\" && !pending ? k.muted(\"This conversation is closed. Write to start a new one.\", { textAlign: \"center\" }) : null,\n ),\n h(\n RN.View,\n { style: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 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","same","who","text","h","clip","who","options","text","h","m","v","RN","h","import_react","RN","text","h","who","r","RN","text"]}
|