@guidelytech/react-native 0.14.0 → 0.15.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/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/flags.tsx","../../shared/src/utils.ts","../../shared/src/platform.ts","../../shared/src/widgets.ts","../../shared/src/targeting-eval.ts","../../shared/src/contrast.ts","../../shared/src/events-util.ts","../../shared/src/errors.ts","../../shared/src/complaints-limits.ts","../../shared/src/agents-limits.ts","../../shared/src/network.ts","../../shared/src/media.ts","../../shared/src/resource-center.ts","../../shared/src/howto-limits.ts","../../shared/src/page.ts","../../shared/src/tagging.ts","../../shared/src/localization.ts","../../shared/src/guide-experiments.ts","../../shared/src/custom-css.ts","../../sdk-core/src/health.ts","../../sdk-core/src/http.ts","../../sdk-core/src/storage.ts","../../sdk-core/src/queue.ts","../../sdk-core/src/outbox.ts","../../sdk-core/src/emitter.ts","../../sdk-core/src/frequency.ts","../src/core/client.ts","../src/core/launcherPlacement.ts","../src/core/autocapture.ts","../src/core/targets.ts","../src/core/controller.ts","../src/core/messenger.ts","../src/core/replay.ts","../src/core/storage.ts","../src/core/device.ts","../src/ui/Autocapture.tsx","../src/core/viewTree.ts","../src/ui/Overlay.tsx","../src/ui/Checklist.tsx","../src/ui/primitives.tsx","../src/ui/RichText.tsx","../src/core/html.ts","../src/ui/Messenger.tsx","../src/ui/ResourceCenter.tsx","../src/ui/StepLayer.tsx","../src/core/position.ts","../src/ui/StepCard.tsx","../src/ui/Survey.tsx","../src/ui/theme.ts","../src/ui/Target.tsx"],"sourcesContent":["/**\n * @guidelytech/react-native — Guidely guides, checklists, surveys and resource center for React\n * Native and Expo apps, rendered with native components.\n *\n * ```tsx\n * <GuidelyProvider projectId=\"pk_prod_…\" apiUrl=\"https://guidelytech.com\" storage={AsyncStorage}>\n * <App />\n * </GuidelyProvider>\n * ```\n */\nimport { useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { AppState, Dimensions, Linking, NativeModules, Platform, StyleSheet, View, type ViewProps } from \"react-native\";\nimport type { PublishedGuide } from \"@guidelytech/shared\";\nimport { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\nimport { GuidelyClient, type PlatformBridge } from \"./core/client\";\nimport { detectAppVersion, detectOsVersion, type NativeSources } from \"./core/device\";\nimport type { Insets } from \"./core/position\";\nimport type { ReplayCaptureOptions, ReplayFrame, ScreenCapturer } from \"./core/replay\";\nimport type { ChecklistProgressState, GuidelyAccount, GuidelyEvents, GuidelyOptions, GuidelyUser } from \"./core/types\";\nimport { useTapObserver } from \"./ui/Autocapture\";\nimport { GuidelyOverlay } from \"./ui/Overlay\";\nimport { GuidelyContext } from \"./ui/Target\";\n\nexport { GuidelyClient, SDK_NAME, SDK_VERSION, DEFAULT_API_URL } from \"./core/client\";\nexport type { PlatformBridge } from \"./core/client\";\nexport { detectAppVersion, detectOsVersion } from \"./core/device\";\nexport type { AppVersionInfo, NativeSources } from \"./core/device\";\nexport { GuidelyTarget, useGuidelyTarget, GuidelyScreenScope, guidelyScreenLayout } from \"./ui/Target\";\nexport type { GuidelyTargetProps } from \"./ui/Target\";\nexport { GuidelyOverlay } from \"./ui/Overlay\";\nexport { GuidelyMask } from \"./ui/Autocapture\";\nexport type { GuidelyMaskProps } from \"./ui/Autocapture\";\nexport { RageClickDetector, HeatmapBuffer, TapTracker } from \"./core/autocapture\";\nexport type { AutocaptureOption, TapElement, TapInfo, TapProperties } from \"./core/autocapture\";\nexport type { AutocaptureSettings, HeatmapPoint } from \"@guidelytech/shared\";\nexport { TargetRegistry, targetIdsFor } from \"./core/targets\";\nexport { parseHtml, htmlToText } from \"./core/html\";\nexport { positionCard } from \"./core/position\";\nexport { Messenger, createSseParser } from \"./core/messenger\";\nexport type { MessengerTab, MessengerView, MessengerSnapshot, MessengerThread } from \"./core/messenger\";\nexport type { Insets } from \"./core/position\";\nexport { ReplayUploader, SessionRecorder, RrwebEvents } from \"./core/replay\";\nexport type { ReplayFrame, ReplayCaptureOptions, ScreenCapturer, TouchPhase } from \"./core/replay\";\nexport type * from \"./core/types\";\nexport type { PublishedGuide, SdkConfigResponse, GuideStep } from \"@guidelytech/shared\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport { createFlagsClient, InMemoryStickyBucketStore } from \"@guidelytech/flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nfunction deviceLocale(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale;\n } catch {\n return undefined;\n }\n}\n\nfunction nativeSources(): NativeSources {\n return {\n platform: Platform as NativeSources[\"platform\"],\n nativeModules: NativeModules as Record<string, unknown>,\n expoModules: (globalThis as { expo?: { modules?: Record<string, unknown> } }).expo?.modules,\n };\n}\n\nfunction defaultBridge(appVersion?: string, appBuild?: string): PlatformBridge {\n const { width, height } = Dimensions.get(\"window\");\n const sources = nativeSources();\n // The app's own values win; a detected build only goes with a detected version.\n const detected = appVersion ? {} : detectAppVersion(sources);\n return {\n device: {\n platform: Platform.OS === \"android\" ? \"android\" : \"ios\",\n deviceType: (Platform.OS === \"ios\" && Platform.isPad) || Math.min(width, height) >= 600 ? \"tablet\" : \"mobile\",\n locale: deviceLocale(),\n appVersion: appVersion ?? detected.appVersion,\n appBuild: appBuild ?? detected.appBuild,\n osVersion: detectOsVersion(sources),\n },\n openExternal: (url) => void Linking.openURL(url).catch(() => {}),\n windowSize: () => Dimensions.get(\"window\"),\n capturer: nativeCapturer(),\n };\n}\n\ninterface NativeReplayModule {\n capture(options: ReplayCaptureOptions): Promise<ReplayFrame | null>;\n}\n\n/** Screenshots from `@guidelytech/react-native-replay` when the app has it installed (looked up, never imported). */\nfunction nativeCapturer(): ScreenCapturer | undefined {\n const mod = (NativeModules as { GuidelyReplay?: NativeReplayModule }).GuidelyReplay;\n if (!mod || typeof mod.capture !== \"function\") return undefined;\n return (options) => mod.capture(options);\n}\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user once the client is ready; changing to `null` resets the identity (logout). */\n user?: GuidelyUser | null;\n /** Safe-area insets for banners, launchers and sheets. Pass `useSafeAreaInsets()` from react-native-safe-area-context for exact values. */\n insets?: Partial<Insets>;\n /** How far above the bottom inset the checklist launcher sits, to clear tab bars (default 72). */\n launcherOffset?: number;\n /** Flags bootstrap (a payload or remote results) served until the client has loaded. */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, screen and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/**\n * Creates one Guidely client for the app and renders guide UI above `children`. Place it at the\n * root of the app (outside navigators) so the overlay covers every screen.\n */\nexport function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl, storage } = options;\n\n useEffect(() => {\n if (!projectId) return;\n let c: GuidelyClient;\n try {\n // Callbacks read the latest props so re-renders never need a new client.\n const latest = optionsRef.current;\n c = new GuidelyClient(\n {\n ...latest,\n projectId,\n environment,\n apiUrl,\n storage,\n // Known up front so flags evaluate for this user from the first render.\n user: userRef.current?.id ? userRef.current : undefined,\n flags: latest.flags === false ? false : { ...(latest.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current },\n onNavigate: (url) => optionsRef.current.onNavigate?.(url),\n onError: (err) => optionsRef.current.onError?.(err),\n },\n defaultBridge(latest.appVersion, latest.appBuild),\n );\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setClient(c);\n void c.init();\n const sub = AppState.addEventListener(\"change\", (s) => c.setAppState(s));\n return () => {\n sub.remove();\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl, storage]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n // A changed `locale` prop switches the language without a new client.\n useEffect(() => {\n client?.setLocale(options.locale ?? null);\n }, [client, options.locale]);\n\n const bootstrap = useBootstrap(payload, { ...(user?.id ? { ...(user.traits ?? {}), id: user.id } : {}), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n const tapObserver = useTapObserver(client);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>\n {/* Taps (and replay touches) are observed on a wrapper around the app only, so Guidely's own UI (a sibling) is never captured. */}\n {options.autocapture === false && !options.sessionReplay?.enabled ? (\n children\n ) : (\n <View style={styles.root} {...(tapObserver as ViewProps)}>\n {children}\n </View>\n )}\n {client ? <GuidelyOverlay client={client} insets={insets} launcherOffset={launcherOffset} /> : null}\n </FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst styles = StyleSheet.create({ root: { flex: 1 } });\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n getGuideState: { impressions: 0 },\n getMessenger: null,\n isGuideCompleted: false,\n isClientReady: false,\n isRecording: false,\n isRecordingTouches: false,\n getSessionId: \"\",\n getScreen: \"\",\n on: () => {},\n subscribeUi: () => () => {},\n getState: { ready: false, destroyed: false },\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` before the provider has created one. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client (a no-op stand-in until the provider has created it). */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once config is loaded and triggers have been evaluated. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(() => !!client?.isClientReady());\n useEffect(() => {\n if (!client) return setReady(false);\n setReady(client.isClientReady());\n const off = client.on(\"ready\", () => setReady(true));\n void client.ready().then(() => setReady(client.isClientReady()));\n return off;\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the id or traits change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyAccount): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (client && userId) void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a Guidely event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n return client.on(event, ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K]);\n }, [client, event]);\n}\n\n/** Records a screen view while the component is mounted (and when `name` changes). */\nexport function useGuidelyScreen(name: string | null | undefined, properties?: Record<string, unknown>): void {\n const client = useContext(GuidelyContext);\n useEffect(() => {\n if (client && name) client.screen(name, properties);\n }, [client, name]);\n}\n\ninterface NavigationRefLike {\n getCurrentRoute(): { name: string } | undefined | null;\n}\n\n/**\n * React Navigation integration: spread the result on `<NavigationContainer>` and every route\n * change becomes a Guidely screen view named after the route.\n *\n * ```tsx\n * const ref = useNavigationContainerRef();\n * <NavigationContainer ref={ref} {...useGuidelyNavigation(ref)}>\n * ```\n */\nexport function useGuidelyNavigation(navigationRef: NavigationRefLike, options: { screenName?: (route: { name: string }) => string } = {}) {\n const client = useContext(GuidelyContext);\n const nameRef = useRef(options.screenName);\n nameRef.current = options.screenName;\n const report = () => {\n const route = navigationRef.getCurrentRoute?.();\n if (client && route?.name) client.screen(nameRef.current ? nameRef.current(route) : route.name);\n };\n // The client may arrive after the navigator is ready: report the current route then.\n useEffect(report, [client]);\n return { onReady: report, onStateChange: report };\n}\n\nfunction useUiSelector<T>(select: (c: GuidelyClient) => T, fallback: T): T {\n const client = useContext(GuidelyContext);\n const selectRef = useRef(select);\n selectRef.current = select;\n const [value, setValue] = useState<T>(() => (client ? select(client) : fallback));\n useEffect(() => {\n if (!client) return;\n let last = JSON.stringify(selectRef.current(client));\n setValue(selectRef.current(client));\n const update = () => {\n const next = selectRef.current(client);\n const key = JSON.stringify(next);\n if (key !== last) {\n last = key;\n setValue(next);\n }\n };\n const offs = [client.subscribeUi(update), client.on(\"checklist:task\", update), client.on(\"identify\", update), client.on(\"guide:complete\", update), client.on(\"guide:dismiss\", update), client.on(\"ready\", update)];\n return () => offs.forEach((off) => off());\n }, [client]);\n return value;\n}\n\n/** Live progress of a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n return useUiSelector((c) => c.getChecklistProgress(idOrKey), { completedTaskIds: [], completedAt: null, dismissedAt: null });\n}\n\n/** Live impressions / completion / dismissal of a guide (by id or key). */\nexport function useGuideState(idOrKey: string): { impressions: number; completed: boolean; dismissed: boolean } {\n return useUiSelector(\n (c) => {\n const s = c.getGuideState(idOrKey);\n return { impressions: s.impressions, completed: !!s.completedAt, dismissed: !!s.dismissedAt };\n },\n { impressions: 0, completed: false, dismissed: false },\n );\n}\n\n/** The guide currently running exclusively (flow, modal, survey…), or null. */\nexport function useActiveGuide(): PublishedGuide | null {\n return useUiSelector((c) => c.getActiveGuide(), null);\n}\n","/** Feature-flag hooks and components for React Native (same API as `@guidelytech/react`). */\nimport { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\nimport { AppState } from \"react-native\";\n\n/** What the flag hooks read: the live client once created, else a snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const src = useContext(FlagsContext);\n const reader = src?.client ?? src?.bootstrap ?? EMPTY;\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (bootstrap, storage or network) or failed to and serve fallbacks. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot of a bootstrap payload, rebuilt only when it or the attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap payload (or remote results) used until the client has loaded. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Pass AsyncStorage as `storage` so the last flags\n * serve offline at cold start. Refreshes when the app returns to the foreground.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" apiUrl=\"https://guidelytech.com\" storage={AsyncStorage} attributes={{ id: user.id }}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n\n useEffect(() => {\n if (external || !sdkKey) return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n const sub = AppState.addEventListener(\"change\", (s) => {\n if (s === \"active\") void c.refresh();\n else if (s === \"background\") void c.flush();\n });\n return () => {\n sub.remove();\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n","/** FNV-1a 32-bit hash; deterministic across SDK and server for rollout bucketing. */\nexport function fnv1a(input: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h >>> 0;\n}\n\n/** Deterministic 0-99 bucket for percentage rollouts. */\nexport function rolloutBucket(subject: string, salt: string): number {\n return fnv1a(`${salt}:${subject}`) % 100;\n}\n\nexport function slugify(input: string): string {\n return input\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64) || \"untitled\";\n}\n\nconst ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n/** URL-safe random id. Uses crypto when available, falls back to Math.random (ids are not secrets). */\nexport function randomId(size = 16): string {\n const g: any = typeof globalThis !== \"undefined\" ? globalThis : {};\n let bytes: Uint8Array;\n if (g.crypto && typeof g.crypto.getRandomValues === \"function\") {\n bytes = new Uint8Array(size);\n g.crypto.getRandomValues(bytes);\n } else {\n bytes = new Uint8Array(size);\n for (let i = 0; i < size; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n let out = \"\";\n for (let i = 0; i < size; i++) out += ALPHABET[(bytes[i] as number) % ALPHABET.length];\n return out;\n}\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Safe nested getter: get(obj, \"account.plan\") */\nexport function getPath(obj: unknown, path: string): unknown {\n if (!path) return obj;\n let cur: any = obj;\n for (const part of path.split(\".\")) {\n if (cur == null) return undefined;\n cur = cur[part];\n }\n return cur;\n}\n\nexport function clamp(n: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, n));\n}\n\n/** Glob-style URL pattern match: `*` matches any chars except `/`, `**` matches anything. */\nexport function matchUrlPattern(pattern: string, url: string): boolean {\n if (!pattern) return true;\n if (pattern === url) return true;\n const escaped = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"__GLOBSTAR__\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/__GLOBSTAR__/g, \".*\");\n const re = new RegExp(`^${escaped}$`);\n return re.test(url) || re.test(stripOrigin(url));\n}\n\nexport function stripOrigin(url: string): string {\n try {\n const u = new URL(url);\n return u.pathname + u.search + u.hash;\n } catch {\n return url;\n }\n}\n\n/** Safe regexp construction with a length cap to limit ReDoS exposure. */\nexport function safeRegExp(source: string, flags = \"i\"): RegExp | null {\n if (!source || source.length > 200) return null;\n try {\n return new RegExp(source, flags);\n } catch {\n return null;\n }\n}\n","/**\n * Cross-platform helpers shared by the web SDK, the React Native SDK and (as a reference for) the\n * native iOS/Android SDKs. Zod-free so it can ship in runtime bundles.\n */\n\n/** Platforms a guide can be delivered to. */\nexport const PLATFORMS = [\"web\", \"ios\", \"android\"] as const;\nexport type Platform = (typeof PLATFORMS)[number];\n\n/** Guides published before platforms existed have no `platforms` field and are web-only. */\nexport const DEFAULT_PLATFORMS: Platform[] = [\"web\"];\n\n/** Platforms a guide config targets (missing field → web only). */\nexport function guidePlatforms(config: { platforms?: readonly string[] | null }): string[] {\n return Array.isArray(config.platforms) ? [...config.platforms] : [...DEFAULT_PLATFORMS];\n}\n\nexport function supportsPlatform(config: { platforms?: readonly string[] | null }, platform: string): boolean {\n return guidePlatforms(config).includes(platform);\n}\n\n/** Attribute web apps put on elements to share a target id with their mobile apps. */\nexport const GUIDELY_ID_ATTRIBUTE = \"data-guidely-id\";\n\n/**\n * Extracts a Guidely target id from a trigger / advance / checklist value so the same guide works on\n * web and mobile. Accepts a bare id (`new-deal`), `#new-deal`, or `[data-guidely-id=\"new-deal\"]`\n * (also `data-testid` / `data-tour`). Returns null for selectors that cannot name a single id.\n */\nexport function guidelyIdFromSelector(value: string | null | undefined): string | null {\n const v = (value ?? \"\").trim();\n if (!v) return null;\n if (/^[A-Za-z0-9_][A-Za-z0-9_\\-:.]*$/.test(v)) return v;\n const hash = v.match(/^#([A-Za-z0-9_][A-Za-z0-9_\\-:.]*)$/);\n if (hash) return hash[1] as string;\n const attr = v.match(/^(?:[a-z][a-z0-9]*)?\\[\\s*data-(?:guidely-id|testid|tour)\\s*=\\s*([\"']?)([^\"'\\]]+)\\1\\s*\\]$/i);\n if (attr) return (attr[2] as string).trim();\n return null;\n}\n\n/**\n * Mobile SDKs have screens instead of URLs. URL-based features (URL patterns, `url_match` triggers,\n * multi-page steps, `url_visited` checklist tasks) match against the screen path `/<ScreenName>`.\n */\nexport function screenPath(screen: string | null | undefined): string {\n const s = (screen ?? \"\").trim();\n if (!s) return \"/\";\n return s.startsWith(\"/\") ? s : `/${s}`;\n}\n\n/**\n * Compares dotted version strings numerically (`2.10.0` > `2.9.3`). Non-numeric parts compare as\n * strings; a missing part counts as 0 (`2.1` == `2.1.0`). Returns -1, 0 or 1, or null when either\n * side is empty.\n */\nexport function compareVersions(a: unknown, b: unknown): -1 | 0 | 1 | null {\n const sa = a == null ? \"\" : String(a).trim().replace(/^v/i, \"\");\n const sb = b == null ? \"\" : String(b).trim().replace(/^v/i, \"\");\n if (!sa || !sb) return null;\n const pa = sa.split(/[.+-]/);\n const pb = sb.split(/[.+-]/);\n const n = Math.max(pa.length, pb.length);\n for (let i = 0; i < n; i++) {\n const x = pa[i] ?? \"0\";\n const y = pb[i] ?? \"0\";\n const nx = /^\\d+$/.test(x) ? Number(x) : NaN;\n const ny = /^\\d+$/.test(y) ? Number(y) : NaN;\n if (!Number.isNaN(nx) && !Number.isNaN(ny)) {\n if (nx !== ny) return nx < ny ? -1 : 1;\n } else if (x !== y) {\n return x < y ? -1 : 1;\n }\n }\n return 0;\n}\n","/**\n * Pure checklist / survey logic shared by every renderer (web runtime, React Native, and the\n * reference for the native SDKs). Zod-free; uses structural types so it stays in the runtime entry.\n */\n\nexport type SurveyAnswer = string | number | boolean | string[];\nexport type SurveyAnswers = Record<string, SurveyAnswer>;\n\nexport interface ShowWhen {\n questionId: string;\n op: \"equals\" | \"lte\" | \"gte\" | \"in\";\n value: string | number | string[];\n}\n\n/** Evaluates a question's `showWhen` condition against current answers. */\nexport function isQuestionVisible(q: { showWhen?: ShowWhen }, answers: SurveyAnswers): boolean {\n if (!q.showWhen) return true;\n const actual = answers[q.showWhen.questionId];\n if (actual === undefined) return false;\n const expected = q.showWhen.value;\n switch (q.showWhen.op) {\n case \"equals\":\n return Array.isArray(actual) ? actual.includes(String(expected)) : String(actual) === String(expected);\n case \"lte\":\n return Number(actual) <= Number(expected);\n case \"gte\":\n return Number(actual) >= Number(expected);\n case \"in\": {\n const list = Array.isArray(expected) ? expected : [String(expected)];\n return Array.isArray(actual) ? actual.some((a) => list.includes(a)) : list.includes(String(actual));\n }\n default:\n return false;\n }\n}\n\n/** Are all required tasks done? */\nexport function isChecklistComplete(config: { tasks: Array<{ id: string; required: boolean }> }, progress: { completedTaskIds: string[] }): boolean {\n const done = new Set(progress.completedTaskIds);\n return config.tasks.filter((t) => t.required).every((t) => done.has(t.id));\n}\n","/**\n * Zod-free targeting evaluation. Imported by the browser SDK via `@guidelytech/shared/runtime`\n * so the runtime bundle does not pull in zod. Schemas live in ./targeting.ts.\n */\nimport { compareVersions } from \"./platform\";\nimport { getPath, matchUrlPattern, rolloutBucket, safeRegExp } from \"./utils\";\n\nexport const RULE_OPERATORS = [\n \"equals\",\n \"not_equals\",\n \"contains\",\n \"not_contains\",\n \"starts_with\",\n \"ends_with\",\n \"exists\",\n \"not_exists\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"in\",\n \"not_in\",\n \"regex\",\n \"is_true\",\n \"is_false\",\n \"before\",\n \"after\",\n] as const;\nexport type RuleOperator = (typeof RULE_OPERATORS)[number];\n\nexport const RULE_FIELDS = [\n \"user.attribute\",\n \"account.attribute\",\n \"user.role\",\n \"user.plan\",\n \"user.identified\",\n \"url.path\",\n \"url.full\",\n \"url.query\",\n \"device.type\",\n \"device.browser\",\n \"device.os\",\n \"visitor.firstVisit\",\n \"visitor.returning\",\n \"event.seen\",\n \"guide.completed\",\n \"guide.dismissed\",\n \"guide.seen\",\n \"checklist.completed\",\n \"audience.member\",\n \"datetime.now\",\n \"datetime.dayOfWeek\",\n \"datetime.hour\",\n \"rollout.percentage\",\n /** Guide A/B tests: the visitor's 0-99 bucket for the salt in `key` (see guide-experiments.ts). */\n \"experiment.bucket\",\n \"environment\",\n \"locale\",\n \"app.platform\",\n \"app.screen\",\n \"app.version\",\n \"page.views\",\n \"feature.clicks\",\n] as const;\nexport type RuleField = (typeof RULE_FIELDS)[number];\n\nexport interface Rule {\n id: string;\n field: RuleField;\n /** For attribute/query/event fields: the attribute key, query param name, event name, guide id... */\n key?: string;\n op: RuleOperator;\n value?: string | number | boolean | string[];\n /** When true, the rule is negated (exclusion rule). */\n negate?: boolean;\n}\n\nexport type RuleGroup = {\n id: string;\n op: \"and\" | \"or\";\n rules: Array<Rule | RuleGroup>;\n negate?: boolean;\n};\n\nexport function isRuleGroup(r: Rule | RuleGroup): r is RuleGroup {\n return (r as RuleGroup).rules !== undefined;\n}\n\nexport function emptyRuleGroup(id = \"root\"): RuleGroup {\n return { id, op: \"and\", rules: [] };\n}\n\n/** Everything targeting evaluation can see. Built by the SDK (browser) or the server. */\nexport interface TargetingContext {\n userId?: string | null;\n anonymousId: string;\n userAttributes: Record<string, unknown>;\n accountAttributes: Record<string, unknown>;\n url: string;\n path: string;\n query: Record<string, string>;\n device: { type: \"desktop\" | \"tablet\" | \"mobile\"; browser?: string; os?: string };\n firstVisit: boolean;\n eventsSeen: Set<string> | string[];\n completedGuides: Set<string> | string[];\n dismissedGuides: Set<string> | string[];\n seenGuides: Set<string> | string[];\n completedChecklists: Set<string> | string[];\n audienceIds: Set<string> | string[];\n now: Date;\n environment: string;\n locale?: string;\n /** `web`, `ios` or `android`. Missing means web. */\n platform?: string;\n /** Current screen name (mobile SDKs; set via `screen()`). */\n screen?: string;\n /** Host app version (mobile SDKs), e.g. `2.4.1`. */\n appVersion?: string;\n /** Salt for rollout (guide id). Set per guide before evaluating. */\n rolloutSalt?: string;\n /**\n * Views of tagged pages / clicks on tagged features in the last 30 days, by tag id. Only the server\n * fills it (audience evaluation); in the browser `page.views` / `feature.clicks` read 0.\n */\n tagUsage?: Record<string, number>;\n}\n\nfunction has(set: Set<string> | string[] | undefined, v: string): boolean {\n if (!set) return false;\n return set instanceof Set ? set.has(v) : set.includes(v);\n}\n\nfunction resolveField(rule: Rule, ctx: TargetingContext): unknown {\n switch (rule.field) {\n case \"user.attribute\":\n return rule.key ? getPath(ctx.userAttributes, rule.key) : undefined;\n case \"account.attribute\":\n return rule.key ? getPath(ctx.accountAttributes, rule.key) : undefined;\n case \"user.role\":\n return ctx.userAttributes.role;\n case \"user.plan\":\n return ctx.userAttributes.plan ?? ctx.accountAttributes.plan;\n case \"user.identified\":\n return !!ctx.userId;\n case \"url.path\":\n return ctx.path;\n case \"url.full\":\n return ctx.url;\n case \"url.query\":\n return rule.key ? ctx.query[rule.key] : undefined;\n case \"device.type\":\n return ctx.device.type;\n case \"device.browser\":\n return ctx.device.browser;\n case \"device.os\":\n return ctx.device.os;\n case \"visitor.firstVisit\":\n return ctx.firstVisit;\n case \"visitor.returning\":\n return !ctx.firstVisit;\n case \"event.seen\":\n return rule.key ? has(ctx.eventsSeen, rule.key) : false;\n case \"guide.completed\":\n return rule.key ? has(ctx.completedGuides, rule.key) : false;\n case \"guide.dismissed\":\n return rule.key ? has(ctx.dismissedGuides, rule.key) : false;\n case \"guide.seen\":\n return rule.key ? has(ctx.seenGuides, rule.key) : false;\n case \"checklist.completed\":\n return rule.key ? has(ctx.completedChecklists, rule.key) : false;\n case \"audience.member\":\n return rule.key ? has(ctx.audienceIds, rule.key) : false;\n case \"datetime.now\":\n return ctx.now.toISOString();\n case \"datetime.dayOfWeek\":\n return ctx.now.getDay();\n case \"datetime.hour\":\n return ctx.now.getHours();\n case \"rollout.percentage\":\n return rolloutBucket(ctx.userId || ctx.anonymousId, ctx.rolloutSalt || \"guidely\");\n case \"experiment.bucket\":\n return rule.key ? rolloutBucket(ctx.userId || ctx.anonymousId, rule.key) : undefined;\n case \"environment\":\n return ctx.environment;\n case \"locale\":\n return ctx.locale;\n case \"app.platform\":\n return ctx.platform ?? \"web\";\n case \"app.screen\":\n return ctx.screen;\n case \"app.version\":\n return ctx.appVersion;\n case \"page.views\":\n case \"feature.clicks\":\n return rule.key ? (ctx.tagUsage?.[rule.key] ?? 0) : 0;\n default:\n return undefined;\n }\n}\n\nfunction toNumber(v: unknown): number | null {\n if (typeof v === \"number\") return v;\n if (typeof v === \"string\" && v.trim() !== \"\" && !Number.isNaN(Number(v))) return Number(v);\n if (v instanceof Date) return v.getTime();\n return null;\n}\n\nfunction toDateMs(v: unknown): number | null {\n if (v instanceof Date) return v.getTime();\n if (typeof v === \"string\") {\n const t = Date.parse(v);\n return Number.isNaN(t) ? null : t;\n }\n if (typeof v === \"number\") return v;\n return null;\n}\n\nexport function compare(op: RuleOperator, actual: unknown, expected: Rule[\"value\"]): boolean {\n switch (op) {\n case \"exists\":\n return actual !== undefined && actual !== null && actual !== \"\";\n case \"not_exists\":\n return actual === undefined || actual === null || actual === \"\";\n case \"is_true\":\n return actual === true || actual === \"true\";\n case \"is_false\":\n return actual === false || actual === \"false\";\n case \"equals\":\n if (typeof actual === \"boolean\") return String(actual) === String(expected);\n return String(actual ?? \"\") === String(expected ?? \"\");\n case \"not_equals\":\n return String(actual ?? \"\") !== String(expected ?? \"\");\n case \"contains\":\n return typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase());\n case \"not_contains\":\n return !(typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase()));\n case \"starts_with\":\n return typeof actual === \"string\" && actual.startsWith(String(expected ?? \"\"));\n case \"ends_with\":\n return typeof actual === \"string\" && actual.endsWith(String(expected ?? \"\"));\n case \"gt\":\n case \"gte\":\n case \"lt\":\n case \"lte\": {\n const a = toNumber(actual);\n const b = toNumber(expected);\n if (a === null || b === null) return false;\n return op === \"gt\" ? a > b : op === \"gte\" ? a >= b : op === \"lt\" ? a < b : a <= b;\n }\n case \"in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return list.includes(String(actual ?? \"\"));\n }\n case \"not_in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return !list.includes(String(actual ?? \"\"));\n }\n case \"regex\": {\n const re = safeRegExp(String(expected ?? \"\"));\n return !!re && typeof actual === \"string\" && re.test(actual);\n }\n case \"before\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a < b;\n }\n case \"after\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a > b;\n }\n default:\n return false;\n }\n}\n\nexport function evaluateRule(rule: Rule, ctx: TargetingContext): boolean {\n let result: boolean;\n if (rule.field === \"url.path\" || rule.field === \"url.full\" || rule.field === \"app.screen\") {\n const actual = String(resolveField(rule, ctx) ?? \"\");\n if (rule.op === \"equals\") result = matchUrlPattern(String(rule.value ?? \"\"), actual);\n else if (rule.op === \"not_equals\") result = !matchUrlPattern(String(rule.value ?? \"\"), actual);\n else result = compare(rule.op, actual, rule.value);\n } else if (rule.field === \"app.version\" && [\"equals\", \"not_equals\", \"gt\", \"gte\", \"lt\", \"lte\"].includes(rule.op)) {\n const c = compareVersions(resolveField(rule, ctx), rule.value);\n if (c === null) result = rule.op === \"not_equals\";\n else result = rule.op === \"equals\" ? c === 0 : rule.op === \"not_equals\" ? c !== 0 : rule.op === \"gt\" ? c > 0 : rule.op === \"gte\" ? c >= 0 : rule.op === \"lt\" ? c < 0 : c <= 0;\n } else {\n result = compare(rule.op, resolveField(rule, ctx), rule.value);\n }\n return rule.negate ? !result : result;\n}\n\n/** Evaluate a rule tree. An empty group matches everyone. */\nexport function evaluateRules(group: RuleGroup | null | undefined, ctx: TargetingContext): boolean {\n if (!group || group.rules.length === 0) return group?.negate ? false : true;\n const results = group.rules.map((r) => (isRuleGroup(r) ? evaluateRules(r, ctx) : evaluateRule(r, ctx)));\n const value = group.op === \"and\" ? results.every(Boolean) : results.some(Boolean);\n return group.negate ? !value : value;\n}\n\n/** Fields whose evaluation requires server-held data. Used by docs/UI to annotate rules. */\nexport const SERVER_ASSISTED_FIELDS: RuleField[] = [\"audience.member\", \"guide.completed\", \"guide.dismissed\", \"guide.seen\", \"checklist.completed\", \"page.views\", \"feature.clicks\"];\n\n/** Who a guide is shown to, before its targeting rules: everyone, only signed-in (identified) users, or only anonymous visitors. */\nexport const GUIDE_VISIBILITIES = [\"everyone\", \"identified\", \"anonymous\"] as const;\nexport type GuideVisibility = (typeof GUIDE_VISIBILITIES)[number];\n\n/**\n * Targeting with the visibility folded in as a `user.identified` rule. The server sends guides to SDKs\n * this way, so every SDK applies it through the rules it already evaluates (SDKs that predate the field\n * resolve it as undefined and show the guide to nobody rather than to everyone).\n */\nexport function withVisibility(targeting: RuleGroup, visibility: GuideVisibility | undefined): RuleGroup {\n if (!visibility || visibility === \"everyone\") return targeting;\n return { id: \"visibility\", op: \"and\", rules: [{ id: \"visibility-rule\", field: \"user.identified\", op: visibility === \"identified\" ? \"is_true\" : \"is_false\" }, targeting] };\n}\n\nexport function describeRule(rule: Rule): string {\n const subject = rule.key ? `${rule.field}[${rule.key}]` : rule.field;\n const v = Array.isArray(rule.value) ? rule.value.join(\", \") : rule.value === undefined ? \"\" : String(rule.value);\n return `${rule.negate ? \"NOT \" : \"\"}${subject} ${rule.op.replace(/_/g, \" \")}${v ? ` \"${v}\"` : \"\"}`;\n}\n","/**\n * WCAG 2.1 colour contrast (zod-free). The editor warns when a guide's colours fall below AA:\n * 4.5:1 for body text, 3:1 for large text and UI components (button outlines, the close icon).\n */\n\nexport const WCAG_AA_TEXT = 4.5;\nexport const WCAG_AA_LARGE = 3;\n\nfunction channel(c: number): number {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n}\n\n/** `#rgb` / `#rrggbb` → [r, g, b]; null when not a hex colour. */\nexport function parseHexColor(hex: string | null | undefined): [number, number, number] | null {\n if (!hex) return null;\n const m = hex.trim().match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);\n if (!m) return null;\n const h = m[1]!.length === 3 ? m[1]!.split(\"\").map((c) => c + c).join(\"\") : m[1]!;\n return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];\n}\n\nexport function relativeLuminance(hex: string): number | null {\n const rgb = parseHexColor(hex);\n if (!rgb) return null;\n return 0.2126 * channel(rgb[0]) + 0.7152 * channel(rgb[1]) + 0.0722 * channel(rgb[2]);\n}\n\n/** Contrast ratio 1–21 between two hex colours, or null when either is not a hex colour. */\nexport function contrastRatio(a: string, b: string): number | null {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n if (la === null || lb === null) return null;\n const [hi, lo] = la > lb ? [la, lb] : [lb, la];\n return Math.round(((hi + 0.05) / (lo + 0.05)) * 100) / 100;\n}\n\n/** Text colour (black or white) with the better contrast on `background`. */\nexport function readableTextOn(background: string): \"#ffffff\" | \"#111827\" {\n const white = contrastRatio(background, \"#ffffff\") ?? 0;\n const dark = contrastRatio(background, \"#111827\") ?? 0;\n return white >= dark ? \"#ffffff\" : \"#111827\";\n}\n\nexport interface ContrastIssue {\n /** What is hard to read. */\n pair: \"text\" | \"button\" | \"link\";\n ratio: number;\n required: number;\n message: string;\n}\n\n/**\n * Contrast problems of a guide's effective colours (guide appearance over the project theme).\n * Buttons use white or dark text, whichever reads better, so only a mid-tone primary colour fails.\n */\nexport function contrastIssues(colors: { primaryColor?: string; backgroundColor?: string; textColor?: string }): ContrastIssue[] {\n const issues: ContrastIssue[] = [];\n const { primaryColor, backgroundColor, textColor } = colors;\n if (textColor && backgroundColor) {\n const r = contrastRatio(textColor, backgroundColor);\n if (r !== null && r < WCAG_AA_TEXT) issues.push({ pair: \"text\", ratio: r, required: WCAG_AA_TEXT, message: `Text on the background has a contrast of ${r}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });\n }\n if (primaryColor) {\n const label = contrastRatio(primaryColor, readableTextOn(primaryColor));\n if (label !== null && label < WCAG_AA_TEXT) issues.push({ pair: \"button\", ratio: label, required: WCAG_AA_TEXT, message: `Button labels on the primary colour have a contrast of ${label}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });\n if (backgroundColor) {\n const link = contrastRatio(primaryColor, backgroundColor);\n if (link !== null && link < WCAG_AA_LARGE) issues.push({ pair: \"link\", ratio: link, required: WCAG_AA_LARGE, message: `The primary colour on the background (links, outlined buttons) has a contrast of ${link}:1; WCAG AA needs ${WCAG_AA_LARGE}:1.` });\n }\n }\n return issues;\n}\n","/** Reserved property names that are stripped from `properties` to avoid collecting sensitive data. */\nexport const SENSITIVE_PROPERTY_PATTERN = /(password|passwd|secret|token|credit|card|cvv|ssn|iban)/i;\n\nexport const MAX_PROPERTY_BYTES = 8 * 1024;\n\nexport function sanitizeProperties(props: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!props) return {};\n const out: Record<string, unknown> = {};\n let size = 0;\n for (const [k, v] of Object.entries(props)) {\n if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;\n if (typeof v === \"function\" || typeof v === \"symbol\") continue;\n const str = typeof v === \"string\" ? v : JSON.stringify(v ?? null);\n size += k.length + (str?.length ?? 0);\n if (size > MAX_PROPERTY_BYTES) break;\n out[k.slice(0, 100)] = typeof v === \"string\" ? v.slice(0, 1000) : v;\n }\n return out;\n}\n","import { fnv1a } from \"./utils\";\n\n/** One parsed stack frame. `file` is the script URL (or path) as the browser reported it. */\nexport interface StackFrame {\n fn?: string;\n file?: string;\n line?: number;\n col?: number;\n}\n\n/** Properties carried by an `exception` event (see `docs/product-analytics.md`). */\nexport interface ExceptionProperties {\n type: string;\n message: string;\n frames: StackFrame[];\n /** `onerror` | `unhandledrejection` | `manual` (captureException) | `console`. */\n source?: string;\n handled?: boolean;\n /** App version or commit (SDK option `release`); selects the matching uploaded source maps. */\n release?: string;\n /** Set by the server at ingestion; groups occurrences into an issue. */\n fingerprint?: string;\n}\n\nexport const MAX_STACK_FRAMES = 30;\n\n// Chrome / Edge / Node: \" at fn (https://x/app.js:1:2)\" or \" at https://x/app.js:1:2\"\nconst V8 = /^\\s*at (?:(.+?) \\()?((?:[a-z][\\w+.-]*:)?[^\\s()]+?):(\\d+):(\\d+)\\)?\\s*$/i;\n// Firefox / Safari: \"fn@https://x/app.js:1:2\" or \"@https://x/app.js:1:2\"\nconst GECKO = /^\\s*(.*?)@(.+?):(\\d+):(\\d+)\\s*$/;\n\n/** Parses `Error.stack` from V8, SpiderMonkey and JavaScriptCore into frames (innermost first). */\nexport function parseStack(stack: string | undefined | null, max = MAX_STACK_FRAMES): StackFrame[] {\n if (!stack || typeof stack !== \"string\") return [];\n const frames: StackFrame[] = [];\n for (const raw of stack.split(\"\\n\")) {\n if (frames.length >= max) break;\n const line = raw.slice(0, 1000);\n const m = V8.exec(line) ?? GECKO.exec(line);\n if (!m) continue;\n const fn = (m[1] || \"\").trim();\n frames.push({ fn: fn ? fn.slice(0, 200) : undefined, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });\n }\n return frames;\n}\n\n/** Replaces volatile parts of a message (numbers, ids, quoted values) so repeats group together. */\nexport function normalizeErrorMessage(message: string): string {\n return (message || \"\")\n .slice(0, 500)\n .replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, \"<uuid>\")\n .replace(/([\"'`]).*?\\1/g, \"<str>\")\n .replace(/\\b0x[0-9a-f]+\\b/gi, \"<hex>\")\n .replace(/\\d+(\\.\\d+)?/g, \"<n>\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** Strips origin, query, hash and build hashes (`main.3f2a1b9c.js` → `main.js`) from a script URL. */\nexport function normalizeFrameFile(file: string | undefined): string {\n if (!file) return \"\";\n let path = file;\n try {\n path = new URL(file).pathname;\n } catch {\n path = file.replace(/[?#].*$/, \"\");\n }\n return path.replace(/[.-][0-9a-f]{6,}(?=\\.\\w+$)/i, \"\").replace(/\\/\\d+\\//g, \"/<n>/\");\n}\n\n/** Source map upload limits (`POST /api/v1/sourcemaps/upload`). */\n/** Per map, uncompressed (the CLI uploads maps gzipped). */\nexport const SOURCEMAP_MAX_FILE_BYTES = 100 * 1024 * 1024;\nexport const SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;\n\n/**\n * Stable issue key for an exception: error type + normalised message + the innermost frame that\n * has a file (path without build hash + function name, or its original source + name when a source\n * map resolved it). Line/column numbers are left out because they change with every deploy of a\n * minified bundle.\n */\nexport function fingerprintError(input: { type?: string; message?: string; frames?: StackFrame[]; original?: { source: string; name?: string | null } | null }): string {\n const top = (input.frames ?? []).find((f) => f.file);\n // With a source map the original file and function name identify the frame across deploys, even\n // when a minifier renames functions between builds.\n const frameKey = input.original ? `src:${input.original.source}:${input.original.name || \"?\"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || \"?\"}` : \"\";\n const key = [input.type || \"Error\", normalizeErrorMessage(input.message || \"\"), frameKey].join(\"|\");\n const a = fnv1a(key).toString(16).padStart(8, \"0\");\n const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, \"0\");\n return a + b;\n}\n","/** Complaint types and limits shared by the server and the messenger runtime (zod-free). */\n\n/** Where a complaint is in its handling; the messenger shows it as Received → In review → Resolved. */\nexport const COMPLAINT_STATUSES = [\"open\", \"in_review\", \"resolved\"] as const;\nexport type ComplaintStatus = (typeof COMPLAINT_STATUSES)[number];\n\n/** Events a complaint webhook can fire on. */\nexport const COMPLAINT_EVENTS = [\"complaint.filed\", \"complaint.status_changed\", \"complaint.replied\", \"complaint.resolved\"] as const;\nexport type ComplaintEvent = (typeof COMPLAINT_EVENTS)[number];\n\n/** Extra questions a category asks for. */\nexport const COMPLAINT_FIELD_TYPES = [\"text\", \"choice\"] as const;\nexport type ComplaintFieldType = (typeof COMPLAINT_FIELD_TYPES)[number];\n\nexport const MAX_COMPLAINT_FIELDS = 8;\nexport const MAX_COMPLAINT_CHOICES = 12;\nexport const MAX_COMPLAINT_LENGTH = 4000;\nexport const MAX_COMPLAINT_ANSWER_LENGTH = 500;\n/** Largest screenshot the messenger may attach (after it scales the image down). */\nexport const MAX_COMPLAINT_ATTACHMENT_BYTES = 2 * 1024 * 1024;\n\nexport interface ComplaintField {\n /** Stable id (`invoice_number`), used as the answer's key in webhook payloads. */\n id: string;\n label: string;\n type: ComplaintFieldType;\n /** Choices for `choice` questions. */\n options?: string[];\n required: boolean;\n}\n\n/** \"CMP-1042\" for complaint number 1042. */\nexport const complaintReference = (number: number) => `CMP-${number}`;\n\n/** A category as the messenger offers it. */\nexport interface MessengerComplaintCategory {\n id: string;\n name: string;\n description: string;\n color: string;\n fields: ComplaintField[];\n}\n\n/** Complaints block of `MessengerConfig`; absent when the project doesn't take complaints. */\nexport interface MessengerComplaintsConfig {\n categories: MessengerComplaintCategory[];\n /** Visitors the app hasn't identified may file one (with an email address). */\n anonymous: boolean;\n}\n\n/** A complaint as the person who filed it sees it (on its conversation). */\nexport interface MessengerComplaint {\n id: string;\n reference: string;\n status: ComplaintStatus;\n categoryName: string;\n createdAt: string;\n}\n\n/** Scout offered the complaint form in a reply, with this category picked. */\nexport interface MessengerComplaintOffer {\n categoryId: string;\n name: string;\n}\n","/**\n * Agent Analytics: the `agent.conversation` turn the customer's own AI agents send (zod-free, so the\n * browser SDK can use the types and limits without bundling the schema). The schema is in agents.ts.\n */\n\nexport const AGENT_TURN_ROLES = [\"user\", \"assistant\", \"tool\", \"system\"] as const;\nexport type AgentTurnRole = (typeof AGENT_TURN_ROLES)[number];\n\n/** How a conversation ended, as the agent reports it. */\nexport const AGENT_OUTCOMES = [\"success\", \"failure\", \"escalated\", \"abandoned\"] as const;\nexport type AgentOutcome = (typeof AGENT_OUTCOMES)[number];\n\nexport const AGENT_TOOL_STATUSES = [\"ok\", \"error\"] as const;\nexport type AgentToolStatus = (typeof AGENT_TOOL_STATUSES)[number];\n\n/** Longest turn text accepted (characters). */\nexport const AGENT_TURN_MAX_TEXT = 20_000;\n/** Most turns in one request. */\nexport const AGENT_TURNS_PER_BATCH = 100;\n/** Most tool calls on one turn. */\nexport const AGENT_TOOL_CALLS_PER_TURN = 50;\n/** Metadata: at most this many keys, string values up to 500 characters, 4 KB in all. */\nexport const AGENT_METADATA_MAX_KEYS = 30;\nexport const AGENT_METADATA_MAX_BYTES = 4096;\n/** The built-in Scout agent's id; customer agents can't use it. */\nexport const SCOUT_AGENT_ID = \"scout\";\n\n/** One tool the agent called in a turn. Arguments and results are never sent or stored. */\nexport interface AgentToolCallInput {\n name: string;\n status?: AgentToolStatus;\n latencyMs?: number;\n}\n\n/** One `agent.conversation` turn. */\nexport interface AgentTurnInput {\n type?: \"agent.conversation\";\n /** Your conversation (thread) id. */\n conversationId: string;\n /** Your agent's id, e.g. \"support-bot\". The agent is created on its first turn. */\n agentId: string;\n /** Display name for a new agent (defaults to agentId). */\n agentName?: string;\n /** Idempotency key: a turn sent twice with the same id is stored once. */\n turnId?: string;\n role: AgentTurnRole;\n text?: string;\n toolCalls?: AgentToolCallInput[];\n /** How long the agent took to produce this turn (assistant turns). */\n latencyMs?: number;\n /** How the conversation ended, when this turn ends it (the latest reported outcome wins). */\n outcome?: AgentOutcome;\n /** Whether the person got what they came for, when the agent knows. */\n taskSuccess?: boolean;\n /** ISO 8601 time of the turn (default: when Guidely receives it). */\n occurredAt?: string;\n userId?: string | null;\n anonymousId?: string | null;\n accountId?: string | null;\n sessionId?: string | null;\n /** Flat key/value pairs (strings, numbers, booleans), e.g. { model: \"gpt-4.1\" }. */\n metadata?: Record<string, string | number | boolean | null>;\n}\n\n/** Response of both ingestion endpoints. */\nexport interface AgentEventsResponse {\n accepted: number;\n duplicates: number;\n /** Turns refused (an agent past the per-project limit, or a conversation past its turn limit). */\n rejected?: number;\n /** Turns dropped because this month's product analytics allowance is used up. */\n overLimit?: number;\n}\n","/* Network requests recorded into session replays (zod-free: imported by the SDK recorder). */\n\n/** rrweb plugin name for network events in recordings (event type 6, `data.plugin`). */\nexport const NETWORK_PLUGIN = \"guidely/network@1\";\n\n/** Request kinds, from `fetch`/`XMLHttpRequest` patching or `PerformanceResourceTiming.initiatorType`. */\nexport type NetworkRequestType = \"fetch\" | \"xhr\" | \"websocket\" | \"document\" | \"script\" | \"stylesheet\" | \"image\" | \"font\" | \"media\" | \"beacon\" | \"other\";\n\n/**\n * One network request in a recording: the payload of an rrweb plugin event\n * `{ type: 6, data: { plugin: NETWORK_PLUGIN, payload: NetworkPluginPayload } }`, batched.\n * Times are epoch milliseconds (same clock as rrweb event timestamps).\n *\n * A WebSocket is a request with `type: \"websocket\"` and `method: \"GET\"`, emitted when it opens\n * (`startTime`) and again, with the same `id`, when it closes (`endTime`, `closeCode`, `closeReason`,\n * totals in `messages`). Its frames are `WebSocketMessage`s referencing that `id`.\n */\nexport interface NetworkRequest {\n /** Stable id within the recording. */\n id: string;\n type: NetworkRequestType;\n method: string;\n /** Absolute URL; values of sensitive-looking query parameters replaced with `[redacted]`. */\n url: string;\n startTime: number;\n endTime?: number;\n durationMs?: number;\n /** HTTP status; 0 for network errors / blocked / aborted. Absent when the browser doesn't expose it. */\n status?: number;\n /** Set for failed requests: network error, abort or timeout message. */\n error?: string;\n /** Encoded bytes transferred / decoded response size, when known. */\n transferSize?: number;\n responseSize?: number;\n /** Only when `recordNetworkPayloads` is on; sensitive headers are `[redacted]`. */\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n /** Text/JSON bodies, ≤10KB, sensitive JSON fields masked; `[binary]` / `[truncated]` markers otherwise. */\n requestBody?: string;\n responseBody?: string;\n /** WebSocket only: negotiated subprotocol, close details, and frame totals (all frames, including ones not recorded). */\n protocol?: string;\n closeCode?: number;\n closeReason?: string;\n messages?: { sent: number; received: number; sentBytes: number; receivedBytes: number; recorded: number };\n}\n\n/** One WebSocket frame. At most `WS_MAX_MESSAGES_PER_SOCKET` are recorded per connection per page load. */\nexport interface WebSocketMessage {\n /** The `NetworkRequest.id` of the connection. */\n socketId: string;\n dir: \"send\" | \"recv\";\n time: number;\n /** Bytes (UTF-8 length for text frames). */\n size: number;\n binary?: boolean;\n /** Only with `recordNetworkPayloads`: text ≤ 2KB (JSON with sensitive keys masked), else `[truncated]`; binary frames are `[binary <n> B]`. */\n data?: string;\n}\n\nexport interface NetworkPluginPayload {\n requests?: NetworkRequest[];\n messages?: WebSocketMessage[];\n /** Requests/frames dropped since the previous payload because a cap was reached. */\n dropped?: { requests?: number; messages?: number };\n}\n\nexport const WS_MAX_MESSAGES_PER_SOCKET = 200;\nexport const WS_MAX_MESSAGE_BYTES = 2048;\n\n/** Header names always replaced with `[redacted]` when payload capture is on. */\nexport const SENSITIVE_HEADER_PATTERN = /^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|x-csrf-token|x-xsrf-token|x-guidely-key|x-guidely-conversation)$/i;\n\n/** Query parameter and JSON field names whose values are redacted. */\nexport const SENSITIVE_PARAM_PATTERN = /(token|key|secret|password|passwd|pwd|auth|session|code|sig|signature|credential|ssn|card|cvv|iban)/i;\n","/**\n * Media in article bodies: uploaded images, videos and PDFs, and video embeds from a fixed set of hosts.\n * Sanitizers (server, browser runtime) only keep an `<iframe>` whose `src` is the canonical embed URL\n * that `toEmbedUrl` produces, so authors can never point a frame anywhere else.\n *\n * An uploaded PDF reads inline, as its pages: the dashboard renders each page to an image when the\n * PDF is uploaded, and the body holds plain HTML every renderer already understands:\n *\n * <div class=\"gd-pdf\">\n * <a class=\"gd-file\" href=\"…/{id}.pdf\" target=\"_blank\">{file name}</a>\n * <div class=\"gd-pdf-pages\"><img src=\"…/{page}.webp\" alt=\"{file name}, page 1 of 12\"> …</div>\n * </div>\n *\n * Renderers that know the classes draw a swipeable page viewer with the PDF one tap away; older ones\n * show a link and the pages as images. A PDF whose pages couldn't be rendered (password-protected,\n * damaged) is just the `gd-file` link, drawn as a file card.\n */\n\nexport type EmbedProvider = \"youtube\" | \"vimeo\" | \"loom\" | \"wistia\";\n\nexport interface VideoEmbed {\n provider: EmbedProvider;\n /** Canonical player URL, safe to use as an iframe `src`. */\n src: string;\n /** Page a viewer can open instead (native SDKs show a link rather than a player). */\n watchUrl: string;\n /** Accessible iframe title. */\n title: string;\n}\n\nexport const MEDIA_IMAGE_TYPES = [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"] as const;\nexport const MEDIA_VIDEO_TYPES = [\"video/mp4\", \"video/webm\"] as const;\nexport const MEDIA_FILE_TYPES = [\"application/pdf\"] as const;\nexport type MediaContentType = (typeof MEDIA_IMAGE_TYPES)[number] | (typeof MEDIA_VIDEO_TYPES)[number] | (typeof MEDIA_FILE_TYPES)[number];\nexport type MediaKind = \"image\" | \"video\" | \"file\";\nexport const MEDIA_IMAGE_MAX_BYTES = 10 * 1024 * 1024;\nexport const MEDIA_VIDEO_MAX_BYTES = 200 * 1024 * 1024;\nexport const MEDIA_FILE_MAX_BYTES = 50 * 1024 * 1024;\n/** The largest upload of any type. */\nexport const MEDIA_MAX_BYTES = Math.max(MEDIA_IMAGE_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_FILE_MAX_BYTES);\n\nexport function isMediaContentType(type: string): type is MediaContentType {\n return mediaKind(type) !== null;\n}\nexport function isVideoContentType(type: string): boolean {\n return (MEDIA_VIDEO_TYPES as readonly string[]).includes(type);\n}\nexport function mediaKind(type: string): MediaKind | null {\n if ((MEDIA_IMAGE_TYPES as readonly string[]).includes(type)) return \"image\";\n if ((MEDIA_VIDEO_TYPES as readonly string[]).includes(type)) return \"video\";\n if ((MEDIA_FILE_TYPES as readonly string[]).includes(type)) return \"file\";\n return null;\n}\nexport function mediaMaxBytes(type: string): number {\n const kind = mediaKind(type);\n return kind === \"video\" ? MEDIA_VIDEO_MAX_BYTES : kind === \"file\" ? MEDIA_FILE_MAX_BYTES : MEDIA_IMAGE_MAX_BYTES;\n}\n\n/** Class marking a link as an attached file (an uploaded PDF), drawn as a file card. */\nexport const FILE_LINK_CLASS = \"gd-file\";\n/** Class of the block holding a PDF's link and its rendered pages. */\nexport const PDF_BLOCK_CLASS = \"gd-pdf\";\n/** Class of the element wrapping a PDF's page images. */\nexport const PDF_PAGES_CLASS = \"gd-pdf-pages\";\n/** Pages rendered inline per PDF; readers open the PDF itself for the rest. */\nexport const PDF_MAX_PAGES = 40;\n\n/** True for an `<a>` with the file class and an absolute http(s) `href`: render it as a file card. */\nexport function isFileLink(className: string | null | undefined, href: string | null | undefined): boolean {\n return !!className && className.split(/\\s+/).includes(FILE_LINK_CLASS) && isSafeMediaUrl(href);\n}\n\nconst YOUTUBE_ID = /^[A-Za-z0-9_-]{11}$/;\nconst VIMEO_ID = /^\\d{1,12}$/;\nconst VIMEO_HASH = /^[0-9a-f]{6,20}$/i;\nconst LOOM_ID = /^[0-9a-f]{32}$/i;\nconst WISTIA_ID = /^[a-z0-9]{10}$/i;\n\nfunction parseUrl(input: string): URL | null {\n const s = input.trim();\n if (!s) return null;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(s) ? s : `https://${s}`);\n if (u.protocol !== \"https:\" && u.protocol !== \"http:\") return null;\n if (u.username || u.password || (u.port && u.port !== \"443\" && u.port !== \"80\")) return null;\n return u;\n } catch {\n return null;\n }\n}\n\n/** \"1h2m3s\", \"90s\", \"90\" → seconds. */\nfunction parseStart(v: string | null): number {\n if (!v) return 0;\n if (/^\\d+$/.test(v)) return Math.min(Number(v), 86400);\n const m = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(v);\n if (!m || !m[0]) return 0;\n return Math.min(Number(m[1] ?? 0) * 3600 + Number(m[2] ?? 0) * 60 + Number(m[3] ?? 0), 86400);\n}\n\nfunction youtube(id: string, start: number): VideoEmbed | null {\n if (!YOUTUBE_ID.test(id)) return null;\n return {\n provider: \"youtube\",\n src: `https://www.youtube-nocookie.com/embed/${id}${start ? `?start=${start}` : \"\"}`,\n watchUrl: `https://www.youtube.com/watch?v=${id}${start ? `&t=${start}s` : \"\"}`,\n title: \"YouTube video\",\n };\n}\n\nfunction vimeo(id: string, hash: string | null): VideoEmbed | null {\n if (!VIMEO_ID.test(id) || (hash !== null && !VIMEO_HASH.test(hash))) return null;\n const h = hash ? hash.toLowerCase() : null;\n return { provider: \"vimeo\", src: `https://player.vimeo.com/video/${id}${h ? `?h=${h}` : \"\"}`, watchUrl: `https://vimeo.com/${id}${h ? `/${h}` : \"\"}`, title: \"Vimeo video\" };\n}\n\n/**\n * Turns a pasted video page or player URL from YouTube, Vimeo, Loom or Wistia into its canonical\n * embed. Returns null for anything else, including lookalike hosts.\n */\nexport function toEmbedUrl(input: string): VideoEmbed | null {\n const u = parseUrl(input);\n if (!u) return null;\n const host = u.hostname.toLowerCase().replace(/^www\\./, \"\");\n const parts = u.pathname.split(\"/\").filter(Boolean);\n switch (host) {\n case \"youtube.com\":\n case \"m.youtube.com\":\n case \"youtube-nocookie.com\": {\n const start = parseStart(u.searchParams.get(\"start\") ?? u.searchParams.get(\"t\"));\n if (parts[0] === \"watch\" && parts.length === 1) return youtube(u.searchParams.get(\"v\") ?? \"\", start);\n if ((parts[0] === \"embed\" || parts[0] === \"shorts\" || parts[0] === \"live\") && parts.length === 2) return youtube(parts[1]!, start);\n return null;\n }\n case \"youtu.be\":\n return parts.length === 1 ? youtube(parts[0]!, parseStart(u.searchParams.get(\"t\") ?? u.searchParams.get(\"start\"))) : null;\n case \"vimeo.com\":\n if (parts.length === 1) return vimeo(parts[0]!, null);\n if (parts.length === 2 && VIMEO_ID.test(parts[0]!)) return vimeo(parts[0]!, parts[1]!);\n return null;\n case \"player.vimeo.com\":\n return parts[0] === \"video\" && parts.length === 2 ? vimeo(parts[1]!, u.searchParams.get(\"h\")) : null;\n case \"loom.com\":\n if ((parts[0] === \"share\" || parts[0] === \"embed\") && parts.length === 2 && LOOM_ID.test(parts[1]!)) {\n const id = parts[1]!.toLowerCase();\n return { provider: \"loom\", src: `https://www.loom.com/embed/${id}`, watchUrl: `https://www.loom.com/share/${id}`, title: \"Loom video\" };\n }\n return null;\n default: {\n let id: string | undefined;\n if (host === \"fast.wistia.net\" || host === \"fast.wistia.com\") id = parts[0] === \"embed\" && parts[1] === \"iframe\" && parts.length === 3 ? parts[2] : undefined;\n else if (host === \"wi.st\" || host === \"wistia.com\" || /^[a-z0-9-]+\\.wistia\\.com$/.test(host)) id = parts[0] === \"medias\" && parts.length === 2 ? parts[1] : undefined;\n if (!id || !WISTIA_ID.test(id)) return null;\n return { provider: \"wistia\", src: `https://fast.wistia.net/embed/iframe/${id}`, watchUrl: `https://fast.wistia.net/embed/iframe/${id}`, title: \"Wistia video\" };\n }\n }\n}\n\n/** True only for a canonical embed URL (exactly what `toEmbedUrl` returns), so an iframe can't be pointed elsewhere. */\nexport function isAllowedEmbedSrc(src: string | null | undefined): boolean {\n if (!src) return false;\n return toEmbedUrl(src)?.src === src;\n}\n\n/** Fixed iframe attributes for an embed; sanitizers overwrite whatever the author's HTML carried. */\nexport const EMBED_IFRAME_ATTRS: Readonly<Record<string, string>> = {\n allow: \"fullscreen; picture-in-picture; encrypted-media\",\n allowfullscreen: \"\",\n loading: \"lazy\",\n referrerpolicy: \"strict-origin-when-cross-origin\",\n sandbox: \"allow-scripts allow-same-origin allow-presentation allow-popups allow-popups-to-escape-sandbox\",\n};\n\n/** Fixed `<video>` attributes: player controls, no autoplay or loop. */\nexport const VIDEO_ATTRS: Readonly<Record<string, string>> = { controls: \"\", preload: \"metadata\", playsinline: \"\" };\n\n/** `<video src>` / `poster` must be plain http(s): no data:, blob: or relative URLs (bodies render on customer sites). */\nexport function isSafeMediaUrl(url: string | null | undefined): boolean {\n if (!url) return false;\n try {\n const u = new URL(url);\n return (u.protocol === \"https:\" || u.protocol === \"http:\") && !u.username && !u.password;\n } catch {\n return false;\n }\n}\n","/**\n * Resource center structure shared by every SDK: nested collections and audience targeting.\n *\n * Audience targeting decides what the help widget lists; it is not access control. The published\n * config (and every article body) is the same for all visitors of an environment, and end-user\n * identities are self-asserted, so never rely on it to keep an article private.\n */\n\n/** Collections nest at most this deep (a collection, its sections, and their sub-sections). */\nexport const MAX_COLLECTION_DEPTH = 3;\n\nexport interface RcCollectionLike {\n id: string;\n name: string;\n order: number;\n /** Parent collection; null/absent for a top-level collection. */\n parentId?: string | null;\n /** Shown only to members of any of these audiences; empty/absent means everyone. */\n audienceIds?: string[];\n}\n\nexport interface RcArticleLike {\n id: string;\n collectionId?: string | null;\n audienceIds?: string[];\n}\n\nexport interface RcSection<C extends RcCollectionLike, A extends RcArticleLike> {\n /** null for articles outside any (known) collection. */\n collection: C | null;\n /** Collection names from the top level down, e.g. [\"Billing\", \"Invoices\"]. */\n path: string[];\n /** 0 for a top-level collection. */\n depth: number;\n articles: A[];\n}\n\ntype Membership = ReadonlySet<string> | readonly string[] | undefined | null;\n\n/** True when an item targeted at `required` audiences is shown to someone in `member`. */\nexport function matchesAudiences(required: readonly string[] | undefined | null, member: Membership): boolean {\n if (!required || required.length === 0) return true;\n if (!member) return false;\n const has = member instanceof Set ? (id: string) => member.has(id) : (id: string) => (member as readonly string[]).includes(id);\n return required.some(has);\n}\n\n/**\n * Article sections in display order: each collection (depth first, siblings by `order`) with the\n * visible articles filed directly in it, then the uncategorized articles. A collection the viewer\n * isn't targeted by hides its whole subtree, and sections without visible articles are left out\n * (their sub-collections still appear). Unknown parents count as top level, so an old config or a\n * dangling reference never hides content.\n */\nexport function resourceCenterSections<C extends RcCollectionLike, A extends RcArticleLike>(collections: readonly C[], articles: readonly A[], member?: Membership): Array<RcSection<C, A>> {\n const byId = new Map(collections.map((c) => [c.id, c]));\n const children = new Map<string | null, C[]>();\n for (const c of collections) {\n const parent = c.parentId && c.parentId !== c.id && byId.has(c.parentId) ? c.parentId : null;\n const list = children.get(parent) ?? [];\n list.push(c);\n children.set(parent, list);\n }\n for (const list of children.values()) list.sort((a, b) => a.order - b.order || a.name.localeCompare(b.name));\n const direct = new Map<string, A[]>();\n const uncategorized: A[] = [];\n for (const a of articles) {\n if (!matchesAudiences(a.audienceIds, member)) continue;\n if (a.collectionId && byId.has(a.collectionId)) {\n const list = direct.get(a.collectionId) ?? [];\n list.push(a);\n direct.set(a.collectionId, list);\n } else uncategorized.push(a);\n }\n\n const sections: Array<RcSection<C, A>> = [];\n const seen = new Set<string>();\n const visit = (c: C, path: string[]) => {\n // A parent cycle in bad data would otherwise recurse forever; cycle members simply don't show.\n if (seen.has(c.id)) return;\n seen.add(c.id);\n if (!matchesAudiences(c.audienceIds, member)) return;\n const here = [...path, c.name];\n const list = direct.get(c.id);\n if (list?.length) sections.push({ collection: c, path: here, depth: here.length - 1, articles: list });\n for (const child of children.get(c.id) ?? []) visit(child, here);\n };\n for (const root of children.get(null) ?? []) visit(root, []);\n if (uncategorized.length) sections.push({ collection: null, path: [], depth: 0, articles: uncategorized });\n return sections;\n}\n\n/**\n * Whether one article is listed for a viewer: its own audiences and those of every collection above\n * it must match. For articles outside a loaded list (e.g. server search results).\n */\nexport function isArticleListed(collections: readonly RcCollectionLike[], article: RcArticleLike, member?: Membership): boolean {\n if (!matchesAudiences(article.audienceIds, member)) return false;\n const byId = new Map(collections.map((c) => [c.id, c]));\n let cur = article.collectionId ? byId.get(article.collectionId) : undefined;\n for (let guard = 0; cur && guard <= MAX_COLLECTION_DEPTH * 4; guard++) {\n if (!matchesAudiences(cur.audienceIds, member)) return false;\n cur = cur.parentId ? byId.get(cur.parentId) : undefined;\n }\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Logged-in only articles\n// ---------------------------------------------------------------------------\n\n/** Who an article is listed for, besides its audiences: everyone, or logged-in (identified) visitors only. */\nexport const ARTICLE_VISIBILITIES = [\"everyone\", \"identified\"] as const;\nexport type ArticleVisibility = (typeof ARTICLE_VISIBILITIES)[number];\n\n/**\n * Reserved audience every logged-in visitor belongs to. The server folds an article's visibility into\n * the audiences it serves and adds this one to identified visitors' memberships, so every SDK (old ones\n * too) applies \"logged-in only\" through the audience matching it already does. Anonymous visitors never\n * identify, so their membership is empty and these articles stay hidden.\n */\nexport const LOGGED_IN_AUDIENCE = \"$identified\";\n\n/**\n * The audiences an article is served with. Logged-in only with no audiences becomes the reserved\n * audience; with audiences it is already implied, since audience membership only comes from identify.\n */\nexport function servedArticleAudiences(audienceIds: readonly string[], visibility: ArticleVisibility | string | null | undefined): string[] {\n return visibility === \"identified\" && audienceIds.length === 0 ? [LOGGED_IN_AUDIENCE] : [...audienceIds];\n}\n\n/** A visitor's memberships as matched against served articles: logged-in visitors are also in `LOGGED_IN_AUDIENCE`. */\nexport function visitorAudiences(audienceIds: readonly string[], identified: boolean): string[] {\n const ids = audienceIds.filter((id) => id !== LOGGED_IN_AUDIENCE);\n return identified ? [...ids, LOGGED_IN_AUDIENCE] : ids;\n}\n\n/** Ids of the articles a viewer sees (for filtering server search results the same way). */\nexport function visibleArticleIds(collections: readonly RcCollectionLike[], articles: readonly RcArticleLike[], member?: Membership): Set<string> {\n return new Set(resourceCenterSections(collections, articles, member).flatMap((s) => s.articles.map((a) => a.id)));\n}\n\n// ---------------------------------------------------------------------------\n// \"Show me\" prompts in help articles\n// ---------------------------------------------------------------------------\n\n/**\n * A \"Show me\" prompt in an article body is a plain link, `<p class=\"gd-show-me\"><a href=\"#guidely-show-me:<guide key>\">Show me how</a></p>`,\n * so it survives every sanitizer and reads as a harmless link anywhere else. The widgets turn it into a\n * button that starts the walkthrough (a live flow guide), or hide it when that guide isn't available.\n */\nexport const SHOW_ME_CLASS = \"gd-show-me\";\nexport const SHOW_ME_HREF_PREFIX = \"#guidely-show-me:\";\nconst SHOW_ME_KEY = /^[A-Za-z0-9_-]{1,64}$/;\n\nexport function showMeHref(guideKey: string): string {\n return `${SHOW_ME_HREF_PREFIX}${guideKey}`;\n}\n\n/** The guide key of a Show me link's `href`, or null. */\nexport function showMeKeyFromHref(href: string | null | undefined): string | null {\n if (!href || !href.startsWith(SHOW_ME_HREF_PREFIX)) return null;\n const key = href.slice(SHOW_ME_HREF_PREFIX.length);\n return SHOW_ME_KEY.test(key) ? key : null;\n}\n\n/** Guide keys of the Show me prompts in an article body, in order, without repeats (at most 10). */\nexport function showMeKeys(html: string | null | undefined): string[] {\n const out: string[] = [];\n for (const m of (html ?? \"\").matchAll(/href=\"#guidely-show-me:([A-Za-z0-9_-]{1,64})\"/g)) if (!out.includes(m[1]!)) out.push(m[1]!);\n return out.slice(0, 10);\n}\n\n/** The article body plays a video (uploaded, or embedded from YouTube, Vimeo, Loom or Wistia). */\nexport function hasVideoMedia(html: string | null | undefined): boolean {\n return /<(video|iframe)\\b/i.test(html ?? \"\");\n}\n\nconst words = (s: string) => s.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [];\n\n/**\n * Help search on the device: every word of the query starts a word of the text, in any order, or the\n * query appears as typed. \"add user\" finds \"Add a new user\" and \"Users › Add\".\n */\nexport function matchesHelpQuery(text: string, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n const hay = text.toLowerCase();\n if (hay.includes(q)) return true;\n const terms = words(q);\n if (!terms.length) return false;\n const have = words(hay);\n return terms.every((t) => have.some((w) => w.startsWith(t) || (t.length > 3 && t.endsWith(\"s\") && w.startsWith(t.slice(0, -1)))));\n}\n\n// ---------------------------------------------------------------------------\n// Modules (section order + targeting) and \"What's new\"\n// ---------------------------------------------------------------------------\n\nexport const RC_MODULE_IDS = [\"announcements\", \"search\", \"checklists\", \"guides\", \"articles\", \"links\", \"faqs\"] as const;\nexport type ResourceCenterModuleId = (typeof RC_MODULE_IDS)[number];\n\nexport const RC_MODULE_LABELS: Record<ResourceCenterModuleId, string> = {\n announcements: \"What's new\",\n search: \"Search\",\n checklists: \"Checklists\",\n guides: \"Guides & tours\",\n articles: \"Articles\",\n links: \"Links\",\n faqs: \"FAQs\",\n};\n\n/**\n * The resource center's sections in display order: the configured modules (unknown ids dropped,\n * missing ones appended enabled, in the default order), so an old config shows every section.\n */\nexport function orderedModules<M extends { id: string; enabled: boolean }>(modules: readonly M[] | null | undefined): Array<M | { id: ResourceCenterModuleId; enabled: true }> {\n const known = (modules ?? []).filter((m, i, all) => (RC_MODULE_IDS as readonly string[]).includes(m.id) && all.findIndex((x) => x.id === m.id) === i);\n const missing = RC_MODULE_IDS.filter((id) => !known.some((m) => m.id === id)).map((id) => ({ id, enabled: true as const }));\n return [...known, ...missing];\n}\n\n/** Announcements a visitor sees: published (not in the future), audience-matched, newest first. */\nexport function visibleAnnouncements<A extends { publishedAt: string; audienceIds?: string[] }>(items: readonly A[] | null | undefined, member?: Membership, now: number = Date.now()): A[] {\n return (items ?? [])\n .filter((a) => {\n const t = Date.parse(a.publishedAt);\n return !Number.isNaN(t) && t <= now && matchesAudiences(a.audienceIds, member);\n })\n .sort((a, b) => Date.parse(b.publishedAt) - Date.parse(a.publishedAt));\n}\n\n/** Unread count for the launcher badge: announcements published after the visitor last opened \"What's new\". */\nexport function unreadAnnouncements(items: readonly { publishedAt: string }[], lastSeenAt: string | null | undefined): number {\n const seen = lastSeenAt ? Date.parse(lastSeenAt) : NaN;\n if (Number.isNaN(seen)) return items.length;\n return items.filter((a) => Date.parse(a.publishedAt) > seen).length;\n}\n","/** How-to capture constants the browser SDK needs without zod (also exported from `@guidelytech/shared/runtime`). */\n\n/** Query parameter that starts capture mode in the SDK (separate from `guidely_authoring`, so SDKs without capture ignore it). */\nexport const CAPTURE_PARAM = \"guidely_capture\";\n/** Largest screenshot the capture endpoint accepts. */\nexport const CAPTURE_SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;\n","/**\n * Page helpers shared by the SDK (page-aware messenger) and the server (page matching, analytics).\n * Pure and zod-free.\n */\n\n/**\n * One path segment that looks like an identifier: digits, a UUID, or a long hex string (hashes,\n * Mongo ids). Written so the same source works as a JS RegExp and a Postgres ARE (`regexp_replace`\n * with flags `gi`), which keeps id folding identical in SQL and in code. A segment may be followed\n * by the page query parameters a project keeps in its paths (`/contacts/42?tab=notes`).\n */\nexport const PATH_ID_PATTERN = \"/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(?=[/?]|$)\";\n\n/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`; `/contacts/42?tab=notes` → `/contacts/:id?tab=notes`. */\nexport function foldPathIds(path: string): string {\n return path.replace(new RegExp(PATH_ID_PATTERN, \"gi\"), \"/:id\");\n}\n\n/** Path segments that say nothing about what a page is for. */\nconst GENERIC_SEGMENTS = new Set([\"\", \":id\", \"app\", \"apps\", \"dashboard\", \"home\", \"index\", \"main\", \"new\", \"edit\", \"view\", \"show\", \"details\", \"detail\", \"overview\", \"list\", \"all\", \"page\", \"pages\", \"en\", \"v1\", \"v2\"]);\n\nfunction segmentsOf(path: string): string[] {\n const clean = foldPathIds((path.split(/[?#]/)[0] || \"/\").toLowerCase());\n return clean\n .split(\"/\")\n .map((s) => s.replace(/\\.(html?|php|aspx?)$/, \"\"))\n .filter((s) => !GENERIC_SEGMENTS.has(s) && /[a-z]/.test(s) && s.length <= 40);\n}\n\n/** Words describing a page, from its path (`/settings/billing-plans/42` → `settings billing plans`). */\nexport function pageTerms(path: string): string[] {\n const words = segmentsOf(path).flatMap((s) => s.split(/[-_.+\\s]+/).filter((w) => w.length > 1 && /[a-z]/.test(w)));\n return [...new Set(words)].slice(0, 8);\n}\n\n/** A short human name for a page (`/app/invoices/42` → `Invoices`), or null for the root and unnamed pages. */\nexport function pageLabel(path: string): string | null {\n const last = segmentsOf(path).at(-1);\n if (!last) return null;\n const words = last.split(/[-_.+\\s]+/).filter(Boolean);\n if (!words.length) return null;\n const label = words.join(\" \");\n return label.charAt(0).toUpperCase() + label.slice(1);\n}\n\n/** The first name in a user's traits (`firstName`, `first_name`, or the first word of `name`), or null. */\nexport function firstNameFromTraits(traits: Record<string, unknown> | null | undefined): string | null {\n if (!traits) return null;\n const pick = (v: unknown) => (typeof v === \"string\" ? v.trim() : \"\");\n const first = pick(traits.firstName) || pick(traits.first_name) || pick(traits.firstname) || pick(traits.name).split(/\\s+/)[0] || \"\";\n // Never greet someone by an email address or an id.\n if (!first || first.length > 40 || first.includes(\"@\") || !/\\p{L}/u.test(first)) return null;\n return first;\n}\n","/**\n * Tagged pages and features (named rules over the URLs and clicks the SDK captures), shared by the server (retroactive\n * matching, SQL generation), the dashboard (previews) and the SDK (event properties). Pure and zod-free.\n *\n * - An `ElementSnapshot` is the compact description of a clicked element the SDK attaches to `click`\n * events (`properties.el`): tag, id, classes, a few safe attributes, nth-of-type, ~5 ancestors and\n * the shadow hosts above it. CSS selector rules are evaluated against it with {@link matchCssSelector},\n * so a rule written today also matches clicks stored before it existed.\n * - Older clicks carry only a selector string; {@link snapshotFromSelector} turns that string into a\n * partial snapshot so CSS rules still match them where the string says enough.\n */\n\n// ---------------------------------------------------------------------------\n// Element snapshots\n// ---------------------------------------------------------------------------\n\n/** One element in a snapshot: tag, id, classes, safe attributes and its 1-based nth-of-type. */\nexport interface ElementNode {\n t: string;\n id?: string;\n c?: string[];\n a?: Record<string, string>;\n n?: number;\n}\n\n/** A clicked element (`click.properties.el`): the element, its ancestors (`p`, parent first) and shadow hosts (`h`, nearest first). */\nexport interface ElementSnapshot extends ElementNode {\n p?: ElementNode[];\n h?: ElementNode[];\n}\n\nexport const SNAPSHOT_LIMITS = { classes: 8, className: 60, attrs: 6, attrValue: 100, ancestors: 5, hosts: 3, tag: 40, id: 80 } as const;\n\n/** Attributes a snapshot may carry besides `data-*` ones. Never `value`, never event handlers. */\nexport const SNAPSHOT_ATTRS = [\"role\", \"name\", \"type\", \"aria-label\", \"title\", \"alt\", \"for\", \"href\"] as const;\n\n/** Framework and state `data-*` attributes that say nothing stable about an element. */\nexport const NOISY_DATA_ATTR = /^data-(state|v-|react|radix|headlessui|svelte|orientation|highlighted|focus|key|index|side|align|disabled|selected|active|open|rbd|dnd|sveltekit|guidely-(mask|ignore|block))/i;\n\n/** The custom attribute that names a feature by default (`<button data-guidely-feature=\"Export CSV\">`). */\nexport const DEFAULT_FEATURE_ATTRIBUTE = \"data-guidely-feature\";\nexport const FEATURE_ATTRIBUTE_PATTERN = /^data-[a-z0-9][a-z0-9_.-]{0,60}$/;\n\nfunction str(v: unknown, max: number): string | undefined {\n return typeof v === \"string\" && v ? v.slice(0, max) : undefined;\n}\n\nfunction cleanNode(raw: unknown): ElementNode | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n const t = str(r.t, SNAPSHOT_LIMITS.tag)?.toLowerCase();\n if (!t || !/^[a-z][a-z0-9-]*$/.test(t)) return null;\n const node: ElementNode = { t };\n const id = str(r.id, SNAPSHOT_LIMITS.id);\n if (id) node.id = id;\n if (Array.isArray(r.c)) {\n const c = r.c.filter((x): x is string => typeof x === \"string\" && !!x && x.length <= SNAPSHOT_LIMITS.className && !/\\s/.test(x)).slice(0, SNAPSHOT_LIMITS.classes);\n if (c.length) node.c = c;\n }\n if (r.a && typeof r.a === \"object\" && !Array.isArray(r.a)) {\n const a: Record<string, string> = {};\n for (const [k, v] of Object.entries(r.a as Record<string, unknown>)) {\n if (Object.keys(a).length >= SNAPSHOT_LIMITS.attrs) break;\n const key = k.toLowerCase();\n if (typeof v !== \"string\" || !(key.startsWith(\"data-\") || (SNAPSHOT_ATTRS as readonly string[]).includes(key)) || key === \"value\" || key.length > 60) continue;\n a[key] = v.slice(0, SNAPSHOT_LIMITS.attrValue);\n }\n if (Object.keys(a).length) node.a = a;\n }\n if (typeof r.n === \"number\" && Number.isInteger(r.n) && r.n >= 1 && r.n <= 10_000) node.n = r.n;\n return node;\n}\n\n/** Validates and trims a snapshot sent by an SDK (server side); null when it is not one. */\nexport function normalizeSnapshot(raw: unknown): ElementSnapshot | null {\n const el = cleanNode(raw);\n if (!el) return null;\n const r = raw as Record<string, unknown>;\n const out: ElementSnapshot = el;\n if (Array.isArray(r.p)) {\n const p = r.p.slice(0, SNAPSHOT_LIMITS.ancestors).map(cleanNode);\n // Ancestors are consecutive; stop at the first unusable one rather than skipping it.\n const cut = p.indexOf(null);\n const list = (cut === -1 ? p : p.slice(0, cut)) as ElementNode[];\n if (list.length) out.p = list;\n }\n if (Array.isArray(r.h)) {\n const h = r.h.slice(0, SNAPSHOT_LIMITS.hosts).map(cleanNode).filter((x): x is ElementNode => !!x);\n if (h.length) out.h = h;\n }\n return out;\n}\n\n/** JSON with sorted keys, so equal snapshots hash the same whatever order the SDK wrote them in. */\nexport function stableStringify(v: unknown): string {\n if (Array.isArray(v)) return `[${v.map(stableStringify).join(\",\")}]`;\n if (v && typeof v === \"object\") {\n const o = v as Record<string, unknown>;\n return `{${Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${stableStringify(o[k])}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(v ?? null);\n}\n\n// ---------------------------------------------------------------------------\n// CSS selector subset: parse + match against a snapshot\n// ---------------------------------------------------------------------------\n\nexport type AttrOp = \"exists\" | \"=\" | \"^=\" | \"$=\" | \"*=\" | \"~=\" | \"|=\";\n\nexport interface AttrTest {\n name: string;\n op: AttrOp;\n value?: string;\n /** `[attr=\"x\" i]` */\n insensitive?: boolean;\n}\n\nexport interface Compound {\n tag?: string;\n id?: string;\n classes: string[];\n attrs: AttrTest[];\n /** `:nth-of-type(n)`; `odd`/`even` as `{ a: 2, b: 1|0 }`; `:first-of-type` is `{ a: 0, b: 1 }`. */\n nth?: { a: number; b: number };\n}\n\n/** A complex selector: compounds left to right and the combinator before each (index 0 has none). */\nexport interface ComplexSelector {\n compounds: Compound[];\n combinators: Array<\" \" | \">\" | \">>>\">;\n}\n\nexport class SelectorSyntaxError extends Error {}\n\nconst IDENT_START = /[A-Za-z_\\u00a0-\\uffff-]/;\nconst IDENT_CHAR = /[A-Za-z0-9_\\u00a0-\\uffff-]/;\n\n/**\n * Parses the supported subset: type and universal selectors, `#id`, `.class`, `[attr]`,\n * `[attr=v]`, `^=`, `$=`, `*=`, `~=`, `|=` (optionally `i`), `:nth-of-type(n|odd|even)`,\n * `:first-of-type`, descendant and child combinators, `>>>` (shadow host) and selector lists.\n * Throws {@link SelectorSyntaxError} on anything else.\n */\nexport function parseCssSelector(input: string): ComplexSelector[] {\n const s = input.trim();\n if (!s) throw new SelectorSyntaxError(\"Empty selector\");\n if (s.length > 1000) throw new SelectorSyntaxError(\"Selector is too long\");\n let i = 0;\n const peek = () => s[i];\n const eof = () => i >= s.length;\n const fail = (msg: string): never => {\n throw new SelectorSyntaxError(`${msg} at position ${i + 1}`);\n };\n const ws = () => {\n let any = false;\n while (!eof() && /\\s/.test(s[i]!)) {\n i++;\n any = true;\n }\n return any;\n };\n const escape = (): string => {\n // after the backslash\n i++;\n const hex = /^[0-9a-fA-F]{1,6}/.exec(s.slice(i));\n if (hex) {\n i += hex[0].length;\n if (s[i] === \" \") i++;\n return String.fromCodePoint(parseInt(hex[0], 16));\n }\n if (eof()) fail(\"Unfinished escape\");\n return s[i++]!;\n };\n const ident = (): string => {\n let out = \"\";\n if (s[i] === \"\\\\\") out += escape();\n else if (!eof() && IDENT_START.test(s[i]!)) out += s[i++];\n else fail(\"Expected a name\");\n while (!eof()) {\n if (s[i] === \"\\\\\") out += escape();\n else if (IDENT_CHAR.test(s[i]!)) out += s[i++];\n else break;\n }\n return out;\n };\n const quoted = (): string => {\n const q = s[i++];\n let out = \"\";\n while (!eof() && s[i] !== q) {\n if (s[i] === \"\\\\\") out += escape();\n else out += s[i++];\n }\n if (eof()) fail(\"Unterminated string\");\n i++;\n return out;\n };\n const compound = (): Compound | null => {\n const c: Compound = { classes: [], attrs: [] };\n let any = false;\n if (peek() === \"*\") {\n i++;\n any = true;\n } else if (!eof() && (IDENT_START.test(peek()!) || peek() === \"\\\\\")) {\n c.tag = ident().toLowerCase();\n any = true;\n }\n for (;;) {\n const ch = peek();\n if (ch === \"#\") {\n i++;\n c.id = ident();\n } else if (ch === \".\") {\n i++;\n c.classes.push(ident());\n } else if (ch === \"[\") {\n i++;\n ws();\n const name = ident().toLowerCase();\n ws();\n let op: AttrOp = \"exists\";\n let value: string | undefined;\n let insensitive = false;\n if (peek() !== \"]\") {\n const m = /^(=|\\^=|\\$=|\\*=|~=|\\|=)/.exec(s.slice(i));\n if (!m) fail(\"Unsupported attribute operator\");\n op = m![1] as AttrOp;\n i += m![1]!.length;\n ws();\n value = peek() === '\"' || peek() === \"'\" ? quoted() : ident();\n ws();\n if (peek() === \"i\" || peek() === \"I\") {\n i++;\n insensitive = true;\n ws();\n } else if (peek() === \"s\" || peek() === \"S\") {\n i++;\n ws();\n }\n }\n if (peek() !== \"]\") fail(\"Expected ]\");\n i++;\n c.attrs.push({ name, op, ...(value !== undefined ? { value } : {}), ...(insensitive ? { insensitive } : {}) });\n } else if (ch === \":\") {\n i++;\n if (peek() === \":\") fail(\"Pseudo-elements are not supported\");\n const name = ident().toLowerCase();\n if (name === \"first-of-type\") c.nth = { a: 0, b: 1 };\n else if (name === \"nth-of-type\") {\n if (peek() !== \"(\") fail(\"Expected (\");\n i++;\n ws();\n const m = /^(odd|even|\\d+)/i.exec(s.slice(i));\n if (!m) fail(\"Only :nth-of-type(n), odd or even are supported\");\n i += m![0].length;\n ws();\n if (peek() !== \")\") fail(\"Expected )\");\n i++;\n const v = m![0].toLowerCase();\n c.nth = v === \"odd\" ? { a: 2, b: 1 } : v === \"even\" ? { a: 2, b: 0 } : { a: 0, b: Number(v) };\n } else fail(`Unsupported pseudo-class :${name}`);\n } else break;\n any = true;\n }\n return any ? c : null;\n };\n\n const list: ComplexSelector[] = [];\n for (;;) {\n ws();\n const sel: ComplexSelector = { compounds: [], combinators: [] };\n const first = compound();\n if (!first) fail(\"Expected a selector\");\n sel.compounds.push(first!);\n for (;;) {\n const hadWs = ws();\n if (eof() || peek() === \",\") break;\n let comb: \" \" | \">\" | \">>>\" = \" \";\n if (s.startsWith(\">>>\", i)) {\n comb = \">>>\";\n i += 3;\n ws();\n } else if (peek() === \">\") {\n comb = \">\";\n i++;\n ws();\n } else if (peek() === \"+\" || peek() === \"~\") fail(\"Sibling combinators are not supported\");\n else if (!hadWs) fail(\"Unexpected character\");\n const next = compound();\n if (!next) fail(\"Expected a selector after the combinator\");\n sel.compounds.push(next!);\n sel.combinators.push(comb);\n }\n list.push(sel);\n if (eof()) break;\n i++; // \",\"\n }\n return list;\n}\n\n/** Is the selector inside the supported subset? Returns the error message, or null when it parses. */\nexport function cssSelectorError(selector: string): string | null {\n try {\n parseCssSelector(selector);\n return null;\n } catch (e) {\n return e instanceof Error ? e.message : \"Invalid selector\";\n }\n}\n\nfunction attrMatches(test: AttrTest, node: ElementNode): boolean {\n let actual: string | undefined;\n if (test.name === \"id\") actual = node.id;\n else if (test.name === \"class\") actual = node.c?.join(\" \");\n else actual = node.a?.[test.name];\n if (actual === undefined) return false;\n if (test.op === \"exists\") return true;\n let v = test.value ?? \"\";\n if (test.insensitive) {\n actual = actual.toLowerCase();\n v = v.toLowerCase();\n }\n switch (test.op) {\n case \"=\":\n return actual === v;\n case \"^=\":\n return !!v && actual.startsWith(v);\n case \"$=\":\n return !!v && actual.endsWith(v);\n case \"*=\":\n return !!v && actual.includes(v);\n case \"~=\":\n return !!v && actual.split(/\\s+/).includes(v);\n case \"|=\":\n return actual === v || actual.startsWith(`${v}-`);\n default:\n return false;\n }\n}\n\n/** Does one compound match one node? An unknown nth-of-type fails `:nth-of-type` tests. */\nexport function compoundMatches(c: Compound, node: ElementNode): boolean {\n if (c.tag && c.tag !== node.t) return false;\n if (c.id !== undefined && node.id !== c.id) return false;\n for (const cls of c.classes) if (!node.c?.includes(cls)) return false;\n for (const a of c.attrs) if (!attrMatches(a, node)) return false;\n if (c.nth) {\n if (!node.n) return false;\n const { a, b } = c.nth;\n if (a === 0 ? node.n !== b : (node.n - b) % a !== 0 || (node.n - b) / a < 0) return false;\n }\n return true;\n}\n\n/** Matches compounds (right to left) against a chain of nodes: index 0 is the element, then its ancestors. */\nfunction chainMatches(compounds: Compound[], combinators: Array<\" \" | \">\">, nodes: ElementNode[], ci = compounds.length - 1, ni = 0): boolean {\n if (!compoundMatches(compounds[ci]!, nodes[ni]!)) return false;\n if (ci === 0) return true;\n const comb = combinators[ci - 1]!;\n if (comb === \">\") return ni + 1 < nodes.length && chainMatches(compounds, combinators, nodes, ci - 1, ni + 1);\n for (let k = ni + 1; k < nodes.length; k++) if (chainMatches(compounds, combinators, nodes, ci - 1, k)) return true;\n return false;\n}\n\nfunction complexMatches(sel: ComplexSelector, snap: ElementSnapshot): boolean {\n // Split at `>>>`: the last segment is matched inside the element's own tree, each earlier\n // segment's last compound against a shadow host further out (any depth, like the runtime).\n const segments: Array<{ compounds: Compound[]; combinators: Array<\" \" | \">\"> }> = [{ compounds: [sel.compounds[0]!], combinators: [] }];\n sel.combinators.forEach((comb, k) => {\n const next = sel.compounds[k + 1]!;\n if (comb === \">>>\") segments.push({ compounds: [next], combinators: [] });\n else {\n const seg = segments[segments.length - 1]!;\n seg.compounds.push(next);\n seg.combinators.push(comb);\n }\n });\n const last = segments.pop()!;\n const nodes: ElementNode[] = [snap, ...(snap.p ?? [])];\n if (!chainMatches(last.compounds, last.combinators, nodes)) return false;\n const hosts = snap.h ?? [];\n let from = 0;\n for (let k = segments.length - 1; k >= 0; k--) {\n const target = segments[k]!.compounds[segments[k]!.compounds.length - 1]!;\n let found = -1;\n for (let j = from; j < hosts.length; j++) {\n if (compoundMatches(target, hosts[j]!)) {\n found = j;\n break;\n }\n }\n if (found === -1) return false;\n from = found + 1;\n }\n return true;\n}\n\nconst parsedCache = new Map<string, ComplexSelector[] | null>();\n\n/** Does a CSS selector (subset, see {@link parseCssSelector}) match the snapshot? Invalid selectors match nothing. */\nexport function matchCssSelector(selector: string | ComplexSelector[], snap: ElementSnapshot): boolean {\n let list: ComplexSelector[] | null;\n if (typeof selector === \"string\") {\n if (!parsedCache.has(selector)) {\n if (parsedCache.size > 500) parsedCache.clear();\n try {\n parsedCache.set(selector, parseCssSelector(selector));\n } catch {\n parsedCache.set(selector, null);\n }\n }\n list = parsedCache.get(selector)!;\n } else list = selector;\n return !!list && list.some((sel) => complexMatches(sel, snap));\n}\n\nfunction nodeOfCompound(c: Compound): ElementNode {\n const node: ElementNode = { t: c.tag ?? \"*\" };\n if (c.id) node.id = c.id;\n if (c.classes.length) node.c = c.classes.slice(0, SNAPSHOT_LIMITS.classes);\n const a: Record<string, string> = {};\n for (const t of c.attrs) if (t.op === \"=\" && t.value !== undefined) a[t.name] = t.value;\n if (Object.keys(a).length) node.a = a;\n if (c.nth && c.nth.a === 0) node.n = c.nth.b;\n return node;\n}\n\n/**\n * A partial snapshot read from a stored selector string (clicks captured before snapshots existed):\n * `#form > div:nth-of-type(2) > button[data-testid=\"save\"]` becomes a `button` with that attribute,\n * nth 1-unknown, and two ancestors. Shadow steps (`c-app >>> button`) become hosts. Null when the\n * string is not a selector in the supported subset.\n */\nexport function snapshotFromSelector(selector: string, tag?: string | null): ElementSnapshot | null {\n let list: ComplexSelector[];\n try {\n list = parseCssSelector(selector);\n } catch {\n return null;\n }\n if (list.length !== 1) return null;\n const sel = list[0]!;\n const segments: Compound[][] = [[sel.compounds[0]!]];\n sel.combinators.forEach((comb, k) => {\n if (comb === \">>>\") segments.push([sel.compounds[k + 1]!]);\n else segments[segments.length - 1]!.push(sel.compounds[k + 1]!);\n });\n const own = segments.pop()!;\n const el = nodeOfCompound(own[own.length - 1]!);\n if (el.t === \"*\" && tag && /^[a-z][a-z0-9-]*$/i.test(tag)) el.t = tag.toLowerCase();\n const snap: ElementSnapshot = el;\n const p = own.slice(0, -1).reverse().map(nodeOfCompound);\n if (p.length) snap.p = p.slice(0, SNAPSHOT_LIMITS.ancestors);\n const h = segments.reverse().map((seg) => nodeOfCompound(seg[seg.length - 1]!));\n if (h.length) snap.h = h.slice(0, SNAPSHOT_LIMITS.hosts);\n return snap;\n}\n\n// ---------------------------------------------------------------------------\n// Page rules\n// ---------------------------------------------------------------------------\n\nexport type QueryParamOp = \"exists\" | \"absent\" | \"equals\" | \"contains\";\nexport interface QueryParamCondition {\n name: string;\n op: QueryParamOp;\n value?: string;\n}\n\n/**\n * One way a URL belongs to a page. `url`: a pattern (`/accounts/:id/settings`, `/reports/*`,\n * `/docs/**`, `//*\\/billing`, `https://app.acme.com/x`) plus optional query conditions; `regex`: a\n * regular expression over the path; `title`: the document title (`equals` / `contains`). With\n * `exclude`, matching URLs are taken out of the page instead.\n */\nexport interface PageRule {\n id?: string;\n type: \"url\" | \"regex\" | \"title\";\n value: string;\n op?: \"equals\" | \"contains\";\n query?: QueryParamCondition[];\n exclude?: boolean;\n}\n\nexport const PAGE_RULE_LIMITS = { rules: 20, value: 500, query: 5 } as const;\n\nexport interface PagePattern {\n /** Anchored regex source, valid both as a JS RegExp (flag `i`) and a Postgres ARE (`~*`). */\n source: string;\n /** What it runs against: the path (query removed) or the full URL without query and hash. */\n target: \"path\" | \"url\";\n /** Query conditions written into the pattern (`/search?tab=people`). */\n query: QueryParamCondition[];\n}\n\nconst escapeRe = (s: string) => s.replace(/[.+?^${}()|[\\]\\\\*]/g, \"\\\\$&\");\n\nfunction globToRegex(pattern: string): string {\n let out = \"\";\n for (let k = 0; k < pattern.length; k++) {\n const ch = pattern[k]!;\n if (ch === \"*\") {\n if (pattern[k + 1] === \"*\") {\n out += \".*\";\n k++;\n } else out += \"[^/]*\";\n } else if (ch === \":\" && (k === 0 || pattern[k - 1] === \"/\") && /[A-Za-z_]/.test(pattern[k + 1] ?? \"\")) {\n // `:name` path parameter: one whole segment.\n let j = k + 1;\n while (j < pattern.length && /[\\w]/.test(pattern[j]!)) j++;\n out += \"[^/]+\";\n k = j - 1;\n } else out += escapeRe(ch);\n }\n return out;\n}\n\n/** Turns a URL rule pattern into a regex. Query parameters in the pattern become conditions. */\nexport function pagePattern(raw: string): PagePattern {\n let p = raw.trim();\n const query: QueryParamCondition[] = [];\n const hash = p.indexOf(\"#\");\n if (hash !== -1) p = p.slice(0, hash);\n const q = p.indexOf(\"?\");\n if (q !== -1) {\n for (const part of p.slice(q + 1).split(\"&\")) {\n if (!part) continue;\n const eq = part.indexOf(\"=\");\n const name = decodeSafe(eq === -1 ? part : part.slice(0, eq));\n const value = eq === -1 ? undefined : decodeSafe(part.slice(eq + 1));\n if (!name) continue;\n query.push(value === undefined || value === \"*\" ? { name, op: \"exists\" } : { name, op: \"equals\", value });\n }\n p = p.slice(0, q);\n }\n let target: \"path\" | \"url\" = \"path\";\n // `//*` means any domain: keep only the path.\n if (p.startsWith(\"//*\")) p = p.slice(3);\n let prefix = \"\";\n const abs = /^(https?:)?\\/\\/([^/]+)(.*)$/i.exec(p);\n if (abs) {\n target = \"url\";\n prefix = `https?://${globToRegex(abs[2]!.toLowerCase())}`;\n p = abs[3] || \"/\";\n }\n if (!p.startsWith(\"/\")) p = `/${p}`;\n // A trailing slash is optional, as on most sites.\n const body = p.length > 1 && p.endsWith(\"/\") ? p.slice(0, -1) : p;\n const src = body === \"/\" ? \"/?\" : `${globToRegex(body)}/?`;\n return { source: `^${prefix}${src}$`, target, query: query.slice(0, PAGE_RULE_LIMITS.query) };\n}\n\nfunction decodeSafe(s: string): string {\n try {\n return decodeURIComponent(s.replace(/\\+/g, \" \"));\n } catch {\n return s;\n }\n}\n\n/** Regex (JS + Postgres) for a query condition over a raw URL. */\nexport function queryConditionRegex(c: QueryParamCondition): string {\n const name = escapeRe(c.name);\n switch (c.op) {\n case \"equals\":\n return `[?&]${name}=${escapeRe(encodeLoose(c.value ?? \"\"))}(&|#|$)`;\n case \"contains\":\n return `[?&]${name}=[^&#]*${escapeRe(encodeLoose(c.value ?? \"\"))}`;\n default:\n return `[?&]${name}(=|&|#|$)`;\n }\n}\n\n/** URL-encodes what browsers encode in query values, leaving the common safe characters alone. */\nfunction encodeLoose(v: string): string {\n return encodeURIComponent(v).replace(/%2F/gi, \"/\").replace(/%3A/gi, \":\").replace(/%2C/gi, \",\").replace(/%40/gi, \"@\");\n}\n\nexport interface PageContext {\n /** Full URL (with query) when known. */\n url?: string | null;\n /** Path as stored (`/a/b`, or `/a/b?section=x` with kept page parameters). */\n path?: string | null;\n title?: string | null;\n}\n\nfunction pathOnly(ctx: PageContext): string | null {\n if (ctx.path) return ctx.path.split(\"?\")[0] || \"/\";\n if (!ctx.url) return null;\n try {\n return new URL(ctx.url, \"http://x.invalid\").pathname;\n } catch {\n return null;\n }\n}\n\nfunction regexOrNull(source: string): RegExp | null {\n try {\n return new RegExp(source, \"i\");\n } catch {\n return null;\n }\n}\n\n/** JS twin of the SQL a page rule compiles to (server `pageRuleSql`). */\nexport function pageRuleMatches(rule: PageRule, ctx: PageContext): boolean {\n const path = pathOnly(ctx);\n if (rule.type === \"title\") {\n const t = (ctx.title ?? \"\").toLowerCase();\n const v = rule.value.toLowerCase();\n return !!t && (rule.op === \"contains\" ? t.includes(v) : t === v);\n }\n if (rule.type === \"regex\") {\n const re = regexOrNull(rule.value);\n return !!re && path !== null && re.test(path);\n }\n const pat = pagePattern(rule.value);\n const re = regexOrNull(pat.source);\n if (!re) return false;\n let subject: string | null = path;\n if (pat.target === \"url\") {\n if (!ctx.url) return false;\n subject = ctx.url.split(/[?#]/)[0]!;\n }\n if (subject === null || !re.test(subject)) return false;\n const conds = [...pat.query, ...(rule.query ?? [])];\n for (const c of conds) {\n const hit = !!ctx.url && new RegExp(queryConditionRegex(c), \"i\").test(ctx.url);\n if (c.op === \"absent\" ? hit : !hit) return false;\n }\n return true;\n}\n\n/** Included by any include rule and excluded by no exclude rule. */\nexport function pageRulesMatch(rules: PageRule[], ctx: PageContext): boolean {\n const include = rules.filter((r) => !r.exclude);\n if (!include.length || !include.some((r) => pageRuleMatches(r, ctx))) return false;\n return !rules.some((r) => r.exclude && pageRuleMatches(r, ctx));\n}\n\n/** Validation message for a page rule, or null. */\nexport function pageRuleError(rule: PageRule): string | null {\n const v = rule.value?.trim();\n if (!v) return \"A rule needs a value\";\n if (v.length > PAGE_RULE_LIMITS.value) return \"The rule is too long\";\n if (rule.type === \"regex\") {\n if (!regexOrNull(v)) return `\"${v}\" is not a valid regular expression`;\n if (/\\(\\?[<=!]/.test(v) || /\\\\[1-9]/.test(v)) return \"Look-arounds and back-references are not supported\";\n }\n if (rule.type === \"url\" && !regexOrNull(pagePattern(v).source)) return `\"${v}\" is not a valid URL rule`;\n for (const q of rule.query ?? []) if (!/^[A-Za-z0-9_.\\-[\\]]{1,60}$/.test(q.name)) return `\"${q.name}\" is not a query parameter name`;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Feature rules\n// ---------------------------------------------------------------------------\n\nexport type SelectorOp = \"exact\" | \"prefix\" | \"contains\" | \"glob\" | \"css\";\n\n/**\n * One way a click belongs to a feature. Every condition present must hold. `selector.op = \"css\"`\n * evaluates a CSS selector against the element snapshot (or, for old clicks, the snapshot read from\n * the stored selector string); the other selector operators compare the stored selector string —\n * mobile taps store the accessibility id / `data-guidely-id` there, so `exact` works for them too.\n */\nexport interface FeatureRule {\n id?: string;\n selector?: { op: SelectorOp; value: string };\n text?: { op: \"equals\" | \"contains\"; value: string };\n tag?: string;\n href?: { op: \"equals\" | \"prefix\" | \"contains\"; value: string };\n /** Only clicks on this tagged page / URL pattern. */\n page?: { pageId?: string; pattern?: string };\n /** `web`, `ios`, `android` (mobile autocapture sets `properties.platform`). */\n platform?: string;\n exclude?: boolean;\n}\n\nexport const FEATURE_RULE_LIMITS = { rules: 20, value: 1000 } as const;\n\nexport interface ClickFacts {\n selector?: string | null;\n text?: string | null;\n tag?: string | null;\n href?: string | null;\n platform?: string | null;\n}\n\nfunction globMatch(pattern: string, value: string): boolean {\n const re = new RegExp(`^${pattern.split(\"*\").map(escapeRe).join(\".*\")}$`, \"s\");\n return re.test(value);\n}\n\n/** Does a click (facts + a CSS test) satisfy one rule's element conditions? Page scope is checked by the caller. */\nexport function featureRuleMatchesClick(rule: FeatureRule, click: ClickFacts, css: (selector: string) => boolean): boolean {\n if (!rule.selector && !rule.text && !rule.tag && !rule.href) return false;\n if (rule.selector) {\n const sel = click.selector ?? \"\";\n const v = rule.selector.value;\n const ok =\n rule.selector.op === \"css\" ? css(v) : rule.selector.op === \"exact\" ? sel === v : rule.selector.op === \"prefix\" ? sel.startsWith(v) : rule.selector.op === \"contains\" ? sel.includes(v) : globMatch(v, sel);\n if (!ok) return false;\n }\n if (rule.text) {\n const t = (click.text ?? \"\").toLowerCase();\n const v = rule.text.value.toLowerCase();\n if (rule.text.op === \"contains\" ? !t.includes(v) : t !== v) return false;\n }\n if (rule.tag && (click.tag ?? \"\").toLowerCase() !== rule.tag.toLowerCase()) return false;\n if (rule.href) {\n const h = click.href ?? \"\";\n const v = rule.href.value;\n if (rule.href.op === \"equals\" ? h !== v : rule.href.op === \"prefix\" ? !h.startsWith(v) : !h.includes(v)) return false;\n }\n if (rule.platform && (click.platform ?? \"web\") !== rule.platform) return false;\n return true;\n}\n\n/** Validation message for a feature rule, or null. */\nexport function featureRuleError(rule: FeatureRule): string | null {\n if (!rule.selector && !rule.text && !rule.tag && !rule.href) return \"A feature rule needs a selector, text, tag or link condition\";\n if (rule.selector) {\n const v = rule.selector.value?.trim();\n if (!v) return \"The selector is empty\";\n if (v.length > FEATURE_RULE_LIMITS.value) return \"The selector is too long\";\n if (rule.selector.op === \"css\") {\n const err = cssSelectorError(v);\n if (err) return `Unsupported CSS selector: ${err}`;\n }\n }\n if (rule.text && !rule.text.value.trim()) return \"The text condition is empty\";\n if (rule.href && !rule.href.value.trim()) return \"The link condition is empty\";\n if (rule.tag && !/^[a-z][a-z0-9-]{0,40}$/i.test(rule.tag)) return \"The tag is not an element name\";\n if (rule.page?.pattern) return pageRuleError({ type: \"url\", value: rule.page.pattern });\n return null;\n}\n\n/** Selector to find a feature's elements on a page (dashboard overlays, SDK property capture), when the rules give one. */\nexport function featureCssSelectors(rules: FeatureRule[]): string[] {\n const out: string[] = [];\n for (const r of rules) {\n if (r.exclude || !r.selector) continue;\n if ((r.selector.op === \"css\" || r.selector.op === \"exact\") && !cssSelectorError(r.selector.value)) out.push(r.selector.value);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Event properties captured from the DOM (configured per page / feature, sent in the SDK config)\n// ---------------------------------------------------------------------------\n\nexport interface TagPropertyDefinition {\n id: string;\n name: string;\n /** Element to read: CSS selector (may use `>>>`); empty = the clicked element itself (features only). */\n selector?: string;\n source: \"text\" | \"attribute\";\n /** Attribute name for `source: \"attribute\"`; `value` is never read. */\n attribute?: string;\n}\n\n/** One tag's capture config in the SDK payload (`SdkConfigResponse.tagging.properties`). */\nexport interface TagPropertyConfig {\n kind: \"page\" | \"feature\";\n tagId: string;\n /** Page rules (pages) or feature rules (features), evaluated in the browser. */\n pageRules?: PageRule[];\n featureRules?: FeatureRule[];\n properties: TagPropertyDefinition[];\n}\n\nexport interface TaggingSdkConfig {\n /** Attribute that names features automatically (null = off). */\n featureAttribute: string | null;\n properties: TagPropertyConfig[];\n}\n\nexport const TAG_PROPERTY_LIMITS = { perTag: 10, total: 50, value: 100 } as const;\n\n/** Attribute names an event property may read. */\nexport function propertyAttributeAllowed(name: string): boolean {\n const n = name.toLowerCase();\n if (n === \"value\" || n.startsWith(\"on\") || n === \"style\" || n === \"srcdoc\") return false;\n return /^[a-z][a-z0-9_:.-]{0,60}$/.test(n);\n}\n","/**\n * Guide and resource-center localization (zod-free, so the browser SDK can import it).\n *\n * Every translatable text field has a stable key derived from ids, never from positions, so\n * reordering steps keeps translations attached: `steps.<stepId>.title`,\n * `steps.<stepId>.buttons.<buttonId>.label`, `checklist.tasks.<taskId>.title`,\n * `survey.questions.<questionId>.options.<optionId>.label`, …\n *\n * A visitor's language comes from (in order) an explicit SDK locale, the `language` / `locale`\n * trait, then the browser / device language. `resolveLocale` matches it against the languages a\n * guide is translated into (exact tag first, then the base language) and falls back to the\n * project's default language, in which the guide is written.\n */\nimport type { GuideConfig } from \"./guide\";\nimport type { PublishedGuide, ResourceCenterAnnouncement, ResourceCenterArticle, ResourceCenterConfig } from \"./sdk-api\";\n\nexport type TextKind = \"text\" | \"html\";\n\nexport interface TextEntry {\n key: string;\n /** Default-language text. */\n source: string;\n kind: TextKind;\n /** Human-readable location for translators (\"Step 2 · Title\"). */\n label: string;\n}\n\n/** Project-level language settings (Project.settings.localization). */\nexport interface LocalizationSettings {\n /** Language the content is written in. */\n defaultLocale: string;\n /** Additional languages offered for translation. */\n locales: string[];\n /** Machine-translate new and changed text into every language automatically. */\n autoTranslate?: boolean;\n /** Machine translations need a teammate's approval before visitors see them. */\n requireReview?: boolean;\n}\n\n/**\n * Review state of one translated text. `machine` texts were written by AI translation; `human`\n * ones were typed or imported by a teammate (approved by doing so). `outdated` means the source\n * text changed after the translation was written or approved.\n */\nexport interface TranslationReviewState {\n origin: \"machine\" | \"human\";\n approved: boolean;\n outdated: boolean;\n reviewedBy?: string | null;\n reviewedAt?: string | null;\n}\n\n/** locale → key → review state. Texts without a state are human translations from before review existed. */\nexport type TranslationReviewMap = Record<string, Record<string, TranslationReviewState>>;\n\n/** Does this translation still need a teammate to look at it? */\nexport function needsReview(state: TranslationReviewState | undefined): boolean {\n return !!state && ((state.origin === \"machine\" && !state.approved) || state.outdated);\n}\n\nexport const DEFAULT_LOCALE = \"en\";\n\n/** Common languages offered in the dashboard's language picker (any BCP 47 tag is accepted). */\nexport const COMMON_LOCALES: Array<{ code: string; name: string }> = [\n { code: \"en\", name: \"English\" },\n { code: \"en-GB\", name: \"English (UK)\" },\n { code: \"fr\", name: \"French\" },\n { code: \"fr-CA\", name: \"French (Canada)\" },\n { code: \"de\", name: \"German\" },\n { code: \"es\", name: \"Spanish\" },\n { code: \"es-MX\", name: \"Spanish (Mexico)\" },\n { code: \"it\", name: \"Italian\" },\n { code: \"pt\", name: \"Portuguese\" },\n { code: \"pt-BR\", name: \"Portuguese (Brazil)\" },\n { code: \"nl\", name: \"Dutch\" },\n { code: \"sv\", name: \"Swedish\" },\n { code: \"da\", name: \"Danish\" },\n { code: \"nb\", name: \"Norwegian\" },\n { code: \"fi\", name: \"Finnish\" },\n { code: \"pl\", name: \"Polish\" },\n { code: \"cs\", name: \"Czech\" },\n { code: \"tr\", name: \"Turkish\" },\n { code: \"ru\", name: \"Russian\" },\n { code: \"uk\", name: \"Ukrainian\" },\n { code: \"ar\", name: \"Arabic\" },\n { code: \"he\", name: \"Hebrew\" },\n { code: \"hi\", name: \"Hindi\" },\n { code: \"ja\", name: \"Japanese\" },\n { code: \"ko\", name: \"Korean\" },\n { code: \"zh-Hans\", name: \"Chinese (Simplified)\" },\n { code: \"zh-Hant\", name: \"Chinese (Traditional)\" },\n { code: \"id\", name: \"Indonesian\" },\n { code: \"th\", name: \"Thai\" },\n { code: \"vi\", name: \"Vietnamese\" },\n];\n\nexport function localeName(code: string): string {\n const exact = COMMON_LOCALES.find((l) => l.code.toLowerCase() === code.toLowerCase());\n if (exact) return exact.name;\n const base = COMMON_LOCALES.find((l) => l.code.toLowerCase() === baseLanguage(code));\n return base ? `${base.name} (${code})` : code;\n}\n\n/** `fr_FR` / `FR-fr` → `fr-FR`; script subtags keep title case (`zh-hans` → `zh-Hans`). Invalid input → \"\". */\nexport function normalizeLocale(input: unknown): string {\n if (typeof input !== \"string\") return \"\";\n const parts = input.trim().replace(/_/g, \"-\").split(\"-\").filter(Boolean);\n if (!parts.length || !/^[a-zA-Z]{2,3}$/.test(parts[0]!)) return \"\";\n return parts\n .slice(0, 3)\n .map((p, i) => (i === 0 ? p.toLowerCase() : p.length === 4 ? p[0]!.toUpperCase() + p.slice(1).toLowerCase() : p.length === 2 ? p.toUpperCase() : p))\n .join(\"-\");\n}\n\nexport function baseLanguage(locale: string): string {\n return normalizeLocale(locale).split(\"-\")[0] ?? \"\";\n}\n\n/**\n * Picks the language to show: for each requested locale in order, an exact match among\n * `available`, else one sharing its base language (`fr-CA` → `fr`, `fr` → `fr-FR`). Falls back to\n * `defaultLocale`. Matching ignores case.\n */\nexport function resolveLocale(requested: ReadonlyArray<string | null | undefined>, available: readonly string[], defaultLocale: string = DEFAULT_LOCALE): string {\n const def = normalizeLocale(defaultLocale) || DEFAULT_LOCALE;\n const avail = available.map(normalizeLocale).filter(Boolean);\n const all = [def, ...avail.filter((a) => a.toLowerCase() !== def.toLowerCase())];\n for (const raw of requested) {\n const want = normalizeLocale(raw);\n if (!want) continue;\n const exact = all.find((a) => a.toLowerCase() === want.toLowerCase());\n if (exact) return exact;\n const base = baseLanguage(want);\n const sameBase = all.find((a) => a.toLowerCase() === base) ?? all.find((a) => baseLanguage(a) === base);\n if (sameBase) return sameBase;\n }\n return def;\n}\n\n/** Locale candidates for a visitor: explicit option, traits (`language`, `locale`), then the platform's languages. */\nexport function visitorLocales(explicit: string | null | undefined, traits: Record<string, unknown> | null | undefined, platform: ReadonlyArray<string | null | undefined> = []): string[] {\n const out: string[] = [];\n const push = (v: unknown) => {\n const n = normalizeLocale(v);\n if (n && !out.includes(n)) out.push(n);\n };\n push(explicit);\n push(traits?.language);\n push(traits?.locale);\n for (const p of platform) push(p);\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Guides\n// ---------------------------------------------------------------------------\n\n/** Every translatable text in a guide config, in display order. Empty texts are skipped. */\nexport function guideTextEntries(config: Pick<GuideConfig, \"steps\" | \"checklist\" | \"survey\">): TextEntry[] {\n const out: TextEntry[] = [];\n const add = (key: string, source: string | undefined | null, kind: TextKind, label: string) => {\n if (source && source.trim()) out.push({ key, source, kind, label });\n };\n config.steps.forEach((s, i) => {\n const at = `Step ${i + 1}`;\n add(`steps.${s.id}.title`, s.title, \"text\", `${at} · Title`);\n add(`steps.${s.id}.body`, s.body, \"html\", `${at} · Body`);\n add(`steps.${s.id}.customHtml`, s.customHtml, \"html\", `${at} · Custom HTML`);\n add(`steps.${s.id}.imageAlt`, s.imageAlt, \"text\", `${at} · Image description`);\n s.buttons.forEach((b) => add(`steps.${s.id}.buttons.${b.id}.label`, b.label, \"text\", `${at} · Button “${b.label}”`));\n });\n const c = config.checklist;\n if (c) {\n add(\"checklist.launcherLabel\", c.launcherLabel, \"text\", \"Checklist · Launcher label\");\n add(\"checklist.completionTitle\", c.completionTitle, \"text\", \"Checklist · Completion title\");\n add(\"checklist.completionBody\", c.completionBody, \"html\", \"Checklist · Completion message\");\n c.tasks.forEach((t, i) => {\n add(`checklist.tasks.${t.id}.title`, t.title, \"text\", `Task ${i + 1} · Title`);\n add(`checklist.tasks.${t.id}.description`, t.description, \"html\", `Task ${i + 1} · Description`);\n });\n }\n const sv = config.survey;\n if (sv) {\n sv.questions.forEach((q, i) => {\n const at = `Question ${i + 1}`;\n add(`survey.questions.${q.id}.title`, q.title, \"text\", `${at} · Question`);\n add(`survey.questions.${q.id}.description`, q.description, \"text\", `${at} · Description`);\n add(`survey.questions.${q.id}.placeholder`, q.placeholder, \"text\", `${at} · Placeholder`);\n add(`survey.questions.${q.id}.lowLabel`, q.lowLabel, \"text\", `${at} · Low label`);\n add(`survey.questions.${q.id}.highLabel`, q.highLabel, \"text\", `${at} · High label`);\n q.options.forEach((o) => add(`survey.questions.${q.id}.options.${o.id}.label`, o.label, \"text\", `${at} · Option “${o.label}”`));\n });\n add(\"survey.thankYouTitle\", sv.thankYouTitle, \"text\", \"Survey · Thank-you title\");\n add(\"survey.thankYouBody\", sv.thankYouBody, \"html\", \"Survey · Thank-you message\");\n }\n return out;\n}\n\n/** Locales a guide has any translation for. */\nexport function guideLocales(config: Pick<GuideConfig, \"localization\">): string[] {\n const t = config.localization?.translations ?? {};\n return Object.keys(t).filter((l) => Object.values(t[l] ?? {}).some((v) => typeof v === \"string\" && v.trim() !== \"\"));\n}\n\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string): string;\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string | undefined): string | undefined;\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string | undefined): string | undefined {\n const v = map?.[key];\n return typeof v === \"string\" && v.trim() !== \"\" ? v : fallback;\n}\n\n/** The config with one language's translations applied (untranslated texts keep the default language). */\nexport function applyGuideTranslations<C extends Pick<GuideConfig, \"steps\" | \"checklist\" | \"survey\">>(config: C, map: Record<string, string> | undefined): C {\n if (!map || !Object.keys(map).length) return config;\n return {\n ...config,\n steps: config.steps.map((s) => ({\n ...s,\n title: pick(map, `steps.${s.id}.title`, s.title),\n body: pick(map, `steps.${s.id}.body`, s.body),\n customHtml: pick(map, `steps.${s.id}.customHtml`, s.customHtml),\n imageAlt: pick(map, `steps.${s.id}.imageAlt`, s.imageAlt),\n buttons: s.buttons.map((b) => ({ ...b, label: pick(map, `steps.${s.id}.buttons.${b.id}.label`, b.label) })),\n })),\n checklist: config.checklist\n ? {\n ...config.checklist,\n launcherLabel: pick(map, \"checklist.launcherLabel\", config.checklist.launcherLabel),\n completionTitle: pick(map, \"checklist.completionTitle\", config.checklist.completionTitle),\n completionBody: pick(map, \"checklist.completionBody\", config.checklist.completionBody),\n tasks: config.checklist.tasks.map((t) => ({ ...t, title: pick(map, `checklist.tasks.${t.id}.title`, t.title), description: pick(map, `checklist.tasks.${t.id}.description`, t.description) })),\n }\n : config.checklist,\n survey: config.survey\n ? {\n ...config.survey,\n thankYouTitle: pick(map, \"survey.thankYouTitle\", config.survey.thankYouTitle),\n thankYouBody: pick(map, \"survey.thankYouBody\", config.survey.thankYouBody),\n questions: config.survey.questions.map((q) => ({\n ...q,\n title: pick(map, `survey.questions.${q.id}.title`, q.title),\n description: pick(map, `survey.questions.${q.id}.description`, q.description),\n placeholder: pick(map, `survey.questions.${q.id}.placeholder`, q.placeholder),\n lowLabel: pick(map, `survey.questions.${q.id}.lowLabel`, q.lowLabel),\n highLabel: pick(map, `survey.questions.${q.id}.highLabel`, q.highLabel),\n options: q.options.map((o) => ({ ...o, label: pick(map, `survey.questions.${q.id}.options.${o.id}.label`, o.label) })),\n })),\n }\n : config.survey,\n };\n}\n\n/**\n * The guide as a visitor speaking `requested` should see it, with `locale` set to the language\n * chosen (the default language when none of the guide's translations match).\n */\nexport function localizeGuide(guide: PublishedGuide, requested: readonly string[], defaultLocale: string = DEFAULT_LOCALE): PublishedGuide & { locale: string } {\n const translations = guide.config.localization?.translations ?? {};\n const locale = resolveLocale(requested, guideLocales(guide.config), defaultLocale);\n const key = Object.keys(translations).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());\n if (!key) return { ...guide, locale };\n return { ...guide, locale, config: applyGuideTranslations(guide.config, translations[key]) };\n}\n\nexport interface TranslationCoverage {\n locale: string;\n total: number;\n translated: number;\n /** Keys with no translation. */\n missing: string[];\n /** Keys whose translation exists but whose key no longer matches any text (stale). */\n stale: string[];\n}\n\nexport function translationCoverage(entries: readonly TextEntry[], map: Record<string, string> | undefined, locale: string): TranslationCoverage {\n const keys = new Set(entries.map((e) => e.key));\n const missing = entries.filter((e) => !pick(map, e.key, undefined)).map((e) => e.key);\n const stale = Object.keys(map ?? {}).filter((k) => !keys.has(k) && (map?.[k] ?? \"\").trim() !== \"\");\n return { locale, total: entries.length, translated: entries.length - missing.length, missing, stale };\n}\n\n// ---------------------------------------------------------------------------\n// Resource center\n// ---------------------------------------------------------------------------\n\n/** Translations carried by the published resource center (texts other than articles and announcements). */\nexport type ResourceCenterTranslations = Record<string, Record<string, string>>;\n\n/** Translatable resource-center texts (title, launcher label, links, FAQs, collections). */\nexport function resourceCenterTextEntries(rc: Pick<ResourceCenterConfig, \"title\" | \"launcher\" | \"links\" | \"faqs\" | \"collections\">): TextEntry[] {\n const out: TextEntry[] = [];\n const add = (key: string, source: string | undefined | null, kind: TextKind, label: string) => {\n if (source && source.trim()) out.push({ key, source, kind, label });\n };\n add(\"title\", rc.title, \"text\", \"Title\");\n add(\"launcher.label\", rc.launcher?.label, \"text\", \"Launcher label\");\n rc.collections.forEach((c) => {\n add(`collections.${c.id}.name`, c.name, \"text\", `Collection “${c.name}”`);\n add(`collections.${c.id}.description`, c.description, \"text\", `Collection “${c.name}” · Description`);\n });\n rc.links.forEach((l) => add(`links.${l.id}.label`, l.label, \"text\", `Link “${l.label}”`));\n rc.faqs.forEach((f, i) => {\n add(`faqs.${f.id}.question`, f.question, \"text\", `FAQ ${i + 1} · Question`);\n add(`faqs.${f.id}.answer`, f.answer, \"html\", `FAQ ${i + 1} · Answer`);\n });\n return out;\n}\n\n/** Article texts, keyed `title` / `summary` / `body`. */\nexport function articleTextEntries(a: { title: string; summary?: string | null; body?: string | null }): TextEntry[] {\n const out: TextEntry[] = [];\n if (a.title.trim()) out.push({ key: \"title\", source: a.title, kind: \"text\", label: \"Title\" });\n if (a.summary?.trim()) out.push({ key: \"summary\", source: a.summary, kind: \"text\", label: \"Summary\" });\n if (a.body?.trim()) out.push({ key: \"body\", source: a.body, kind: \"html\", label: \"Body\" });\n return out;\n}\n\n/** Locales the resource center offers (its own strings, articles or announcements). */\nexport function resourceCenterLocales(rc: ResourceCenterConfig): string[] {\n const set = new Set<string>(Object.keys(rc.translations ?? {}));\n for (const a of rc.articles) for (const l of Object.keys(a.translations ?? {})) set.add(l);\n for (const a of rc.announcements ?? []) for (const l of Object.keys(a.translations ?? {})) set.add(l);\n return [...set];\n}\n\nfunction translationFor<T>(map: Record<string, T> | undefined, locale: string): T | undefined {\n if (!map) return undefined;\n const key = Object.keys(map).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());\n return key ? map[key] : undefined;\n}\n\nexport function localizeArticle(a: ResourceCenterArticle, locale: string): ResourceCenterArticle {\n const t = translationFor(a.translations, locale);\n if (!t) return a;\n const body = t.body?.trim() ? t.body : a.body;\n // A translated body that was left out of the snapshot is fetched with `?locale=`.\n return { ...a, title: t.title?.trim() ? t.title : a.title, summary: t.summary?.trim() ? t.summary : a.summary, body, ...(t.bodyOmitted ? { bodyOmitted: true } : {}) };\n}\n\nexport function localizeAnnouncement(a: ResourceCenterAnnouncement, locale: string): ResourceCenterAnnouncement {\n const t = translationFor(a.translations, locale);\n if (!t) return a;\n return { ...a, title: t.title?.trim() ? t.title : a.title, body: t.body?.trim() ? t.body : a.body };\n}\n\n/** The resource center in the visitor's language (with `locale` = the language chosen). */\nexport function localizeResourceCenter(rc: ResourceCenterConfig, requested: readonly string[], defaultLocale: string = DEFAULT_LOCALE): ResourceCenterConfig & { locale: string } {\n const locale = resolveLocale(requested, resourceCenterLocales(rc), defaultLocale);\n if (locale.toLowerCase() === normalizeLocale(defaultLocale).toLowerCase()) return { ...rc, locale };\n const map = translationFor(rc.translations, locale);\n return {\n ...rc,\n locale,\n title: pick(map, \"title\", rc.title),\n launcher: { ...rc.launcher, label: pick(map, \"launcher.label\", rc.launcher.label) },\n collections: rc.collections.map((c) => ({ ...c, name: pick(map, `collections.${c.id}.name`, c.name), description: pick(map, `collections.${c.id}.description`, c.description) })),\n links: rc.links.map((l) => ({ ...l, label: pick(map, `links.${l.id}.label`, l.label) })),\n faqs: rc.faqs.map((f) => ({ ...f, question: pick(map, `faqs.${f.id}.question`, f.question), answer: pick(map, `faqs.${f.id}.answer`, f.answer) })),\n articles: rc.articles.map((a) => localizeArticle(a, locale)),\n announcements: rc.announcements?.map((a) => localizeAnnouncement(a, locale)),\n };\n}\n","/**\n * Guide A/B tests (zod-free; shared by the server, the web SDK and the mobile SDK ports).\n *\n * Each visitor falls into a bucket 0–99: `rolloutBucket(userId || anonymousId, salt)` (FNV-1a,\n * see utils.ts), with `salt = experimentSalt(experimentId)`. Variants own consecutive bucket ranges\n * in their listed order, sized by their integer weights (which sum to 100). The server folds each\n * variant's range into the targeting it serves as two `experiment.bucket` rules, so every SDK\n * applies the split with the rule engine it already has, and assignment is the same everywhere:\n * the server's `assignGuideVariant` and an SDK evaluating the served rules always agree.\n */\nimport { rolloutBucket } from \"./utils\";\nimport type { Rule, RuleGroup } from \"./targeting-eval\";\n\n/** The \"no guide\" variant: visitors in it see nothing, and are measured against the guide variants. */\nexport const CONTROL_VARIANT_ID = \"control\";\n\nexport const GUIDE_EXPERIMENT_STATUSES = [\"draft\", \"running\", \"completed\"] as const;\nexport type GuideExperimentStatus = (typeof GUIDE_EXPERIMENT_STATUSES)[number];\n\nexport const GUIDE_EXPERIMENT_GOALS = [\"guide_completed\", \"event\", \"page_visit\", \"click_text\"] as const;\nexport type GuideExperimentGoalKind = (typeof GUIDE_EXPERIMENT_GOALS)[number];\n\nexport const GUIDE_EXPERIMENT_GOAL_LABELS: Record<GuideExperimentGoalKind, string> = {\n guide_completed: \"Completes the guide\",\n event: \"Tracks an event\",\n page_visit: \"Visits a page\",\n click_text: \"Clicks an element with text\",\n};\n\nexport interface GuideExperimentGoal {\n kind: GuideExperimentGoalKind;\n /** Event name, page path pattern (`/billing/*`) or click text, depending on `kind`. */\n value?: string;\n}\n\nexport interface GuideExperimentVariant {\n id: string;\n name: string;\n /** The guide shown to this variant; null for the control group (no guide). */\n guideId: string | null;\n /** Share of visitors, a whole percentage; all weights sum to 100. */\n weight: number;\n}\n\nexport function experimentSalt(experimentId: string): string {\n return `gx:${experimentId}`;\n}\n\n/** Bucket ranges `[from, to)` per variant, in order. */\nexport function variantRanges(variants: ReadonlyArray<Pick<GuideExperimentVariant, \"id\" | \"weight\">>): Array<{ id: string; from: number; to: number }> {\n let at = 0;\n return variants.map((v) => {\n const from = at;\n at = Math.min(100, at + Math.max(0, Math.round(v.weight)));\n return { id: v.id, from, to: at };\n });\n}\n\n/** The variant a visitor is in, or null when weights leave their bucket unassigned. */\nexport function assignGuideVariant(variants: ReadonlyArray<Pick<GuideExperimentVariant, \"id\" | \"weight\">>, experimentId: string, subject: string): string | null {\n const bucket = rolloutBucket(subject, experimentSalt(experimentId));\n return variantRanges(variants).find((r) => bucket >= r.from && bucket < r.to)?.id ?? null;\n}\n\n/** Rules restricting targeting to bucket range `[from, to)` of `salt`. */\nexport function experimentBucketRules(salt: string, from: number, to: number): Rule[] {\n return [\n { id: \"experiment-from\", field: \"experiment.bucket\", key: salt, op: \"gte\", value: from },\n { id: \"experiment-to\", field: \"experiment.bucket\", key: salt, op: \"lt\", value: to },\n ];\n}\n\n/** Targeting with a variant's bucket range folded in (an SDK without `experiment.bucket` shows the guide to nobody). */\nexport function withExperimentBucket(targeting: RuleGroup, salt: string, from: number, to: number): RuleGroup {\n return { id: \"experiment\", op: \"and\", rules: [...experimentBucketRules(salt, from, to), targeting] };\n}\n\n/** Problems with a variant list; empty when it can run. */\nexport function variantProblems(variants: ReadonlyArray<GuideExperimentVariant>): string[] {\n const problems: string[] = [];\n if (variants.length < 2) problems.push(\"An A/B test needs at least two variants.\");\n if (variants.length > 5) problems.push(\"An A/B test can have at most five variants.\");\n const guides = variants.filter((v) => v.guideId);\n if (guides.length === 0) problems.push(\"At least one variant must show a guide.\");\n if (variants.filter((v) => !v.guideId).length > 1) problems.push(\"Only one variant can be the control group (no guide).\");\n if (new Set(guides.map((v) => v.guideId)).size !== guides.length) problems.push(\"Each variant needs its own guide.\");\n if (new Set(variants.map((v) => v.id)).size !== variants.length) problems.push(\"Variant ids must be unique.\");\n if (variants.some((v) => !Number.isInteger(v.weight) || v.weight < 1)) problems.push(\"Every variant needs a whole-number share of at least 1%.\");\n const total = variants.reduce((s, v) => s + v.weight, 0);\n if (total !== 100) problems.push(`Traffic shares must add up to 100% (now ${total}%).`);\n return problems;\n}\n\n/** Splits 100% as evenly as possible across `n` variants (first ones get the remainder). */\nexport function evenWeights(n: number): number[] {\n if (n <= 0) return [];\n const base = Math.floor(100 / n);\n return Array.from({ length: n }, (_, i) => base + (i < 100 - base * n ? 1 : 0));\n}\n","/**\n * Custom CSS for guides and themes (zod-free; the server sanitizes on save, the web runtime\n * sanitizes again and scopes before injecting).\n *\n * Guides render inside the SDK's Shadow DOM, so page styles and guide styles never mix. Within the\n * shadow root, every rule is additionally prefixed with the guide's own container selector, so one\n * guide's CSS can't restyle another guide, the resource center or the messenger. Sanitizing removes\n * what could reach outside the container or load anything: `@import`, `:host` / `::slotted` rules,\n * `url()`s other than https images and `data:image/…`, legacy script hooks (`expression()`,\n * `behavior`, `-moz-binding`, `javascript:`) and any markup.\n */\n\nexport const MAX_CUSTOM_CSS = 20000;\n\nconst BLOCKED_AT_RULES = /^@(import|charset|namespace|document|-moz-document)\\b/i;\nconst ALLOWED_AT_RULES = /^@(media|supports|container|layer|keyframes|-webkit-keyframes|font-face)\\b/i;\n\ninterface Block {\n /** Selector or at-rule prelude; \"\" for a bare declaration list. */\n prelude: string;\n /** Declarations (for rules) or nested CSS (for grouping at-rules). */\n body: string;\n}\n\n/** Splits CSS into top-level `prelude { body }` blocks, respecting strings and nesting. Statements without a block are dropped. */\nfunction splitBlocks(css: string): Block[] {\n const out: Block[] = [];\n let i = 0;\n const n = css.length;\n while (i < n) {\n let prelude = \"\";\n let quote: string | null = null;\n while (i < n) {\n const ch = css[i]!;\n if (quote) {\n prelude += ch;\n if (ch === \"\\\\\") prelude += css[++i] ?? \"\";\n else if (ch === quote) quote = null;\n } else if (ch === '\"' || ch === \"'\") {\n quote = ch;\n prelude += ch;\n } else if (ch === \"{\") break;\n else if (ch === \";\") {\n prelude = \"\"; // a statement (e.g. @import) – dropped\n } else if (ch === \"}\") {\n prelude = \"\"; // stray brace\n } else prelude += ch;\n i++;\n }\n if (i >= n) break;\n // css[i] === \"{\"\n i++;\n let depth = 1;\n let body = \"\";\n quote = null;\n while (i < n && depth > 0) {\n const ch = css[i]!;\n if (quote) {\n body += ch;\n if (ch === \"\\\\\") body += css[++i] ?? \"\";\n else if (ch === quote) quote = null;\n } else if (ch === '\"' || ch === \"'\") {\n quote = ch;\n body += ch;\n } else if (ch === \"{\") {\n depth++;\n body += ch;\n } else if (ch === \"}\") {\n depth--;\n if (depth > 0) body += ch;\n } else body += ch;\n i++;\n }\n out.push({ prelude: prelude.trim(), body });\n }\n return out;\n}\n\n/** Splits a selector list on top-level commas. */\nfunction splitSelectors(list: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let cur = \"\";\n for (const ch of list) {\n if (ch === \"(\" || ch === \"[\") depth++;\n else if (ch === \")\" || ch === \"]\") depth = Math.max(0, depth - 1);\n if (ch === \",\" && depth === 0) {\n out.push(cur.trim());\n cur = \"\";\n } else cur += ch;\n }\n if (cur.trim()) out.push(cur.trim());\n return out;\n}\n\nfunction safeUrl(raw: string): boolean {\n const u = raw.trim().replace(/^['\"]|['\"]$/g, \"\").trim();\n return /^https:\\/\\//i.test(u) || /^data:image\\/(png|jpe?g|gif|webp|svg\\+xml)[;,]/i.test(u);\n}\n\n/** Cleans one declaration list. */\nfunction cleanDeclarations(body: string): string {\n return body\n .replace(/url\\(([^)]*)\\)/gi, (m, inner: string) => (safeUrl(inner) ? m : \"none\"))\n .replace(/expression\\s*\\(/gi, \"(\")\n .replace(/javascript\\s*:/gi, \"\")\n .replace(/(^|[;{\\s])(-moz-binding|behavior)\\s*:[^;]*;?/gi, \"$1\")\n .replace(/[{}]/g, \"\")\n .trim();\n}\n\n/** Removes everything unsafe; keeps the rule structure. */\nexport function sanitizeCustomCss(input: string | null | undefined): string {\n if (!input) return \"\";\n let css = String(input).slice(0, MAX_CUSTOM_CSS);\n css = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/<(script|style)\\b[^>]*>[\\s\\S]*?<\\/\\1\\s*>/gi, \"\").replace(/<\\/?[a-z!][^>]*>/gi, \"\").replace(/</g, \"\");\n return render(splitBlocks(css), 0);\n}\n\nfunction render(blocks: Block[], depth: number): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (!b.prelude) continue;\n if (b.prelude.startsWith(\"@\")) {\n if (BLOCKED_AT_RULES.test(b.prelude) || !ALLOWED_AT_RULES.test(b.prelude)) continue;\n if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) {\n // Keyframe selectors (from/to/50%) and font-face descriptors are declarations-like.\n const inner = /^@font-face/i.test(b.prelude) ? cleanDeclarations(b.body) : splitBlocks(b.body).map((k) => `${k.prelude}{${cleanDeclarations(k.body)}}`).join(\"\");\n parts.push(`${b.prelude}{${inner}}`);\n } else if (depth < 3) parts.push(`${b.prelude}{${render(splitBlocks(b.body), depth + 1)}}`);\n continue;\n }\n const selectors = splitSelectors(b.prelude).filter((s) => !/:host|::slotted|::part/i.test(s));\n if (!selectors.length) continue;\n parts.push(`${selectors.join(\",\")}{${cleanDeclarations(b.body)}}`);\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * Prefixes every selector with `scope` (e.g. `.g-scope[data-guide=\"abc\"]`). `:root`, `html`,\n * `body`, `:scope` and `&` at the start of a selector refer to the container itself.\n */\nexport function scopeCustomCss(css: string, scope: string): string {\n return scopeBlocks(splitBlocks(sanitizeCustomCss(css)), scope, 0);\n}\n\nfunction scopeBlocks(blocks: Block[], scope: string, depth: number): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (b.prelude.startsWith(\"@\")) {\n if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) parts.push(`${b.prelude}{${b.body}}`);\n else if (depth < 3) parts.push(`${b.prelude}{${scopeBlocks(splitBlocks(b.body), scope, depth + 1)}}`);\n continue;\n }\n const sels = splitSelectors(b.prelude).map((s) => {\n const self = s.match(/^(:root|html|body|:scope|&)(?![\\w-])(.*)$/i);\n if (self) return `${scope}${self[2] ?? \"\"}`;\n return `${scope} ${s}`;\n });\n parts.push(`${sels.join(\",\")}{${b.body}}`);\n }\n return parts.join(\"\\n\");\n}\n","/**\n * Whether the Guidely API is reachable right now: a circuit breaker shared by everything the SDK\n * sends in the background (event batches, replay uploads, config refreshes, queued survey answers).\n *\n * Every API answer is reported here. After `threshold` failures in a row (network errors, timeouts,\n * 429, 5xx) the circuit opens for a cooldown that doubles with each further failure (5 s up to\n * 5 min, ±20% jitter so tabs don't retry in step); a `Retry-After` answer sets the cooldown\n * directly. While it is open, background senders wait `waitMs()` instead of sending. Requests the\n * person makes (a messenger message) still go out, and any answer closes the circuit again. The\n * browser's `online` event ends the cooldown early.\n */\nexport interface ServerHealthOptions {\n threshold?: number;\n baseMs?: number;\n maxMs?: number;\n now?: () => number;\n random?: () => number;\n}\n\n/** Longest `Retry-After` honoured, so a bad header can't silence the SDK for days. */\nconst MAX_RETRY_AFTER_MS = 60 * 60 * 1000;\n/** How long background senders wait while the browser reports being offline (the `online` event usually comes first). */\nconst OFFLINE_WAIT_MS = 30_000;\n\nexport class ServerHealth {\n private failures = 0;\n private openUntil = 0;\n private lastOkAt = 0;\n private readonly listeners = new Set<() => void>();\n private readonly threshold: number;\n private readonly baseMs: number;\n private readonly maxMs: number;\n private readonly now: () => number;\n private readonly random: () => number;\n\n constructor(opts: ServerHealthOptions = {}) {\n this.threshold = opts.threshold ?? 3;\n this.baseMs = opts.baseMs ?? 5000;\n this.maxMs = opts.maxMs ?? 5 * 60 * 1000;\n this.now = opts.now ?? Date.now;\n this.random = opts.random ?? Math.random;\n }\n\n /** The server answered (2xx, 3xx, or a 4xx other than 429): it is up. */\n success(): void {\n const wasDown = this.failures > 0 || this.openUntil > 0;\n this.failures = 0;\n this.openUntil = 0;\n this.lastOkAt = this.now();\n if (wasDown) this.notify();\n }\n\n /** The request failed or the server is overloaded. `retryAfterMs` comes from a `Retry-After` header. */\n failure(retryAfterMs?: number | null): void {\n this.failures += 1;\n const now = this.now();\n if (retryAfterMs != null && retryAfterMs > 0) {\n this.openUntil = Math.max(this.openUntil, now + Math.min(retryAfterMs, MAX_RETRY_AFTER_MS));\n return;\n }\n if (this.failures < this.threshold) return;\n const cooldown = Math.min(this.maxMs, this.baseMs * 2 ** (this.failures - this.threshold));\n this.openUntil = Math.max(this.openUntil, now + cooldown * (0.8 + this.random() * 0.4));\n }\n\n /** Milliseconds background traffic should wait before trying again (0: send now). */\n waitMs(): number {\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) return OFFLINE_WAIT_MS;\n return Math.max(0, this.openUntil - this.now());\n }\n\n canSend(): boolean {\n return this.waitMs() === 0;\n }\n\n /**\n * The last request got an answer. Unload beacons can't report back, so what they carry is only\n * forgotten while this holds; otherwise it stays queued and is sent again (the server drops duplicates).\n */\n get reachable(): boolean {\n return this.failures === 0 && this.lastOkAt > 0;\n }\n\n /** The browser came back online: end the cooldown and let queued traffic try straight away. */\n online(): void {\n this.openUntil = 0;\n this.notify();\n }\n\n /** Called when the server answers again after failures, or the browser comes back online. */\n onRecover(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n private notify(): void {\n for (const cb of Array.from(this.listeners)) {\n try {\n cb();\n } catch {\n /* a listener must not break the others */\n }\n }\n }\n}\n\n/** `Retry-After` as milliseconds: delta-seconds or an HTTP date. Null when absent or unparseable. */\nexport function parseRetryAfter(value: string | null | undefined, now = Date.now()): number | null {\n if (!value) return null;\n const trimmed = value.trim();\n if (/^\\d+$/.test(trimmed)) return Number(trimmed) * 1000;\n const at = Date.parse(trimmed);\n return Number.isNaN(at) ? null : Math.max(0, at - now);\n}\n\n/** Answers that mean the server is down or shedding load (retry later) rather than refusing the request. */\nexport function isServerFailure(status: number): boolean {\n return status === 429 || status >= 500;\n}\n","import { isServerFailure, parseRetryAfter, ServerHealth } from \"./health\";\n\nexport interface ApiResponse<T> {\n status: number;\n ok: boolean;\n data: T | null;\n etag: string | null;\n}\n\nexport type FetchLike = typeof fetch;\n\n/** Reply streams: the response must start within this long, and then never go quiet longer than the idle limit (the server sends a keepalive every 15 s). */\nexport const STREAM_RESPONSE_TIMEOUT_MS = 30_000;\nexport const STREAM_IDLE_TIMEOUT_MS = 60_000;\n\n/** Thin HTTP client for the public SDK API. Adds the public key as query + header. */\nexport class Api {\n /** Reachability of the API, fed by every answer (see {@link ServerHealth}). */\n readonly health: ServerHealth;\n\n constructor(\n private readonly baseUrl: string,\n private readonly key: string,\n private readonly fetchImpl?: FetchLike,\n health?: ServerHealth,\n ) {\n this.health = health ?? new ServerHealth();\n }\n\n /** Feeds an answer (or a failed request, `null`) into {@link health}. */\n private observe(res: Response | null): void {\n if (!res) this.health.failure();\n else if (isServerFailure(res.status)) this.health.failure(parseRetryAfter(res.headers?.get?.(\"retry-after\")));\n else this.health.success();\n }\n\n url(path: string, params: Record<string, string | undefined> = {}): string {\n // Built by hand rather than with URL/searchParams, which React Native does not implement.\n const query = Object.entries({ key: this.key, ...params })\n .filter((e): e is [string, string] => e[1] != null)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n return `${this.baseUrl.replace(/\\/$/, \"\")}/api/v1/sdk${path}?${query}`;\n }\n\n private get fetcher(): FetchLike | null {\n if (this.fetchImpl) return this.fetchImpl;\n return typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n }\n\n async request<T>(method: \"GET\" | \"POST\", path: string, options: { body?: unknown; etag?: string | null; params?: Record<string, string | undefined>; keepalive?: boolean; timeoutMs?: number; headers?: Record<string, string> } = {}): Promise<ApiResponse<T>> {\n const f = this.fetcher;\n if (!f) throw new Error(\"fetch is not available\");\n const headers: Record<string, string> = { ...options.headers, \"X-Guidely-Key\": this.key, Accept: \"application/json\" };\n // Multipart bodies set their own Content-Type (with the boundary).\n const form = typeof FormData !== \"undefined\" && options.body instanceof FormData;\n if (options.body !== undefined && !form) headers[\"Content-Type\"] = \"application/json\";\n if (options.etag) headers[\"If-None-Match\"] = options.etag;\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ac ? setTimeout(() => ac.abort(), options.timeoutMs ?? 10000) : null;\n try {\n let res: Response;\n try {\n res = await f(this.url(path, options.params), {\n method,\n headers,\n body: options.body === undefined ? undefined : form ? (options.body as FormData) : JSON.stringify(options.body),\n keepalive: options.keepalive,\n signal: ac?.signal,\n credentials: \"omit\",\n mode: \"cors\",\n });\n } catch (err) {\n this.observe(null);\n throw err;\n }\n this.observe(res);\n let data: T | null = null;\n if (res.status !== 304 && res.status !== 204) {\n try {\n data = (await res.json()) as T;\n } catch {\n data = null;\n }\n }\n return { status: res.status, ok: res.ok, data, etag: res.headers?.get?.(\"etag\") ?? null };\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n get<T>(path: string, options?: { etag?: string | null; params?: Record<string, string | undefined>; headers?: Record<string, string> }): Promise<ApiResponse<T>> {\n return this.request<T>(\"GET\", path, options);\n }\n\n post<T>(path: string, body: unknown, options?: { params?: Record<string, string | undefined>; keepalive?: boolean; headers?: Record<string, string> }): Promise<ApiResponse<T>> {\n return this.request<T>(\"POST\", path, { body, ...options });\n }\n\n /** Multipart POST (file uploads). No Content-Type header: the browser adds it with the boundary. */\n postForm<T>(path: string, form: FormData, options?: { params?: Record<string, string | undefined>; timeoutMs?: number }): Promise<ApiResponse<T>> {\n return this.request<T>(\"POST\", path, { body: form, ...options });\n }\n\n /**\n * POST that may answer with server-sent events. Each event is passed to `onEvent`; a JSON answer is\n * returned instead. Scout replies can take a while, so there is no overall timeout: the response\n * must start within 30 s and then never go quiet for more than 60 s (the server sends keepalives),\n * otherwise the request is aborted and rejects.\n */\n async stream<T>(path: string, body: unknown, onEvent: (event: string, data: unknown) => void, headers: Record<string, string> = {}): Promise<ApiResponse<T>> {\n const f = this.fetcher;\n if (!f) throw new Error(\"fetch is not available\");\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const arm = (ms: number) => {\n if (!ac) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => ac.abort(), ms);\n };\n arm(STREAM_RESPONSE_TIMEOUT_MS);\n try {\n let res: Response;\n try {\n res = await f(this.url(path), {\n method: \"POST\",\n headers: { ...headers, \"X-Guidely-Key\": this.key, Accept: \"text/event-stream, application/json\", \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: ac?.signal,\n credentials: \"omit\",\n mode: \"cors\",\n });\n } catch (err) {\n this.observe(null);\n throw err;\n }\n this.observe(res);\n const type = res.headers?.get?.(\"content-type\") ?? \"\";\n if (!type.includes(\"text/event-stream\") || !res.body) {\n let data: T | null = null;\n try {\n data = (await res.json()) as T;\n } catch {\n data = null;\n }\n return { status: res.status, ok: res.ok, data, etag: null };\n }\n arm(STREAM_IDLE_TIMEOUT_MS);\n await readEventStream(res.body, onEvent, () => arm(STREAM_IDLE_TIMEOUT_MS));\n return { status: res.status, ok: res.ok, data: null, etag: null };\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n /** `navigator.sendBeacon` when available (page unload); returns false when it could not be queued. */\n beacon(path: string, body: unknown): boolean {\n try {\n if (typeof navigator === \"undefined\" || typeof navigator.sendBeacon !== \"function\") return false;\n // text/plain is a CORS-safelisted type: cross-origin beacons need no preflight (which\n // browsers drop during unload). The API parses the body regardless of content type.\n const blob = new Blob([JSON.stringify(body)], { type: \"text/plain;charset=UTF-8\" });\n return navigator.sendBeacon(this.url(path), blob);\n } catch {\n return false;\n }\n }\n}\n\nexport const sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n/** Exponential backoff helper: 1s → 2s → 4s … capped. */\nexport function backoffMs(attempt: number, baseMs = 1000, maxMs = 30000): number {\n return Math.min(maxMs, baseMs * 2 ** Math.max(0, attempt));\n}\n\n/**\n * Sends with bounded retries: network errors, 429 and 5xx are retried with backoff; success and\n * other 4xx answers are returned as they are. Null when every attempt failed.\n */\nexport async function withRetry<T>(send: () => Promise<ApiResponse<T>>, attempts = 3, baseMs = 500): Promise<ApiResponse<T> | null> {\n for (let i = 0; i < attempts; i++) {\n try {\n const res = await send();\n if (res.ok || (res.status >= 400 && res.status < 500 && res.status !== 429)) return res;\n } catch {\n /* network error → retry */\n }\n if (i < attempts - 1) await sleep(backoffMs(i, baseMs, 8000));\n }\n return null;\n}\n\n/** Fire-and-forget POST with bounded retries (used for state sync; never blocks UI). */\nexport function postWithRetry<T>(api: Api, path: string, body: unknown, attempts = 3, baseMs = 500): Promise<ApiResponse<T> | null> {\n return withRetry(() => api.post<T>(path, body), attempts, baseMs);\n}\n\n/** Parses a `text/event-stream` body (`event:` + single-line JSON `data:`; comment lines ignored). `onChunk` runs whenever bytes arrive. */\nexport async function readEventStream(body: ReadableStream<Uint8Array>, onEvent: (event: string, data: unknown) => void, onChunk?: () => void): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const dispatch = (raw: string) => {\n let event = \"message\";\n const data: string[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) continue;\n const i = line.indexOf(\":\");\n const field = i < 0 ? line : line.slice(0, i);\n const value = i < 0 ? \"\" : line.slice(i + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n }\n if (!data.length) return;\n try {\n onEvent(event, JSON.parse(data.join(\"\\n\")));\n } catch {\n /* ignore malformed events */\n }\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (value) onChunk?.();\n if (value) buffer += decoder.decode(value, { stream: true }).replace(/\\r\\n?/g, \"\\n\");\n let sep: number;\n while ((sep = buffer.indexOf(\"\\n\\n\")) >= 0) {\n dispatch(buffer.slice(0, sep));\n buffer = buffer.slice(sep + 2);\n }\n if (done) break;\n }\n if (buffer.trim()) dispatch(buffer);\n}\n","export type StorageKind = \"local\" | \"session\" | \"memory\";\n\n/** Minimal synchronous key/value store; never throws (private mode, quota, SSR). */\nexport interface KeyValueStore {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport function memoryStore(): KeyValueStore {\n const map = new Map<string, string>();\n return { get: (k) => map.get(k) ?? null, set: (k, v) => void map.set(k, v), remove: (k) => void map.delete(k) };\n}\n\nfunction webStore(area: \"localStorage\" | \"sessionStorage\"): KeyValueStore | null {\n try {\n if (typeof window === \"undefined\") return null;\n const s = window[area];\n if (!s) return null;\n const probe = \"__guidely_probe__\";\n s.setItem(probe, \"1\");\n s.removeItem(probe);\n return {\n get: (k) => {\n try {\n return s.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n s.setItem(k, v);\n } catch {\n /* quota / private mode */\n }\n },\n remove: (k) => {\n try {\n s.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n } catch {\n return null;\n }\n}\n\n/** Creates a store of the requested kind, degrading to memory when unavailable. */\nexport function createStorage(kind: StorageKind = \"local\"): KeyValueStore {\n if (kind === \"memory\") return memoryStore();\n return webStore(kind === \"local\" ? \"localStorage\" : \"sessionStorage\") ?? memoryStore();\n}\n\nexport function readJson<T>(store: KeyValueStore, key: string, fallback: T): T {\n const raw = store.get(key);\n if (raw == null) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n}\n\nexport function writeJson(store: KeyValueStore, key: string, value: unknown): void {\n try {\n store.set(key, JSON.stringify(value));\n } catch {\n /* ignore */\n }\n}\n\n/** Storage keys used by the SDK (documented for integrators). */\nexport const KEYS = {\n anon: \"guidely:anon\",\n seen: \"guidely:seen\",\n config: (key: string) => `guidely:config:${key}`,\n etag: (key: string) => `guidely:etag:${key}`,\n state: (key: string) => `guidely:state:${key}`,\n user: (key: string) => `guidely:user:${key}`,\n queue: (key: string) => `guidely:queue:${key}`,\n /** Survey answers and guide/checklist progress not yet accepted by the server. */\n outbox: (key: string) => `guidely:outbox:${key}`,\n /** Agent Analytics turns not yet accepted by the server. */\n agentOutbox: (key: string) => `guidely:agents:${key}`,\n session: \"guidely:session\",\n active: \"guidely:active\",\n authoring: \"guidely:authoring\",\n /** How-to capture session marker ({ token, … }) and its not-yet-uploaded steps. */\n capture: \"guidely:capture\",\n capturePending: \"guidely:capture:pending\",\n /** Messenger conversations this browser can read: [{ id, token }]. */\n conversations: (key: string) => `guidely:conversations:${key}`,\n /** Announcement ids opened in the messenger's News tab. */\n newsSeen: (key: string) => `guidely:news:${key}`,\n /** Where the visitor dragged the messenger launcher ({ side, y }). */\n launcher: (key: string) => `guidely:launcher:${key}`,\n} as const;\n","import type { SdkEvent } from \"@guidelytech/shared\";\nimport type { ServerHealth } from \"./health\";\nimport { backoffMs } from \"./http\";\nimport { readJson, writeJson, type KeyValueStore } from \"./storage\";\n\nexport interface EventQueueOptions {\n store: KeyValueStore;\n storageKey: string;\n /** Sends one batch. Resolve `{ ok: true }` on success, `{ ok: false, retry }` otherwise. */\n send: (events: SdkEvent[]) => Promise<{ ok: boolean; retry?: boolean }>;\n /** Synchronous best-effort send used on page hide. */\n beacon?: (events: SdkEvent[]) => boolean;\n /** Should events be flushed right now? (analytics enabled + consent granted). */\n enabled: () => boolean;\n /** API reachability: sends wait while its circuit is open, and beaconed events are only forgotten while it is reachable. */\n health?: ServerHealth;\n flushIntervalMs?: number;\n maxQueue?: number;\n batchSize?: number;\n maxAttempts?: number;\n onError?: (err: unknown) => void;\n}\n\n/**\n * Bounded, persisted event queue. Batches ≤50 events every 2s (or on demand), dedupes by\n * `eventId`, and keeps failed events (also across page loads) until the server takes them:\n * retries back off 1s→60s, wait while the API's circuit is open, and start again as soon as it\n * recovers. Drops the oldest events once the queue exceeds 500.\n */\nexport class EventQueue {\n private events: SdkEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private inflight = false;\n private inflightIds = new Set<string>();\n private attempt = 0;\n private destroyed = false;\n private offRecover: (() => void) | null = null;\n private readonly flushIntervalMs: number;\n private readonly maxQueue: number;\n private readonly batchSize: number;\n private readonly maxAttempts: number;\n\n constructor(private readonly opts: EventQueueOptions) {\n this.flushIntervalMs = opts.flushIntervalMs ?? 2000;\n this.maxQueue = opts.maxQueue ?? 500;\n this.batchSize = opts.batchSize ?? 50;\n this.maxAttempts = opts.maxAttempts ?? 5;\n const persisted = readJson<SdkEvent[]>(opts.store, opts.storageKey, []);\n if (Array.isArray(persisted)) this.events = persisted.filter((e) => e && typeof e.eventId === \"string\").slice(-this.maxQueue);\n // Events left over from a previous page load are flushed on the next tick.\n if (this.events.length) this.schedule();\n this.offRecover = opts.health?.onRecover(() => this.retryNow()) ?? null;\n }\n\n /** The API is back: drop any pending backoff and send what is queued. */\n private retryNow(): void {\n if (this.destroyed) return;\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = null;\n this.attempt = 0;\n void this.flush();\n }\n\n private retryIn(ms: number): void {\n if (this.retryTimer || this.destroyed) return;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n void this.flush();\n }, ms);\n }\n\n get size(): number {\n return this.events.length;\n }\n\n /** Pending events (read-only copy, for debugging). */\n peek(): SdkEvent[] {\n return this.events.slice();\n }\n\n enqueue(event: SdkEvent): void {\n if (this.destroyed) return;\n if (this.events.some((e) => e.eventId === event.eventId)) return;\n this.events.push(event);\n if (this.events.length > this.maxQueue) this.events.splice(0, this.events.length - this.maxQueue);\n this.persist();\n this.schedule();\n }\n\n private persist(): void {\n writeJson(this.opts.store, this.opts.storageKey, this.events);\n }\n\n private schedule(): void {\n if (this.timer || this.retryTimer || this.destroyed) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, this.flushIntervalMs);\n }\n\n /** Sends queued events now (one batch at a time). Safe to call at any time. */\n async flush(): Promise<void> {\n if (this.destroyed || this.inflight || !this.events.length || !this.opts.enabled()) return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n const wait = this.opts.health?.waitMs() ?? 0;\n if (wait > 0) return this.retryIn(wait);\n this.inflight = true;\n const batch = this.events.slice(0, this.batchSize);\n this.inflightIds = new Set(batch.map((e) => e.eventId));\n let ok = false;\n let retry = true;\n try {\n const res = await this.opts.send(batch);\n ok = res.ok;\n retry = res.retry ?? !res.ok;\n } catch (err) {\n this.opts.onError?.(err);\n }\n this.inflight = false;\n this.inflightIds.clear();\n if (this.destroyed) return;\n if (ok || !retry) {\n const ids = new Set(batch.map((e) => e.eventId));\n this.events = this.events.filter((e) => !ids.has(e.eventId));\n this.attempt = 0;\n this.persist();\n if (this.events.length) this.schedule();\n return;\n }\n // Fast retries first, then about once a minute until the server takes the events (or the\n // API's circuit says to wait longer); a recovery or the next page load sends them sooner.\n this.attempt = Math.min(this.attempt + 1, this.maxAttempts);\n const delay = this.attempt >= this.maxAttempts ? 60_000 : backoffMs(this.attempt - 1);\n this.retryIn(Math.max(delay, this.opts.health?.waitMs() ?? 0));\n }\n\n /** Best-effort synchronous flush on unload using `sendBeacon`. */\n flushSync(): void {\n if (this.destroyed || !this.opts.enabled() || !this.opts.beacon) return;\n // Events already in flight (fetch with keepalive) survive unload; only beacon the rest to avoid duplicate batches.\n const batch = this.events.filter((e) => !this.inflightIds.has(e.eventId)).slice(0, this.batchSize);\n if (!batch.length) return;\n // A beacon that was queued may still never arrive (the server is down), and nothing reports\n // back. Only forget its events while the API is answering; otherwise they stay persisted and the\n // next page load sends them again (the server drops events it already has, by eventId).\n if (this.opts.beacon(batch) && (this.opts.health?.reachable ?? true)) {\n const ids = new Set(batch.map((e) => e.eventId));\n this.events = this.events.filter((e) => !ids.has(e.eventId));\n }\n this.persist();\n }\n\n clear(): void {\n this.events = [];\n this.persist();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.offRecover?.();\n if (this.timer) clearTimeout(this.timer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.timer = null;\n this.retryTimer = null;\n this.persist();\n }\n}\n","import type { ServerHealth } from \"./health\";\nimport { backoffMs, type Api } from \"./http\";\nimport { readJson, writeJson, type KeyValueStore } from \"./storage\";\n\n/** One request waiting to reach the server. */\ninterface OutboxItem {\n /** Same key → the newer request replaces the older one (e.g. a checklist's latest progress). */\n key: string;\n path: string;\n body: unknown;\n createdAt: number;\n}\n\nexport interface OutboxOptions {\n api: Api;\n store: KeyValueStore;\n storageKey: string;\n health?: ServerHealth;\n maxItems?: number;\n maxAgeMs?: number;\n onError?: (err: unknown) => void;\n}\n\n/**\n * Persisted queue for writes that must not be lost when the API is down: survey answers, guide\n * completions and checklist progress. Each request is kept (also across page loads) until the\n * server answers it; 5xx, 429 and network errors are retried with backoff, waiting while the API's\n * circuit is open. Every request is idempotent on the server (survey answers dedupe by\n * `responseId`, progress merges), so sending one twice is harmless. Bounded to 50 requests and 7 days.\n */\nexport class Outbox {\n private items: OutboxItem[];\n private sending = false;\n private attempt = 0;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n private readonly offRecover: (() => void) | null;\n private readonly maxItems: number;\n private readonly maxAgeMs: number;\n\n constructor(private readonly opts: OutboxOptions) {\n this.maxItems = opts.maxItems ?? 50;\n this.maxAgeMs = opts.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;\n const stored = readJson<OutboxItem[]>(opts.store, opts.storageKey, []);\n const cutoff = Date.now() - this.maxAgeMs;\n this.items = Array.isArray(stored) ? stored.filter((i) => i && typeof i.path === \"string\" && typeof i.key === \"string\" && i.createdAt > cutoff).slice(-this.maxItems) : [];\n this.offRecover = opts.health?.onRecover(() => {\n this.attempt = 0;\n this.retryIn(0);\n }) ?? null;\n if (this.items.length) this.retryIn(0);\n }\n\n get size(): number {\n return this.items.length;\n }\n\n /** Queues `POST path` and sends it now (or as soon as the API is reachable). */\n add(key: string, path: string, body: unknown): void {\n if (this.destroyed) return;\n this.items = this.items.filter((i) => i.key !== key);\n this.items.push({ key, path, body, createdAt: Date.now() });\n if (this.items.length > this.maxItems) this.items.splice(0, this.items.length - this.maxItems);\n this.persist();\n void this.flush();\n }\n\n private persist(): void {\n writeJson(this.opts.store, this.opts.storageKey, this.items);\n }\n\n private retryIn(ms: number): void {\n if (this.destroyed) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, ms);\n }\n\n /** Sends queued requests in order, one at a time. */\n async flush(): Promise<void> {\n if (this.destroyed || this.sending || !this.items.length) return;\n const wait = this.opts.health?.waitMs() ?? 0;\n if (wait > 0) return this.retryIn(wait);\n this.sending = true;\n try {\n while (this.items.length && !this.destroyed) {\n const item = this.items[0] as OutboxItem;\n let retry = false;\n try {\n const res = await this.opts.api.post(item.path, item.body);\n retry = !res.ok && (res.status === 429 || res.status >= 500);\n } catch (err) {\n retry = true;\n this.opts.onError?.(err);\n }\n if (retry) {\n this.attempt += 1;\n this.retryIn(Math.max(backoffMs(this.attempt - 1, 1000, 60_000), this.opts.health?.waitMs() ?? 0));\n return;\n }\n // Answered (or refused for good, e.g. the survey was deleted): done with it. A newer request\n // under the same key may have replaced it while this one was in flight; keep that one.\n this.attempt = 0;\n this.items = this.items.filter((i) => i !== item);\n this.persist();\n }\n } finally {\n this.sending = false;\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n this.offRecover?.();\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n}\n","type AnyFn = (...args: any[]) => void;\n\n/** Tiny typed event emitter. Listener errors are reported, never thrown into the caller. */\nexport class Emitter<Events extends { [K in keyof Events]: AnyFn }> {\n private listeners = new Map<keyof Events, Set<AnyFn>>();\n constructor(private readonly onError?: (err: unknown) => void) {}\n\n on<K extends keyof Events>(event: K, cb: Events[K]): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(cb);\n return () => this.off(event, cb);\n }\n\n off<K extends keyof Events>(event: K, cb: Events[K]): void {\n this.listeners.get(event)?.delete(cb);\n }\n\n emit<K extends keyof Events>(event: K, ...args: Parameters<Events[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const cb of Array.from(set)) {\n try {\n cb(...args);\n } catch (err) {\n this.onError?.(err);\n }\n }\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","import type { FrequencyConfig, GuideThrottlingSettings, PublishedGuide } from \"@guidelytech/shared\";\n\n/** Per-guide state kept locally and merged with the server's `IdentifyResponse.guideState`. */\nexport interface GuideLocalState {\n impressions: number;\n completedAt?: string | null;\n dismissedAt?: string | null;\n lastShownAt?: string | null;\n /** Last step reached in a multi-step flow (local only), so the messenger can offer to resume it. */\n lastStepId?: string | null;\n}\n\nconst HOUR = 3600 * 1000;\n\n/**\n * Pure frequency evaluation. `shownThisSession` comes from session storage.\n * - `once`: a single impression ever (unless `reshowAfterDismiss` and it was only dismissed).\n * - `once_per_session`: at most once per browser session.\n * - `every_time`: on every trigger (still blocked by completion/dismissal rules below).\n * - `interval`: at most once every `intervalHours`.\n * `maxImpressions` caps total impressions; dismissal blocks re-showing unless `reshowAfterDismiss`\n * (then `cooldownHours` must have elapsed); completion blocks unless mode is `every_time`.\n */\nexport function isFrequencyEligible(freq: FrequencyConfig, state: GuideLocalState | undefined, shownThisSession: boolean, now: number = Date.now()): boolean {\n const s = state ?? { impressions: 0 };\n if (freq.maxImpressions != null && s.impressions >= freq.maxImpressions) return false;\n if (s.completedAt && freq.mode !== \"every_time\") return false;\n if (s.dismissedAt) {\n if (!freq.reshowAfterDismiss) return false;\n if (freq.cooldownHours > 0 && now - Date.parse(s.dismissedAt) < freq.cooldownHours * HOUR) return false;\n }\n switch (freq.mode) {\n case \"once\":\n return s.impressions === 0 || (!!s.dismissedAt && freq.reshowAfterDismiss);\n case \"once_per_session\":\n return !shownThisSession;\n case \"interval\": {\n if (!s.lastShownAt) return true;\n const hours = freq.intervalHours ?? 24;\n return now - Date.parse(s.lastShownAt) >= hours * HOUR;\n }\n case \"every_time\":\n default:\n return true;\n }\n}\n\n/**\n * Exclusive guides (flows, modals, tooltips, announcements, surveys) run one at a time.\n * Banners, checklists and hotspot-only tooltips can coexist with an active flow.\n */\nexport function isExclusiveGuide(guide: PublishedGuide): boolean {\n if (guide.kind === \"banner\" || guide.kind === \"checklist\") return false;\n const steps = guide.config.steps;\n if (steps.length > 0 && steps.every((s) => s.type === \"hotspot\" || s.type === \"banner\")) return false;\n return true;\n}\n\n/** Is `a` mutually exclusive with `b` (by id or key, in either direction)? */\nexport function areMutuallyExclusive(a: PublishedGuide, b: PublishedGuide): boolean {\n const la = a.config.frequency.mutuallyExclusiveWith;\n const lb = b.config.frequency.mutuallyExclusiveWith;\n return la.includes(b.id) || la.includes(b.key) || lb.includes(a.id) || lb.includes(a.key);\n}\n\n/**\n * Scheduling window: the guide's `schedule` (any kind) and, for surveys, `survey.startAt` / `endAt`.\n * Unparsable dates are ignored.\n */\nexport function isWithinSchedule(guide: Pick<PublishedGuide, \"config\">, now: number = Date.now()): boolean {\n for (const w of [guide.config.schedule, guide.config.survey]) {\n if (!w) continue;\n if (w.startAt && now < Date.parse(w.startAt)) return false;\n if (w.endAt && now > Date.parse(w.endAt)) return false;\n }\n return true;\n}\n\nconst MINUTE = 60 * 1000;\n\n/**\n * Does showing this guide automatically count toward (and get limited by) the project's guide\n * throttling? Only exclusive guides (flows, modals, tooltips, announcements, surveys) interrupt;\n * banners, checklists and hotspot-only guides never count, nor does a guide set to ignore throttling.\n * Guides started by the visitor or the app (`startGuide`, buttons, Help) are never throttled.\n */\nexport function countsTowardThrottle(guide: PublishedGuide): boolean {\n return isExclusiveGuide(guide) && !guide.config.frequency.ignoreThrottling;\n}\n\n/**\n * Pure throttling check. `launches` = ISO times of this visitor's earlier automatic launches of\n * counted guides (any order). Disabled or missing settings never throttle.\n */\nexport function isThrottleEligible(settings: GuideThrottlingSettings | null | undefined, launches: readonly string[], now: number = Date.now()): boolean {\n if (!settings || !settings.enabled) return true;\n const times = launches.map((l) => Date.parse(l)).filter((t) => !Number.isNaN(t));\n const windowMs = Math.max(1, settings.windowHours) * HOUR;\n if (times.filter((t) => now - t < windowMs).length >= Math.max(1, settings.maxGuides)) return false;\n if (settings.minGapMinutes > 0 && times.some((t) => now - t < settings.minGapMinutes * MINUTE)) return false;\n return true;\n}\n\n/** Launch times worth keeping: those still inside the window or the minimum gap (at most 100). */\nexport function pruneLaunches(launches: readonly string[], settings: GuideThrottlingSettings | null | undefined, now: number = Date.now()): string[] {\n const keepMs = Math.max(settings?.windowHours ?? 24, 1) * HOUR + (settings?.minGapMinutes ?? 0) * MINUTE;\n return launches.filter((l) => { const t = Date.parse(l); return !Number.isNaN(t) && now - t < keepMs; }).slice(-100);\n}\n\n/**\n * A checklist's dismissal after merging server state. A local dismissal normally wins (it may not have\n * synced yet), but when the server reports a reset this device hasn't applied, the server's value wins:\n * null, or a dismissal made on another device after the reset. Compared as tokens, not times, so a\n * skewed device clock can't keep a reset dismissal.\n */\nexport function dismissedAfterMerge(local: { dismissedAt?: string | null; dismissResetAt?: string | null } | undefined, server: { dismissedAt?: string | null; dismissResetAt?: string | null }): string | null {\n if (server.dismissResetAt && server.dismissResetAt !== local?.dismissResetAt) return server.dismissedAt ?? null;\n return local?.dismissedAt ?? server.dismissedAt ?? null;\n}\n","import { evaluateRules, guidelyIdFromSelector, rolloutBucket, isChecklistComplete, localizeGuide, localizeResourceCenter, normalizeLocale, orderedModules, randomId, RC_MODULE_IDS, type ResourceCenterModuleId, sanitizeProperties, screenPath, supportsPlatform, unreadAnnouncements, visibleAnnouncements, visitorLocales } from \"@guidelytech/shared/runtime\";\nimport type { AutocaptureSettings, ChecklistTask, EventName, IdentifyRequest, IdentifyResponse, ProjectTheme, PublishedGuide, ResourceCenterAnnouncement, ResourceCenterArticle, ResourceCenterConfig, RuleGroup, SdkConfigResponse, SdkEvent, StepButton, TargetingContext } from \"@guidelytech/shared\";\nimport {\n Api,\n Emitter,\n EventQueue,\n KEYS,\n Outbox,\n areMutuallyExclusive,\n countsTowardThrottle,\n dismissedAfterMerge,\n isExclusiveGuide,\n isFrequencyEligible,\n isThrottleEligible,\n isWithinSchedule,\n postWithRetry,\n pruneLaunches,\n readJson,\n writeJson,\n type ChecklistProgressState,\n type ConsentState,\n type GuideLocalState,\n type GuidelyAccount,\n type GuidelyUser,\n type PersistedState,\n type SessionState,\n} from \"@guidelytech/sdk-core/headless\";\nimport { createFlagsClient, type Attributes, type EvaluationResult, type FlagDetails, type FlagValue, type FlagsClient, type JsonValue } from \"@guidelytech/flags\";\nimport { LAUNCHER_PLACEMENT_KEY, parsePlacement, serializePlacement, type LauncherPlacement } from \"./launcherPlacement\";\nimport { HeatmapBuffer, heatmapPoint, RageClickDetector, tapProperties, type TapElement, type TapInfo } from \"./autocapture\";\nimport { runGuide, screenMatches, type GuideController } from \"./controller\";\nimport { fetchStreamPost, Messenger, xhrStreamPost, type MessengerTab } from \"./messenger\";\nimport { ReplayUploader, SessionRecorder, type ReplayCaptureOptions, type ScreenCapturer, type TouchPhase } from \"./replay\";\nimport { PersistentStore } from \"./storage\";\nimport { TargetRegistry, type Rect } from \"./targets\";\nimport type { ChecklistView, DeviceEnvironment, GuidelyEvents, GuidelyOptions, StepView, SurveyView, UiState } from \"./types\";\n\nexport const SDK_NAME = \"@guidelytech/react-native\";\nexport const SDK_VERSION = \"0.14.0\";\nexport const DEFAULT_API_URL = \"https://guidelytech.com\";\n\n/** Host-platform services the engine needs; the provider supplies React Native implementations. */\nexport interface PlatformBridge {\n device: DeviceEnvironment;\n /** Opens an external URL (React Native `Linking.openURL`). */\n openExternal(url: string): void;\n /** Window size in points (React Native `Dimensions.get(\"window\")`), for heatmaps. */\n windowSize?(): { width: number; height: number };\n /** Session-replay screenshots; absent where the native replay module is not installed. */\n capturer?: ScreenCapturer;\n}\n\ntype EvalReason = \"ready\" | \"navigation\" | \"event\" | \"click\" | \"visible\" | \"identify\" | \"after_guide\" | \"timer\" | \"manual\";\ninterface EvalDetail {\n eventName?: string;\n targetId?: string;\n guideId?: string;\n endedGuide?: PublishedGuide;\n newAudiences?: Set<string>;\n}\n\ninterface RunningFlow {\n guide: PublishedGuide;\n controller: GuideController;\n manual: boolean;\n view: StepView | null;\n}\n\ninterface QueuedGuide {\n guide: PublishedGuide;\n url: string;\n pageScoped: boolean;\n}\n\n/** Mobile sessions persist across launches and expire after the configured inactivity timeout. */\ninterface MobileSession extends SessionState {\n lastActiveAt: string;\n}\n\nconst PAGE_SCOPED = new Set([\"page_load\", \"url_match\", \"element_click\", \"element_visible\", \"delay\"]);\n\n/**\n * With a cached config, start from it when the server takes longer than this to answer (config or\n * identify): guides, the messenger and flags keep working through an outage, and the fresh answer\n * is applied when it arrives.\n */\nconst CACHED_START_MS = 1500;\n\n/** Resolves true when `promise` settles within `ms`, false otherwise (it keeps running either way). */\nfunction settlesWithin(promise: Promise<unknown>, ms: number): Promise<boolean> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(false), ms);\n const done = () => {\n clearTimeout(timer);\n resolve(true);\n };\n promise.then(done, done);\n });\n}\n\n/** `{ appVersion, build }` of the last launch, per public key (app_install / app_update detection). */\nconst appVersionKey = (key: string) => `guidely:app:${key}`;\n\n/** Stand-in for a tap whose view could not be identified (rage taps still need properties). */\nconst UNKNOWN_VIEW: TapElement = { selector: \"View\", tag: \"View\" };\n\nconst nowIso = () => new Date().toISOString();\nconst emptyState = (): PersistedState => ({ guides: {}, checklists: {}, surveysSubmitted: [], audienceIds: [] });\nconst newSession = (): MobileSession => ({ id: `s_${randomId(16)}`, startedAt: nowIso(), lastActiveAt: nowIso(), shownGuides: [], events: [] });\n\n/**\n * The React Native Guidely client: the web SDK's engine (config, identity, events, triggers,\n * frequency, checklists, surveys) with screens instead of URLs and `<GuidelyTarget>` views instead\n * of DOM elements. The overlay renders whatever {@link getUiState} describes.\n */\nexport class GuidelyClient {\n readonly options: Readonly<GuidelyOptions & { environment: NonNullable<GuidelyOptions[\"environment\"]>; apiUrl: string; analytics: boolean; configRefreshMs: number; debug: boolean }>;\n readonly targets = new TargetRegistry();\n private readonly bridge: PlatformBridge;\n private readonly api: Api;\n private readonly store: PersistentStore;\n private readonly emitter: Emitter<GuidelyEvents>;\n private queue: EventQueue | null = null;\n /** Survey answers, guide completions/dismissals and checklist progress, kept until the server has them. */\n private outbox: Outbox | null = null;\n private config: SdkConfigResponse | null = null;\n private configFetchedAt = 0;\n private etag: string | null = null;\n private anonymousId = \"\";\n private user: GuidelyUser | null = null;\n private state: PersistedState = emptyState();\n private session: MobileSession = newSession();\n private consent: ConsentState;\n private readyPromise: Promise<void> | null = null;\n private hydrated = false;\n private pending: Array<() => void> = [];\n private isReady = false;\n private destroyed = false;\n private active: RunningFlow | null = null;\n private activeSurvey: { guide: PublishedGuide; manual: boolean } | null = null;\n private queued: QueuedGuide[] = [];\n private flows = new Map<string, RunningFlow>();\n /** Checklists on screen, with the guide as rendered (in the visitor's language). */\n private checklists = new Map<string, { open: boolean; guide: PublishedGuide }>();\n private expanded = new Set<string>();\n private surveyView: SurveyView | null = null;\n private resourceCenterOpen = false;\n private cleanups: Array<() => void> = [];\n private timers = new Set<ReturnType<typeof setTimeout>>();\n private visibilityWatchers = new Map<string, () => void>();\n private firedDelays = new Set<string>();\n private firstVisit = true;\n private screenName = \"\";\n private lastAudiences = new Set<string>();\n private backgroundedAt: number | null = null;\n private messenger: Messenger | null = null;\n private replayUploader: ReplayUploader | null = null;\n private recorder: SessionRecorder | null = null;\n /** Replay decision for the current session (sampled once; forced by start/stopSessionRecording). */\n private replayDecision: { sessionId: string; record: boolean } | null = null;\n private ui: UiState = { steps: [], checklists: [], survey: null, resourceCenterOpen: false, theme: {}, messenger: false };\n private uiListeners = new Set<() => void>();\n /** Feature flags for this environment: `guidely.flags.isEnabled(\"new-checkout\")`. */\n readonly flags: FlagsClient;\n /** Experiments already reported this session (`experiment_viewed` is sent once per session). */\n private exposures = new Set<string>();\n // Product analytics (autocapture).\n private readonly rage = new RageClickDetector();\n private readonly heatmap = new HeatmapBuffer();\n /** Taps are processed in order (target frames are measured asynchronously). */\n private tapChain: Promise<void> = Promise.resolve();\n /** When the current screen's foreground measurement started; `screenLeft` once it has been reported. */\n private screenStartedAt = 0;\n private screenLeft = true;\n /** Last `app_open` (cold start or return to the foreground), for `app_background.foregroundMs`. */\n private openedAt = Date.now();\n private launchChecked = false;\n /** An identity was stored before this launch (an existing install adopting lifecycle events). */\n private hadIdentity = false;\n /** Language set with `setLocale()` (or the `locale` option). */\n private locale: string | null = null;\n /** Language each shown guide was rendered in; added to its events as `locale`. */\n private guideLocales = new Map<string, string>();\n /** The resource center in the visitor's language, recomputed when the config or language changes. */\n private localizedRc: { source: ResourceCenterConfig; locales: string; value: ResourceCenterConfig & { locale: string } } | null = null;\n /** \"What's new\" last-seen time when the resource center opened (entries after it read as new). */\n private announcementsSeenAtOpen: string | null = null;\n private readonly customListeners = new Map<string, Set<() => void>>();\n private readonly eventBus = {\n on: (name: string, cb: () => void) => {\n let set = this.customListeners.get(name);\n if (!set) {\n set = new Set();\n this.customListeners.set(name, set);\n }\n set.add(cb);\n return () => void set?.delete(cb);\n },\n };\n\n constructor(options: GuidelyOptions, bridge: PlatformBridge) {\n if (!options || !options.projectId) throw new Error(\"[Guidely] `projectId` (your environment public key, e.g. pk_dev_…) is required.\");\n this.options = {\n ...options,\n environment: options.environment ?? (options.projectId.startsWith(\"pk_prod\") ? \"production\" : options.projectId.startsWith(\"pk_stag\") ? \"staging\" : \"development\"),\n apiUrl: options.apiUrl ?? DEFAULT_API_URL,\n analytics: options.analytics ?? true,\n configRefreshMs: options.configRefreshMs ?? 5 * 60 * 1000,\n debug: options.debug ?? false,\n };\n this.bridge = bridge;\n this.consent = options.consent ?? \"granted\";\n this.emitter = new Emitter<GuidelyEvents>((err) => this.reportError(err));\n this.api = new Api(this.options.apiUrl, this.options.projectId, options.fetch);\n this.store = new PersistentStore(options.storage ?? null, (err) => this.log(\"storage error\", err));\n if (!options.storage) this.log(\"no `storage` passed: identity, guide history, queued events and survey answers last only for this app session, so whatever could not be sent during a Guidely outage is lost when the app restarts. Pass AsyncStorage to persist them.\");\n this.cleanups.push(this.targets.onTap((id) => this.handleTap(id)));\n if (options.user) this.user = { ...options.user };\n this.locale = options.locale ? normalizeLocale(options.locale) || null : null;\n this.flags = this.createFlags(options.flags);\n }\n\n private createFlags(opts: GuidelyOptions[\"flags\"]): FlagsClient {\n const base = { sdkKey: this.options.projectId, apiUrl: this.options.apiUrl, fetch: this.options.fetch, sdk: { name: SDK_NAME, version: SDK_VERSION } };\n if (opts === false) return createFlagsClient({ ...base, overrideBehaviour: \"localOnly\", offline: true, reportUsage: false, trackExposures: false, storage: false, logger: null });\n const o = opts ?? {};\n return createFlagsClient({\n ...base,\n storage: this.options.storage ?? false,\n reportUsage: this.options.analytics,\n // Failures surface through onError (and `debug` logs); development warnings (unknown flag keys) reach the console.\n logger: { warn: (...a: unknown[]) => console.warn(\"[Guidely]\", ...a), error: (...a: unknown[]) => this.log(...a) },\n ...o,\n contextAttributes: this.flagContext(),\n // Exposures travel through the event pipeline (with the session) as `experiment_viewed`.\n trackExposures: false,\n onFlagEvaluated: (result) => {\n this.trackExposure(result);\n o.onFlagEvaluated?.(result);\n },\n onReady: () => {\n this.emitter.emit(\"flags:ready\");\n o.onReady?.();\n },\n onChange: (data) => {\n this.emitter.emit(\"flags:change\");\n o.onChange?.(data);\n },\n onError: (err) => {\n this.reportError(err);\n o.onError?.(err);\n },\n });\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Loads persisted state and config, identifies the stored user and evaluates triggers. Idempotent. */\n init(): Promise<void> {\n if (!this.readyPromise) this.readyPromise = this.bootstrap();\n return this.readyPromise;\n }\n\n ready(): Promise<void> {\n return this.init();\n }\n\n private async bootstrap(): Promise<void> {\n const key = this.options.projectId;\n try {\n await this.store.hydrate([KEYS.anon, KEYS.seen, KEYS.session, KEYS.config(key), KEYS.etag(key), KEYS.state(key), KEYS.user(key), KEYS.queue(key), KEYS.outbox(key), KEYS.conversations(key), appVersionKey(key), LAUNCHER_PLACEMENT_KEY]);\n if (this.destroyed) return;\n this.anonymousId = this.store.get(KEYS.anon) || \"\";\n this.hadIdentity = !!this.anonymousId;\n if (!this.anonymousId) {\n this.anonymousId = `anon_${randomId(20)}`;\n this.store.set(KEYS.anon, this.anonymousId);\n }\n this.firstVisit = !this.store.get(KEYS.seen);\n this.store.set(KEYS.seen, nowIso());\n this.state = { ...emptyState(), ...readJson<Partial<PersistedState>>(this.store, KEYS.state(key), {}) };\n this.user = this.options.user ? { ...this.options.user } : readJson<GuidelyUser | null>(this.store, KEYS.user(key), null);\n const saved = readJson<MobileSession | null>(this.store, KEYS.session, null);\n this.session = saved?.id && !this.sessionExpired(Date.parse(saved.lastActiveAt)) ? saved : newSession();\n this.persistSession();\n this.lastAudiences = new Set(this.state.audienceIds);\n this.syncFlagAttributes(); // stored identity is known now\n // Both read what a previous launch left unsent from the hydrated store (and resend it).\n this.queue = new EventQueue({\n store: this.store,\n storageKey: KEYS.queue(key),\n enabled: () => this.analyticsEnabled(),\n health: this.api.health,\n send: async (events) => {\n const res = await this.api.post<{ accepted: number }>(\"/events\", { events, sentAt: nowIso(), sdk: { name: SDK_NAME, version: SDK_VERSION } });\n return { ok: res.ok, retry: !(res.status >= 400 && res.status < 500 && res.status !== 429) };\n },\n onError: (err) => this.reportError(err),\n });\n this.outbox = new Outbox({ api: this.api, store: this.store, storageKey: KEYS.outbox(key), health: this.api.health });\n this.hydrated = true;\n const cached = readJson<SdkConfigResponse | null>(this.store, KEYS.config(key), null);\n this.etag = this.store.get(KEYS.etag(key));\n if (cached && Array.isArray(cached.guides)) this.config = forPlatform(cached, this.bridge.device.platform);\n this.syncMessenger();\n // Calls made before storage was ready (track, screen, identify…) run now, in order.\n this.pending.splice(0).forEach((fn) => fn());\n const before = this.config?.configVersion;\n const fresh = this.fetchConfig();\n // With a cached config a slow or unreachable server doesn't hold guides back: start from the\n // cache and apply the fresh config when it lands. Without one there is nothing to show yet.\n if (!this.config) await fresh;\n else if (!(await settlesWithin(fresh, CACHED_START_MS))) void fresh.then(() => this.applyConfigChange(before));\n if (this.destroyed) return;\n this.checkLaunch();\n this.wireTimers();\n // identify() re-evaluates guides when it completes, so a slow answer is applied later too.\n if (this.user?.id) await settlesWithin(this.identify(this.user.id, this.user.traits, this.user.account), CACHED_START_MS);\n if (this.destroyed) return;\n this.isReady = true;\n if (this.config) this.emitter.emit(\"ready\", this.config);\n this.syncReplay();\n this.notify();\n this.evaluate(\"ready\");\n } catch (err) {\n this.reportError(err);\n this.isReady = true;\n }\n }\n\n private whenHydrated(fn: () => void): void {\n if (this.destroyed) return;\n if (this.hydrated) fn();\n else this.pending.push(fn);\n }\n\n private async fetchConfig(): Promise<boolean> {\n try {\n const res = await this.api.get<SdkConfigResponse>(\"/config\", { etag: this.etag, params: { platform: this.bridge.device.platform } });\n this.configFetchedAt = Date.now();\n if (res.status === 304) return true;\n if (res.ok && res.data && Array.isArray(res.data.guides)) {\n this.config = forPlatform(res.data, this.bridge.device.platform);\n this.etag = res.etag;\n writeJson(this.store, KEYS.config(this.options.projectId), res.data);\n if (res.etag) this.store.set(KEYS.etag(this.options.projectId), res.etag);\n else this.store.remove(KEYS.etag(this.options.projectId));\n this.syncMessenger();\n // A launch that started without any config records its lifecycle events once one arrives.\n if (this.hydrated) this.checkLaunch();\n this.emitter.emit(\"config\", this.config);\n this.syncReplay();\n this.log(\"config loaded\", this.config.configVersion, `${this.config.guides.length} guides`);\n return true;\n }\n this.reportError(new Error(`[Guidely] config request failed (${res.status})${this.config ? \"; using cached config\" : \"\"}`));\n return false;\n } catch (err) {\n this.reportError(new Error(`[Guidely] config request failed: ${err instanceof Error ? err.message : String(err)}${this.config ? \"; using cached config\" : \"\"}`));\n return false;\n }\n }\n\n private wireTimers(): void {\n // Skipped while the API's circuit is open; the cached config keeps serving meanwhile.\n const refresh = setInterval(() => {\n if (this.api.health.canSend()) void this.refresh();\n }, this.options.configRefreshMs);\n this.cleanups.push(() => clearInterval(refresh));\n // Targets mount and unmount without navigation (lists, tabs): re-arm visibility triggers and drain the queue.\n const poll = setInterval(() => {\n if (!this.isReady || !this.config || this.backgroundedAt !== null) return;\n const url = this.currentUrl();\n const ctx = this.getContext();\n for (const guide of this.candidates()) if (guide.config.trigger.type === \"element_visible\" && guide.config.trigger.value) this.armVisibility(guide, ctx, url);\n this.drainQueue(url, ctx);\n }, 1000);\n this.cleanups.push(() => clearInterval(poll));\n }\n\n /** Re-fetches the published config and re-evaluates triggers. */\n async refresh(): Promise<void> {\n if (this.destroyed) return;\n const before = this.config?.configVersion;\n await this.fetchConfig();\n this.applyConfigChange(before);\n }\n\n /** Re-renders after a config change (refresh, or a config that arrived after start). */\n private applyConfigChange(before: number | undefined): void {\n if (this.destroyed || !this.isReady) return;\n if (this.config && this.config.configVersion !== before) {\n this.notify();\n this.evaluate(\"ready\");\n }\n }\n\n /** Called by the provider with React Native `AppState` changes. */\n setAppState(state: \"active\" | \"background\" | \"inactive\" | string): void {\n if (this.destroyed || !this.hydrated) return;\n if (state === \"background\") {\n const wasForeground = this.backgroundedAt === null;\n this.backgroundedAt = Date.now();\n // Before the flushes below, so these events leave with them.\n if (wasForeground) this.wentToBackground();\n this.session.lastActiveAt = nowIso();\n this.persistSession();\n void this.queue?.flush();\n void this.outbox?.flush();\n void this.store.flush();\n void this.flags.flush();\n this.recorder?.pause();\n this.messenger?.setForeground(false);\n } else if (state === \"active\" && this.backgroundedAt !== null) {\n this.messenger?.setForeground(true);\n const away = this.backgroundedAt;\n this.backgroundedAt = null;\n if (this.sessionExpired(away)) {\n this.session = newSession();\n this.persistSession();\n this.firedDelays.clear();\n this.recorder?.stop(false); // the old session's recording is uploaded; a new one starts below\n }\n this.recorder?.resume();\n this.syncReplay();\n this.cameToForeground();\n void this.flags.refresh();\n if (Date.now() - this.configFetchedAt > this.options.configRefreshMs && this.api.health.canSend()) void this.refresh();\n else if (this.isReady) this.evaluate(\"ready\");\n }\n }\n\n private sessionExpired(lastActiveMs: number): boolean {\n const minutes = this.config?.settings?.sessionTimeoutMinutes ?? 30;\n return !Number.isFinite(lastActiveMs) || Date.now() - lastActiveMs > minutes * 60_000;\n }\n\n /** Tears everything down. Create a new client to start again. */\n destroy(): void {\n if (this.destroyed) return;\n this.flushHeatmap();\n this.destroyed = true;\n this.active?.controller.destroy();\n this.active = null;\n this.flows.forEach((f) => f.controller.destroy());\n this.flows.clear();\n this.queued = [];\n this.messenger?.destroy();\n this.messenger = null;\n this.recorder?.stop(!this.analyticsEnabled());\n this.recorder = null;\n this.replayUploader?.destroy();\n this.visibilityWatchers.forEach((stop) => stop());\n this.visibilityWatchers.clear();\n this.timers.forEach((t) => clearTimeout(t));\n this.timers.clear();\n this.cleanups.splice(0).forEach((fn) => fn());\n void this.queue?.flush();\n this.queue?.destroy();\n this.outbox?.destroy();\n this.flags.destroy();\n this.emitter.clear();\n this.uiListeners.clear();\n }\n\n // ---------------------------------------------------------------------------\n // Identity\n // ---------------------------------------------------------------------------\n\n /** Identifies the end user and loads server-held state (audiences, guide history, checklist progress). */\n identify(userId: string, traits?: Record<string, unknown>, account?: GuidelyAccount): Promise<void> {\n return new Promise((resolve) =>\n this.whenHydrated(() => {\n const id = String(userId);\n const same = this.user?.id === id;\n this.user = { id, traits: { ...(same ? this.user?.traits : {}), ...(traits || {}) }, account: account ?? (same ? this.user?.account : undefined) };\n writeJson(this.store, KEYS.user(this.options.projectId), this.user);\n this.syncFlagAttributes();\n this.enqueue(\"identify\", { properties: { traits: sanitizeProperties(this.user.traits) } });\n void this.syncIdentify().then(() => {\n this.emitter.emit(\"identify\", { userId: id, anonymousId: this.anonymousId });\n if (this.isReady) this.evaluate(\"identify\");\n resolve();\n });\n }),\n );\n }\n\n private async syncIdentify(): Promise<void> {\n const body: IdentifyRequest = { anonymousId: this.anonymousId, userId: this.user?.id || null, traits: this.user?.traits, account: this.user?.account ? { id: this.user.account.id, traits: this.user.account.traits } : null, sessionId: this.session.id, url: this.collectUrls() ? this.currentUrl() : undefined };\n const res = await postWithRetry<IdentifyResponse>(this.api, \"/identify\", body, 2);\n if (res?.ok && res.data) this.mergeServerState(res.data);\n }\n\n private mergeServerState(data: IdentifyResponse): void {\n const guides = { ...this.state.guides };\n for (const [id, s] of Object.entries(data.guideState || {})) {\n const local = guides[id];\n guides[id] = {\n ...local,\n impressions: Math.max(local?.impressions ?? 0, s.impressions ?? 0),\n completedAt: local?.completedAt ?? s.completedAt ?? null,\n dismissedAt: local?.dismissedAt ?? s.dismissedAt ?? null,\n lastShownAt: local?.lastShownAt ?? s.lastShownAt ?? null,\n };\n }\n const checklists = { ...this.state.checklists };\n for (const [id, p] of Object.entries(data.checklistProgress || {})) {\n const local = checklists[id];\n checklists[id] = {\n completedTaskIds: Array.from(new Set([...(local?.completedTaskIds ?? []), ...(p.completedTaskIds ?? [])])),\n completedAt: local?.completedAt ?? p.completedAt ?? null,\n dismissedAt: dismissedAfterMerge(local, p),\n dismissResetAt: p.dismissResetAt ?? local?.dismissResetAt ?? null,\n };\n }\n this.state = {\n guides,\n checklists,\n surveysSubmitted: Array.from(new Set([...this.state.surveysSubmitted, ...(data.surveysSubmitted || [])])),\n audienceIds: data.audienceIds || [],\n firstSeenAt: this.state.firstSeenAt ?? data.firstSeenAt,\n // Device-local only (the server doesn't hold them).\n ...(this.state.throttle ? { throttle: this.state.throttle } : {}),\n ...(this.state.announcementsSeenAt ? { announcementsSeenAt: this.state.announcementsSeenAt } : {}),\n };\n if (data.firstSeenAt && Date.now() - Date.parse(data.firstSeenAt) > 60_000) this.firstVisit = false;\n this.persistState();\n this.syncFlagAttributes(); // audiences\n this.notify();\n }\n\n /** Sets or replaces the account (company / organisation) for the current user. */\n async setAccount(account: GuidelyAccount): Promise<void> {\n await this.init();\n if (!this.user?.id) {\n this.user = { id: \"\", traits: this.user?.traits, account };\n writeJson(this.store, KEYS.user(this.options.projectId), this.user);\n this.syncFlagAttributes();\n return;\n }\n await this.identify(this.user.id, undefined, account);\n }\n\n /** Merges additional traits into the current user. */\n async updateTraits(traits: Record<string, unknown>): Promise<void> {\n await this.init();\n if (!this.user?.id) {\n this.user = { id: \"\", traits: { ...(this.user?.traits || {}), ...traits }, account: this.user?.account };\n this.syncFlagAttributes();\n return;\n }\n await this.identify(this.user.id, traits, this.user.account);\n }\n\n /** Forgets the user (call on logout): new anonymous id, cleared guide/checklist state, new session. */\n reset(): void {\n this.whenHydrated(() => {\n this.stopGuide();\n this.flows.forEach((f) => f.controller.destroy());\n this.flows.clear();\n this.checklists.clear();\n this.surveyView = null;\n this.activeSurvey = null;\n this.resourceCenterOpen = false;\n // Conversations belong to the previous user.\n if (this.messenger) this.messenger.forgetAll();\n else this.store.remove(KEYS.conversations(this.options.projectId));\n this.user = null;\n this.store.remove(KEYS.user(this.options.projectId));\n this.anonymousId = `anon_${randomId(20)}`;\n this.store.set(KEYS.anon, this.anonymousId);\n this.state = emptyState();\n this.persistState();\n this.recorder?.stop(false); // the recording belongs to the previous user; restarted below when eligible\n this.session = newSession();\n this.persistSession();\n this.lastAudiences = new Set();\n this.firedDelays.clear();\n this.firstVisit = true;\n this.exposures.clear();\n this.syncFlagAttributes();\n this.syncReplay();\n this.emitter.emit(\"identify\", { userId: null, anonymousId: this.anonymousId });\n this.notify();\n if (this.isReady) this.evaluate(\"identify\");\n });\n }\n\n // ---------------------------------------------------------------------------\n // Events & screens\n // ---------------------------------------------------------------------------\n\n /** Updates consent at runtime (`granted` flushes buffered events; `denied` drops them). */\n setConsent(consent: ConsentState): void {\n this.consent = consent;\n this.whenHydrated(() => {\n if (consent === \"denied\") this.queue?.clear();\n else if (consent === \"granted\") void this.queue?.flush();\n this.syncReplay();\n });\n }\n\n private analyticsEnabled(): boolean {\n return this.options.analytics && this.consent === \"granted\" && (this.config?.settings?.analyticsEnabled ?? true);\n }\n\n private collectUrls(): boolean {\n return this.config?.settings?.collectUrls ?? true;\n }\n\n private currentUrl(): string {\n return screenPath(this.screenName);\n }\n\n private enqueue(name: EventName, extra: Partial<SdkEvent> = {}): SdkEvent | null {\n if (this.consent === \"denied\" || !this.options.analytics || !this.queue) return null;\n const event: SdkEvent = {\n eventId: randomId(24),\n name,\n occurredAt: nowIso(),\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n accountId: this.user?.account?.id || null,\n sessionId: this.session.id,\n url: this.collectUrls() && this.screenName ? this.currentUrl() : undefined,\n ...extra,\n };\n if (extra.properties) event.properties = sanitizeProperties(extra.properties);\n const locale = extra.guideId ? this.guideLocales.get(extra.guideId) : undefined;\n if (locale) event.properties = { ...(event.properties ?? {}), locale };\n this.queue.enqueue(event);\n this.recorder?.addGuidelyEvent(name, event.customName, event.guideId);\n this.emitter.emit(\"track\", event);\n return event;\n }\n\n /** Tracks a custom event. Events drive `event` triggers, `advanceOn: \"event\"` steps and checklist tasks. */\n track(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n this.whenHydrated(() => {\n if (!this.session.events.includes(name)) {\n this.session.events.push(name);\n this.persistSession();\n }\n this.enqueue(\"custom\", { customName: name.slice(0, 120), properties: properties ?? {} });\n this.customListeners.get(name)?.forEach((cb) => {\n try {\n cb();\n } catch (err) {\n this.reportError(err);\n }\n });\n this.completeChecklistTasksBy(\"event\", name);\n if (this.isReady) this.evaluate(\"event\", { eventName: name });\n });\n }\n\n /**\n * Records a screen view (the mobile equivalent of a page view) and re-evaluates triggers. URL\n * patterns, `url_match` triggers, multi-screen steps and `url_visited` tasks match `/<name>`.\n */\n screen(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n this.whenHydrated(() => {\n const changed = name !== this.screenName;\n if (changed) {\n // Time on the screen being left, and its heatmap batch.\n this.leaveScreen();\n this.flushHeatmap();\n }\n this.screenName = name;\n this.targets.setScreen(name);\n if (changed) this.recorder?.onScreen();\n if (changed) this.syncFlagAttributes();\n const url = this.currentUrl();\n if (changed) {\n this.screenStartedAt = Date.now();\n this.screenLeft = this.backgroundedAt !== null;\n if (this.pageviewsOn()) this.enqueue(\"page_view\", { properties: { ...properties, path: url, screen: name, ...this.deviceProperties() } });\n }\n this.completeChecklistTasksBy(\"url_visited\", url);\n this.active?.controller.resume();\n this.flows.forEach((f) => f.controller.resume());\n if (this.active) {\n const st = this.active.controller.getState();\n const g = this.active.guide;\n if (st.status === \"running\" && !this.active.manual && g.config.urlPatterns.length && !g.config.urlPatterns.some((p) => screenMatches(p, url))) this.active.controller.destroy();\n }\n // Banners and hotspots are screen-scoped too: close the ones whose patterns no longer match.\n this.flows.forEach((f) => {\n const patterns = f.guide.config.urlPatterns;\n if (!f.manual && patterns.length && !patterns.some((p) => screenMatches(p, url))) f.controller.destroy();\n });\n this.firedDelays.clear();\n if (this.isReady) this.evaluate(\"navigation\");\n if (changed) void this.queue?.flush();\n });\n }\n\n /** The current screen name (last value passed to `screen()`). */\n getScreen(): string {\n return this.screenName;\n }\n\n private handleTap(targetId: string): void {\n if (!this.hydrated) return;\n this.completeChecklistTasksBy(\"click\", targetId);\n if (this.isReady) this.evaluate(\"click\", { targetId });\n }\n\n // ---------------------------------------------------------------------------\n // Session replay\n // ---------------------------------------------------------------------------\n\n private replaySettings() {\n const r = this.config?.settings?.replay;\n if (!r?.enabled || !this.options.sessionReplay?.enabled || !this.bridge.capturer) return null;\n return r;\n }\n\n /** Reconciles recording with config, consent, readiness, the session and its sample decision. Idempotent. */\n private syncReplay(): void {\n if (this.destroyed || !this.hydrated) return;\n const r = this.isReady && this.analyticsEnabled() ? this.replaySettings() : null;\n const id = this.session.id;\n if (r && this.replayDecision?.sessionId !== id) {\n this.replayDecision = { sessionId: id, record: rolloutBucket(id, \"replay\") < (r.sampleRate ?? 100) };\n this.log(`replay ${this.replayDecision.record ? \"sampled\" : \"not sampled\"} for session ${id}`);\n }\n if (!r || !this.replayDecision?.record) {\n if (this.recorder?.isRecording) this.recorder.stop(!this.analyticsEnabled());\n return;\n }\n const rec = this.recorder ?? this.createRecorder();\n if (rec && rec.sessionId !== id) {\n this.log(`recording session ${id}`);\n rec.start(id);\n }\n }\n\n private createRecorder(): SessionRecorder | null {\n const capturer = this.bridge.capturer;\n if (!capturer) return null;\n const uploader =\n this.replayUploader ??\n (this.replayUploader = new ReplayUploader({\n url: () => this.api.url(\"/replay\"),\n fetch: () => this.options.fetch ?? (typeof fetch === \"function\" ? fetch : null),\n health: this.api.health,\n meta: () => {\n const rec = this.recorder;\n return {\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n ...(this.collectUrls() && this.screenName ? { url: this.currentUrl() } : {}),\n device: { type: this.bridge.device.deviceType, os: this.bridge.device.platform },\n ...(rec && rec.viewportWidth > 0 && rec.viewportHeight > 0 ? { viewport: { width: rec.viewportWidth, height: rec.viewportHeight } } : {}),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n };\n },\n onDisabled: (sid) => {\n if (sid !== this.session.id) return;\n this.log(`replay disabled by the server for session ${sid}`);\n this.replayDecision = { sessionId: sid, record: false };\n this.recorder?.stop(true);\n },\n log: (m) => this.log(m),\n }));\n const opts = this.options.sessionReplay ?? {};\n const rec = new SessionRecorder({\n capturer,\n uploader,\n intervalMs: opts.captureIntervalMs ?? 1000,\n captureOptions: () => this.replayCaptureOptions(),\n href: () => this.currentUrl(),\n onError: (err) => this.reportError(err),\n });\n if (this.backgroundedAt !== null) rec.pause();\n this.recorder = rec;\n return rec;\n }\n\n private async replayCaptureOptions(): Promise<ReplayCaptureOptions> {\n const r = this.config?.settings?.replay;\n const opts = this.options.sessionReplay ?? {};\n const ids = new Set((r?.blockSelectors ?? []).map((sel) => guidelyIdFromSelector(sel)).filter((id): id is string => !!id));\n const rects = await Promise.all(Array.from(ids, (id) => this.targets.measure(id)));\n return { maskAllText: !!opts.maskAllText || !!r?.maskAllText, maskAllImages: !!opts.maskAllImages, blockRects: rects.filter((rect): rect is Rect => !!rect) };\n }\n\n /**\n * Records this session even when it was not sampled (still needs `sessionReplay.enabled`, replay\n * enabled for the project, analytics consent and the native replay module). Sticks until the session ends.\n */\n startSessionRecording(): void {\n this.whenHydrated(() => {\n this.replayDecision = { sessionId: this.session.id, record: true };\n this.syncReplay();\n });\n }\n\n /** Stops recording for the rest of this session; what was recorded is uploaded. */\n stopSessionRecording(): void {\n this.whenHydrated(() => {\n this.replayDecision = { sessionId: this.session.id, record: false };\n this.recorder?.stop(false);\n });\n }\n\n /** True while this session is being recorded. */\n isRecording(): boolean {\n return !!this.recorder?.isRecording;\n }\n\n /** The current analytics session id (also the replay id). */\n getSessionId(): string {\n return this.session.id;\n }\n\n /** True when touches should be passed to {@link recordTouch}. */\n isRecordingTouches(): boolean {\n return !!this.recorder?.isRecording;\n }\n\n /** A primary-pointer touch on the app, in window points (the provider's touch observer calls this). */\n recordTouch(phase: TouchPhase, x: number, y: number): void {\n this.recorder?.touch(phase, x, y);\n }\n\n // ---------------------------------------------------------------------------\n // Product analytics (autocapture)\n // ---------------------------------------------------------------------------\n\n private captureAllowed(): boolean {\n return !this.destroyed && this.analyticsEnabled();\n }\n\n /** A capability runs when the project enables it (absent on old servers → off), no option turns it off and analytics are allowed. */\n private autocaptureOn(key: keyof AutocaptureSettings): boolean {\n const o = this.options.autocapture;\n return !!this.config?.settings?.autocapture?.[key] && o !== false && !(typeof o === \"object\" && o?.[key] === false) && this.captureAllowed();\n }\n\n /** `page_view` from `screen()` predates autocapture: only an explicit opt-out stops it. */\n private pageviewsOn(): boolean {\n const o = this.options.autocapture;\n return this.config?.settings?.autocapture?.pageviews !== false && o !== false && !(typeof o === \"object\" && o?.pageviews === false);\n }\n\n /** True when taps are worth observing (clicks, rage taps or heatmaps are on); the provider skips resolving views otherwise. */\n isTapCaptureOn(): boolean {\n return this.hydrated && (this.autocaptureOn(\"clicks\") || this.autocaptureOn(\"rageClicks\") || this.autocaptureOn(\"heatmaps\"));\n }\n\n /**\n * Records a tap observed by the provider: `click` for an interactive element, `rage_click` for\n * bursts and a heatmap point. A registered `<GuidelyTarget>` whose frame contains the point\n * (smallest wins) takes precedence over the resolved element and is reported as `#<id>`.\n */\n recordTap(tap: TapInfo): void {\n try {\n if (!this.hydrated || this.destroyed || !Number.isFinite(tap.x) || !Number.isFinite(tap.y)) return;\n const on = { clicks: this.autocaptureOn(\"clicks\"), rage: this.autocaptureOn(\"rageClicks\"), heat: this.autocaptureOn(\"heatmaps\") };\n if (!on.clicks && !on.rage && !on.heat) return;\n const t = tap.t ?? Date.now();\n // The screen at tap time: navigation often lands while target frames are being measured.\n const url = this.screenName ? this.currentUrl() : \"\";\n this.tapChain = this.tapChain.then(() => this.processTap(tap, t, url, on)).catch((err) => this.reportError(err));\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private async processTap(tap: TapInfo, t: number, url: string, on: { clicks: boolean; rage: boolean; heat: boolean }): Promise<void> {\n let el = tap.element ?? null;\n let rect: Rect | null = null;\n const target = this.targets.ids().length ? await this.targets.hitTest(tap.x, tap.y) : null;\n if (target) {\n el = { selector: `#${target.id}`, tag: el?.tag ?? tap.hit?.tag ?? \"View\", text: el?.text };\n rect = target.rect;\n }\n if (this.destroyed) return;\n const platform = this.bridge.device.platform;\n const maskAll = !!this.config?.settings?.replay?.maskAllText || !!this.options.sessionReplay?.maskAllText;\n const eventUrl = this.collectUrls() && url ? url : undefined;\n if (on.clicks && el) this.enqueue(\"click\", { url: eventUrl, properties: { ...tapProperties(el, tap.x, tap.y, platform, maskAll) } });\n const count = this.rage.add(tap.x, tap.y, t);\n if (on.rage && count) this.enqueue(\"rage_click\", { url: eventUrl, properties: { ...tapProperties(el ?? tap.hit ?? UNKNOWN_VIEW, tap.x, tap.y, platform, maskAll), count } });\n if (!on.heat) return;\n const burst = this.rage.burst;\n if (el && !rect && el.measure) rect = await el.measure().catch(() => null);\n if (this.destroyed) return;\n if (this.heatmap.url !== url) this.flushHeatmap();\n if (this.heatmap.add(url, heatmapPoint(tap.x, tap.y, el, rect, burst > 0), burst)) this.flushHeatmap();\n }\n\n /** Sends the buffered heatmap taps as one `heatmap` event attributed to the screen they happened on. */\n private flushHeatmap(): void {\n const batch = this.heatmap.take();\n if (!batch || !this.captureAllowed()) return;\n const collect = this.collectUrls() && !!batch.url;\n const { width, height } = this.windowSize();\n this.enqueue(\"heatmap\", {\n url: collect ? batch.url : undefined,\n properties: { ...(collect ? { path: batch.url } : {}), viewportWidth: width, viewportHeight: height, pageHeight: height, platform: this.bridge.device.platform, points: batch.points },\n });\n }\n\n private windowSize(): { width: number; height: number } {\n try {\n const s = this.bridge.windowSize?.();\n if (s && Number.isFinite(s.width) && Number.isFinite(s.height)) return { width: Math.round(s.width), height: Math.round(s.height) };\n } catch {\n /* fall through */\n }\n return { width: 0, height: 0 };\n }\n\n /** Ends the foreground measurement of the current screen with a `page_leave` (once per measurement). */\n private leaveScreen(): void {\n if (!this.screenName || this.screenLeft) return;\n this.screenLeft = true;\n if (!this.autocaptureOn(\"pageLeave\")) return;\n const url = this.currentUrl();\n const collect = this.collectUrls();\n this.enqueue(\"page_leave\", {\n url: collect ? url : undefined,\n properties: { ...(collect ? { path: url } : {}), screen: this.screenName, durationMs: Math.max(0, Date.now() - this.screenStartedAt), scrollDepth: 100, platform: this.bridge.device.platform },\n });\n }\n\n /** `{ appVersion, build }` of this launch, without unknown keys. */\n private appInfo(): { appVersion?: string; build?: string } {\n const appVersion = this.options.appVersion ?? this.bridge.device.appVersion;\n // A detected build belongs to the detected version, not to an `appVersion` the app passed.\n const build = this.options.appBuild ?? (this.options.appVersion ? undefined : this.bridge.device.appBuild);\n return { ...(appVersion ? { appVersion: String(appVersion) } : {}), ...(build ? { build: String(build) } : {}) };\n }\n\n /**\n * Once per launch, as soon as a config is known: `app_install` / `app_update` from the stored\n * version (when the app version is known and the app passes `storage`), then `app_open` with `coldStart: true`.\n */\n private checkLaunch(): void {\n if (this.launchChecked || !this.config || this.destroyed || !this.hydrated) return;\n this.launchChecked = true;\n try {\n const on = this.autocaptureOn(\"appLifecycle\");\n const info = this.appInfo();\n if (info.appVersion && this.options.storage) {\n const key = appVersionKey(this.options.projectId);\n const stored = readJson<{ appVersion?: string; build?: string } | null>(this.store, key, null);\n if (!stored?.appVersion) {\n // No stored version: a fresh install, unless this install predates lifecycle events (stored identity).\n if (!this.hadIdentity && on) this.enqueue(\"app_install\", { properties: { ...info } });\n } else if (stored.appVersion !== info.appVersion || (!!stored.build && !!info.build && stored.build !== info.build)) {\n if (on) this.enqueue(\"app_update\", { properties: { ...info, previousVersion: stored.appVersion, ...(stored.build ? { previousBuild: stored.build } : {}) } });\n }\n writeJson(this.store, key, info);\n }\n if (on) this.enqueue(\"app_open\", { properties: { ...info, coldStart: true } });\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private wentToBackground(): void {\n try {\n this.leaveScreen();\n this.flushHeatmap();\n if (this.launchChecked && this.autocaptureOn(\"appLifecycle\")) this.enqueue(\"app_background\", { properties: { foregroundMs: Math.max(0, Date.now() - this.openedAt) } });\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private cameToForeground(): void {\n try {\n this.openedAt = Date.now();\n if (this.launchChecked && this.autocaptureOn(\"appLifecycle\")) this.enqueue(\"app_open\", { properties: { ...this.appInfo(), coldStart: false } });\n if (this.screenName && this.screenLeft) {\n // A new measurement of the screen, paired with a page_view so every page_leave has one.\n this.screenStartedAt = Date.now();\n this.screenLeft = false;\n if (this.pageviewsOn() && this.autocaptureOn(\"pageLeave\")) this.enqueue(\"page_view\", { properties: { path: this.currentUrl(), screen: this.screenName, ...this.deviceProperties(), resumed: true } });\n }\n } catch (err) {\n this.reportError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Targeting + triggers\n // ---------------------------------------------------------------------------\n\n /** Builds the targeting context for the current moment. */\n getContext(): TargetingContext {\n const guides = this.state.guides;\n const keysOf = (ids: string[]) => ids.flatMap((id) => [id, this.findGuide(id)?.key ?? id]);\n const url = this.currentUrl();\n const device = this.bridge.device;\n return {\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n userAttributes: this.user?.traits ?? {},\n accountAttributes: this.user?.account?.traits ?? {},\n url,\n path: url,\n query: {},\n device: { type: device.deviceType, os: device.platform },\n firstVisit: this.firstVisit,\n eventsSeen: new Set(this.session.events),\n completedGuides: new Set(keysOf(Object.keys(guides).filter((id) => guides[id]?.completedAt))),\n dismissedGuides: new Set(keysOf(Object.keys(guides).filter((id) => guides[id]?.dismissedAt))),\n seenGuides: new Set(keysOf(Object.keys(guides).filter((id) => (guides[id]?.impressions ?? 0) > 0))),\n completedChecklists: new Set(keysOf(Object.entries(this.state.checklists).filter(([, p]) => !!p.completedAt).map(([id]) => id))),\n audienceIds: new Set(this.state.audienceIds),\n now: new Date(),\n environment: this.options.environment,\n locale: device.locale,\n platform: device.platform,\n screen: this.screenName,\n appVersion: this.options.appVersion ?? device.appVersion,\n };\n }\n\n private isTargeted(guide: PublishedGuide, ctx: TargetingContext, url: string): boolean {\n const c = guide.config;\n if (c.urlPatterns.length && !c.urlPatterns.some((p) => screenMatches(p, url))) return false;\n if (c.trigger.urlPattern && !screenMatches(c.trigger.urlPattern, url)) return false;\n if (!isWithinSchedule(guide)) return false;\n if (guide.kind === \"survey\" && (this.state.surveysSubmitted.includes(guide.id) || this.state.surveysSubmitted.includes(guide.key))) return false;\n ctx.rolloutSalt = guide.id;\n return evaluateRules(c.targeting, ctx);\n }\n\n private isEligible(guide: PublishedGuide, ctx: TargetingContext, url: string): boolean {\n if (!this.isTargeted(guide, ctx, url)) return false;\n if (guide.kind === \"checklist\") return !this.state.checklists[guide.id]?.dismissedAt;\n return isFrequencyEligible(guide.config.frequency, this.state.guides[guide.id], this.session.shownGuides.includes(guide.id));\n }\n\n /** Guide throttling: may this guide launch automatically now? */\n private throttleAllows(guide: PublishedGuide): boolean {\n if (!countsTowardThrottle(guide)) return true;\n return isThrottleEligible(this.config?.settings.throttling, this.state.throttle ?? []);\n }\n\n private recordLaunch(guide: PublishedGuide, manual: boolean): void {\n if (manual || !countsTowardThrottle(guide) || !this.config?.settings.throttling?.enabled) return;\n this.state.throttle = pruneLaunches([...(this.state.throttle ?? []), nowIso()], this.config.settings.throttling);\n }\n\n /** Guides and A/B test control groups, which are evaluated the same way but never render. */\n private candidates(): PublishedGuide[] {\n const guides = this.config?.guides ?? [];\n const holdouts = this.config?.guideHoldouts ?? [];\n return holdouts.length ? [...guides, ...holdouts.map((h) => h.guide)] : guides;\n }\n\n private holdoutFor(guide: PublishedGuide) {\n return this.config?.guideHoldouts?.find((h) => h.guide.id === guide.id) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // Localization\n // ---------------------------------------------------------------------------\n\n /** The visitor's language candidates, most preferred first: `setLocale()` / `locale` option, traits, device. */\n private locales(): string[] {\n return visitorLocales(this.locale, this.user?.traits, [this.bridge.device.locale]);\n }\n\n private defaultLocale(): string {\n return this.config?.settings?.localization?.defaultLocale || \"en\";\n }\n\n /** The guide in the visitor's language (remembered so its events carry `locale`). */\n private localize(guide: PublishedGuide): PublishedGuide {\n const localized = localizeGuide(guide, this.locales(), this.defaultLocale());\n this.guideLocales.set(guide.id, localized.locale);\n return localized;\n }\n\n /**\n * Sets the language for guides and the resource center (`null` = back to the user's traits and\n * the device language). Guides already on screen keep their language; the resource center re-renders.\n */\n setLocale(locale: string | null): void {\n const next = locale ? normalizeLocale(locale) || null : null;\n if (next === this.locale) return;\n this.locale = next;\n this.notify();\n }\n\n private triggerFires(guide: PublishedGuide, reason: EvalReason, detail: EvalDetail): boolean {\n const t = guide.config.trigger;\n switch (t.type) {\n case \"page_load\":\n // A delayed page_load re-evaluates from its own timer.\n if (t.delayMs > 0) return reason === \"timer\" && detail.guideId === guide.id;\n return reason === \"ready\" || reason === \"navigation\" || reason === \"identify\";\n case \"url_match\":\n return (reason === \"ready\" || reason === \"navigation\" || reason === \"identify\") && screenMatches(t.value, this.currentUrl());\n case \"event\":\n return reason === \"event\" && !!t.value && detail.eventName === t.value;\n case \"element_click\":\n return reason === \"click\" && !!detail.targetId && guidelyIdFromSelector(t.value) === detail.targetId;\n case \"element_visible\":\n return reason === \"visible\" && detail.guideId === guide.id;\n case \"delay\":\n return reason === \"timer\" && detail.guideId === guide.id;\n case \"after_guide\":\n return reason === \"after_guide\" && !!detail.endedGuide && (detail.endedGuide.id === t.value || detail.endedGuide.key === t.value);\n case \"segment_enter\":\n return reason === \"identify\" && !!t.value && !!detail.newAudiences?.has(t.value);\n case \"manual\":\n default:\n return false;\n }\n }\n\n private evaluate(reason: EvalReason, detail: EvalDetail = {}): void {\n if (!this.config || this.destroyed) return;\n const url = this.currentUrl();\n const ctx = this.getContext();\n if (reason === \"identify\") {\n const current = new Set(this.state.audienceIds);\n detail.newAudiences = new Set(Array.from(current).filter((a) => !this.lastAudiences.has(a)));\n this.lastAudiences = current;\n }\n const candidates: PublishedGuide[] = [];\n for (const guide of this.candidates()) {\n const t = guide.config.trigger;\n if (detail.endedGuide && detail.endedGuide.id === guide.id) continue;\n if (reason === \"ready\" || reason === \"navigation\") {\n if (t.type === \"element_visible\" && t.value) this.armVisibility(guide, ctx, url);\n if ((t.type === \"delay\" || (t.type === \"page_load\" && t.delayMs > 0)) && !this.firedDelays.has(guide.id)) {\n if (!this.isEligible(guide, ctx, url)) continue;\n this.firedDelays.add(guide.id);\n this.setTimer(() => this.evaluate(\"timer\", { guideId: guide.id }), t.delayMs);\n continue;\n }\n }\n if (t.type === \"page_load\" && t.delayMs > 0 && reason !== \"timer\") continue;\n if (t.type === \"page_load\" && t.delayMs > 0 && reason === \"timer\" && detail.guideId !== guide.id) continue;\n if (!this.triggerFires(guide, reason, detail)) continue;\n if (!this.isEligible(guide, ctx, url)) continue;\n if (!this.throttleAllows(guide)) {\n this.log(\"throttled\", guide.key);\n continue;\n }\n candidates.push(guide);\n }\n if (reason === \"after_guide\" || reason === \"navigation\") this.drainQueue(url, ctx);\n if (!candidates.length) return;\n candidates.sort((a, b) => a.config.frequency.priority - b.config.frequency.priority);\n for (const guide of candidates) {\n if (this.isShowing(guide.id)) continue;\n const delay = guide.config.trigger.type !== \"delay\" && guide.config.trigger.type !== \"page_load\" ? guide.config.trigger.delayMs : 0;\n if (delay > 0) this.setTimer(() => this.tryShow(guide, url, false), delay);\n else this.tryShow(guide, url, false);\n }\n }\n\n private armVisibility(guide: PublishedGuide, ctx: TargetingContext, url: string): void {\n const id = guidelyIdFromSelector(guide.config.trigger.value);\n if (!id || this.visibilityWatchers.has(guide.id) || !this.isEligible(guide, ctx, url)) return;\n const ac = new AbortController();\n const stop = () => {\n ac.abort();\n this.visibilityWatchers.delete(guide.id);\n };\n this.visibilityWatchers.set(guide.id, stop);\n this.targets.waitFor([id], { timeoutMs: 0, signal: ac.signal }).then(\n () => {\n if (ac.signal.aborted) return;\n stop();\n this.evaluate(\"visible\", { guideId: guide.id });\n },\n () => stop(),\n );\n }\n\n private setTimer(fn: () => void, ms: number): void {\n const t = setTimeout(() => {\n this.timers.delete(t);\n if (!this.destroyed) fn();\n }, ms);\n this.timers.add(t);\n }\n\n private isShowing(id: string): boolean {\n return this.flows.has(id) || this.checklists.has(id) || this.active?.guide.id === id || this.activeSurvey?.guide.id === id;\n }\n\n private hasExclusive(): PublishedGuide | null {\n return this.active?.guide ?? this.activeSurvey?.guide ?? null;\n }\n\n private tryShow(guide: PublishedGuide, url: string, manual: boolean): boolean {\n if (this.destroyed) return false;\n // Another automatic guide may have launched since this one was picked (delays, queue).\n if (!manual && !this.throttleAllows(guide)) return false;\n if (this.holdoutFor(guide)) {\n // A/B test control group: count the exposure as if the guide had shown, render nothing.\n if (this.hasExclusive() && !manual) return false;\n this.recordImpression(guide, manual);\n return true;\n }\n if (!isExclusiveGuide(guide)) {\n if (this.flows.has(guide.id) || this.checklists.has(guide.id)) return false;\n this.show(guide, manual);\n return true;\n }\n const current = this.hasExclusive();\n if (current) {\n if (current.id === guide.id) return false;\n if (manual) this.stopGuide();\n else {\n if (!this.queued.some((q) => q.guide.id === guide.id)) this.queued.push({ guide, url, pageScoped: PAGE_SCOPED.has(guide.config.trigger.type) });\n this.log(\"queued\", guide.key, \"behind\", current.key);\n return false;\n }\n }\n const blocked = [...this.flows.values()].map((f) => f.guide).some((g) => areMutuallyExclusive(g, guide));\n if (blocked && !manual) {\n if (!this.queued.some((q) => q.guide.id === guide.id)) this.queued.push({ guide, url, pageScoped: true });\n return false;\n }\n this.show(guide, manual);\n return true;\n }\n\n private drainQueue(url: string, ctx: TargetingContext): void {\n if (this.hasExclusive()) return;\n this.queued = this.queued.filter((q) => !(q.pageScoped && q.url !== url));\n while (this.queued.length) {\n const next = this.queued.shift() as QueuedGuide;\n if (!this.isEligible(next.guide, ctx, url)) continue;\n if (this.tryShow(next.guide, url, false)) return;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Showing guides\n // ---------------------------------------------------------------------------\n\n private findGuide(idOrKey: string): PublishedGuide | undefined {\n return this.config?.guides.find((g) => g.id === idOrKey || g.key === idOrKey);\n }\n\n private guideState(id: string): GuideLocalState {\n return this.state.guides[id] ?? (this.state.guides[id] = { impressions: 0 });\n }\n\n private recordImpression(guide: PublishedGuide, manual = false): void {\n const s = this.guideState(guide.id);\n s.impressions += 1;\n s.lastShownAt = nowIso();\n if (!this.session.shownGuides.includes(guide.id)) this.session.shownGuides.push(guide.id);\n this.recordLaunch(guide, manual);\n this.persistState();\n this.persistSession();\n const holdout = this.holdoutFor(guide);\n const experiment = holdout ? { id: holdout.experimentId, variantId: holdout.variantId } : guide.experiment;\n if (experiment) this.enqueue(\"experiment_viewed\", { properties: { guideExperimentId: experiment.id, variantId: experiment.variantId, ...(holdout ? {} : { guideId: guide.id }) } });\n // Control groups are local only: the server knows no guide by that id.\n if (!holdout) this.syncGuideState(guide.id, { impression: true });\n }\n\n private recordEnd(guide: PublishedGuide, reason: \"completed\" | \"dismissed\" | \"skipped\"): void {\n const s = this.guideState(guide.id);\n if (reason === \"completed\") s.completedAt = nowIso();\n else s.dismissedAt = nowIso();\n this.persistState();\n this.syncGuideState(guide.id, reason === \"completed\" ? { completed: true } : { dismissed: true });\n if (reason === \"completed\") this.completeChecklistTasksBy(\"guide_completed\", guide);\n }\n\n private syncGuideState(guideId: string, update: { impression?: boolean; completed?: boolean; dismissed?: boolean }): void {\n const body = { anonymousId: this.anonymousId, userId: this.user?.id || null, updates: [{ guideId, ...update }] };\n // Impressions are counters (a resend would count twice) and matter less; completions and\n // dismissals are kept until the server has them, so a guide doesn't come back on another device.\n if (update.impression) void postWithRetry(this.api, \"/guide-state\", body);\n else this.sendDurably(`guide:${guideId}:${update.completed ? \"completed\" : \"dismissed\"}:${this.anonymousId}`, \"/guide-state\", body);\n }\n\n /** Queues a write in the persisted outbox (sent now, or once the API is reachable again). */\n private sendDurably(key: string, path: string, body: unknown): void {\n this.whenHydrated(() => this.outbox?.add(key, path, body));\n }\n\n private show(guide: PublishedGuide, manual: boolean, stepId?: string): void {\n try {\n if (guide.kind === \"checklist\" && guide.config.checklist) return this.showChecklist(guide);\n if (guide.kind === \"survey\" && guide.config.survey) return this.showSurvey(guide, manual);\n this.showFlow(guide, manual, stepId);\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private showFlow(raw: PublishedGuide, manual: boolean, stepId?: string): void {\n const guide = this.localize(raw);\n const exclusive = isExclusiveGuide(guide);\n const flow: RunningFlow = { guide, manual, view: null, controller: null as unknown as GuideController };\n let renders = 0;\n flow.controller = runGuide(guide, {\n targets: this.targets,\n ctx: () => this.getContext(),\n currentUrl: () => this.currentUrl(),\n startAtStep: stepId,\n eventBus: this.eventBus,\n onError: (err) => this.reportError(err),\n onEvent: (e) => {\n const step = e.stepId ? guide.config.steps.find((s) => s.id === e.stepId) : undefined;\n this.enqueue(e.name, { guideId: guide.id, guideVersion: guide.version, stepId: e.stepId, stepIndex: e.stepIndex, properties: e.properties });\n if (e.name === \"guide_started\") {\n this.recordImpression(guide, manual);\n this.emitter.emit(\"guide:start\", guide);\n } else if (e.name === \"step_viewed\" && step) {\n this.emitter.emit(\"guide:step\", { guide, stepId: step.id, stepIndex: e.stepIndex ?? 0 });\n } else if (e.name === \"guide_completed\") {\n this.recordEnd(guide, \"completed\");\n this.emitter.emit(\"guide:complete\", guide);\n } else if (e.name === \"guide_dismissed\") {\n this.recordEnd(guide, \"dismissed\");\n this.emitter.emit(\"guide:dismiss\", guide);\n } else if (e.name === \"guide_skipped\") {\n this.recordEnd(guide, \"skipped\");\n this.emitter.emit(\"guide:skip\", guide);\n }\n },\n onRender: (r) => {\n renders += 1;\n this.expanded.delete(guide.id);\n flow.view = { key: `${guide.id}:${r.step.id}:${renders}`, guide, step: r.step, index: r.index, total: r.total, canGoBack: r.canGoBack, targetId: r.targetId, asModal: r.asModal, expanded: false };\n this.notify();\n },\n onClear: () => {\n flow.view = null;\n this.notify();\n },\n onNavigate: (url) => this.navigate(url),\n onAction: (action, value) => {\n if (action === \"start_guide\" && value) this.setTimer(() => this.startGuide(value), 0);\n else if (action === \"event\" && value) this.track(value);\n else if (action === \"open_resource_center\") this.openResourceCenter();\n },\n onEnd: (reason) => {\n if (exclusive) {\n if (this.active === flow) this.active = null;\n } else if (this.flows.get(guide.id) === flow) this.flows.delete(guide.id);\n this.notify();\n if (reason !== \"destroyed\" && !this.destroyed) this.setTimer(() => this.evaluate(\"after_guide\", { endedGuide: guide }), 0);\n },\n });\n if (exclusive) this.active = flow;\n else this.flows.set(guide.id, flow);\n flow.controller.start();\n if (flow.controller.getState().status === \"ended\") {\n if (this.active === flow) this.active = null;\n if (this.flows.get(guide.id) === flow) this.flows.delete(guide.id);\n }\n }\n\n private showChecklist(raw: PublishedGuide, open?: boolean): void {\n if (!raw.config.checklist || this.checklists.has(raw.id)) return;\n const guide = this.localize(raw);\n const config = guide.config.checklist;\n if (!config) return;\n const progress = this.getChecklistProgress(guide.id);\n const first = !this.state.guides[guide.id]?.impressions;\n this.checklists.set(guide.id, { guide, open: open ?? (config.autoOpen && first && !progress.completedAt) });\n if (first) this.recordImpression(guide);\n if (this.checklists.get(guide.id)?.open) this.enqueue(\"guide_viewed\", { guideId: guide.id, guideVersion: guide.version });\n this.notify();\n }\n\n private showSurvey(raw: PublishedGuide, manual: boolean): void {\n if (!raw.config.survey) return;\n const guide = this.localize(raw);\n this.activeSurvey = { guide, manual };\n this.surveyView = { key: `${guide.id}:${randomId(6)}`, guide, submitted: false };\n this.recordImpression(guide, manual);\n this.enqueue(\"survey_displayed\", { guideId: guide.id, guideVersion: guide.version });\n this.emitter.emit(\"guide:start\", guide);\n this.notify();\n }\n\n private finishSurvey(reason: \"submitted\" | \"dismissed\"): void {\n const s = this.activeSurvey;\n if (!s) return;\n this.activeSurvey = null;\n this.surveyView = null;\n if (reason === \"dismissed\") {\n this.enqueue(\"survey_dismissed\", { guideId: s.guide.id, guideVersion: s.guide.version });\n this.recordEnd(s.guide, \"dismissed\");\n this.emitter.emit(\"guide:dismiss\", s.guide);\n }\n this.notify();\n this.setTimer(() => this.evaluate(\"after_guide\", { endedGuide: s.guide }), 0);\n }\n\n /** Theme for a guide: project theme ← app overrides ← guide appearance. */\n themeFor(guide?: PublishedGuide): Partial<ProjectTheme> & { dark?: \"light\" | \"dark\" | \"auto\"; overlayOpacity?: number } {\n const a = guide?.config.appearance;\n return {\n ...(this.config?.theme || {}),\n ...(this.options.theme || {}),\n ...(a?.primaryColor ? { primaryColor: a.primaryColor } : {}),\n ...(a?.backgroundColor ? { backgroundColor: a.backgroundColor } : {}),\n ...(a?.textColor ? { textColor: a.textColor } : {}),\n ...(a?.borderRadius != null ? { borderRadius: a.borderRadius } : {}),\n dark: a?.theme ?? \"auto\",\n overlayOpacity: a?.overlayOpacity,\n };\n }\n\n /**\n * Opens a URL from a button, link or task: the app's `onNavigate` handler first (deep links and\n * in-app routes), then http(s) and custom-scheme URLs through the OS.\n */\n navigate(url: string): void {\n if (!url) return;\n try {\n if (this.options.onNavigate?.(url) === true) return;\n if (/^[a-z][a-z0-9+.-]*:/i.test(url)) this.bridge.openExternal(url);\n else if (!this.options.onNavigate) this.log(`no onNavigate handler for in-app URL \"${url}\"`);\n } catch (err) {\n this.reportError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // UI state (consumed by the overlay)\n // ---------------------------------------------------------------------------\n\n getUiState(): UiState {\n return this.ui;\n }\n\n subscribeUi(cb: () => void): () => void {\n this.uiListeners.add(cb);\n return () => this.uiListeners.delete(cb);\n }\n\n private notify(): void {\n const steps: StepView[] = [];\n for (const f of [...this.flows.values(), ...(this.active ? [this.active] : [])]) if (f.view) steps.push({ ...f.view, expanded: this.expanded.has(f.guide.id) });\n const checklists: ChecklistView[] = [];\n this.checklists.forEach((w, id) => checklists.push({ guide: w.guide, progress: this.getChecklistProgress(id), open: w.open }));\n this.ui = { steps, checklists, survey: this.surveyView, resourceCenterOpen: this.resourceCenterOpen, theme: this.themeFor(), messenger: !!this.messenger };\n for (const cb of Array.from(this.uiListeners)) {\n try {\n cb();\n } catch (err) {\n this.reportError(err);\n }\n }\n }\n\n private flowFor(guideId: string): RunningFlow | undefined {\n return this.active?.guide.id === guideId ? this.active : this.flows.get(guideId);\n }\n\n /** A step button was pressed in the overlay. */\n pressButton(guideId: string, button: StepButton): void {\n this.flowFor(guideId)?.controller.press(button);\n }\n\n /** The close (×) button of a step. */\n closeStep(guideId: string): void {\n this.flowFor(guideId)?.controller.dismiss();\n }\n\n /** The dimmed backdrop behind a step was tapped. */\n backdropPressed(guideId: string): void {\n const f = this.flowFor(guideId);\n if (f?.view?.step.dismissOnOutsideClick) f.controller.dismiss();\n }\n\n /** Hotspot dot tapped: show (or hide) its card. */\n toggleHotspot(guideId: string): void {\n if (this.expanded.has(guideId)) this.expanded.delete(guideId);\n else this.expanded.add(guideId);\n this.notify();\n }\n\n setChecklistOpen(guideId: string, open: boolean): void {\n const w = this.checklists.get(guideId);\n const guide = this.findGuide(guideId);\n if (!w || !guide || w.open === open) return;\n w.open = open;\n if (open) this.enqueue(\"guide_viewed\", { guideId: guide.id, guideVersion: guide.version });\n this.notify();\n }\n\n checklistTaskPressed(guideId: string, taskId: string): void {\n const guide = this.findGuide(guideId);\n const task = guide?.config.checklist?.tasks.find((t) => t.id === taskId);\n if (!guide || !task) return;\n if (task.completion === \"manual\") this.markTaskDone(guide, task);\n if (task.action === \"start_guide\" && task.actionValue) {\n this.setChecklistOpen(guide.id, false);\n this.startGuide(task.actionValue);\n } else if (task.action === \"url\" && task.actionValue) this.navigate(task.actionValue);\n else if (task.action === \"event\" && task.actionValue) this.track(task.actionValue);\n }\n\n dismissChecklist(guideId: string): void {\n const guide = this.findGuide(guideId);\n if (!guide) return;\n const progress = this.state.checklists[guide.id] ?? (this.state.checklists[guide.id] = { completedTaskIds: [] });\n progress.dismissedAt = nowIso();\n this.persistState();\n this.enqueue(\"checklist_dismissed\", { guideId: guide.id, guideVersion: guide.version });\n this.sendDurably(`checklist:${guide.id}:dismissed:${this.anonymousId}`, `/checklists/${encodeURIComponent(guide.id)}/progress`, { anonymousId: this.anonymousId, userId: this.user?.id || null, guideVersion: guide.version, completedTaskIds: progress.completedTaskIds, dismissed: true });\n this.checklists.delete(guide.id);\n this.notify();\n }\n\n submitSurvey(guideId: string, answers: Record<string, unknown>): void {\n const s = this.activeSurvey;\n if (!s || s.guide.id !== guideId || !this.surveyView || this.surveyView.submitted) return;\n const guide = s.guide;\n const responseId = randomId(24);\n this.state.surveysSubmitted.push(guide.id);\n this.persistState();\n this.recordEnd(guide, \"completed\");\n this.enqueue(\"survey_submitted\", { guideId: guide.id, guideVersion: guide.version, properties: { responseId } });\n this.sendDurably(`survey:${responseId}`, `/surveys/${encodeURIComponent(guide.id)}/responses`, { anonymousId: this.anonymousId, userId: this.user?.id || null, accountId: this.user?.account?.id || null, guideVersion: guide.version, answers, responseId });\n this.emitter.emit(\"survey:submit\", { guide, answers, responseId });\n this.emitter.emit(\"guide:complete\", guide);\n this.surveyView = { ...this.surveyView, submitted: true };\n this.notify();\n }\n\n closeSurvey(guideId: string): void {\n if (this.activeSurvey?.guide.id !== guideId) return;\n this.finishSurvey(this.surveyView?.submitted ? \"submitted\" : \"dismissed\");\n }\n\n /** The visitor's audiences (from the last identify), for audience-targeted help articles. */\n getAudienceIds(): readonly string[] {\n return this.state.audienceIds;\n }\n\n /** The published resource center in the visitor's language, or null when it is off. */\n getResourceCenter(): ResourceCenterConfig | null {\n const rc = this.localizedResourceCenter();\n return rc && rc.enabled ? rc : null;\n }\n\n /** The resource center in the visitor's language (cached until the config or language changes). */\n private localizedResourceCenter(): (ResourceCenterConfig & { locale: string }) | null {\n const rc = this.config?.resourceCenter;\n if (!rc) return null;\n const locales = this.locales();\n const key = `${locales.join(\",\")}|${this.defaultLocale()}`;\n if (this.localizedRc?.source !== rc || this.localizedRc.locales !== key) this.localizedRc = { source: rc, locales: key, value: localizeResourceCenter(rc, locales, this.defaultLocale()) };\n return this.localizedRc.value;\n }\n\n /** Evaluates targeting rules (e.g. a resource-center section's) for the current visitor and screen. */\n matchesTargeting(rules: RuleGroup | null | undefined): boolean {\n if (!rules) return true;\n try {\n return evaluateRules(rules, this.getContext());\n } catch (err) {\n this.reportError(err);\n return false;\n }\n }\n\n /** Resource-center sections this visitor sees, in order (disabled and non-matching ones left out). */\n getResourceCenterModules(): ResourceCenterModuleId[] {\n const rc = this.getResourceCenter();\n if (!rc) return [];\n return orderedModules(rc.modules)\n .filter((m) => m.enabled && (!(\"targeting\" in m) || this.matchesTargeting(m.targeting)))\n .map((m) => m.id as ResourceCenterModuleId);\n }\n\n /**\n * Sections of the messenger's Help tab, in order: the resource center's modules without \"What's\n * new\" (the messenger has its own News tab); every section when no resource center is published.\n */\n getHelpModules(): ResourceCenterModuleId[] {\n const modules = this.getResourceCenter() ? this.getResourceCenterModules() : [...RC_MODULE_IDS];\n return modules.filter((id) => id !== \"announcements\");\n }\n\n /** \"What's new\" entries this visitor sees (newest first); empty when the section is off. */\n getAnnouncements(): ResourceCenterAnnouncement[] {\n const rc = this.getResourceCenter();\n if (!rc || !this.getResourceCenterModules().includes(\"announcements\")) return [];\n return visibleAnnouncements(rc.announcements, this.state.audienceIds);\n }\n\n /** \"What's new\" entries published since the visitor last opened the resource center. */\n getUnreadAnnouncements(): number {\n return unreadAnnouncements(this.getAnnouncements(), this.state.announcementsSeenAt);\n }\n\n /** Whether an entry is new to the visitor in the resource center that is open now. */\n isAnnouncementNew(a: ResourceCenterAnnouncement): boolean {\n return unreadAnnouncements([a], this.announcementsSeenAtOpen) > 0;\n }\n\n async searchResourceCenter(q: string): Promise<ResourceCenterArticle[]> {\n try {\n const res = await this.api.get<{ articles: ResourceCenterArticle[] }>(\"/resource-center/search\", { params: { q } });\n return res.ok && res.data ? res.data.articles : [];\n } catch {\n return [];\n }\n }\n\n /** The language of the resource center as shown, when it isn't the default (sent with article fetches). */\n private articleLocale(): string | undefined {\n const locale = this.localizedResourceCenter()?.locale;\n return locale && locale.toLowerCase() !== this.defaultLocale().toLowerCase() ? locale : undefined;\n }\n\n articleViewed(article: ResourceCenterArticle): void {\n this.enqueue(\"article_viewed\", { properties: { articleId: article.id, slug: article.slug } });\n }\n\n // ---------------------------------------------------------------------------\n // Checklists\n // ---------------------------------------------------------------------------\n\n getChecklistProgress(idOrKey: string): ChecklistProgressState {\n const id = this.findGuide(idOrKey)?.id ?? idOrKey;\n const p = this.state.checklists[id];\n return p ? { completedTaskIds: [...p.completedTaskIds], completedAt: p.completedAt ?? null, dismissedAt: p.dismissedAt ?? null } : { completedTaskIds: [], completedAt: null, dismissedAt: null };\n }\n\n completeChecklistTask(idOrKey: string, taskId: string): void {\n this.whenHydrated(() => {\n const guide = this.findGuide(idOrKey);\n const task = guide?.config.checklist?.tasks.find((t) => t.id === taskId);\n if (guide && task) this.markTaskDone(guide, task);\n });\n }\n\n private markTaskDone(guide: PublishedGuide, task: ChecklistTask): void {\n const config = guide.config.checklist;\n if (!config) return;\n const progress = this.state.checklists[guide.id] ?? (this.state.checklists[guide.id] = { completedTaskIds: [] });\n if (progress.completedTaskIds.includes(task.id)) return;\n progress.completedTaskIds.push(task.id);\n this.enqueue(\"checklist_task_completed\", { guideId: guide.id, guideVersion: guide.version, properties: { taskId: task.id } });\n const complete = isChecklistComplete(config, progress) && !progress.completedAt;\n if (complete) {\n progress.completedAt = nowIso();\n this.enqueue(\"checklist_completed\", { guideId: guide.id, guideVersion: guide.version });\n }\n this.persistState();\n this.sendDurably(`checklist:${guide.id}:progress:${this.anonymousId}`, `/checklists/${encodeURIComponent(guide.id)}/progress`, { anonymousId: this.anonymousId, userId: this.user?.id || null, guideVersion: guide.version, completedTaskIds: progress.completedTaskIds, completed: !!progress.completedAt });\n this.emitter.emit(\"checklist:task\", { guide, task, progress: this.getChecklistProgress(guide.id) });\n if (complete) {\n this.emitter.emit(\"checklist:complete\", guide);\n const w = this.checklists.get(guide.id);\n if (w) w.open = true;\n }\n this.notify();\n }\n\n private completeChecklistTasksBy(kind: ChecklistTask[\"completion\"], value: string | PublishedGuide): void {\n if (!this.config) return;\n for (const guide of this.config.guides) {\n for (const task of guide.config.checklist?.tasks ?? []) {\n if (task.completion !== kind || !task.completionValue) continue;\n let hit = false;\n if (kind === \"event\") hit = value === task.completionValue;\n else if (kind === \"url_visited\") hit = screenMatches(screenPath(task.completionValue), value as string) || screenMatches(task.completionValue, value as string);\n else if (kind === \"guide_completed\") hit = (value as PublishedGuide).id === task.completionValue || (value as PublishedGuide).key === task.completionValue;\n else if (kind === \"click\") hit = guidelyIdFromSelector(task.completionValue) === value;\n if (hit) this.markTaskDone(guide, task);\n }\n }\n }\n\n openChecklist(idOrKey: string): void {\n this.whenHydrated(() => {\n const guide = this.findGuide(idOrKey);\n if (!guide?.config.checklist) return;\n if (!this.checklists.has(guide.id)) {\n const p = this.state.checklists[guide.id];\n if (p?.dismissedAt) {\n delete p.dismissedAt;\n this.persistState();\n }\n this.showChecklist(guide, true);\n }\n this.setChecklistOpen(guide.id, true);\n });\n }\n\n closeChecklist(idOrKey: string): void {\n const guide = this.findGuide(idOrKey);\n if (guide) this.setChecklistOpen(guide.id, false);\n }\n\n // ---------------------------------------------------------------------------\n // Public guide controls\n // ---------------------------------------------------------------------------\n\n /** Starts a guide by id or key, bypassing targeting and frequency rules. */\n startGuide(idOrKey: string, options: { stepId?: string } = {}): boolean {\n const guide = this.findGuide(idOrKey);\n if (!guide) {\n this.reportError(new Error(`[Guidely] startGuide: unknown guide \"${idOrKey}\"`));\n return false;\n }\n if (guide.kind === \"checklist\") {\n this.openChecklist(guide.id);\n return true;\n }\n if (this.hasExclusive()) this.stopGuide();\n this.flows.get(guide.id)?.controller.destroy();\n this.flows.delete(guide.id);\n this.show(guide, true, options.stepId);\n return true;\n }\n\n /** Stops the active guide silently (no dismiss event). */\n stopGuide(): void {\n const a = this.active;\n if (a) {\n this.active = null;\n a.controller.destroy();\n }\n if (this.activeSurvey) {\n this.activeSurvey = null;\n this.surveyView = null;\n }\n this.notify();\n }\n\n /** Dismisses the active guide (records a dismissal). */\n dismissGuide(): void {\n if (this.active) this.active.controller.dismiss();\n else if (this.activeSurvey) this.finishSurvey(\"dismissed\");\n }\n\n getActiveGuide(): PublishedGuide | null {\n return this.hasExclusive();\n }\n\n getGuides(): ReadonlyArray<PublishedGuide> {\n return this.config?.guides ?? [];\n }\n\n isGuideCompleted(idOrKey: string): boolean {\n const guide = this.findGuide(idOrKey);\n return !!this.state.guides[guide?.id ?? idOrKey]?.completedAt;\n }\n\n /** Impressions, completion and dismissal for a guide. */\n getGuideState(idOrKey: string): GuideLocalState {\n const guide = this.findGuide(idOrKey);\n return { impressions: 0, ...(this.state.guides[guide?.id ?? idOrKey] ?? {}) };\n }\n\n openResourceCenter(): void {\n // With Scout on, help lives in the messenger's Help tab (one launcher, as on the web).\n if (this.messenger) return this.openMessenger(\"help\");\n if (!this.getResourceCenter()) {\n this.log(\"openResourceCenter: the resource center is not enabled or published for this environment\");\n return;\n }\n if (this.resourceCenterOpen) return;\n this.resourceCenterOpen = true;\n // Entries stay marked \"New\" while it is open; the launcher badge clears now.\n this.announcementsSeenAtOpen = this.state.announcementsSeenAt ?? null;\n if (this.getAnnouncements().length) {\n this.state.announcementsSeenAt = nowIso();\n this.persistState();\n }\n this.enqueue(\"resource_center_opened\");\n this.emitter.emit(\"resource-center:open\");\n this.notify();\n }\n\n closeResourceCenter(): void {\n if (this.messenger) return this.closeMessenger();\n if (!this.resourceCenterOpen) return;\n this.resourceCenterOpen = false;\n this.notify();\n }\n\n // ---------------------------------------------------------------------------\n // Scout messenger\n // ---------------------------------------------------------------------------\n\n /** Creates or removes the messenger to match the config (on only when enabled for this platform). */\n private syncMessenger(): void {\n const cfg = this.config?.messenger;\n if (cfg?.enabled) {\n if (this.messenger) this.messenger.updateConfig(cfg);\n else {\n this.messenger = new Messenger(cfg, {\n baseUrl: this.options.apiUrl,\n publicKey: this.options.projectId,\n store: this.store,\n fetch: this.options.fetch ?? fetch,\n streamPost: (this.options.fetch ? null : xhrStreamPost()) ?? fetchStreamPost(this.options.fetch ?? fetch),\n anonymousId: () => this.anonymousId,\n userId: () => this.user?.id || null,\n pageUrl: () => (this.collectUrls() && this.screenName ? this.currentUrl() : undefined),\n onOpen: () => {\n this.enqueue(\"messenger_opened\");\n this.emitter.emit(\"messenger:open\");\n },\n onMessage: (message, conversation) => this.emitter.emit(\"conversation:message\", { message, conversation }),\n onStartGuide: (key) => this.setTimer(() => this.startGuide(key), 0),\n onError: (err) => this.log(\"messenger\", err instanceof Error ? err.message : err),\n health: this.api.health,\n locale: () => this.articleLocale(),\n });\n this.resourceCenterOpen = false;\n }\n } else if (this.messenger) {\n this.messenger.destroy();\n this.messenger = null;\n }\n this.notify();\n }\n\n /** The Scout messenger store when Scout is on for this platform (rendered by the overlay). */\n getMessenger(): Messenger | null {\n return this.messenger;\n }\n\n /** Where the visitor dragged the messenger bubble on this device, or null to use the configured spot. */\n getMessengerLauncherPlacement(): LauncherPlacement | null {\n return parsePlacement(this.store.get(LAUNCHER_PLACEMENT_KEY));\n }\n\n /** Remembers the bubble's spot on this device (in memory only when no `storage` was passed). */\n setMessengerLauncherPlacement(placement: LauncherPlacement): void {\n this.store.set(LAUNCHER_PLACEMENT_KEY, serializePlacement(placement));\n }\n\n /** Opens the Scout messenger, optionally on a tab. No-op when Scout is off for this platform. */\n openMessenger(tab?: MessengerTab): void {\n this.whenHydrated(() => this.messenger?.open(tab));\n }\n\n closeMessenger(): void {\n this.messenger?.close();\n }\n\n /** Opens a new messenger conversation, optionally pre-filling the message. */\n showNewMessage(text?: string): void {\n this.whenHydrated(() => this.messenger?.showNewMessage(text));\n }\n\n // ---------------------------------------------------------------------------\n // Feature flags\n // ---------------------------------------------------------------------------\n\n /** Boolean flag value for the current user; `fallback` (default `false`) until loaded or when missing. */\n isFeatureEnabled(key: string, fallback = false): boolean {\n return this.flags.isEnabled(key, fallback);\n }\n\n /** Flag value for the current user; `fallback` when missing or of a different type. */\n getFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return this.flags.getValue(key, fallback);\n }\n\n /** Flag value plus why it was served (reason, rule, variation, experiment). */\n getFeatureDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return this.flags.getDetails(key, fallback);\n }\n\n /** Calls `cb` whenever flag values may have changed. Returns an unsubscribe function. */\n onFlagsChange(cb: () => void): () => void {\n return this.flags.subscribe(cb);\n }\n\n /** Device facts on every screen view, read by the Pages devices / browsers breakdowns. */\n private deviceProperties(): Record<string, string> {\n const d = this.bridge.device;\n return { platform: d.platform, deviceType: d.deviceType, os: d.platform, ...(d.osVersion ? { osVersion: d.osVersion } : {}) };\n }\n\n /** Attributes flags are evaluated with: identity, traits, account, audiences, screen and device. */\n private flagContext(): Attributes {\n const d = this.bridge.device;\n const account = this.user?.account;\n return {\n platform: d.platform,\n deviceType: d.deviceType,\n locale: d.locale,\n appVersion: this.options.appVersion ?? d.appVersion,\n osVersion: d.osVersion,\n environment: this.options.environment,\n ...(this.screenName ? { screen: this.screenName, path: this.currentUrl() } : {}),\n ...(this.user?.traits ?? {}),\n id: this.user?.id || this.anonymousId || undefined,\n anonymousId: this.anonymousId || undefined,\n account: account ? { ...(account.traits ?? {}), id: account.id } : undefined,\n $audiences: [...this.state.audienceIds],\n };\n }\n\n private syncFlagAttributes(): void {\n if (!this.destroyed) this.flags?.setContextAttributes(this.flagContext());\n }\n\n /** `experiment_viewed`, once per session and assignment, through the event queue (consent applies). */\n private trackExposure(result: EvaluationResult): void {\n const exp = result.inExperiment ? result.experiment : undefined;\n if (!exp || this.destroyed) return;\n this.whenHydrated(() => {\n const key = `${this.session.id}|${exp.key}|${exp.hashValue}|${exp.variationId}`;\n if (this.exposures.has(key)) return;\n if (this.exposures.size > 500) this.exposures.clear();\n this.exposures.add(key);\n this.enqueue(\"experiment_viewed\", { properties: { experimentKey: exp.key, variationId: exp.variationId, flagKey: result.key, hashAttribute: exp.hashAttribute, ...(exp.variationName ? { variationName: exp.variationName } : {}) } });\n });\n }\n\n on<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): () => void {\n return this.emitter.on(event, cb);\n }\n\n off<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): void {\n this.emitter.off(event, cb);\n }\n\n isClientReady(): boolean {\n return this.isReady;\n }\n\n /** Snapshot for debugging. */\n getState() {\n return {\n ready: this.isReady,\n destroyed: this.destroyed,\n anonymousId: this.anonymousId,\n user: this.user,\n consent: this.consent,\n screen: this.screenName,\n configVersion: this.config?.configVersion ?? null,\n guides: this.getGuides().map((g) => ({ id: g.id, key: g.key, kind: g.kind })),\n activeGuide: this.active ? { id: this.active.guide.id, key: this.active.guide.key, ...this.active.controller.getState() } : this.activeSurvey ? { id: this.activeSurvey.guide.id, key: this.activeSurvey.guide.key } : null,\n queued: this.queued.map((q) => q.guide.key),\n widgets: [...this.flows.keys(), ...this.checklists.keys()],\n guideState: this.state.guides,\n checklists: this.state.checklists,\n audienceIds: this.state.audienceIds,\n session: this.session,\n pendingEvents: this.queue?.size ?? 0,\n pendingWrites: this.outbox?.size ?? 0,\n targets: this.targets.ids(),\n flagsReady: this.flags.isReady(),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Internals\n // ---------------------------------------------------------------------------\n\n private persistState(): void {\n writeJson(this.store, KEYS.state(this.options.projectId), this.state);\n }\n\n private persistSession(): void {\n this.session.lastActiveAt = nowIso();\n writeJson(this.store, KEYS.session, this.session);\n }\n\n private reportError(err: unknown): void {\n const error = err instanceof Error ? err : new Error(String(err));\n this.log(\"error\", error.message);\n try {\n this.options.onError?.(error);\n } catch {\n /* ignore */\n }\n this.emitter.emit(\"error\", error);\n }\n\n private log(...args: unknown[]): void {\n if (this.options.debug && typeof console !== \"undefined\") console.log(\"[Guidely]\", ...args);\n }\n}\n\n/**\n * Keeps only the guides (and A/B control groups) enabled for this platform (the server already\n * filters; older caches may not be), and drops code blocks: they never run on React Native.\n */\nfunction forPlatform(config: SdkConfigResponse, platform: string): SdkConfigResponse {\n const keep = (g: PublishedGuide) => supportsPlatform(g.config, platform);\n const holdouts = config.guideHoldouts?.filter((h) => keep(h.guide)).map((h) => ({ ...h, guide: withoutCode(h.guide) }));\n return { ...config, guides: config.guides.filter(keep).map(withoutCode), ...(holdouts ? { guideHoldouts: holdouts } : {}) };\n}\n\n/** The guide without code-block steps' JavaScript (`step.code`), which mobile SDKs never execute. */\nfunction withoutCode(guide: PublishedGuide): PublishedGuide {\n if (!guide.config.steps.some((s) => s.code)) return guide;\n return { ...guide, config: { ...guide.config, steps: guide.config.steps.map(({ code: _code, ...step }) => step) } };\n}\n","import type { Insets } from \"./position\";\n\n/**\n * Where the visitor dragged the Scout bubble on this device: the side edge it snapped to and how\n * high it sits, as a fraction of the allowed range (0 = the default bottom position, 1 = highest).\n */\nexport interface LauncherPlacement {\n side: \"left\" | \"right\";\n fraction: number;\n}\n\n/** The window the bubble moves in. `defaultBottom` is today's gap between its bottom edge and the window bottom. */\nexport interface LauncherFrame {\n width: number;\n height: number;\n insets: Insets;\n size: number;\n defaultBottom: number;\n}\n\n/** Top-left corner of the bubble in window coordinates. */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Storage key (device-wide, like `guidely:anon`; the same on iOS, Android and Flutter). */\nexport const LAUNCHER_PLACEMENT_KEY = \"guidely:messenger.launcher\";\n/** Gap kept between the bubble and the safe-area edges. */\nexport const LAUNCHER_MARGIN = 16;\n/** Finger travel before a touch on the bubble becomes a drag instead of a tap. */\nexport const LAUNCHER_DRAG_THRESHOLD = 8;\n\nconst clamp = (v: number, min: number, max: number) => Math.min(max, Math.max(min, v));\n\n/** Left edge of the bubble when it rests on `side`. */\nexport function sideX(f: LauncherFrame, side: LauncherPlacement[\"side\"]): number {\n return side === \"left\" ? f.insets.left + LAUNCHER_MARGIN : f.width - f.insets.right - LAUNCHER_MARGIN - f.size;\n}\n\n/** Resting range of the bubble's top edge: `max` is the default bottom position (never lower), `min` the highest. */\nexport function verticalRange(f: LauncherFrame): { min: number; max: number } {\n const max = f.height - f.defaultBottom - f.size;\n return { min: Math.min(max, f.insets.top + LAUNCHER_MARGIN), max };\n}\n\n/** Keeps a dragged bubble inside the safe area. */\nexport function clampToSafeArea(f: LauncherFrame, p: Point): Point {\n const left = f.insets.left + LAUNCHER_MARGIN;\n const top = f.insets.top + LAUNCHER_MARGIN;\n return {\n x: clamp(p.x, left, Math.max(left, f.width - f.insets.right - LAUNCHER_MARGIN - f.size)),\n y: clamp(p.y, top, Math.max(top, f.height - f.insets.bottom - LAUNCHER_MARGIN - f.size)),\n };\n}\n\n/** Where a bubble dropped at `p` comes to rest: the nearer side edge, at the drop height clamped to the resting range. */\nexport function snapPlacement(f: LauncherFrame, p: Point): LauncherPlacement {\n const { min, max } = verticalRange(f);\n const side = p.x + f.size / 2 < f.width / 2 ? \"left\" : \"right\";\n return { side, fraction: max > min ? (max - clamp(p.y, min, max)) / (max - min) : 0 };\n}\n\n/** Top-left corner for a placement in this frame (re-clamped, so it survives rotation and size changes). */\nexport function placementPoint(f: LauncherFrame, placement: LauncherPlacement): Point {\n const { min, max } = verticalRange(f);\n return { x: sideX(f, placement.side), y: max - clamp(placement.fraction, 0, 1) * (max - min) };\n}\n\n/** Reads a stored placement; anything malformed reads as none, so the bubble sits where it always did. */\nexport function parsePlacement(raw: string | null | undefined): LauncherPlacement | null {\n if (!raw) return null;\n try {\n const v = JSON.parse(raw) as Partial<LauncherPlacement> | null;\n if (!v || typeof v !== \"object\" || (v.side !== \"left\" && v.side !== \"right\") || typeof v.fraction !== \"number\" || !Number.isFinite(v.fraction)) return null;\n return { side: v.side, fraction: clamp(v.fraction, 0, 1) };\n } catch {\n return null;\n }\n}\n\nexport function serializePlacement(p: LauncherPlacement): string {\n return JSON.stringify({ side: p.side, fraction: Math.round(clamp(p.fraction, 0, 1) * 1e4) / 1e4 });\n}\n","import type { AutocaptureSettings, HeatmapPoint } from \"@guidelytech/shared\";\nimport type { Rect } from \"./targets\";\n\n/** `autocapture` option: `false` turns every capability off, an object turns single ones off. */\nexport type AutocaptureOption = boolean | Partial<AutocaptureSettings>;\n\n/** A tap moves at most this far (points) and lasts less than {@link TAP_MAX_MS} (the replay definition). */\nexport const TAP_SLOP = 10;\nexport const TAP_MAX_MS = 1000;\n\n/** Points per `heatmap` event. */\nexport const HEATMAP_MAX_POINTS = 40;\n\n/** The element a tap resolved to (or the view it hit), as `click` properties need it. */\nexport interface TapElement {\n selector: string;\n /** Component / host name (`Pressable`, `TouchableOpacity`, `Text`, `View`). */\n tag: string;\n /** Visible label; already empty for text fields and masked content. */\n text?: string;\n /** Window frame of the element, for the position inside it (heatmaps). */\n measure?: () => Promise<Rect | null>;\n}\n\n/** One observed tap, reported by the provider's touch observer. */\nexport interface TapInfo {\n /** Window coordinates in points. */\n x: number;\n y: number;\n /** When the tap ended (ms since epoch); defaults to now. */\n t?: number;\n /** Innermost interactive element under the tap (touchable, `Pressable`, `accessibilityRole=\"button\"`…), if found. */\n element?: TapElement | null;\n /** The view the tap hit, used for rage taps and heatmaps when there is no interactive element. */\n hit?: TapElement | null;\n}\n\n/** `click` / `rage_click` properties on mobile (`ClickProperties` on the web plus `platform`). */\nexport interface TapProperties {\n selector: string;\n tag: string;\n text?: string;\n x: number;\n y: number;\n platform: string;\n count?: number;\n}\n\n/** Quotes an attribute-selector value: `\"` and `\\` escaped with `\\`. */\nexport function quoteValue(value: string): string {\n return `\"${value.replace(/[\"\\\\]/g, \"\\\\$&\")}\"`;\n}\n\n/** `[name=\"value\"]`. */\nexport function attrSelector(name: string, value: string): string {\n return `[${name}=${quoteValue(value)}]`.slice(0, 300);\n}\n\n/** Visible text for analytics: whitespace collapsed, trimmed, at most 100 UTF-16 units. */\nexport function cleanText(text: string | null | undefined): string | undefined {\n const t = (text ?? \"\").replace(/\\s+/g, \" \").trim();\n return t ? t.slice(0, 100) : undefined;\n}\n\n/** Builds `click` properties for an element. */\nexport function tapProperties(el: TapElement, x: number, y: number, platform: string, maskAll: boolean): TapProperties {\n const props: TapProperties = { selector: el.selector.slice(0, 300), tag: el.tag || \"View\", x: Math.round(x) || 0, y: Math.round(y) || 0, platform };\n const text = maskAll ? undefined : cleanText(el.text);\n if (text) props.text = text;\n return props;\n}\n\nconst r2 = (n: number) => Math.round(Math.min(1, Math.max(0, n)) * 100) / 100;\n\n/** One heatmap point: window x/y, the element selector and the position inside its frame (0–1). */\nexport function heatmapPoint(x: number, y: number, el: TapElement | null, rect: Rect | null, rage: boolean): HeatmapPoint {\n const p: HeatmapPoint = { k: rage ? \"r\" : \"c\", x: Math.round(x) || 0, y: Math.round(y) || 0 };\n const s = el?.selector.slice(0, 120);\n if (s) p.s = s;\n if (s && rect && rect.width > 0 && rect.height > 0) {\n p.rx = r2((x - rect.x) / rect.width);\n p.ry = r2((y - rect.y) / rect.height);\n }\n return p;\n}\n\n/**\n * Detects rage taps: 3+ taps within 1s (each within 1s of the previous) and 30pt of the burst's\n * first tap, reported once per burst. Same semantics as the web SDK's `RageClickDetector`\n * (conformance vectors: `rageClicks` in `mobile/conformance/vectors.json`).\n */\nexport class RageClickDetector {\n private clicks: Array<{ x: number; y: number; t: number }> = [];\n private fired = false;\n\n constructor(\n private readonly threshold = 3,\n private readonly windowMs = 1000,\n private readonly radius = 30,\n ) {}\n\n /** Taps in the current burst once it has fired (rage), otherwise 0. */\n get burst(): number {\n return this.fired ? this.clicks.length : 0;\n }\n\n /** Records a tap; returns the tap count when it completes a burst, otherwise 0. */\n add(x: number, y: number, t: number): number {\n const first = this.clicks[0];\n const last = this.clicks[this.clicks.length - 1];\n if (!first || !last || t - last.t > this.windowMs || Math.hypot(x - first.x, y - first.y) > this.radius) {\n this.clicks = [];\n this.fired = false;\n }\n this.clicks = this.clicks.filter((c) => t - c.t <= this.windowMs);\n this.clicks.push({ x, y, t });\n if (this.fired || this.clicks.length < this.threshold) return 0;\n this.fired = true;\n return this.clicks.length;\n }\n}\n\n/** Tap positions on the current screen, sent as one `heatmap` event per batch (40 points, screen change, background). */\nexport class HeatmapBuffer {\n /** Screen path the buffered points belong to. */\n url = \"\";\n points: HeatmapPoint[] = [];\n\n /** Adds a tap (`burst` > 0 marks it and the burst's previous taps as rage); true when the batch is full. */\n add(url: string, point: HeatmapPoint, burst: number): boolean {\n this.url = url;\n for (let i = Math.max(0, this.points.length - burst + 1); i < this.points.length; i++) (this.points[i] as HeatmapPoint).k = \"r\";\n this.points.push(point);\n return this.points.length >= HEATMAP_MAX_POINTS;\n }\n\n /** Empties the buffer, returning what was in it. */\n take(): { url: string; points: HeatmapPoint[] } | null {\n const points = this.points;\n this.points = [];\n return points.length ? { url: this.url, points } : null;\n }\n}\n\n/**\n * Tracks one primary-pointer touch and decides whether it was a tap. Feed it the touch events the\n * provider observes; `end` returns the tap position (window points) or null.\n */\nexport class TapTracker {\n private start: { x: number; y: number; t: number; id: unknown } | null = null;\n private moved = 0;\n\n /** A finger went down. A second finger while one is tracked cancels the gesture (not a tap). */\n begin(x: number, y: number, t: number, touches: number, id?: unknown): void {\n if (this.start || touches > 1) {\n this.start = null;\n return;\n }\n this.start = { x, y, t, id };\n this.moved = 0;\n }\n\n move(x: number, y: number, id?: unknown): void {\n const s = this.start;\n if (s && (id === undefined || s.id === undefined || id === s.id)) this.moved = Math.max(this.moved, Math.hypot(x - s.x, y - s.y));\n }\n\n /** The finger lifted: the tap position when it moved ≤ 10pt and lasted < 1s, else null. */\n end(x: number, y: number, t: number, id?: unknown): { x: number; y: number } | null {\n const s = this.start;\n if (!s || (id !== undefined && s.id !== undefined && id !== s.id)) return null;\n this.start = null;\n const moved = Math.max(this.moved, Math.hypot(x - s.x, y - s.y));\n return moved <= TAP_SLOP && t - s.t < TAP_MAX_MS ? { x, y } : null;\n }\n\n cancel(): void {\n this.start = null;\n }\n}\n","import { guidelyIdFromSelector } from \"@guidelytech/shared/runtime\";\nimport type { SelectorStrategy } from \"@guidelytech/shared\";\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A mounted `<GuidelyTarget>`; `measure` returns its frame in window coordinates. */\nexport interface TargetHandle {\n measure(): Promise<Rect | null>;\n /**\n * Screen the view lives on (from `GuidelyScreenScope`). Navigators keep inactive screens mounted\n * and laid out, so a target on another screen would otherwise measure as visible.\n */\n screen?: string | null;\n}\n\nexport class TargetTimeoutError extends Error {\n constructor(ids: string[]) {\n super(`[Guidely] target not found: ${ids.join(\", \") || \"(no mobile-compatible selector)\"}`);\n this.name = \"TargetTimeoutError\";\n }\n}\n\n/**\n * The Guidely ids a step target can match on mobile, in order: `guidely-id` and `id` strategies\n * by value, CSS / data-attribute strategies when they name a single id (`#x`, `[data-guidely-id=x]`).\n */\nexport function targetIdsFor(selectors: SelectorStrategy[]): string[] {\n const ids: string[] = [];\n for (const s of selectors) {\n let id: string | null = null;\n if (s.kind === \"guidely-id\" || s.kind === \"id\") id = s.value.trim().replace(/^#/, \"\") || null;\n else if (s.kind === \"css\" || s.kind === \"data-attr\") id = guidelyIdFromSelector(s.value);\n if (id && !ids.includes(id)) ids.push(id);\n }\n return ids;\n}\n\n/** Registry of mounted targets. One per client; `<GuidelyTarget>` registers itself on mount. */\nexport class TargetRegistry {\n private readonly targets = new Map<string, TargetHandle[]>();\n private readonly changeListeners = new Set<() => void>();\n private readonly tapListeners = new Set<(id: string) => void>();\n private viewport: { width: number; height: number } | null = null;\n private screen: string | null = null;\n\n register(id: string, handle: TargetHandle): () => void {\n const list = this.targets.get(id) ?? [];\n list.push(handle);\n this.targets.set(id, list);\n this.changed();\n return () => {\n const cur = this.targets.get(id);\n if (!cur) return;\n const next = cur.filter((h) => h !== handle);\n if (next.length) this.targets.set(id, next);\n else this.targets.delete(id);\n this.changed();\n };\n }\n\n /** Window size used for the on-screen check. */\n setViewport(width: number, height: number): void {\n this.viewport = { width, height };\n }\n\n /** The current screen; targets scoped to other screens are treated as hidden. */\n setScreen(name: string | null): void {\n if (name === this.screen) return;\n this.screen = name;\n this.changed();\n }\n\n has(id: string): boolean {\n return this.targets.has(id);\n }\n\n ids(): string[] {\n return Array.from(this.targets.keys());\n }\n\n /** Call when a target's layout may have changed (onLayout, scroll). */\n changed(): void {\n for (const cb of Array.from(this.changeListeners)) {\n try {\n cb();\n } catch {\n /* listener errors never break registration */\n }\n }\n }\n\n onChange(cb: () => void): () => void {\n this.changeListeners.add(cb);\n return () => this.changeListeners.delete(cb);\n }\n\n tapped(id: string): void {\n for (const cb of Array.from(this.tapListeners)) {\n try {\n cb(id);\n } catch {\n /* ignore */\n }\n }\n }\n\n onTap(cb: (id: string) => void): () => void {\n this.tapListeners.add(cb);\n return () => this.tapListeners.delete(cb);\n }\n\n /** Frame of a visible target (the most recently mounted visible one when an id is used twice), else null. */\n async measure(id: string): Promise<Rect | null> {\n const list = this.targets.get(id) ?? [];\n for (let i = list.length - 1; i >= 0; i--) {\n const handle = list[i] as TargetHandle;\n if (handle.screen && this.screen && handle.screen !== this.screen) continue;\n const r = await this.measureHandle(handle);\n if (r) return r;\n }\n return null;\n }\n\n private async measureHandle(handle: TargetHandle): Promise<Rect | null> {\n try {\n const r = await handle.measure();\n if (!r || !(r.width > 0) || !(r.height > 0)) return null;\n const vp = this.viewport;\n if (vp && (r.x + r.width <= 0 || r.y + r.height <= 0 || r.x >= vp.width || r.y >= vp.height)) return null;\n return r;\n } catch {\n return null;\n }\n }\n\n /**\n * The registered target on the current screen whose visible frame contains the point (window\n * coordinates); the smallest one when targets are nested. Frames that do not answer within\n * `timeoutMs` are skipped.\n */\n async hitTest(x: number, y: number, timeoutMs = 500): Promise<{ id: string; rect: Rect } | null> {\n const candidates: Array<{ id: string; handle: TargetHandle }> = [];\n this.targets.forEach((list, id) => {\n for (const handle of list) if (!(handle.screen && this.screen && handle.screen !== this.screen)) candidates.push({ id, handle });\n });\n if (!candidates.length) return null;\n const rects = await Promise.all(\n candidates.map(\n ({ handle }) =>\n new Promise<Rect | null>((resolve) => {\n const timer = setTimeout(() => resolve(null), timeoutMs);\n void this.measureHandle(handle).then((r) => {\n clearTimeout(timer);\n resolve(r);\n });\n }),\n ),\n );\n let best: { id: string; rect: Rect } | null = null;\n rects.forEach((r, i) => {\n if (!r || x < r.x || y < r.y || x > r.x + r.width || y > r.y + r.height) return;\n if (!best || r.width * r.height < best.rect.width * best.rect.height) best = { id: (candidates[i] as { id: string }).id, rect: r };\n });\n return best;\n }\n\n /** First of `ids` that is mounted and visible. */\n async resolve(ids: string[]): Promise<{ id: string; rect: Rect } | null> {\n for (const id of ids) {\n const rect = await this.measure(id);\n if (rect) return { id, rect };\n }\n return null;\n }\n\n /** Resolves when one of `ids` is visible; `timeoutMs` 0 waits forever. Re-checks on registry changes and every 300ms. */\n waitFor(ids: string[], options: { timeoutMs: number; signal?: AbortSignal }): Promise<{ id: string; rect: Rect }> {\n return new Promise((resolve, reject) => {\n let done = false;\n let checking = false;\n let again = false;\n const timers: Array<ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>> = [];\n const finish = (fn: () => void) => {\n if (done) return;\n done = true;\n off();\n timers.forEach((t) => clearTimeout(t as ReturnType<typeof setTimeout>));\n timers.forEach((t) => clearInterval(t as ReturnType<typeof setInterval>));\n options.signal?.removeEventListener?.(\"abort\", onAbort);\n fn();\n };\n const check = async () => {\n if (done) return;\n if (checking) {\n again = true;\n return;\n }\n checking = true;\n const hit = ids.length ? await this.resolve(ids) : null;\n checking = false;\n if (hit) return finish(() => resolve(hit));\n if (again) {\n again = false;\n void check();\n }\n };\n const onAbort = () => finish(() => reject(Object.assign(new Error(\"aborted\"), { name: \"AbortError\" })));\n if (options.signal?.aborted) return onAbort();\n options.signal?.addEventListener?.(\"abort\", onAbort);\n const off = this.onChange(() => void check());\n timers.push(setInterval(() => void check(), 300));\n if (options.timeoutMs > 0) timers.push(setTimeout(() => finish(() => reject(new TargetTimeoutError(ids))), options.timeoutMs));\n void check();\n });\n }\n}\n","import { evaluateRules, guidelyIdFromSelector, matchUrlPattern } from \"@guidelytech/shared/runtime\";\nimport type { EventName, GuideStep, PublishedGuide, StepButton, TargetingContext } from \"@guidelytech/shared\";\nimport { targetIdsFor, type TargetRegistry } from \"./targets\";\n\n/**\n * Headless port of `@guidelytech/guide-runtime`'s `runGuide`: walks steps, waits for targets,\n * handles advancement, branches, multi-screen steps, buttons and back history. Instead of touching\n * a DOM it reports the step to show through `onRender`, and the React Native overlay draws it.\n */\n\nexport interface RuntimeEvent {\n name: EventName;\n stepId?: string;\n stepIndex?: number;\n properties?: Record<string, unknown>;\n}\n\nexport type GuideEndReason = \"completed\" | \"dismissed\" | \"skipped\" | \"destroyed\";\nexport type GuideStatus = \"idle\" | \"running\" | \"waiting_url\" | \"waiting_target\" | \"ended\";\n\nexport interface RenderedStep {\n step: GuideStep;\n index: number;\n total: number;\n canGoBack: boolean;\n targetId: string | null;\n asModal: boolean;\n}\n\nexport interface ControllerOptions {\n targets: TargetRegistry;\n ctx: () => TargetingContext;\n /** Current screen path (`/Deals`). */\n currentUrl: () => string;\n onEvent: (event: RuntimeEvent) => void;\n onRender: (step: RenderedStep) => void;\n onClear: () => void;\n onNavigate: (url: string) => void;\n onAction: (action: \"start_guide\" | \"event\" | \"open_resource_center\", value?: string) => void;\n onEnd: (reason: GuideEndReason) => void;\n onError?: (err: unknown) => void;\n eventBus: { on(name: string, cb: () => void): () => void };\n startAtStep?: string;\n}\n\nexport interface GuideController {\n readonly guide: PublishedGuide;\n start(): void;\n next(): void;\n back(): void;\n goTo(stepId: string): void;\n dismiss(): void;\n complete(): void;\n skip(): void;\n press(button: StepButton): void;\n /** Re-evaluate a step waiting for a screen (call after `screen()`). */\n resume(): void;\n destroy(): void;\n getState(): { status: GuideStatus; stepId: string | null; stepIndex: number; total: number };\n}\n\nconst ANCHORED = new Set([\"tooltip\", \"popover\", \"spotlight\", \"hotspot\"]);\nexport const isAnchoredStep = (step: GuideStep) => ANCHORED.has(step.type);\n/** Same rule as `visibleButtons` in `@guidelytech/shared`: no Back button without a previous step. */\nexport function visibleButtons(step: GuideStep, canGoBack: boolean): StepButton[] {\n return canGoBack ? step.buttons : step.buttons.filter((b) => b.action !== \"back\");\n}\n\n/** `urlMatches` from the web runtime, for screen paths: a pattern without `?`/`#` ignores the query. */\nexport function screenMatches(pattern: string | undefined | null, url: string): boolean {\n if (!pattern) return true;\n if (matchUrlPattern(pattern, url)) return true;\n if (!pattern.includes(\"?\") && !pattern.includes(\"#\")) return matchUrlPattern(pattern, url.split(/[?#]/)[0] ?? url);\n return false;\n}\n\nexport function runGuide(guide: PublishedGuide, o: ControllerOptions): GuideController {\n const steps = guide.config.steps;\n const total = steps.length;\n const onError = o.onError ?? (() => {});\n let status: GuideStatus = \"idle\";\n let index = -1;\n let pendingIndex = -1;\n let rendered = false;\n let started = false;\n let stepDone = false;\n let ended = false;\n const history: number[] = [];\n const stepCleanups: Array<() => void> = [];\n\n const emit = (name: EventName, step?: GuideStep | null, stepIndex?: number, properties?: Record<string, unknown>) => {\n try {\n o.onEvent({ name, stepId: step?.id, stepIndex, properties });\n } catch (err) {\n onError(err);\n }\n };\n\n const clearStep = () => {\n stepCleanups.splice(0).forEach((fn) => {\n try {\n fn();\n } catch {\n /* ignore */\n }\n });\n if (rendered) {\n rendered = false;\n try {\n o.onClear();\n } catch (err) {\n onError(err);\n }\n }\n stepDone = false;\n };\n\n const end = (reason: GuideEndReason) => {\n if (ended) return;\n ended = true;\n const step = steps[index];\n clearStep();\n status = \"ended\";\n if (reason === \"completed\") emit(\"guide_completed\", step, index);\n else if (reason === \"dismissed\") emit(\"guide_dismissed\", step, index);\n else if (reason === \"skipped\") emit(\"guide_skipped\", step, index);\n try {\n o.onEnd(reason);\n } catch (err) {\n onError(err);\n }\n };\n\n const completeStep = () => {\n if (stepDone || index < 0) return;\n stepDone = true;\n emit(\"step_completed\", steps[index], index);\n };\n\n const goNext = (overrideStepId?: string) => {\n const step = steps[index];\n let target = -1;\n const ctx = o.ctx();\n if (step) {\n for (const branch of step.branches) {\n if (evaluateRules(branch.when, ctx)) {\n target = steps.findIndex((s) => s.id === branch.goTo);\n if (target >= 0) break;\n }\n }\n }\n if (target < 0 && overrideStepId) target = steps.findIndex((s) => s.id === overrideStepId);\n if (target < 0) target = index + 1;\n if (target >= total) return end(\"completed\");\n history.push(index);\n showStep(target, 1);\n };\n\n const advance = () => {\n if (ended) return;\n completeStep();\n goNext();\n };\n\n const press = (b: StepButton) => {\n try {\n switch (b.action) {\n case \"next\":\n completeStep();\n goNext(b.value);\n break;\n case \"back\":\n controller.back();\n break;\n case \"dismiss\":\n end(\"dismissed\");\n break;\n case \"complete\":\n completeStep();\n end(\"completed\");\n break;\n case \"skip\":\n end(\"skipped\");\n break;\n case \"url\":\n completeStep();\n o.onNavigate(b.value || \"\");\n if (index + 1 >= total) end(\"completed\");\n else goNext();\n break;\n case \"start_guide\":\n completeStep();\n end(\"completed\");\n o.onAction(\"start_guide\", b.value);\n break;\n case \"event\":\n o.onAction(\"event\", b.value);\n break;\n case \"open_resource_center\":\n o.onAction(\"open_resource_center\", b.value);\n break;\n default:\n break;\n }\n } catch (err) {\n onError(err);\n }\n };\n\n const setupAdvance = (step: GuideStep, targetId: string | null) => {\n const modes = step.advanceOn === \"any\" ? [\"element_click\", \"element_visible\", \"event\", \"delay\"] : [step.advanceOn];\n for (const mode of modes) {\n // The editor documents an empty element value as \"use the step target\".\n const id = guidelyIdFromSelector(step.advanceValue) ?? (mode === \"element_click\" ? targetId : null);\n if (mode === \"element_click\" && id) {\n stepCleanups.push(o.targets.onTap((tapped) => tapped === id && advance()));\n } else if (mode === \"element_visible\" && id) {\n const ac = new AbortController();\n stepCleanups.push(() => ac.abort());\n o.targets.waitFor([id], { timeoutMs: 0, signal: ac.signal }).then(() => !ac.signal.aborted && advance(), () => {});\n } else if (mode === \"event\" && step.advanceValue) {\n stepCleanups.push(o.eventBus.on(step.advanceValue, advance));\n } else if (mode === \"delay\") {\n const t = setTimeout(advance, step.advanceDelayMs ?? 3000);\n stepCleanups.push(() => clearTimeout(t));\n }\n }\n };\n\n const render = (step: GuideStep, targetId: string | null, asModal = false) => {\n if (ended) return;\n status = \"running\";\n try {\n o.onRender({ step, index, total, canGoBack: history.length > 0 || index > 0, targetId, asModal });\n rendered = true;\n } catch (err) {\n onError(err);\n if (index + 1 < total) return goNext();\n return end(\"skipped\");\n }\n if (!started) {\n started = true;\n emit(\"guide_started\", step, index);\n }\n emit(\"step_viewed\", step, index, asModal ? { fallback: \"show_as_modal\" } : undefined);\n setupAdvance(step, targetId);\n };\n\n const applyFallback = (step: GuideStep, direction: 1 | -1) => {\n const fallback = step.target?.fallback ?? \"skip\";\n emit(\"step_viewed\", step, index, { fallback, targetMissing: true });\n if (fallback === \"show_as_modal\") return render(step, null, true);\n if (fallback === \"end_guide\") return end(\"skipped\");\n const nextIndex = index + direction;\n if (nextIndex < 0) return showStep(0, 1);\n if (nextIndex >= total) return end(\"completed\");\n showStep(nextIndex, direction);\n };\n\n function showStep(i: number, direction: 1 | -1 = 1): void {\n if (ended) return;\n clearStep();\n if (i < 0) i = 0;\n if (i >= total) return end(\"completed\");\n index = i;\n const step = steps[i] as GuideStep;\n if (step.targeting && step.targeting.rules.length && !evaluateRules(step.targeting, o.ctx())) {\n const nextIndex = i + direction;\n if (nextIndex >= total) return end(\"completed\");\n if (nextIndex < 0) return;\n return showStep(nextIndex, direction);\n }\n if (step.url && !screenMatches(step.url, o.currentUrl())) {\n status = \"waiting_url\";\n pendingIndex = i;\n return;\n }\n pendingIndex = -1;\n if (isAnchoredStep(step) && step.target) {\n status = \"waiting_target\";\n const ids = targetIdsFor(step.target.selectors);\n if (!ids.length) return applyFallback(step, direction);\n const ac = new AbortController();\n stepCleanups.push(() => ac.abort());\n const timeoutMs = step.target.fallback === \"wait\" ? 0 : step.target.waitMs;\n o.targets.waitFor(ids, { timeoutMs, signal: ac.signal }).then(\n (hit) => {\n if (ac.signal.aborted || ended) return;\n render(step, hit.id);\n },\n (err) => {\n if (ac.signal.aborted || ended || (err as Error)?.name === \"AbortError\") return;\n applyFallback(step, direction);\n },\n );\n return;\n }\n render(step, null);\n }\n\n const controller: GuideController = {\n guide,\n start() {\n if (status !== \"idle\") return;\n emit(\"guide_viewed\");\n if (total === 0) return end(\"completed\");\n let startIndex = o.startAtStep ? steps.findIndex((s) => s.id === o.startAtStep) : 0;\n if (startIndex < 0) startIndex = 0;\n showStep(startIndex, 1);\n },\n next() {\n if (ended || index < 0) return;\n completeStep();\n goNext();\n },\n back() {\n if (ended) return;\n const prev = history.pop();\n if (prev == null) {\n if (index > 0) showStep(index - 1, -1);\n return;\n }\n showStep(prev, -1);\n },\n goTo(stepId) {\n const i = steps.findIndex((s) => s.id === stepId);\n if (i >= 0 && !ended) {\n if (index >= 0) history.push(index);\n showStep(i, 1);\n }\n },\n dismiss: () => end(\"dismissed\"),\n complete() {\n completeStep();\n end(\"completed\");\n },\n skip: () => end(\"skipped\"),\n press,\n resume() {\n if (ended) return;\n if (status === \"waiting_url\" && pendingIndex >= 0) return showStep(pendingIndex, 1);\n const step = steps[index];\n if (step?.url && status === \"running\" && !screenMatches(step.url, o.currentUrl())) showStep(index, 1);\n },\n destroy() {\n if (ended) return;\n ended = true;\n clearStep();\n status = \"ended\";\n try {\n o.onEnd(\"destroyed\");\n } catch (err) {\n onError(err);\n }\n },\n getState: () => ({ status, stepId: steps[index]?.id ?? null, stepIndex: index, total }),\n };\n return controller;\n}\n","import type {\n ConversationLookupResponse,\n ConversationMessagesResponse,\n MessengerConfig,\n MessengerConversation,\n MessengerMessage,\n ResourceCenterArticle,\n SdkArticlesResponse,\n StartConversationResponse,\n} from \"@guidelytech/shared\";\nimport { KEYS, isServerFailure, readJson, writeJson, type KeyValueStore, type ServerHealth } from \"@guidelytech/sdk-core/headless\";\n\n/**\n * Scout messenger for React Native: the transport of `@guidelytech/sdk-core`'s messenger-api plus\n * the conversation state the web widget keeps, as a headless store the overlay renders.\n */\n\nexport type MessengerTab = \"home\" | \"messages\" | \"help\";\nexport type MessengerView = { kind: \"tab\"; tab: MessengerTab } | { kind: \"thread\"; conversationId: string | null } | { kind: \"article\"; articleId: string; from: MessengerView };\n\nexport interface MessengerThread {\n conversation: MessengerConversation | null;\n messages: MessengerMessage[];\n /** Reply text streamed so far, by message id (before the final `done` message arrives). */\n streaming: Record<string, string>;\n sending: boolean;\n error: string | null;\n /** Text to pre-fill in the composer (`showNewMessage(text)`). */\n draft: string;\n}\n\nexport interface MessengerSnapshot {\n config: MessengerConfig;\n open: boolean;\n view: MessengerView;\n conversations: MessengerConversation[];\n thread: MessengerThread | null;\n /** Conversations with unread replies. */\n unread: number;\n articles: SdkArticlesResponse | null;\n article: ResourceCenterArticle | null;\n}\n\nconst TOKEN_HEADER = \"X-Guidely-Conversation\";\nconst MAX_STORED = 50;\n\ninterface StoredConversation {\n id: string;\n token: string;\n}\n\n/** Incremental `text/event-stream` parser: `event:` + single-line JSON `data:`, `:` comments ignored. */\nexport function createSseParser(onEvent: (event: string, data: unknown) => void) {\n let buffer = \"\";\n const dispatch = (raw: string) => {\n let event = \"message\";\n const data: string[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) continue;\n const i = line.indexOf(\":\");\n const field = i < 0 ? line : line.slice(0, i);\n const value = i < 0 ? \"\" : line.slice(i + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n }\n if (!data.length) return;\n try {\n onEvent(event, JSON.parse(data.join(\"\\n\")));\n } catch {\n /* ignore malformed events */\n }\n };\n return {\n feed(chunk: string) {\n buffer += chunk.replace(/\\r\\n?/g, \"\\n\");\n let sep: number;\n while ((sep = buffer.indexOf(\"\\n\\n\")) >= 0) {\n dispatch(buffer.slice(0, sep));\n buffer = buffer.slice(sep + 2);\n }\n },\n end() {\n if (buffer.trim()) dispatch(buffer);\n buffer = \"\";\n },\n };\n}\n\nexport interface HttpResult {\n status: number;\n /** JSON body when the server answered with JSON. */\n json: unknown;\n}\n\n/**\n * POST that streams server-sent events as they arrive. React Native's `fetch` cannot read a body\n * incrementally, but its `XMLHttpRequest` reports partial `responseText` on progress events.\n */\nexport type StreamPost = (url: string, headers: Record<string, string>, body: unknown, onChunk: (text: string) => void) => Promise<HttpResult & { streamed: boolean }>;\n\n/** Reply streams: the response must start within this long, and then never go quiet longer than the idle limit (the server sends a keepalive every 15 s). */\nexport const STREAM_RESPONSE_TIMEOUT_MS = 30_000;\nexport const STREAM_IDLE_TIMEOUT_MS = 60_000;\n\nexport function xhrStreamPost(): StreamPost | null {\n if (typeof XMLHttpRequest === \"undefined\") return null;\n return (url, headers, body, onChunk) =>\n new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n let seen = 0;\n let streamed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer) clearTimeout(timer);\n fn();\n };\n // No overall timeout (Scout replies can take a while), but a server that never answers or goes\n // silent mid-reply aborts the request instead of leaving the composer spinning forever.\n const arm = (ms: number, what: string) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n settle(() => reject(new Error(`Scout ${what} timed out`)));\n xhr.abort();\n }, ms);\n };\n const pump = () => {\n const type = xhr.getResponseHeader(\"content-type\") || \"\";\n if (!type.includes(\"text/event-stream\")) return;\n streamed = true;\n const text = xhr.responseText || \"\";\n if (text.length > seen) {\n onChunk(text.slice(seen));\n seen = text.length;\n }\n };\n xhr.open(\"POST\", url);\n for (const [k, v] of Object.entries(headers)) xhr.setRequestHeader(k, v);\n xhr.onreadystatechange = () => {\n if (!settled && xhr.readyState >= 2 && xhr.readyState < 4) arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n };\n xhr.onprogress = () => {\n if (settled) return;\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n pump();\n };\n xhr.onload = () =>\n settle(() => {\n pump();\n let json: unknown = null;\n if (!streamed) {\n try {\n json = JSON.parse(xhr.responseText || \"null\");\n } catch {\n json = null;\n }\n }\n resolve({ status: xhr.status, json, streamed });\n });\n xhr.onerror = () => settle(() => reject(new Error(\"Network request failed\")));\n arm(STREAM_RESPONSE_TIMEOUT_MS, \"request\");\n xhr.send(JSON.stringify(body));\n });\n}\n\n/** The parts of a streaming `fetch` body read below; React Native's types (no DOM lib) don't declare them. */\ninterface ByteReader {\n read(): Promise<{ done: boolean; value?: Uint8Array }>;\n}\ninterface TextDecoderLike {\n decode(input?: Uint8Array, options?: { stream?: boolean }): string;\n}\n\n/** A streaming reader for the body, or null when the `fetch` or the runtime (no `TextDecoder`) can't stream it. */\nfunction bodyReader(res: Response): { reader: ByteReader; decoder: TextDecoderLike } | null {\n const body = (res as { body?: { getReader?: () => ByteReader } | null }).body;\n const Decoder = (globalThis as { TextDecoder?: new () => TextDecoderLike }).TextDecoder;\n return body && typeof body.getReader === \"function\" && Decoder ? { reader: body.getReader(), decoder: new Decoder() } : null;\n}\n\n/** Fallback (tests, platforms without XHR): reads the body as it arrives when the `fetch` exposes a stream, otherwise waits for all of it. Same timeouts as {@link xhrStreamPost}. */\nexport function fetchStreamPost(fetchImpl: typeof fetch): StreamPost {\n return async (url, headers, body, onChunk) => {\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let timedOut = \"\";\n // Rejects on its own too, for `fetch` implementations that ignore the abort signal.\n let fail: (err: Error) => void = () => {};\n const expired = new Promise<never>((_, reject) => (fail = reject));\n expired.catch(() => {});\n const arm = (ms: number, what: string) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timedOut = what;\n ac?.abort();\n fail(new Error(`Scout ${what} timed out`));\n }, ms);\n };\n const race = <T>(p: Promise<T>) => Promise.race([p, expired]);\n arm(STREAM_RESPONSE_TIMEOUT_MS, \"request\");\n try {\n const res = await race(fetchImpl(url, { method: \"POST\", headers, body: JSON.stringify(body), signal: ac?.signal }));\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n const type = res.headers.get(\"content-type\") || \"\";\n const sse = type.includes(\"text/event-stream\");\n const streaming = sse ? bodyReader(res) : null;\n if (streaming) {\n const { reader, decoder } = streaming;\n for (;;) {\n const { done, value } = await race(reader.read());\n if (value) {\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n onChunk(decoder.decode(value, { stream: true }));\n }\n if (done) break;\n }\n const rest = decoder.decode();\n if (rest) onChunk(rest);\n return { status: res.status, json: null, streamed: true };\n }\n const text = await race(res.text());\n if (sse) {\n onChunk(text);\n return { status: res.status, json: null, streamed: true };\n }\n let json: unknown = null;\n try {\n json = JSON.parse(text || \"null\");\n } catch {\n json = null;\n }\n return { status: res.status, json, streamed: false };\n } catch (err) {\n throw timedOut ? new Error(`Scout ${timedOut} timed out`) : err;\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n}\n\nexport interface MessengerDeps {\n baseUrl: string;\n publicKey: string;\n store: KeyValueStore;\n fetch: typeof fetch;\n streamPost: StreamPost;\n anonymousId: () => string;\n userId: () => string | null;\n /** Screen path to attach to new conversations (omitted when URL collection is off). */\n pageUrl: () => string | undefined;\n onOpen: () => void;\n onMessage: (message: MessengerMessage, conversation: MessengerConversation) => void;\n onStartGuide: (key: string) => void;\n onError: (err: unknown) => void;\n /** The SDK API's circuit breaker, told how each reply stream went. */\n health?: ServerHealth;\n /** The help center's language when it isn't the default; translated articles are fetched with `?locale=`. */\n locale?: () => string | undefined;\n /** Poll intervals (ms): open thread, and unread badge otherwise. */\n pollMs?: { thread: number; background: number };\n}\n\nconst byNewest = (a: MessengerConversation, b: MessengerConversation) => Date.parse(b.lastMessageAt) - Date.parse(a.lastMessageAt);\n\nexport class Messenger {\n private snapshot: MessengerSnapshot;\n private readonly listeners = new Set<() => void>();\n private threadTimer: ReturnType<typeof setTimeout> | null = null;\n private backgroundTimer: ReturnType<typeof setInterval> | null = null;\n private foreground = true;\n private destroyed = false;\n private readonly poll: { thread: number; background: number };\n\n constructor(\n config: MessengerConfig,\n private readonly deps: MessengerDeps,\n ) {\n this.poll = deps.pollMs ?? { thread: 5000, background: 60000 };\n this.snapshot = { config, open: false, view: { kind: \"tab\", tab: \"home\" }, conversations: [], thread: null, unread: 0, articles: null, article: null };\n void this.refreshConversations();\n this.startBackgroundPolling();\n }\n\n // -------------------------------------------------------------------------- state\n\n getSnapshot(): MessengerSnapshot {\n return this.snapshot;\n }\n\n subscribe(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n private set(patch: Partial<MessengerSnapshot>): void {\n if (this.destroyed) return;\n const next = { ...this.snapshot, ...patch };\n next.unread = next.conversations.filter((c) => c.unread > 0).length;\n this.snapshot = next;\n for (const cb of Array.from(this.listeners)) {\n try {\n cb();\n } catch (err) {\n this.deps.onError(err);\n }\n }\n }\n\n private setThread(patch: Partial<MessengerThread>): void {\n const t = this.snapshot.thread;\n if (!t) return;\n this.set({ thread: { ...t, ...patch } });\n }\n\n updateConfig(config: MessengerConfig): void {\n this.set({ config });\n }\n\n // -------------------------------------------------------------------------- tokens\n\n private stored(): StoredConversation[] {\n const list = readJson<StoredConversation[]>(this.deps.store, KEYS.conversations(this.deps.publicKey), []);\n return Array.isArray(list) ? list.filter((c) => c && typeof c.id === \"string\" && typeof c.token === \"string\") : [];\n }\n\n private remember(id: string, token: string): void {\n writeJson(this.deps.store, KEYS.conversations(this.deps.publicKey), [{ id, token }, ...this.stored().filter((c) => c.id !== id)].slice(0, MAX_STORED));\n }\n\n private tokenFor(id: string): string {\n return this.stored().find((c) => c.id === id)?.token ?? \"\";\n }\n\n /** Forgets every conversation (logout). */\n forgetAll(): void {\n this.deps.store.remove(KEYS.conversations(this.deps.publicKey));\n this.stopThreadPolling();\n this.set({ open: false, view: { kind: \"tab\", tab: \"home\" }, conversations: [], thread: null, article: null });\n }\n\n // -------------------------------------------------------------------------- http\n\n private url(path: string, params: Record<string, string | undefined> = {}): string {\n const query = Object.entries({ key: this.deps.publicKey, ...params })\n .filter((e): e is [string, string] => e[1] != null)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n return `${this.deps.baseUrl.replace(/\\/$/, \"\")}/api/v1/sdk${path}?${query}`;\n }\n\n private headers(extra: Record<string, string> = {}): Record<string, string> {\n return { \"X-Guidely-Key\": this.deps.publicKey, Accept: \"application/json\", \"Content-Type\": \"application/json\", ...extra };\n }\n\n private async request<T>(method: \"GET\" | \"POST\", path: string, opts: { body?: unknown; params?: Record<string, string | undefined>; conversationId?: string } = {}): Promise<T> {\n const headers = this.headers(opts.conversationId ? { [TOKEN_HEADER]: this.tokenFor(opts.conversationId) } : {});\n const res = await this.deps.fetch(this.url(path, opts.params), { method, headers, body: opts.body === undefined ? undefined : JSON.stringify(opts.body) });\n if (!res.ok) throw new Error(`Request failed (${res.status})`);\n return (await res.json()) as T;\n }\n\n // -------------------------------------------------------------------------- navigation\n\n open(tab?: MessengerTab): void {\n const wasOpen = this.snapshot.open;\n this.set({ open: true, ...(tab ? { view: { kind: \"tab\", tab } as MessengerView } : {}) });\n if (!wasOpen) {\n this.deps.onOpen();\n void this.refreshConversations();\n }\n if (tab === \"help\" || this.snapshot.view.kind === \"tab\") this.onView();\n }\n\n close(): void {\n this.stopThreadPolling();\n this.set({ open: false });\n }\n\n setTab(tab: MessengerTab): void {\n this.stopThreadPolling();\n this.set({ view: { kind: \"tab\", tab }, thread: null });\n this.onView();\n }\n\n private onView(): void {\n const v = this.snapshot.view;\n if (v.kind === \"tab\" && v.tab === \"help\" && !this.snapshot.articles) void this.loadArticles();\n if (v.kind === \"tab\" && v.tab === \"messages\") void this.refreshConversations();\n }\n\n /** Opens a new thread (optionally pre-filling the composer). */\n showNewMessage(text = \"\"): void {\n this.stopThreadPolling();\n if (!this.snapshot.open) this.deps.onOpen();\n this.set({ open: true, view: { kind: \"thread\", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft: text } });\n }\n\n async openConversation(id: string): Promise<void> {\n const known = this.snapshot.conversations.find((c) => c.id === id) ?? null;\n this.stopThreadPolling();\n this.set({ open: true, view: { kind: \"thread\", conversationId: id }, thread: { conversation: known, messages: [], streaming: {}, sending: false, error: null, draft: \"\" } });\n try {\n const res = await this.request<ConversationMessagesResponse>(\"GET\", `/conversations/${encodeURIComponent(id)}/messages`, { conversationId: id });\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 }, messages: res.messages });\n } catch (err) {\n this.setThread({ error: \"Couldn't load this conversation.\" });\n this.deps.onError(err);\n }\n this.scheduleThreadPoll();\n }\n\n back(): void {\n const v = this.snapshot.view;\n if (v.kind === \"article\") return this.set({ view: v.from, article: null });\n this.setTab(this.snapshot.thread?.conversation ? \"messages\" : \"home\");\n }\n\n // -------------------------------------------------------------------------- conversations\n\n private upsertConversation(c: MessengerConversation): void {\n const list = [c, ...this.snapshot.conversations.filter((x) => x.id !== c.id)].sort(byNewest);\n this.set({ conversations: list });\n }\n\n private markRead(c: MessengerConversation): void {\n this.upsertConversation({ ...c, unread: 0 });\n }\n\n async refreshConversations(): Promise<void> {\n const stored = this.stored();\n if (!stored.length) return;\n try {\n const res = await this.request<ConversationLookupResponse>(\"POST\", \"/conversations/lookup\", { body: { tokens: stored.map((c) => c.token) } });\n const known = new Set(res.conversations.map((c) => c.id));\n // Drop tokens the server no longer knows (deleted by retention).\n if (stored.some((c) => !known.has(c.id))) writeJson(this.deps.store, KEYS.conversations(this.deps.publicKey), stored.filter((c) => known.has(c.id)));\n const openId = this.snapshot.view.kind === \"thread\" ? this.snapshot.view.conversationId : null;\n const list = res.conversations.map(({ token: _token, ...c }) => (c.id === openId && this.snapshot.open ? { ...c, unread: 0 } : c)).sort(byNewest);\n this.set({ conversations: list });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n /** Sends the composer text: starts a conversation or posts to the open one. Streams Scout's reply. */\n async send(text: string): Promise<void> {\n const body = text.trim().slice(0, 4000);\n const thread = this.snapshot.thread;\n if (!body || !thread || thread.sending) return;\n this.setThread({ sending: true, error: null, draft: \"\" });\n const conversationId = thread.conversation?.id ?? null;\n const path = conversationId ? `/conversations/${encodeURIComponent(conversationId)}/messages` : \"/conversations\";\n const payload = conversationId ? { message: body } : { anonymousId: this.deps.anonymousId(), userId: this.deps.userId(), message: body, pageUrl: this.deps.pageUrl() };\n const headers = { ...this.headers(conversationId ? { [TOKEN_HEADER]: this.tokenFor(conversationId) } : {}), Accept: \"text/event-stream, application/json\" };\n let finished = false;\n const parser = createSseParser((event, data) => {\n if (event === \"conversation\") {\n const d = data as StartConversationResponse;\n this.remember(d.conversation.id, d.token);\n this.markRead(d.conversation);\n this.set({ view: { kind: \"thread\", conversationId: d.conversation.id } });\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n d.messages.forEach((m) => this.addMessage(m));\n } else if (event === \"message\") this.addMessage(data as MessengerMessage);\n else if (event === \"delta\") {\n const d = data as { messageId: string; text: string };\n const t = this.snapshot.thread;\n if (t) this.setThread({ streaming: { ...t.streaming, [d.messageId]: (t.streaming[d.messageId] ?? \"\") + d.text } });\n } else if (event === \"done\") {\n finished = true;\n const d = data as { message: MessengerMessage | null; conversation: MessengerConversation };\n if (d.message) this.addMessage(d.message);\n this.markRead(d.conversation);\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n } else if (event === \"error\") {\n this.setThread({ error: (data as { message?: string })?.message ?? \"Something went wrong\" });\n }\n });\n try {\n let res: HttpResult & { streamed: boolean };\n try {\n res = await this.deps.streamPost(this.url(path), headers, payload, (chunk) => parser.feed(chunk));\n } catch (err) {\n this.deps.health?.failure();\n throw err;\n }\n if (isServerFailure(res.status)) this.deps.health?.failure();\n else this.deps.health?.success();\n parser.end();\n if (res.status < 200 || res.status >= 300) throw new Error(`Request failed (${res.status})`);\n if (!res.streamed && res.json) {\n const d = res.json as StartConversationResponse | ConversationMessagesResponse;\n if (\"token\" in d) {\n this.remember(d.conversation.id, d.token);\n this.set({ view: { kind: \"thread\", conversationId: d.conversation.id } });\n }\n this.markRead(d.conversation);\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n d.messages.forEach((m) => this.addMessage(m));\n } else if (res.streamed && !finished) this.setThread({ error: \"The reply was interrupted. Pull to refresh in a moment.\" });\n } catch (err) {\n this.setThread({ error: \"Your message wasn't sent. Check your connection and try again.\", draft: body });\n this.deps.onError(err);\n } finally {\n const t = this.snapshot.thread;\n if (t) this.setThread({ sending: false, streaming: {} });\n this.scheduleThreadPoll();\n }\n }\n\n private addMessage(m: MessengerMessage): void {\n const t = this.snapshot.thread;\n if (!t) return;\n const exists = t.messages.some((x) => x.id === m.id);\n const messages = exists ? t.messages.map((x) => (x.id === m.id ? m : x)) : [...t.messages, m];\n const streaming = { ...t.streaming };\n if (m.status !== \"pending\") delete streaming[m.id];\n this.setThread({ messages, streaming });\n if (!exists && m.status !== \"pending\" && (m.author === \"scout\" || m.author === \"agent\") && t.conversation) this.deps.onMessage(m, t.conversation);\n }\n\n async handoff(): Promise<void> {\n const id = this.snapshot.thread?.conversation?.id;\n if (!id) return;\n try {\n const res = await this.request<ConversationMessagesResponse>(\"POST\", `/conversations/${encodeURIComponent(id)}/handoff`, { body: {}, conversationId: id });\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 } });\n res.messages.forEach((m) => this.addMessage(m));\n } catch (err) {\n this.setThread({ error: \"Couldn't reach the team. Try again.\" });\n this.deps.onError(err);\n }\n }\n\n async rate(rating: number): Promise<void> {\n const c = this.snapshot.thread?.conversation;\n if (!c) return;\n this.setThread({ conversation: { ...c, rating } });\n try {\n await this.request(\"POST\", `/conversations/${encodeURIComponent(c.id)}/rating`, { body: { rating }, conversationId: c.id });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n startGuide(key: string): void {\n this.close();\n this.deps.onStartGuide(key);\n }\n\n // -------------------------------------------------------------------------- help\n\n async loadArticles(): Promise<void> {\n try {\n this.set({ articles: await this.request<SdkArticlesResponse>(\"GET\", \"/articles\") });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n async openArticle(id: string): Promise<void> {\n const from = this.snapshot.view.kind === \"article\" ? this.snapshot.view.from : this.snapshot.view;\n this.stopThreadPolling();\n this.set({ open: true, view: { kind: \"article\", articleId: id, from }, article: null });\n try {\n const locale = this.deps.locale?.();\n const res = await this.request<{ article: ResourceCenterArticle }>(\"GET\", `/articles/${encodeURIComponent(id)}`, locale ? { params: { locale } } : {});\n this.set({ article: res.article });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n async search(q: string): Promise<ResourceCenterArticle[]> {\n try {\n return (await this.request<{ articles: ResourceCenterArticle[] }>(\"GET\", \"/resource-center/search\", { params: { q } })).articles;\n } catch {\n return [];\n }\n }\n\n // -------------------------------------------------------------------------- polling\n\n /** Called with app foreground/background changes; polling only runs in the foreground. */\n setForeground(active: boolean): void {\n this.foreground = active;\n if (!active) {\n this.stopThreadPolling();\n return;\n }\n void this.refreshConversations();\n if (this.snapshot.open && this.snapshot.view.kind === \"thread\") this.scheduleThreadPoll();\n }\n\n private startBackgroundPolling(): void {\n this.backgroundTimer = setInterval(() => {\n if (this.foreground && !(this.snapshot.open && this.snapshot.view.kind === \"thread\")) void this.refreshConversations();\n }, this.poll.background);\n }\n\n private scheduleThreadPoll(): void {\n this.stopThreadPolling();\n if (this.destroyed || !this.foreground) return;\n this.threadTimer = setTimeout(() => void this.pollThread(), this.poll.thread);\n }\n\n private stopThreadPolling(): void {\n if (this.threadTimer) clearTimeout(this.threadTimer);\n this.threadTimer = null;\n }\n\n private async pollThread(): Promise<void> {\n const t = this.snapshot.thread;\n const id = t?.conversation?.id;\n if (!t || !id || !this.snapshot.open || t.sending) return this.scheduleThreadPoll();\n const since = t.messages[t.messages.length - 1]?.createdAt;\n try {\n const res = await this.request<ConversationMessagesResponse>(\"GET\", `/conversations/${encodeURIComponent(id)}/messages`, { params: { since }, conversationId: id });\n if (this.snapshot.thread?.conversation?.id !== id) return;\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 } });\n res.messages.forEach((m) => this.addMessage(m));\n } catch (err) {\n this.deps.onError(err);\n }\n this.scheduleThreadPoll();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.stopThreadPolling();\n if (this.backgroundTimer) clearInterval(this.backgroundTimer);\n this.listeners.clear();\n }\n}\n","import { randomId } from \"@guidelytech/shared/runtime\";\nimport { backoffMs, type ServerHealth } from \"@guidelytech/sdk-core/headless\";\nimport type { Rect } from \"./targets\";\n\n// Session replay (mobile/SPEC.md \"Session replay\"): rrweb events built from masked screenshots and\n// touches, buffered and uploaded like the web ReplayController. A port of the Android SDK's\n// `core/Replay.kt`; the screenshots come from the native `@guidelytech/react-native-replay` module.\n\n/** One captured screen: a masked JPEG (base64) at 1 px per point, and the viewport in points. */\nexport interface ReplayFrame {\n base64: string;\n width: number;\n height: number;\n /** Window position (points) of the React root view that touch coordinates are relative to. */\n originX?: number;\n originY?: number;\n}\n\n/** What the capturer must paint over in the next frame. */\nexport interface ReplayCaptureOptions {\n maskAllText: boolean;\n maskAllImages: boolean;\n /** Window rects (points) of targets whose Guidely id is in `settings.replay.blockSelectors`. */\n blockRects: Rect[];\n}\n\n/** Captures the app's visible windows; resolves null when there is nothing to capture. */\nexport type ScreenCapturer = (options: ReplayCaptureOptions) => Promise<ReplayFrame | null>;\n\nexport type TouchPhase = \"down\" | \"move\" | \"up\" | \"cancel\";\n\n/** Fixed rrweb document (ids 1–8, see the SPEC) whose single `img` (id 8) shows the current screenshot. */\nexport const RrwebEvents = {\n IMG_ID: 8,\n TOUCH_START: 7,\n TOUCH_END: 9,\n CLICK: 2,\n CSS: \"html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden;background:#000}img{display:block;width:100%;height:100%;object-fit:contain}\",\n\n dataUrl(base64: string): string {\n return `data:image/jpeg;base64,${base64}`;\n },\n\n meta(timestamp: number, href: string, width: number, height: number): string {\n return JSON.stringify({ type: 4, data: { href, width, height }, timestamp });\n },\n\n fullSnapshot(timestamp: number, dataUrl: string, width: number, height: number): string {\n const style = { type: 2, id: 5, tagName: \"style\", attributes: {}, childNodes: [{ type: 3, id: 6, textContent: RrwebEvents.CSS, isStyle: true }] };\n const img = { type: 2, id: 8, tagName: \"img\", attributes: { src: dataUrl, width, height, alt: \"\" }, childNodes: [] };\n const html = { type: 2, id: 3, tagName: \"html\", attributes: {}, childNodes: [{ type: 2, id: 4, tagName: \"head\", attributes: {}, childNodes: [style] }, { type: 2, id: 7, tagName: \"body\", attributes: {}, childNodes: [img] }] };\n const node = { type: 0, id: 1, childNodes: [{ type: 1, id: 2, name: \"html\", publicId: \"\", systemId: \"\" }, html] };\n return JSON.stringify({ type: 2, data: { node, initialOffset: { left: 0, top: 0 } }, timestamp });\n },\n\n frame(timestamp: number, dataUrl: string): string {\n return JSON.stringify({ type: 3, data: { source: 0, texts: [], attributes: [{ id: 8, attributes: { src: dataUrl } }], removes: [], adds: [] }, timestamp });\n },\n\n /** MouseInteraction (source 2): 7 TouchStart, 9 TouchEnd, 2 Click. */\n interaction(timestamp: number, type: number, x: number, y: number): string {\n return JSON.stringify({ type: 3, data: { source: 2, type, id: 8, x: round1(x), y: round1(y) }, timestamp });\n },\n\n touchMove(timestamp: number, x: number, y: number): string {\n return JSON.stringify({ type: 3, data: { source: 6, positions: [{ x: round1(x), y: round1(y), id: 8, timeOffset: 0 }] }, timestamp });\n },\n\n custom(timestamp: number, tag: string, payload: Record<string, unknown>): string {\n return JSON.stringify({ type: 5, data: { tag, payload }, timestamp });\n },\n};\n\nconst round1 = (v: number) => Math.round(v * 10) / 10;\n\n/** Per-upload metadata (`ReplayChunk` minus `sessionId` / `windowId` / `seq` / `events`). */\nexport interface ReplayChunkMeta {\n anonymousId: string;\n userId: string | null;\n url?: string;\n device: { type: string; os: string };\n viewport?: { width: number; height: number };\n sdk: { name: string; version: string };\n}\n\ninterface Chunk {\n sessionId: string;\n meta: ReplayChunkMeta;\n events: string[];\n bytes: number;\n seq?: number;\n}\n\ntype UploadResult = \"ok\" | \"drop\" | \"retry\" | \"disabled\";\n\nexport interface ReplayUploaderOptions {\n /** `POST /replay` URL. */\n url: () => string;\n fetch: () => typeof fetch | null;\n meta: () => ReplayChunkMeta;\n onDisabled: (sessionId: string) => void;\n health?: ServerHealth;\n log?: (message: string) => void;\n flushIntervalMs?: number;\n maxBufferBytes?: number;\n maxQueuedBytes?: number;\n maxAttempts?: number;\n slowRetryMs?: number;\n}\n\n/** Uploads still running after this long are aborted and retried. */\nconst UPLOAD_TIMEOUT_MS = 30_000;\n\n/**\n * Buffers rrweb events (JSON strings) and uploads them with `POST /replay`. The buffer is sealed every\n * 10 s, above ~1 MB, on {@link flush} (stop, background) and when the session changes. Chunks go out\n * one at a time as plain JSON (Hermes has no gzip, and base64 JPEGs barely compress); `seq` is\n * assigned per session on a chunk's first attempt and kept for its retries. 2xx removes the chunk\n * (`{disabled:true}` drops that session's chunks), 4xx other than 429 drops it, anything else retries\n * with backoff, then about once a minute. The backlog is capped at ~5 MB (oldest first, never the\n * chunk in flight).\n */\nexport class ReplayUploader {\n readonly windowId = randomId(16);\n private buffer: Chunk | null = null;\n private queue: Chunk[] = [];\n private queuedBytes = 0;\n private seqs = new Map<string, number>();\n private inflight: Chunk | null = null;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private destroyed = false;\n private readonly offRecover: (() => void) | null;\n\n constructor(private readonly opts: ReplayUploaderOptions) {\n this.offRecover =\n opts.health?.onRecover?.(() => {\n this.clearRetry();\n this.attempt = 0;\n this.flush();\n }) ?? null;\n }\n\n get pendingChunks(): number {\n return this.queue.length;\n }\n\n get bufferedEvents(): number {\n return this.buffer?.events.length ?? 0;\n }\n\n push(sessionId: string, json: string): void {\n if (this.destroyed) return;\n if (this.buffer && this.buffer.sessionId !== sessionId) this.seal();\n const chunk = this.buffer ?? (this.buffer = { sessionId, meta: this.opts.meta(), events: [], bytes: 0 });\n chunk.events.push(json);\n chunk.bytes += json.length;\n if (chunk.bytes > (this.opts.maxBufferBytes ?? 1_000_000)) this.flush();\n else if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n this.flush();\n }, this.opts.flushIntervalMs ?? 10_000);\n }\n }\n\n /** Seals the buffer and uploads the backlog (one chunk at a time). */\n flush(): void {\n if (this.destroyed) return;\n this.seal();\n if (this.retryTimer || this.inflight || !this.queue.length) return;\n void this.sendNext();\n }\n\n /** Drops everything buffered or queued (consent withdrawn, server disabled replay). */\n discard(): void {\n this.buffer = null;\n this.queue = [];\n this.queuedBytes = 0;\n this.clearFlushTimer();\n this.clearRetry();\n this.attempt = 0;\n }\n\n /** Uploads what is left once; no retries afterwards. */\n destroy(): void {\n this.flush();\n this.destroyed = true;\n this.offRecover?.();\n this.clearFlushTimer();\n this.clearRetry();\n }\n\n private clearFlushTimer(): void {\n if (this.flushTimer) clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n private clearRetry(): void {\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n private scheduleRetry(ms: number): void {\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n this.flush();\n }, ms);\n }\n\n private seal(): void {\n this.clearFlushTimer();\n const chunk = this.buffer;\n this.buffer = null;\n if (!chunk || !chunk.events.length) return;\n this.queue.push(chunk);\n this.queuedBytes += chunk.bytes;\n const max = this.opts.maxQueuedBytes ?? 5_000_000;\n while (this.queuedBytes > max && this.queue.length > 1) {\n const i = this.inflight && this.queue[0] === this.inflight ? 1 : 0;\n const [dropped] = this.queue.splice(i, 1);\n if (!dropped) break;\n this.queuedBytes -= dropped.bytes;\n this.opts.log?.(`replay backlog full: dropped a chunk of ${dropped.events.length} events`);\n }\n }\n\n private nextSeq(chunk: Chunk): number {\n if (chunk.seq === undefined) {\n const seq = this.seqs.get(chunk.sessionId) ?? 0;\n this.seqs.set(chunk.sessionId, seq + 1);\n chunk.seq = seq;\n }\n return chunk.seq;\n }\n\n body(chunk: Chunk): string {\n const head = JSON.stringify({ sessionId: chunk.sessionId, windowId: this.windowId, seq: this.nextSeq(chunk), ...chunk.meta });\n return `${head.slice(0, -1)},\"events\":[${chunk.events.join(\",\")}]}`;\n }\n\n private async sendNext(): Promise<void> {\n const chunk = this.queue[0];\n if (!chunk) return;\n // The API is down: wait for its circuit instead of uploading into the void.\n const wait = this.destroyed ? 0 : (this.opts.health?.waitMs() ?? 0);\n if (wait > 0) return this.scheduleRetry(wait);\n this.inflight = chunk;\n const result = await this.upload(this.body(chunk));\n this.onResult(chunk, result);\n }\n\n private async upload(json: string): Promise<UploadResult> {\n const f = this.opts.fetch();\n if (!f) return \"drop\";\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ac ? setTimeout(() => ac.abort(), UPLOAD_TIMEOUT_MS) : null;\n try {\n let res: Response;\n try {\n res = await f(this.opts.url(), { method: \"POST\", body: json, headers: { \"Content-Type\": \"application/json\" }, signal: ac?.signal });\n } catch {\n this.opts.health?.failure();\n return \"retry\";\n }\n if (res.status === 429 || res.status >= 500) this.opts.health?.failure();\n else this.opts.health?.success();\n if (res.ok) {\n const data = (await res.json().catch(() => null)) as { disabled?: boolean } | null;\n return data?.disabled ? \"disabled\" : \"ok\";\n }\n return res.status >= 400 && res.status < 500 && res.status !== 429 ? \"drop\" : \"retry\";\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n private onResult(chunk: Chunk, result: UploadResult): void {\n if (this.inflight === chunk) this.inflight = null;\n if (result === \"retry\" && this.queue.includes(chunk)) {\n if (!this.destroyed) {\n // Quick retries first, then about once a minute (or as long as the circuit says).\n const max = this.opts.maxAttempts ?? 5;\n this.attempt = Math.min(this.attempt + 1, max);\n const delay = this.attempt >= max ? (this.opts.slowRetryMs ?? 60_000) : backoffMs(this.attempt - 1, 1000, 8000);\n return this.scheduleRetry(Math.max(delay, this.opts.health?.waitMs() ?? 0));\n }\n this.opts.log?.(\"replay upload failed after the recorder stopped; dropping the chunk\");\n }\n this.attempt = 0;\n this.remove(chunk);\n if (result === \"disabled\") {\n for (const c of this.queue.slice()) if (c.sessionId === chunk.sessionId) this.remove(c);\n if (this.buffer?.sessionId === chunk.sessionId) this.buffer = null;\n this.opts.onDisabled(chunk.sessionId);\n }\n // Keeps draining after destroy() so the last chunks still go out (without retries).\n if (this.queue.length && !this.retryTimer && !this.inflight) void this.sendNext();\n }\n\n private remove(chunk: Chunk): void {\n const i = this.queue.indexOf(chunk);\n if (i >= 0) {\n this.queue.splice(i, 1);\n this.queuedBytes -= chunk.bytes;\n }\n }\n}\n\nexport interface SessionRecorderOptions {\n capturer: ScreenCapturer;\n uploader: ReplayUploader;\n /** Time between screenshots (minimum 500 ms). */\n intervalMs: number;\n captureOptions: () => Promise<ReplayCaptureOptions> | ReplayCaptureOptions;\n href: () => string;\n now?: () => number;\n onError?: (err: unknown) => void;\n}\n\n/** Delay of the capture after a touch ends. */\nexport const TOUCH_SETTLE_MS = 200;\n/** Unchanged captures before the interval stretches. */\nexport const IDLE_FRAMES = 3;\n/** Longest stretched interval. */\nexport const MAX_IDLE_INTERVAL_MS = 5000;\n\n/**\n * Records one session at a time: a frame every interval while in the foreground, skipping frames\n * identical to the previous one; keyframes (Meta + FullSnapshot) for the first frame, a viewport\n * change, the first frame after the foreground returns and after `screen()`, mutations otherwise,\n * plus touches and Guidely markers. No capture while a finger is down; one {@link TOUCH_SETTLE_MS}\n * after every touch ends; after {@link IDLE_FRAMES} unchanged captures the interval stretches to\n * `min(4 × interval, 5 s)` until a changed frame, touch, `screen()` or Guidely event.\n */\nexport class SessionRecorder {\n private readonly intervalMs: number;\n private readonly now: () => number;\n private sid: string | null = null;\n private foreground = true;\n private generation = 0;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private timerDue = 0;\n private capturing = false;\n private needKeyframe = true;\n private hasKeyframe = false;\n private lastFrame: string | null = null;\n private unchanged = 0;\n private captureSoon = false;\n private pendingCustom: Array<[number, Record<string, unknown>]> = [];\n private touchDown = false;\n private downX = 0;\n private downY = 0;\n private downAt = 0;\n private maxDistance = 0;\n private lastMoveAt = 0;\n private originX = 0;\n private originY = 0;\n /** Viewport of the last frame (points), for chunk metadata. */\n viewportWidth = 0;\n viewportHeight = 0;\n\n constructor(private readonly opts: SessionRecorderOptions) {\n this.intervalMs = Math.max(500, opts.intervalMs);\n this.now = opts.now ?? Date.now;\n }\n\n get sessionId(): string | null {\n return this.sid;\n }\n\n get isRecording(): boolean {\n return this.sid !== null;\n }\n\n get currentIntervalMs(): number {\n return this.unchanged >= IDLE_FRAMES ? Math.max(this.intervalMs, Math.min(4 * this.intervalMs, MAX_IDLE_INTERVAL_MS)) : this.intervalMs;\n }\n\n /** Starts (or keeps) recording `sessionId`; another session stops the current one first (uploading it). */\n start(sessionId: string): void {\n if (this.sid === sessionId) return;\n if (this.sid !== null) this.stop(false);\n this.sid = sessionId;\n this.generation++;\n this.needKeyframe = true;\n this.hasKeyframe = false;\n this.lastFrame = null;\n this.unchanged = 0;\n this.captureSoon = false;\n this.pendingCustom = [];\n this.touchDown = false;\n if (this.foreground) this.schedule(0);\n }\n\n /** Stops recording; buffered events are uploaded unless `discard`. */\n stop(discard: boolean): void {\n if (this.sid === null) return;\n this.sid = null;\n this.generation++;\n this.clearTimer();\n this.capturing = false;\n this.pendingCustom = [];\n this.touchDown = false;\n if (discard) this.opts.uploader.discard();\n else this.opts.uploader.flush();\n }\n\n /** App backgrounded: no captures; uploads what is buffered. */\n pause(): void {\n this.foreground = false;\n this.clearTimer();\n this.generation++;\n this.capturing = false;\n this.touchDown = false;\n this.opts.uploader.flush();\n }\n\n /** App foregrounded: resume with a keyframe. */\n resume(): void {\n if (this.foreground) return;\n this.foreground = true;\n this.needKeyframe = true;\n this.unchanged = 0;\n if (this.sid !== null) this.schedule(0);\n }\n\n /** A new screen: the next frame is a keyframe with the new href. */\n onScreen(): void {\n if (this.sid === null) return;\n this.needKeyframe = true;\n this.activity();\n }\n\n private activity(): void {\n const wasIdle = this.unchanged >= IDLE_FRAMES;\n this.unchanged = 0;\n if (wasIdle && this.sid !== null && this.foreground && !this.capturing && !this.touchDown) this.schedule(this.intervalMs, true);\n }\n\n /** Adds the `guidely` marker for an analytics event. */\n addGuidelyEvent(name: string, customName?: string, guideId?: string): void {\n const id = this.sid;\n if (id === null) return;\n const payload: Record<string, unknown> = { name };\n if (customName) payload.customName = customName;\n if (guideId) payload.guideId = guideId;\n this.activity();\n const now = this.now();\n // Until the first keyframe the player has nothing to attach events to: hold them briefly.\n if (!this.hasKeyframe) {\n if (this.pendingCustom.length < 50) this.pendingCustom.push([now, payload]);\n return;\n }\n this.opts.uploader.push(id, RrwebEvents.custom(now, \"guidely\", payload));\n }\n\n /** A primary-pointer touch at (x, y) points from the React root view. */\n touch(phase: TouchPhase, rootX: number, rootY: number): void {\n const id = this.sid;\n if (id === null || !this.foreground) return;\n const x = rootX + this.originX;\n const y = rootY + this.originY;\n const now = this.now();\n const emit = this.hasKeyframe;\n const push = (json: string) => emit && this.opts.uploader.push(id, json);\n switch (phase) {\n case \"down\":\n this.touchDown = true;\n this.unchanged = 0;\n this.downX = x;\n this.downY = y;\n this.downAt = now;\n this.maxDistance = 0;\n this.lastMoveAt = now;\n push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_START, x, y));\n return;\n case \"move\":\n if (!this.touchDown) return;\n this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));\n if (now - this.lastMoveAt < 50) return;\n this.lastMoveAt = now;\n push(RrwebEvents.touchMove(now, x, y));\n return;\n default:\n if (!this.touchDown) return;\n this.touchDown = false;\n this.unchanged = 0;\n this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));\n push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_END, x, y));\n if (phase === \"up\" && this.maxDistance <= 10 && now - this.downAt < 1000) push(RrwebEvents.interaction(now, RrwebEvents.CLICK, x, y));\n // Show the result of the touch soon.\n if (this.capturing) this.captureSoon = true;\n else this.schedule(TOUCH_SETTLE_MS, true);\n }\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n\n /** Schedules the next capture `delay` ms from now, or keeps an earlier one when `ifSooner`. */\n private schedule(delay: number, ifSooner = false): void {\n const due = this.now() + delay;\n if (ifSooner && this.timer && this.timerDue <= due) return;\n this.clearTimer();\n this.timerDue = due;\n const gen = this.generation;\n this.timer = setTimeout(() => {\n this.timer = null;\n if (gen === this.generation) void this.tick();\n }, delay);\n }\n\n private async tick(): Promise<void> {\n if (this.sid === null || !this.foreground || this.capturing) return;\n if (this.touchDown) {\n // A capture would compete with the app's drag / scroll; touch end schedules one.\n this.schedule(this.intervalMs);\n return;\n }\n this.capturing = true;\n this.captureSoon = false;\n const gen = this.generation;\n let frame: ReplayFrame | null = null;\n try {\n frame = await this.opts.capturer(await this.opts.captureOptions());\n } catch (err) {\n this.opts.onError?.(err);\n }\n if (gen !== this.generation) return;\n this.capturing = false;\n // Stamped on delivery so events stay in timestamp order within a chunk.\n if (frame) this.onFrame(frame, this.now());\n if (this.sid !== null && this.foreground) this.schedule(this.captureSoon ? TOUCH_SETTLE_MS : this.currentIntervalMs);\n }\n\n private onFrame(frame: ReplayFrame, at: number): void {\n const id = this.sid;\n if (id === null || !(frame.width > 0) || !(frame.height > 0) || !frame.base64) return;\n const sizeChanged = frame.width !== this.viewportWidth || frame.height !== this.viewportHeight;\n const keyframe = this.needKeyframe || !this.hasKeyframe || sizeChanged;\n if (!keyframe && this.lastFrame === frame.base64) {\n this.unchanged++;\n return;\n }\n this.unchanged = 0;\n this.lastFrame = frame.base64;\n this.originX = frame.originX ?? 0;\n this.originY = frame.originY ?? 0;\n this.viewportWidth = frame.width;\n this.viewportHeight = frame.height;\n const url = RrwebEvents.dataUrl(frame.base64);\n const up = this.opts.uploader;\n if (!keyframe) return up.push(id, RrwebEvents.frame(at, url));\n this.needKeyframe = false;\n up.push(id, RrwebEvents.meta(at, this.opts.href(), frame.width, frame.height));\n up.push(id, RrwebEvents.fullSnapshot(at, url, frame.width, frame.height));\n if (!this.hasKeyframe) {\n this.hasKeyframe = true;\n for (const [ts, payload] of this.pendingCustom) up.push(id, RrwebEvents.custom(Math.max(ts, at), \"guidely\", payload));\n this.pendingCustom = [];\n }\n }\n}\n","import type { KeyValueStore } from \"@guidelytech/sdk-core/headless\";\nimport type { GuidelyStorage } from \"./types\";\n\n/**\n * Synchronous key/value view over asynchronous storage (AsyncStorage). Keys are loaded once with\n * {@link hydrate}; reads come from memory and writes go to memory immediately and to storage in the\n * background, so the engine can keep the web SDK's synchronous storage model. Never throws.\n */\nexport class PersistentStore implements KeyValueStore {\n private readonly cache = new Map<string, string>();\n private chain: Promise<unknown> = Promise.resolve();\n\n constructor(\n private readonly backing: GuidelyStorage | null,\n private readonly onError: (err: unknown) => void = () => {},\n ) {}\n\n async hydrate(keys: string[]): Promise<void> {\n if (!this.backing) return;\n await Promise.all(\n keys.map(async (k) => {\n try {\n const v = await this.backing!.getItem(k);\n if (v != null && !this.cache.has(k)) this.cache.set(k, v);\n } catch (err) {\n this.onError(err);\n }\n }),\n );\n }\n\n get(key: string): string | null {\n return this.cache.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n if (this.cache.get(key) === value) return;\n this.cache.set(key, value);\n this.write(() => this.backing?.setItem(key, value));\n }\n\n remove(key: string): void {\n if (!this.cache.has(key)) return;\n this.cache.delete(key);\n this.write(() => this.backing?.removeItem(key));\n }\n\n /** Resolves once every pending write has reached the backing storage. */\n flush(): Promise<void> {\n return this.chain.then(() => undefined);\n }\n\n private write(op: () => Promise<void> | void | undefined): void {\n if (!this.backing) return;\n // Serialised so a later write of the same key can never land before an earlier one.\n this.chain = this.chain.then(async () => {\n try {\n await op();\n } catch (err) {\n this.onError(err);\n }\n });\n }\n}\n","/**\n * Host app and OS versions, read from native modules the app already links (never imported, so none\n * of them is a dependency): `@guidelytech/react-native-replay`, `expo-application`, then\n * `react-native-device-info`. React Native itself has no API for the app's own version.\n */\n\nexport interface AppVersionInfo {\n /** `CFBundleShortVersionString` / `versionName`. */\n appVersion?: string;\n /** `CFBundleVersion` / `versionCode`. */\n appBuild?: string;\n}\n\n/** Where the lookups read from; the provider passes React Native's objects, tests pass fakes. */\nexport interface NativeSources {\n platform: { OS: string; Version?: string | number; constants?: Record<string, unknown> };\n nativeModules: Record<string, unknown>;\n /** `globalThis.expo.modules` in Expo SDK 50+ apps. */\n expoModules?: Record<string, unknown>;\n}\n\ntype Module = Record<string, unknown> & { getConstants?: () => Record<string, unknown> };\n\nfunction text(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n if (typeof value !== \"string\") return undefined;\n const v = value.trim();\n return v ? v.slice(0, 64) : undefined;\n}\n\n/**\n * Reads one constant: from `getConstants()` (TurboModules, new architecture), else the module's own\n * property (old architecture, Expo modules). Properties are read by name because JSI host objects\n * do not enumerate them.\n */\nfunction constant(mod: unknown, key: string): unknown {\n if (!mod || (typeof mod !== \"object\" && typeof mod !== \"function\")) return undefined;\n const m = mod as Module;\n try {\n const fromGetter = typeof m.getConstants === \"function\" ? m.getConstants()?.[key] : undefined;\n return fromGetter ?? m[key];\n } catch {\n // A module that throws here is treated as absent.\n return undefined;\n }\n}\n\nfunction read(mod: unknown, versionKey: string, buildKey: string): AppVersionInfo | null {\n const appVersion = text(constant(mod, versionKey));\n if (!appVersion) return null;\n const appBuild = text(constant(mod, buildKey));\n return { appVersion, ...(appBuild ? { appBuild } : {}) };\n}\n\n/** True inside Expo Go, where `expo-application` reports Expo Go's own version rather than the app's. */\nfunction inExpoGo(src: NativeSources): boolean {\n const c = src.expoModules?.ExponentConstants ?? src.nativeModules.ExponentConstants;\n return constant(c, \"executionEnvironment\") === \"storeClient\" || constant(c, \"appOwnership\") === \"expo\";\n}\n\n/** The host app's version and build, or `{}` when no linked module knows them. */\nexport function detectAppVersion(src: NativeSources): AppVersionInfo {\n try {\n const expo = inExpoGo(src) ? null : (src.expoModules?.ExpoApplication ?? src.nativeModules.ExpoApplication);\n return (\n read(src.nativeModules.GuidelyReplay, \"appVersion\", \"appBuild\") ??\n read(expo, \"nativeApplicationVersion\", \"nativeBuildVersion\") ??\n read(src.nativeModules.RNDeviceInfo, \"appVersion\", \"buildNumber\") ??\n {}\n );\n } catch {\n return {};\n }\n}\n\n/** The OS version: `18.1` on iOS, `14` on Android (falling back to the API level). */\nexport function detectOsVersion(src: NativeSources): string | undefined {\n try {\n const c = src.platform.constants ?? {};\n if (src.platform.OS === \"android\") return text(c.Release) ?? text(src.platform.Version);\n return text(c.osVersion) ?? text(src.platform.Version);\n } catch {\n return undefined;\n }\n}\n","import { useMemo, useRef, type ReactNode } from \"react\";\nimport { View, type GestureResponderEvent, type ViewProps } from \"react-native\";\nimport { TapTracker } from \"../core/autocapture\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { TouchPhase } from \"../core/replay\";\nimport { resolveTapTarget, type ResolveOptions } from \"../core/viewTree\";\nimport { GuidelyOverlay } from \"./Overlay\";\n\nexport interface GuidelyMaskProps extends ViewProps {\n children?: ReactNode;\n}\n\n/** `nativeID` the native replay module looks for: views carrying it are painted over in recordings. */\nexport const GUIDELY_MASK_NATIVE_ID = \"guidely-mask\";\n\n/**\n * Keeps its children out of product analytics and session replay: taps inside it (or on an element\n * that contains it) are captured without `text`, and recordings paint over it. Renders a plain `View`\n * (its `nativeID` is how the native recorder finds it).\n */\nexport function GuidelyMask({ children, ...rest }: GuidelyMaskProps) {\n return (\n <View collapsable={false} {...rest} nativeID={GUIDELY_MASK_NATIVE_ID}>\n {children}\n </View>\n );\n}\n\nconst RESOLVE: ResolveOptions = {\n isIgnored: (type) => type === GuidelyOverlay,\n isMask: (type) => type === GuidelyMask,\n};\n\ntype TouchHandler = (e: GestureResponderEvent) => void;\n\n/**\n * Capture-phase touch handlers for the provider's root view. They only observe: they never claim\n * the responder, stop propagation or delay anything, so the app's own touch handling is unchanged.\n */\nexport function useTapObserver(client: GuidelyClient | null): Partial<Record<\"onTouchStartCapture\" | \"onTouchMoveCapture\" | \"onTouchEndCapture\" | \"onTouchCancelCapture\", TouchHandler>> {\n const clientRef = useRef(client);\n clientRef.current = client;\n return useMemo(() => {\n const tracker = new TapTracker();\n /** Identifier of the finger a recording follows (the first one down). */\n let replayPointer: number | string | null = null;\n const replay = (phase: TouchPhase, e: GestureResponderEvent) => {\n const c = clientRef.current;\n const n = e.nativeEvent;\n if (!c?.isRecordingTouches()) return void (replayPointer = null);\n if (phase === \"down\") {\n if (replayPointer !== null) return;\n replayPointer = n.identifier;\n } else if (n.identifier !== replayPointer) return;\n if (phase === \"up\" || phase === \"cancel\") replayPointer = null;\n c.recordTouch(phase, n.pageX, n.pageY);\n };\n const guard = (fn: TouchHandler): TouchHandler => (e) => {\n try {\n fn(e);\n } catch {\n tracker.cancel(); // never throw into the app's touch handling\n }\n };\n return {\n onTouchStartCapture: guard((e) => {\n replay(\"down\", e);\n const n = e.nativeEvent;\n if (!clientRef.current?.isTapCaptureOn()) return tracker.cancel();\n tracker.begin(n.pageX, n.pageY, Date.now(), Array.isArray(n.touches) ? n.touches.length : 1, n.identifier);\n }),\n onTouchMoveCapture: guard((e) => {\n replay(\"move\", e);\n tracker.move(e.nativeEvent.pageX, e.nativeEvent.pageY, e.nativeEvent.identifier);\n }),\n onTouchEndCapture: guard((e) => {\n replay(\"up\", e);\n const n = e.nativeEvent;\n const tap = tracker.end(n.pageX, n.pageY, Date.now(), n.identifier);\n const c = clientRef.current;\n if (!tap || !c) return;\n // Resolved now: the event's target is released after dispatch and the view may unmount.\n const r = resolveTapTarget(e, RESOLVE);\n if (!r.ignored) c.recordTap({ x: tap.x, y: tap.y, t: Date.now(), element: r.element, hit: r.hit });\n }),\n onTouchCancelCapture: guard((e) => {\n replay(\"cancel\", e);\n tracker.cancel();\n }),\n };\n }, []);\n}\n","/**\n * Best-effort identification of the view a tap landed on, from React's component tree.\n *\n * React Native has no public \"which component is under this point\" API, so the touch observer\n * reads the event's target fiber (`event._targetInst`, or the host instance's internal handle) and\n * walks it. Everything here is defensive: React internals can change between versions, and any\n * surprise yields \"unknown\" instead of an exception.\n */\nimport { attrSelector, cleanText, type TapElement } from \"./autocapture\";\nimport type { Rect } from \"./targets\";\n\n/** The fields of a React fiber this module reads. */\nexport interface FiberLike {\n tag?: number;\n type?: unknown;\n memoizedProps?: any;\n return?: FiberLike | null;\n child?: FiberLike | null;\n sibling?: FiberLike | null;\n stateNode?: any;\n}\n\nexport interface ResolveOptions {\n /** Guidely's own UI (overlay): taps inside it are never captured. */\n isIgnored?: (type: unknown) => boolean;\n /** `<GuidelyMask>`: text inside (or around) it is never captured. */\n isMask?: (type: unknown) => boolean;\n}\n\nexport interface ResolvedTap {\n /** The tap landed in Guidely's own UI. */\n ignored: boolean;\n /** Innermost interactive element (touchable / `Pressable` / `onPress` / `accessibilityRole=\"button\"`…). */\n element: TapElement | null;\n /** The view that was hit (its nearest named component), for rage taps and heatmaps. */\n hit: TapElement | null;\n}\n\nconst HOST_TEXT = 6;\nconst MAX_ANCESTORS = 500;\nconst MAX_TEXT_NODES = 300;\nconst INTERACTIVE_ROLES = new Set([\"button\", \"link\", \"tab\", \"menuitem\", \"checkbox\", \"switch\", \"radio\", \"togglebutton\", \"imagebutton\", \"option\", \"combobox\", \"adjustable\"]);\nconst TEXT_INPUT_HOST = /TextInput/i;\n/** Wrappers that say nothing about where a view is. */\nconst NOISE = /^(Anonymous|Unknown|ForwardRef|Memo|Context|Provider|Consumer|Fragment|StrictMode|Suspense|Profiler)$|Context$|Provider$|Consumer$/;\n\nconst isFiber = (v: unknown): v is FiberLike => !!v && typeof v === \"object\" && \"return\" in (v as object) && \"memoizedProps\" in (v as object);\n\n/** The tap target's fiber from a React Native touch event, or null. */\nexport function fiberFromEvent(event: unknown): FiberLike | null {\n try {\n const e = event as { _targetInst?: unknown; target?: unknown } | null;\n if (isFiber(e?._targetInst)) return e._targetInst;\n const target = e?.target as Record<string | symbol, unknown> | null | undefined;\n if (!target || typeof target !== \"object\") return null;\n for (const key of [\"__internalInstanceHandle\", \"_internalInstanceHandle\", \"_internalFiberInstanceHandleDEV\"]) if (isFiber(target[key])) return target[key] as FiberLike;\n for (const sym of Object.getOwnPropertySymbols(target)) if (sym.description === \"internalInstanceHandle\" && isFiber(target[sym])) return target[sym] as FiberLike;\n } catch {\n /* unknown renderer internals */\n }\n return null;\n}\n\n/** Component name of a fiber type (`Pressable`, `TouchableOpacity`, `Text`…); null for host components and anonymous wrappers. */\nexport function componentName(type: unknown, depth = 0): string | null {\n if (!type || depth > 3) return null;\n if (typeof type === \"function\") {\n const f = type as { displayName?: unknown; name?: unknown };\n const n = typeof f.displayName === \"string\" && f.displayName ? f.displayName : typeof f.name === \"string\" ? f.name : \"\";\n return n || null;\n }\n if (typeof type === \"object\") {\n const o = type as { displayName?: unknown; render?: unknown; type?: unknown };\n if (typeof o.displayName === \"string\" && o.displayName) return o.displayName;\n return componentName(o.render, depth + 1) ?? componentName(o.type, depth + 1);\n }\n return null;\n}\n\nconst isHost = (f: FiberLike) => typeof f.type === \"string\";\nconst isTextInput = (f: FiberLike) => (typeof f.type === \"string\" ? TEXT_INPUT_HOST.test(f.type) : componentName(f.type) === \"TextInput\");\n\nfunction isInteractive(props: any): \"press\" | \"role\" | null {\n if (!props || typeof props !== \"object\") return null;\n if (typeof props.onPress === \"function\" || typeof props.onLongPress === \"function\") return \"press\";\n const role = props.accessibilityRole ?? props.role;\n return typeof role === \"string\" && INTERACTIVE_ROLES.has(role) ? \"role\" : null;\n}\n\n/** First host-component fiber at or below `f` along first children. */\nfunction firstHost(f: FiberLike): FiberLike | null {\n let cur: FiberLike | null | undefined = f;\n for (let i = 0; cur && i < 30; i++, cur = cur.child) if (isHost(cur)) return cur;\n return null;\n}\n\n/** `[nativeID=\"…\"]` / `[testID=\"…\"]` from the component's or its host view's props. */\nfunction idSelector(f: FiberLike): string | null {\n const host = firstHost(f);\n const sources = [f.memoizedProps, host?.memoizedProps];\n for (const key of [\"nativeID\", \"testID\"]) {\n for (const p of sources) {\n const v = p && typeof p === \"object\" ? p[key] : undefined;\n if (typeof v === \"string\" && v) return attrSelector(key, v);\n }\n }\n return null;\n}\n\n/** Short component path, at most 4 named levels, innermost last, `Name:nth-of-type(n)` when siblings share the type. */\nexport function pathSelector(f: FiberLike): string {\n const parts: string[] = [];\n let cur: FiberLike | null | undefined = f;\n for (let i = 0; cur && parts.length < 4 && i < MAX_ANCESTORS; i++, cur = cur.return) {\n if (isHost(cur)) continue;\n const name = componentName(cur.type);\n if (!name || NOISE.test(name)) continue;\n let same = 0;\n let index = 0;\n for (let s: FiberLike | null | undefined = cur.return?.child, n = 0; s && n < 500; s = s.sibling, n++) {\n if (s.type !== cur.type) continue;\n same += 1;\n if (s === cur) index = same;\n }\n parts.unshift(same > 1 && index ? `${name}:nth-of-type(${index})` : name);\n }\n return parts.join(\" > \").slice(0, 300) || \"View\";\n}\n\n/** Visible text below `f` (raw text nodes), skipping text fields; `masked` when a mask is inside. */\nfunction subtreeText(f: FiberLike, opts: ResolveOptions): { text: string; masked: boolean } {\n const out: string[] = [];\n let visited = 0;\n let masked = false;\n const walk = (node: FiberLike | null | undefined): void => {\n for (let n = node; n && visited < MAX_TEXT_NODES && !masked; n = n.sibling) {\n visited += 1;\n if (opts.isMask?.(n.type)) {\n masked = true;\n return;\n }\n if (isTextInput(n)) continue;\n if (n.tag === HOST_TEXT && (typeof n.memoizedProps === \"string\" || typeof n.memoizedProps === \"number\")) out.push(String(n.memoizedProps));\n else walk(n.child);\n }\n };\n if (opts.isMask?.(f.type)) return { text: \"\", masked: true };\n walk(f.child);\n return { text: out.join(\" \"), masked };\n}\n\n/** Window frame of a host view (Paper instance, Fabric public instance, or the Fabric UI manager). */\nfunction measureHost(host: FiberLike): Promise<Rect | null> {\n return new Promise((resolve) => {\n let settled = false;\n const done = (r: Rect | null) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(r);\n };\n const timer = setTimeout(() => done(null), 500);\n const cb = (x: number, y: number, width: number, height: number) => done(Number.isFinite(x) && Number.isFinite(y) && width > 0 && height > 0 ? { x, y, width, height } : null);\n try {\n const sn = host.stateNode;\n const pub = sn?.canonical?.publicInstance ?? sn;\n if (pub && typeof pub.measureInWindow === \"function\") return pub.measureInWindow(cb);\n const ui = (globalThis as { nativeFabricUIManager?: { measureInWindow?: (node: unknown, callback: (x: number, y: number, width: number, height: number) => void) => void } }).nativeFabricUIManager;\n if (sn?.node && typeof ui?.measureInWindow === \"function\") return ui.measureInWindow(sn.node, cb);\n } catch {\n /* fall through */\n }\n done(null);\n });\n}\n\nfunction describe(f: FiberLike, masked: boolean, opts: ResolveOptions, withText: boolean): TapElement {\n const props = f.memoizedProps && typeof f.memoizedProps === \"object\" ? f.memoizedProps : {};\n const host = firstHost(f);\n const el: TapElement = { selector: idSelector(f) ?? pathSelector(f), tag: componentName(f.type) ?? \"View\" };\n if (withText && !masked) {\n const sub = subtreeText(f, opts);\n if (!sub.masked) {\n const hostProps = host?.memoizedProps && typeof host.memoizedProps === \"object\" ? host.memoizedProps : {};\n const label = props.accessibilityLabel ?? props[\"aria-label\"] ?? hostProps.accessibilityLabel ?? hostProps[\"aria-label\"];\n const text = cleanText(sub.text) ?? (typeof label === \"string\" ? cleanText(label) : undefined);\n if (text) el.text = text;\n }\n }\n if (host) el.measure = () => measureHost(host);\n return el;\n}\n\n/**\n * Resolves a tap from its target fiber: whether it hit Guidely's UI, the innermost interactive\n * element (a component with `onPress` / `onLongPress`; else one with an interactive\n * `accessibilityRole`) and the hit view. Taps inside a `TextInput` have no interactive element.\n */\nexport function resolveFiber(target: FiberLike | null, opts: ResolveOptions = {}): ResolvedTap {\n const none: ResolvedTap = { ignored: false, element: null, hit: null };\n if (!target) return none;\n try {\n let press: FiberLike | null = null;\n let role: FiberLike | null = null;\n let hitFiber: FiberLike | null = null;\n let stopped = false;\n // A mask anywhere on the path from the tapped view to the root hides the text.\n let masked = false;\n for (let f: FiberLike | null | undefined = target, i = 0; f && i < MAX_ANCESTORS; f = f.return, i++) {\n if (opts.isIgnored?.(f.type)) return { ignored: true, element: null, hit: null };\n if (opts.isMask?.(f.type)) masked = true;\n if (stopped) continue;\n if (isTextInput(f)) {\n stopped = true;\n continue;\n }\n if (isHost(f)) continue;\n const name = componentName(f.type);\n if (!hitFiber && name && !NOISE.test(name)) hitFiber = f;\n const kind = isInteractive(f.memoizedProps);\n if (kind === \"press\") {\n press = f;\n stopped = true;\n } else if (kind === \"role\" && !role) role = f;\n }\n const element = press ?? role;\n return {\n ignored: false,\n element: element ? describe(element, masked, opts, true) : null,\n hit: hitFiber ? describe(hitFiber, masked, opts, componentName(hitFiber.type) === \"Text\") : null,\n };\n } catch {\n return none;\n }\n}\n\n/** {@link resolveFiber} for a touch event; never throws. */\nexport function resolveTapTarget(event: unknown, opts: ResolveOptions = {}): ResolvedTap {\n return resolveFiber(fiberFromEvent(event), opts);\n}\n","import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Platform, Pressable, StatusBar, StyleSheet, Text, useColorScheme, useWindowDimensions, View } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { Insets } from \"../core/position\";\nimport { Checklist } from \"./Checklist\";\nimport { LAUNCHER_SIZE, MessengerLauncher, MessengerSheet } from \"./Messenger\";\nimport { ResourceCenter } from \"./ResourceCenter\";\nimport { StepLayer, type LayerGeometry } from \"./StepLayer\";\nimport { Survey } from \"./Survey\";\nimport { palette } from \"./theme\";\n\n/** Best-effort safe-area insets when the app does not pass real ones (e.g. from react-native-safe-area-context). */\nfunction defaultInsets(width: number, height: number): Insets {\n if (Platform.OS === \"ios\") {\n const notch = Math.max(width, height) >= 812 && !Platform.isPad;\n const landscape = width > height;\n return { top: landscape ? 0 : notch ? 50 : 20, bottom: notch ? (landscape ? 21 : 34) : 0, left: landscape && notch ? 44 : 0, right: landscape && notch ? 44 : 0 };\n }\n return { top: StatusBar.currentHeight ?? 24, bottom: 16, left: 0, right: 0 };\n}\n\nexport interface OverlayProps {\n client: GuidelyClient;\n insets?: Partial<Insets>;\n /** Distance of the checklist launcher above the bottom inset (clears tab bars). */\n launcherOffset: number;\n}\n\n/**\n * Draws everything the client wants on screen, above the app. `pointerEvents=\"box-none\"` keeps the\n * app fully interactive except where guide UI (or a modal backdrop) is shown.\n */\nexport function GuidelyOverlay({ client, insets: insetsProp, launcherOffset }: OverlayProps) {\n const ui = useSyncExternalStore(\n useCallback((cb) => client.subscribeUi(cb), [client]),\n () => client.getUiState(),\n () => client.getUiState(),\n );\n const { width, height } = useWindowDimensions();\n const scheme = useColorScheme();\n const ref = useRef<View>(null);\n const [origin, setOrigin] = useState({ x: 0, y: 0 });\n\n useEffect(() => {\n client.targets.setViewport(width, height);\n }, [client, width, height]);\n\n const measureOrigin = useCallback(() => {\n ref.current?.measureInWindow?.((x, y) => {\n if (Number.isFinite(x) && Number.isFinite(y)) setOrigin((o) => (o.x === x && o.y === y ? o : { x, y }));\n });\n }, []);\n\n const insets: Insets = { ...defaultInsets(width, height), ...insetsProp };\n const geometry: LayerGeometry = { origin, viewport: { width, height }, insets };\n const basePalette = palette(ui.theme, scheme);\n const messenger = ui.messenger ? client.getMessenger() : null;\n const showRcLauncher = !messenger && !!client.options.showResourceCenterLauncher && !!client.getResourceCenter();\n // \"What's new\" entries published since the visitor last opened the resource center.\n const unread = showRcLauncher ? client.getUnreadAnnouncements() : 0;\n const messengerLeft = messenger?.getSnapshot().config.launcher.position === \"bottom-left\";\n // The chat bubble stacks above a checklist launcher on the same side.\n const checklistOnSameSide = ui.checklists.some((c) => (c.guide.config.checklist?.position === \"bottom-left\") === messengerLeft) && client.options.showChecklistLauncher !== false;\n // Default bubble position, and the lowest a dragged bubble may rest (clears tab bars).\n const messengerBottom = insets.bottom + launcherOffset + (checklistOnSameSide ? 56 : 0);\n\n return (\n <View ref={ref} collapsable={false} pointerEvents=\"box-none\" style={StyleSheet.absoluteFill} onLayout={measureOrigin}>\n {ui.checklists.map((c) => (\n <Checklist key={c.guide.id} view={c} client={client} palette={palette(client.themeFor(c.guide), scheme)} geometry={geometry} showLauncher={client.options.showChecklistLauncher !== false} launcherBottom={launcherOffset} />\n ))}\n {showRcLauncher ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={rcLauncherLabel(client)}\n onPress={() => client.openResourceCenter()}\n style={[styles.rc, client.getResourceCenter()?.launcher.position === \"bottom-left\" ? { left: insets.left + 16 } : { right: insets.right + 16 }, { bottom: insets.bottom + launcherOffset + (ui.checklists.length ? 56 : 0), backgroundColor: basePalette.primary }]}\n >\n <Text style={[styles.rcText, { color: basePalette.onPrimary }]}>?</Text>\n {unread ? (\n <View pointerEvents=\"none\" style={[styles.rcBadge, { borderColor: basePalette.primary }]}>\n <Text style={styles.rcBadgeText}>{unread > 9 ? \"9+\" : unread}</Text>\n </View>\n ) : null}\n </Pressable>\n ) : null}\n {messenger && client.options.showMessengerLauncher !== false ? (\n <MessengerLauncher\n store={messenger}\n client={client}\n palette={basePalette}\n style={[messengerLeft ? { left: insets.left + 16 } : { right: insets.right + 16 }, { bottom: messengerBottom }]}\n frame={{ width, height, insets, size: LAUNCHER_SIZE, defaultBottom: messengerBottom }}\n defaultSide={messengerLeft ? \"left\" : \"right\"}\n />\n ) : null}\n {ui.survey ? <Survey view={ui.survey} client={client} palette={palette(client.themeFor(ui.survey.guide), scheme)} geometry={geometry} /> : null}\n {ui.steps.map((s) => (\n <StepLayer key={s.key} view={s} client={client} palette={palette(client.themeFor(s.guide), scheme, s.guide.config.appearance)} geometry={geometry} />\n ))}\n {messenger ? <MessengerSheet store={messenger} client={client} palette={basePalette} topInset={insets.top} bottomInset={insets.bottom} /> : <ResourceCenter client={client} palette={basePalette} open={ui.resourceCenterOpen} topInset={insets.top} bottomInset={insets.bottom} />}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n rc: { position: \"absolute\", width: 48, height: 48, borderRadius: 24, alignItems: \"center\", justifyContent: \"center\", elevation: 8, shadowColor: \"#000\", shadowOpacity: 0.2, shadowRadius: 10, shadowOffset: { width: 0, height: 4 } },\n rcText: { fontSize: 22, fontWeight: \"800\" },\n rcBadge: { position: \"absolute\", top: -4, right: -4, minWidth: 20, height: 20, paddingHorizontal: 5, borderRadius: 10, borderWidth: 2, backgroundColor: \"#dc2626\", alignItems: \"center\", justifyContent: \"center\" },\n rcBadgeText: { color: \"#ffffff\", fontSize: 11, fontWeight: \"800\" },\n});\n\nfunction rcLauncherLabel(client: GuidelyClient): string {\n const label = client.getResourceCenter()?.launcher.label || \"Help\";\n const unread = client.getUnreadAnnouncements();\n return unread ? `${label} (${unread} new update${unread === 1 ? \"\" : \"s\"})` : label;\n}\n","import { Pressable, ScrollView, StyleSheet, Text, View } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { ChecklistView } from \"../core/types\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { LayerGeometry } from \"./StepLayer\";\nimport type { Palette } from \"./theme\";\n\n/** Floating launcher pill + task panel for one checklist guide. */\nexport function Checklist({ view, client, palette: p, geometry, showLauncher, launcherBottom }: { view: ChecklistView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry; showLauncher: boolean; launcherBottom: number }) {\n const config = view.guide.config.checklist;\n if (!config) return null;\n const done = new Set(view.progress.completedTaskIds);\n const total = config.tasks.length;\n const completed = config.tasks.filter((t) => done.has(t.id)).length;\n const finished = !!view.progress.completedAt;\n const left = config.position === \"bottom-left\";\n const { insets, viewport } = geometry;\n const side = left ? { left: insets.left + 16 } : { right: insets.right + 16 };\n const width = Math.min(viewport.width - insets.left - insets.right - 32, 360);\n const nextOpen = config.ordered ? config.tasks.find((t) => !done.has(t.id))?.id : undefined;\n const bottom = insets.bottom + launcherBottom;\n\n return (\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n {view.open ? (\n <Surface palette={p} style={[styles.panel, side, { width, bottom: bottom + (showLauncher ? 56 : 0), maxHeight: viewport.height - insets.top - bottom - 80 }]}>\n <View accessibilityViewIsModal style={styles.panelInner}>\n <View style={styles.head}>\n <View style={styles.flex}>\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {finished ? config.completionTitle : config.launcherLabel}\n </Text>\n <Text style={[styles.sub, { color: p.muted }]}>\n {completed} of {total} complete\n </Text>\n </View>\n <CloseButton palette={p} onPress={() => client.setChecklistOpen(view.guide.id, false)} label=\"Close checklist\" />\n </View>\n <View style={[styles.bar, { backgroundColor: p.surface }]} accessibilityRole=\"progressbar\" accessibilityValue={{ min: 0, max: total, now: completed }}>\n <View style={[styles.fill, { backgroundColor: p.primary, width: `${total ? (completed / total) * 100 : 0}%` }]} />\n </View>\n {finished && config.completionBody ? <RichText html={config.completionBody} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n <ScrollView style={styles.tasks} contentContainerStyle={styles.tasksContent}>\n {config.tasks.map((task) => {\n const isDone = done.has(task.id);\n const locked = !!nextOpen && !isDone && task.id !== nextOpen;\n return (\n <Pressable\n key={task.id}\n disabled={locked}\n accessibilityRole=\"button\"\n accessibilityState={{ checked: isDone, disabled: locked }}\n accessibilityLabel={`${task.title}${isDone ? \", done\" : \"\"}`}\n onPress={() => client.checklistTaskPressed(view.guide.id, task.id)}\n style={({ pressed }) => [styles.task, { borderColor: p.border, opacity: locked ? 0.5 : pressed ? 0.7 : 1 }]}\n >\n <View style={[styles.check, isDone ? { backgroundColor: p.primary, borderColor: p.primary } : { borderColor: p.border }]}>{isDone ? <Text style={[styles.tick, { color: p.onPrimary }]}>✓</Text> : null}</View>\n <View style={styles.flex}>\n <Text style={[styles.taskTitle, { color: p.text, fontFamily: p.fontFamily }, isDone && { textDecorationLine: \"line-through\", color: p.muted }]}>\n {task.title}\n {!task.required ? <Text style={{ color: p.muted, fontWeight: \"400\" }}> (optional)</Text> : null}\n </Text>\n {task.description ? <Text style={[styles.taskDesc, { color: p.muted }]}>{task.description}</Text> : null}\n </View>\n </Pressable>\n );\n })}\n </ScrollView>\n {config.dismissible ? <GButton label={finished ? \"Close for good\" : \"Dismiss checklist\"} variant=\"ghost\" palette={p} onPress={() => client.dismissChecklist(view.guide.id)} style={styles.dismiss} /> : null}\n </View>\n </Surface>\n ) : null}\n {showLauncher ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={`${config.launcherLabel}, ${completed} of ${total} complete`}\n accessibilityState={{ expanded: view.open }}\n onPress={() => client.setChecklistOpen(view.guide.id, !view.open)}\n style={({ pressed }) => [styles.launcher, side, { bottom, backgroundColor: p.primary, opacity: pressed ? 0.85 : 1 }]}\n >\n <View style={[styles.count, { borderColor: p.onPrimary }]}>\n <Text style={[styles.countText, { color: p.onPrimary }]}>{finished ? \"✓\" : `${completed}/${total}`}</Text>\n </View>\n <Text style={[styles.launcherText, { color: p.onPrimary, fontFamily: p.fontFamily }]} numberOfLines={1}>\n {config.launcherLabel}\n </Text>\n </Pressable>\n ) : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n panel: { position: \"absolute\" },\n panelInner: { padding: 16, gap: 10, flexShrink: 1 },\n head: { flexDirection: \"row\", alignItems: \"flex-start\", gap: 8 },\n title: { fontSize: 17, fontWeight: \"700\" },\n sub: { fontSize: 13, marginTop: 2 },\n bar: { height: 6, borderRadius: 3, overflow: \"hidden\" },\n fill: { height: 6, borderRadius: 3 },\n tasks: { flexGrow: 0 },\n tasksContent: { gap: 8 },\n task: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\", borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, padding: 10 },\n check: { width: 22, height: 22, borderRadius: 11, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\", marginTop: 1 },\n tick: { fontSize: 13, fontWeight: \"800\" },\n taskTitle: { fontSize: 15, fontWeight: \"600\" },\n taskDesc: { fontSize: 13, marginTop: 2 },\n dismiss: { alignSelf: \"center\" },\n launcher: {\n position: \"absolute\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 8,\n paddingVertical: 10,\n paddingHorizontal: 14,\n borderRadius: 24,\n shadowColor: \"#000\",\n shadowOpacity: 0.22,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 4 },\n elevation: 8,\n maxWidth: 240,\n },\n count: { minWidth: 30, height: 22, borderRadius: 11, borderWidth: 1.5, alignItems: \"center\", justifyContent: \"center\", paddingHorizontal: 4 },\n countText: { fontSize: 11, fontWeight: \"700\" },\n launcherText: { fontSize: 14, fontWeight: \"700\", flexShrink: 1 },\n});\n","import type { ReactNode } from \"react\";\nimport { Pressable, StyleSheet, Text, View, type StyleProp, type ViewStyle } from \"react-native\";\nimport type { Palette } from \"./theme\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"link\";\n\nexport function GButton({ label, variant = \"primary\", onPress, palette: p, style, accessibilityHint, disabled }: { label: string; variant?: ButtonVariant; onPress: () => void; palette: Palette; style?: StyleProp<ViewStyle>; accessibilityHint?: string; disabled?: boolean }) {\n const filled = variant === \"primary\";\n const outlined = variant === \"secondary\";\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n accessibilityHint={accessibilityHint}\n accessibilityState={{ disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n hitSlop={6}\n style={({ pressed }) => [\n styles.btn,\n { borderRadius: Math.min(p.radius, 10), opacity: disabled ? 0.5 : pressed ? 0.75 : 1 },\n filled && { backgroundColor: p.primary },\n outlined && { borderWidth: 1, borderColor: p.border, backgroundColor: p.background },\n variant === \"link\" && styles.link,\n style,\n ]}\n >\n <Text style={[styles.btnText, { color: filled ? p.onPrimary : variant === \"link\" ? p.primary : variant === \"ghost\" ? p.muted : p.text, fontFamily: p.fontFamily }, variant === \"link\" && styles.underline]} numberOfLines={1}>\n {label}\n </Text>\n </Pressable>\n );\n}\n\nexport function CloseButton({ onPress, palette: p, label = \"Close\" }: { onPress: () => void; palette: Palette; label?: string }) {\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={10} style={({ pressed }) => [styles.close, { opacity: pressed ? 0.6 : 1 }]}>\n <Text style={[styles.closeText, { color: p.muted }]}>×</Text>\n </Pressable>\n );\n}\n\n/** Rounded surface with a soft shadow. */\nexport function Surface({ palette: p, children, style }: { palette: Palette; children: ReactNode; style?: StyleProp<ViewStyle> }) {\n return <View style={[styles.surface, { backgroundColor: p.background, borderRadius: p.radius, borderColor: p.border }, style]}>{children}</View>;\n}\n\nconst styles = StyleSheet.create({\n btn: { minHeight: 36, paddingHorizontal: 14, paddingVertical: 8, alignItems: \"center\", justifyContent: \"center\" },\n link: { paddingHorizontal: 4 },\n btnText: { fontSize: 14, fontWeight: \"600\" },\n underline: { textDecorationLine: \"underline\" },\n close: { width: 28, height: 28, alignItems: \"center\", justifyContent: \"center\", marginTop: -4, marginRight: -6 },\n closeText: { fontSize: 24, lineHeight: 26, fontWeight: \"400\" },\n surface: {\n borderWidth: StyleSheet.hairlineWidth,\n shadowColor: \"#000\",\n shadowOpacity: 0.18,\n shadowRadius: 18,\n shadowOffset: { width: 0, height: 8 },\n elevation: 10,\n },\n});\n","import { useEffect, useMemo, useState } from \"react\";\nimport { Image, Modal, Platform, Pressable, ScrollView, StyleSheet, Text, View, type NativeScrollEvent, type NativeSyntheticEvent, type TextStyle } from \"react-native\";\nimport { parseHtml, type PdfPage, type TextBlock, type TextRun } from \"../core/html\";\nimport type { Palette } from \"./theme\";\n\nconst MONO = Platform.select({ ios: \"Menlo\", android: \"monospace\", default: \"monospace\" });\nconst HEADING_SIZE = [0, 20, 17, 15] as const;\n\nfunction runStyle(run: TextRun, p: Palette): TextStyle {\n return {\n fontWeight: run.bold ? \"700\" : undefined,\n fontStyle: run.italic ? \"italic\" : undefined,\n textDecorationLine: run.underline || run.href ? \"underline\" : undefined,\n fontFamily: run.code ? MONO : undefined,\n backgroundColor: run.code ? p.surface : undefined,\n color: run.href ? p.primary : undefined,\n };\n}\n\n/** Full-width image that keeps its aspect ratio (from width/height attributes, else measured). */\nfunction BodyImage({ block, palette: p }: { block: TextBlock; palette: Palette }) {\n const [ratio, setRatio] = useState(block.width && block.height ? block.width / block.height : 16 / 9);\n useEffect(() => {\n if (block.width && block.height) return;\n let live = true;\n Image.getSize(block.src as string, (w, h) => live && w > 0 && h > 0 && setRatio(w / h), () => {});\n return () => {\n live = false;\n };\n }, [block.src, block.width, block.height]);\n return <Image source={{ uri: block.src }} accessible accessibilityRole=\"image\" accessibilityLabel={block.alt || undefined} resizeMode=\"contain\" style={[styles.image, { aspectRatio: ratio, backgroundColor: p.surface }]} />;\n}\n\n/** Videos open outside the app (the browser or the provider's app) rather than playing inline. */\nfunction BodyVideo({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n return (\n <Pressable accessibilityRole=\"link\" accessibilityLabel={block.alt} onPress={() => onLink(block.href as string)} style={({ pressed }) => [styles.video, { borderColor: p.border, backgroundColor: p.surface, opacity: pressed ? 0.7 : 1 }]}>\n <Text style={[styles.play, { color: p.primary }]}>▶</Text>\n <Text style={{ color: p.primary, fontFamily: p.fontFamily, fontWeight: \"600\" }}>{block.alt}</Text>\n </Pressable>\n );\n}\n\n/** A4 portrait, for pages without a stored size. */\nconst PAGE_RATIO = 1 / 1.414;\nconst pageRatio = (p: PdfPage) => (p.width && p.height ? p.width / p.height : PAGE_RATIO);\n\nfunction PdfBadge() {\n return (\n <View style={styles.badge}>\n <Text style={styles.badgeText}>PDF</Text>\n </View>\n );\n}\n\n/** A PDF that couldn't be shown page by page: a card that opens it. */\nfunction BodyFile({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n return (\n <Pressable accessibilityRole=\"link\" accessibilityLabel={`${block.alt}, PDF`} onPress={() => onLink(block.href as string)} style={({ pressed }) => [styles.video, { borderColor: p.border, backgroundColor: p.surface, opacity: pressed ? 0.7 : 1 }]}>\n <PdfBadge />\n <Text numberOfLines={2} ellipsizeMode=\"middle\" style={[styles.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: \"600\" }]}>{block.alt}</Text>\n </Pressable>\n );\n}\n\n/**\n * A PDF read in place: its pages swipe sideways with a page counter, and a tap opens every page in a\n * full-screen reader with the original PDF one button away. Nothing downloads.\n */\nfunction BodyPdf({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n const pages = block.pages ?? [];\n const [width, setWidth] = useState(0);\n const [index, setIndex] = useState(0);\n const [reading, setReading] = useState(false);\n // Every page gets the tallest page's height, so swiping never resizes the article.\n const height = width ? Math.max(...pages.map((pg) => width / pageRatio(pg))) : 0;\n const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => width && setIndex(Math.round(e.nativeEvent.contentOffset.x / width));\n return (\n <View style={[styles.pdf, { borderColor: p.border, backgroundColor: p.surface }]}>\n <Pressable accessibilityRole=\"button\" accessibilityLabel={`Read ${block.alt} full screen`} onPress={() => setReading(true)} style={({ pressed }) => [styles.pdfHeader, { opacity: pressed ? 0.7 : 1 }]}>\n <PdfBadge />\n <Text numberOfLines={1} ellipsizeMode=\"middle\" style={[styles.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: \"600\" }]}>{block.alt}</Text>\n <Text style={{ color: p.muted, fontSize: 16 }}>⤢</Text>\n </Pressable>\n <View style={styles.pdfPages} onLayout={(e) => setWidth(e.nativeEvent.layout.width)}>\n {width > 0 && (\n <ScrollView horizontal pagingEnabled showsHorizontalScrollIndicator={false} onScroll={onScroll} scrollEventThrottle={32} accessibilityLabel={`${block.alt}, page ${index + 1} of ${pages.length}`}>\n {pages.map((pg, i) => (\n <Pressable key={i} onPress={() => setReading(true)} accessibilityRole=\"imagebutton\" accessibilityLabel={pg.alt || `Page ${i + 1}`} accessibilityHint=\"Opens the document full screen\" style={{ width, height, alignItems: \"center\", justifyContent: \"center\" }}>\n <Image source={{ uri: pg.src }} resizeMode=\"contain\" style={[styles.page, { width: Math.min(width, height * pageRatio(pg)), aspectRatio: pageRatio(pg) }]} />\n </Pressable>\n ))}\n </ScrollView>\n )}\n {pages.length > 1 && (\n <View pointerEvents=\"none\" style={styles.count}>\n <Text style={styles.countText}>{index + 1} / {pages.length}</Text>\n </View>\n )}\n </View>\n <Modal visible={reading} animationType=\"slide\" presentationStyle=\"fullScreen\" onRequestClose={() => setReading(false)}>\n <View style={styles.reader}>\n <View style={styles.readerBar}>\n <Text numberOfLines={1} ellipsizeMode=\"middle\" style={[styles.flex, styles.readerTitle]} accessibilityRole=\"header\">{block.alt}</Text>\n <Pressable accessibilityRole=\"link\" onPress={() => onLink(block.href as string)} style={styles.readerBtn}>\n <Text style={styles.readerBtnText}>Open PDF ↗</Text>\n </Pressable>\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Close\" onPress={() => setReading(false)} style={styles.readerBtn}>\n <Text style={styles.readerBtnText}>Done</Text>\n </Pressable>\n </View>\n <ScrollView contentContainerStyle={styles.readerPages}>\n {pages.map((pg, i) => (\n <Image key={i} source={{ uri: pg.src }} accessible accessibilityLabel={pg.alt || `Page ${i + 1}`} resizeMode=\"contain\" style={[styles.readerPage, { aspectRatio: pageRatio(pg) }]} />\n ))}\n </ScrollView>\n </View>\n </Modal>\n </View>\n );\n}\n\n/** Renders a sanitized HTML guide body with native Text. Links call `onLink`. */\nexport function RichText({ html, palette: p, onLink, size = 15 }: { html: string; palette: Palette; onLink: (url: string) => void; size?: number }) {\n const blocks = useMemo(() => parseHtml(html), [html]);\n if (!blocks.length) return null;\n const base: TextStyle = { color: p.text, fontSize: size, lineHeight: Math.round(size * 1.42), fontFamily: p.fontFamily };\n return (\n <View style={styles.wrap}>\n {blocks.map((b, i) => {\n if (b.kind === \"image\") return <BodyImage key={i} block={b} palette={p} />;\n if (b.kind === \"video\") return <BodyVideo key={i} block={b} palette={p} onLink={onLink} />;\n if (b.kind === \"pdf\") return <BodyPdf key={i} block={b} palette={p} onLink={onLink} />;\n if (b.kind === \"file\") return <BodyFile key={i} block={b} palette={p} onLink={onLink} />;\n const runs = b.runs.map((r, j) => (\n <Text key={j} style={runStyle(r, p)} onPress={r.href ? () => onLink(r.href as string) : undefined} accessibilityRole={r.href ? \"link\" : undefined}>\n {r.text}\n </Text>\n ));\n if (b.kind === \"list-item\") {\n return (\n <View key={i} style={[styles.li, { paddingLeft: (b.level - 1) * 14 }]}>\n <Text style={[base, styles.marker]}>{b.marker}</Text>\n <Text style={[base, styles.flex]}>{runs}</Text>\n </View>\n );\n }\n if (b.kind === \"heading\") {\n const fs = HEADING_SIZE[b.level as 1 | 2 | 3] ?? 15;\n return (\n <Text key={i} accessibilityRole=\"header\" style={[base, { fontSize: fs, lineHeight: Math.round(fs * 1.3), fontWeight: \"700\" }]}>\n {runs}\n </Text>\n );\n }\n return (\n <Text key={i} style={[base, b.kind === \"quote\" && { borderLeftWidth: 3, borderLeftColor: p.border, paddingLeft: 8, color: p.muted }]}>\n {runs}\n </Text>\n );\n })}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n wrap: { gap: 6 },\n li: { flexDirection: \"row\", gap: 6 },\n marker: { minWidth: 14 },\n flex: { flex: 1 },\n image: { width: \"100%\", borderRadius: 6 },\n video: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingVertical: 12, paddingHorizontal: 14, borderWidth: 1, borderRadius: 8 },\n play: { fontSize: 14 },\n badge: { backgroundColor: \"#e5484d\", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 3 },\n badgeText: { color: \"#fff\", fontSize: 9, fontWeight: \"700\", letterSpacing: 0.4 },\n pdf: { borderWidth: 1, borderRadius: 10, overflow: \"hidden\" },\n pdfHeader: { flexDirection: \"row\", alignItems: \"center\", gap: 8, minHeight: 44, paddingHorizontal: 12 },\n pdfPages: { marginHorizontal: 10, marginBottom: 10 },\n page: { backgroundColor: \"#fff\", borderRadius: 3 },\n count: { position: \"absolute\", right: 8, bottom: 8, backgroundColor: \"rgba(17,17,17,0.72)\", borderRadius: 999, paddingHorizontal: 8, paddingVertical: 2 },\n countText: { color: \"#fff\", fontSize: 11, fontWeight: \"500\", fontVariant: [\"tabular-nums\"] },\n reader: { flex: 1, backgroundColor: \"#0b0b0d\" },\n readerBar: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingTop: Platform.OS === \"ios\" ? 52 : 12, paddingBottom: 10, paddingHorizontal: 16 },\n readerTitle: { color: \"#fff\", fontSize: 16, fontWeight: \"600\" },\n readerBtn: { minHeight: 36, justifyContent: \"center\", paddingHorizontal: 12, borderRadius: 8, backgroundColor: \"rgba(255,255,255,0.12)\" },\n readerBtnText: { color: \"#fff\", fontWeight: \"600\" },\n readerPages: { gap: 12, paddingHorizontal: 12, paddingBottom: 32 },\n readerPage: { width: \"100%\", backgroundColor: \"#fff\", borderRadius: 2 },\n});\n","import { PDF_BLOCK_CLASS, isAllowedEmbedSrc, isFileLink, isSafeMediaUrl, toEmbedUrl } from \"@guidelytech/shared/runtime\";\n\n/**\n * Tiny, tolerant HTML → rich-text converter for guide bodies (already sanitized server-side).\n * Supports p, div, br, strong/b, em/i, u, a, code, ul/ol/li, h1–h6 and blockquote; every other tag\n * is reduced to its text. `img` becomes an image block, and `video` / canonical embed `iframe`s\n * become video blocks (shown as a link that opens the video). A PDF (`div.gd-pdf`: its link and its\n * pages as images) becomes one pdf block, and a lone file link (`a.gd-file`) a file block. Output is\n * plain data so it can be unit-tested without React Native.\n */\n\nexport interface PdfPage {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n}\n\nexport interface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n code?: boolean;\n href?: string;\n}\n\nexport interface TextBlock {\n kind: \"paragraph\" | \"heading\" | \"list-item\" | \"quote\" | \"image\" | \"video\" | \"pdf\" | \"file\";\n /** Heading level 1–3, list nesting depth from 1. */\n level: number;\n /** For list items: the bullet (\"•\") or number (\"1.\") to show. */\n marker?: string;\n runs: TextRun[];\n /** Image blocks: http(s) or data:image source. */\n src?: string;\n /** Image alt text, a video's label, or a PDF's file name. */\n alt?: string;\n /** Video, pdf and file blocks: the page or file to open. */\n href?: string;\n /** Pdf blocks: the rendered pages, in order. */\n pages?: PdfPage[];\n /** Image intrinsic size from `width`/`height`, when present. */\n width?: number;\n height?: number;\n}\n\nconst ENTITIES: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \" \", mdash: \"—\", ndash: \"–\", hellip: \"…\", rsquo: \"’\", lsquo: \"‘\", rdquo: \"”\", ldquo: \"“\", copy: \"©\", reg: \"®\", trade: \"™\", times: \"×\", rarr: \"→\", larr: \"←\", bull: \"•\" };\n\nexport function decodeEntities(s: string): string {\n return s.replace(/&(#x[0-9a-f]+|#\\d+|[a-z]+);/gi, (m, e: string) => {\n if (e[0] === \"#\") {\n const code = e[1] === \"x\" || e[1] === \"X\" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);\n return Number.isFinite(code) && code > 0 && code < 0x110000 ? String.fromCodePoint(code) : m;\n }\n return ENTITIES[e.toLowerCase()] ?? m;\n });\n}\n\nconst BLOCK_TAGS = new Set([\"p\", \"div\", \"section\", \"article\", \"header\", \"footer\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"li\", \"blockquote\", \"ul\", \"ol\", \"table\", \"tr\", \"pre\"]);\nconst SKIP_TAGS = new Set([\"script\", \"style\", \"head\", \"title\", \"svg\", \"template\", \"iframe\", \"video\"]);\nconst PROVIDER_LABEL = { youtube: \"Watch on YouTube\", vimeo: \"Watch on Vimeo\", loom: \"Watch on Loom\", wistia: \"Watch video\" } as const;\n\nfunction attr(attrs: string, name: string): string | undefined {\n const m = attrs.match(new RegExp(`\\\\b${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, \"i\"));\n return m ? decodeEntities(m[2] ?? m[3] ?? m[4] ?? \"\") : undefined;\n}\n\nexport function parseHtml(html: string): TextBlock[] {\n const blocks: TextBlock[] = [];\n const style = { bold: 0, italic: 0, underline: 0, code: 0 };\n const hrefs: string[] = [];\n const lists: Array<{ ordered: boolean; n: number }> = [];\n let current: TextBlock | null = null;\n let skipping: string | null = null;\n /** Inside a `div.gd-pdf`: nesting depth of divs, the PDF link, its name and the pages so far. */\n let pdf: { depth: number; href?: string; name: string; inLink: boolean; pages: PdfPage[] } | null = null;\n /** Inside a lone `a.gd-file`: its target and text so far. */\n let fileLink: { href: string; name: string } | null = null;\n\n const media = (block: Omit<TextBlock, \"level\" | \"runs\">) => {\n flush();\n blocks.push({ level: 1, runs: [], ...block });\n };\n const flush = () => {\n if (current) {\n // Trim surrounding whitespace of the block; drop empty blocks.\n const runs = current.runs;\n while (runs.length && !runs[0]!.text.trim()) runs.shift();\n while (runs.length && !runs[runs.length - 1]!.text.trim()) runs.pop();\n if (runs.length) {\n runs[0]!.text = runs[0]!.text.replace(/^[ \\t\\n]+/, \"\");\n runs[runs.length - 1]!.text = runs[runs.length - 1]!.text.replace(/[ \\t\\n]+$/, \"\");\n blocks.push(current);\n }\n }\n current = null;\n };\n const open = (kind: TextBlock[\"kind\"], level = 1, marker?: string) => {\n flush();\n current = { kind, level, marker, runs: [] };\n };\n const push = (text: string) => {\n if (!text) return;\n if (!current) current = { kind: \"paragraph\", level: 1, runs: [] };\n const run: TextRun = { text };\n if (style.bold) run.bold = true;\n if (style.italic) run.italic = true;\n if (style.underline) run.underline = true;\n if (style.code) run.code = true;\n if (hrefs.length) run.href = hrefs[hrefs.length - 1];\n const last = current.runs[current.runs.length - 1];\n if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text += text;\n else current.runs.push(run);\n };\n\n const size = (attrs: string, name: string) => {\n const n = Number(attr(attrs, name));\n return n > 0 ? n : undefined;\n };\n const endPdf = (p: NonNullable<typeof pdf>) => {\n const name = p.name.replace(/\\s+/g, \" \").trim();\n if (p.href && p.pages.length) media({ kind: \"pdf\", href: p.href, alt: name || \"PDF\", pages: p.pages });\n else if (p.href) media({ kind: \"file\", href: p.href, alt: name || \"Open PDF\" });\n else for (const page of p.pages) media({ kind: \"image\", src: page.src, alt: page.alt, ...(page.width && page.height ? { width: page.width, height: page.height } : {}) });\n };\n\n const re = /<!--[\\s\\S]*?-->|<\\/?([a-zA-Z][a-zA-Z0-9]*)\\b([^>]*)>|([^<]+|<)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(html || \"\"))) {\n const [token, rawTag, attrs = \"\", text] = m;\n if (text !== undefined) {\n if (skipping) continue;\n if (pdf) {\n if (pdf.inLink) pdf.name += decodeEntities(text);\n continue;\n }\n if (fileLink) {\n fileLink.name += decodeEntities(text);\n continue;\n }\n push(decodeEntities(text.replace(/\\s+/g, \" \")));\n continue;\n }\n if (!rawTag) continue; // comment\n const tag = rawTag.toLowerCase();\n const closing = token.startsWith(\"</\");\n if (skipping) {\n if (closing && tag === skipping) skipping = null;\n continue;\n }\n if (SKIP_TAGS.has(tag)) {\n if (closing) continue;\n if (tag === \"iframe\") {\n const src = attr(attrs, \"src\");\n const embed = isAllowedEmbedSrc(src) ? toEmbedUrl(src!) : null;\n if (embed) media({ kind: \"video\", href: embed.watchUrl, alt: PROVIDER_LABEL[embed.provider] });\n } else if (tag === \"video\") {\n const src = attr(attrs, \"src\");\n if (isSafeMediaUrl(src)) media({ kind: \"video\", href: src, alt: \"Play video\" });\n }\n if (!token.endsWith(\"/>\")) skipping = tag;\n continue;\n }\n if (pdf) {\n if (tag === \"div\") {\n pdf.depth += closing ? -1 : 1;\n if (pdf.depth === 0) {\n endPdf(pdf);\n pdf = null;\n }\n } else if (tag === \"a\") {\n if (closing) pdf.inLink = false;\n else if (!pdf.href && isFileLink(attr(attrs, \"class\"), attr(attrs, \"href\"))) {\n pdf.href = attr(attrs, \"href\");\n pdf.inLink = true;\n }\n } else if (tag === \"img\" && !closing) {\n const src = attr(attrs, \"src\");\n const w = size(attrs, \"width\");\n const h = size(attrs, \"height\");\n if (isSafeMediaUrl(src)) pdf.pages.push({ src: src!, alt: attr(attrs, \"alt\") ?? \"\", ...(w && h ? { width: w, height: h } : {}) });\n }\n continue;\n }\n if (fileLink) {\n if (closing && tag === \"a\") {\n media({ kind: \"file\", href: fileLink.href, alt: fileLink.name.replace(/\\s+/g, \" \").trim() || \"Open PDF\" });\n fileLink = null;\n }\n continue;\n }\n if (!closing && tag === \"div\" && (attr(attrs, \"class\") ?? \"\").split(/\\s+/).includes(PDF_BLOCK_CLASS)) {\n flush();\n pdf = { depth: 1, name: \"\", inLink: false, pages: [] };\n continue;\n }\n if (!closing && tag === \"a\" && isFileLink(attr(attrs, \"class\"), attr(attrs, \"href\"))) {\n flush();\n fileLink = { href: attr(attrs, \"href\")!, name: \"\" };\n continue;\n }\n if (closing) {\n if (tag === \"b\" || tag === \"strong\") style.bold = Math.max(0, style.bold - 1);\n else if (tag === \"i\" || tag === \"em\") style.italic = Math.max(0, style.italic - 1);\n else if (tag === \"u\") style.underline = Math.max(0, style.underline - 1);\n else if (tag === \"code\") style.code = Math.max(0, style.code - 1);\n else if (tag === \"a\") hrefs.pop();\n else if (tag === \"ul\" || tag === \"ol\") {\n lists.pop();\n flush();\n } else if (BLOCK_TAGS.has(tag)) flush();\n continue;\n }\n switch (tag) {\n case \"br\":\n push(\"\\n\");\n break;\n case \"b\":\n case \"strong\":\n style.bold += 1;\n break;\n case \"i\":\n case \"em\":\n style.italic += 1;\n break;\n case \"u\":\n style.underline += 1;\n break;\n case \"code\":\n style.code += 1;\n break;\n case \"a\":\n hrefs.push(attr(attrs, \"href\") ?? \"\");\n break;\n case \"ul\":\n case \"ol\":\n flush();\n lists.push({ ordered: tag === \"ol\", n: 0 });\n break;\n case \"li\": {\n const list = lists[lists.length - 1];\n if (list) list.n += 1;\n open(\"list-item\", Math.max(1, lists.length), list?.ordered ? `${list.n}.` : \"•\");\n break;\n }\n case \"h1\":\n case \"h2\":\n case \"h3\":\n case \"h4\":\n case \"h5\":\n case \"h6\":\n open(\"heading\", Math.min(3, Number(tag[1])));\n break;\n case \"blockquote\":\n open(\"quote\");\n break;\n default:\n if (BLOCK_TAGS.has(tag)) open(\"paragraph\");\n else if (tag === \"img\") {\n const src = attr(attrs, \"src\") ?? \"\";\n const alt = attr(attrs, \"alt\") ?? \"\";\n if (isSafeMediaUrl(src) || /^data:image\\//i.test(src)) {\n const w = Number(attr(attrs, \"width\"));\n const h = Number(attr(attrs, \"height\"));\n media({ kind: \"image\", src, alt, ...(w > 0 && h > 0 ? { width: w, height: h } : {}) });\n } else if (alt) push(alt);\n }\n }\n }\n if (pdf) endPdf(pdf);\n if (fileLink) media({ kind: \"file\", href: fileLink.href, alt: fileLink.name.replace(/\\s+/g, \" \").trim() || \"Open PDF\" });\n flush();\n return blocks;\n}\n\n/** Plain-text rendering of an HTML body (accessibility labels, previews). */\nexport function htmlToText(html: string): string {\n return parseHtml(html)\n .map((b) => (b.kind === \"image\" || b.kind === \"video\" || b.kind === \"pdf\" || b.kind === \"file\" ? (b.alt ?? \"\") : (b.marker ? `${b.marker} ` : \"\") + b.runs.map((r) => r.text).join(\"\")))\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport { AccessibilityInfo, ActivityIndicator, Animated, Easing, Keyboard, Modal, PanResponder, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from \"react-native\";\nimport type { MessengerConversation, MessengerMessage, ResourceCenterArticle } from \"@guidelytech/shared\";\nimport { isArticleListed, resourceCenterSections } from \"@guidelytech/shared/runtime\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { clampToSafeArea, LAUNCHER_DRAG_THRESHOLD, placementPoint, snapPlacement, type LauncherFrame, type LauncherPlacement, type Point } from \"../core/launcherPlacement\";\nimport type { Messenger as MessengerStore, MessengerTab } from \"../core/messenger\";\nimport { CloseButton, GButton } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\nfunction useMessenger(store: MessengerStore) {\n return useSyncExternalStore(\n useCallback((cb) => store.subscribe(cb), [store]),\n () => store.getSnapshot(),\n () => store.getSnapshot(),\n );\n}\n\n/**\n * Keyboard height on iOS. KeyboardAvoidingView measures relative to a pageSheet modal rather than\n * the screen and under-shifts; the sheet reaches the bottom of the screen, so padding by the\n * keyboard height is exact. Android resizes the modal window itself.\n */\nfunction useKeyboardHeight(): number {\n const [h, setH] = useState(0);\n useEffect(() => {\n if (Platform.OS !== \"ios\") return;\n const show = Keyboard.addListener(\"keyboardWillShow\", (e) => setH(e.endCoordinates.height));\n const hide = Keyboard.addListener(\"keyboardWillHide\", () => setH(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n return h;\n}\n\nfunction ago(iso: string): string {\n const s = Math.max(0, (Date.now() - Date.parse(iso)) / 1000);\n if (s < 60) return \"now\";\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n}\n\n/** Diameter of the chat bubble. */\nexport const LAUNCHER_SIZE = 54;\n\nfunction useReduceMotion(): boolean {\n const [on, setOn] = useState(false);\n useEffect(() => {\n let live = true;\n AccessibilityInfo.isReduceMotionEnabled?.()\n .then((v) => live && setOn(v))\n .catch(() => {});\n const sub = AccessibilityInfo.addEventListener?.(\"reduceMotionChanged\", setOn);\n return () => {\n live = false;\n sub?.remove();\n };\n }, []);\n return on;\n}\n\n/**\n * Round chat bubble with an unread badge. `style` pins it to the configured corner; a drag (more than a few px, so taps\n * still open the messenger) moves it, and on release it snaps to the nearer side edge at the drop\n * height. The spot is remembered on this device and drawn as a translation from the corner, so\n * until the visitor drags, placement is exactly the configured one.\n */\nexport function MessengerLauncher({ store, client, palette: p, style, frame, defaultSide }: { store: MessengerStore; client: GuidelyClient; palette: Palette; style: object; frame: LauncherFrame; defaultSide: LauncherPlacement[\"side\"] }) {\n const snap = useMessenger(store);\n const reduceMotion = useReduceMotion();\n const [placement, setPlacement] = useState(() => client.getMessengerLauncherPlacement());\n const pan = useRef(new Animated.ValueXY()).current;\n const offset = useRef<Point>({ x: 0, y: 0 });\n const dragging = useRef(false);\n // Read by the (once-created) responder, so it always sees the current window and preferences.\n const live = useRef({ frame, defaultSide, reduceMotion });\n live.current = { frame, defaultSide, reduceMotion };\n\n // Re-applies the remembered spot whenever the window, insets or bottom offset change (rotation).\n // A layout effect, so a remembered spot never flashes in the configured corner first.\n const { width, height, size, defaultBottom } = frame;\n const { top, bottom, left, right } = frame.insets;\n useLayoutEffect(() => {\n if (dragging.current) return;\n const f = live.current.frame;\n const anchor = placementPoint(f, { side: defaultSide, fraction: 0 });\n const at = placement ? placementPoint(f, placement) : anchor;\n offset.current = { x: at.x - anchor.x, y: at.y - anchor.y };\n pan.setValue(offset.current);\n }, [pan, placement, defaultSide, width, height, size, defaultBottom, top, bottom, left, right]);\n\n const responder = useMemo(() => {\n const moved = (g: { dx: number; dy: number }) => Math.hypot(g.dx, g.dy) > LAUNCHER_DRAG_THRESHOLD;\n // Offsets are from the configured corner (`style`), where the bubble's top-left is `anchor()`.\n const anchor = () => placementPoint(live.current.frame, { side: live.current.defaultSide, fraction: 0 });\n let start: Point = { x: 0, y: 0 };\n const follow = (g: { dx: number; dy: number }): Point => {\n const a = anchor();\n const at = clampToSafeArea(live.current.frame, { x: a.x + start.x + g.dx, y: a.y + start.y + g.dy });\n return { x: at.x - a.x, y: at.y - a.y };\n };\n const drop = (g: { dx: number; dy: number }) => {\n const a = anchor();\n const d = follow(g);\n const next = snapPlacement(live.current.frame, { x: a.x + d.x, y: a.y + d.y });\n const at = placementPoint(live.current.frame, next);\n const to = { x: at.x - a.x, y: at.y - a.y };\n offset.current = to;\n client.setMessengerLauncherPlacement(next);\n const done = ({ finished }: { finished: boolean }) => {\n // Not finished = grabbed again mid-snap; that drag is still in charge.\n if (finished) dragging.current = false;\n setPlacement(next);\n };\n if (live.current.reduceMotion) {\n pan.setValue(to);\n done({ finished: true });\n } else Animated.timing(pan, { toValue: to, duration: 300, easing: Easing.out(Easing.cubic), useNativeDriver: true }).start(done);\n };\n return PanResponder.create({\n // Taps stay with the Pressable; only a real drag is taken (which cancels its press).\n onMoveShouldSetPanResponderCapture: (_, g) => moved(g),\n onMoveShouldSetPanResponder: (_, g) => moved(g),\n onPanResponderGrant: () => {\n dragging.current = true;\n start = offset.current;\n pan.stopAnimation((v) => {\n if (Number.isFinite(v?.x) && Number.isFinite(v?.y)) start = v;\n });\n },\n onPanResponderMove: (_, g) => pan.setValue(follow(g)),\n onPanResponderRelease: (_, g) => drop(g),\n onPanResponderTerminate: (_, g) => drop(g),\n onPanResponderTerminationRequest: () => false,\n });\n }, [client, pan]);\n\n if (snap.open) return null;\n const label = snap.unread ? `Open ${snap.config.name}, ${snap.unread} unread` : `Open ${snap.config.name}`;\n return (\n <Animated.View {...responder.panHandlers} style={[styles.launcherWrap, style, { transform: pan.getTranslateTransform() }]}>\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={() => !dragging.current && store.open()} style={({ pressed }) => [styles.launcher, { backgroundColor: p.primary, opacity: pressed ? 0.85 : 1 }]}>\n <Text style={[styles.launcherIcon, { color: p.onPrimary }]}>💬</Text>\n {snap.unread ? (\n <View style={styles.badge}>\n <Text style={styles.badgeText}>{snap.unread}</Text>\n </View>\n ) : null}\n </Pressable>\n </Animated.View>\n );\n}\n\n/** The messenger sheet: Home, Messages and Help tabs, threads and articles. */\nexport function MessengerSheet({ store, client, palette: p, topInset, bottomInset }: { store: MessengerStore; client: GuidelyClient; palette: Palette; topInset: number; bottomInset: number }) {\n const snap = useMessenger(store);\n const keyboard = useKeyboardHeight();\n const v = snap.view;\n const title = v.kind === \"thread\" ? snap.thread?.conversation?.subject || \"New conversation\" : v.kind === \"article\" ? \"\" : v.tab === \"home\" ? snap.config.name : v.tab === \"messages\" ? \"Messages\" : \"Help\";\n return (\n <Modal visible={snap.open} animationType=\"slide\" presentationStyle={Platform.OS === \"ios\" ? \"pageSheet\" : \"fullScreen\"} onRequestClose={() => (v.kind === \"tab\" ? store.close() : store.back())}>\n <View style={[styles.sheet, { backgroundColor: p.background, paddingTop: Platform.OS === \"ios\" ? 8 : topInset, paddingBottom: keyboard }]}>\n <View style={[styles.header, { borderColor: p.border }]}>\n {v.kind !== \"tab\" ? (\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Back\" onPress={() => store.back()} hitSlop={10}>\n <Text style={[styles.back, { color: p.primary }]}>‹ Back</Text>\n </Pressable>\n ) : null}\n <Text accessibilityRole=\"header\" numberOfLines={1} style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {title}\n </Text>\n <CloseButton palette={p} onPress={() => store.close()} label={`Close ${snap.config.name}`} />\n </View>\n <View style={styles.flex}>\n {v.kind === \"thread\" ? <Thread store={store} palette={p} bottomInset={keyboard ? 0 : bottomInset} /> : v.kind === \"article\" ? <Article article={snap.article} palette={p} client={client} /> : v.tab === \"home\" ? <Home store={store} palette={p} /> : v.tab === \"messages\" ? <Conversations store={store} palette={p} /> : <Help store={store} client={client} palette={p} />}\n </View>\n {v.kind === \"tab\" && !keyboard ? <Tabs store={store} active={v.tab} palette={p} bottomInset={bottomInset} /> : null}\n </View>\n </Modal>\n );\n}\n\nfunction Tabs({ store, active, palette: p, bottomInset }: { store: MessengerStore; active: MessengerTab; palette: Palette; bottomInset: number }) {\n const unread = useMessenger(store).unread;\n const tabs: Array<[MessengerTab, string, string]> = [\n [\"home\", \"⌂\", \"Home\"],\n [\"messages\", \"\\u2709\\uFE0E\", \"Messages\"],\n [\"help\", \"?\", \"Help\"],\n ];\n return (\n <View accessibilityRole=\"tablist\" style={[styles.tabs, { borderColor: p.border, paddingBottom: Math.max(8, bottomInset) }]}>\n {tabs.map(([tab, icon, label]) => {\n const on = tab === active;\n return (\n <Pressable key={tab} accessibilityRole=\"tab\" accessibilityState={{ selected: on }} accessibilityLabel={tab === \"messages\" && unread ? `${label}, ${unread} unread` : label} onPress={() => store.setTab(tab)} style={styles.tab}>\n <Text style={[styles.tabIcon, { color: on ? p.primary : p.muted }]}>{icon}</Text>\n <Text style={[styles.tabLabel, { color: on ? p.primary : p.muted }]}>{label}</Text>\n {tab === \"messages\" && unread ? <View style={[styles.dot, styles.tabDot]} /> : null}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nfunction Home({ store, palette: p }: { store: MessengerStore; palette: Palette }) {\n const snap = useMessenger(store);\n const recent = snap.conversations[0];\n const [q, setQ] = useState(\"\");\n return (\n <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps=\"handled\">\n <View style={[styles.hero, { backgroundColor: p.primary, borderRadius: p.radius }]}>\n <Text style={[styles.heroTitle, { color: p.onPrimary }]}>{snap.config.greeting || `Hi! I'm ${snap.config.name}.`}</Text>\n <Text style={[styles.heroSub, { color: p.onPrimary }]}>{snap.config.aiAvailable ? `${snap.config.name} answers right away${snap.config.handoffEnabled ? \", and the team is here when you need a person\" : \"\"}.` : \"The team usually replies within a few hours.\"}</Text>\n </View>\n <GButton label=\"Send us a message\" palette={p} onPress={() => store.showNewMessage()} style={styles.fullWidth} />\n {recent ? (\n <View style={styles.section}>\n <Text style={[styles.sectionTitle, { color: p.muted }]}>RECENT</Text>\n <ConversationRow c={recent} palette={p} onPress={() => void store.openConversation(recent.id)} />\n </View>\n ) : null}\n <View style={styles.section}>\n <Text style={[styles.sectionTitle, { color: p.muted }]}>SEARCH FOR HELP</Text>\n <TextInput\n value={q}\n onChangeText={setQ}\n onSubmitEditing={() => {\n pendingSearch.current = q;\n store.setTab(\"help\");\n }}\n returnKeyType=\"search\"\n placeholder=\"Search articles\"\n placeholderTextColor={p.muted}\n accessibilityLabel=\"Search help articles\"\n style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]}\n />\n </View>\n </ScrollView>\n );\n}\n\n/** Carries a search typed on Home over to the Help tab. */\nconst pendingSearch: { current: string } = { current: \"\" };\n\nfunction ConversationRow({ c, palette: p, onPress }: { c: MessengerConversation; palette: Palette; onPress: () => void }) {\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={`${c.subject || \"Conversation\"}${c.unread ? \", unread\" : \"\"}`} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text numberOfLines={1} style={[styles.rowTitle, { color: p.text }]}>\n {c.subject || \"Conversation\"}\n </Text>\n <Text numberOfLines={1} style={[styles.rowSub, { color: p.muted }]}>\n {c.lastMessagePreview || (c.status === \"closed\" ? \"Closed\" : \" \")}\n </Text>\n </View>\n <View style={styles.rowEnd}>\n <Text style={[styles.time, { color: p.muted }]}>{ago(c.lastMessageAt)}</Text>\n {c.unread ? <View style={[styles.dot, { backgroundColor: p.primary }]} /> : null}\n </View>\n </Pressable>\n );\n}\n\nfunction Conversations({ store, palette: p }: { store: MessengerStore; palette: Palette }) {\n const snap = useMessenger(store);\n return (\n <ScrollView contentContainerStyle={styles.content}>\n {snap.conversations.length ? snap.conversations.map((c) => <ConversationRow key={c.id} c={c} palette={p} onPress={() => void store.openConversation(c.id)} />) : <Text style={[styles.empty, { color: p.muted }]}>No conversations yet.</Text>}\n <GButton label=\"New conversation\" palette={p} onPress={() => store.showNewMessage()} style={styles.fullWidth} />\n </ScrollView>\n );\n}\n\nfunction Bubble({ m, text, name, palette: p, onArticle, onGuide }: { m: MessengerMessage; text: string; name: string; palette: Palette; onArticle: (id: string) => void; onGuide: (key: string) => void }) {\n if (m.author === \"system\")\n return (\n <Text accessibilityRole=\"text\" style={[styles.system, { color: p.muted }]}>\n {text}\n </Text>\n );\n const mine = m.author === \"user\";\n return (\n <View style={[styles.bubbleWrap, mine ? styles.mine : styles.theirs]}>\n {!mine ? <Text style={[styles.author, { color: p.muted }]}>{m.author === \"agent\" ? m.authorName || \"Team\" : name}</Text> : null}\n <View style={[styles.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }]}>\n {m.status === \"pending\" && !text ? <TypingDots color={p.muted} /> : <Text style={[styles.bubbleText, { color: mine ? p.onPrimary : p.text }]}>{text}</Text>}\n </View>\n {m.citations.length || m.suggestedGuides.length ? (\n <View style={styles.chips}>\n {m.citations.map((c) => (\n <Pressable key={c.articleId} accessibilityRole=\"link\" accessibilityLabel={`Article: ${c.title}`} onPress={() => onArticle(c.articleId)} style={[styles.chip, { borderColor: p.border }]}>\n <Text style={[styles.chipText, { color: p.text }]}>📄 {c.title}</Text>\n </Pressable>\n ))}\n {m.suggestedGuides.map((g) => (\n <Pressable key={g.key} accessibilityRole=\"button\" accessibilityLabel={`Show me: ${g.name}`} onPress={() => onGuide(g.key)} style={[styles.chip, { borderColor: p.primary }]}>\n <Text style={[styles.chipText, { color: p.primary }]}>▶ Show me: {g.name}</Text>\n </Pressable>\n ))}\n </View>\n ) : null}\n </View>\n );\n}\n\nfunction TypingDots({ color }: { color: string }) {\n return <ActivityIndicator size=\"small\" color={color} accessibilityLabel=\"Typing\" />;\n}\n\nfunction Thread({ store, palette: p, bottomInset }: { store: MessengerStore; palette: Palette; bottomInset: number }) {\n const snap = useMessenger(store);\n const t = snap.thread;\n const [text, setText] = useState(t?.draft ?? \"\");\n const scroll = useRef<ScrollView>(null);\n const convo = t?.conversation ?? null;\n useEffect(() => {\n if (t?.draft) setText(t.draft);\n }, [t?.draft]);\n const streamingIds = useMemo(() => Object.keys(t?.streaming ?? {}).filter((id) => !t?.messages.some((m) => m.id === id)), [t]);\n if (!t) return null;\n const send = () => {\n const value = text;\n setText(\"\");\n void store.send(value);\n };\n const canHandoff = snap.config.handoffEnabled && snap.config.aiAvailable && convo?.status === \"bot\" && !t.sending;\n return (\n <View style={styles.flex}>\n <ScrollView ref={scroll} contentContainerStyle={styles.thread} onContentSizeChange={() => scroll.current?.scrollToEnd({ animated: true })} keyboardShouldPersistTaps=\"handled\">\n {!t.messages.length && !t.sending ? <Text style={[styles.empty, { color: p.muted }]}>{snap.config.greeting || \"Ask us anything.\"}</Text> : null}\n {t.messages.map((m) => (\n <Bubble key={m.id} m={m} text={t.streaming[m.id] ?? m.body} name={snap.config.name} palette={p} onArticle={(id) => void store.openArticle(id)} onGuide={(k) => store.startGuide(k)} />\n ))}\n {streamingIds.map((id) => (\n <Bubble key={id} m={{ id, author: \"scout\", body: \"\", citations: [], suggestedGuides: [], status: \"pending\", createdAt: new Date().toISOString() }} text={t.streaming[id] ?? \"\"} name={snap.config.name} palette={p} onArticle={() => {}} onGuide={() => {}} />\n ))}\n {t.sending && !streamingIds.length && snap.config.aiAvailable && t.messages.length ? <TypingDots color={p.muted} /> : null}\n {t.error ? (\n <Text accessibilityLiveRegion=\"polite\" style={styles.error}>\n {t.error}\n </Text>\n ) : null}\n {convo?.status === \"closed\" && convo.rating == null ? <Rating palette={p} onRate={(n) => void store.rate(n)} /> : null}\n {convo?.status === \"closed\" && convo.rating != null ? <Text style={[styles.system, { color: p.muted }]}>Thanks for rating this conversation.</Text> : null}\n </ScrollView>\n {canHandoff ? <GButton label=\"Talk to a person\" variant=\"secondary\" palette={p} onPress={() => void store.handoff()} style={styles.handoff} /> : null}\n <View style={[styles.composer, { borderColor: p.border, paddingBottom: Math.max(10, bottomInset) }]}>\n <TextInput\n value={text}\n onChangeText={(v) => setText(v.slice(0, 4000))}\n placeholder={convo ? \"Reply…\" : \"Write a message…\"}\n placeholderTextColor={p.muted}\n multiline\n accessibilityLabel=\"Message\"\n style={[styles.input, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(18, p.radius + 6) }]}\n />\n <GButton label=\"Send\" palette={p} onPress={send} disabled={!text.trim() || t.sending} />\n </View>\n </View>\n );\n}\n\nfunction Rating({ palette: p, onRate }: { palette: Palette; onRate: (n: number) => void }) {\n return (\n <View style={styles.rating}>\n <Text style={[styles.ratingTitle, { color: p.text }]}>How did we do?</Text>\n <View accessibilityRole=\"radiogroup\" style={styles.stars}>\n {[1, 2, 3, 4, 5].map((n) => (\n <Pressable key={n} accessibilityRole=\"radio\" accessibilityLabel={`${n} of 5`} onPress={() => onRate(n)} hitSlop={6}>\n <Text style={[styles.star, { color: p.primary }]}>★</Text>\n </Pressable>\n ))}\n </View>\n </View>\n );\n}\n\nfunction Help({ store, client, palette: p }: { store: MessengerStore; client: GuidelyClient; palette: Palette }) {\n const snap = useMessenger(store);\n const rc = client.getResourceCenter();\n const [q, setQ] = useState(pendingSearch.current);\n const [results, setResults] = useState<ResourceCenterArticle[] | null>(null);\n const [faq, setFaq] = useState<string | null>(null);\n useEffect(() => {\n pendingSearch.current = \"\";\n }, []);\n useEffect(() => {\n const query = q.trim();\n if (query.length < 2) return setResults(null);\n let alive = true;\n const t = setTimeout(() => void store.search(query).then((r) => alive && setResults(r)), 250);\n return () => {\n alive = false;\n clearTimeout(t);\n };\n }, [q, store]);\n const guides = client.getGuides();\n const recommended = (rc?.recommendedGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g);\n const articles = snap.articles;\n const row = (key: string, title: string, sub: string | undefined, onPress: () => void, icon = \"›\") => (\n <Pressable key={key} accessibilityRole=\"button\" accessibilityLabel={title} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text style={[styles.rowTitle, { color: p.text }]}>{title}</Text>\n {sub ? (\n <Text numberOfLines={2} style={[styles.rowSub, { color: p.muted }]}>\n {sub}\n </Text>\n ) : null}\n </View>\n <Text style={[styles.chev, { color: p.muted }]}>{icon}</Text>\n </Pressable>\n );\n const open = (a: { id: string; externalUrl?: string | null }) => (a.externalUrl ? client.navigate(a.externalUrl) : void store.openArticle(a.id));\n const section = (title: string, children: React.ReactNode) => (\n <View key={title} style={styles.section}>\n <Text accessibilityRole=\"header\" style={[styles.sectionTitle, { color: p.muted }]}>\n {title.toUpperCase()}\n </Text>\n {children}\n </View>\n );\n const audiences = client.getAudienceIds();\n const sections = resourceCenterSections(articles?.collections ?? [], articles?.articles ?? [], audiences);\n const modules = client.getHelpModules();\n const searchOn = modules.includes(\"search\");\n const listed = searchOn ? results?.filter((a) => isArticleListed(articles?.collections ?? [], a, audiences)) : undefined;\n const checklists = (rc?.checklistGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind === \"checklist\");\n const renderModule = (id: (typeof modules)[number]) => {\n switch (id) {\n case \"guides\":\n return recommended.length ? section(\"Recommended\", recommended.map((g) => row(g.id, g.name, undefined, () => store.startGuide(g.key), \"▶\"))) : null;\n case \"checklists\":\n return checklists.length ? section(\"Checklists\", checklists.map((g) => row(g.id, g.name, undefined, () => store.startGuide(g.key), \"☑\"))) : null;\n case \"articles\":\n return (\n <>\n {!articles ? <ActivityIndicator color={p.muted} /> : null}\n {sections.map((s) => section(s.collection ? s.path.join(\" › \") : \"Articles\", s.articles.map((a) => row(a.id, a.title, a.summary, () => open(a)))))}\n </>\n );\n case \"faqs\":\n return rc?.faqs.length\n ? section(\n \"FAQ\",\n rc.faqs.map((f) => (\n <View key={f.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <Pressable accessibilityRole=\"button\" accessibilityState={{ expanded: faq === f.id }} onPress={() => setFaq(faq === f.id ? null : f.id)} style={styles.faqHead}>\n <Text style={[styles.rowTitle, styles.flex, { color: p.text }]}>{f.question}</Text>\n <Text style={[styles.chev, { color: p.muted }]}>{faq === f.id ? \"−\" : \"+\"}</Text>\n </Pressable>\n {faq === f.id ? <RichText html={f.answer} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n </View>\n )),\n )\n : null;\n case \"links\":\n return rc?.links.length ? section(\"Links\", rc.links.map((l) => row(l.id, l.label, undefined, () => client.navigate(l.url), \"↗\"))) : null;\n default:\n return null; // \"search\" renders above the sections\n }\n };\n return (\n <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps=\"handled\">\n {searchOn ? <TextInput value={q} onChangeText={setQ} placeholder=\"Search articles\" placeholderTextColor={p.muted} accessibilityLabel=\"Search help articles\" returnKeyType=\"search\" style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]} /> : null}\n {listed ? (\n section(`Results for “${q.trim()}”`, listed.length ? listed.map((a) => row(a.id, a.title, a.summary, () => open(a))) : <Text style={[styles.rowSub, { color: p.muted }]}>No articles found.</Text>)\n ) : (\n <>\n {modules\n .filter((id) => id !== \"search\")\n .map((id) => (\n <Fragment key={id}>{renderModule(id)}</Fragment>\n ))}\n </>\n )}\n </ScrollView>\n );\n}\n\nfunction Article({ article, palette: p, client }: { article: ResourceCenterArticle | null; palette: Palette; client: GuidelyClient }) {\n if (!article) return <ActivityIndicator style={styles.loading} color={p.muted} />;\n return (\n <ScrollView contentContainerStyle={styles.content}>\n <Text accessibilityRole=\"header\" style={[styles.articleTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {article.title}\n </Text>\n <RichText html={article.body} palette={p} onLink={(u) => client.navigate(u)} />\n </ScrollView>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n launcherWrap: { position: \"absolute\", width: LAUNCHER_SIZE, height: LAUNCHER_SIZE, elevation: 8 },\n launcher: { width: LAUNCHER_SIZE, height: LAUNCHER_SIZE, borderRadius: 27, alignItems: \"center\", justifyContent: \"center\", elevation: 8, shadowColor: \"#000\", shadowOpacity: 0.22, shadowRadius: 12, shadowOffset: { width: 0, height: 4 } },\n launcherIcon: { fontSize: 24 },\n badge: { position: \"absolute\", top: -2, right: -2, minWidth: 20, height: 20, borderRadius: 10, backgroundColor: \"#dc2626\", alignItems: \"center\", justifyContent: \"center\", paddingHorizontal: 5, borderWidth: 2, borderColor: \"#ffffff\" },\n badgeText: { color: \"#ffffff\", fontSize: 11, fontWeight: \"800\" },\n sheet: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\", gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: StyleSheet.hairlineWidth },\n back: { fontSize: 16, fontWeight: \"600\" },\n title: { flex: 1, fontSize: 18, fontWeight: \"700\" },\n tabs: { flexDirection: \"row\", borderTopWidth: StyleSheet.hairlineWidth, paddingTop: 8 },\n tab: { flex: 1, alignItems: \"center\", gap: 2 },\n tabIcon: { fontSize: 18 },\n tabLabel: { fontSize: 11, fontWeight: \"600\" },\n tabDot: { position: \"absolute\", top: 0, right: \"34%\", backgroundColor: \"#dc2626\" },\n dot: { width: 8, height: 8, borderRadius: 4 },\n content: { padding: 16, gap: 16 },\n hero: { padding: 18, gap: 6 },\n heroTitle: { fontSize: 20, fontWeight: \"800\" },\n heroSub: { fontSize: 14, opacity: 0.9 },\n fullWidth: { alignSelf: \"stretch\" },\n section: { gap: 8 },\n sectionTitle: { fontSize: 12, fontWeight: \"700\", letterSpacing: 0.6 },\n search: { height: 42, paddingHorizontal: 12, fontSize: 15 },\n row: { flexDirection: \"row\", alignItems: \"center\", gap: 10, borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, paddingVertical: 12, paddingHorizontal: 12 },\n rowTitle: { fontSize: 15, fontWeight: \"600\" },\n rowSub: { fontSize: 13, marginTop: 2 },\n rowEnd: { alignItems: \"flex-end\", gap: 6 },\n time: { fontSize: 12 },\n chev: { fontSize: 18 },\n empty: { textAlign: \"center\", paddingVertical: 24, fontSize: 14 },\n faq: { flexDirection: \"column\", alignItems: \"stretch\" },\n faqHead: { flexDirection: \"row\", alignItems: \"center\", gap: 10 },\n thread: { padding: 16, gap: 12 },\n system: { textAlign: \"center\", fontSize: 12, paddingHorizontal: 24 },\n bubbleWrap: { maxWidth: \"86%\", gap: 4 },\n mine: { alignSelf: \"flex-end\", alignItems: \"flex-end\" },\n theirs: { alignSelf: \"flex-start\", alignItems: \"flex-start\" },\n author: { fontSize: 12, fontWeight: \"600\", marginLeft: 4 },\n bubble: { paddingHorizontal: 14, paddingVertical: 10 },\n bubbleText: { fontSize: 15, lineHeight: 21 },\n chips: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 },\n chip: { borderWidth: 1, borderRadius: 14, paddingHorizontal: 10, paddingVertical: 5 },\n chipText: { fontSize: 13, fontWeight: \"600\" },\n error: { color: \"#dc2626\", fontSize: 13, textAlign: \"center\" },\n handoff: { alignSelf: \"center\", marginBottom: 8 },\n composer: { flexDirection: \"row\", alignItems: \"flex-end\", gap: 8, paddingHorizontal: 12, paddingTop: 10, borderTopWidth: StyleSheet.hairlineWidth },\n input: { flex: 1, minHeight: 40, maxHeight: 120, paddingHorizontal: 14, paddingTop: 10, paddingBottom: 10, fontSize: 15 },\n rating: { alignItems: \"center\", gap: 6, paddingVertical: 8 },\n ratingTitle: { fontSize: 15, fontWeight: \"600\" },\n stars: { flexDirection: \"row\", gap: 8 },\n star: { fontSize: 30 },\n articleTitle: { fontSize: 22, fontWeight: \"700\" },\n loading: { marginTop: 40 },\n});\n","import { Fragment, useEffect, useMemo, useState } from \"react\";\nimport { Modal, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from \"react-native\";\nimport type { ResourceCenterAnnouncement, ResourceCenterArticle } from \"@guidelytech/shared\";\nimport { isArticleListed, resourceCenterSections } from \"@guidelytech/shared/runtime\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { CloseButton } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\n/**\n * Full-height sheet: \"What's new\", search, recommended guides, checklists, collections, links and FAQs,\n * in the order (and with the visibility) of the resource center's modules.\n */\nexport function ResourceCenter({ client, palette: p, open, topInset, bottomInset }: { client: GuidelyClient; palette: Palette; open: boolean; topInset: number; bottomInset: number }) {\n const rc = client.getResourceCenter();\n const [query, setQuery] = useState(\"\");\n const [results, setResults] = useState<ResourceCenterArticle[] | null>(null);\n const [article, setArticle] = useState<ResourceCenterArticle | null>(null);\n const [faq, setFaq] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setQuery(\"\");\n setResults(null);\n setArticle(null);\n }\n }, [open]);\n useEffect(() => {\n const q = query.trim();\n if (q.length < 2) {\n setResults(null);\n return;\n }\n let alive = true;\n const t = setTimeout(() => {\n void client.searchResourceCenter(q).then((r) => alive && setResults(r));\n }, 250);\n return () => {\n alive = false;\n clearTimeout(t);\n };\n }, [client, query]);\n\n const guides = client.getGuides();\n const recommended = useMemo(() => (rc?.recommendedGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind !== \"checklist\"), [rc, guides]);\n const checklists = useMemo(() => (rc?.checklistGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind === \"checklist\"), [rc, guides]);\n if (!rc) return null;\n\n const close = () => client.closeResourceCenter();\n const modules = client.getResourceCenterModules();\n const announcements = client.getAnnouncements();\n const openArticle = (a: ResourceCenterArticle) => {\n if (a.externalUrl) return client.navigate(a.externalUrl);\n client.articleViewed(a);\n setArticle(a);\n };\n const row = (key: string, title: string, subtitle: string | undefined, onPress: () => void, icon = \"›\") => (\n <Pressable key={key} accessibilityRole=\"button\" accessibilityLabel={title} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text style={[styles.rowTitle, { color: p.text, fontFamily: p.fontFamily }]}>{title}</Text>\n {subtitle ? (\n <Text style={[styles.rowSub, { color: p.muted }]} numberOfLines={2}>\n {subtitle}\n </Text>\n ) : null}\n </View>\n <Text style={[styles.chev, { color: p.muted }]}>{icon}</Text>\n </Pressable>\n );\n const section = (title: string, children: React.ReactNode) => (\n <View style={styles.section} key={title}>\n <Text accessibilityRole=\"header\" style={[styles.sectionTitle, { color: p.muted }]}>\n {title.toUpperCase()}\n </Text>\n {children}\n </View>\n );\n // Nested collections read as \"Billing › Invoices\"; targeted articles show only to their audiences.\n const audiences = client.getAudienceIds();\n const sections = resourceCenterSections(rc.collections, rc.articles, audiences);\n const listed = modules.includes(\"search\") ? results?.filter((a) => isArticleListed(rc.collections, a, audiences)) : undefined;\n const link = (label: string, onPress: () => void) => (\n <Pressable key={label} accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={8}>\n <Text style={[styles.link, { color: p.primary }]}>{label}</Text>\n </Pressable>\n );\n // \"What's new\" entries published since the last visit keep a \"New\" mark while the sheet is open.\n const announcement = (a: ResourceCenterAnnouncement) => {\n const linked = a.articleId ? rc.articles.find((x) => x.id === a.articleId) : undefined;\n const isNew = client.isAnnouncementNew(a);\n return (\n <View key={a.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <View style={styles.faqHead}>\n <Text accessibilityRole=\"header\" style={[styles.rowTitle, styles.flex, { color: p.text, fontFamily: p.fontFamily }]}>\n {a.title}\n </Text>\n {isNew ? <Text style={[styles.badge, { color: p.onPrimary, backgroundColor: p.primary }]}>NEW</Text> : null}\n </View>\n {a.body ? <RichText html={a.body} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n {a.guideId || linked || a.url ? (\n <View style={styles.links}>\n {a.guideId ? link(\"Show me\", () => (close(), client.startGuide(a.guideId as string))) : null}\n {linked ? link(\"Read more\", () => openArticle(linked)) : null}\n {a.url ? link(a.linkLabel || \"Learn more\", () => client.navigate(a.url as string)) : null}\n </View>\n ) : null}\n </View>\n );\n };\n const renderModule = (id: (typeof modules)[number]) => {\n switch (id) {\n case \"announcements\":\n return announcements.length ? section(\"What's new\", announcements.map(announcement)) : null;\n case \"guides\":\n return recommended.length ? section(\"Recommended\", recommended.map((g) => row(g.id, g.name, undefined, () => (close(), client.startGuide(g.id)), \"▶\"))) : null;\n case \"checklists\":\n return checklists.length ? section(\"Checklists\", checklists.map((g) => row(g.id, g.name, undefined, () => (close(), client.openChecklist(g.id)), \"☑\"))) : null;\n case \"articles\":\n return sections.map((s) => section(s.collection ? s.path.join(\" › \") : \"Articles\", s.articles.map((a) => row(a.id, a.title, a.summary, () => openArticle(a)))));\n case \"faqs\":\n return rc.faqs.length\n ? section(\n \"FAQ\",\n rc.faqs.map((f) => (\n <View key={f.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <Pressable accessibilityRole=\"button\" accessibilityState={{ expanded: faq === f.id }} onPress={() => setFaq(faq === f.id ? null : f.id)} style={styles.faqHead}>\n <Text style={[styles.rowTitle, styles.flex, { color: p.text }]}>{f.question}</Text>\n <Text style={[styles.chev, { color: p.muted }]}>{faq === f.id ? \"−\" : \"+\"}</Text>\n </Pressable>\n {faq === f.id ? <RichText html={f.answer} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n </View>\n )),\n )\n : null;\n case \"links\":\n return rc.links.length ? section(\"Links\", rc.links.map((l) => row(l.id, l.label, undefined, () => client.navigate(l.url), \"↗\"))) : null;\n default:\n return null; // \"search\" renders above the sections\n }\n };\n\n return (\n <Modal visible={open} animationType=\"slide\" presentationStyle={Platform.OS === \"ios\" ? \"pageSheet\" : \"fullScreen\"} onRequestClose={() => (article ? setArticle(null) : close())}>\n <View style={[styles.sheet, { backgroundColor: p.background, paddingTop: Platform.OS === \"ios\" ? 8 : topInset }]}>\n <View style={[styles.header, { borderColor: p.border }]}>\n {article ? (\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Back\" onPress={() => setArticle(null)} hitSlop={10}>\n <Text style={[styles.back, { color: p.primary }]}>‹ Back</Text>\n </Pressable>\n ) : null}\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]} numberOfLines={1}>\n {article ? \"\" : rc.title}\n </Text>\n <CloseButton palette={p} onPress={close} label=\"Close help\" />\n </View>\n {article ? (\n <ScrollView contentContainerStyle={[styles.content, { paddingBottom: bottomInset + 24 }]}>\n <Text accessibilityRole=\"header\" style={[styles.articleTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {article.title}\n </Text>\n <RichText html={article.body} palette={p} onLink={(u) => client.navigate(u)} />\n </ScrollView>\n ) : (\n <ScrollView contentContainerStyle={[styles.content, { paddingBottom: bottomInset + 24 }]} keyboardShouldPersistTaps=\"handled\">\n {modules.includes(\"search\") ? (\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search help articles\"\n placeholderTextColor={p.muted}\n accessibilityLabel=\"Search help articles\"\n clearButtonMode=\"while-editing\"\n returnKeyType=\"search\"\n style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]}\n />\n ) : null}\n {listed ? (\n section(\n `Results for “${query.trim()}”`,\n listed.length ? listed.map((a) => row(a.id, a.title, a.summary, () => openArticle(a))) : <Text style={[styles.rowSub, { color: p.muted }]}>No articles found.</Text>,\n )\n ) : (\n <>\n {modules.filter((id) => id !== \"search\").map((id) => (\n <Fragment key={id}>{renderModule(id)}</Fragment>\n ))}\n </>\n )}\n </ScrollView>\n )}\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n sheet: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\", gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: StyleSheet.hairlineWidth },\n back: { fontSize: 16, fontWeight: \"600\" },\n title: { flex: 1, fontSize: 18, fontWeight: \"700\" },\n content: { padding: 16, gap: 18 },\n search: { height: 42, paddingHorizontal: 12, fontSize: 15 },\n section: { gap: 8 },\n sectionTitle: { fontSize: 12, fontWeight: \"700\", letterSpacing: 0.6 },\n row: { flexDirection: \"row\", alignItems: \"center\", gap: 10, borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, paddingVertical: 12, paddingHorizontal: 12 },\n rowTitle: { fontSize: 15, fontWeight: \"600\" },\n rowSub: { fontSize: 13, marginTop: 2 },\n chev: { fontSize: 18 },\n faq: { flexDirection: \"column\", alignItems: \"stretch\" },\n faqHead: { flexDirection: \"row\", alignItems: \"center\", gap: 10 },\n articleTitle: { fontSize: 22, fontWeight: \"700\" },\n badge: { fontSize: 10, fontWeight: \"800\", letterSpacing: 0.5, paddingHorizontal: 6, paddingVertical: 2, borderRadius: 6, overflow: \"hidden\" },\n links: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 16, marginTop: 4 },\n link: { fontSize: 14, fontWeight: \"600\" },\n});\n","import { useEffect, useRef, useState } from \"react\";\nimport { AccessibilityInfo, Animated, Easing, Pressable, StyleSheet, View, type LayoutChangeEvent } from \"react-native\";\nimport { positionCard, type Insets, type Side } from \"../core/position\";\nimport type { Rect } from \"../core/targets\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { StepView } from \"../core/types\";\nimport { announcement, StepCard } from \"./StepCard\";\nimport type { Palette } from \"./theme\";\n\nexport interface LayerGeometry {\n /** Overlay origin in window coordinates (targets are measured in window coordinates). */\n origin: { x: number; y: number };\n viewport: { width: number; height: number };\n insets: Insets;\n}\n\n/** Tracks a target's frame (relative to the overlay) while a step is shown: layout changes, scrolling, rotation. */\nfunction useTargetRect(client: GuidelyClient, targetId: string | null, origin: { x: number; y: number }): Rect | null {\n const [rect, setRect] = useState<Rect | null>(null);\n useEffect(() => {\n if (!targetId) {\n setRect(null);\n return;\n }\n let alive = true;\n const measure = async () => {\n const r = await client.targets.measure(targetId);\n if (!alive) return;\n setRect((prev) => {\n const next = r ? { x: r.x - origin.x, y: r.y - origin.y, width: r.width, height: r.height } : null;\n if (prev && next && Math.abs(prev.x - next.x) < 0.5 && Math.abs(prev.y - next.y) < 0.5 && prev.width === next.width && prev.height === next.height) return prev;\n return next;\n });\n };\n void measure();\n const off = client.targets.onChange(() => void measure());\n const timer = setInterval(() => void measure(), 250);\n return () => {\n alive = false;\n off();\n clearInterval(timer);\n };\n }, [client, targetId, origin.x, origin.y]);\n return rect;\n}\n\nfunction useFadeIn(key: string) {\n const opacity = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n opacity.setValue(0);\n Animated.timing(opacity, { toValue: 1, duration: 160, easing: Easing.out(Easing.quad), useNativeDriver: true }).start();\n }, [key, opacity]);\n return opacity;\n}\n\nexport function StepLayer({ view, client, palette: p, geometry }: { view: StepView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry }) {\n const { step } = view;\n const rect = useTargetRect(client, view.asModal ? null : view.targetId, geometry.origin);\n const opacity = useFadeIn(view.key);\n const { viewport, insets } = geometry;\n const cardWidth = Math.min(viewport.width - 32, step.width ?? 340);\n\n useEffect(() => {\n if (step.type === \"hotspot\" && !view.expanded) return;\n AccessibilityInfo.announceForAccessibility?.(announcement(view));\n }, [view.key, view.expanded]);\n\n const backdrop = (children?: React.ReactNode) => (\n <Pressable accessible={false} style={[StyleSheet.absoluteFill, { backgroundColor: p.overlay }]} onPress={() => client.backdropPressed(view.guide.id)}>\n {children}\n </Pressable>\n );\n\n // Modal-like: real modals, steps whose target is missing (fallback), and step types without an anchor.\n const anchored = !view.asModal && [\"tooltip\", \"popover\", \"spotlight\", \"hotspot\"].includes(step.type);\n if (!anchored && step.type === \"banner\") {\n const top = step.position.startsWith(\"top\");\n return (\n <Animated.View pointerEvents=\"box-none\" style={[styles.banner, top ? { top: insets.top + 8 } : { bottom: insets.bottom + 8 }, { left: insets.left + 8, right: insets.right + 8, opacity }]}>\n <StepCard view={view} client={client} palette={p} width={viewport.width - insets.left - insets.right - 16} compact />\n </Animated.View>\n );\n }\n if (!anchored && step.type === \"slideout\") {\n const wide = viewport.width >= 600;\n const right = !step.position.endsWith(\"left\");\n const width = wide ? Math.min(380, cardWidth) : viewport.width - insets.left - insets.right - 24;\n return (\n <Animated.View pointerEvents=\"box-none\" style={[styles.abs, { bottom: insets.bottom + 12, opacity }, wide ? (right ? { right: insets.right + 16 } : { left: insets.left + 16 }) : { left: insets.left + 12 }]}>\n <StepCard view={view} client={client} palette={p} width={width} />\n </Animated.View>\n );\n }\n if (!anchored) {\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, styles.center, { opacity }]}>\n {step.showOverlay ? backdrop() : null}\n <StepCard view={view} client={client} palette={p} width={Math.min(viewport.width - 40, step.width ?? 360)} />\n </Animated.View>\n );\n }\n if (!rect) return null;\n\n if (step.type === \"hotspot\") {\n const size = step.hotspot?.size ?? 14;\n return (\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n <Hotspot x={rect.x + rect.width - size / 2} y={rect.y - size / 2} size={size} pulse={step.hotspot?.pulse ?? true} color={p.primary} onPress={() => client.toggleHotspot(view.guide.id)} label={step.title || \"Show tip\"} />\n {view.expanded ? <Anchored view={view} client={client} palette={p} geometry={geometry} rect={rect} width={cardWidth} /> : null}\n </View>\n );\n }\n\n if (step.type === \"spotlight\") {\n const pad = step.spotlightPadding;\n const hole = { x: rect.x - pad, y: rect.y - pad, width: rect.width + pad * 2, height: rect.height + pad * 2 };\n const r = Math.max(0, Math.min(12, p.radius, hole.width / 2, hole.height / 2));\n const shade = { backgroundColor: p.overlay };\n const press = () => client.backdropPressed(view.guide.id);\n // Corner pieces dim what lies inside the hole's rectangle but outside its rounded corners.\n const corners: Array<[number, number, number, number]> = [\n [hole.x, hole.y, -r, -r],\n [hole.x + hole.width - r, hole.y, -2 * r, -r],\n [hole.x, hole.y + hole.height - r, -r, -2 * r],\n [hole.x + hole.width - r, hole.y + hole.height - r, -2 * r, -2 * r],\n ];\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { opacity }]}>\n {/* Four panes around the hole: the highlighted element itself stays tappable. */}\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, right: 0, top: 0, height: Math.max(0, hole.y) }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, right: 0, top: hole.y + hole.height, bottom: 0 }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, width: Math.max(0, hole.x), top: hole.y, height: hole.height }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: hole.x + hole.width, right: 0, top: hole.y, height: hole.height }]} />\n {r > 0\n ? corners.map(([left, top, dx, dy], i) => (\n <View key={i} pointerEvents=\"none\" style={[styles.abs, { left, top, width: r, height: r, overflow: \"hidden\" }]}>\n <View style={[styles.abs, { left: dx, top: dy, width: 4 * r, height: 4 * r, borderRadius: 2 * r, borderWidth: r, borderColor: p.overlay }]} />\n </View>\n ))\n : null}\n <View pointerEvents=\"none\" style={[styles.abs, { left: hole.x, top: hole.y, width: hole.width, height: hole.height, borderRadius: r, borderWidth: 2, borderColor: p.primary }]} />\n <Anchored view={view} client={client} palette={p} geometry={geometry} rect={hole} width={cardWidth} />\n </Animated.View>\n );\n }\n\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { opacity }]}>\n {step.showOverlay ? backdrop() : null}\n <Anchored view={view} client={client} palette={p} geometry={geometry} rect={rect} width={cardWidth} />\n </Animated.View>\n );\n}\n\nconst ARROW = 12;\n\n/** A card placed next to `rect` with an arrow pointing at it. */\nfunction Anchored({ view, client, palette: p, geometry, rect, width }: { view: StepView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry; rect: Rect; width: number }) {\n const [height, setHeight] = useState(0);\n const onLayout = (e: LayoutChangeEvent) => setHeight(Math.round(e.nativeEvent.layout.height));\n const offset = view.step.offset + ARROW / 2;\n const pos = positionCard(rect, { width, height: height || 120 }, geometry.viewport, geometry.insets, view.step.placement, offset);\n return (\n <View pointerEvents=\"box-none\" style={[styles.abs, { left: pos.x, top: pos.y, width, opacity: height ? 1 : 0 }]} onLayout={onLayout}>\n <Arrow side={pos.side} at={pos.arrow} color={p.background} border={p.border} />\n <StepCard view={view} client={client} palette={p} width={width} />\n </View>\n );\n}\n\nfunction Arrow({ side, at, color, border }: { side: Side; at: number; color: string; border: string }) {\n const half = ARROW / 2;\n const place =\n side === \"bottom\" ? { top: -half, left: at - half } : side === \"top\" ? { bottom: -half, left: at - half } : side === \"right\" ? { left: -half, top: at - half } : { right: -half, top: at - half };\n return <View pointerEvents=\"none\" style={[styles.abs, styles.arrow, place, { backgroundColor: color, borderColor: border }]} />;\n}\n\nfunction Hotspot({ x, y, size, pulse, color, onPress, label }: { x: number; y: number; size: number; pulse: boolean; color: string; onPress: () => void; label: string }) {\n const scale = useRef(new Animated.Value(0)).current;\n const [reduceMotion, setReduceMotion] = useState(false);\n useEffect(() => {\n let alive = true;\n AccessibilityInfo.isReduceMotionEnabled?.().then((v) => alive && setReduceMotion(v), () => {});\n return () => {\n alive = false;\n };\n }, []);\n useEffect(() => {\n if (!pulse || reduceMotion) return;\n const loop = Animated.loop(Animated.timing(scale, { toValue: 1, duration: 1400, easing: Easing.out(Easing.ease), useNativeDriver: true }));\n loop.start();\n return () => loop.stop();\n }, [pulse, reduceMotion, scale]);\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={14} style={[styles.abs, { left: x, top: y, width: size, height: size }]}>\n {pulse && !reduceMotion ? (\n <Animated.View\n pointerEvents=\"none\"\n style={[styles.abs, { width: size, height: size, borderRadius: size / 2, backgroundColor: color, opacity: scale.interpolate({ inputRange: [0, 1], outputRange: [0.55, 0] }), transform: [{ scale: scale.interpolate({ inputRange: [0, 1], outputRange: [1, 2.6] }) }] }]}\n />\n ) : null}\n <View style={{ width: size, height: size, borderRadius: size / 2, backgroundColor: color, borderWidth: 2, borderColor: \"#ffffff\" }} />\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create({\n abs: { position: \"absolute\" },\n center: { alignItems: \"center\", justifyContent: \"center\" },\n banner: { position: \"absolute\" },\n arrow: { width: ARROW, height: ARROW, transform: [{ rotate: \"45deg\" }], borderWidth: StyleSheet.hairlineWidth },\n});\n","import type { Placement } from \"@guidelytech/shared\";\nimport type { Rect } from \"./targets\";\n\nexport type Side = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface Insets {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\nexport interface CardPosition {\n x: number;\n y: number;\n side: Side;\n /** Arrow centre along the card edge facing the target (px from the card's left/top). */\n arrow: number;\n}\n\nconst MARGIN = 12;\nconst ARROW_INSET = 18;\n\nconst opposite: Record<Side, Side> = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" };\n\n/**\n * Places a card of `size` next to `target` inside `viewport` minus `insets`, honouring the step's\n * placement when it fits and flipping (then falling back to below/above) when it does not.\n */\nexport function positionCard(target: Rect, size: { width: number; height: number }, viewport: { width: number; height: number }, insets: Insets, placement: Placement, offset: number): CardPosition {\n const [rawSide, align] = placement.split(\"-\") as [Side | \"auto\", \"start\" | \"end\" | undefined];\n const fits = (side: Side) => {\n switch (side) {\n case \"bottom\":\n return target.y + target.height + offset + size.height <= viewport.height - insets.bottom - MARGIN;\n case \"top\":\n return target.y - offset - size.height >= insets.top + MARGIN;\n case \"right\":\n return target.x + target.width + offset + size.width <= viewport.width - insets.right - MARGIN;\n case \"left\":\n return target.x - offset - size.width >= insets.left + MARGIN;\n }\n };\n const order: Side[] = rawSide === \"auto\" ? [\"bottom\", \"top\"] : [rawSide, opposite[rawSide], \"bottom\", \"top\"];\n const space = { top: target.y - insets.top, bottom: viewport.height - insets.bottom - (target.y + target.height) };\n const side = order.find(fits) ?? (space.bottom >= space.top ? \"bottom\" : \"top\");\n\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n if (side === \"top\" || side === \"bottom\") {\n const cx = target.x + target.width / 2;\n let x = align === \"start\" ? target.x : align === \"end\" ? target.x + target.width - size.width : cx - size.width / 2;\n x = clamp(x, insets.left + MARGIN, Math.max(insets.left + MARGIN, viewport.width - insets.right - MARGIN - size.width));\n let y = side === \"bottom\" ? target.y + target.height + offset : target.y - offset - size.height;\n y = clamp(y, insets.top + MARGIN, Math.max(insets.top + MARGIN, viewport.height - insets.bottom - MARGIN - size.height));\n return { x, y, side, arrow: clamp(cx - x, ARROW_INSET, size.width - ARROW_INSET) };\n }\n const cy = target.y + target.height / 2;\n let y = align === \"start\" ? target.y : align === \"end\" ? target.y + target.height - size.height : cy - size.height / 2;\n y = clamp(y, insets.top + MARGIN, Math.max(insets.top + MARGIN, viewport.height - insets.bottom - MARGIN - size.height));\n const x = side === \"right\" ? target.x + target.width + offset : target.x - offset - size.width;\n return { x, y, side, arrow: clamp(cy - y, ARROW_INSET, size.height - ARROW_INSET) };\n}\n","import { Image, StyleSheet, Text, View, type StyleProp, type ViewStyle } from \"react-native\";\nimport { htmlToText } from \"../core/html\";\nimport { visibleButtons } from \"../core/controller\";\nimport type { StepView } from \"../core/types\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\n/** Title, image, rich-text body, progress, close and buttons for one step. */\nexport function StepCard({ view, client, palette: p, width, style, compact }: { view: StepView; client: GuidelyClient; palette: Palette; width: number; style?: StyleProp<ViewStyle>; compact?: boolean }) {\n const { step, guide } = view;\n const buttons = visibleButtons(step, view.canGoBack);\n // Custom HTML steps have no chrome on the web; on mobile they become a plain card.\n const body = step.type === \"custom\" ? step.customHtml || step.body : step.body;\n const showProgress = step.showProgress && view.total > 1;\n const onLink = (url: string) => client.navigate(url);\n return (\n <Surface palette={p} style={[{ width }, style]}>\n <View accessible={false} accessibilityViewIsModal={view.asModal || step.type === \"modal\"} style={compact ? styles.compact : styles.inner}>\n {step.imageUrl ? (\n // An empty description marks the image as decorative: screen readers skip it.\n <Image\n source={{ uri: step.imageUrl }}\n style={[styles.image, { borderRadius: Math.max(0, p.radius - 4) }]}\n resizeMode=\"cover\"\n accessibilityIgnoresInvertColors\n {...(step.imageAlt?.trim() ? { accessible: true, accessibilityRole: \"image\" as const, accessibilityLabel: step.imageAlt.trim() } : { accessible: false, importantForAccessibility: \"no\" as const })}\n />\n ) : null}\n {step.title ? (\n <View style={styles.header}>\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {step.title}\n </Text>\n {step.showClose ? <CloseButton palette={p} onPress={() => client.closeStep(guide.id)} label=\"Dismiss guide\" /> : null}\n </View>\n ) : null}\n {body ? (\n // Without a title the close button floats beside the body instead of taking a row.\n <View style={!step.title && step.showClose ? styles.bodyBesideClose : undefined}>\n <RichText html={body} palette={p} onLink={onLink} />\n </View>\n ) : null}\n {!step.title && step.showClose ? (\n <View style={compact ? styles.floatingCloseCompact : styles.floatingClose}>\n <CloseButton palette={p} onPress={() => client.closeStep(guide.id)} label=\"Dismiss guide\" />\n </View>\n ) : null}\n {showProgress || buttons.length ? (\n <View style={styles.footer}>\n {showProgress ? (\n <Text style={[styles.progress, { color: p.muted }]} accessibilityLabel={`Step ${view.index + 1} of ${view.total}`}>\n {view.index + 1} of {view.total}\n </Text>\n ) : (\n <View style={styles.flex} />\n )}\n <View style={styles.buttons}>\n {buttons.map((b) => (\n <GButton key={b.id} label={b.label} variant={b.variant} palette={p} onPress={() => client.pressButton(guide.id, b)} />\n ))}\n </View>\n </View>\n ) : null}\n </View>\n </Surface>\n );\n}\n\n/** Text read by screen readers when a step appears. */\nexport function announcement(view: StepView): string {\n const parts = [view.step.title, htmlToText(view.step.body)].filter(Boolean);\n if (view.total > 1) parts.push(`Step ${view.index + 1} of ${view.total}`);\n return parts.join(\". \");\n}\n\nconst styles = StyleSheet.create({\n inner: { padding: 16, gap: 10 },\n compact: { paddingHorizontal: 14, paddingVertical: 10, gap: 6 },\n image: { width: \"100%\", height: 140, marginBottom: 2 },\n header: { flexDirection: \"row\", alignItems: \"flex-start\", gap: 8 },\n title: { flex: 1, fontSize: 17, fontWeight: \"700\", lineHeight: 22 },\n flex: { flex: 1 },\n bodyBesideClose: { paddingRight: 24 },\n floatingClose: { position: \"absolute\", top: 16, right: 16 },\n floatingCloseCompact: { position: \"absolute\", top: 10, right: 14 },\n footer: { flexDirection: \"row\", alignItems: \"center\", gap: 8, marginTop: 4, flexWrap: \"wrap\" },\n progress: { flex: 1, fontSize: 12, fontWeight: \"500\" },\n buttons: { flexDirection: \"row\", gap: 8, flexWrap: \"wrap\", justifyContent: \"flex-end\" },\n});\n","import { useEffect, useState } from \"react\";\nimport {\n AccessibilityInfo,\n KeyboardAvoidingView,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n Text,\n TextInput,\n View,\n} from \"react-native\";\nimport { isQuestionVisible, type SurveyAnswers } from \"@guidelytech/shared/runtime\";\nimport type { SurveyQuestion } from \"@guidelytech/shared\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { SurveyView } from \"../core/types\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { LayerGeometry } from \"./StepLayer\";\nimport type { Palette } from \"./theme\";\n\n/** Survey card: every visible question at once (like the web SDK), required checks, thank-you state. */\nexport function Survey({\n view,\n client,\n palette: p,\n geometry,\n}: {\n view: SurveyView;\n client: GuidelyClient;\n palette: Palette;\n geometry: LayerGeometry;\n}) {\n const config = view.guide.config.survey;\n const [answers, setAnswers] = useState<SurveyAnswers>({});\n const [error, setError] = useState(\"\");\n useEffect(() => {\n setAnswers({});\n setError(\"\");\n AccessibilityInfo.announceForAccessibility?.(\n `Survey: ${config?.questions[0]?.title ?? view.guide.name}`,\n );\n }, [view.key]);\n if (!config) return null;\n const { insets, viewport } = geometry;\n const width = Math.min(viewport.width - insets.left - insets.right - 24, 420);\n const centered = config.position === \"center\";\n\n const set = (id: string, value: SurveyAnswers[string] | undefined) =>\n setAnswers((prev) => {\n const next = { ...prev };\n if (value === undefined) delete next[id];\n else next[id] = value;\n // Hidden follow-ups lose their answers, as on the web.\n for (const q of config.questions)\n if (!isQuestionVisible(q, next) && next[q.id] !== undefined) delete next[q.id];\n return next;\n });\n const submit = () => {\n const missing = config.questions.filter(\n (q) => q.required && isQuestionVisible(q, answers) && answers[q.id] === undefined,\n );\n if (missing.length) {\n setError(`Please answer: ${missing.map((q) => q.title).join(\", \")}`);\n return;\n }\n setError(\"\");\n client.submitSurvey(view.guide.id, { ...answers });\n };\n const close = () => client.closeSurvey(view.guide.id);\n\n return (\n // KeyboardAvoidingView owns its bottom padding, so the safe-area padding lives on an inner view.\n <KeyboardAvoidingView\n pointerEvents=\"box-none\"\n behavior={Platform.OS === \"ios\" ? \"padding\" : undefined}\n style={StyleSheet.absoluteFill}\n >\n {centered ? (\n <Pressable\n accessible={false}\n style={[StyleSheet.absoluteFill, { backgroundColor: p.overlay }]}\n onPress={close}\n />\n ) : null}\n <View\n pointerEvents=\"box-none\"\n style={[\n styles.fill,\n centered ? styles.center : styles.bottom,\n !centered && { paddingBottom: insets.bottom + 12 },\n ]}\n >\n <Surface\n palette={p}\n style={{ width, maxHeight: viewport.height - insets.top - insets.bottom - 40 }}\n >\n {view.submitted ? (\n <View style={styles.inner}>\n <Text\n accessibilityRole=\"header\"\n style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}\n >\n {config.thankYouTitle}\n </Text>\n {config.thankYouBody ? (\n <RichText\n html={config.thankYouBody}\n palette={p}\n onLink={(u) => client.navigate(u)}\n />\n ) : null}\n <GButton label=\"Done\" palette={p} onPress={close} style={styles.end} />\n </View>\n ) : (\n <ScrollView contentContainerStyle={styles.inner} keyboardShouldPersistTaps=\"handled\">\n {config.questions\n .filter((q) => isQuestionVisible(q, answers))\n .map((q, i) => (\n <View key={q.id} style={styles.question}>\n <View style={styles.head}>\n <Text style={[styles.qTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {q.title}\n {!q.required ? (\n <Text style={{ color: p.muted, fontWeight: \"400\" }}> (optional)</Text>\n ) : null}\n </Text>\n {i === 0 ? (\n <CloseButton palette={p} onPress={close} label=\"Dismiss survey\" />\n ) : null}\n </View>\n {q.description ? (\n <Text style={[styles.desc, { color: p.muted }]}>{q.description}</Text>\n ) : null}\n <QuestionInput\n q={q}\n value={answers[q.id]}\n onChange={(v) => set(q.id, v)}\n palette={p}\n />\n </View>\n ))}\n {error ? (\n <Text accessibilityLiveRegion=\"polite\" style={[styles.error]}>\n {error}\n </Text>\n ) : null}\n <GButton label=\"Submit\" palette={p} onPress={submit} style={styles.end} />\n </ScrollView>\n )}\n </Surface>\n </View>\n </KeyboardAvoidingView>\n );\n}\n\nfunction QuestionInput({\n q,\n value,\n onChange,\n palette: p,\n}: {\n q: SurveyQuestion;\n value: SurveyAnswers[string] | undefined;\n onChange: (v: SurveyAnswers[string] | undefined) => void;\n palette: Palette;\n}) {\n const chip = (selected: boolean) => [\n styles.chip,\n {\n borderColor: selected ? p.primary : p.border,\n backgroundColor: selected ? p.primary : p.background,\n borderRadius: Math.min(8, p.radius),\n },\n ];\n const chipText = (selected: boolean) => [\n styles.chipText,\n { color: selected ? p.onPrimary : p.text },\n ];\n switch (q.type) {\n case \"nps\":\n case \"csat\": {\n const min = q.type === \"nps\" ? 0 : 1;\n const max = q.type === \"nps\" ? 10 : (q.scaleMax ?? 5);\n const values = Array.from({ length: max - min + 1 }, (_, i) => min + i);\n return (\n <View>\n <View style={styles.scale} accessibilityRole=\"radiogroup\" accessibilityLabel={q.title}>\n {values.map((n) => (\n <Pressable\n key={n}\n accessibilityRole=\"radio\"\n accessibilityState={{ selected: value === n }}\n accessibilityLabel={String(n)}\n onPress={() => onChange(n)}\n style={[...chip(value === n), styles.scaleItem]}\n >\n <Text style={chipText(value === n)}>{n}</Text>\n </Pressable>\n ))}\n </View>\n {q.lowLabel || q.highLabel ? (\n <View style={styles.labels}>\n <Text style={[styles.small, { color: p.muted }]}>{q.lowLabel}</Text>\n <Text style={[styles.small, { color: p.muted }]}>{q.highLabel}</Text>\n </View>\n ) : null}\n </View>\n );\n }\n case \"rating\": {\n const max = q.scaleMax ?? 5;\n return (\n <View style={styles.stars} accessibilityRole=\"radiogroup\" accessibilityLabel={q.title}>\n {Array.from({ length: max }, (_, i) => i + 1).map((n) => (\n <Pressable\n key={n}\n accessibilityRole=\"radio\"\n accessibilityLabel={`${n} of ${max}`}\n accessibilityState={{ selected: value === n }}\n onPress={() => onChange(n)}\n hitSlop={4}\n >\n <Text\n style={[\n styles.star,\n { color: typeof value === \"number\" && n <= value ? p.primary : p.border },\n ]}\n >\n ★\n </Text>\n </Pressable>\n ))}\n </View>\n );\n }\n case \"thumbs\":\n return (\n <View style={styles.row} accessibilityRole=\"radiogroup\">\n {[\n [true, \"👍\", \"Thumbs up\"],\n [false, \"👎\", \"Thumbs down\"],\n ].map(([val, icon, label]) => (\n <Pressable\n key={String(val)}\n accessibilityRole=\"radio\"\n accessibilityLabel={label as string}\n accessibilityState={{ selected: value === val }}\n onPress={() => onChange(val as boolean)}\n style={[...chip(value === val), styles.thumb]}\n >\n <Text style={styles.thumbText}>{icon as string}</Text>\n </Pressable>\n ))}\n </View>\n );\n case \"single_choice\":\n case \"multiple_choice\": {\n const multi = q.type === \"multiple_choice\";\n const selected = new Set(\n multi\n ? ((value as string[] | undefined) ?? [])\n : value !== undefined\n ? [String(value)]\n : [],\n );\n return (\n <View style={styles.choices}>\n {q.options.map((o) => {\n const on = selected.has(o.id);\n return (\n <Pressable\n key={o.id}\n accessibilityRole={multi ? \"checkbox\" : \"radio\"}\n accessibilityState={{ checked: on }}\n accessibilityLabel={o.label}\n onPress={() => {\n if (!multi) return onChange(o.id);\n const next = new Set(selected);\n if (on) next.delete(o.id);\n else next.add(o.id);\n onChange(next.size ? Array.from(next) : undefined);\n }}\n style={[\n styles.choice,\n { borderColor: on ? p.primary : p.border, borderRadius: Math.min(10, p.radius) },\n ]}\n >\n <View\n style={[\n styles.dot,\n multi && styles.box,\n {\n borderColor: on ? p.primary : p.border,\n backgroundColor: on ? p.primary : \"transparent\",\n },\n ]}\n />\n <Text style={[styles.choiceText, { color: p.text }]}>{o.label}</Text>\n </Pressable>\n );\n })}\n </View>\n );\n }\n case \"text\":\n default:\n return (\n <TextInput\n accessibilityLabel={q.title}\n multiline\n value={typeof value === \"string\" ? value : \"\"}\n onChangeText={(t) => onChange(t ? t.slice(0, 5000) : undefined)}\n placeholder={q.placeholder || \"\"}\n placeholderTextColor={p.muted}\n style={[\n styles.input,\n {\n color: p.text,\n borderColor: p.border,\n borderRadius: Math.min(10, p.radius),\n backgroundColor: p.surface,\n },\n ]}\n />\n );\n }\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n center: { alignItems: \"center\", justifyContent: \"center\" },\n bottom: { alignItems: \"center\", justifyContent: \"flex-end\" },\n inner: { padding: 16, gap: 14 },\n title: { fontSize: 17, fontWeight: \"700\" },\n end: { alignSelf: \"flex-end\" },\n question: { gap: 8 },\n head: { flexDirection: \"row\", gap: 8, alignItems: \"flex-start\" },\n qTitle: { flex: 1, fontSize: 15, fontWeight: \"600\", lineHeight: 20 },\n desc: { fontSize: 13 },\n scale: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 },\n scaleItem: { flexGrow: 1, flexBasis: 26 },\n chip: {\n borderWidth: 1,\n minHeight: 36,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: 4,\n },\n chipText: { fontSize: 14, fontWeight: \"600\" },\n labels: { flexDirection: \"row\", justifyContent: \"space-between\", marginTop: 4 },\n small: { fontSize: 12 },\n stars: { flexDirection: \"row\", gap: 6 },\n star: { fontSize: 30 },\n row: { flexDirection: \"row\", gap: 10 },\n thumb: { width: 56, height: 44 },\n thumbText: { fontSize: 22 },\n choices: { gap: 8 },\n choice: {\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n borderWidth: 1,\n paddingVertical: 10,\n paddingHorizontal: 12,\n },\n dot: { width: 18, height: 18, borderRadius: 9, borderWidth: 2 },\n box: { borderRadius: 4 },\n choiceText: { fontSize: 15, flex: 1 },\n input: { minHeight: 80, borderWidth: 1, padding: 10, fontSize: 15, textAlignVertical: \"top\" },\n error: { color: \"#dc2626\", fontSize: 13 },\n});\n","import type { ProjectTheme } from \"@guidelytech/shared\";\n\nexport interface Palette {\n primary: string;\n onPrimary: string;\n background: string;\n text: string;\n muted: string;\n border: string;\n surface: string;\n radius: number;\n overlay: string;\n fontFamily?: string;\n}\n\nconst DARK = { background: \"#18181b\", text: \"#f4f4f5\", muted: \"#a1a1aa\", border: \"#3f3f46\", surface: \"#27272a\" };\n\nfunction luminance(hex: string): number {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex);\n if (!m) return 1;\n const n = parseInt(m[1] as string, 16);\n const ch = [(n >> 16) & 255, (n >> 8) & 255, n & 255].map((c) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * (ch[0] as number) + 0.7152 * (ch[1] as number) + 0.0722 * (ch[2] as number);\n}\n\nfunction mix(hex: string, alpha: number): string {\n const a = Math.round(Math.max(0, Math.min(1, alpha)) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return /^#[0-9a-f]{6}$/i.test(hex) ? `${hex}${a}` : hex;\n}\n\n/** RN only understands a few system font names; web font stacks like \"Inter, system-ui\" are ignored. */\nfunction nativeFont(stack?: string): string | undefined {\n const first = stack?.split(\",\")[0]?.trim().replace(/^[\"']|[\"']$/g, \"\");\n if (!first || /^(system-ui|-apple-system|sans-serif|serif|monospace|inter|ui-sans-serif)$/i.test(first)) return undefined;\n return first;\n}\n\n/**\n * Colours for guide UI. The project theme is designed for light backgrounds; `dark` (or `auto` with a\n * dark system scheme) swaps background/text unless the guide set explicit colours.\n */\nexport function palette(theme: Partial<ProjectTheme> & { dark?: \"light\" | \"dark\" | \"auto\"; overlayOpacity?: number }, systemScheme: string | null | undefined, explicit?: { backgroundColor?: string; textColor?: string }): Palette {\n const primary = theme.primaryColor ?? \"#4f46e5\";\n const wantsDark = theme.dark === \"dark\" || (theme.dark === \"auto\" && systemScheme === \"dark\");\n const dark = wantsDark && !explicit?.backgroundColor;\n const background = dark ? DARK.background : (theme.backgroundColor ?? \"#ffffff\");\n const text = dark ? DARK.text : (theme.textColor ?? \"#111827\");\n return {\n primary,\n onPrimary: luminance(primary) > 0.45 ? \"#111827\" : \"#ffffff\",\n background,\n text,\n muted: dark ? DARK.muted : mix(text, 0.65),\n border: dark ? DARK.border : mix(text, 0.12),\n surface: dark ? DARK.surface : mix(text, 0.05),\n radius: theme.borderRadius ?? 12,\n overlay: `rgba(15, 23, 42, ${theme.overlayOpacity ?? 0.55})`,\n fontFamily: nativeFont(theme.fontFamily),\n };\n}\n","import { createContext, useCallback, useContext, useEffect, useRef, type ReactNode } from \"react\";\nimport { View, type GestureResponderEvent, type LayoutChangeEvent, type StyleProp, type ViewProps, type ViewStyle } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\n\nexport const GuidelyContext = createContext<GuidelyClient | null>(null);\n\n/** Name of the screen a subtree belongs to; see {@link GuidelyScreenScope}. */\nexport const GuidelyScreenContext = createContext<string | null>(null);\n\n/**\n * Declares which screen its children are on, so targets on screens that are mounted but not\n * visible (inactive tabs, screens under a stack) are never used. `name` must match what you pass\n * to `screen()`. With React Navigation, use {@link guidelyScreenLayout} instead of wrapping by hand.\n */\nexport function GuidelyScreenScope({ name, children }: { name: string; children?: ReactNode }) {\n return <GuidelyScreenContext.Provider value={name}>{children}</GuidelyScreenContext.Provider>;\n}\n\n/**\n * React Navigation 7 `screenLayout`: scopes every screen of a navigator to its route name.\n * `<Tab.Navigator screenLayout={guidelyScreenLayout}>`.\n */\nexport function guidelyScreenLayout({ route, children }: { route: { name: string }; children: ReactNode }) {\n return <GuidelyScreenScope name={route.name}>{children}</GuidelyScreenScope>;\n}\n\nconst TAP_SLOP = 10;\n\n/**\n * Props to spread on an existing view so guides can point at it, without adding a wrapper:\n * `const target = useGuidelyTarget(\"new-deal-button\"); <Pressable {...target}>…</Pressable>`.\n * Taps are observed, never intercepted.\n */\nexport function useGuidelyTarget(id: string) {\n const client = useContext(GuidelyContext);\n const screen = useContext(GuidelyScreenContext);\n const ref = useRef<View>(null);\n const start = useRef<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!client || !id) return;\n return client.targets.register(id, {\n screen,\n measure: () =>\n new Promise((resolve) => {\n const node = ref.current;\n if (!node || typeof node.measureInWindow !== \"function\") return resolve(null);\n node.measureInWindow((x, y, width, height) => resolve(Number.isFinite(x) ? { x, y, width, height } : null));\n }),\n });\n }, [client, id, screen]);\n\n const onLayout = useCallback(() => client?.targets.changed(), [client]);\n const onTouchStart = useCallback((e: GestureResponderEvent) => {\n start.current = { x: e.nativeEvent.pageX, y: e.nativeEvent.pageY };\n }, []);\n const onTouchEnd = useCallback(\n (e: GestureResponderEvent) => {\n const s = start.current;\n start.current = null;\n // A drag or scroll that happens to end on the view is not a tap.\n if (s && Math.abs(e.nativeEvent.pageX - s.x) < TAP_SLOP && Math.abs(e.nativeEvent.pageY - s.y) < TAP_SLOP) client?.targets.tapped(id);\n },\n [client, id],\n );\n return { ref, collapsable: false as const, onLayout, onTouchStart, onTouchEnd };\n}\n\nexport interface GuidelyTargetProps extends ViewProps {\n /** The Guidely id guides use to find this view (`data-guidely-id` on the web). */\n id: string;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Marks a view as a guide target. Wraps children in a `View`; give it `style={{ alignSelf: \"flex-start\" }}`\n * (or use {@link useGuidelyTarget}) when the wrapper should not stretch to its parent's width.\n */\nexport function GuidelyTarget({ id, children, onLayout, onTouchStart, onTouchEnd, ...rest }: GuidelyTargetProps) {\n const t = useGuidelyTarget(id);\n return (\n <View\n {...rest}\n ref={t.ref}\n collapsable={false}\n onLayout={(e: LayoutChangeEvent) => {\n t.onLayout();\n onLayout?.(e);\n }}\n onTouchStart={(e) => {\n t.onTouchStart(e);\n onTouchStart?.(e);\n }}\n onTouchEnd={(e) => {\n t.onTouchEnd(e);\n onTouchEnd?.(e);\n }}\n >\n {children}\n </View>\n );\n}\n"],"mappings":"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","names":["import_react","import_react_native","import_flags","attr","str","has","missing","__publicField","__publicField","import_flags","clamp","text","STREAM_RESPONSE_TIMEOUT_MS","STREAM_IDLE_TIMEOUT_MS","text","rec","text","import_react","import_react_native","text","import_react","import_react_native","import_react_native","import_react_native","import_jsx_runtime","import_react","import_react_native","text","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_react_native","import_jsx_runtime","styles","text","import_react","import_react_native","import_jsx_runtime","styles","announcement","import_react","import_react_native","side","clamp","x","y","import_react_native","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_react_native","import_jsx_runtime","missing","styles","text","import_jsx_runtime","styles","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","TAP_SLOP","import_flags","import_jsx_runtime","styles"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/flags.tsx","../../shared/src/utils.ts","../../shared/src/platform.ts","../../shared/src/widgets.ts","../../shared/src/targeting-eval.ts","../../shared/src/contrast.ts","../../shared/src/events-util.ts","../../shared/src/errors.ts","../../shared/src/complaints-limits.ts","../../shared/src/agents-limits.ts","../../shared/src/network.ts","../../shared/src/media.ts","../../shared/src/resource-center.ts","../../shared/src/howto-limits.ts","../../shared/src/page.ts","../../shared/src/tagging.ts","../../shared/src/localization.ts","../../shared/src/guide-experiments.ts","../../shared/src/custom-css.ts","../../sdk-core/src/health.ts","../../sdk-core/src/http.ts","../../sdk-core/src/storage.ts","../../sdk-core/src/queue.ts","../../sdk-core/src/outbox.ts","../../sdk-core/src/emitter.ts","../../sdk-core/src/frequency.ts","../src/core/client.ts","../src/core/launcherPlacement.ts","../src/core/autocapture.ts","../src/core/targets.ts","../src/core/controller.ts","../src/core/messenger.ts","../src/core/replay.ts","../src/core/storage.ts","../src/core/device.ts","../src/ui/Autocapture.tsx","../src/core/viewTree.ts","../src/ui/Overlay.tsx","../src/ui/Checklist.tsx","../src/ui/primitives.tsx","../src/ui/RichText.tsx","../src/core/html.ts","../src/ui/Messenger.tsx","../src/ui/ResourceCenter.tsx","../src/ui/StepLayer.tsx","../src/core/position.ts","../src/ui/StepCard.tsx","../src/ui/Survey.tsx","../src/ui/theme.ts","../src/ui/Target.tsx"],"sourcesContent":["/**\n * @guidelytech/react-native — Guidely guides, checklists, surveys and resource center for React\n * Native and Expo apps, rendered with native components.\n *\n * ```tsx\n * <GuidelyProvider projectId=\"pk_prod_…\" apiUrl=\"https://guidelytech.com\" storage={AsyncStorage}>\n * <App />\n * </GuidelyProvider>\n * ```\n */\nimport { useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { AppState, Dimensions, Linking, NativeModules, Platform, StyleSheet, View, type ViewProps } from \"react-native\";\nimport type { PublishedGuide } from \"@guidelytech/shared\";\nimport { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\nimport { GuidelyClient, type PlatformBridge } from \"./core/client\";\nimport { detectAppVersion, detectOsVersion, type NativeSources } from \"./core/device\";\nimport type { Insets } from \"./core/position\";\nimport type { ReplayCaptureOptions, ReplayFrame, ScreenCapturer } from \"./core/replay\";\nimport type { ChecklistProgressState, GuidelyAccount, GuidelyEvents, GuidelyOptions, GuidelyUser } from \"./core/types\";\nimport { useTapObserver } from \"./ui/Autocapture\";\nimport { GuidelyOverlay } from \"./ui/Overlay\";\nimport { GuidelyContext } from \"./ui/Target\";\n\nexport { GuidelyClient, SDK_NAME, SDK_VERSION, DEFAULT_API_URL } from \"./core/client\";\nexport type { PlatformBridge } from \"./core/client\";\nexport { detectAppVersion, detectOsVersion } from \"./core/device\";\nexport type { AppVersionInfo, NativeSources } from \"./core/device\";\nexport { GuidelyTarget, useGuidelyTarget, GuidelyScreenScope, guidelyScreenLayout } from \"./ui/Target\";\nexport type { GuidelyTargetProps } from \"./ui/Target\";\nexport { GuidelyOverlay } from \"./ui/Overlay\";\nexport { GuidelyMask } from \"./ui/Autocapture\";\nexport type { GuidelyMaskProps } from \"./ui/Autocapture\";\nexport { RageClickDetector, HeatmapBuffer, TapTracker } from \"./core/autocapture\";\nexport type { AutocaptureOption, TapElement, TapInfo, TapProperties } from \"./core/autocapture\";\nexport type { AutocaptureSettings, HeatmapPoint } from \"@guidelytech/shared\";\nexport { TargetRegistry, targetIdsFor } from \"./core/targets\";\nexport { parseHtml, htmlToText } from \"./core/html\";\nexport { positionCard } from \"./core/position\";\nexport { Messenger, createSseParser } from \"./core/messenger\";\nexport type { MessengerTab, MessengerView, MessengerSnapshot, MessengerThread } from \"./core/messenger\";\nexport type { Insets } from \"./core/position\";\nexport { ReplayUploader, SessionRecorder, RrwebEvents } from \"./core/replay\";\nexport type { ReplayFrame, ReplayCaptureOptions, ScreenCapturer, TouchPhase } from \"./core/replay\";\nexport type * from \"./core/types\";\nexport type { PublishedGuide, SdkConfigResponse, GuideStep } from \"@guidelytech/shared\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport { createFlagsClient, InMemoryStickyBucketStore } from \"@guidelytech/flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nfunction deviceLocale(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale;\n } catch {\n return undefined;\n }\n}\n\nfunction nativeSources(): NativeSources {\n return {\n platform: Platform as NativeSources[\"platform\"],\n nativeModules: NativeModules as Record<string, unknown>,\n expoModules: (globalThis as { expo?: { modules?: Record<string, unknown> } }).expo?.modules,\n };\n}\n\nfunction defaultBridge(appVersion?: string, appBuild?: string): PlatformBridge {\n const { width, height } = Dimensions.get(\"window\");\n const sources = nativeSources();\n // The app's own values win; a detected build only goes with a detected version.\n const detected = appVersion ? {} : detectAppVersion(sources);\n return {\n device: {\n platform: Platform.OS === \"android\" ? \"android\" : \"ios\",\n deviceType: (Platform.OS === \"ios\" && Platform.isPad) || Math.min(width, height) >= 600 ? \"tablet\" : \"mobile\",\n locale: deviceLocale(),\n appVersion: appVersion ?? detected.appVersion,\n appBuild: appBuild ?? detected.appBuild,\n osVersion: detectOsVersion(sources),\n },\n openExternal: (url) => void Linking.openURL(url).catch(() => {}),\n windowSize: () => Dimensions.get(\"window\"),\n capturer: nativeCapturer(),\n };\n}\n\ninterface NativeReplayModule {\n capture(options: ReplayCaptureOptions): Promise<ReplayFrame | null>;\n}\n\n/** Screenshots from `@guidelytech/react-native-replay` when the app has it installed (looked up, never imported). */\nfunction nativeCapturer(): ScreenCapturer | undefined {\n const mod = (NativeModules as { GuidelyReplay?: NativeReplayModule }).GuidelyReplay;\n if (!mod || typeof mod.capture !== \"function\") return undefined;\n return (options) => mod.capture(options);\n}\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user once the client is ready; changing to `null` resets the identity (logout). */\n user?: GuidelyUser | null;\n /** Safe-area insets for banners, launchers and sheets. Pass `useSafeAreaInsets()` from react-native-safe-area-context for exact values. */\n insets?: Partial<Insets>;\n /** How far above the bottom inset the checklist launcher sits, to clear tab bars (default 72). */\n launcherOffset?: number;\n /** Flags bootstrap (a payload or remote results) served until the client has loaded. */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, screen and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/**\n * Creates one Guidely client for the app and renders guide UI above `children`. Place it at the\n * root of the app (outside navigators) so the overlay covers every screen.\n */\nexport function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl, storage } = options;\n\n useEffect(() => {\n if (!projectId) return;\n let c: GuidelyClient;\n try {\n // Callbacks read the latest props so re-renders never need a new client.\n const latest = optionsRef.current;\n c = new GuidelyClient(\n {\n ...latest,\n projectId,\n environment,\n apiUrl,\n storage,\n // Known up front so flags evaluate for this user from the first render.\n user: userRef.current?.id ? userRef.current : undefined,\n flags: latest.flags === false ? false : { ...(latest.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current },\n onNavigate: (url) => optionsRef.current.onNavigate?.(url),\n onError: (err) => optionsRef.current.onError?.(err),\n },\n defaultBridge(latest.appVersion, latest.appBuild),\n );\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setClient(c);\n void c.init();\n const sub = AppState.addEventListener(\"change\", (s) => c.setAppState(s));\n return () => {\n sub.remove();\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl, storage]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n // A changed `locale` prop switches the language without a new client.\n useEffect(() => {\n client?.setLocale(options.locale ?? null);\n }, [client, options.locale]);\n\n const bootstrap = useBootstrap(payload, { ...(user?.id ? { ...(user.traits ?? {}), id: user.id } : {}), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n const tapObserver = useTapObserver(client);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>\n {/* Taps (and replay touches) are observed on a wrapper around the app only, so Guidely's own UI (a sibling) is never captured. */}\n {options.autocapture === false && !options.sessionReplay?.enabled ? (\n children\n ) : (\n <View style={styles.root} {...(tapObserver as ViewProps)}>\n {children}\n </View>\n )}\n {client ? <GuidelyOverlay client={client} insets={insets} launcherOffset={launcherOffset} /> : null}\n </FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst styles = StyleSheet.create({ root: { flex: 1 } });\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n getGuideState: { impressions: 0 },\n getMessenger: null,\n isGuideCompleted: false,\n isClientReady: false,\n isRecording: false,\n isRecordingTouches: false,\n getSessionId: \"\",\n getScreen: \"\",\n on: () => {},\n subscribeUi: () => () => {},\n getState: { ready: false, destroyed: false },\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` before the provider has created one. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client (a no-op stand-in until the provider has created it). */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once config is loaded and triggers have been evaluated. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(() => !!client?.isClientReady());\n useEffect(() => {\n if (!client) return setReady(false);\n setReady(client.isClientReady());\n const off = client.on(\"ready\", () => setReady(true));\n void client.ready().then(() => setReady(client.isClientReady()));\n return off;\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the id or traits change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyAccount): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (client && userId) void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a Guidely event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n return client.on(event, ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K]);\n }, [client, event]);\n}\n\n/** Records a screen view while the component is mounted (and when `name` changes). */\nexport function useGuidelyScreen(name: string | null | undefined, properties?: Record<string, unknown>): void {\n const client = useContext(GuidelyContext);\n useEffect(() => {\n if (client && name) client.screen(name, properties);\n }, [client, name]);\n}\n\ninterface NavigationRefLike {\n getCurrentRoute(): { name: string } | undefined | null;\n}\n\n/**\n * React Navigation integration: spread the result on `<NavigationContainer>` and every route\n * change becomes a Guidely screen view named after the route.\n *\n * ```tsx\n * const ref = useNavigationContainerRef();\n * <NavigationContainer ref={ref} {...useGuidelyNavigation(ref)}>\n * ```\n */\nexport function useGuidelyNavigation(navigationRef: NavigationRefLike, options: { screenName?: (route: { name: string }) => string } = {}) {\n const client = useContext(GuidelyContext);\n const nameRef = useRef(options.screenName);\n nameRef.current = options.screenName;\n const report = () => {\n const route = navigationRef.getCurrentRoute?.();\n if (client && route?.name) client.screen(nameRef.current ? nameRef.current(route) : route.name);\n };\n // The client may arrive after the navigator is ready: report the current route then.\n useEffect(report, [client]);\n return { onReady: report, onStateChange: report };\n}\n\nfunction useUiSelector<T>(select: (c: GuidelyClient) => T, fallback: T): T {\n const client = useContext(GuidelyContext);\n const selectRef = useRef(select);\n selectRef.current = select;\n const [value, setValue] = useState<T>(() => (client ? select(client) : fallback));\n useEffect(() => {\n if (!client) return;\n let last = JSON.stringify(selectRef.current(client));\n setValue(selectRef.current(client));\n const update = () => {\n const next = selectRef.current(client);\n const key = JSON.stringify(next);\n if (key !== last) {\n last = key;\n setValue(next);\n }\n };\n const offs = [client.subscribeUi(update), client.on(\"checklist:task\", update), client.on(\"identify\", update), client.on(\"guide:complete\", update), client.on(\"guide:dismiss\", update), client.on(\"ready\", update)];\n return () => offs.forEach((off) => off());\n }, [client]);\n return value;\n}\n\n/** Live progress of a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n return useUiSelector((c) => c.getChecklistProgress(idOrKey), { completedTaskIds: [], completedAt: null, dismissedAt: null });\n}\n\n/** Live impressions / completion / dismissal of a guide (by id or key). */\nexport function useGuideState(idOrKey: string): { impressions: number; completed: boolean; dismissed: boolean } {\n return useUiSelector(\n (c) => {\n const s = c.getGuideState(idOrKey);\n return { impressions: s.impressions, completed: !!s.completedAt, dismissed: !!s.dismissedAt };\n },\n { impressions: 0, completed: false, dismissed: false },\n );\n}\n\n/** The guide currently running exclusively (flow, modal, survey…), or null. */\nexport function useActiveGuide(): PublishedGuide | null {\n return useUiSelector((c) => c.getActiveGuide(), null);\n}\n","/** Feature-flag hooks and components for React Native (same API as `@guidelytech/react`). */\nimport { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\nimport { AppState } from \"react-native\";\n\n/** What the flag hooks read: the live client once created, else a snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const src = useContext(FlagsContext);\n const reader = src?.client ?? src?.bootstrap ?? EMPTY;\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (bootstrap, storage or network) or failed to and serve fallbacks. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot of a bootstrap payload, rebuilt only when it or the attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap payload (or remote results) used until the client has loaded. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Pass AsyncStorage as `storage` so the last flags\n * serve offline at cold start. Refreshes when the app returns to the foreground.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" apiUrl=\"https://guidelytech.com\" storage={AsyncStorage} attributes={{ id: user.id }}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n\n useEffect(() => {\n if (external || !sdkKey) return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n const sub = AppState.addEventListener(\"change\", (s) => {\n if (s === \"active\") void c.refresh();\n else if (s === \"background\") void c.flush();\n });\n return () => {\n sub.remove();\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n","/** FNV-1a 32-bit hash; deterministic across SDK and server for rollout bucketing. */\nexport function fnv1a(input: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h >>> 0;\n}\n\n/** Deterministic 0-99 bucket for percentage rollouts. */\nexport function rolloutBucket(subject: string, salt: string): number {\n return fnv1a(`${salt}:${subject}`) % 100;\n}\n\nexport function slugify(input: string): string {\n return input\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64) || \"untitled\";\n}\n\nconst ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n/** URL-safe random id. Uses crypto when available, falls back to Math.random (ids are not secrets). */\nexport function randomId(size = 16): string {\n const g: any = typeof globalThis !== \"undefined\" ? globalThis : {};\n let bytes: Uint8Array;\n if (g.crypto && typeof g.crypto.getRandomValues === \"function\") {\n bytes = new Uint8Array(size);\n g.crypto.getRandomValues(bytes);\n } else {\n bytes = new Uint8Array(size);\n for (let i = 0; i < size; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n let out = \"\";\n for (let i = 0; i < size; i++) out += ALPHABET[(bytes[i] as number) % ALPHABET.length];\n return out;\n}\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Safe nested getter: get(obj, \"account.plan\") */\nexport function getPath(obj: unknown, path: string): unknown {\n if (!path) return obj;\n let cur: any = obj;\n for (const part of path.split(\".\")) {\n if (cur == null) return undefined;\n cur = cur[part];\n }\n return cur;\n}\n\nexport function clamp(n: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, n));\n}\n\n/** Glob-style URL pattern match: `*` matches any chars except `/`, `**` matches anything. */\nexport function matchUrlPattern(pattern: string, url: string): boolean {\n if (!pattern) return true;\n if (pattern === url) return true;\n const escaped = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"__GLOBSTAR__\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/__GLOBSTAR__/g, \".*\");\n const re = new RegExp(`^${escaped}$`);\n return re.test(url) || re.test(stripOrigin(url));\n}\n\nexport function stripOrigin(url: string): string {\n try {\n const u = new URL(url);\n return u.pathname + u.search + u.hash;\n } catch {\n return url;\n }\n}\n\n/** Safe regexp construction with a length cap to limit ReDoS exposure. */\nexport function safeRegExp(source: string, flags = \"i\"): RegExp | null {\n if (!source || source.length > 200) return null;\n try {\n return new RegExp(source, flags);\n } catch {\n return null;\n }\n}\n","/**\n * Cross-platform helpers shared by the web SDK, the React Native SDK and (as a reference for) the\n * native iOS/Android SDKs. Zod-free so it can ship in runtime bundles.\n */\n\n/** Platforms a guide can be delivered to. */\nexport const PLATFORMS = [\"web\", \"ios\", \"android\"] as const;\nexport type Platform = (typeof PLATFORMS)[number];\n\n/** Guides published before platforms existed have no `platforms` field and are web-only. */\nexport const DEFAULT_PLATFORMS: Platform[] = [\"web\"];\n\n/** Platforms a guide config targets (missing field → web only). */\nexport function guidePlatforms(config: { platforms?: readonly string[] | null }): string[] {\n return Array.isArray(config.platforms) ? [...config.platforms] : [...DEFAULT_PLATFORMS];\n}\n\nexport function supportsPlatform(config: { platforms?: readonly string[] | null }, platform: string): boolean {\n return guidePlatforms(config).includes(platform);\n}\n\n/** Attribute web apps put on elements to share a target id with their mobile apps. */\nexport const GUIDELY_ID_ATTRIBUTE = \"data-guidely-id\";\n\n/**\n * Extracts a Guidely target id from a trigger / advance / checklist value so the same guide works on\n * web and mobile. Accepts a bare id (`new-deal`), `#new-deal`, or `[data-guidely-id=\"new-deal\"]`\n * (also `data-testid` / `data-tour`). Returns null for selectors that cannot name a single id.\n */\nexport function guidelyIdFromSelector(value: string | null | undefined): string | null {\n const v = (value ?? \"\").trim();\n if (!v) return null;\n if (/^[A-Za-z0-9_][A-Za-z0-9_\\-:.]*$/.test(v)) return v;\n const hash = v.match(/^#([A-Za-z0-9_][A-Za-z0-9_\\-:.]*)$/);\n if (hash) return hash[1] as string;\n const attr = v.match(/^(?:[a-z][a-z0-9]*)?\\[\\s*data-(?:guidely-id|testid|tour)\\s*=\\s*([\"']?)([^\"'\\]]+)\\1\\s*\\]$/i);\n if (attr) return (attr[2] as string).trim();\n return null;\n}\n\n/**\n * Mobile SDKs have screens instead of URLs. URL-based features (URL patterns, `url_match` triggers,\n * multi-page steps, `url_visited` checklist tasks) match against the screen path `/<ScreenName>`.\n */\nexport function screenPath(screen: string | null | undefined): string {\n const s = (screen ?? \"\").trim();\n if (!s) return \"/\";\n return s.startsWith(\"/\") ? s : `/${s}`;\n}\n\n/**\n * Compares dotted version strings numerically (`2.10.0` > `2.9.3`). Non-numeric parts compare as\n * strings; a missing part counts as 0 (`2.1` == `2.1.0`). Returns -1, 0 or 1, or null when either\n * side is empty.\n */\nexport function compareVersions(a: unknown, b: unknown): -1 | 0 | 1 | null {\n const sa = a == null ? \"\" : String(a).trim().replace(/^v/i, \"\");\n const sb = b == null ? \"\" : String(b).trim().replace(/^v/i, \"\");\n if (!sa || !sb) return null;\n const pa = sa.split(/[.+-]/);\n const pb = sb.split(/[.+-]/);\n const n = Math.max(pa.length, pb.length);\n for (let i = 0; i < n; i++) {\n const x = pa[i] ?? \"0\";\n const y = pb[i] ?? \"0\";\n const nx = /^\\d+$/.test(x) ? Number(x) : NaN;\n const ny = /^\\d+$/.test(y) ? Number(y) : NaN;\n if (!Number.isNaN(nx) && !Number.isNaN(ny)) {\n if (nx !== ny) return nx < ny ? -1 : 1;\n } else if (x !== y) {\n return x < y ? -1 : 1;\n }\n }\n return 0;\n}\n","/**\n * Pure checklist / survey logic shared by every renderer (web runtime, React Native, and the\n * reference for the native SDKs). Zod-free; uses structural types so it stays in the runtime entry.\n */\n\nexport type SurveyAnswer = string | number | boolean | string[];\nexport type SurveyAnswers = Record<string, SurveyAnswer>;\n\nexport interface ShowWhen {\n questionId: string;\n op: \"equals\" | \"lte\" | \"gte\" | \"in\";\n value: string | number | string[];\n}\n\n/** Evaluates a question's `showWhen` condition against current answers. */\nexport function isQuestionVisible(q: { showWhen?: ShowWhen }, answers: SurveyAnswers): boolean {\n if (!q.showWhen) return true;\n const actual = answers[q.showWhen.questionId];\n if (actual === undefined) return false;\n const expected = q.showWhen.value;\n switch (q.showWhen.op) {\n case \"equals\":\n return Array.isArray(actual) ? actual.includes(String(expected)) : String(actual) === String(expected);\n case \"lte\":\n return Number(actual) <= Number(expected);\n case \"gte\":\n return Number(actual) >= Number(expected);\n case \"in\": {\n const list = Array.isArray(expected) ? expected : [String(expected)];\n return Array.isArray(actual) ? actual.some((a) => list.includes(a)) : list.includes(String(actual));\n }\n default:\n return false;\n }\n}\n\n/** Are all required tasks done? */\nexport function isChecklistComplete(config: { tasks: Array<{ id: string; required: boolean }> }, progress: { completedTaskIds: string[] }): boolean {\n const done = new Set(progress.completedTaskIds);\n return config.tasks.filter((t) => t.required).every((t) => done.has(t.id));\n}\n","/**\n * Zod-free targeting evaluation. Imported by the browser SDK via `@guidelytech/shared/runtime`\n * so the runtime bundle does not pull in zod. Schemas live in ./targeting.ts.\n */\nimport { compareVersions } from \"./platform\";\nimport { getPath, matchUrlPattern, rolloutBucket, safeRegExp } from \"./utils\";\n\nexport const RULE_OPERATORS = [\n \"equals\",\n \"not_equals\",\n \"contains\",\n \"not_contains\",\n \"starts_with\",\n \"ends_with\",\n \"exists\",\n \"not_exists\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"in\",\n \"not_in\",\n \"regex\",\n \"is_true\",\n \"is_false\",\n \"before\",\n \"after\",\n] as const;\nexport type RuleOperator = (typeof RULE_OPERATORS)[number];\n\nexport const RULE_FIELDS = [\n \"user.attribute\",\n \"account.attribute\",\n \"user.role\",\n \"user.plan\",\n \"user.identified\",\n \"url.path\",\n \"url.full\",\n \"url.query\",\n \"device.type\",\n \"device.browser\",\n \"device.os\",\n \"visitor.firstVisit\",\n \"visitor.returning\",\n \"event.seen\",\n \"guide.completed\",\n \"guide.dismissed\",\n \"guide.seen\",\n \"checklist.completed\",\n \"audience.member\",\n \"datetime.now\",\n \"datetime.dayOfWeek\",\n \"datetime.hour\",\n \"rollout.percentage\",\n /** Guide A/B tests: the visitor's 0-99 bucket for the salt in `key` (see guide-experiments.ts). */\n \"experiment.bucket\",\n \"environment\",\n \"locale\",\n \"app.platform\",\n \"app.screen\",\n \"app.version\",\n \"page.views\",\n \"feature.clicks\",\n] as const;\nexport type RuleField = (typeof RULE_FIELDS)[number];\n\nexport interface Rule {\n id: string;\n field: RuleField;\n /** For attribute/query/event fields: the attribute key, query param name, event name, guide id... */\n key?: string;\n op: RuleOperator;\n value?: string | number | boolean | string[];\n /** When true, the rule is negated (exclusion rule). */\n negate?: boolean;\n}\n\nexport type RuleGroup = {\n id: string;\n op: \"and\" | \"or\";\n rules: Array<Rule | RuleGroup>;\n negate?: boolean;\n};\n\nexport function isRuleGroup(r: Rule | RuleGroup): r is RuleGroup {\n return (r as RuleGroup).rules !== undefined;\n}\n\nexport function emptyRuleGroup(id = \"root\"): RuleGroup {\n return { id, op: \"and\", rules: [] };\n}\n\n/** Everything targeting evaluation can see. Built by the SDK (browser) or the server. */\nexport interface TargetingContext {\n userId?: string | null;\n anonymousId: string;\n userAttributes: Record<string, unknown>;\n accountAttributes: Record<string, unknown>;\n url: string;\n path: string;\n query: Record<string, string>;\n device: { type: \"desktop\" | \"tablet\" | \"mobile\"; browser?: string; os?: string };\n firstVisit: boolean;\n eventsSeen: Set<string> | string[];\n completedGuides: Set<string> | string[];\n dismissedGuides: Set<string> | string[];\n seenGuides: Set<string> | string[];\n completedChecklists: Set<string> | string[];\n audienceIds: Set<string> | string[];\n now: Date;\n environment: string;\n locale?: string;\n /** `web`, `ios` or `android`. Missing means web. */\n platform?: string;\n /** Current screen name (mobile SDKs; set via `screen()`). */\n screen?: string;\n /** Host app version (mobile SDKs), e.g. `2.4.1`. */\n appVersion?: string;\n /** Salt for rollout (guide id). Set per guide before evaluating. */\n rolloutSalt?: string;\n /**\n * Views of tagged pages / clicks on tagged features in the last 30 days, by tag id. Only the server\n * fills it (audience evaluation); in the browser `page.views` / `feature.clicks` read 0.\n */\n tagUsage?: Record<string, number>;\n}\n\nfunction has(set: Set<string> | string[] | undefined, v: string): boolean {\n if (!set) return false;\n return set instanceof Set ? set.has(v) : set.includes(v);\n}\n\nfunction resolveField(rule: Rule, ctx: TargetingContext): unknown {\n switch (rule.field) {\n case \"user.attribute\":\n return rule.key ? getPath(ctx.userAttributes, rule.key) : undefined;\n case \"account.attribute\":\n return rule.key ? getPath(ctx.accountAttributes, rule.key) : undefined;\n case \"user.role\":\n return ctx.userAttributes.role;\n case \"user.plan\":\n return ctx.userAttributes.plan ?? ctx.accountAttributes.plan;\n case \"user.identified\":\n return !!ctx.userId;\n case \"url.path\":\n return ctx.path;\n case \"url.full\":\n return ctx.url;\n case \"url.query\":\n return rule.key ? ctx.query[rule.key] : undefined;\n case \"device.type\":\n return ctx.device.type;\n case \"device.browser\":\n return ctx.device.browser;\n case \"device.os\":\n return ctx.device.os;\n case \"visitor.firstVisit\":\n return ctx.firstVisit;\n case \"visitor.returning\":\n return !ctx.firstVisit;\n case \"event.seen\":\n return rule.key ? has(ctx.eventsSeen, rule.key) : false;\n case \"guide.completed\":\n return rule.key ? has(ctx.completedGuides, rule.key) : false;\n case \"guide.dismissed\":\n return rule.key ? has(ctx.dismissedGuides, rule.key) : false;\n case \"guide.seen\":\n return rule.key ? has(ctx.seenGuides, rule.key) : false;\n case \"checklist.completed\":\n return rule.key ? has(ctx.completedChecklists, rule.key) : false;\n case \"audience.member\":\n return rule.key ? has(ctx.audienceIds, rule.key) : false;\n case \"datetime.now\":\n return ctx.now.toISOString();\n case \"datetime.dayOfWeek\":\n return ctx.now.getDay();\n case \"datetime.hour\":\n return ctx.now.getHours();\n case \"rollout.percentage\":\n return rolloutBucket(ctx.userId || ctx.anonymousId, ctx.rolloutSalt || \"guidely\");\n case \"experiment.bucket\":\n return rule.key ? rolloutBucket(ctx.userId || ctx.anonymousId, rule.key) : undefined;\n case \"environment\":\n return ctx.environment;\n case \"locale\":\n return ctx.locale;\n case \"app.platform\":\n return ctx.platform ?? \"web\";\n case \"app.screen\":\n return ctx.screen;\n case \"app.version\":\n return ctx.appVersion;\n case \"page.views\":\n case \"feature.clicks\":\n return rule.key ? (ctx.tagUsage?.[rule.key] ?? 0) : 0;\n default:\n return undefined;\n }\n}\n\nfunction toNumber(v: unknown): number | null {\n if (typeof v === \"number\") return v;\n if (typeof v === \"string\" && v.trim() !== \"\" && !Number.isNaN(Number(v))) return Number(v);\n if (v instanceof Date) return v.getTime();\n return null;\n}\n\nfunction toDateMs(v: unknown): number | null {\n if (v instanceof Date) return v.getTime();\n if (typeof v === \"string\") {\n const t = Date.parse(v);\n return Number.isNaN(t) ? null : t;\n }\n if (typeof v === \"number\") return v;\n return null;\n}\n\nexport function compare(op: RuleOperator, actual: unknown, expected: Rule[\"value\"]): boolean {\n switch (op) {\n case \"exists\":\n return actual !== undefined && actual !== null && actual !== \"\";\n case \"not_exists\":\n return actual === undefined || actual === null || actual === \"\";\n case \"is_true\":\n return actual === true || actual === \"true\";\n case \"is_false\":\n return actual === false || actual === \"false\";\n case \"equals\":\n if (typeof actual === \"boolean\") return String(actual) === String(expected);\n return String(actual ?? \"\") === String(expected ?? \"\");\n case \"not_equals\":\n return String(actual ?? \"\") !== String(expected ?? \"\");\n case \"contains\":\n return typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase());\n case \"not_contains\":\n return !(typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase()));\n case \"starts_with\":\n return typeof actual === \"string\" && actual.startsWith(String(expected ?? \"\"));\n case \"ends_with\":\n return typeof actual === \"string\" && actual.endsWith(String(expected ?? \"\"));\n case \"gt\":\n case \"gte\":\n case \"lt\":\n case \"lte\": {\n const a = toNumber(actual);\n const b = toNumber(expected);\n if (a === null || b === null) return false;\n return op === \"gt\" ? a > b : op === \"gte\" ? a >= b : op === \"lt\" ? a < b : a <= b;\n }\n case \"in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return list.includes(String(actual ?? \"\"));\n }\n case \"not_in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return !list.includes(String(actual ?? \"\"));\n }\n case \"regex\": {\n const re = safeRegExp(String(expected ?? \"\"));\n return !!re && typeof actual === \"string\" && re.test(actual);\n }\n case \"before\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a < b;\n }\n case \"after\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a > b;\n }\n default:\n return false;\n }\n}\n\nexport function evaluateRule(rule: Rule, ctx: TargetingContext): boolean {\n let result: boolean;\n if (rule.field === \"url.path\" || rule.field === \"url.full\" || rule.field === \"app.screen\") {\n const actual = String(resolveField(rule, ctx) ?? \"\");\n if (rule.op === \"equals\") result = matchUrlPattern(String(rule.value ?? \"\"), actual);\n else if (rule.op === \"not_equals\") result = !matchUrlPattern(String(rule.value ?? \"\"), actual);\n else result = compare(rule.op, actual, rule.value);\n } else if (rule.field === \"app.version\" && [\"equals\", \"not_equals\", \"gt\", \"gte\", \"lt\", \"lte\"].includes(rule.op)) {\n const c = compareVersions(resolveField(rule, ctx), rule.value);\n if (c === null) result = rule.op === \"not_equals\";\n else result = rule.op === \"equals\" ? c === 0 : rule.op === \"not_equals\" ? c !== 0 : rule.op === \"gt\" ? c > 0 : rule.op === \"gte\" ? c >= 0 : rule.op === \"lt\" ? c < 0 : c <= 0;\n } else {\n result = compare(rule.op, resolveField(rule, ctx), rule.value);\n }\n return rule.negate ? !result : result;\n}\n\n/** Evaluate a rule tree. An empty group matches everyone. */\nexport function evaluateRules(group: RuleGroup | null | undefined, ctx: TargetingContext): boolean {\n if (!group || group.rules.length === 0) return group?.negate ? false : true;\n const results = group.rules.map((r) => (isRuleGroup(r) ? evaluateRules(r, ctx) : evaluateRule(r, ctx)));\n const value = group.op === \"and\" ? results.every(Boolean) : results.some(Boolean);\n return group.negate ? !value : value;\n}\n\n/** Fields whose evaluation requires server-held data. Used by docs/UI to annotate rules. */\nexport const SERVER_ASSISTED_FIELDS: RuleField[] = [\"audience.member\", \"guide.completed\", \"guide.dismissed\", \"guide.seen\", \"checklist.completed\", \"page.views\", \"feature.clicks\"];\n\n/** Who a guide is shown to, before its targeting rules: everyone, only signed-in (identified) users, or only anonymous visitors. */\nexport const GUIDE_VISIBILITIES = [\"everyone\", \"identified\", \"anonymous\"] as const;\nexport type GuideVisibility = (typeof GUIDE_VISIBILITIES)[number];\n\n/**\n * Targeting with the visibility folded in as a `user.identified` rule. The server sends guides to SDKs\n * this way, so every SDK applies it through the rules it already evaluates (SDKs that predate the field\n * resolve it as undefined and show the guide to nobody rather than to everyone).\n */\nexport function withVisibility(targeting: RuleGroup, visibility: GuideVisibility | undefined): RuleGroup {\n if (!visibility || visibility === \"everyone\") return targeting;\n return { id: \"visibility\", op: \"and\", rules: [{ id: \"visibility-rule\", field: \"user.identified\", op: visibility === \"identified\" ? \"is_true\" : \"is_false\" }, targeting] };\n}\n\nexport function describeRule(rule: Rule): string {\n const subject = rule.key ? `${rule.field}[${rule.key}]` : rule.field;\n const v = Array.isArray(rule.value) ? rule.value.join(\", \") : rule.value === undefined ? \"\" : String(rule.value);\n return `${rule.negate ? \"NOT \" : \"\"}${subject} ${rule.op.replace(/_/g, \" \")}${v ? ` \"${v}\"` : \"\"}`;\n}\n","/**\n * WCAG 2.1 colour contrast (zod-free). The editor warns when a guide's colours fall below AA:\n * 4.5:1 for body text, 3:1 for large text and UI components (button outlines, the close icon).\n */\n\nexport const WCAG_AA_TEXT = 4.5;\nexport const WCAG_AA_LARGE = 3;\n\nfunction channel(c: number): number {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n}\n\n/** `#rgb` / `#rrggbb` → [r, g, b]; null when not a hex colour. */\nexport function parseHexColor(hex: string | null | undefined): [number, number, number] | null {\n if (!hex) return null;\n const m = hex.trim().match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);\n if (!m) return null;\n const h = m[1]!.length === 3 ? m[1]!.split(\"\").map((c) => c + c).join(\"\") : m[1]!;\n return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];\n}\n\nexport function relativeLuminance(hex: string): number | null {\n const rgb = parseHexColor(hex);\n if (!rgb) return null;\n return 0.2126 * channel(rgb[0]) + 0.7152 * channel(rgb[1]) + 0.0722 * channel(rgb[2]);\n}\n\n/** Contrast ratio 1–21 between two hex colours, or null when either is not a hex colour. */\nexport function contrastRatio(a: string, b: string): number | null {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n if (la === null || lb === null) return null;\n const [hi, lo] = la > lb ? [la, lb] : [lb, la];\n return Math.round(((hi + 0.05) / (lo + 0.05)) * 100) / 100;\n}\n\n/** Text colour (black or white) with the better contrast on `background`. */\nexport function readableTextOn(background: string): \"#ffffff\" | \"#111827\" {\n const white = contrastRatio(background, \"#ffffff\") ?? 0;\n const dark = contrastRatio(background, \"#111827\") ?? 0;\n return white >= dark ? \"#ffffff\" : \"#111827\";\n}\n\nexport interface ContrastIssue {\n /** What is hard to read. */\n pair: \"text\" | \"button\" | \"link\";\n ratio: number;\n required: number;\n message: string;\n}\n\n/**\n * Contrast problems of a guide's effective colours (guide appearance over the project theme).\n * Buttons use white or dark text, whichever reads better, so only a mid-tone primary colour fails.\n */\nexport function contrastIssues(colors: { primaryColor?: string; backgroundColor?: string; textColor?: string }): ContrastIssue[] {\n const issues: ContrastIssue[] = [];\n const { primaryColor, backgroundColor, textColor } = colors;\n if (textColor && backgroundColor) {\n const r = contrastRatio(textColor, backgroundColor);\n if (r !== null && r < WCAG_AA_TEXT) issues.push({ pair: \"text\", ratio: r, required: WCAG_AA_TEXT, message: `Text on the background has a contrast of ${r}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });\n }\n if (primaryColor) {\n const label = contrastRatio(primaryColor, readableTextOn(primaryColor));\n if (label !== null && label < WCAG_AA_TEXT) issues.push({ pair: \"button\", ratio: label, required: WCAG_AA_TEXT, message: `Button labels on the primary colour have a contrast of ${label}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });\n if (backgroundColor) {\n const link = contrastRatio(primaryColor, backgroundColor);\n if (link !== null && link < WCAG_AA_LARGE) issues.push({ pair: \"link\", ratio: link, required: WCAG_AA_LARGE, message: `The primary colour on the background (links, outlined buttons) has a contrast of ${link}:1; WCAG AA needs ${WCAG_AA_LARGE}:1.` });\n }\n }\n return issues;\n}\n","/** Reserved property names that are stripped from `properties` to avoid collecting sensitive data. */\nexport const SENSITIVE_PROPERTY_PATTERN = /(password|passwd|secret|token|credit|card|cvv|ssn|iban)/i;\n\nexport const MAX_PROPERTY_BYTES = 8 * 1024;\n\nexport function sanitizeProperties(props: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!props) return {};\n const out: Record<string, unknown> = {};\n let size = 0;\n for (const [k, v] of Object.entries(props)) {\n if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;\n if (typeof v === \"function\" || typeof v === \"symbol\") continue;\n const str = typeof v === \"string\" ? v : JSON.stringify(v ?? null);\n size += k.length + (str?.length ?? 0);\n if (size > MAX_PROPERTY_BYTES) break;\n out[k.slice(0, 100)] = typeof v === \"string\" ? v.slice(0, 1000) : v;\n }\n return out;\n}\n","import { fnv1a } from \"./utils\";\n\n/** One parsed stack frame. `file` is the script URL (or path) as the browser reported it. */\nexport interface StackFrame {\n fn?: string;\n file?: string;\n line?: number;\n col?: number;\n}\n\n/** Properties carried by an `exception` event (see `docs/product-analytics.md`). */\nexport interface ExceptionProperties {\n type: string;\n message: string;\n frames: StackFrame[];\n /** `onerror` | `unhandledrejection` | `manual` (captureException) | `console`. */\n source?: string;\n handled?: boolean;\n /** App version or commit (SDK option `release`); selects the matching uploaded source maps. */\n release?: string;\n /** Set by the server at ingestion; groups occurrences into an issue. */\n fingerprint?: string;\n}\n\nexport const MAX_STACK_FRAMES = 30;\n\n// Chrome / Edge / Node: \" at fn (https://x/app.js:1:2)\" or \" at https://x/app.js:1:2\"\nconst V8 = /^\\s*at (?:(.+?) \\()?((?:[a-z][\\w+.-]*:)?[^\\s()]+?):(\\d+):(\\d+)\\)?\\s*$/i;\n// Firefox / Safari: \"fn@https://x/app.js:1:2\" or \"@https://x/app.js:1:2\"\nconst GECKO = /^\\s*(.*?)@(.+?):(\\d+):(\\d+)\\s*$/;\n\n/** Parses `Error.stack` from V8, SpiderMonkey and JavaScriptCore into frames (innermost first). */\nexport function parseStack(stack: string | undefined | null, max = MAX_STACK_FRAMES): StackFrame[] {\n if (!stack || typeof stack !== \"string\") return [];\n const frames: StackFrame[] = [];\n for (const raw of stack.split(\"\\n\")) {\n if (frames.length >= max) break;\n const line = raw.slice(0, 1000);\n const m = V8.exec(line) ?? GECKO.exec(line);\n if (!m) continue;\n const fn = (m[1] || \"\").trim();\n frames.push({ fn: fn ? fn.slice(0, 200) : undefined, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });\n }\n return frames;\n}\n\n/** Replaces volatile parts of a message (numbers, ids, quoted values) so repeats group together. */\nexport function normalizeErrorMessage(message: string): string {\n return (message || \"\")\n .slice(0, 500)\n .replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, \"<uuid>\")\n .replace(/([\"'`]).*?\\1/g, \"<str>\")\n .replace(/\\b0x[0-9a-f]+\\b/gi, \"<hex>\")\n .replace(/\\d+(\\.\\d+)?/g, \"<n>\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** Strips origin, query, hash and build hashes (`main.3f2a1b9c.js` → `main.js`) from a script URL. */\nexport function normalizeFrameFile(file: string | undefined): string {\n if (!file) return \"\";\n let path = file;\n try {\n path = new URL(file).pathname;\n } catch {\n path = file.replace(/[?#].*$/, \"\");\n }\n return path.replace(/[.-][0-9a-f]{6,}(?=\\.\\w+$)/i, \"\").replace(/\\/\\d+\\//g, \"/<n>/\");\n}\n\n/** Source map upload limits (`POST /api/v1/sourcemaps/upload`). */\n/** Per map, uncompressed (the CLI uploads maps gzipped). */\nexport const SOURCEMAP_MAX_FILE_BYTES = 100 * 1024 * 1024;\nexport const SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;\n\n/**\n * Stable issue key for an exception: error type + normalised message + the innermost frame that\n * has a file (path without build hash + function name, or its original source + name when a source\n * map resolved it). Line/column numbers are left out because they change with every deploy of a\n * minified bundle.\n */\nexport function fingerprintError(input: { type?: string; message?: string; frames?: StackFrame[]; original?: { source: string; name?: string | null } | null }): string {\n const top = (input.frames ?? []).find((f) => f.file);\n // With a source map the original file and function name identify the frame across deploys, even\n // when a minifier renames functions between builds.\n const frameKey = input.original ? `src:${input.original.source}:${input.original.name || \"?\"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || \"?\"}` : \"\";\n const key = [input.type || \"Error\", normalizeErrorMessage(input.message || \"\"), frameKey].join(\"|\");\n const a = fnv1a(key).toString(16).padStart(8, \"0\");\n const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, \"0\");\n return a + b;\n}\n","/** Complaint types and limits shared by the server and the messenger runtime (zod-free). */\n\n/** Where a complaint is in its handling; the messenger shows it as Received → In review → Resolved. */\nexport const COMPLAINT_STATUSES = [\"open\", \"in_review\", \"resolved\"] as const;\nexport type ComplaintStatus = (typeof COMPLAINT_STATUSES)[number];\n\n/** Events a complaint webhook can fire on. */\nexport const COMPLAINT_EVENTS = [\"complaint.filed\", \"complaint.status_changed\", \"complaint.replied\", \"complaint.resolved\"] as const;\nexport type ComplaintEvent = (typeof COMPLAINT_EVENTS)[number];\n\n/** Extra questions a category asks for. */\nexport const COMPLAINT_FIELD_TYPES = [\"text\", \"choice\"] as const;\nexport type ComplaintFieldType = (typeof COMPLAINT_FIELD_TYPES)[number];\n\nexport const MAX_COMPLAINT_FIELDS = 8;\nexport const MAX_COMPLAINT_CHOICES = 12;\nexport const MAX_COMPLAINT_LENGTH = 4000;\nexport const MAX_COMPLAINT_ANSWER_LENGTH = 500;\n/** Largest screenshot the messenger may attach (after it scales the image down). */\nexport const MAX_COMPLAINT_ATTACHMENT_BYTES = 2 * 1024 * 1024;\n\nexport interface ComplaintField {\n /** Stable id (`invoice_number`), used as the answer's key in webhook payloads. */\n id: string;\n label: string;\n type: ComplaintFieldType;\n /** Choices for `choice` questions. */\n options?: string[];\n required: boolean;\n}\n\n/** \"CMP-1042\" for complaint number 1042. */\nexport const complaintReference = (number: number) => `CMP-${number}`;\n\n/** A category as the messenger offers it. */\nexport interface MessengerComplaintCategory {\n id: string;\n name: string;\n description: string;\n color: string;\n fields: ComplaintField[];\n}\n\n/** Complaints block of `MessengerConfig`; absent when the project doesn't take complaints. */\nexport interface MessengerComplaintsConfig {\n categories: MessengerComplaintCategory[];\n /** Visitors the app hasn't identified may file one (with an email address). */\n anonymous: boolean;\n}\n\n/** A complaint as the person who filed it sees it (on its conversation). */\nexport interface MessengerComplaint {\n id: string;\n reference: string;\n status: ComplaintStatus;\n categoryName: string;\n createdAt: string;\n}\n\n/** Scout offered the complaint form in a reply, with this category picked. */\nexport interface MessengerComplaintOffer {\n categoryId: string;\n name: string;\n}\n","/**\n * Agent Analytics: the `agent.conversation` turn the customer's own AI agents send (zod-free, so the\n * browser SDK can use the types and limits without bundling the schema). The schema is in agents.ts.\n */\n\nexport const AGENT_TURN_ROLES = [\"user\", \"assistant\", \"tool\", \"system\"] as const;\nexport type AgentTurnRole = (typeof AGENT_TURN_ROLES)[number];\n\n/** How a conversation ended, as the agent reports it. */\nexport const AGENT_OUTCOMES = [\"success\", \"failure\", \"escalated\", \"abandoned\"] as const;\nexport type AgentOutcome = (typeof AGENT_OUTCOMES)[number];\n\nexport const AGENT_TOOL_STATUSES = [\"ok\", \"error\"] as const;\nexport type AgentToolStatus = (typeof AGENT_TOOL_STATUSES)[number];\n\n/** Longest turn text accepted (characters). */\nexport const AGENT_TURN_MAX_TEXT = 20_000;\n/** Most turns in one request. */\nexport const AGENT_TURNS_PER_BATCH = 100;\n/** Most tool calls on one turn. */\nexport const AGENT_TOOL_CALLS_PER_TURN = 50;\n/** Metadata: at most this many keys, string values up to 500 characters, 4 KB in all. */\nexport const AGENT_METADATA_MAX_KEYS = 30;\nexport const AGENT_METADATA_MAX_BYTES = 4096;\n/** The built-in Scout agent's id; customer agents can't use it. */\nexport const SCOUT_AGENT_ID = \"scout\";\n\n/** One tool the agent called in a turn. Arguments and results are never sent or stored. */\nexport interface AgentToolCallInput {\n name: string;\n status?: AgentToolStatus;\n latencyMs?: number;\n}\n\n/** One `agent.conversation` turn. */\nexport interface AgentTurnInput {\n type?: \"agent.conversation\";\n /** Your conversation (thread) id. */\n conversationId: string;\n /** Your agent's id, e.g. \"support-bot\". The agent is created on its first turn. */\n agentId: string;\n /** Display name for a new agent (defaults to agentId). */\n agentName?: string;\n /** Idempotency key: a turn sent twice with the same id is stored once. */\n turnId?: string;\n role: AgentTurnRole;\n text?: string;\n toolCalls?: AgentToolCallInput[];\n /** How long the agent took to produce this turn (assistant turns). */\n latencyMs?: number;\n /** How the conversation ended, when this turn ends it (the latest reported outcome wins). */\n outcome?: AgentOutcome;\n /** Whether the person got what they came for, when the agent knows. */\n taskSuccess?: boolean;\n /** ISO 8601 time of the turn (default: when Guidely receives it). */\n occurredAt?: string;\n userId?: string | null;\n anonymousId?: string | null;\n accountId?: string | null;\n sessionId?: string | null;\n /** Flat key/value pairs (strings, numbers, booleans), e.g. { model: \"gpt-4.1\" }. */\n metadata?: Record<string, string | number | boolean | null>;\n}\n\n/** Response of both ingestion endpoints. */\nexport interface AgentEventsResponse {\n accepted: number;\n duplicates: number;\n /** Turns refused (an agent past the per-project limit, or a conversation past its turn limit). */\n rejected?: number;\n /** Turns dropped because this month's product analytics allowance is used up. */\n overLimit?: number;\n}\n","/* Network requests recorded into session replays (zod-free: imported by the SDK recorder). */\n\n/** rrweb plugin name for network events in recordings (event type 6, `data.plugin`). */\nexport const NETWORK_PLUGIN = \"guidely/network@1\";\n\n/** Request kinds, from `fetch`/`XMLHttpRequest` patching or `PerformanceResourceTiming.initiatorType`. */\nexport type NetworkRequestType = \"fetch\" | \"xhr\" | \"websocket\" | \"document\" | \"script\" | \"stylesheet\" | \"image\" | \"font\" | \"media\" | \"beacon\" | \"other\";\n\n/**\n * One network request in a recording: the payload of an rrweb plugin event\n * `{ type: 6, data: { plugin: NETWORK_PLUGIN, payload: NetworkPluginPayload } }`, batched.\n * Times are epoch milliseconds (same clock as rrweb event timestamps).\n *\n * A WebSocket is a request with `type: \"websocket\"` and `method: \"GET\"`, emitted when it opens\n * (`startTime`) and again, with the same `id`, when it closes (`endTime`, `closeCode`, `closeReason`,\n * totals in `messages`). Its frames are `WebSocketMessage`s referencing that `id`.\n */\nexport interface NetworkRequest {\n /** Stable id within the recording. */\n id: string;\n type: NetworkRequestType;\n method: string;\n /** Absolute URL; values of sensitive-looking query parameters replaced with `[redacted]`. */\n url: string;\n startTime: number;\n endTime?: number;\n durationMs?: number;\n /** HTTP status; 0 for network errors / blocked / aborted. Absent when the browser doesn't expose it. */\n status?: number;\n /** Set for failed requests: network error, abort or timeout message. */\n error?: string;\n /** Encoded bytes transferred / decoded response size, when known. */\n transferSize?: number;\n responseSize?: number;\n /** Only when `recordNetworkPayloads` is on; sensitive headers are `[redacted]`. */\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n /** Text/JSON bodies, ≤10KB, sensitive JSON fields masked; `[binary]` / `[truncated]` markers otherwise. */\n requestBody?: string;\n responseBody?: string;\n /** WebSocket only: negotiated subprotocol, close details, and frame totals (all frames, including ones not recorded). */\n protocol?: string;\n closeCode?: number;\n closeReason?: string;\n messages?: { sent: number; received: number; sentBytes: number; receivedBytes: number; recorded: number };\n}\n\n/** One WebSocket frame. At most `WS_MAX_MESSAGES_PER_SOCKET` are recorded per connection per page load. */\nexport interface WebSocketMessage {\n /** The `NetworkRequest.id` of the connection. */\n socketId: string;\n dir: \"send\" | \"recv\";\n time: number;\n /** Bytes (UTF-8 length for text frames). */\n size: number;\n binary?: boolean;\n /** Only with `recordNetworkPayloads`: text ≤ 2KB (JSON with sensitive keys masked), else `[truncated]`; binary frames are `[binary <n> B]`. */\n data?: string;\n}\n\nexport interface NetworkPluginPayload {\n requests?: NetworkRequest[];\n messages?: WebSocketMessage[];\n /** Requests/frames dropped since the previous payload because a cap was reached. */\n dropped?: { requests?: number; messages?: number };\n}\n\nexport const WS_MAX_MESSAGES_PER_SOCKET = 200;\nexport const WS_MAX_MESSAGE_BYTES = 2048;\n\n/** Header names always replaced with `[redacted]` when payload capture is on. */\nexport const SENSITIVE_HEADER_PATTERN = /^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|x-csrf-token|x-xsrf-token|x-guidely-key|x-guidely-conversation)$/i;\n\n/** Query parameter and JSON field names whose values are redacted. */\nexport const SENSITIVE_PARAM_PATTERN = /(token|key|secret|password|passwd|pwd|auth|session|code|sig|signature|credential|ssn|card|cvv|iban)/i;\n","/**\n * Media in article bodies: uploaded images, videos and PDFs, and video embeds from a fixed set of hosts.\n * Sanitizers (server, browser runtime) only keep an `<iframe>` whose `src` is the canonical embed URL\n * that `toEmbedUrl` produces, so authors can never point a frame anywhere else.\n *\n * An uploaded PDF reads inline, as its pages: the dashboard renders each page to an image when the\n * PDF is uploaded, and the body holds plain HTML every renderer already understands:\n *\n * <div class=\"gd-pdf\">\n * <a class=\"gd-file\" href=\"…/{id}.pdf\" target=\"_blank\">{file name}</a>\n * <div class=\"gd-pdf-pages\"><img src=\"…/{page}.webp\" alt=\"{file name}, page 1 of 12\"> …</div>\n * </div>\n *\n * Renderers that know the classes draw a swipeable page viewer with the PDF one tap away; older ones\n * show a link and the pages as images. A PDF whose pages couldn't be rendered (password-protected,\n * damaged) is just the `gd-file` link, drawn as a file card.\n */\n\nexport type EmbedProvider = \"youtube\" | \"vimeo\" | \"loom\" | \"wistia\";\n\nexport interface VideoEmbed {\n provider: EmbedProvider;\n /** Canonical player URL, safe to use as an iframe `src`. */\n src: string;\n /** Page a viewer can open instead (native SDKs show a link rather than a player). */\n watchUrl: string;\n /** Accessible iframe title. */\n title: string;\n}\n\nexport const MEDIA_IMAGE_TYPES = [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"] as const;\nexport const MEDIA_VIDEO_TYPES = [\"video/mp4\", \"video/webm\"] as const;\nexport const MEDIA_FILE_TYPES = [\"application/pdf\"] as const;\nexport type MediaContentType = (typeof MEDIA_IMAGE_TYPES)[number] | (typeof MEDIA_VIDEO_TYPES)[number] | (typeof MEDIA_FILE_TYPES)[number];\nexport type MediaKind = \"image\" | \"video\" | \"file\";\nexport const MEDIA_IMAGE_MAX_BYTES = 10 * 1024 * 1024;\nexport const MEDIA_VIDEO_MAX_BYTES = 200 * 1024 * 1024;\nexport const MEDIA_FILE_MAX_BYTES = 50 * 1024 * 1024;\n/** The largest upload of any type. */\nexport const MEDIA_MAX_BYTES = Math.max(MEDIA_IMAGE_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_FILE_MAX_BYTES);\n\nexport function isMediaContentType(type: string): type is MediaContentType {\n return mediaKind(type) !== null;\n}\nexport function isVideoContentType(type: string): boolean {\n return (MEDIA_VIDEO_TYPES as readonly string[]).includes(type);\n}\nexport function mediaKind(type: string): MediaKind | null {\n if ((MEDIA_IMAGE_TYPES as readonly string[]).includes(type)) return \"image\";\n if ((MEDIA_VIDEO_TYPES as readonly string[]).includes(type)) return \"video\";\n if ((MEDIA_FILE_TYPES as readonly string[]).includes(type)) return \"file\";\n return null;\n}\nexport function mediaMaxBytes(type: string): number {\n const kind = mediaKind(type);\n return kind === \"video\" ? MEDIA_VIDEO_MAX_BYTES : kind === \"file\" ? MEDIA_FILE_MAX_BYTES : MEDIA_IMAGE_MAX_BYTES;\n}\n\n/** Class marking a link as an attached file (an uploaded PDF), drawn as a file card. */\nexport const FILE_LINK_CLASS = \"gd-file\";\n/** Class of the block holding a PDF's link and its rendered pages. */\nexport const PDF_BLOCK_CLASS = \"gd-pdf\";\n/** Class of the element wrapping a PDF's page images. */\nexport const PDF_PAGES_CLASS = \"gd-pdf-pages\";\n/** Pages rendered inline per PDF; readers open the PDF itself for the rest. */\nexport const PDF_MAX_PAGES = 40;\n\n/** True for an `<a>` with the file class and an absolute http(s) `href`: render it as a file card. */\nexport function isFileLink(className: string | null | undefined, href: string | null | undefined): boolean {\n return !!className && className.split(/\\s+/).includes(FILE_LINK_CLASS) && isSafeMediaUrl(href);\n}\n\nconst YOUTUBE_ID = /^[A-Za-z0-9_-]{11}$/;\nconst VIMEO_ID = /^\\d{1,12}$/;\nconst VIMEO_HASH = /^[0-9a-f]{6,20}$/i;\nconst LOOM_ID = /^[0-9a-f]{32}$/i;\nconst WISTIA_ID = /^[a-z0-9]{10}$/i;\n\nfunction parseUrl(input: string): URL | null {\n const s = input.trim();\n if (!s) return null;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(s) ? s : `https://${s}`);\n if (u.protocol !== \"https:\" && u.protocol !== \"http:\") return null;\n if (u.username || u.password || (u.port && u.port !== \"443\" && u.port !== \"80\")) return null;\n return u;\n } catch {\n return null;\n }\n}\n\n/** \"1h2m3s\", \"90s\", \"90\" → seconds. */\nfunction parseStart(v: string | null): number {\n if (!v) return 0;\n if (/^\\d+$/.test(v)) return Math.min(Number(v), 86400);\n const m = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(v);\n if (!m || !m[0]) return 0;\n return Math.min(Number(m[1] ?? 0) * 3600 + Number(m[2] ?? 0) * 60 + Number(m[3] ?? 0), 86400);\n}\n\nfunction youtube(id: string, start: number): VideoEmbed | null {\n if (!YOUTUBE_ID.test(id)) return null;\n return {\n provider: \"youtube\",\n src: `https://www.youtube-nocookie.com/embed/${id}${start ? `?start=${start}` : \"\"}`,\n watchUrl: `https://www.youtube.com/watch?v=${id}${start ? `&t=${start}s` : \"\"}`,\n title: \"YouTube video\",\n };\n}\n\nfunction vimeo(id: string, hash: string | null): VideoEmbed | null {\n if (!VIMEO_ID.test(id) || (hash !== null && !VIMEO_HASH.test(hash))) return null;\n const h = hash ? hash.toLowerCase() : null;\n return { provider: \"vimeo\", src: `https://player.vimeo.com/video/${id}${h ? `?h=${h}` : \"\"}`, watchUrl: `https://vimeo.com/${id}${h ? `/${h}` : \"\"}`, title: \"Vimeo video\" };\n}\n\n/**\n * Turns a pasted video page or player URL from YouTube, Vimeo, Loom or Wistia into its canonical\n * embed. Returns null for anything else, including lookalike hosts.\n */\nexport function toEmbedUrl(input: string): VideoEmbed | null {\n const u = parseUrl(input);\n if (!u) return null;\n const host = u.hostname.toLowerCase().replace(/^www\\./, \"\");\n const parts = u.pathname.split(\"/\").filter(Boolean);\n switch (host) {\n case \"youtube.com\":\n case \"m.youtube.com\":\n case \"youtube-nocookie.com\": {\n const start = parseStart(u.searchParams.get(\"start\") ?? u.searchParams.get(\"t\"));\n if (parts[0] === \"watch\" && parts.length === 1) return youtube(u.searchParams.get(\"v\") ?? \"\", start);\n if ((parts[0] === \"embed\" || parts[0] === \"shorts\" || parts[0] === \"live\") && parts.length === 2) return youtube(parts[1]!, start);\n return null;\n }\n case \"youtu.be\":\n return parts.length === 1 ? youtube(parts[0]!, parseStart(u.searchParams.get(\"t\") ?? u.searchParams.get(\"start\"))) : null;\n case \"vimeo.com\":\n if (parts.length === 1) return vimeo(parts[0]!, null);\n if (parts.length === 2 && VIMEO_ID.test(parts[0]!)) return vimeo(parts[0]!, parts[1]!);\n return null;\n case \"player.vimeo.com\":\n return parts[0] === \"video\" && parts.length === 2 ? vimeo(parts[1]!, u.searchParams.get(\"h\")) : null;\n case \"loom.com\":\n if ((parts[0] === \"share\" || parts[0] === \"embed\") && parts.length === 2 && LOOM_ID.test(parts[1]!)) {\n const id = parts[1]!.toLowerCase();\n return { provider: \"loom\", src: `https://www.loom.com/embed/${id}`, watchUrl: `https://www.loom.com/share/${id}`, title: \"Loom video\" };\n }\n return null;\n default: {\n let id: string | undefined;\n if (host === \"fast.wistia.net\" || host === \"fast.wistia.com\") id = parts[0] === \"embed\" && parts[1] === \"iframe\" && parts.length === 3 ? parts[2] : undefined;\n else if (host === \"wi.st\" || host === \"wistia.com\" || /^[a-z0-9-]+\\.wistia\\.com$/.test(host)) id = parts[0] === \"medias\" && parts.length === 2 ? parts[1] : undefined;\n if (!id || !WISTIA_ID.test(id)) return null;\n return { provider: \"wistia\", src: `https://fast.wistia.net/embed/iframe/${id}`, watchUrl: `https://fast.wistia.net/embed/iframe/${id}`, title: \"Wistia video\" };\n }\n }\n}\n\n/** True only for a canonical embed URL (exactly what `toEmbedUrl` returns), so an iframe can't be pointed elsewhere. */\nexport function isAllowedEmbedSrc(src: string | null | undefined): boolean {\n if (!src) return false;\n return toEmbedUrl(src)?.src === src;\n}\n\n/** Fixed iframe attributes for an embed; sanitizers overwrite whatever the author's HTML carried. */\nexport const EMBED_IFRAME_ATTRS: Readonly<Record<string, string>> = {\n allow: \"fullscreen; picture-in-picture; encrypted-media\",\n allowfullscreen: \"\",\n loading: \"lazy\",\n referrerpolicy: \"strict-origin-when-cross-origin\",\n sandbox: \"allow-scripts allow-same-origin allow-presentation allow-popups allow-popups-to-escape-sandbox\",\n};\n\n/** Fixed `<video>` attributes: player controls, no autoplay or loop. */\nexport const VIDEO_ATTRS: Readonly<Record<string, string>> = { controls: \"\", preload: \"metadata\", playsinline: \"\" };\n\n/** `<video src>` / `poster` must be plain http(s): no data:, blob: or relative URLs (bodies render on customer sites). */\nexport function isSafeMediaUrl(url: string | null | undefined): boolean {\n if (!url) return false;\n try {\n const u = new URL(url);\n return (u.protocol === \"https:\" || u.protocol === \"http:\") && !u.username && !u.password;\n } catch {\n return false;\n }\n}\n","/**\n * Resource center structure shared by every SDK: nested collections and audience targeting.\n *\n * Audience targeting decides what the help widget lists; it is not access control. The published\n * config (and every article body) is the same for all visitors of an environment, and end-user\n * identities are self-asserted, so never rely on it to keep an article private.\n */\n\n/** Collections nest at most this deep (a collection, its sections, and their sub-sections). */\nexport const MAX_COLLECTION_DEPTH = 3;\n\nexport interface RcCollectionLike {\n id: string;\n name: string;\n order: number;\n /** Parent collection; null/absent for a top-level collection. */\n parentId?: string | null;\n /** Shown only to members of any of these audiences; empty/absent means everyone. */\n audienceIds?: string[];\n}\n\nexport interface RcArticleLike {\n id: string;\n collectionId?: string | null;\n audienceIds?: string[];\n}\n\nexport interface RcSection<C extends RcCollectionLike, A extends RcArticleLike> {\n /** null for articles outside any (known) collection. */\n collection: C | null;\n /** Collection names from the top level down, e.g. [\"Billing\", \"Invoices\"]. */\n path: string[];\n /** 0 for a top-level collection. */\n depth: number;\n articles: A[];\n}\n\ntype Membership = ReadonlySet<string> | readonly string[] | undefined | null;\n\n/** True when an item targeted at `required` audiences is shown to someone in `member`. */\nexport function matchesAudiences(required: readonly string[] | undefined | null, member: Membership): boolean {\n if (!required || required.length === 0) return true;\n if (!member) return false;\n const has = member instanceof Set ? (id: string) => member.has(id) : (id: string) => (member as readonly string[]).includes(id);\n return required.some(has);\n}\n\n/**\n * Article sections in display order: each collection (depth first, siblings by `order`) with the\n * visible articles filed directly in it, then the uncategorized articles. A collection the viewer\n * isn't targeted by hides its whole subtree, and sections without visible articles are left out\n * (their sub-collections still appear). Unknown parents count as top level, so an old config or a\n * dangling reference never hides content.\n */\nexport function resourceCenterSections<C extends RcCollectionLike, A extends RcArticleLike>(collections: readonly C[], articles: readonly A[], member?: Membership): Array<RcSection<C, A>> {\n const byId = new Map(collections.map((c) => [c.id, c]));\n const children = new Map<string | null, C[]>();\n for (const c of collections) {\n const parent = c.parentId && c.parentId !== c.id && byId.has(c.parentId) ? c.parentId : null;\n const list = children.get(parent) ?? [];\n list.push(c);\n children.set(parent, list);\n }\n for (const list of children.values()) list.sort((a, b) => a.order - b.order || a.name.localeCompare(b.name));\n const direct = new Map<string, A[]>();\n const uncategorized: A[] = [];\n for (const a of articles) {\n if (!matchesAudiences(a.audienceIds, member)) continue;\n if (a.collectionId && byId.has(a.collectionId)) {\n const list = direct.get(a.collectionId) ?? [];\n list.push(a);\n direct.set(a.collectionId, list);\n } else uncategorized.push(a);\n }\n\n const sections: Array<RcSection<C, A>> = [];\n const seen = new Set<string>();\n const visit = (c: C, path: string[]) => {\n // A parent cycle in bad data would otherwise recurse forever; cycle members simply don't show.\n if (seen.has(c.id)) return;\n seen.add(c.id);\n if (!matchesAudiences(c.audienceIds, member)) return;\n const here = [...path, c.name];\n const list = direct.get(c.id);\n if (list?.length) sections.push({ collection: c, path: here, depth: here.length - 1, articles: list });\n for (const child of children.get(c.id) ?? []) visit(child, here);\n };\n for (const root of children.get(null) ?? []) visit(root, []);\n if (uncategorized.length) sections.push({ collection: null, path: [], depth: 0, articles: uncategorized });\n return sections;\n}\n\n/**\n * Whether one article is listed for a viewer: its own audiences and those of every collection above\n * it must match. For articles outside a loaded list (e.g. server search results).\n */\nexport function isArticleListed(collections: readonly RcCollectionLike[], article: RcArticleLike, member?: Membership): boolean {\n if (!matchesAudiences(article.audienceIds, member)) return false;\n const byId = new Map(collections.map((c) => [c.id, c]));\n let cur = article.collectionId ? byId.get(article.collectionId) : undefined;\n for (let guard = 0; cur && guard <= MAX_COLLECTION_DEPTH * 4; guard++) {\n if (!matchesAudiences(cur.audienceIds, member)) return false;\n cur = cur.parentId ? byId.get(cur.parentId) : undefined;\n }\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Logged-in only articles\n// ---------------------------------------------------------------------------\n\n/** Who an article is listed for, besides its audiences: everyone, or logged-in (identified) visitors only. */\nexport const ARTICLE_VISIBILITIES = [\"everyone\", \"identified\"] as const;\nexport type ArticleVisibility = (typeof ARTICLE_VISIBILITIES)[number];\n\n/**\n * Reserved audience every logged-in visitor belongs to. The server folds an article's visibility into\n * the audiences it serves and adds this one to identified visitors' memberships, so every SDK (old ones\n * too) applies \"logged-in only\" through the audience matching it already does. Anonymous visitors never\n * identify, so their membership is empty and these articles stay hidden.\n */\nexport const LOGGED_IN_AUDIENCE = \"$identified\";\n\n/**\n * The audiences an article is served with. Logged-in only with no audiences becomes the reserved\n * audience; with audiences it is already implied, since audience membership only comes from identify.\n */\nexport function servedArticleAudiences(audienceIds: readonly string[], visibility: ArticleVisibility | string | null | undefined): string[] {\n return visibility === \"identified\" && audienceIds.length === 0 ? [LOGGED_IN_AUDIENCE] : [...audienceIds];\n}\n\n/** A visitor's memberships as matched against served articles: logged-in visitors are also in `LOGGED_IN_AUDIENCE`. */\nexport function visitorAudiences(audienceIds: readonly string[], identified: boolean): string[] {\n const ids = audienceIds.filter((id) => id !== LOGGED_IN_AUDIENCE);\n return identified ? [...ids, LOGGED_IN_AUDIENCE] : ids;\n}\n\n/** Ids of the articles a viewer sees (for filtering server search results the same way). */\nexport function visibleArticleIds(collections: readonly RcCollectionLike[], articles: readonly RcArticleLike[], member?: Membership): Set<string> {\n return new Set(resourceCenterSections(collections, articles, member).flatMap((s) => s.articles.map((a) => a.id)));\n}\n\n// ---------------------------------------------------------------------------\n// \"Show me\" prompts in help articles\n// ---------------------------------------------------------------------------\n\n/**\n * A \"Show me\" prompt in an article body is a plain link, `<p class=\"gd-show-me\"><a href=\"#guidely-show-me:<guide key>\">Show me how</a></p>`,\n * so it survives every sanitizer and reads as a harmless link anywhere else. The widgets turn it into a\n * button that starts the walkthrough (a live flow guide), or hide it when that guide isn't available.\n */\nexport const SHOW_ME_CLASS = \"gd-show-me\";\nexport const SHOW_ME_HREF_PREFIX = \"#guidely-show-me:\";\nconst SHOW_ME_KEY = /^[A-Za-z0-9_-]{1,64}$/;\n\nexport function showMeHref(guideKey: string): string {\n return `${SHOW_ME_HREF_PREFIX}${guideKey}`;\n}\n\n/** The guide key of a Show me link's `href`, or null. */\nexport function showMeKeyFromHref(href: string | null | undefined): string | null {\n if (!href || !href.startsWith(SHOW_ME_HREF_PREFIX)) return null;\n const key = href.slice(SHOW_ME_HREF_PREFIX.length);\n return SHOW_ME_KEY.test(key) ? key : null;\n}\n\n/** Guide keys of the Show me prompts in an article body, in order, without repeats (at most 10). */\nexport function showMeKeys(html: string | null | undefined): string[] {\n const out: string[] = [];\n for (const m of (html ?? \"\").matchAll(/href=\"#guidely-show-me:([A-Za-z0-9_-]{1,64})\"/g)) if (!out.includes(m[1]!)) out.push(m[1]!);\n return out.slice(0, 10);\n}\n\n/** The article body plays a video (uploaded, or embedded from YouTube, Vimeo, Loom or Wistia). */\nexport function hasVideoMedia(html: string | null | undefined): boolean {\n return /<(video|iframe)\\b/i.test(html ?? \"\");\n}\n\nconst words = (s: string) => s.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [];\n\n/**\n * Help search on the device: every word of the query starts a word of the text, in any order, or the\n * query appears as typed. \"add user\" finds \"Add a new user\" and \"Users › Add\".\n */\nexport function matchesHelpQuery(text: string, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n const hay = text.toLowerCase();\n if (hay.includes(q)) return true;\n const terms = words(q);\n if (!terms.length) return false;\n const have = words(hay);\n return terms.every((t) => have.some((w) => w.startsWith(t) || (t.length > 3 && t.endsWith(\"s\") && w.startsWith(t.slice(0, -1)))));\n}\n\n// ---------------------------------------------------------------------------\n// Modules (section order + targeting) and \"What's new\"\n// ---------------------------------------------------------------------------\n\nexport const RC_MODULE_IDS = [\"announcements\", \"search\", \"checklists\", \"guides\", \"articles\", \"links\", \"faqs\"] as const;\nexport type ResourceCenterModuleId = (typeof RC_MODULE_IDS)[number];\n\nexport const RC_MODULE_LABELS: Record<ResourceCenterModuleId, string> = {\n announcements: \"What's new\",\n search: \"Search\",\n checklists: \"Checklists\",\n guides: \"Guides & tours\",\n articles: \"Articles\",\n links: \"Links\",\n faqs: \"FAQs\",\n};\n\n/**\n * The resource center's sections in display order: the configured modules (unknown ids dropped,\n * missing ones appended enabled, in the default order), so an old config shows every section.\n */\nexport function orderedModules<M extends { id: string; enabled: boolean }>(modules: readonly M[] | null | undefined): Array<M | { id: ResourceCenterModuleId; enabled: true }> {\n const known = (modules ?? []).filter((m, i, all) => (RC_MODULE_IDS as readonly string[]).includes(m.id) && all.findIndex((x) => x.id === m.id) === i);\n const missing = RC_MODULE_IDS.filter((id) => !known.some((m) => m.id === id)).map((id) => ({ id, enabled: true as const }));\n return [...known, ...missing];\n}\n\n/** Announcements a visitor sees: published (not in the future), audience-matched, newest first. */\nexport function visibleAnnouncements<A extends { publishedAt: string; audienceIds?: string[] }>(items: readonly A[] | null | undefined, member?: Membership, now: number = Date.now()): A[] {\n return (items ?? [])\n .filter((a) => {\n const t = Date.parse(a.publishedAt);\n return !Number.isNaN(t) && t <= now && matchesAudiences(a.audienceIds, member);\n })\n .sort((a, b) => Date.parse(b.publishedAt) - Date.parse(a.publishedAt));\n}\n\n/** Unread count for the launcher badge: announcements published after the visitor last opened \"What's new\". */\nexport function unreadAnnouncements(items: readonly { publishedAt: string }[], lastSeenAt: string | null | undefined): number {\n const seen = lastSeenAt ? Date.parse(lastSeenAt) : NaN;\n if (Number.isNaN(seen)) return items.length;\n return items.filter((a) => Date.parse(a.publishedAt) > seen).length;\n}\n","/** How-to capture constants the browser SDK needs without zod (also exported from `@guidelytech/shared/runtime`). */\n\n/** Query parameter that starts capture mode in the SDK (separate from `guidely_authoring`, so SDKs without capture ignore it). */\nexport const CAPTURE_PARAM = \"guidely_capture\";\n/** Largest screenshot the capture endpoint accepts. */\nexport const CAPTURE_SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;\n","/**\n * Page helpers shared by the SDK (page-aware messenger) and the server (page matching, analytics).\n * Pure and zod-free.\n */\n\n/**\n * One path segment that looks like an identifier: digits, a UUID, or a long hex string (hashes,\n * Mongo ids). Written so the same source works as a JS RegExp and a Postgres ARE (`regexp_replace`\n * with flags `gi`), which keeps id folding identical in SQL and in code. A segment may be followed\n * by the page query parameters a project keeps in its paths (`/contacts/42?tab=notes`).\n */\nexport const PATH_ID_PATTERN = \"/([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12,})(?=[/?]|$)\";\n\n/** `/contacts/42/notes/9f8e…` → `/contacts/:id/notes/:id`; `/contacts/42?tab=notes` → `/contacts/:id?tab=notes`. */\nexport function foldPathIds(path: string): string {\n return path.replace(new RegExp(PATH_ID_PATTERN, \"gi\"), \"/:id\");\n}\n\n/** Path segments that say nothing about what a page is for. */\nconst GENERIC_SEGMENTS = new Set([\"\", \":id\", \"app\", \"apps\", \"dashboard\", \"home\", \"index\", \"main\", \"new\", \"edit\", \"view\", \"show\", \"details\", \"detail\", \"overview\", \"list\", \"all\", \"page\", \"pages\", \"en\", \"v1\", \"v2\"]);\n\nfunction segmentsOf(path: string): string[] {\n const clean = foldPathIds((path.split(/[?#]/)[0] || \"/\").toLowerCase());\n return clean\n .split(\"/\")\n .map((s) => s.replace(/\\.(html?|php|aspx?)$/, \"\"))\n .filter((s) => !GENERIC_SEGMENTS.has(s) && /[a-z]/.test(s) && s.length <= 40);\n}\n\n/** Words describing a page, from its path (`/settings/billing-plans/42` → `settings billing plans`). */\nexport function pageTerms(path: string): string[] {\n const words = segmentsOf(path).flatMap((s) => s.split(/[-_.+\\s]+/).filter((w) => w.length > 1 && /[a-z]/.test(w)));\n return [...new Set(words)].slice(0, 8);\n}\n\n/** A short human name for a page (`/app/invoices/42` → `Invoices`), or null for the root and unnamed pages. */\nexport function pageLabel(path: string): string | null {\n const last = segmentsOf(path).at(-1);\n if (!last) return null;\n const words = last.split(/[-_.+\\s]+/).filter(Boolean);\n if (!words.length) return null;\n const label = words.join(\" \");\n return label.charAt(0).toUpperCase() + label.slice(1);\n}\n\n/** The first name in a user's traits (`firstName`, `first_name`, or the first word of `name`), or null. */\nexport function firstNameFromTraits(traits: Record<string, unknown> | null | undefined): string | null {\n if (!traits) return null;\n const pick = (v: unknown) => (typeof v === \"string\" ? v.trim() : \"\");\n const first = pick(traits.firstName) || pick(traits.first_name) || pick(traits.firstname) || pick(traits.name).split(/\\s+/)[0] || \"\";\n // Never greet someone by an email address or an id.\n if (!first || first.length > 40 || first.includes(\"@\") || !/\\p{L}/u.test(first)) return null;\n return first;\n}\n","/**\n * Tagged pages and features (named rules over the URLs and clicks the SDK captures), shared by the server (retroactive\n * matching, SQL generation), the dashboard (previews) and the SDK (event properties). Pure and zod-free.\n *\n * - An `ElementSnapshot` is the compact description of a clicked element the SDK attaches to `click`\n * events (`properties.el`): tag, id, classes, a few safe attributes, nth-of-type, ~5 ancestors and\n * the shadow hosts above it. CSS selector rules are evaluated against it with {@link matchCssSelector},\n * so a rule written today also matches clicks stored before it existed.\n * - Older clicks carry only a selector string; {@link snapshotFromSelector} turns that string into a\n * partial snapshot so CSS rules still match them where the string says enough.\n */\n\n// ---------------------------------------------------------------------------\n// Element snapshots\n// ---------------------------------------------------------------------------\n\n/** One element in a snapshot: tag, id, classes, safe attributes and its 1-based nth-of-type. */\nexport interface ElementNode {\n t: string;\n id?: string;\n c?: string[];\n a?: Record<string, string>;\n n?: number;\n}\n\n/** A clicked element (`click.properties.el`): the element, its ancestors (`p`, parent first) and shadow hosts (`h`, nearest first). */\nexport interface ElementSnapshot extends ElementNode {\n p?: ElementNode[];\n h?: ElementNode[];\n}\n\nexport const SNAPSHOT_LIMITS = { classes: 8, className: 60, attrs: 6, attrValue: 100, ancestors: 5, hosts: 3, tag: 40, id: 80 } as const;\n\n/** Attributes a snapshot may carry besides `data-*` ones. Never `value`, never event handlers. */\nexport const SNAPSHOT_ATTRS = [\"role\", \"name\", \"type\", \"aria-label\", \"title\", \"alt\", \"for\", \"href\"] as const;\n\n/** Framework and state `data-*` attributes that say nothing stable about an element. */\nexport const NOISY_DATA_ATTR = /^data-(state|v-|react|radix|headlessui|svelte|orientation|highlighted|focus|key|index|side|align|disabled|selected|active|open|rbd|dnd|sveltekit|guidely-(mask|ignore|block))/i;\n\n/** The custom attribute that names a feature by default (`<button data-guidely-feature=\"Export CSV\">`). */\nexport const DEFAULT_FEATURE_ATTRIBUTE = \"data-guidely-feature\";\nexport const FEATURE_ATTRIBUTE_PATTERN = /^data-[a-z0-9][a-z0-9_.-]{0,60}$/;\n\nfunction str(v: unknown, max: number): string | undefined {\n return typeof v === \"string\" && v ? v.slice(0, max) : undefined;\n}\n\nfunction cleanNode(raw: unknown): ElementNode | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n const t = str(r.t, SNAPSHOT_LIMITS.tag)?.toLowerCase();\n if (!t || !/^[a-z][a-z0-9-]*$/.test(t)) return null;\n const node: ElementNode = { t };\n const id = str(r.id, SNAPSHOT_LIMITS.id);\n if (id) node.id = id;\n if (Array.isArray(r.c)) {\n const c = r.c.filter((x): x is string => typeof x === \"string\" && !!x && x.length <= SNAPSHOT_LIMITS.className && !/\\s/.test(x)).slice(0, SNAPSHOT_LIMITS.classes);\n if (c.length) node.c = c;\n }\n if (r.a && typeof r.a === \"object\" && !Array.isArray(r.a)) {\n const a: Record<string, string> = {};\n for (const [k, v] of Object.entries(r.a as Record<string, unknown>)) {\n if (Object.keys(a).length >= SNAPSHOT_LIMITS.attrs) break;\n const key = k.toLowerCase();\n if (typeof v !== \"string\" || !(key.startsWith(\"data-\") || (SNAPSHOT_ATTRS as readonly string[]).includes(key)) || key === \"value\" || key.length > 60) continue;\n a[key] = v.slice(0, SNAPSHOT_LIMITS.attrValue);\n }\n if (Object.keys(a).length) node.a = a;\n }\n if (typeof r.n === \"number\" && Number.isInteger(r.n) && r.n >= 1 && r.n <= 10_000) node.n = r.n;\n return node;\n}\n\n/** Validates and trims a snapshot sent by an SDK (server side); null when it is not one. */\nexport function normalizeSnapshot(raw: unknown): ElementSnapshot | null {\n const el = cleanNode(raw);\n if (!el) return null;\n const r = raw as Record<string, unknown>;\n const out: ElementSnapshot = el;\n if (Array.isArray(r.p)) {\n const p = r.p.slice(0, SNAPSHOT_LIMITS.ancestors).map(cleanNode);\n // Ancestors are consecutive; stop at the first unusable one rather than skipping it.\n const cut = p.indexOf(null);\n const list = (cut === -1 ? p : p.slice(0, cut)) as ElementNode[];\n if (list.length) out.p = list;\n }\n if (Array.isArray(r.h)) {\n const h = r.h.slice(0, SNAPSHOT_LIMITS.hosts).map(cleanNode).filter((x): x is ElementNode => !!x);\n if (h.length) out.h = h;\n }\n return out;\n}\n\n/** JSON with sorted keys, so equal snapshots hash the same whatever order the SDK wrote them in. */\nexport function stableStringify(v: unknown): string {\n if (Array.isArray(v)) return `[${v.map(stableStringify).join(\",\")}]`;\n if (v && typeof v === \"object\") {\n const o = v as Record<string, unknown>;\n return `{${Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${stableStringify(o[k])}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(v ?? null);\n}\n\n// ---------------------------------------------------------------------------\n// CSS selector subset: parse + match against a snapshot\n// ---------------------------------------------------------------------------\n\nexport type AttrOp = \"exists\" | \"=\" | \"^=\" | \"$=\" | \"*=\" | \"~=\" | \"|=\";\n\nexport interface AttrTest {\n name: string;\n op: AttrOp;\n value?: string;\n /** `[attr=\"x\" i]` */\n insensitive?: boolean;\n}\n\nexport interface Compound {\n tag?: string;\n id?: string;\n classes: string[];\n attrs: AttrTest[];\n /** `:nth-of-type(n)`; `odd`/`even` as `{ a: 2, b: 1|0 }`; `:first-of-type` is `{ a: 0, b: 1 }`. */\n nth?: { a: number; b: number };\n}\n\n/** A complex selector: compounds left to right and the combinator before each (index 0 has none). */\nexport interface ComplexSelector {\n compounds: Compound[];\n combinators: Array<\" \" | \">\" | \">>>\">;\n}\n\nexport class SelectorSyntaxError extends Error {}\n\nconst IDENT_START = /[A-Za-z_\\u00a0-\\uffff-]/;\nconst IDENT_CHAR = /[A-Za-z0-9_\\u00a0-\\uffff-]/;\n\n/**\n * Parses the supported subset: type and universal selectors, `#id`, `.class`, `[attr]`,\n * `[attr=v]`, `^=`, `$=`, `*=`, `~=`, `|=` (optionally `i`), `:nth-of-type(n|odd|even)`,\n * `:first-of-type`, descendant and child combinators, `>>>` (shadow host) and selector lists.\n * Throws {@link SelectorSyntaxError} on anything else.\n */\nexport function parseCssSelector(input: string): ComplexSelector[] {\n const s = input.trim();\n if (!s) throw new SelectorSyntaxError(\"Empty selector\");\n if (s.length > 1000) throw new SelectorSyntaxError(\"Selector is too long\");\n let i = 0;\n const peek = () => s[i];\n const eof = () => i >= s.length;\n const fail = (msg: string): never => {\n throw new SelectorSyntaxError(`${msg} at position ${i + 1}`);\n };\n const ws = () => {\n let any = false;\n while (!eof() && /\\s/.test(s[i]!)) {\n i++;\n any = true;\n }\n return any;\n };\n const escape = (): string => {\n // after the backslash\n i++;\n const hex = /^[0-9a-fA-F]{1,6}/.exec(s.slice(i));\n if (hex) {\n i += hex[0].length;\n if (s[i] === \" \") i++;\n return String.fromCodePoint(parseInt(hex[0], 16));\n }\n if (eof()) fail(\"Unfinished escape\");\n return s[i++]!;\n };\n const ident = (): string => {\n let out = \"\";\n if (s[i] === \"\\\\\") out += escape();\n else if (!eof() && IDENT_START.test(s[i]!)) out += s[i++];\n else fail(\"Expected a name\");\n while (!eof()) {\n if (s[i] === \"\\\\\") out += escape();\n else if (IDENT_CHAR.test(s[i]!)) out += s[i++];\n else break;\n }\n return out;\n };\n const quoted = (): string => {\n const q = s[i++];\n let out = \"\";\n while (!eof() && s[i] !== q) {\n if (s[i] === \"\\\\\") out += escape();\n else out += s[i++];\n }\n if (eof()) fail(\"Unterminated string\");\n i++;\n return out;\n };\n const compound = (): Compound | null => {\n const c: Compound = { classes: [], attrs: [] };\n let any = false;\n if (peek() === \"*\") {\n i++;\n any = true;\n } else if (!eof() && (IDENT_START.test(peek()!) || peek() === \"\\\\\")) {\n c.tag = ident().toLowerCase();\n any = true;\n }\n for (;;) {\n const ch = peek();\n if (ch === \"#\") {\n i++;\n c.id = ident();\n } else if (ch === \".\") {\n i++;\n c.classes.push(ident());\n } else if (ch === \"[\") {\n i++;\n ws();\n const name = ident().toLowerCase();\n ws();\n let op: AttrOp = \"exists\";\n let value: string | undefined;\n let insensitive = false;\n if (peek() !== \"]\") {\n const m = /^(=|\\^=|\\$=|\\*=|~=|\\|=)/.exec(s.slice(i));\n if (!m) fail(\"Unsupported attribute operator\");\n op = m![1] as AttrOp;\n i += m![1]!.length;\n ws();\n value = peek() === '\"' || peek() === \"'\" ? quoted() : ident();\n ws();\n if (peek() === \"i\" || peek() === \"I\") {\n i++;\n insensitive = true;\n ws();\n } else if (peek() === \"s\" || peek() === \"S\") {\n i++;\n ws();\n }\n }\n if (peek() !== \"]\") fail(\"Expected ]\");\n i++;\n c.attrs.push({ name, op, ...(value !== undefined ? { value } : {}), ...(insensitive ? { insensitive } : {}) });\n } else if (ch === \":\") {\n i++;\n if (peek() === \":\") fail(\"Pseudo-elements are not supported\");\n const name = ident().toLowerCase();\n if (name === \"first-of-type\") c.nth = { a: 0, b: 1 };\n else if (name === \"nth-of-type\") {\n if (peek() !== \"(\") fail(\"Expected (\");\n i++;\n ws();\n const m = /^(odd|even|\\d+)/i.exec(s.slice(i));\n if (!m) fail(\"Only :nth-of-type(n), odd or even are supported\");\n i += m![0].length;\n ws();\n if (peek() !== \")\") fail(\"Expected )\");\n i++;\n const v = m![0].toLowerCase();\n c.nth = v === \"odd\" ? { a: 2, b: 1 } : v === \"even\" ? { a: 2, b: 0 } : { a: 0, b: Number(v) };\n } else fail(`Unsupported pseudo-class :${name}`);\n } else break;\n any = true;\n }\n return any ? c : null;\n };\n\n const list: ComplexSelector[] = [];\n for (;;) {\n ws();\n const sel: ComplexSelector = { compounds: [], combinators: [] };\n const first = compound();\n if (!first) fail(\"Expected a selector\");\n sel.compounds.push(first!);\n for (;;) {\n const hadWs = ws();\n if (eof() || peek() === \",\") break;\n let comb: \" \" | \">\" | \">>>\" = \" \";\n if (s.startsWith(\">>>\", i)) {\n comb = \">>>\";\n i += 3;\n ws();\n } else if (peek() === \">\") {\n comb = \">\";\n i++;\n ws();\n } else if (peek() === \"+\" || peek() === \"~\") fail(\"Sibling combinators are not supported\");\n else if (!hadWs) fail(\"Unexpected character\");\n const next = compound();\n if (!next) fail(\"Expected a selector after the combinator\");\n sel.compounds.push(next!);\n sel.combinators.push(comb);\n }\n list.push(sel);\n if (eof()) break;\n i++; // \",\"\n }\n return list;\n}\n\n/** Is the selector inside the supported subset? Returns the error message, or null when it parses. */\nexport function cssSelectorError(selector: string): string | null {\n try {\n parseCssSelector(selector);\n return null;\n } catch (e) {\n return e instanceof Error ? e.message : \"Invalid selector\";\n }\n}\n\nfunction attrMatches(test: AttrTest, node: ElementNode): boolean {\n let actual: string | undefined;\n if (test.name === \"id\") actual = node.id;\n else if (test.name === \"class\") actual = node.c?.join(\" \");\n else actual = node.a?.[test.name];\n if (actual === undefined) return false;\n if (test.op === \"exists\") return true;\n let v = test.value ?? \"\";\n if (test.insensitive) {\n actual = actual.toLowerCase();\n v = v.toLowerCase();\n }\n switch (test.op) {\n case \"=\":\n return actual === v;\n case \"^=\":\n return !!v && actual.startsWith(v);\n case \"$=\":\n return !!v && actual.endsWith(v);\n case \"*=\":\n return !!v && actual.includes(v);\n case \"~=\":\n return !!v && actual.split(/\\s+/).includes(v);\n case \"|=\":\n return actual === v || actual.startsWith(`${v}-`);\n default:\n return false;\n }\n}\n\n/** Does one compound match one node? An unknown nth-of-type fails `:nth-of-type` tests. */\nexport function compoundMatches(c: Compound, node: ElementNode): boolean {\n if (c.tag && c.tag !== node.t) return false;\n if (c.id !== undefined && node.id !== c.id) return false;\n for (const cls of c.classes) if (!node.c?.includes(cls)) return false;\n for (const a of c.attrs) if (!attrMatches(a, node)) return false;\n if (c.nth) {\n if (!node.n) return false;\n const { a, b } = c.nth;\n if (a === 0 ? node.n !== b : (node.n - b) % a !== 0 || (node.n - b) / a < 0) return false;\n }\n return true;\n}\n\n/** Matches compounds (right to left) against a chain of nodes: index 0 is the element, then its ancestors. */\nfunction chainMatches(compounds: Compound[], combinators: Array<\" \" | \">\">, nodes: ElementNode[], ci = compounds.length - 1, ni = 0): boolean {\n if (!compoundMatches(compounds[ci]!, nodes[ni]!)) return false;\n if (ci === 0) return true;\n const comb = combinators[ci - 1]!;\n if (comb === \">\") return ni + 1 < nodes.length && chainMatches(compounds, combinators, nodes, ci - 1, ni + 1);\n for (let k = ni + 1; k < nodes.length; k++) if (chainMatches(compounds, combinators, nodes, ci - 1, k)) return true;\n return false;\n}\n\nfunction complexMatches(sel: ComplexSelector, snap: ElementSnapshot): boolean {\n // Split at `>>>`: the last segment is matched inside the element's own tree, each earlier\n // segment's last compound against a shadow host further out (any depth, like the runtime).\n const segments: Array<{ compounds: Compound[]; combinators: Array<\" \" | \">\"> }> = [{ compounds: [sel.compounds[0]!], combinators: [] }];\n sel.combinators.forEach((comb, k) => {\n const next = sel.compounds[k + 1]!;\n if (comb === \">>>\") segments.push({ compounds: [next], combinators: [] });\n else {\n const seg = segments[segments.length - 1]!;\n seg.compounds.push(next);\n seg.combinators.push(comb);\n }\n });\n const last = segments.pop()!;\n const nodes: ElementNode[] = [snap, ...(snap.p ?? [])];\n if (!chainMatches(last.compounds, last.combinators, nodes)) return false;\n const hosts = snap.h ?? [];\n let from = 0;\n for (let k = segments.length - 1; k >= 0; k--) {\n const target = segments[k]!.compounds[segments[k]!.compounds.length - 1]!;\n let found = -1;\n for (let j = from; j < hosts.length; j++) {\n if (compoundMatches(target, hosts[j]!)) {\n found = j;\n break;\n }\n }\n if (found === -1) return false;\n from = found + 1;\n }\n return true;\n}\n\nconst parsedCache = new Map<string, ComplexSelector[] | null>();\n\n/** Does a CSS selector (subset, see {@link parseCssSelector}) match the snapshot? Invalid selectors match nothing. */\nexport function matchCssSelector(selector: string | ComplexSelector[], snap: ElementSnapshot): boolean {\n let list: ComplexSelector[] | null;\n if (typeof selector === \"string\") {\n if (!parsedCache.has(selector)) {\n if (parsedCache.size > 500) parsedCache.clear();\n try {\n parsedCache.set(selector, parseCssSelector(selector));\n } catch {\n parsedCache.set(selector, null);\n }\n }\n list = parsedCache.get(selector)!;\n } else list = selector;\n return !!list && list.some((sel) => complexMatches(sel, snap));\n}\n\nfunction nodeOfCompound(c: Compound): ElementNode {\n const node: ElementNode = { t: c.tag ?? \"*\" };\n if (c.id) node.id = c.id;\n if (c.classes.length) node.c = c.classes.slice(0, SNAPSHOT_LIMITS.classes);\n const a: Record<string, string> = {};\n for (const t of c.attrs) if (t.op === \"=\" && t.value !== undefined) a[t.name] = t.value;\n if (Object.keys(a).length) node.a = a;\n if (c.nth && c.nth.a === 0) node.n = c.nth.b;\n return node;\n}\n\n/**\n * A partial snapshot read from a stored selector string (clicks captured before snapshots existed):\n * `#form > div:nth-of-type(2) > button[data-testid=\"save\"]` becomes a `button` with that attribute,\n * nth 1-unknown, and two ancestors. Shadow steps (`c-app >>> button`) become hosts. Null when the\n * string is not a selector in the supported subset.\n */\nexport function snapshotFromSelector(selector: string, tag?: string | null): ElementSnapshot | null {\n let list: ComplexSelector[];\n try {\n list = parseCssSelector(selector);\n } catch {\n return null;\n }\n if (list.length !== 1) return null;\n const sel = list[0]!;\n const segments: Compound[][] = [[sel.compounds[0]!]];\n sel.combinators.forEach((comb, k) => {\n if (comb === \">>>\") segments.push([sel.compounds[k + 1]!]);\n else segments[segments.length - 1]!.push(sel.compounds[k + 1]!);\n });\n const own = segments.pop()!;\n const el = nodeOfCompound(own[own.length - 1]!);\n if (el.t === \"*\" && tag && /^[a-z][a-z0-9-]*$/i.test(tag)) el.t = tag.toLowerCase();\n const snap: ElementSnapshot = el;\n const p = own.slice(0, -1).reverse().map(nodeOfCompound);\n if (p.length) snap.p = p.slice(0, SNAPSHOT_LIMITS.ancestors);\n const h = segments.reverse().map((seg) => nodeOfCompound(seg[seg.length - 1]!));\n if (h.length) snap.h = h.slice(0, SNAPSHOT_LIMITS.hosts);\n return snap;\n}\n\n// ---------------------------------------------------------------------------\n// Page rules\n// ---------------------------------------------------------------------------\n\nexport type QueryParamOp = \"exists\" | \"absent\" | \"equals\" | \"contains\";\nexport interface QueryParamCondition {\n name: string;\n op: QueryParamOp;\n value?: string;\n}\n\n/**\n * One way a URL belongs to a page. `url`: a pattern (`/accounts/:id/settings`, `/reports/*`,\n * `/docs/**`, `//*\\/billing`, `https://app.acme.com/x`) plus optional query conditions; `regex`: a\n * regular expression over the path; `title`: the document title (`equals` / `contains`). With\n * `exclude`, matching URLs are taken out of the page instead.\n */\nexport interface PageRule {\n id?: string;\n type: \"url\" | \"regex\" | \"title\";\n value: string;\n op?: \"equals\" | \"contains\";\n query?: QueryParamCondition[];\n exclude?: boolean;\n}\n\nexport const PAGE_RULE_LIMITS = { rules: 20, value: 500, query: 5 } as const;\n\nexport interface PagePattern {\n /** Anchored regex source, valid both as a JS RegExp (flag `i`) and a Postgres ARE (`~*`). */\n source: string;\n /** What it runs against: the path (query removed) or the full URL without query and hash. */\n target: \"path\" | \"url\";\n /** Query conditions written into the pattern (`/search?tab=people`). */\n query: QueryParamCondition[];\n}\n\nconst escapeRe = (s: string) => s.replace(/[.+?^${}()|[\\]\\\\*]/g, \"\\\\$&\");\n\nfunction globToRegex(pattern: string): string {\n let out = \"\";\n for (let k = 0; k < pattern.length; k++) {\n const ch = pattern[k]!;\n if (ch === \"*\") {\n if (pattern[k + 1] === \"*\") {\n out += \".*\";\n k++;\n } else out += \"[^/]*\";\n } else if (ch === \":\" && (k === 0 || pattern[k - 1] === \"/\") && /[A-Za-z_]/.test(pattern[k + 1] ?? \"\")) {\n // `:name` path parameter: one whole segment.\n let j = k + 1;\n while (j < pattern.length && /[\\w]/.test(pattern[j]!)) j++;\n out += \"[^/]+\";\n k = j - 1;\n } else out += escapeRe(ch);\n }\n return out;\n}\n\n/** Turns a URL rule pattern into a regex. Query parameters in the pattern become conditions. */\nexport function pagePattern(raw: string): PagePattern {\n let p = raw.trim();\n const query: QueryParamCondition[] = [];\n const hash = p.indexOf(\"#\");\n if (hash !== -1) p = p.slice(0, hash);\n const q = p.indexOf(\"?\");\n if (q !== -1) {\n for (const part of p.slice(q + 1).split(\"&\")) {\n if (!part) continue;\n const eq = part.indexOf(\"=\");\n const name = decodeSafe(eq === -1 ? part : part.slice(0, eq));\n const value = eq === -1 ? undefined : decodeSafe(part.slice(eq + 1));\n if (!name) continue;\n query.push(value === undefined || value === \"*\" ? { name, op: \"exists\" } : { name, op: \"equals\", value });\n }\n p = p.slice(0, q);\n }\n let target: \"path\" | \"url\" = \"path\";\n // `//*` means any domain: keep only the path.\n if (p.startsWith(\"//*\")) p = p.slice(3);\n let prefix = \"\";\n const abs = /^(https?:)?\\/\\/([^/]+)(.*)$/i.exec(p);\n if (abs) {\n target = \"url\";\n prefix = `https?://${globToRegex(abs[2]!.toLowerCase())}`;\n p = abs[3] || \"/\";\n }\n if (!p.startsWith(\"/\")) p = `/${p}`;\n // A trailing slash is optional, as on most sites.\n const body = p.length > 1 && p.endsWith(\"/\") ? p.slice(0, -1) : p;\n const src = body === \"/\" ? \"/?\" : `${globToRegex(body)}/?`;\n return { source: `^${prefix}${src}$`, target, query: query.slice(0, PAGE_RULE_LIMITS.query) };\n}\n\nfunction decodeSafe(s: string): string {\n try {\n return decodeURIComponent(s.replace(/\\+/g, \" \"));\n } catch {\n return s;\n }\n}\n\n/** Regex (JS + Postgres) for a query condition over a raw URL. */\nexport function queryConditionRegex(c: QueryParamCondition): string {\n const name = escapeRe(c.name);\n switch (c.op) {\n case \"equals\":\n return `[?&]${name}=${escapeRe(encodeLoose(c.value ?? \"\"))}(&|#|$)`;\n case \"contains\":\n return `[?&]${name}=[^&#]*${escapeRe(encodeLoose(c.value ?? \"\"))}`;\n default:\n return `[?&]${name}(=|&|#|$)`;\n }\n}\n\n/** URL-encodes what browsers encode in query values, leaving the common safe characters alone. */\nfunction encodeLoose(v: string): string {\n return encodeURIComponent(v).replace(/%2F/gi, \"/\").replace(/%3A/gi, \":\").replace(/%2C/gi, \",\").replace(/%40/gi, \"@\");\n}\n\nexport interface PageContext {\n /** Full URL (with query) when known. */\n url?: string | null;\n /** Path as stored (`/a/b`, or `/a/b?section=x` with kept page parameters). */\n path?: string | null;\n title?: string | null;\n}\n\nfunction pathOnly(ctx: PageContext): string | null {\n if (ctx.path) return ctx.path.split(\"?\")[0] || \"/\";\n if (!ctx.url) return null;\n try {\n return new URL(ctx.url, \"http://x.invalid\").pathname;\n } catch {\n return null;\n }\n}\n\nfunction regexOrNull(source: string): RegExp | null {\n try {\n return new RegExp(source, \"i\");\n } catch {\n return null;\n }\n}\n\n/** JS twin of the SQL a page rule compiles to (server `pageRuleSql`). */\nexport function pageRuleMatches(rule: PageRule, ctx: PageContext): boolean {\n const path = pathOnly(ctx);\n if (rule.type === \"title\") {\n const t = (ctx.title ?? \"\").toLowerCase();\n const v = rule.value.toLowerCase();\n return !!t && (rule.op === \"contains\" ? t.includes(v) : t === v);\n }\n if (rule.type === \"regex\") {\n const re = regexOrNull(rule.value);\n return !!re && path !== null && re.test(path);\n }\n const pat = pagePattern(rule.value);\n const re = regexOrNull(pat.source);\n if (!re) return false;\n let subject: string | null = path;\n if (pat.target === \"url\") {\n if (!ctx.url) return false;\n subject = ctx.url.split(/[?#]/)[0]!;\n }\n if (subject === null || !re.test(subject)) return false;\n const conds = [...pat.query, ...(rule.query ?? [])];\n for (const c of conds) {\n const hit = !!ctx.url && new RegExp(queryConditionRegex(c), \"i\").test(ctx.url);\n if (c.op === \"absent\" ? hit : !hit) return false;\n }\n return true;\n}\n\n/** Included by any include rule and excluded by no exclude rule. */\nexport function pageRulesMatch(rules: PageRule[], ctx: PageContext): boolean {\n const include = rules.filter((r) => !r.exclude);\n if (!include.length || !include.some((r) => pageRuleMatches(r, ctx))) return false;\n return !rules.some((r) => r.exclude && pageRuleMatches(r, ctx));\n}\n\n/** Validation message for a page rule, or null. */\nexport function pageRuleError(rule: PageRule): string | null {\n const v = rule.value?.trim();\n if (!v) return \"A rule needs a value\";\n if (v.length > PAGE_RULE_LIMITS.value) return \"The rule is too long\";\n if (rule.type === \"regex\") {\n if (!regexOrNull(v)) return `\"${v}\" is not a valid regular expression`;\n if (/\\(\\?[<=!]/.test(v) || /\\\\[1-9]/.test(v)) return \"Look-arounds and back-references are not supported\";\n }\n if (rule.type === \"url\" && !regexOrNull(pagePattern(v).source)) return `\"${v}\" is not a valid URL rule`;\n for (const q of rule.query ?? []) if (!/^[A-Za-z0-9_.\\-[\\]]{1,60}$/.test(q.name)) return `\"${q.name}\" is not a query parameter name`;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Feature rules\n// ---------------------------------------------------------------------------\n\nexport type SelectorOp = \"exact\" | \"prefix\" | \"contains\" | \"glob\" | \"css\";\n\n/**\n * One way a click belongs to a feature. Every condition present must hold. `selector.op = \"css\"`\n * evaluates a CSS selector against the element snapshot (or, for old clicks, the snapshot read from\n * the stored selector string); the other selector operators compare the stored selector string —\n * mobile taps store the accessibility id / `data-guidely-id` there, so `exact` works for them too.\n */\nexport interface FeatureRule {\n id?: string;\n selector?: { op: SelectorOp; value: string };\n text?: { op: \"equals\" | \"contains\"; value: string };\n tag?: string;\n href?: { op: \"equals\" | \"prefix\" | \"contains\"; value: string };\n /** Only clicks on this tagged page / URL pattern. */\n page?: { pageId?: string; pattern?: string };\n /** `web`, `ios`, `android` (mobile autocapture sets `properties.platform`). */\n platform?: string;\n exclude?: boolean;\n}\n\nexport const FEATURE_RULE_LIMITS = { rules: 20, value: 1000 } as const;\n\nexport interface ClickFacts {\n selector?: string | null;\n text?: string | null;\n tag?: string | null;\n href?: string | null;\n platform?: string | null;\n}\n\nfunction globMatch(pattern: string, value: string): boolean {\n const re = new RegExp(`^${pattern.split(\"*\").map(escapeRe).join(\".*\")}$`, \"s\");\n return re.test(value);\n}\n\n/** Does a click (facts + a CSS test) satisfy one rule's element conditions? Page scope is checked by the caller. */\nexport function featureRuleMatchesClick(rule: FeatureRule, click: ClickFacts, css: (selector: string) => boolean): boolean {\n if (!rule.selector && !rule.text && !rule.tag && !rule.href) return false;\n if (rule.selector) {\n const sel = click.selector ?? \"\";\n const v = rule.selector.value;\n const ok =\n rule.selector.op === \"css\" ? css(v) : rule.selector.op === \"exact\" ? sel === v : rule.selector.op === \"prefix\" ? sel.startsWith(v) : rule.selector.op === \"contains\" ? sel.includes(v) : globMatch(v, sel);\n if (!ok) return false;\n }\n if (rule.text) {\n const t = (click.text ?? \"\").toLowerCase();\n const v = rule.text.value.toLowerCase();\n if (rule.text.op === \"contains\" ? !t.includes(v) : t !== v) return false;\n }\n if (rule.tag && (click.tag ?? \"\").toLowerCase() !== rule.tag.toLowerCase()) return false;\n if (rule.href) {\n const h = click.href ?? \"\";\n const v = rule.href.value;\n if (rule.href.op === \"equals\" ? h !== v : rule.href.op === \"prefix\" ? !h.startsWith(v) : !h.includes(v)) return false;\n }\n if (rule.platform && (click.platform ?? \"web\") !== rule.platform) return false;\n return true;\n}\n\n/** Validation message for a feature rule, or null. */\nexport function featureRuleError(rule: FeatureRule): string | null {\n if (!rule.selector && !rule.text && !rule.tag && !rule.href) return \"A feature rule needs a selector, text, tag or link condition\";\n if (rule.selector) {\n const v = rule.selector.value?.trim();\n if (!v) return \"The selector is empty\";\n if (v.length > FEATURE_RULE_LIMITS.value) return \"The selector is too long\";\n if (rule.selector.op === \"css\") {\n const err = cssSelectorError(v);\n if (err) return `Unsupported CSS selector: ${err}`;\n }\n }\n if (rule.text && !rule.text.value.trim()) return \"The text condition is empty\";\n if (rule.href && !rule.href.value.trim()) return \"The link condition is empty\";\n if (rule.tag && !/^[a-z][a-z0-9-]{0,40}$/i.test(rule.tag)) return \"The tag is not an element name\";\n if (rule.page?.pattern) return pageRuleError({ type: \"url\", value: rule.page.pattern });\n return null;\n}\n\n/** Selector to find a feature's elements on a page (dashboard overlays, SDK property capture), when the rules give one. */\nexport function featureCssSelectors(rules: FeatureRule[]): string[] {\n const out: string[] = [];\n for (const r of rules) {\n if (r.exclude || !r.selector) continue;\n if ((r.selector.op === \"css\" || r.selector.op === \"exact\") && !cssSelectorError(r.selector.value)) out.push(r.selector.value);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Event properties captured from the DOM (configured per page / feature, sent in the SDK config)\n// ---------------------------------------------------------------------------\n\nexport interface TagPropertyDefinition {\n id: string;\n name: string;\n /** Element to read: CSS selector (may use `>>>`); empty = the clicked element itself (features only). */\n selector?: string;\n source: \"text\" | \"attribute\";\n /** Attribute name for `source: \"attribute\"`; `value` is never read. */\n attribute?: string;\n}\n\n/** One tag's capture config in the SDK payload (`SdkConfigResponse.tagging.properties`). */\nexport interface TagPropertyConfig {\n kind: \"page\" | \"feature\";\n tagId: string;\n /** Page rules (pages) or feature rules (features), evaluated in the browser. */\n pageRules?: PageRule[];\n featureRules?: FeatureRule[];\n properties: TagPropertyDefinition[];\n}\n\nexport interface TaggingSdkConfig {\n /** Attribute that names features automatically (null = off). */\n featureAttribute: string | null;\n properties: TagPropertyConfig[];\n}\n\nexport const TAG_PROPERTY_LIMITS = { perTag: 10, total: 50, value: 100 } as const;\n\n/** Attribute names an event property may read. */\nexport function propertyAttributeAllowed(name: string): boolean {\n const n = name.toLowerCase();\n if (n === \"value\" || n.startsWith(\"on\") || n === \"style\" || n === \"srcdoc\") return false;\n return /^[a-z][a-z0-9_:.-]{0,60}$/.test(n);\n}\n","/**\n * Guide and resource-center localization (zod-free, so the browser SDK can import it).\n *\n * Every translatable text field has a stable key derived from ids, never from positions, so\n * reordering steps keeps translations attached: `steps.<stepId>.title`,\n * `steps.<stepId>.buttons.<buttonId>.label`, `checklist.tasks.<taskId>.title`,\n * `survey.questions.<questionId>.options.<optionId>.label`, …\n *\n * A visitor's language comes from (in order) an explicit SDK locale, the `language` / `locale`\n * trait, then the browser / device language. `resolveLocale` matches it against the languages a\n * guide is translated into (exact tag first, then the base language) and falls back to the\n * project's default language, in which the guide is written.\n */\nimport type { GuideConfig } from \"./guide\";\nimport type { PublishedGuide, ResourceCenterAnnouncement, ResourceCenterArticle, ResourceCenterConfig } from \"./sdk-api\";\n\nexport type TextKind = \"text\" | \"html\";\n\nexport interface TextEntry {\n key: string;\n /** Default-language text. */\n source: string;\n kind: TextKind;\n /** Human-readable location for translators (\"Step 2 · Title\"). */\n label: string;\n}\n\n/** Project-level language settings (Project.settings.localization). */\nexport interface LocalizationSettings {\n /** Language the content is written in. */\n defaultLocale: string;\n /** Additional languages offered for translation. */\n locales: string[];\n /** Machine-translate new and changed text into every language automatically. */\n autoTranslate?: boolean;\n /** Machine translations need a teammate's approval before visitors see them. */\n requireReview?: boolean;\n}\n\n/**\n * Review state of one translated text. `machine` texts were written by AI translation; `human`\n * ones were typed or imported by a teammate (approved by doing so). `outdated` means the source\n * text changed after the translation was written or approved.\n */\nexport interface TranslationReviewState {\n origin: \"machine\" | \"human\";\n approved: boolean;\n outdated: boolean;\n reviewedBy?: string | null;\n reviewedAt?: string | null;\n}\n\n/** locale → key → review state. Texts without a state are human translations from before review existed. */\nexport type TranslationReviewMap = Record<string, Record<string, TranslationReviewState>>;\n\n/** Does this translation still need a teammate to look at it? */\nexport function needsReview(state: TranslationReviewState | undefined): boolean {\n return !!state && ((state.origin === \"machine\" && !state.approved) || state.outdated);\n}\n\nexport const DEFAULT_LOCALE = \"en\";\n\n/** Common languages offered in the dashboard's language picker (any BCP 47 tag is accepted). */\nexport const COMMON_LOCALES: Array<{ code: string; name: string }> = [\n { code: \"en\", name: \"English\" },\n { code: \"en-GB\", name: \"English (UK)\" },\n { code: \"fr\", name: \"French\" },\n { code: \"fr-CA\", name: \"French (Canada)\" },\n { code: \"de\", name: \"German\" },\n { code: \"es\", name: \"Spanish\" },\n { code: \"es-MX\", name: \"Spanish (Mexico)\" },\n { code: \"it\", name: \"Italian\" },\n { code: \"pt\", name: \"Portuguese\" },\n { code: \"pt-BR\", name: \"Portuguese (Brazil)\" },\n { code: \"nl\", name: \"Dutch\" },\n { code: \"sv\", name: \"Swedish\" },\n { code: \"da\", name: \"Danish\" },\n { code: \"nb\", name: \"Norwegian\" },\n { code: \"fi\", name: \"Finnish\" },\n { code: \"pl\", name: \"Polish\" },\n { code: \"cs\", name: \"Czech\" },\n { code: \"tr\", name: \"Turkish\" },\n { code: \"ru\", name: \"Russian\" },\n { code: \"uk\", name: \"Ukrainian\" },\n { code: \"ar\", name: \"Arabic\" },\n { code: \"he\", name: \"Hebrew\" },\n { code: \"hi\", name: \"Hindi\" },\n { code: \"ja\", name: \"Japanese\" },\n { code: \"ko\", name: \"Korean\" },\n { code: \"zh-Hans\", name: \"Chinese (Simplified)\" },\n { code: \"zh-Hant\", name: \"Chinese (Traditional)\" },\n { code: \"id\", name: \"Indonesian\" },\n { code: \"th\", name: \"Thai\" },\n { code: \"vi\", name: \"Vietnamese\" },\n];\n\nexport function localeName(code: string): string {\n const exact = COMMON_LOCALES.find((l) => l.code.toLowerCase() === code.toLowerCase());\n if (exact) return exact.name;\n const base = COMMON_LOCALES.find((l) => l.code.toLowerCase() === baseLanguage(code));\n return base ? `${base.name} (${code})` : code;\n}\n\n/** `fr_FR` / `FR-fr` → `fr-FR`; script subtags keep title case (`zh-hans` → `zh-Hans`). Invalid input → \"\". */\nexport function normalizeLocale(input: unknown): string {\n if (typeof input !== \"string\") return \"\";\n const parts = input.trim().replace(/_/g, \"-\").split(\"-\").filter(Boolean);\n if (!parts.length || !/^[a-zA-Z]{2,3}$/.test(parts[0]!)) return \"\";\n return parts\n .slice(0, 3)\n .map((p, i) => (i === 0 ? p.toLowerCase() : p.length === 4 ? p[0]!.toUpperCase() + p.slice(1).toLowerCase() : p.length === 2 ? p.toUpperCase() : p))\n .join(\"-\");\n}\n\nexport function baseLanguage(locale: string): string {\n return normalizeLocale(locale).split(\"-\")[0] ?? \"\";\n}\n\n/**\n * Picks the language to show: for each requested locale in order, an exact match among\n * `available`, else one sharing its base language (`fr-CA` → `fr`, `fr` → `fr-FR`). Falls back to\n * `defaultLocale`. Matching ignores case.\n */\nexport function resolveLocale(requested: ReadonlyArray<string | null | undefined>, available: readonly string[], defaultLocale: string = DEFAULT_LOCALE): string {\n const def = normalizeLocale(defaultLocale) || DEFAULT_LOCALE;\n const avail = available.map(normalizeLocale).filter(Boolean);\n const all = [def, ...avail.filter((a) => a.toLowerCase() !== def.toLowerCase())];\n for (const raw of requested) {\n const want = normalizeLocale(raw);\n if (!want) continue;\n const exact = all.find((a) => a.toLowerCase() === want.toLowerCase());\n if (exact) return exact;\n const base = baseLanguage(want);\n const sameBase = all.find((a) => a.toLowerCase() === base) ?? all.find((a) => baseLanguage(a) === base);\n if (sameBase) return sameBase;\n }\n return def;\n}\n\n/** Locale candidates for a visitor: explicit option, traits (`language`, `locale`), then the platform's languages. */\nexport function visitorLocales(explicit: string | null | undefined, traits: Record<string, unknown> | null | undefined, platform: ReadonlyArray<string | null | undefined> = []): string[] {\n const out: string[] = [];\n const push = (v: unknown) => {\n const n = normalizeLocale(v);\n if (n && !out.includes(n)) out.push(n);\n };\n push(explicit);\n push(traits?.language);\n push(traits?.locale);\n for (const p of platform) push(p);\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Guides\n// ---------------------------------------------------------------------------\n\n/** Every translatable text in a guide config, in display order. Empty texts are skipped. */\nexport function guideTextEntries(config: Pick<GuideConfig, \"steps\" | \"checklist\" | \"survey\">): TextEntry[] {\n const out: TextEntry[] = [];\n const add = (key: string, source: string | undefined | null, kind: TextKind, label: string) => {\n if (source && source.trim()) out.push({ key, source, kind, label });\n };\n config.steps.forEach((s, i) => {\n const at = `Step ${i + 1}`;\n add(`steps.${s.id}.title`, s.title, \"text\", `${at} · Title`);\n add(`steps.${s.id}.body`, s.body, \"html\", `${at} · Body`);\n add(`steps.${s.id}.customHtml`, s.customHtml, \"html\", `${at} · Custom HTML`);\n add(`steps.${s.id}.imageAlt`, s.imageAlt, \"text\", `${at} · Image description`);\n s.buttons.forEach((b) => add(`steps.${s.id}.buttons.${b.id}.label`, b.label, \"text\", `${at} · Button “${b.label}”`));\n });\n const c = config.checklist;\n if (c) {\n add(\"checklist.launcherLabel\", c.launcherLabel, \"text\", \"Checklist · Launcher label\");\n add(\"checklist.completionTitle\", c.completionTitle, \"text\", \"Checklist · Completion title\");\n add(\"checklist.completionBody\", c.completionBody, \"html\", \"Checklist · Completion message\");\n c.tasks.forEach((t, i) => {\n add(`checklist.tasks.${t.id}.title`, t.title, \"text\", `Task ${i + 1} · Title`);\n add(`checklist.tasks.${t.id}.description`, t.description, \"html\", `Task ${i + 1} · Description`);\n });\n }\n const sv = config.survey;\n if (sv) {\n sv.questions.forEach((q, i) => {\n const at = `Question ${i + 1}`;\n add(`survey.questions.${q.id}.title`, q.title, \"text\", `${at} · Question`);\n add(`survey.questions.${q.id}.description`, q.description, \"text\", `${at} · Description`);\n add(`survey.questions.${q.id}.placeholder`, q.placeholder, \"text\", `${at} · Placeholder`);\n add(`survey.questions.${q.id}.lowLabel`, q.lowLabel, \"text\", `${at} · Low label`);\n add(`survey.questions.${q.id}.highLabel`, q.highLabel, \"text\", `${at} · High label`);\n q.options.forEach((o) => add(`survey.questions.${q.id}.options.${o.id}.label`, o.label, \"text\", `${at} · Option “${o.label}”`));\n });\n add(\"survey.thankYouTitle\", sv.thankYouTitle, \"text\", \"Survey · Thank-you title\");\n add(\"survey.thankYouBody\", sv.thankYouBody, \"html\", \"Survey · Thank-you message\");\n }\n return out;\n}\n\n/** Locales a guide has any translation for. */\nexport function guideLocales(config: Pick<GuideConfig, \"localization\">): string[] {\n const t = config.localization?.translations ?? {};\n return Object.keys(t).filter((l) => Object.values(t[l] ?? {}).some((v) => typeof v === \"string\" && v.trim() !== \"\"));\n}\n\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string): string;\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string | undefined): string | undefined;\nfunction pick(map: Record<string, string> | undefined, key: string, fallback: string | undefined): string | undefined {\n const v = map?.[key];\n return typeof v === \"string\" && v.trim() !== \"\" ? v : fallback;\n}\n\n/** The config with one language's translations applied (untranslated texts keep the default language). */\nexport function applyGuideTranslations<C extends Pick<GuideConfig, \"steps\" | \"checklist\" | \"survey\">>(config: C, map: Record<string, string> | undefined): C {\n if (!map || !Object.keys(map).length) return config;\n return {\n ...config,\n steps: config.steps.map((s) => ({\n ...s,\n title: pick(map, `steps.${s.id}.title`, s.title),\n body: pick(map, `steps.${s.id}.body`, s.body),\n customHtml: pick(map, `steps.${s.id}.customHtml`, s.customHtml),\n imageAlt: pick(map, `steps.${s.id}.imageAlt`, s.imageAlt),\n buttons: s.buttons.map((b) => ({ ...b, label: pick(map, `steps.${s.id}.buttons.${b.id}.label`, b.label) })),\n })),\n checklist: config.checklist\n ? {\n ...config.checklist,\n launcherLabel: pick(map, \"checklist.launcherLabel\", config.checklist.launcherLabel),\n completionTitle: pick(map, \"checklist.completionTitle\", config.checklist.completionTitle),\n completionBody: pick(map, \"checklist.completionBody\", config.checklist.completionBody),\n tasks: config.checklist.tasks.map((t) => ({ ...t, title: pick(map, `checklist.tasks.${t.id}.title`, t.title), description: pick(map, `checklist.tasks.${t.id}.description`, t.description) })),\n }\n : config.checklist,\n survey: config.survey\n ? {\n ...config.survey,\n thankYouTitle: pick(map, \"survey.thankYouTitle\", config.survey.thankYouTitle),\n thankYouBody: pick(map, \"survey.thankYouBody\", config.survey.thankYouBody),\n questions: config.survey.questions.map((q) => ({\n ...q,\n title: pick(map, `survey.questions.${q.id}.title`, q.title),\n description: pick(map, `survey.questions.${q.id}.description`, q.description),\n placeholder: pick(map, `survey.questions.${q.id}.placeholder`, q.placeholder),\n lowLabel: pick(map, `survey.questions.${q.id}.lowLabel`, q.lowLabel),\n highLabel: pick(map, `survey.questions.${q.id}.highLabel`, q.highLabel),\n options: q.options.map((o) => ({ ...o, label: pick(map, `survey.questions.${q.id}.options.${o.id}.label`, o.label) })),\n })),\n }\n : config.survey,\n };\n}\n\n/**\n * The guide as a visitor speaking `requested` should see it, with `locale` set to the language\n * chosen (the default language when none of the guide's translations match).\n */\nexport function localizeGuide(guide: PublishedGuide, requested: readonly string[], defaultLocale: string = DEFAULT_LOCALE): PublishedGuide & { locale: string } {\n const translations = guide.config.localization?.translations ?? {};\n const locale = resolveLocale(requested, guideLocales(guide.config), defaultLocale);\n const key = Object.keys(translations).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());\n if (!key) return { ...guide, locale };\n return { ...guide, locale, config: applyGuideTranslations(guide.config, translations[key]) };\n}\n\nexport interface TranslationCoverage {\n locale: string;\n total: number;\n translated: number;\n /** Keys with no translation. */\n missing: string[];\n /** Keys whose translation exists but whose key no longer matches any text (stale). */\n stale: string[];\n}\n\nexport function translationCoverage(entries: readonly TextEntry[], map: Record<string, string> | undefined, locale: string): TranslationCoverage {\n const keys = new Set(entries.map((e) => e.key));\n const missing = entries.filter((e) => !pick(map, e.key, undefined)).map((e) => e.key);\n const stale = Object.keys(map ?? {}).filter((k) => !keys.has(k) && (map?.[k] ?? \"\").trim() !== \"\");\n return { locale, total: entries.length, translated: entries.length - missing.length, missing, stale };\n}\n\n// ---------------------------------------------------------------------------\n// Resource center\n// ---------------------------------------------------------------------------\n\n/** Translations carried by the published resource center (texts other than articles and announcements). */\nexport type ResourceCenterTranslations = Record<string, Record<string, string>>;\n\n/** Translatable resource-center texts (title, launcher label, links, FAQs, collections). */\nexport function resourceCenterTextEntries(rc: Pick<ResourceCenterConfig, \"title\" | \"launcher\" | \"links\" | \"faqs\" | \"collections\">): TextEntry[] {\n const out: TextEntry[] = [];\n const add = (key: string, source: string | undefined | null, kind: TextKind, label: string) => {\n if (source && source.trim()) out.push({ key, source, kind, label });\n };\n add(\"title\", rc.title, \"text\", \"Title\");\n add(\"launcher.label\", rc.launcher?.label, \"text\", \"Launcher label\");\n rc.collections.forEach((c) => {\n add(`collections.${c.id}.name`, c.name, \"text\", `Collection “${c.name}”`);\n add(`collections.${c.id}.description`, c.description, \"text\", `Collection “${c.name}” · Description`);\n });\n rc.links.forEach((l) => add(`links.${l.id}.label`, l.label, \"text\", `Link “${l.label}”`));\n rc.faqs.forEach((f, i) => {\n add(`faqs.${f.id}.question`, f.question, \"text\", `FAQ ${i + 1} · Question`);\n add(`faqs.${f.id}.answer`, f.answer, \"html\", `FAQ ${i + 1} · Answer`);\n });\n return out;\n}\n\n/** Article texts, keyed `title` / `summary` / `body`. */\nexport function articleTextEntries(a: { title: string; summary?: string | null; body?: string | null }): TextEntry[] {\n const out: TextEntry[] = [];\n if (a.title.trim()) out.push({ key: \"title\", source: a.title, kind: \"text\", label: \"Title\" });\n if (a.summary?.trim()) out.push({ key: \"summary\", source: a.summary, kind: \"text\", label: \"Summary\" });\n if (a.body?.trim()) out.push({ key: \"body\", source: a.body, kind: \"html\", label: \"Body\" });\n return out;\n}\n\n/** Locales the resource center offers (its own strings, articles or announcements). */\nexport function resourceCenterLocales(rc: ResourceCenterConfig): string[] {\n const set = new Set<string>(Object.keys(rc.translations ?? {}));\n for (const a of rc.articles) for (const l of Object.keys(a.translations ?? {})) set.add(l);\n for (const a of rc.announcements ?? []) for (const l of Object.keys(a.translations ?? {})) set.add(l);\n return [...set];\n}\n\nfunction translationFor<T>(map: Record<string, T> | undefined, locale: string): T | undefined {\n if (!map) return undefined;\n const key = Object.keys(map).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());\n return key ? map[key] : undefined;\n}\n\nexport function localizeArticle(a: ResourceCenterArticle, locale: string): ResourceCenterArticle {\n const t = translationFor(a.translations, locale);\n if (!t) return a;\n const body = t.body?.trim() ? t.body : a.body;\n // A translated body that was left out of the snapshot is fetched with `?locale=`.\n return { ...a, title: t.title?.trim() ? t.title : a.title, summary: t.summary?.trim() ? t.summary : a.summary, body, ...(t.bodyOmitted ? { bodyOmitted: true } : {}) };\n}\n\nexport function localizeAnnouncement(a: ResourceCenterAnnouncement, locale: string): ResourceCenterAnnouncement {\n const t = translationFor(a.translations, locale);\n if (!t) return a;\n return { ...a, title: t.title?.trim() ? t.title : a.title, body: t.body?.trim() ? t.body : a.body };\n}\n\n/** The resource center in the visitor's language (with `locale` = the language chosen). */\nexport function localizeResourceCenter(rc: ResourceCenterConfig, requested: readonly string[], defaultLocale: string = DEFAULT_LOCALE): ResourceCenterConfig & { locale: string } {\n const locale = resolveLocale(requested, resourceCenterLocales(rc), defaultLocale);\n if (locale.toLowerCase() === normalizeLocale(defaultLocale).toLowerCase()) return { ...rc, locale };\n const map = translationFor(rc.translations, locale);\n return {\n ...rc,\n locale,\n title: pick(map, \"title\", rc.title),\n launcher: { ...rc.launcher, label: pick(map, \"launcher.label\", rc.launcher.label) },\n collections: rc.collections.map((c) => ({ ...c, name: pick(map, `collections.${c.id}.name`, c.name), description: pick(map, `collections.${c.id}.description`, c.description) })),\n links: rc.links.map((l) => ({ ...l, label: pick(map, `links.${l.id}.label`, l.label) })),\n faqs: rc.faqs.map((f) => ({ ...f, question: pick(map, `faqs.${f.id}.question`, f.question), answer: pick(map, `faqs.${f.id}.answer`, f.answer) })),\n articles: rc.articles.map((a) => localizeArticle(a, locale)),\n announcements: rc.announcements?.map((a) => localizeAnnouncement(a, locale)),\n };\n}\n","/**\n * Guide A/B tests (zod-free; shared by the server, the web SDK and the mobile SDK ports).\n *\n * Each visitor falls into a bucket 0–99: `rolloutBucket(userId || anonymousId, salt)` (FNV-1a,\n * see utils.ts), with `salt = experimentSalt(experimentId)`. Variants own consecutive bucket ranges\n * in their listed order, sized by their integer weights (which sum to 100). The server folds each\n * variant's range into the targeting it serves as two `experiment.bucket` rules, so every SDK\n * applies the split with the rule engine it already has, and assignment is the same everywhere:\n * the server's `assignGuideVariant` and an SDK evaluating the served rules always agree.\n */\nimport { rolloutBucket } from \"./utils\";\nimport type { Rule, RuleGroup } from \"./targeting-eval\";\n\n/** The \"no guide\" variant: visitors in it see nothing, and are measured against the guide variants. */\nexport const CONTROL_VARIANT_ID = \"control\";\n\nexport const GUIDE_EXPERIMENT_STATUSES = [\"draft\", \"running\", \"completed\"] as const;\nexport type GuideExperimentStatus = (typeof GUIDE_EXPERIMENT_STATUSES)[number];\n\nexport const GUIDE_EXPERIMENT_GOALS = [\"guide_completed\", \"event\", \"page_visit\", \"click_text\"] as const;\nexport type GuideExperimentGoalKind = (typeof GUIDE_EXPERIMENT_GOALS)[number];\n\nexport const GUIDE_EXPERIMENT_GOAL_LABELS: Record<GuideExperimentGoalKind, string> = {\n guide_completed: \"Completes the guide\",\n event: \"Tracks an event\",\n page_visit: \"Visits a page\",\n click_text: \"Clicks an element with text\",\n};\n\nexport interface GuideExperimentGoal {\n kind: GuideExperimentGoalKind;\n /** Event name, page path pattern (`/billing/*`) or click text, depending on `kind`. */\n value?: string;\n}\n\nexport interface GuideExperimentVariant {\n id: string;\n name: string;\n /** The guide shown to this variant; null for the control group (no guide). */\n guideId: string | null;\n /** Share of visitors, a whole percentage; all weights sum to 100. */\n weight: number;\n}\n\nexport function experimentSalt(experimentId: string): string {\n return `gx:${experimentId}`;\n}\n\n/** Bucket ranges `[from, to)` per variant, in order. */\nexport function variantRanges(variants: ReadonlyArray<Pick<GuideExperimentVariant, \"id\" | \"weight\">>): Array<{ id: string; from: number; to: number }> {\n let at = 0;\n return variants.map((v) => {\n const from = at;\n at = Math.min(100, at + Math.max(0, Math.round(v.weight)));\n return { id: v.id, from, to: at };\n });\n}\n\n/** The variant a visitor is in, or null when weights leave their bucket unassigned. */\nexport function assignGuideVariant(variants: ReadonlyArray<Pick<GuideExperimentVariant, \"id\" | \"weight\">>, experimentId: string, subject: string): string | null {\n const bucket = rolloutBucket(subject, experimentSalt(experimentId));\n return variantRanges(variants).find((r) => bucket >= r.from && bucket < r.to)?.id ?? null;\n}\n\n/** Rules restricting targeting to bucket range `[from, to)` of `salt`. */\nexport function experimentBucketRules(salt: string, from: number, to: number): Rule[] {\n return [\n { id: \"experiment-from\", field: \"experiment.bucket\", key: salt, op: \"gte\", value: from },\n { id: \"experiment-to\", field: \"experiment.bucket\", key: salt, op: \"lt\", value: to },\n ];\n}\n\n/** Targeting with a variant's bucket range folded in (an SDK without `experiment.bucket` shows the guide to nobody). */\nexport function withExperimentBucket(targeting: RuleGroup, salt: string, from: number, to: number): RuleGroup {\n return { id: \"experiment\", op: \"and\", rules: [...experimentBucketRules(salt, from, to), targeting] };\n}\n\n/** Problems with a variant list; empty when it can run. */\nexport function variantProblems(variants: ReadonlyArray<GuideExperimentVariant>): string[] {\n const problems: string[] = [];\n if (variants.length < 2) problems.push(\"An A/B test needs at least two variants.\");\n if (variants.length > 5) problems.push(\"An A/B test can have at most five variants.\");\n const guides = variants.filter((v) => v.guideId);\n if (guides.length === 0) problems.push(\"At least one variant must show a guide.\");\n if (variants.filter((v) => !v.guideId).length > 1) problems.push(\"Only one variant can be the control group (no guide).\");\n if (new Set(guides.map((v) => v.guideId)).size !== guides.length) problems.push(\"Each variant needs its own guide.\");\n if (new Set(variants.map((v) => v.id)).size !== variants.length) problems.push(\"Variant ids must be unique.\");\n if (variants.some((v) => !Number.isInteger(v.weight) || v.weight < 1)) problems.push(\"Every variant needs a whole-number share of at least 1%.\");\n const total = variants.reduce((s, v) => s + v.weight, 0);\n if (total !== 100) problems.push(`Traffic shares must add up to 100% (now ${total}%).`);\n return problems;\n}\n\n/** Splits 100% as evenly as possible across `n` variants (first ones get the remainder). */\nexport function evenWeights(n: number): number[] {\n if (n <= 0) return [];\n const base = Math.floor(100 / n);\n return Array.from({ length: n }, (_, i) => base + (i < 100 - base * n ? 1 : 0));\n}\n","/**\n * Custom CSS for guides and themes (zod-free; the server sanitizes on save, the web runtime\n * sanitizes again and scopes before injecting).\n *\n * Guides render inside the SDK's Shadow DOM, so page styles and guide styles never mix. Within the\n * shadow root, every rule is additionally prefixed with the guide's own container selector, so one\n * guide's CSS can't restyle another guide, the resource center or the messenger. Sanitizing removes\n * what could reach outside the container or load anything: `@import`, `:host` / `::slotted` rules,\n * `url()`s other than https images and `data:image/…`, legacy script hooks (`expression()`,\n * `behavior`, `-moz-binding`, `javascript:`) and any markup.\n */\n\nexport const MAX_CUSTOM_CSS = 20000;\n\nconst BLOCKED_AT_RULES = /^@(import|charset|namespace|document|-moz-document)\\b/i;\nconst ALLOWED_AT_RULES = /^@(media|supports|container|layer|keyframes|-webkit-keyframes|font-face)\\b/i;\n\ninterface Block {\n /** Selector or at-rule prelude; \"\" for a bare declaration list. */\n prelude: string;\n /** Declarations (for rules) or nested CSS (for grouping at-rules). */\n body: string;\n}\n\n/** Splits CSS into top-level `prelude { body }` blocks, respecting strings and nesting. Statements without a block are dropped. */\nfunction splitBlocks(css: string): Block[] {\n const out: Block[] = [];\n let i = 0;\n const n = css.length;\n while (i < n) {\n let prelude = \"\";\n let quote: string | null = null;\n while (i < n) {\n const ch = css[i]!;\n if (quote) {\n prelude += ch;\n if (ch === \"\\\\\") prelude += css[++i] ?? \"\";\n else if (ch === quote) quote = null;\n } else if (ch === '\"' || ch === \"'\") {\n quote = ch;\n prelude += ch;\n } else if (ch === \"{\") break;\n else if (ch === \";\") {\n prelude = \"\"; // a statement (e.g. @import) – dropped\n } else if (ch === \"}\") {\n prelude = \"\"; // stray brace\n } else prelude += ch;\n i++;\n }\n if (i >= n) break;\n // css[i] === \"{\"\n i++;\n let depth = 1;\n let body = \"\";\n quote = null;\n while (i < n && depth > 0) {\n const ch = css[i]!;\n if (quote) {\n body += ch;\n if (ch === \"\\\\\") body += css[++i] ?? \"\";\n else if (ch === quote) quote = null;\n } else if (ch === '\"' || ch === \"'\") {\n quote = ch;\n body += ch;\n } else if (ch === \"{\") {\n depth++;\n body += ch;\n } else if (ch === \"}\") {\n depth--;\n if (depth > 0) body += ch;\n } else body += ch;\n i++;\n }\n out.push({ prelude: prelude.trim(), body });\n }\n return out;\n}\n\n/** Splits a selector list on top-level commas. */\nfunction splitSelectors(list: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let cur = \"\";\n for (const ch of list) {\n if (ch === \"(\" || ch === \"[\") depth++;\n else if (ch === \")\" || ch === \"]\") depth = Math.max(0, depth - 1);\n if (ch === \",\" && depth === 0) {\n out.push(cur.trim());\n cur = \"\";\n } else cur += ch;\n }\n if (cur.trim()) out.push(cur.trim());\n return out;\n}\n\nfunction safeUrl(raw: string): boolean {\n const u = raw.trim().replace(/^['\"]|['\"]$/g, \"\").trim();\n return /^https:\\/\\//i.test(u) || /^data:image\\/(png|jpe?g|gif|webp|svg\\+xml)[;,]/i.test(u);\n}\n\n/** Cleans one declaration list. */\nfunction cleanDeclarations(body: string): string {\n return body\n .replace(/url\\(([^)]*)\\)/gi, (m, inner: string) => (safeUrl(inner) ? m : \"none\"))\n .replace(/expression\\s*\\(/gi, \"(\")\n .replace(/javascript\\s*:/gi, \"\")\n .replace(/(^|[;{\\s])(-moz-binding|behavior)\\s*:[^;]*;?/gi, \"$1\")\n .replace(/[{}]/g, \"\")\n .trim();\n}\n\n/** Removes everything unsafe; keeps the rule structure. */\nexport function sanitizeCustomCss(input: string | null | undefined): string {\n if (!input) return \"\";\n let css = String(input).slice(0, MAX_CUSTOM_CSS);\n css = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/<(script|style)\\b[^>]*>[\\s\\S]*?<\\/\\1\\s*>/gi, \"\").replace(/<\\/?[a-z!][^>]*>/gi, \"\").replace(/</g, \"\");\n return render(splitBlocks(css), 0);\n}\n\nfunction render(blocks: Block[], depth: number): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (!b.prelude) continue;\n if (b.prelude.startsWith(\"@\")) {\n if (BLOCKED_AT_RULES.test(b.prelude) || !ALLOWED_AT_RULES.test(b.prelude)) continue;\n if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) {\n // Keyframe selectors (from/to/50%) and font-face descriptors are declarations-like.\n const inner = /^@font-face/i.test(b.prelude) ? cleanDeclarations(b.body) : splitBlocks(b.body).map((k) => `${k.prelude}{${cleanDeclarations(k.body)}}`).join(\"\");\n parts.push(`${b.prelude}{${inner}}`);\n } else if (depth < 3) parts.push(`${b.prelude}{${render(splitBlocks(b.body), depth + 1)}}`);\n continue;\n }\n const selectors = splitSelectors(b.prelude).filter((s) => !/:host|::slotted|::part/i.test(s));\n if (!selectors.length) continue;\n parts.push(`${selectors.join(\",\")}{${cleanDeclarations(b.body)}}`);\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * Prefixes every selector with `scope` (e.g. `.g-scope[data-guide=\"abc\"]`). `:root`, `html`,\n * `body`, `:scope` and `&` at the start of a selector refer to the container itself.\n */\nexport function scopeCustomCss(css: string, scope: string): string {\n return scopeBlocks(splitBlocks(sanitizeCustomCss(css)), scope, 0);\n}\n\nfunction scopeBlocks(blocks: Block[], scope: string, depth: number): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (b.prelude.startsWith(\"@\")) {\n if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) parts.push(`${b.prelude}{${b.body}}`);\n else if (depth < 3) parts.push(`${b.prelude}{${scopeBlocks(splitBlocks(b.body), scope, depth + 1)}}`);\n continue;\n }\n const sels = splitSelectors(b.prelude).map((s) => {\n const self = s.match(/^(:root|html|body|:scope|&)(?![\\w-])(.*)$/i);\n if (self) return `${scope}${self[2] ?? \"\"}`;\n return `${scope} ${s}`;\n });\n parts.push(`${sels.join(\",\")}{${b.body}}`);\n }\n return parts.join(\"\\n\");\n}\n","/**\n * Whether the Guidely API is reachable right now: a circuit breaker shared by everything the SDK\n * sends in the background (event batches, replay uploads, config refreshes, queued survey answers).\n *\n * Every API answer is reported here. After `threshold` failures in a row (network errors, timeouts,\n * 429, 5xx) the circuit opens for a cooldown that doubles with each further failure (5 s up to\n * 5 min, ±20% jitter so tabs don't retry in step); a `Retry-After` answer sets the cooldown\n * directly. While it is open, background senders wait `waitMs()` instead of sending. Requests the\n * person makes (a messenger message) still go out, and any answer closes the circuit again. The\n * browser's `online` event ends the cooldown early.\n */\nexport interface ServerHealthOptions {\n threshold?: number;\n baseMs?: number;\n maxMs?: number;\n now?: () => number;\n random?: () => number;\n}\n\n/** Longest `Retry-After` honoured, so a bad header can't silence the SDK for days. */\nconst MAX_RETRY_AFTER_MS = 60 * 60 * 1000;\n/** How long background senders wait while the browser reports being offline (the `online` event usually comes first). */\nconst OFFLINE_WAIT_MS = 30_000;\n\nexport class ServerHealth {\n private failures = 0;\n private openUntil = 0;\n private lastOkAt = 0;\n private readonly listeners = new Set<() => void>();\n private readonly threshold: number;\n private readonly baseMs: number;\n private readonly maxMs: number;\n private readonly now: () => number;\n private readonly random: () => number;\n\n constructor(opts: ServerHealthOptions = {}) {\n this.threshold = opts.threshold ?? 3;\n this.baseMs = opts.baseMs ?? 5000;\n this.maxMs = opts.maxMs ?? 5 * 60 * 1000;\n this.now = opts.now ?? Date.now;\n this.random = opts.random ?? Math.random;\n }\n\n /** The server answered (2xx, 3xx, or a 4xx other than 429): it is up. */\n success(): void {\n const wasDown = this.failures > 0 || this.openUntil > 0;\n this.failures = 0;\n this.openUntil = 0;\n this.lastOkAt = this.now();\n if (wasDown) this.notify();\n }\n\n /** The request failed or the server is overloaded. `retryAfterMs` comes from a `Retry-After` header. */\n failure(retryAfterMs?: number | null): void {\n this.failures += 1;\n const now = this.now();\n if (retryAfterMs != null && retryAfterMs > 0) {\n this.openUntil = Math.max(this.openUntil, now + Math.min(retryAfterMs, MAX_RETRY_AFTER_MS));\n return;\n }\n if (this.failures < this.threshold) return;\n const cooldown = Math.min(this.maxMs, this.baseMs * 2 ** (this.failures - this.threshold));\n this.openUntil = Math.max(this.openUntil, now + cooldown * (0.8 + this.random() * 0.4));\n }\n\n /** Milliseconds background traffic should wait before trying again (0: send now). */\n waitMs(): number {\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) return OFFLINE_WAIT_MS;\n return Math.max(0, this.openUntil - this.now());\n }\n\n canSend(): boolean {\n return this.waitMs() === 0;\n }\n\n /**\n * The last request got an answer. Unload beacons can't report back, so what they carry is only\n * forgotten while this holds; otherwise it stays queued and is sent again (the server drops duplicates).\n */\n get reachable(): boolean {\n return this.failures === 0 && this.lastOkAt > 0;\n }\n\n /** The browser came back online: end the cooldown and let queued traffic try straight away. */\n online(): void {\n this.openUntil = 0;\n this.notify();\n }\n\n /** Called when the server answers again after failures, or the browser comes back online. */\n onRecover(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n private notify(): void {\n for (const cb of Array.from(this.listeners)) {\n try {\n cb();\n } catch {\n /* a listener must not break the others */\n }\n }\n }\n}\n\n/** `Retry-After` as milliseconds: delta-seconds or an HTTP date. Null when absent or unparseable. */\nexport function parseRetryAfter(value: string | null | undefined, now = Date.now()): number | null {\n if (!value) return null;\n const trimmed = value.trim();\n if (/^\\d+$/.test(trimmed)) return Number(trimmed) * 1000;\n const at = Date.parse(trimmed);\n return Number.isNaN(at) ? null : Math.max(0, at - now);\n}\n\n/** Answers that mean the server is down or shedding load (retry later) rather than refusing the request. */\nexport function isServerFailure(status: number): boolean {\n return status === 429 || status >= 500;\n}\n","import { isServerFailure, parseRetryAfter, ServerHealth } from \"./health\";\n\nexport interface ApiResponse<T> {\n status: number;\n ok: boolean;\n data: T | null;\n etag: string | null;\n}\n\nexport type FetchLike = typeof fetch;\n\n/** Reply streams: the response must start within this long, and then never go quiet longer than the idle limit (the server sends a keepalive every 15 s). */\nexport const STREAM_RESPONSE_TIMEOUT_MS = 30_000;\nexport const STREAM_IDLE_TIMEOUT_MS = 60_000;\n\n/** Thin HTTP client for the public SDK API. Adds the public key as query + header. */\nexport class Api {\n /** Reachability of the API, fed by every answer (see {@link ServerHealth}). */\n readonly health: ServerHealth;\n\n constructor(\n private readonly baseUrl: string,\n private readonly key: string,\n private readonly fetchImpl?: FetchLike,\n health?: ServerHealth,\n ) {\n this.health = health ?? new ServerHealth();\n }\n\n /** Feeds an answer (or a failed request, `null`) into {@link health}. */\n private observe(res: Response | null): void {\n if (!res) this.health.failure();\n else if (isServerFailure(res.status)) this.health.failure(parseRetryAfter(res.headers?.get?.(\"retry-after\")));\n else this.health.success();\n }\n\n url(path: string, params: Record<string, string | undefined> = {}): string {\n // Built by hand rather than with URL/searchParams, which React Native does not implement.\n const query = Object.entries({ key: this.key, ...params })\n .filter((e): e is [string, string] => e[1] != null)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n return `${this.baseUrl.replace(/\\/$/, \"\")}/api/v1/sdk${path}?${query}`;\n }\n\n private get fetcher(): FetchLike | null {\n if (this.fetchImpl) return this.fetchImpl;\n return typeof fetch === \"function\" ? fetch.bind(globalThis) : null;\n }\n\n async request<T>(method: \"GET\" | \"POST\", path: string, options: { body?: unknown; etag?: string | null; params?: Record<string, string | undefined>; keepalive?: boolean; timeoutMs?: number; headers?: Record<string, string> } = {}): Promise<ApiResponse<T>> {\n const f = this.fetcher;\n if (!f) throw new Error(\"fetch is not available\");\n const headers: Record<string, string> = { ...options.headers, \"X-Guidely-Key\": this.key, Accept: \"application/json\" };\n // Multipart bodies set their own Content-Type (with the boundary).\n const form = typeof FormData !== \"undefined\" && options.body instanceof FormData;\n if (options.body !== undefined && !form) headers[\"Content-Type\"] = \"application/json\";\n if (options.etag) headers[\"If-None-Match\"] = options.etag;\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ac ? setTimeout(() => ac.abort(), options.timeoutMs ?? 10000) : null;\n try {\n let res: Response;\n try {\n res = await f(this.url(path, options.params), {\n method,\n headers,\n body: options.body === undefined ? undefined : form ? (options.body as FormData) : JSON.stringify(options.body),\n keepalive: options.keepalive,\n signal: ac?.signal,\n credentials: \"omit\",\n mode: \"cors\",\n });\n } catch (err) {\n this.observe(null);\n throw err;\n }\n this.observe(res);\n let data: T | null = null;\n if (res.status !== 304 && res.status !== 204) {\n try {\n data = (await res.json()) as T;\n } catch {\n data = null;\n }\n }\n return { status: res.status, ok: res.ok, data, etag: res.headers?.get?.(\"etag\") ?? null };\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n get<T>(path: string, options?: { etag?: string | null; params?: Record<string, string | undefined>; headers?: Record<string, string> }): Promise<ApiResponse<T>> {\n return this.request<T>(\"GET\", path, options);\n }\n\n post<T>(path: string, body: unknown, options?: { params?: Record<string, string | undefined>; keepalive?: boolean; headers?: Record<string, string> }): Promise<ApiResponse<T>> {\n return this.request<T>(\"POST\", path, { body, ...options });\n }\n\n /** Multipart POST (file uploads). No Content-Type header: the browser adds it with the boundary. */\n postForm<T>(path: string, form: FormData, options?: { params?: Record<string, string | undefined>; timeoutMs?: number }): Promise<ApiResponse<T>> {\n return this.request<T>(\"POST\", path, { body: form, ...options });\n }\n\n /**\n * POST that may answer with server-sent events. Each event is passed to `onEvent`; a JSON answer is\n * returned instead. Scout replies can take a while, so there is no overall timeout: the response\n * must start within 30 s and then never go quiet for more than 60 s (the server sends keepalives),\n * otherwise the request is aborted and rejects.\n */\n async stream<T>(path: string, body: unknown, onEvent: (event: string, data: unknown) => void, headers: Record<string, string> = {}): Promise<ApiResponse<T>> {\n const f = this.fetcher;\n if (!f) throw new Error(\"fetch is not available\");\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const arm = (ms: number) => {\n if (!ac) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => ac.abort(), ms);\n };\n arm(STREAM_RESPONSE_TIMEOUT_MS);\n try {\n let res: Response;\n try {\n res = await f(this.url(path), {\n method: \"POST\",\n headers: { ...headers, \"X-Guidely-Key\": this.key, Accept: \"text/event-stream, application/json\", \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: ac?.signal,\n credentials: \"omit\",\n mode: \"cors\",\n });\n } catch (err) {\n this.observe(null);\n throw err;\n }\n this.observe(res);\n const type = res.headers?.get?.(\"content-type\") ?? \"\";\n if (!type.includes(\"text/event-stream\") || !res.body) {\n let data: T | null = null;\n try {\n data = (await res.json()) as T;\n } catch {\n data = null;\n }\n return { status: res.status, ok: res.ok, data, etag: null };\n }\n arm(STREAM_IDLE_TIMEOUT_MS);\n await readEventStream(res.body, onEvent, () => arm(STREAM_IDLE_TIMEOUT_MS));\n return { status: res.status, ok: res.ok, data: null, etag: null };\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n /** `navigator.sendBeacon` when available (page unload); returns false when it could not be queued. */\n beacon(path: string, body: unknown): boolean {\n try {\n if (typeof navigator === \"undefined\" || typeof navigator.sendBeacon !== \"function\") return false;\n // text/plain is a CORS-safelisted type: cross-origin beacons need no preflight (which\n // browsers drop during unload). The API parses the body regardless of content type.\n const blob = new Blob([JSON.stringify(body)], { type: \"text/plain;charset=UTF-8\" });\n return navigator.sendBeacon(this.url(path), blob);\n } catch {\n return false;\n }\n }\n}\n\nexport const sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n/** Exponential backoff helper: 1s → 2s → 4s … capped. */\nexport function backoffMs(attempt: number, baseMs = 1000, maxMs = 30000): number {\n return Math.min(maxMs, baseMs * 2 ** Math.max(0, attempt));\n}\n\n/**\n * Sends with bounded retries: network errors, 429 and 5xx are retried with backoff; success and\n * other 4xx answers are returned as they are. Null when every attempt failed.\n */\nexport async function withRetry<T>(send: () => Promise<ApiResponse<T>>, attempts = 3, baseMs = 500): Promise<ApiResponse<T> | null> {\n for (let i = 0; i < attempts; i++) {\n try {\n const res = await send();\n if (res.ok || (res.status >= 400 && res.status < 500 && res.status !== 429)) return res;\n } catch {\n /* network error → retry */\n }\n if (i < attempts - 1) await sleep(backoffMs(i, baseMs, 8000));\n }\n return null;\n}\n\n/** Fire-and-forget POST with bounded retries (used for state sync; never blocks UI). */\nexport function postWithRetry<T>(api: Api, path: string, body: unknown, attempts = 3, baseMs = 500): Promise<ApiResponse<T> | null> {\n return withRetry(() => api.post<T>(path, body), attempts, baseMs);\n}\n\n/** Parses a `text/event-stream` body (`event:` + single-line JSON `data:`; comment lines ignored). `onChunk` runs whenever bytes arrive. */\nexport async function readEventStream(body: ReadableStream<Uint8Array>, onEvent: (event: string, data: unknown) => void, onChunk?: () => void): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const dispatch = (raw: string) => {\n let event = \"message\";\n const data: string[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) continue;\n const i = line.indexOf(\":\");\n const field = i < 0 ? line : line.slice(0, i);\n const value = i < 0 ? \"\" : line.slice(i + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n }\n if (!data.length) return;\n try {\n onEvent(event, JSON.parse(data.join(\"\\n\")));\n } catch {\n /* ignore malformed events */\n }\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (value) onChunk?.();\n if (value) buffer += decoder.decode(value, { stream: true }).replace(/\\r\\n?/g, \"\\n\");\n let sep: number;\n while ((sep = buffer.indexOf(\"\\n\\n\")) >= 0) {\n dispatch(buffer.slice(0, sep));\n buffer = buffer.slice(sep + 2);\n }\n if (done) break;\n }\n if (buffer.trim()) dispatch(buffer);\n}\n","export type StorageKind = \"local\" | \"session\" | \"memory\";\n\n/** Minimal synchronous key/value store; never throws (private mode, quota, SSR). */\nexport interface KeyValueStore {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport function memoryStore(): KeyValueStore {\n const map = new Map<string, string>();\n return { get: (k) => map.get(k) ?? null, set: (k, v) => void map.set(k, v), remove: (k) => void map.delete(k) };\n}\n\nfunction webStore(area: \"localStorage\" | \"sessionStorage\"): KeyValueStore | null {\n try {\n if (typeof window === \"undefined\") return null;\n const s = window[area];\n if (!s) return null;\n const probe = \"__guidely_probe__\";\n s.setItem(probe, \"1\");\n s.removeItem(probe);\n return {\n get: (k) => {\n try {\n return s.getItem(k);\n } catch {\n return null;\n }\n },\n set: (k, v) => {\n try {\n s.setItem(k, v);\n } catch {\n /* quota / private mode */\n }\n },\n remove: (k) => {\n try {\n s.removeItem(k);\n } catch {\n /* ignore */\n }\n },\n };\n } catch {\n return null;\n }\n}\n\n/** Creates a store of the requested kind, degrading to memory when unavailable. */\nexport function createStorage(kind: StorageKind = \"local\"): KeyValueStore {\n if (kind === \"memory\") return memoryStore();\n return webStore(kind === \"local\" ? \"localStorage\" : \"sessionStorage\") ?? memoryStore();\n}\n\nexport function readJson<T>(store: KeyValueStore, key: string, fallback: T): T {\n const raw = store.get(key);\n if (raw == null) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n}\n\nexport function writeJson(store: KeyValueStore, key: string, value: unknown): void {\n try {\n store.set(key, JSON.stringify(value));\n } catch {\n /* ignore */\n }\n}\n\n/** Storage keys used by the SDK (documented for integrators). */\nexport const KEYS = {\n anon: \"guidely:anon\",\n seen: \"guidely:seen\",\n config: (key: string) => `guidely:config:${key}`,\n etag: (key: string) => `guidely:etag:${key}`,\n state: (key: string) => `guidely:state:${key}`,\n user: (key: string) => `guidely:user:${key}`,\n queue: (key: string) => `guidely:queue:${key}`,\n /** Survey answers and guide/checklist progress not yet accepted by the server. */\n outbox: (key: string) => `guidely:outbox:${key}`,\n /** Agent Analytics turns not yet accepted by the server. */\n agentOutbox: (key: string) => `guidely:agents:${key}`,\n session: \"guidely:session\",\n active: \"guidely:active\",\n authoring: \"guidely:authoring\",\n /** How-to capture session marker ({ token, … }) and its not-yet-uploaded steps. */\n capture: \"guidely:capture\",\n capturePending: \"guidely:capture:pending\",\n /** Messenger conversations this browser can read: [{ id, token }]. */\n conversations: (key: string) => `guidely:conversations:${key}`,\n /** Announcement ids opened in the messenger's News tab. */\n newsSeen: (key: string) => `guidely:news:${key}`,\n /** Where the visitor dragged the messenger launcher ({ side, y }). */\n launcher: (key: string) => `guidely:launcher:${key}`,\n} as const;\n","import type { SdkEvent } from \"@guidelytech/shared\";\nimport type { ServerHealth } from \"./health\";\nimport { backoffMs } from \"./http\";\nimport { readJson, writeJson, type KeyValueStore } from \"./storage\";\n\nexport interface EventQueueOptions {\n store: KeyValueStore;\n storageKey: string;\n /** Sends one batch. Resolve `{ ok: true }` on success, `{ ok: false, retry }` otherwise. */\n send: (events: SdkEvent[]) => Promise<{ ok: boolean; retry?: boolean }>;\n /** Synchronous best-effort send used on page hide. */\n beacon?: (events: SdkEvent[]) => boolean;\n /** Should events be flushed right now? (analytics enabled + consent granted). */\n enabled: () => boolean;\n /** API reachability: sends wait while its circuit is open, and beaconed events are only forgotten while it is reachable. */\n health?: ServerHealth;\n flushIntervalMs?: number;\n maxQueue?: number;\n batchSize?: number;\n maxAttempts?: number;\n onError?: (err: unknown) => void;\n}\n\n/**\n * Bounded, persisted event queue. Batches ≤50 events every 2s (or on demand), dedupes by\n * `eventId`, and keeps failed events (also across page loads) until the server takes them:\n * retries back off 1s→60s, wait while the API's circuit is open, and start again as soon as it\n * recovers. Drops the oldest events once the queue exceeds 500.\n */\nexport class EventQueue {\n private events: SdkEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private inflight = false;\n private inflightIds = new Set<string>();\n private attempt = 0;\n private destroyed = false;\n private offRecover: (() => void) | null = null;\n private readonly flushIntervalMs: number;\n private readonly maxQueue: number;\n private readonly batchSize: number;\n private readonly maxAttempts: number;\n\n constructor(private readonly opts: EventQueueOptions) {\n this.flushIntervalMs = opts.flushIntervalMs ?? 2000;\n this.maxQueue = opts.maxQueue ?? 500;\n this.batchSize = opts.batchSize ?? 50;\n this.maxAttempts = opts.maxAttempts ?? 5;\n const persisted = readJson<SdkEvent[]>(opts.store, opts.storageKey, []);\n if (Array.isArray(persisted)) this.events = persisted.filter((e) => e && typeof e.eventId === \"string\").slice(-this.maxQueue);\n // Events left over from a previous page load are flushed on the next tick.\n if (this.events.length) this.schedule();\n this.offRecover = opts.health?.onRecover(() => this.retryNow()) ?? null;\n }\n\n /** The API is back: drop any pending backoff and send what is queued. */\n private retryNow(): void {\n if (this.destroyed) return;\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = null;\n this.attempt = 0;\n void this.flush();\n }\n\n private retryIn(ms: number): void {\n if (this.retryTimer || this.destroyed) return;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n void this.flush();\n }, ms);\n }\n\n get size(): number {\n return this.events.length;\n }\n\n /** Pending events (read-only copy, for debugging). */\n peek(): SdkEvent[] {\n return this.events.slice();\n }\n\n enqueue(event: SdkEvent): void {\n if (this.destroyed) return;\n if (this.events.some((e) => e.eventId === event.eventId)) return;\n this.events.push(event);\n if (this.events.length > this.maxQueue) this.events.splice(0, this.events.length - this.maxQueue);\n this.persist();\n this.schedule();\n }\n\n private persist(): void {\n writeJson(this.opts.store, this.opts.storageKey, this.events);\n }\n\n private schedule(): void {\n if (this.timer || this.retryTimer || this.destroyed) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, this.flushIntervalMs);\n }\n\n /** Sends queued events now (one batch at a time). Safe to call at any time. */\n async flush(): Promise<void> {\n if (this.destroyed || this.inflight || !this.events.length || !this.opts.enabled()) return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n const wait = this.opts.health?.waitMs() ?? 0;\n if (wait > 0) return this.retryIn(wait);\n this.inflight = true;\n const batch = this.events.slice(0, this.batchSize);\n this.inflightIds = new Set(batch.map((e) => e.eventId));\n let ok = false;\n let retry = true;\n try {\n const res = await this.opts.send(batch);\n ok = res.ok;\n retry = res.retry ?? !res.ok;\n } catch (err) {\n this.opts.onError?.(err);\n }\n this.inflight = false;\n this.inflightIds.clear();\n if (this.destroyed) return;\n if (ok || !retry) {\n const ids = new Set(batch.map((e) => e.eventId));\n this.events = this.events.filter((e) => !ids.has(e.eventId));\n this.attempt = 0;\n this.persist();\n if (this.events.length) this.schedule();\n return;\n }\n // Fast retries first, then about once a minute until the server takes the events (or the\n // API's circuit says to wait longer); a recovery or the next page load sends them sooner.\n this.attempt = Math.min(this.attempt + 1, this.maxAttempts);\n const delay = this.attempt >= this.maxAttempts ? 60_000 : backoffMs(this.attempt - 1);\n this.retryIn(Math.max(delay, this.opts.health?.waitMs() ?? 0));\n }\n\n /** Best-effort synchronous flush on unload using `sendBeacon`. */\n flushSync(): void {\n if (this.destroyed || !this.opts.enabled() || !this.opts.beacon) return;\n // Events already in flight (fetch with keepalive) survive unload; only beacon the rest to avoid duplicate batches.\n const batch = this.events.filter((e) => !this.inflightIds.has(e.eventId)).slice(0, this.batchSize);\n if (!batch.length) return;\n // A beacon that was queued may still never arrive (the server is down), and nothing reports\n // back. Only forget its events while the API is answering; otherwise they stay persisted and the\n // next page load sends them again (the server drops events it already has, by eventId).\n if (this.opts.beacon(batch) && (this.opts.health?.reachable ?? true)) {\n const ids = new Set(batch.map((e) => e.eventId));\n this.events = this.events.filter((e) => !ids.has(e.eventId));\n }\n this.persist();\n }\n\n clear(): void {\n this.events = [];\n this.persist();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.offRecover?.();\n if (this.timer) clearTimeout(this.timer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.timer = null;\n this.retryTimer = null;\n this.persist();\n }\n}\n","import type { ServerHealth } from \"./health\";\nimport { backoffMs, type Api } from \"./http\";\nimport { readJson, writeJson, type KeyValueStore } from \"./storage\";\n\n/** One request waiting to reach the server. */\ninterface OutboxItem {\n /** Same key → the newer request replaces the older one (e.g. a checklist's latest progress). */\n key: string;\n path: string;\n body: unknown;\n createdAt: number;\n}\n\nexport interface OutboxOptions {\n api: Api;\n store: KeyValueStore;\n storageKey: string;\n health?: ServerHealth;\n maxItems?: number;\n maxAgeMs?: number;\n onError?: (err: unknown) => void;\n}\n\n/**\n * Persisted queue for writes that must not be lost when the API is down: survey answers, guide\n * completions and checklist progress. Each request is kept (also across page loads) until the\n * server answers it; 5xx, 429 and network errors are retried with backoff, waiting while the API's\n * circuit is open. Every request is idempotent on the server (survey answers dedupe by\n * `responseId`, progress merges), so sending one twice is harmless. Bounded to 50 requests and 7 days.\n */\nexport class Outbox {\n private items: OutboxItem[];\n private sending = false;\n private attempt = 0;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n private readonly offRecover: (() => void) | null;\n private readonly maxItems: number;\n private readonly maxAgeMs: number;\n\n constructor(private readonly opts: OutboxOptions) {\n this.maxItems = opts.maxItems ?? 50;\n this.maxAgeMs = opts.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;\n const stored = readJson<OutboxItem[]>(opts.store, opts.storageKey, []);\n const cutoff = Date.now() - this.maxAgeMs;\n this.items = Array.isArray(stored) ? stored.filter((i) => i && typeof i.path === \"string\" && typeof i.key === \"string\" && i.createdAt > cutoff).slice(-this.maxItems) : [];\n this.offRecover = opts.health?.onRecover(() => {\n this.attempt = 0;\n this.retryIn(0);\n }) ?? null;\n if (this.items.length) this.retryIn(0);\n }\n\n get size(): number {\n return this.items.length;\n }\n\n /** Queues `POST path` and sends it now (or as soon as the API is reachable). */\n add(key: string, path: string, body: unknown): void {\n if (this.destroyed) return;\n this.items = this.items.filter((i) => i.key !== key);\n this.items.push({ key, path, body, createdAt: Date.now() });\n if (this.items.length > this.maxItems) this.items.splice(0, this.items.length - this.maxItems);\n this.persist();\n void this.flush();\n }\n\n private persist(): void {\n writeJson(this.opts.store, this.opts.storageKey, this.items);\n }\n\n private retryIn(ms: number): void {\n if (this.destroyed) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, ms);\n }\n\n /** Sends queued requests in order, one at a time. */\n async flush(): Promise<void> {\n if (this.destroyed || this.sending || !this.items.length) return;\n const wait = this.opts.health?.waitMs() ?? 0;\n if (wait > 0) return this.retryIn(wait);\n this.sending = true;\n try {\n while (this.items.length && !this.destroyed) {\n const item = this.items[0] as OutboxItem;\n let retry = false;\n try {\n const res = await this.opts.api.post(item.path, item.body);\n retry = !res.ok && (res.status === 429 || res.status >= 500);\n } catch (err) {\n retry = true;\n this.opts.onError?.(err);\n }\n if (retry) {\n this.attempt += 1;\n this.retryIn(Math.max(backoffMs(this.attempt - 1, 1000, 60_000), this.opts.health?.waitMs() ?? 0));\n return;\n }\n // Answered (or refused for good, e.g. the survey was deleted): done with it. A newer request\n // under the same key may have replaced it while this one was in flight; keep that one.\n this.attempt = 0;\n this.items = this.items.filter((i) => i !== item);\n this.persist();\n }\n } finally {\n this.sending = false;\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n this.offRecover?.();\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n}\n","type AnyFn = (...args: any[]) => void;\n\n/** Tiny typed event emitter. Listener errors are reported, never thrown into the caller. */\nexport class Emitter<Events extends { [K in keyof Events]: AnyFn }> {\n private listeners = new Map<keyof Events, Set<AnyFn>>();\n constructor(private readonly onError?: (err: unknown) => void) {}\n\n on<K extends keyof Events>(event: K, cb: Events[K]): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(cb);\n return () => this.off(event, cb);\n }\n\n off<K extends keyof Events>(event: K, cb: Events[K]): void {\n this.listeners.get(event)?.delete(cb);\n }\n\n emit<K extends keyof Events>(event: K, ...args: Parameters<Events[K]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const cb of Array.from(set)) {\n try {\n cb(...args);\n } catch (err) {\n this.onError?.(err);\n }\n }\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","import type { FrequencyConfig, GuideThrottlingSettings, PublishedGuide } from \"@guidelytech/shared\";\n\n/** Per-guide state kept locally and merged with the server's `IdentifyResponse.guideState`. */\nexport interface GuideLocalState {\n impressions: number;\n completedAt?: string | null;\n dismissedAt?: string | null;\n lastShownAt?: string | null;\n /** Last step reached in a multi-step flow (local only), so the messenger can offer to resume it. */\n lastStepId?: string | null;\n}\n\nconst HOUR = 3600 * 1000;\n\n/**\n * Pure frequency evaluation. `shownThisSession` comes from session storage.\n * - `once`: a single impression ever (unless `reshowAfterDismiss` and it was only dismissed).\n * - `once_per_session`: at most once per browser session.\n * - `every_time`: on every trigger (still blocked by completion/dismissal rules below).\n * - `interval`: at most once every `intervalHours`.\n * `maxImpressions` caps total impressions; dismissal blocks re-showing unless `reshowAfterDismiss`\n * (then `cooldownHours` must have elapsed); completion blocks unless mode is `every_time`.\n */\nexport function isFrequencyEligible(freq: FrequencyConfig, state: GuideLocalState | undefined, shownThisSession: boolean, now: number = Date.now()): boolean {\n const s = state ?? { impressions: 0 };\n if (freq.maxImpressions != null && s.impressions >= freq.maxImpressions) return false;\n if (s.completedAt && freq.mode !== \"every_time\") return false;\n if (s.dismissedAt) {\n if (!freq.reshowAfterDismiss) return false;\n if (freq.cooldownHours > 0 && now - Date.parse(s.dismissedAt) < freq.cooldownHours * HOUR) return false;\n }\n switch (freq.mode) {\n case \"once\":\n return s.impressions === 0 || (!!s.dismissedAt && freq.reshowAfterDismiss);\n case \"once_per_session\":\n return !shownThisSession;\n case \"interval\": {\n if (!s.lastShownAt) return true;\n const hours = freq.intervalHours ?? 24;\n return now - Date.parse(s.lastShownAt) >= hours * HOUR;\n }\n case \"every_time\":\n default:\n return true;\n }\n}\n\n/**\n * Exclusive guides (flows, modals, tooltips, announcements, surveys) run one at a time.\n * Banners, checklists and hotspot-only tooltips can coexist with an active flow.\n */\nexport function isExclusiveGuide(guide: PublishedGuide): boolean {\n if (guide.kind === \"banner\" || guide.kind === \"checklist\") return false;\n const steps = guide.config.steps;\n if (steps.length > 0 && steps.every((s) => s.type === \"hotspot\" || s.type === \"banner\")) return false;\n return true;\n}\n\n/** Is `a` mutually exclusive with `b` (by id or key, in either direction)? */\nexport function areMutuallyExclusive(a: PublishedGuide, b: PublishedGuide): boolean {\n const la = a.config.frequency.mutuallyExclusiveWith;\n const lb = b.config.frequency.mutuallyExclusiveWith;\n return la.includes(b.id) || la.includes(b.key) || lb.includes(a.id) || lb.includes(a.key);\n}\n\n/**\n * Scheduling window: the guide's `schedule` (any kind) and, for surveys, `survey.startAt` / `endAt`.\n * Unparsable dates are ignored.\n */\nexport function isWithinSchedule(guide: Pick<PublishedGuide, \"config\">, now: number = Date.now()): boolean {\n for (const w of [guide.config.schedule, guide.config.survey]) {\n if (!w) continue;\n if (w.startAt && now < Date.parse(w.startAt)) return false;\n if (w.endAt && now > Date.parse(w.endAt)) return false;\n }\n return true;\n}\n\nconst MINUTE = 60 * 1000;\n\n/**\n * Does showing this guide automatically count toward (and get limited by) the project's guide\n * throttling? Only exclusive guides (flows, modals, tooltips, announcements, surveys) interrupt;\n * banners, checklists and hotspot-only guides never count, nor does a guide set to ignore throttling.\n * Guides started by the visitor or the app (`startGuide`, buttons, Help) are never throttled.\n */\nexport function countsTowardThrottle(guide: PublishedGuide): boolean {\n return isExclusiveGuide(guide) && !guide.config.frequency.ignoreThrottling;\n}\n\n/**\n * Pure throttling check. `launches` = ISO times of this visitor's earlier automatic launches of\n * counted guides (any order). Disabled or missing settings never throttle.\n */\nexport function isThrottleEligible(settings: GuideThrottlingSettings | null | undefined, launches: readonly string[], now: number = Date.now()): boolean {\n if (!settings || !settings.enabled) return true;\n const times = launches.map((l) => Date.parse(l)).filter((t) => !Number.isNaN(t));\n const windowMs = Math.max(1, settings.windowHours) * HOUR;\n if (times.filter((t) => now - t < windowMs).length >= Math.max(1, settings.maxGuides)) return false;\n if (settings.minGapMinutes > 0 && times.some((t) => now - t < settings.minGapMinutes * MINUTE)) return false;\n return true;\n}\n\n/** Launch times worth keeping: those still inside the window or the minimum gap (at most 100). */\nexport function pruneLaunches(launches: readonly string[], settings: GuideThrottlingSettings | null | undefined, now: number = Date.now()): string[] {\n const keepMs = Math.max(settings?.windowHours ?? 24, 1) * HOUR + (settings?.minGapMinutes ?? 0) * MINUTE;\n return launches.filter((l) => { const t = Date.parse(l); return !Number.isNaN(t) && now - t < keepMs; }).slice(-100);\n}\n\n/**\n * A checklist's dismissal after merging server state. A local dismissal normally wins (it may not have\n * synced yet), but when the server reports a reset this device hasn't applied, the server's value wins:\n * null, or a dismissal made on another device after the reset. Compared as tokens, not times, so a\n * skewed device clock can't keep a reset dismissal.\n */\nexport function dismissedAfterMerge(local: { dismissedAt?: string | null; dismissResetAt?: string | null } | undefined, server: { dismissedAt?: string | null; dismissResetAt?: string | null }): string | null {\n if (server.dismissResetAt && server.dismissResetAt !== local?.dismissResetAt) return server.dismissedAt ?? null;\n return local?.dismissedAt ?? server.dismissedAt ?? null;\n}\n","import { evaluateRules, guidelyIdFromSelector, rolloutBucket, isChecklistComplete, localizeGuide, localizeResourceCenter, normalizeLocale, orderedModules, randomId, RC_MODULE_IDS, type ResourceCenterModuleId, sanitizeProperties, screenPath, supportsPlatform, unreadAnnouncements, visibleAnnouncements, visitorLocales } from \"@guidelytech/shared/runtime\";\nimport type { AutocaptureSettings, ChecklistTask, EventName, IdentifyRequest, IdentifyResponse, ProjectTheme, PublishedGuide, ResourceCenterAnnouncement, ResourceCenterArticle, ResourceCenterConfig, RuleGroup, SdkConfigResponse, SdkEvent, StepButton, TargetingContext } from \"@guidelytech/shared\";\nimport {\n Api,\n Emitter,\n EventQueue,\n KEYS,\n Outbox,\n areMutuallyExclusive,\n countsTowardThrottle,\n dismissedAfterMerge,\n isExclusiveGuide,\n isFrequencyEligible,\n isThrottleEligible,\n isWithinSchedule,\n postWithRetry,\n pruneLaunches,\n readJson,\n writeJson,\n type ChecklistProgressState,\n type ConsentState,\n type GuideLocalState,\n type GuidelyAccount,\n type GuidelyUser,\n type PersistedState,\n type SessionState,\n} from \"@guidelytech/sdk-core/headless\";\nimport { createFlagsClient, type Attributes, type EvaluationResult, type FlagDetails, type FlagValue, type FlagsClient, type JsonValue } from \"@guidelytech/flags\";\nimport { LAUNCHER_PLACEMENT_KEY, parsePlacement, serializePlacement, type LauncherPlacement } from \"./launcherPlacement\";\nimport { HeatmapBuffer, heatmapPoint, RageClickDetector, tapProperties, type TapElement, type TapInfo } from \"./autocapture\";\nimport { runGuide, screenMatches, type GuideController } from \"./controller\";\nimport { fetchStreamPost, Messenger, xhrStreamPost, type MessengerTab } from \"./messenger\";\nimport { ReplayUploader, SessionRecorder, type ReplayCaptureOptions, type ScreenCapturer, type TouchPhase } from \"./replay\";\nimport { PersistentStore } from \"./storage\";\nimport { TargetRegistry, type Rect } from \"./targets\";\nimport type { ChecklistView, DeviceEnvironment, GuidelyEvents, GuidelyOptions, StepView, SurveyView, UiState } from \"./types\";\n\nexport const SDK_NAME = \"@guidelytech/react-native\";\nexport const SDK_VERSION = \"0.15.0\";\nexport const DEFAULT_API_URL = \"https://guidelytech.com\";\n\n/** Host-platform services the engine needs; the provider supplies React Native implementations. */\nexport interface PlatformBridge {\n device: DeviceEnvironment;\n /** Opens an external URL (React Native `Linking.openURL`). */\n openExternal(url: string): void;\n /** Window size in points (React Native `Dimensions.get(\"window\")`), for heatmaps. */\n windowSize?(): { width: number; height: number };\n /** Session-replay screenshots; absent where the native replay module is not installed. */\n capturer?: ScreenCapturer;\n}\n\ntype EvalReason = \"ready\" | \"navigation\" | \"event\" | \"click\" | \"visible\" | \"identify\" | \"after_guide\" | \"timer\" | \"manual\";\ninterface EvalDetail {\n eventName?: string;\n targetId?: string;\n guideId?: string;\n endedGuide?: PublishedGuide;\n newAudiences?: Set<string>;\n}\n\ninterface RunningFlow {\n guide: PublishedGuide;\n controller: GuideController;\n manual: boolean;\n view: StepView | null;\n}\n\ninterface QueuedGuide {\n guide: PublishedGuide;\n url: string;\n pageScoped: boolean;\n}\n\n/** Mobile sessions persist across launches and expire after the configured inactivity timeout. */\ninterface MobileSession extends SessionState {\n lastActiveAt: string;\n}\n\nconst PAGE_SCOPED = new Set([\"page_load\", \"url_match\", \"element_click\", \"element_visible\", \"delay\"]);\n\n/**\n * With a cached config, start from it when the server takes longer than this to answer (config or\n * identify): guides, the messenger and flags keep working through an outage, and the fresh answer\n * is applied when it arrives.\n */\nconst CACHED_START_MS = 1500;\n\n/** Resolves true when `promise` settles within `ms`, false otherwise (it keeps running either way). */\nfunction settlesWithin(promise: Promise<unknown>, ms: number): Promise<boolean> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(false), ms);\n const done = () => {\n clearTimeout(timer);\n resolve(true);\n };\n promise.then(done, done);\n });\n}\n\n/** `{ appVersion, build }` of the last launch, per public key (app_install / app_update detection). */\nconst appVersionKey = (key: string) => `guidely:app:${key}`;\n\n/** Stand-in for a tap whose view could not be identified (rage taps still need properties). */\nconst UNKNOWN_VIEW: TapElement = { selector: \"View\", tag: \"View\" };\n\nconst nowIso = () => new Date().toISOString();\nconst emptyState = (): PersistedState => ({ guides: {}, checklists: {}, surveysSubmitted: [], audienceIds: [] });\nconst newSession = (): MobileSession => ({ id: `s_${randomId(16)}`, startedAt: nowIso(), lastActiveAt: nowIso(), shownGuides: [], events: [] });\n\n/**\n * The React Native Guidely client: the web SDK's engine (config, identity, events, triggers,\n * frequency, checklists, surveys) with screens instead of URLs and `<GuidelyTarget>` views instead\n * of DOM elements. The overlay renders whatever {@link getUiState} describes.\n */\nexport class GuidelyClient {\n readonly options: Readonly<GuidelyOptions & { environment: NonNullable<GuidelyOptions[\"environment\"]>; apiUrl: string; analytics: boolean; configRefreshMs: number; debug: boolean }>;\n readonly targets = new TargetRegistry();\n private readonly bridge: PlatformBridge;\n private readonly api: Api;\n private readonly store: PersistentStore;\n private readonly emitter: Emitter<GuidelyEvents>;\n private queue: EventQueue | null = null;\n /** Survey answers, guide completions/dismissals and checklist progress, kept until the server has them. */\n private outbox: Outbox | null = null;\n private config: SdkConfigResponse | null = null;\n private configFetchedAt = 0;\n private etag: string | null = null;\n private anonymousId = \"\";\n private user: GuidelyUser | null = null;\n private state: PersistedState = emptyState();\n private session: MobileSession = newSession();\n private consent: ConsentState;\n private readyPromise: Promise<void> | null = null;\n private hydrated = false;\n private pending: Array<() => void> = [];\n private isReady = false;\n private destroyed = false;\n private active: RunningFlow | null = null;\n private activeSurvey: { guide: PublishedGuide; manual: boolean } | null = null;\n private queued: QueuedGuide[] = [];\n private flows = new Map<string, RunningFlow>();\n /** Checklists on screen, with the guide as rendered (in the visitor's language). */\n private checklists = new Map<string, { open: boolean; guide: PublishedGuide }>();\n private expanded = new Set<string>();\n private surveyView: SurveyView | null = null;\n private resourceCenterOpen = false;\n private cleanups: Array<() => void> = [];\n private timers = new Set<ReturnType<typeof setTimeout>>();\n private visibilityWatchers = new Map<string, () => void>();\n private firedDelays = new Set<string>();\n private firstVisit = true;\n private screenName = \"\";\n private lastAudiences = new Set<string>();\n private backgroundedAt: number | null = null;\n private messenger: Messenger | null = null;\n private replayUploader: ReplayUploader | null = null;\n private recorder: SessionRecorder | null = null;\n /** Replay decision for the current session (sampled once; forced by start/stopSessionRecording). */\n private replayDecision: { sessionId: string; record: boolean } | null = null;\n private ui: UiState = { steps: [], checklists: [], survey: null, resourceCenterOpen: false, theme: {}, messenger: false };\n private uiListeners = new Set<() => void>();\n /** Feature flags for this environment: `guidely.flags.isEnabled(\"new-checkout\")`. */\n readonly flags: FlagsClient;\n /** Experiments already reported this session (`experiment_viewed` is sent once per session). */\n private exposures = new Set<string>();\n // Product analytics (autocapture).\n private readonly rage = new RageClickDetector();\n private readonly heatmap = new HeatmapBuffer();\n /** Taps are processed in order (target frames are measured asynchronously). */\n private tapChain: Promise<void> = Promise.resolve();\n /** When the current screen's foreground measurement started; `screenLeft` once it has been reported. */\n private screenStartedAt = 0;\n private screenLeft = true;\n /** Last `app_open` (cold start or return to the foreground), for `app_background.foregroundMs`. */\n private openedAt = Date.now();\n private launchChecked = false;\n /** An identity was stored before this launch (an existing install adopting lifecycle events). */\n private hadIdentity = false;\n /** Language set with `setLocale()` (or the `locale` option). */\n private locale: string | null = null;\n /** Language each shown guide was rendered in; added to its events as `locale`. */\n private guideLocales = new Map<string, string>();\n /** The resource center in the visitor's language, recomputed when the config or language changes. */\n private localizedRc: { source: ResourceCenterConfig; locales: string; value: ResourceCenterConfig & { locale: string } } | null = null;\n /** \"What's new\" last-seen time when the resource center opened (entries after it read as new). */\n private announcementsSeenAtOpen: string | null = null;\n private readonly customListeners = new Map<string, Set<() => void>>();\n private readonly eventBus = {\n on: (name: string, cb: () => void) => {\n let set = this.customListeners.get(name);\n if (!set) {\n set = new Set();\n this.customListeners.set(name, set);\n }\n set.add(cb);\n return () => void set?.delete(cb);\n },\n };\n\n constructor(options: GuidelyOptions, bridge: PlatformBridge) {\n if (!options || !options.projectId) throw new Error(\"[Guidely] `projectId` (your environment public key, e.g. pk_dev_…) is required.\");\n this.options = {\n ...options,\n environment: options.environment ?? (options.projectId.startsWith(\"pk_prod\") ? \"production\" : options.projectId.startsWith(\"pk_stag\") ? \"staging\" : \"development\"),\n apiUrl: options.apiUrl ?? DEFAULT_API_URL,\n analytics: options.analytics ?? true,\n configRefreshMs: options.configRefreshMs ?? 5 * 60 * 1000,\n debug: options.debug ?? false,\n };\n this.bridge = bridge;\n this.consent = options.consent ?? \"granted\";\n this.emitter = new Emitter<GuidelyEvents>((err) => this.reportError(err));\n this.api = new Api(this.options.apiUrl, this.options.projectId, options.fetch);\n this.store = new PersistentStore(options.storage ?? null, (err) => this.log(\"storage error\", err));\n if (!options.storage) this.log(\"no `storage` passed: identity, guide history, queued events and survey answers last only for this app session, so whatever could not be sent during a Guidely outage is lost when the app restarts. Pass AsyncStorage to persist them.\");\n this.cleanups.push(this.targets.onTap((id) => this.handleTap(id)));\n if (options.user) this.user = { ...options.user };\n this.locale = options.locale ? normalizeLocale(options.locale) || null : null;\n this.flags = this.createFlags(options.flags);\n }\n\n private createFlags(opts: GuidelyOptions[\"flags\"]): FlagsClient {\n const base = { sdkKey: this.options.projectId, apiUrl: this.options.apiUrl, fetch: this.options.fetch, sdk: { name: SDK_NAME, version: SDK_VERSION } };\n if (opts === false) return createFlagsClient({ ...base, overrideBehaviour: \"localOnly\", offline: true, reportUsage: false, trackExposures: false, storage: false, logger: null });\n const o = opts ?? {};\n return createFlagsClient({\n ...base,\n storage: this.options.storage ?? false,\n reportUsage: this.options.analytics,\n // Failures surface through onError (and `debug` logs); development warnings (unknown flag keys) reach the console.\n logger: { warn: (...a: unknown[]) => console.warn(\"[Guidely]\", ...a), error: (...a: unknown[]) => this.log(...a) },\n ...o,\n contextAttributes: this.flagContext(),\n // Exposures travel through the event pipeline (with the session) as `experiment_viewed`.\n trackExposures: false,\n onFlagEvaluated: (result) => {\n this.trackExposure(result);\n o.onFlagEvaluated?.(result);\n },\n onReady: () => {\n this.emitter.emit(\"flags:ready\");\n o.onReady?.();\n },\n onChange: (data) => {\n this.emitter.emit(\"flags:change\");\n o.onChange?.(data);\n },\n onError: (err) => {\n this.reportError(err);\n o.onError?.(err);\n },\n });\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Loads persisted state and config, identifies the stored user and evaluates triggers. Idempotent. */\n init(): Promise<void> {\n if (!this.readyPromise) this.readyPromise = this.bootstrap();\n return this.readyPromise;\n }\n\n ready(): Promise<void> {\n return this.init();\n }\n\n private async bootstrap(): Promise<void> {\n const key = this.options.projectId;\n try {\n await this.store.hydrate([KEYS.anon, KEYS.seen, KEYS.session, KEYS.config(key), KEYS.etag(key), KEYS.state(key), KEYS.user(key), KEYS.queue(key), KEYS.outbox(key), KEYS.conversations(key), appVersionKey(key), LAUNCHER_PLACEMENT_KEY]);\n if (this.destroyed) return;\n this.anonymousId = this.store.get(KEYS.anon) || \"\";\n this.hadIdentity = !!this.anonymousId;\n if (!this.anonymousId) {\n this.anonymousId = `anon_${randomId(20)}`;\n this.store.set(KEYS.anon, this.anonymousId);\n }\n this.firstVisit = !this.store.get(KEYS.seen);\n this.store.set(KEYS.seen, nowIso());\n this.state = { ...emptyState(), ...readJson<Partial<PersistedState>>(this.store, KEYS.state(key), {}) };\n this.user = this.options.user ? { ...this.options.user } : readJson<GuidelyUser | null>(this.store, KEYS.user(key), null);\n const saved = readJson<MobileSession | null>(this.store, KEYS.session, null);\n this.session = saved?.id && !this.sessionExpired(Date.parse(saved.lastActiveAt)) ? saved : newSession();\n this.persistSession();\n this.lastAudiences = new Set(this.state.audienceIds);\n this.syncFlagAttributes(); // stored identity is known now\n // Both read what a previous launch left unsent from the hydrated store (and resend it).\n this.queue = new EventQueue({\n store: this.store,\n storageKey: KEYS.queue(key),\n enabled: () => this.analyticsEnabled(),\n health: this.api.health,\n send: async (events) => {\n const res = await this.api.post<{ accepted: number }>(\"/events\", { events, sentAt: nowIso(), sdk: { name: SDK_NAME, version: SDK_VERSION } });\n return { ok: res.ok, retry: !(res.status >= 400 && res.status < 500 && res.status !== 429) };\n },\n onError: (err) => this.reportError(err),\n });\n this.outbox = new Outbox({ api: this.api, store: this.store, storageKey: KEYS.outbox(key), health: this.api.health });\n this.hydrated = true;\n const cached = readJson<SdkConfigResponse | null>(this.store, KEYS.config(key), null);\n this.etag = this.store.get(KEYS.etag(key));\n if (cached && Array.isArray(cached.guides)) this.config = forPlatform(cached, this.bridge.device.platform);\n this.syncMessenger();\n // Calls made before storage was ready (track, screen, identify…) run now, in order.\n this.pending.splice(0).forEach((fn) => fn());\n const before = this.config?.configVersion;\n const fresh = this.fetchConfig();\n // With a cached config a slow or unreachable server doesn't hold guides back: start from the\n // cache and apply the fresh config when it lands. Without one there is nothing to show yet.\n if (!this.config) await fresh;\n else if (!(await settlesWithin(fresh, CACHED_START_MS))) void fresh.then(() => this.applyConfigChange(before));\n if (this.destroyed) return;\n this.checkLaunch();\n this.wireTimers();\n // identify() re-evaluates guides when it completes, so a slow answer is applied later too.\n if (this.user?.id) await settlesWithin(this.identify(this.user.id, this.user.traits, this.user.account), CACHED_START_MS);\n if (this.destroyed) return;\n this.isReady = true;\n if (this.config) this.emitter.emit(\"ready\", this.config);\n this.syncReplay();\n this.notify();\n this.evaluate(\"ready\");\n } catch (err) {\n this.reportError(err);\n this.isReady = true;\n }\n }\n\n private whenHydrated(fn: () => void): void {\n if (this.destroyed) return;\n if (this.hydrated) fn();\n else this.pending.push(fn);\n }\n\n private async fetchConfig(): Promise<boolean> {\n try {\n const res = await this.api.get<SdkConfigResponse>(\"/config\", { etag: this.etag, params: { platform: this.bridge.device.platform } });\n this.configFetchedAt = Date.now();\n if (res.status === 304) return true;\n if (res.ok && res.data && Array.isArray(res.data.guides)) {\n this.config = forPlatform(res.data, this.bridge.device.platform);\n this.etag = res.etag;\n writeJson(this.store, KEYS.config(this.options.projectId), res.data);\n if (res.etag) this.store.set(KEYS.etag(this.options.projectId), res.etag);\n else this.store.remove(KEYS.etag(this.options.projectId));\n this.syncMessenger();\n // A launch that started without any config records its lifecycle events once one arrives.\n if (this.hydrated) this.checkLaunch();\n this.emitter.emit(\"config\", this.config);\n this.syncReplay();\n this.log(\"config loaded\", this.config.configVersion, `${this.config.guides.length} guides`);\n return true;\n }\n this.reportError(new Error(`[Guidely] config request failed (${res.status})${this.config ? \"; using cached config\" : \"\"}`));\n return false;\n } catch (err) {\n this.reportError(new Error(`[Guidely] config request failed: ${err instanceof Error ? err.message : String(err)}${this.config ? \"; using cached config\" : \"\"}`));\n return false;\n }\n }\n\n private wireTimers(): void {\n // Skipped while the API's circuit is open; the cached config keeps serving meanwhile.\n const refresh = setInterval(() => {\n if (this.api.health.canSend()) void this.refresh();\n }, this.options.configRefreshMs);\n this.cleanups.push(() => clearInterval(refresh));\n // Targets mount and unmount without navigation (lists, tabs): re-arm visibility triggers and drain the queue.\n const poll = setInterval(() => {\n if (!this.isReady || !this.config || this.backgroundedAt !== null) return;\n const url = this.currentUrl();\n const ctx = this.getContext();\n for (const guide of this.candidates()) if (guide.config.trigger.type === \"element_visible\" && guide.config.trigger.value) this.armVisibility(guide, ctx, url);\n this.drainQueue(url, ctx);\n }, 1000);\n this.cleanups.push(() => clearInterval(poll));\n }\n\n /** Re-fetches the published config and re-evaluates triggers. */\n async refresh(): Promise<void> {\n if (this.destroyed) return;\n const before = this.config?.configVersion;\n await this.fetchConfig();\n this.applyConfigChange(before);\n }\n\n /** Re-renders after a config change (refresh, or a config that arrived after start). */\n private applyConfigChange(before: number | undefined): void {\n if (this.destroyed || !this.isReady) return;\n if (this.config && this.config.configVersion !== before) {\n this.notify();\n this.evaluate(\"ready\");\n }\n }\n\n /** Called by the provider with React Native `AppState` changes. */\n setAppState(state: \"active\" | \"background\" | \"inactive\" | string): void {\n if (this.destroyed || !this.hydrated) return;\n if (state === \"background\") {\n const wasForeground = this.backgroundedAt === null;\n this.backgroundedAt = Date.now();\n // Before the flushes below, so these events leave with them.\n if (wasForeground) this.wentToBackground();\n this.session.lastActiveAt = nowIso();\n this.persistSession();\n void this.queue?.flush();\n void this.outbox?.flush();\n void this.store.flush();\n void this.flags.flush();\n this.recorder?.pause();\n this.messenger?.setForeground(false);\n } else if (state === \"active\" && this.backgroundedAt !== null) {\n this.messenger?.setForeground(true);\n const away = this.backgroundedAt;\n this.backgroundedAt = null;\n if (this.sessionExpired(away)) {\n this.session = newSession();\n this.persistSession();\n this.firedDelays.clear();\n this.recorder?.stop(false); // the old session's recording is uploaded; a new one starts below\n }\n this.recorder?.resume();\n this.syncReplay();\n this.cameToForeground();\n void this.flags.refresh();\n if (Date.now() - this.configFetchedAt > this.options.configRefreshMs && this.api.health.canSend()) void this.refresh();\n else if (this.isReady) this.evaluate(\"ready\");\n }\n }\n\n private sessionExpired(lastActiveMs: number): boolean {\n const minutes = this.config?.settings?.sessionTimeoutMinutes ?? 30;\n return !Number.isFinite(lastActiveMs) || Date.now() - lastActiveMs > minutes * 60_000;\n }\n\n /** Tears everything down. Create a new client to start again. */\n destroy(): void {\n if (this.destroyed) return;\n this.flushHeatmap();\n this.destroyed = true;\n this.active?.controller.destroy();\n this.active = null;\n this.flows.forEach((f) => f.controller.destroy());\n this.flows.clear();\n this.queued = [];\n this.messenger?.destroy();\n this.messenger = null;\n this.recorder?.stop(!this.analyticsEnabled());\n this.recorder = null;\n this.replayUploader?.destroy();\n this.visibilityWatchers.forEach((stop) => stop());\n this.visibilityWatchers.clear();\n this.timers.forEach((t) => clearTimeout(t));\n this.timers.clear();\n this.cleanups.splice(0).forEach((fn) => fn());\n void this.queue?.flush();\n this.queue?.destroy();\n this.outbox?.destroy();\n this.flags.destroy();\n this.emitter.clear();\n this.uiListeners.clear();\n }\n\n // ---------------------------------------------------------------------------\n // Identity\n // ---------------------------------------------------------------------------\n\n /** Identifies the end user and loads server-held state (audiences, guide history, checklist progress). */\n identify(userId: string, traits?: Record<string, unknown>, account?: GuidelyAccount): Promise<void> {\n return new Promise((resolve) =>\n this.whenHydrated(() => {\n const id = String(userId);\n const same = this.user?.id === id;\n this.user = { id, traits: { ...(same ? this.user?.traits : {}), ...(traits || {}) }, account: account ?? (same ? this.user?.account : undefined) };\n writeJson(this.store, KEYS.user(this.options.projectId), this.user);\n this.syncFlagAttributes();\n this.enqueue(\"identify\", { properties: { traits: sanitizeProperties(this.user.traits) } });\n void this.syncIdentify().then(() => {\n this.emitter.emit(\"identify\", { userId: id, anonymousId: this.anonymousId });\n if (this.isReady) this.evaluate(\"identify\");\n resolve();\n });\n }),\n );\n }\n\n private async syncIdentify(): Promise<void> {\n const body: IdentifyRequest = { anonymousId: this.anonymousId, userId: this.user?.id || null, traits: this.user?.traits, account: this.user?.account ? { id: this.user.account.id, traits: this.user.account.traits } : null, sessionId: this.session.id, url: this.collectUrls() ? this.currentUrl() : undefined };\n const res = await postWithRetry<IdentifyResponse>(this.api, \"/identify\", body, 2);\n if (res?.ok && res.data) this.mergeServerState(res.data);\n }\n\n private mergeServerState(data: IdentifyResponse): void {\n const guides = { ...this.state.guides };\n for (const [id, s] of Object.entries(data.guideState || {})) {\n const local = guides[id];\n guides[id] = {\n ...local,\n impressions: Math.max(local?.impressions ?? 0, s.impressions ?? 0),\n completedAt: local?.completedAt ?? s.completedAt ?? null,\n dismissedAt: local?.dismissedAt ?? s.dismissedAt ?? null,\n lastShownAt: local?.lastShownAt ?? s.lastShownAt ?? null,\n };\n }\n const checklists = { ...this.state.checklists };\n for (const [id, p] of Object.entries(data.checklistProgress || {})) {\n const local = checklists[id];\n checklists[id] = {\n completedTaskIds: Array.from(new Set([...(local?.completedTaskIds ?? []), ...(p.completedTaskIds ?? [])])),\n completedAt: local?.completedAt ?? p.completedAt ?? null,\n dismissedAt: dismissedAfterMerge(local, p),\n dismissResetAt: p.dismissResetAt ?? local?.dismissResetAt ?? null,\n };\n }\n this.state = {\n guides,\n checklists,\n surveysSubmitted: Array.from(new Set([...this.state.surveysSubmitted, ...(data.surveysSubmitted || [])])),\n audienceIds: data.audienceIds || [],\n firstSeenAt: this.state.firstSeenAt ?? data.firstSeenAt,\n // Device-local only (the server doesn't hold them).\n ...(this.state.throttle ? { throttle: this.state.throttle } : {}),\n ...(this.state.announcementsSeenAt ? { announcementsSeenAt: this.state.announcementsSeenAt } : {}),\n };\n if (data.firstSeenAt && Date.now() - Date.parse(data.firstSeenAt) > 60_000) this.firstVisit = false;\n this.persistState();\n this.syncFlagAttributes(); // audiences\n this.notify();\n }\n\n /** Sets or replaces the account (company / organisation) for the current user. */\n async setAccount(account: GuidelyAccount): Promise<void> {\n await this.init();\n if (!this.user?.id) {\n this.user = { id: \"\", traits: this.user?.traits, account };\n writeJson(this.store, KEYS.user(this.options.projectId), this.user);\n this.syncFlagAttributes();\n return;\n }\n await this.identify(this.user.id, undefined, account);\n }\n\n /** Merges additional traits into the current user. */\n async updateTraits(traits: Record<string, unknown>): Promise<void> {\n await this.init();\n if (!this.user?.id) {\n this.user = { id: \"\", traits: { ...(this.user?.traits || {}), ...traits }, account: this.user?.account };\n this.syncFlagAttributes();\n return;\n }\n await this.identify(this.user.id, traits, this.user.account);\n }\n\n /** Forgets the user (call on logout): new anonymous id, cleared guide/checklist state, new session. */\n reset(): void {\n this.whenHydrated(() => {\n this.stopGuide();\n this.flows.forEach((f) => f.controller.destroy());\n this.flows.clear();\n this.checklists.clear();\n this.surveyView = null;\n this.activeSurvey = null;\n this.resourceCenterOpen = false;\n // Conversations belong to the previous user.\n if (this.messenger) this.messenger.forgetAll();\n else this.store.remove(KEYS.conversations(this.options.projectId));\n this.user = null;\n this.store.remove(KEYS.user(this.options.projectId));\n this.anonymousId = `anon_${randomId(20)}`;\n this.store.set(KEYS.anon, this.anonymousId);\n this.state = emptyState();\n this.persistState();\n this.recorder?.stop(false); // the recording belongs to the previous user; restarted below when eligible\n this.session = newSession();\n this.persistSession();\n this.lastAudiences = new Set();\n this.firedDelays.clear();\n this.firstVisit = true;\n this.exposures.clear();\n this.syncFlagAttributes();\n this.syncReplay();\n this.emitter.emit(\"identify\", { userId: null, anonymousId: this.anonymousId });\n this.notify();\n if (this.isReady) this.evaluate(\"identify\");\n });\n }\n\n // ---------------------------------------------------------------------------\n // Events & screens\n // ---------------------------------------------------------------------------\n\n /** Updates consent at runtime (`granted` flushes buffered events; `denied` drops them). */\n setConsent(consent: ConsentState): void {\n this.consent = consent;\n this.whenHydrated(() => {\n if (consent === \"denied\") this.queue?.clear();\n else if (consent === \"granted\") void this.queue?.flush();\n this.syncReplay();\n });\n }\n\n private analyticsEnabled(): boolean {\n return this.options.analytics && this.consent === \"granted\" && (this.config?.settings?.analyticsEnabled ?? true);\n }\n\n private collectUrls(): boolean {\n return this.config?.settings?.collectUrls ?? true;\n }\n\n private currentUrl(): string {\n return screenPath(this.screenName);\n }\n\n private enqueue(name: EventName, extra: Partial<SdkEvent> = {}): SdkEvent | null {\n if (this.consent === \"denied\" || !this.options.analytics || !this.queue) return null;\n const event: SdkEvent = {\n eventId: randomId(24),\n name,\n occurredAt: nowIso(),\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n accountId: this.user?.account?.id || null,\n sessionId: this.session.id,\n url: this.collectUrls() && this.screenName ? this.currentUrl() : undefined,\n ...extra,\n };\n if (extra.properties) event.properties = sanitizeProperties(extra.properties);\n const locale = extra.guideId ? this.guideLocales.get(extra.guideId) : undefined;\n if (locale) event.properties = { ...(event.properties ?? {}), locale };\n this.queue.enqueue(event);\n this.recorder?.addGuidelyEvent(name, event.customName, event.guideId);\n this.emitter.emit(\"track\", event);\n return event;\n }\n\n /** Tracks a custom event. Events drive `event` triggers, `advanceOn: \"event\"` steps and checklist tasks. */\n track(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n this.whenHydrated(() => {\n if (!this.session.events.includes(name)) {\n this.session.events.push(name);\n this.persistSession();\n }\n this.enqueue(\"custom\", { customName: name.slice(0, 120), properties: properties ?? {} });\n this.customListeners.get(name)?.forEach((cb) => {\n try {\n cb();\n } catch (err) {\n this.reportError(err);\n }\n });\n this.completeChecklistTasksBy(\"event\", name);\n if (this.isReady) this.evaluate(\"event\", { eventName: name });\n });\n }\n\n /**\n * Records a screen view (the mobile equivalent of a page view) and re-evaluates triggers. URL\n * patterns, `url_match` triggers, multi-screen steps and `url_visited` tasks match `/<name>`.\n */\n screen(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n this.whenHydrated(() => {\n const changed = name !== this.screenName;\n if (changed) {\n // Time on the screen being left, and its heatmap batch.\n this.leaveScreen();\n this.flushHeatmap();\n }\n this.screenName = name;\n this.targets.setScreen(name);\n if (changed) this.recorder?.onScreen();\n if (changed) this.syncFlagAttributes();\n const url = this.currentUrl();\n if (changed) {\n this.screenStartedAt = Date.now();\n this.screenLeft = this.backgroundedAt !== null;\n if (this.pageviewsOn()) this.enqueue(\"page_view\", { properties: { ...properties, path: url, screen: name, ...this.deviceProperties() } });\n }\n this.completeChecklistTasksBy(\"url_visited\", url);\n this.active?.controller.resume();\n this.flows.forEach((f) => f.controller.resume());\n if (this.active) {\n const st = this.active.controller.getState();\n const g = this.active.guide;\n if (st.status === \"running\" && !this.active.manual && g.config.urlPatterns.length && !g.config.urlPatterns.some((p) => screenMatches(p, url))) this.active.controller.destroy();\n }\n // Banners and hotspots are screen-scoped too: close the ones whose patterns no longer match.\n this.flows.forEach((f) => {\n const patterns = f.guide.config.urlPatterns;\n if (!f.manual && patterns.length && !patterns.some((p) => screenMatches(p, url))) f.controller.destroy();\n });\n this.firedDelays.clear();\n if (this.isReady) this.evaluate(\"navigation\");\n if (changed) void this.queue?.flush();\n });\n }\n\n /** The current screen name (last value passed to `screen()`). */\n getScreen(): string {\n return this.screenName;\n }\n\n private handleTap(targetId: string): void {\n if (!this.hydrated) return;\n this.completeChecklistTasksBy(\"click\", targetId);\n if (this.isReady) this.evaluate(\"click\", { targetId });\n }\n\n // ---------------------------------------------------------------------------\n // Session replay\n // ---------------------------------------------------------------------------\n\n private replaySettings() {\n const r = this.config?.settings?.replay;\n if (!r?.enabled || !this.options.sessionReplay?.enabled || !this.bridge.capturer) return null;\n return r;\n }\n\n /** Reconciles recording with config, consent, readiness, the session and its sample decision. Idempotent. */\n private syncReplay(): void {\n if (this.destroyed || !this.hydrated) return;\n const r = this.isReady && this.analyticsEnabled() ? this.replaySettings() : null;\n const id = this.session.id;\n if (r && this.replayDecision?.sessionId !== id) {\n this.replayDecision = { sessionId: id, record: rolloutBucket(id, \"replay\") < (r.sampleRate ?? 100) };\n this.log(`replay ${this.replayDecision.record ? \"sampled\" : \"not sampled\"} for session ${id}`);\n }\n if (!r || !this.replayDecision?.record) {\n if (this.recorder?.isRecording) this.recorder.stop(!this.analyticsEnabled());\n return;\n }\n const rec = this.recorder ?? this.createRecorder();\n if (rec && rec.sessionId !== id) {\n this.log(`recording session ${id}`);\n rec.start(id);\n }\n }\n\n private createRecorder(): SessionRecorder | null {\n const capturer = this.bridge.capturer;\n if (!capturer) return null;\n const uploader =\n this.replayUploader ??\n (this.replayUploader = new ReplayUploader({\n url: () => this.api.url(\"/replay\"),\n fetch: () => this.options.fetch ?? (typeof fetch === \"function\" ? fetch : null),\n health: this.api.health,\n meta: () => {\n const rec = this.recorder;\n return {\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n ...(this.collectUrls() && this.screenName ? { url: this.currentUrl() } : {}),\n device: { type: this.bridge.device.deviceType, os: this.bridge.device.platform },\n ...(rec && rec.viewportWidth > 0 && rec.viewportHeight > 0 ? { viewport: { width: rec.viewportWidth, height: rec.viewportHeight } } : {}),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n };\n },\n onDisabled: (sid) => {\n if (sid !== this.session.id) return;\n this.log(`replay disabled by the server for session ${sid}`);\n this.replayDecision = { sessionId: sid, record: false };\n this.recorder?.stop(true);\n },\n log: (m) => this.log(m),\n }));\n const opts = this.options.sessionReplay ?? {};\n const rec = new SessionRecorder({\n capturer,\n uploader,\n intervalMs: opts.captureIntervalMs ?? 1000,\n captureOptions: () => this.replayCaptureOptions(),\n href: () => this.currentUrl(),\n onError: (err) => this.reportError(err),\n });\n if (this.backgroundedAt !== null) rec.pause();\n this.recorder = rec;\n return rec;\n }\n\n private async replayCaptureOptions(): Promise<ReplayCaptureOptions> {\n const r = this.config?.settings?.replay;\n const opts = this.options.sessionReplay ?? {};\n const ids = new Set((r?.blockSelectors ?? []).map((sel) => guidelyIdFromSelector(sel)).filter((id): id is string => !!id));\n const rects = await Promise.all(Array.from(ids, (id) => this.targets.measure(id)));\n return { maskAllText: !!opts.maskAllText || !!r?.maskAllText, maskAllImages: !!opts.maskAllImages || !!r?.maskAllImages, blockRects: rects.filter((rect): rect is Rect => !!rect) };\n }\n\n /**\n * Records this session even when it was not sampled (still needs `sessionReplay.enabled`, replay\n * enabled for the project, analytics consent and the native replay module). Sticks until the session ends.\n */\n startSessionRecording(): void {\n this.whenHydrated(() => {\n this.replayDecision = { sessionId: this.session.id, record: true };\n this.syncReplay();\n });\n }\n\n /** Stops recording for the rest of this session; what was recorded is uploaded. */\n stopSessionRecording(): void {\n this.whenHydrated(() => {\n this.replayDecision = { sessionId: this.session.id, record: false };\n this.recorder?.stop(false);\n });\n }\n\n /** True while this session is being recorded. */\n isRecording(): boolean {\n return !!this.recorder?.isRecording;\n }\n\n /** The current analytics session id (also the replay id). */\n getSessionId(): string {\n return this.session.id;\n }\n\n /** True when touches should be passed to {@link recordTouch}. */\n isRecordingTouches(): boolean {\n return !!this.recorder?.isRecording;\n }\n\n /** A primary-pointer touch on the app, in window points (the provider's touch observer calls this). */\n recordTouch(phase: TouchPhase, x: number, y: number): void {\n this.recorder?.touch(phase, x, y);\n }\n\n // ---------------------------------------------------------------------------\n // Product analytics (autocapture)\n // ---------------------------------------------------------------------------\n\n private captureAllowed(): boolean {\n return !this.destroyed && this.analyticsEnabled();\n }\n\n /** A capability runs when the project enables it (absent on old servers → off), no option turns it off and analytics are allowed. */\n private autocaptureOn(key: keyof AutocaptureSettings): boolean {\n const o = this.options.autocapture;\n return !!this.config?.settings?.autocapture?.[key] && o !== false && !(typeof o === \"object\" && o?.[key] === false) && this.captureAllowed();\n }\n\n /** `page_view` from `screen()` predates autocapture: only an explicit opt-out stops it. */\n private pageviewsOn(): boolean {\n const o = this.options.autocapture;\n return this.config?.settings?.autocapture?.pageviews !== false && o !== false && !(typeof o === \"object\" && o?.pageviews === false);\n }\n\n /** True when taps are worth observing (clicks, rage taps or heatmaps are on); the provider skips resolving views otherwise. */\n isTapCaptureOn(): boolean {\n return this.hydrated && (this.autocaptureOn(\"clicks\") || this.autocaptureOn(\"rageClicks\") || this.autocaptureOn(\"heatmaps\"));\n }\n\n /**\n * Records a tap observed by the provider: `click` for an interactive element, `rage_click` for\n * bursts and a heatmap point. A registered `<GuidelyTarget>` whose frame contains the point\n * (smallest wins) takes precedence over the resolved element and is reported as `#<id>`.\n */\n recordTap(tap: TapInfo): void {\n try {\n if (!this.hydrated || this.destroyed || !Number.isFinite(tap.x) || !Number.isFinite(tap.y)) return;\n const on = { clicks: this.autocaptureOn(\"clicks\"), rage: this.autocaptureOn(\"rageClicks\"), heat: this.autocaptureOn(\"heatmaps\") };\n if (!on.clicks && !on.rage && !on.heat) return;\n const t = tap.t ?? Date.now();\n // The screen at tap time: navigation often lands while target frames are being measured.\n const url = this.screenName ? this.currentUrl() : \"\";\n this.tapChain = this.tapChain.then(() => this.processTap(tap, t, url, on)).catch((err) => this.reportError(err));\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private async processTap(tap: TapInfo, t: number, url: string, on: { clicks: boolean; rage: boolean; heat: boolean }): Promise<void> {\n let el = tap.element ?? null;\n let rect: Rect | null = null;\n const target = this.targets.ids().length ? await this.targets.hitTest(tap.x, tap.y) : null;\n if (target) {\n el = { selector: `#${target.id}`, tag: el?.tag ?? tap.hit?.tag ?? \"View\", text: el?.text };\n rect = target.rect;\n }\n if (this.destroyed) return;\n const platform = this.bridge.device.platform;\n const maskAll = !!this.config?.settings?.replay?.maskAllText || !!this.options.sessionReplay?.maskAllText;\n const eventUrl = this.collectUrls() && url ? url : undefined;\n if (on.clicks && el) this.enqueue(\"click\", { url: eventUrl, properties: { ...tapProperties(el, tap.x, tap.y, platform, maskAll) } });\n const count = this.rage.add(tap.x, tap.y, t);\n if (on.rage && count) this.enqueue(\"rage_click\", { url: eventUrl, properties: { ...tapProperties(el ?? tap.hit ?? UNKNOWN_VIEW, tap.x, tap.y, platform, maskAll), count } });\n if (!on.heat) return;\n const burst = this.rage.burst;\n if (el && !rect && el.measure) rect = await el.measure().catch(() => null);\n if (this.destroyed) return;\n if (this.heatmap.url !== url) this.flushHeatmap();\n if (this.heatmap.add(url, heatmapPoint(tap.x, tap.y, el, rect, burst > 0), burst)) this.flushHeatmap();\n }\n\n /** Sends the buffered heatmap taps as one `heatmap` event attributed to the screen they happened on. */\n private flushHeatmap(): void {\n const batch = this.heatmap.take();\n if (!batch || !this.captureAllowed()) return;\n const collect = this.collectUrls() && !!batch.url;\n const { width, height } = this.windowSize();\n this.enqueue(\"heatmap\", {\n url: collect ? batch.url : undefined,\n properties: { ...(collect ? { path: batch.url } : {}), viewportWidth: width, viewportHeight: height, pageHeight: height, platform: this.bridge.device.platform, points: batch.points },\n });\n }\n\n private windowSize(): { width: number; height: number } {\n try {\n const s = this.bridge.windowSize?.();\n if (s && Number.isFinite(s.width) && Number.isFinite(s.height)) return { width: Math.round(s.width), height: Math.round(s.height) };\n } catch {\n /* fall through */\n }\n return { width: 0, height: 0 };\n }\n\n /** Ends the foreground measurement of the current screen with a `page_leave` (once per measurement). */\n private leaveScreen(): void {\n if (!this.screenName || this.screenLeft) return;\n this.screenLeft = true;\n if (!this.autocaptureOn(\"pageLeave\")) return;\n const url = this.currentUrl();\n const collect = this.collectUrls();\n this.enqueue(\"page_leave\", {\n url: collect ? url : undefined,\n properties: { ...(collect ? { path: url } : {}), screen: this.screenName, durationMs: Math.max(0, Date.now() - this.screenStartedAt), scrollDepth: 100, platform: this.bridge.device.platform },\n });\n }\n\n /** `{ appVersion, build }` of this launch, without unknown keys. */\n private appInfo(): { appVersion?: string; build?: string } {\n const appVersion = this.options.appVersion ?? this.bridge.device.appVersion;\n // A detected build belongs to the detected version, not to an `appVersion` the app passed.\n const build = this.options.appBuild ?? (this.options.appVersion ? undefined : this.bridge.device.appBuild);\n return { ...(appVersion ? { appVersion: String(appVersion) } : {}), ...(build ? { build: String(build) } : {}) };\n }\n\n /**\n * Once per launch, as soon as a config is known: `app_install` / `app_update` from the stored\n * version (when the app version is known and the app passes `storage`), then `app_open` with `coldStart: true`.\n */\n private checkLaunch(): void {\n if (this.launchChecked || !this.config || this.destroyed || !this.hydrated) return;\n this.launchChecked = true;\n try {\n const on = this.autocaptureOn(\"appLifecycle\");\n const info = this.appInfo();\n if (info.appVersion && this.options.storage) {\n const key = appVersionKey(this.options.projectId);\n const stored = readJson<{ appVersion?: string; build?: string } | null>(this.store, key, null);\n if (!stored?.appVersion) {\n // No stored version: a fresh install, unless this install predates lifecycle events (stored identity).\n if (!this.hadIdentity && on) this.enqueue(\"app_install\", { properties: { ...info } });\n } else if (stored.appVersion !== info.appVersion || (!!stored.build && !!info.build && stored.build !== info.build)) {\n if (on) this.enqueue(\"app_update\", { properties: { ...info, previousVersion: stored.appVersion, ...(stored.build ? { previousBuild: stored.build } : {}) } });\n }\n writeJson(this.store, key, info);\n }\n if (on) this.enqueue(\"app_open\", { properties: { ...info, coldStart: true } });\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private wentToBackground(): void {\n try {\n this.leaveScreen();\n this.flushHeatmap();\n if (this.launchChecked && this.autocaptureOn(\"appLifecycle\")) this.enqueue(\"app_background\", { properties: { foregroundMs: Math.max(0, Date.now() - this.openedAt) } });\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private cameToForeground(): void {\n try {\n this.openedAt = Date.now();\n if (this.launchChecked && this.autocaptureOn(\"appLifecycle\")) this.enqueue(\"app_open\", { properties: { ...this.appInfo(), coldStart: false } });\n if (this.screenName && this.screenLeft) {\n // A new measurement of the screen, paired with a page_view so every page_leave has one.\n this.screenStartedAt = Date.now();\n this.screenLeft = false;\n if (this.pageviewsOn() && this.autocaptureOn(\"pageLeave\")) this.enqueue(\"page_view\", { properties: { path: this.currentUrl(), screen: this.screenName, ...this.deviceProperties(), resumed: true } });\n }\n } catch (err) {\n this.reportError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Targeting + triggers\n // ---------------------------------------------------------------------------\n\n /** Builds the targeting context for the current moment. */\n getContext(): TargetingContext {\n const guides = this.state.guides;\n const keysOf = (ids: string[]) => ids.flatMap((id) => [id, this.findGuide(id)?.key ?? id]);\n const url = this.currentUrl();\n const device = this.bridge.device;\n return {\n anonymousId: this.anonymousId,\n userId: this.user?.id || null,\n userAttributes: this.user?.traits ?? {},\n accountAttributes: this.user?.account?.traits ?? {},\n url,\n path: url,\n query: {},\n device: { type: device.deviceType, os: device.platform },\n firstVisit: this.firstVisit,\n eventsSeen: new Set(this.session.events),\n completedGuides: new Set(keysOf(Object.keys(guides).filter((id) => guides[id]?.completedAt))),\n dismissedGuides: new Set(keysOf(Object.keys(guides).filter((id) => guides[id]?.dismissedAt))),\n seenGuides: new Set(keysOf(Object.keys(guides).filter((id) => (guides[id]?.impressions ?? 0) > 0))),\n completedChecklists: new Set(keysOf(Object.entries(this.state.checklists).filter(([, p]) => !!p.completedAt).map(([id]) => id))),\n audienceIds: new Set(this.state.audienceIds),\n now: new Date(),\n environment: this.options.environment,\n locale: device.locale,\n platform: device.platform,\n screen: this.screenName,\n appVersion: this.options.appVersion ?? device.appVersion,\n };\n }\n\n private isTargeted(guide: PublishedGuide, ctx: TargetingContext, url: string): boolean {\n const c = guide.config;\n if (c.urlPatterns.length && !c.urlPatterns.some((p) => screenMatches(p, url))) return false;\n if (c.trigger.urlPattern && !screenMatches(c.trigger.urlPattern, url)) return false;\n if (!isWithinSchedule(guide)) return false;\n if (guide.kind === \"survey\" && (this.state.surveysSubmitted.includes(guide.id) || this.state.surveysSubmitted.includes(guide.key))) return false;\n ctx.rolloutSalt = guide.id;\n return evaluateRules(c.targeting, ctx);\n }\n\n private isEligible(guide: PublishedGuide, ctx: TargetingContext, url: string): boolean {\n if (!this.isTargeted(guide, ctx, url)) return false;\n if (guide.kind === \"checklist\") return !this.state.checklists[guide.id]?.dismissedAt;\n return isFrequencyEligible(guide.config.frequency, this.state.guides[guide.id], this.session.shownGuides.includes(guide.id));\n }\n\n /** Guide throttling: may this guide launch automatically now? */\n private throttleAllows(guide: PublishedGuide): boolean {\n if (!countsTowardThrottle(guide)) return true;\n return isThrottleEligible(this.config?.settings.throttling, this.state.throttle ?? []);\n }\n\n private recordLaunch(guide: PublishedGuide, manual: boolean): void {\n if (manual || !countsTowardThrottle(guide) || !this.config?.settings.throttling?.enabled) return;\n this.state.throttle = pruneLaunches([...(this.state.throttle ?? []), nowIso()], this.config.settings.throttling);\n }\n\n /** Guides and A/B test control groups, which are evaluated the same way but never render. */\n private candidates(): PublishedGuide[] {\n const guides = this.config?.guides ?? [];\n const holdouts = this.config?.guideHoldouts ?? [];\n return holdouts.length ? [...guides, ...holdouts.map((h) => h.guide)] : guides;\n }\n\n private holdoutFor(guide: PublishedGuide) {\n return this.config?.guideHoldouts?.find((h) => h.guide.id === guide.id) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // Localization\n // ---------------------------------------------------------------------------\n\n /** The visitor's language candidates, most preferred first: `setLocale()` / `locale` option, traits, device. */\n private locales(): string[] {\n return visitorLocales(this.locale, this.user?.traits, [this.bridge.device.locale]);\n }\n\n private defaultLocale(): string {\n return this.config?.settings?.localization?.defaultLocale || \"en\";\n }\n\n /** The guide in the visitor's language (remembered so its events carry `locale`). */\n private localize(guide: PublishedGuide): PublishedGuide {\n const localized = localizeGuide(guide, this.locales(), this.defaultLocale());\n this.guideLocales.set(guide.id, localized.locale);\n return localized;\n }\n\n /**\n * Sets the language for guides and the resource center (`null` = back to the user's traits and\n * the device language). Guides already on screen keep their language; the resource center re-renders.\n */\n setLocale(locale: string | null): void {\n const next = locale ? normalizeLocale(locale) || null : null;\n if (next === this.locale) return;\n this.locale = next;\n this.notify();\n }\n\n private triggerFires(guide: PublishedGuide, reason: EvalReason, detail: EvalDetail): boolean {\n const t = guide.config.trigger;\n switch (t.type) {\n case \"page_load\":\n // A delayed page_load re-evaluates from its own timer.\n if (t.delayMs > 0) return reason === \"timer\" && detail.guideId === guide.id;\n return reason === \"ready\" || reason === \"navigation\" || reason === \"identify\";\n case \"url_match\":\n return (reason === \"ready\" || reason === \"navigation\" || reason === \"identify\") && screenMatches(t.value, this.currentUrl());\n case \"event\":\n return reason === \"event\" && !!t.value && detail.eventName === t.value;\n case \"element_click\":\n return reason === \"click\" && !!detail.targetId && guidelyIdFromSelector(t.value) === detail.targetId;\n case \"element_visible\":\n return reason === \"visible\" && detail.guideId === guide.id;\n case \"delay\":\n return reason === \"timer\" && detail.guideId === guide.id;\n case \"after_guide\":\n return reason === \"after_guide\" && !!detail.endedGuide && (detail.endedGuide.id === t.value || detail.endedGuide.key === t.value);\n case \"segment_enter\":\n return reason === \"identify\" && !!t.value && !!detail.newAudiences?.has(t.value);\n case \"manual\":\n default:\n return false;\n }\n }\n\n private evaluate(reason: EvalReason, detail: EvalDetail = {}): void {\n if (!this.config || this.destroyed) return;\n const url = this.currentUrl();\n const ctx = this.getContext();\n if (reason === \"identify\") {\n const current = new Set(this.state.audienceIds);\n detail.newAudiences = new Set(Array.from(current).filter((a) => !this.lastAudiences.has(a)));\n this.lastAudiences = current;\n }\n const candidates: PublishedGuide[] = [];\n for (const guide of this.candidates()) {\n const t = guide.config.trigger;\n if (detail.endedGuide && detail.endedGuide.id === guide.id) continue;\n if (reason === \"ready\" || reason === \"navigation\") {\n if (t.type === \"element_visible\" && t.value) this.armVisibility(guide, ctx, url);\n if ((t.type === \"delay\" || (t.type === \"page_load\" && t.delayMs > 0)) && !this.firedDelays.has(guide.id)) {\n if (!this.isEligible(guide, ctx, url)) continue;\n this.firedDelays.add(guide.id);\n this.setTimer(() => this.evaluate(\"timer\", { guideId: guide.id }), t.delayMs);\n continue;\n }\n }\n if (t.type === \"page_load\" && t.delayMs > 0 && reason !== \"timer\") continue;\n if (t.type === \"page_load\" && t.delayMs > 0 && reason === \"timer\" && detail.guideId !== guide.id) continue;\n if (!this.triggerFires(guide, reason, detail)) continue;\n if (!this.isEligible(guide, ctx, url)) continue;\n if (!this.throttleAllows(guide)) {\n this.log(\"throttled\", guide.key);\n continue;\n }\n candidates.push(guide);\n }\n if (reason === \"after_guide\" || reason === \"navigation\") this.drainQueue(url, ctx);\n if (!candidates.length) return;\n candidates.sort((a, b) => a.config.frequency.priority - b.config.frequency.priority);\n for (const guide of candidates) {\n if (this.isShowing(guide.id)) continue;\n const delay = guide.config.trigger.type !== \"delay\" && guide.config.trigger.type !== \"page_load\" ? guide.config.trigger.delayMs : 0;\n if (delay > 0) this.setTimer(() => this.tryShow(guide, url, false), delay);\n else this.tryShow(guide, url, false);\n }\n }\n\n private armVisibility(guide: PublishedGuide, ctx: TargetingContext, url: string): void {\n const id = guidelyIdFromSelector(guide.config.trigger.value);\n if (!id || this.visibilityWatchers.has(guide.id) || !this.isEligible(guide, ctx, url)) return;\n const ac = new AbortController();\n const stop = () => {\n ac.abort();\n this.visibilityWatchers.delete(guide.id);\n };\n this.visibilityWatchers.set(guide.id, stop);\n this.targets.waitFor([id], { timeoutMs: 0, signal: ac.signal }).then(\n () => {\n if (ac.signal.aborted) return;\n stop();\n this.evaluate(\"visible\", { guideId: guide.id });\n },\n () => stop(),\n );\n }\n\n private setTimer(fn: () => void, ms: number): void {\n const t = setTimeout(() => {\n this.timers.delete(t);\n if (!this.destroyed) fn();\n }, ms);\n this.timers.add(t);\n }\n\n private isShowing(id: string): boolean {\n return this.flows.has(id) || this.checklists.has(id) || this.active?.guide.id === id || this.activeSurvey?.guide.id === id;\n }\n\n private hasExclusive(): PublishedGuide | null {\n return this.active?.guide ?? this.activeSurvey?.guide ?? null;\n }\n\n private tryShow(guide: PublishedGuide, url: string, manual: boolean): boolean {\n if (this.destroyed) return false;\n // Another automatic guide may have launched since this one was picked (delays, queue).\n if (!manual && !this.throttleAllows(guide)) return false;\n if (this.holdoutFor(guide)) {\n // A/B test control group: count the exposure as if the guide had shown, render nothing.\n if (this.hasExclusive() && !manual) return false;\n this.recordImpression(guide, manual);\n return true;\n }\n if (!isExclusiveGuide(guide)) {\n if (this.flows.has(guide.id) || this.checklists.has(guide.id)) return false;\n this.show(guide, manual);\n return true;\n }\n const current = this.hasExclusive();\n if (current) {\n if (current.id === guide.id) return false;\n if (manual) this.stopGuide();\n else {\n if (!this.queued.some((q) => q.guide.id === guide.id)) this.queued.push({ guide, url, pageScoped: PAGE_SCOPED.has(guide.config.trigger.type) });\n this.log(\"queued\", guide.key, \"behind\", current.key);\n return false;\n }\n }\n const blocked = [...this.flows.values()].map((f) => f.guide).some((g) => areMutuallyExclusive(g, guide));\n if (blocked && !manual) {\n if (!this.queued.some((q) => q.guide.id === guide.id)) this.queued.push({ guide, url, pageScoped: true });\n return false;\n }\n this.show(guide, manual);\n return true;\n }\n\n private drainQueue(url: string, ctx: TargetingContext): void {\n if (this.hasExclusive()) return;\n this.queued = this.queued.filter((q) => !(q.pageScoped && q.url !== url));\n while (this.queued.length) {\n const next = this.queued.shift() as QueuedGuide;\n if (!this.isEligible(next.guide, ctx, url)) continue;\n if (this.tryShow(next.guide, url, false)) return;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Showing guides\n // ---------------------------------------------------------------------------\n\n private findGuide(idOrKey: string): PublishedGuide | undefined {\n return this.config?.guides.find((g) => g.id === idOrKey || g.key === idOrKey);\n }\n\n private guideState(id: string): GuideLocalState {\n return this.state.guides[id] ?? (this.state.guides[id] = { impressions: 0 });\n }\n\n private recordImpression(guide: PublishedGuide, manual = false): void {\n const s = this.guideState(guide.id);\n s.impressions += 1;\n s.lastShownAt = nowIso();\n if (!this.session.shownGuides.includes(guide.id)) this.session.shownGuides.push(guide.id);\n this.recordLaunch(guide, manual);\n this.persistState();\n this.persistSession();\n const holdout = this.holdoutFor(guide);\n const experiment = holdout ? { id: holdout.experimentId, variantId: holdout.variantId } : guide.experiment;\n if (experiment) this.enqueue(\"experiment_viewed\", { properties: { guideExperimentId: experiment.id, variantId: experiment.variantId, ...(holdout ? {} : { guideId: guide.id }) } });\n // Control groups are local only: the server knows no guide by that id.\n if (!holdout) this.syncGuideState(guide.id, { impression: true });\n }\n\n private recordEnd(guide: PublishedGuide, reason: \"completed\" | \"dismissed\" | \"skipped\"): void {\n const s = this.guideState(guide.id);\n if (reason === \"completed\") s.completedAt = nowIso();\n else s.dismissedAt = nowIso();\n this.persistState();\n this.syncGuideState(guide.id, reason === \"completed\" ? { completed: true } : { dismissed: true });\n if (reason === \"completed\") this.completeChecklistTasksBy(\"guide_completed\", guide);\n }\n\n private syncGuideState(guideId: string, update: { impression?: boolean; completed?: boolean; dismissed?: boolean }): void {\n const body = { anonymousId: this.anonymousId, userId: this.user?.id || null, updates: [{ guideId, ...update }] };\n // Impressions are counters (a resend would count twice) and matter less; completions and\n // dismissals are kept until the server has them, so a guide doesn't come back on another device.\n if (update.impression) void postWithRetry(this.api, \"/guide-state\", body);\n else this.sendDurably(`guide:${guideId}:${update.completed ? \"completed\" : \"dismissed\"}:${this.anonymousId}`, \"/guide-state\", body);\n }\n\n /** Queues a write in the persisted outbox (sent now, or once the API is reachable again). */\n private sendDurably(key: string, path: string, body: unknown): void {\n this.whenHydrated(() => this.outbox?.add(key, path, body));\n }\n\n private show(guide: PublishedGuide, manual: boolean, stepId?: string): void {\n try {\n if (guide.kind === \"checklist\" && guide.config.checklist) return this.showChecklist(guide);\n if (guide.kind === \"survey\" && guide.config.survey) return this.showSurvey(guide, manual);\n this.showFlow(guide, manual, stepId);\n } catch (err) {\n this.reportError(err);\n }\n }\n\n private showFlow(raw: PublishedGuide, manual: boolean, stepId?: string): void {\n const guide = this.localize(raw);\n const exclusive = isExclusiveGuide(guide);\n const flow: RunningFlow = { guide, manual, view: null, controller: null as unknown as GuideController };\n let renders = 0;\n flow.controller = runGuide(guide, {\n targets: this.targets,\n ctx: () => this.getContext(),\n currentUrl: () => this.currentUrl(),\n startAtStep: stepId,\n eventBus: this.eventBus,\n onError: (err) => this.reportError(err),\n onEvent: (e) => {\n const step = e.stepId ? guide.config.steps.find((s) => s.id === e.stepId) : undefined;\n this.enqueue(e.name, { guideId: guide.id, guideVersion: guide.version, stepId: e.stepId, stepIndex: e.stepIndex, properties: e.properties });\n if (e.name === \"guide_started\") {\n this.recordImpression(guide, manual);\n this.emitter.emit(\"guide:start\", guide);\n } else if (e.name === \"step_viewed\" && step) {\n this.emitter.emit(\"guide:step\", { guide, stepId: step.id, stepIndex: e.stepIndex ?? 0 });\n } else if (e.name === \"guide_completed\") {\n this.recordEnd(guide, \"completed\");\n this.emitter.emit(\"guide:complete\", guide);\n } else if (e.name === \"guide_dismissed\") {\n this.recordEnd(guide, \"dismissed\");\n this.emitter.emit(\"guide:dismiss\", guide);\n } else if (e.name === \"guide_skipped\") {\n this.recordEnd(guide, \"skipped\");\n this.emitter.emit(\"guide:skip\", guide);\n }\n },\n onRender: (r) => {\n renders += 1;\n this.expanded.delete(guide.id);\n flow.view = { key: `${guide.id}:${r.step.id}:${renders}`, guide, step: r.step, index: r.index, total: r.total, canGoBack: r.canGoBack, targetId: r.targetId, asModal: r.asModal, expanded: false };\n this.notify();\n },\n onClear: () => {\n flow.view = null;\n this.notify();\n },\n onNavigate: (url) => this.navigate(url),\n onAction: (action, value) => {\n if (action === \"start_guide\" && value) this.setTimer(() => this.startGuide(value), 0);\n else if (action === \"event\" && value) this.track(value);\n else if (action === \"open_resource_center\") this.openResourceCenter();\n },\n onEnd: (reason) => {\n if (exclusive) {\n if (this.active === flow) this.active = null;\n } else if (this.flows.get(guide.id) === flow) this.flows.delete(guide.id);\n this.notify();\n if (reason !== \"destroyed\" && !this.destroyed) this.setTimer(() => this.evaluate(\"after_guide\", { endedGuide: guide }), 0);\n },\n });\n if (exclusive) this.active = flow;\n else this.flows.set(guide.id, flow);\n flow.controller.start();\n if (flow.controller.getState().status === \"ended\") {\n if (this.active === flow) this.active = null;\n if (this.flows.get(guide.id) === flow) this.flows.delete(guide.id);\n }\n }\n\n private showChecklist(raw: PublishedGuide, open?: boolean): void {\n if (!raw.config.checklist || this.checklists.has(raw.id)) return;\n const guide = this.localize(raw);\n const config = guide.config.checklist;\n if (!config) return;\n const progress = this.getChecklistProgress(guide.id);\n const first = !this.state.guides[guide.id]?.impressions;\n this.checklists.set(guide.id, { guide, open: open ?? (config.autoOpen && first && !progress.completedAt) });\n if (first) this.recordImpression(guide);\n if (this.checklists.get(guide.id)?.open) this.enqueue(\"guide_viewed\", { guideId: guide.id, guideVersion: guide.version });\n this.notify();\n }\n\n private showSurvey(raw: PublishedGuide, manual: boolean): void {\n if (!raw.config.survey) return;\n const guide = this.localize(raw);\n this.activeSurvey = { guide, manual };\n this.surveyView = { key: `${guide.id}:${randomId(6)}`, guide, submitted: false };\n this.recordImpression(guide, manual);\n this.enqueue(\"survey_displayed\", { guideId: guide.id, guideVersion: guide.version });\n this.emitter.emit(\"guide:start\", guide);\n this.notify();\n }\n\n private finishSurvey(reason: \"submitted\" | \"dismissed\"): void {\n const s = this.activeSurvey;\n if (!s) return;\n this.activeSurvey = null;\n this.surveyView = null;\n if (reason === \"dismissed\") {\n this.enqueue(\"survey_dismissed\", { guideId: s.guide.id, guideVersion: s.guide.version });\n this.recordEnd(s.guide, \"dismissed\");\n this.emitter.emit(\"guide:dismiss\", s.guide);\n }\n this.notify();\n this.setTimer(() => this.evaluate(\"after_guide\", { endedGuide: s.guide }), 0);\n }\n\n /** Theme for a guide: project theme ← app overrides ← guide appearance. */\n themeFor(guide?: PublishedGuide): Partial<ProjectTheme> & { dark?: \"light\" | \"dark\" | \"auto\"; overlayOpacity?: number } {\n const a = guide?.config.appearance;\n return {\n ...(this.config?.theme || {}),\n ...(this.options.theme || {}),\n ...(a?.primaryColor ? { primaryColor: a.primaryColor } : {}),\n ...(a?.backgroundColor ? { backgroundColor: a.backgroundColor } : {}),\n ...(a?.textColor ? { textColor: a.textColor } : {}),\n ...(a?.borderRadius != null ? { borderRadius: a.borderRadius } : {}),\n dark: a?.theme ?? \"auto\",\n overlayOpacity: a?.overlayOpacity,\n };\n }\n\n /**\n * Opens a URL from a button, link or task: the app's `onNavigate` handler first (deep links and\n * in-app routes), then http(s) and custom-scheme URLs through the OS.\n */\n navigate(url: string): void {\n if (!url) return;\n try {\n if (this.options.onNavigate?.(url) === true) return;\n if (/^[a-z][a-z0-9+.-]*:/i.test(url)) this.bridge.openExternal(url);\n else if (!this.options.onNavigate) this.log(`no onNavigate handler for in-app URL \"${url}\"`);\n } catch (err) {\n this.reportError(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // UI state (consumed by the overlay)\n // ---------------------------------------------------------------------------\n\n getUiState(): UiState {\n return this.ui;\n }\n\n subscribeUi(cb: () => void): () => void {\n this.uiListeners.add(cb);\n return () => this.uiListeners.delete(cb);\n }\n\n private notify(): void {\n const steps: StepView[] = [];\n for (const f of [...this.flows.values(), ...(this.active ? [this.active] : [])]) if (f.view) steps.push({ ...f.view, expanded: this.expanded.has(f.guide.id) });\n const checklists: ChecklistView[] = [];\n this.checklists.forEach((w, id) => checklists.push({ guide: w.guide, progress: this.getChecklistProgress(id), open: w.open }));\n this.ui = { steps, checklists, survey: this.surveyView, resourceCenterOpen: this.resourceCenterOpen, theme: this.themeFor(), messenger: !!this.messenger };\n for (const cb of Array.from(this.uiListeners)) {\n try {\n cb();\n } catch (err) {\n this.reportError(err);\n }\n }\n }\n\n private flowFor(guideId: string): RunningFlow | undefined {\n return this.active?.guide.id === guideId ? this.active : this.flows.get(guideId);\n }\n\n /** A step button was pressed in the overlay. */\n pressButton(guideId: string, button: StepButton): void {\n this.flowFor(guideId)?.controller.press(button);\n }\n\n /** The close (×) button of a step. */\n closeStep(guideId: string): void {\n this.flowFor(guideId)?.controller.dismiss();\n }\n\n /** The dimmed backdrop behind a step was tapped. */\n backdropPressed(guideId: string): void {\n const f = this.flowFor(guideId);\n if (f?.view?.step.dismissOnOutsideClick) f.controller.dismiss();\n }\n\n /** Hotspot dot tapped: show (or hide) its card. */\n toggleHotspot(guideId: string): void {\n if (this.expanded.has(guideId)) this.expanded.delete(guideId);\n else this.expanded.add(guideId);\n this.notify();\n }\n\n setChecklistOpen(guideId: string, open: boolean): void {\n const w = this.checklists.get(guideId);\n const guide = this.findGuide(guideId);\n if (!w || !guide || w.open === open) return;\n w.open = open;\n if (open) this.enqueue(\"guide_viewed\", { guideId: guide.id, guideVersion: guide.version });\n this.notify();\n }\n\n checklistTaskPressed(guideId: string, taskId: string): void {\n const guide = this.findGuide(guideId);\n const task = guide?.config.checklist?.tasks.find((t) => t.id === taskId);\n if (!guide || !task) return;\n if (task.completion === \"manual\") this.markTaskDone(guide, task);\n if (task.action === \"start_guide\" && task.actionValue) {\n this.setChecklistOpen(guide.id, false);\n this.startGuide(task.actionValue);\n } else if (task.action === \"url\" && task.actionValue) this.navigate(task.actionValue);\n else if (task.action === \"event\" && task.actionValue) this.track(task.actionValue);\n }\n\n dismissChecklist(guideId: string): void {\n const guide = this.findGuide(guideId);\n if (!guide) return;\n const progress = this.state.checklists[guide.id] ?? (this.state.checklists[guide.id] = { completedTaskIds: [] });\n progress.dismissedAt = nowIso();\n this.persistState();\n this.enqueue(\"checklist_dismissed\", { guideId: guide.id, guideVersion: guide.version });\n this.sendDurably(`checklist:${guide.id}:dismissed:${this.anonymousId}`, `/checklists/${encodeURIComponent(guide.id)}/progress`, { anonymousId: this.anonymousId, userId: this.user?.id || null, guideVersion: guide.version, completedTaskIds: progress.completedTaskIds, dismissed: true });\n this.checklists.delete(guide.id);\n this.notify();\n }\n\n submitSurvey(guideId: string, answers: Record<string, unknown>): void {\n const s = this.activeSurvey;\n if (!s || s.guide.id !== guideId || !this.surveyView || this.surveyView.submitted) return;\n const guide = s.guide;\n const responseId = randomId(24);\n this.state.surveysSubmitted.push(guide.id);\n this.persistState();\n this.recordEnd(guide, \"completed\");\n this.enqueue(\"survey_submitted\", { guideId: guide.id, guideVersion: guide.version, properties: { responseId } });\n this.sendDurably(`survey:${responseId}`, `/surveys/${encodeURIComponent(guide.id)}/responses`, { anonymousId: this.anonymousId, userId: this.user?.id || null, accountId: this.user?.account?.id || null, guideVersion: guide.version, answers, responseId });\n this.emitter.emit(\"survey:submit\", { guide, answers, responseId });\n this.emitter.emit(\"guide:complete\", guide);\n this.surveyView = { ...this.surveyView, submitted: true };\n this.notify();\n }\n\n closeSurvey(guideId: string): void {\n if (this.activeSurvey?.guide.id !== guideId) return;\n this.finishSurvey(this.surveyView?.submitted ? \"submitted\" : \"dismissed\");\n }\n\n /** The visitor's audiences (from the last identify), for audience-targeted help articles. */\n getAudienceIds(): readonly string[] {\n return this.state.audienceIds;\n }\n\n /** The published resource center in the visitor's language, or null when it is off. */\n getResourceCenter(): ResourceCenterConfig | null {\n const rc = this.localizedResourceCenter();\n return rc && rc.enabled ? rc : null;\n }\n\n /** The resource center in the visitor's language (cached until the config or language changes). */\n private localizedResourceCenter(): (ResourceCenterConfig & { locale: string }) | null {\n const rc = this.config?.resourceCenter;\n if (!rc) return null;\n const locales = this.locales();\n const key = `${locales.join(\",\")}|${this.defaultLocale()}`;\n if (this.localizedRc?.source !== rc || this.localizedRc.locales !== key) this.localizedRc = { source: rc, locales: key, value: localizeResourceCenter(rc, locales, this.defaultLocale()) };\n return this.localizedRc.value;\n }\n\n /** Evaluates targeting rules (e.g. a resource-center section's) for the current visitor and screen. */\n matchesTargeting(rules: RuleGroup | null | undefined): boolean {\n if (!rules) return true;\n try {\n return evaluateRules(rules, this.getContext());\n } catch (err) {\n this.reportError(err);\n return false;\n }\n }\n\n /** Resource-center sections this visitor sees, in order (disabled and non-matching ones left out). */\n getResourceCenterModules(): ResourceCenterModuleId[] {\n const rc = this.getResourceCenter();\n if (!rc) return [];\n return orderedModules(rc.modules)\n .filter((m) => m.enabled && (!(\"targeting\" in m) || this.matchesTargeting(m.targeting)))\n .map((m) => m.id as ResourceCenterModuleId);\n }\n\n /**\n * Sections of the messenger's Help tab, in order: the resource center's modules without \"What's\n * new\" (the messenger has its own News tab); every section when no resource center is published.\n */\n getHelpModules(): ResourceCenterModuleId[] {\n const modules = this.getResourceCenter() ? this.getResourceCenterModules() : [...RC_MODULE_IDS];\n return modules.filter((id) => id !== \"announcements\");\n }\n\n /** \"What's new\" entries this visitor sees (newest first); empty when the section is off. */\n getAnnouncements(): ResourceCenterAnnouncement[] {\n const rc = this.getResourceCenter();\n if (!rc || !this.getResourceCenterModules().includes(\"announcements\")) return [];\n return visibleAnnouncements(rc.announcements, this.state.audienceIds);\n }\n\n /** \"What's new\" entries published since the visitor last opened the resource center. */\n getUnreadAnnouncements(): number {\n return unreadAnnouncements(this.getAnnouncements(), this.state.announcementsSeenAt);\n }\n\n /** Whether an entry is new to the visitor in the resource center that is open now. */\n isAnnouncementNew(a: ResourceCenterAnnouncement): boolean {\n return unreadAnnouncements([a], this.announcementsSeenAtOpen) > 0;\n }\n\n async searchResourceCenter(q: string): Promise<ResourceCenterArticle[]> {\n try {\n const res = await this.api.get<{ articles: ResourceCenterArticle[] }>(\"/resource-center/search\", { params: { q } });\n return res.ok && res.data ? res.data.articles : [];\n } catch {\n return [];\n }\n }\n\n /** The language of the resource center as shown, when it isn't the default (sent with article fetches). */\n private articleLocale(): string | undefined {\n const locale = this.localizedResourceCenter()?.locale;\n return locale && locale.toLowerCase() !== this.defaultLocale().toLowerCase() ? locale : undefined;\n }\n\n articleViewed(article: ResourceCenterArticle): void {\n this.enqueue(\"article_viewed\", { properties: { articleId: article.id, slug: article.slug } });\n }\n\n // ---------------------------------------------------------------------------\n // Checklists\n // ---------------------------------------------------------------------------\n\n getChecklistProgress(idOrKey: string): ChecklistProgressState {\n const id = this.findGuide(idOrKey)?.id ?? idOrKey;\n const p = this.state.checklists[id];\n return p ? { completedTaskIds: [...p.completedTaskIds], completedAt: p.completedAt ?? null, dismissedAt: p.dismissedAt ?? null } : { completedTaskIds: [], completedAt: null, dismissedAt: null };\n }\n\n completeChecklistTask(idOrKey: string, taskId: string): void {\n this.whenHydrated(() => {\n const guide = this.findGuide(idOrKey);\n const task = guide?.config.checklist?.tasks.find((t) => t.id === taskId);\n if (guide && task) this.markTaskDone(guide, task);\n });\n }\n\n private markTaskDone(guide: PublishedGuide, task: ChecklistTask): void {\n const config = guide.config.checklist;\n if (!config) return;\n const progress = this.state.checklists[guide.id] ?? (this.state.checklists[guide.id] = { completedTaskIds: [] });\n if (progress.completedTaskIds.includes(task.id)) return;\n progress.completedTaskIds.push(task.id);\n this.enqueue(\"checklist_task_completed\", { guideId: guide.id, guideVersion: guide.version, properties: { taskId: task.id } });\n const complete = isChecklistComplete(config, progress) && !progress.completedAt;\n if (complete) {\n progress.completedAt = nowIso();\n this.enqueue(\"checklist_completed\", { guideId: guide.id, guideVersion: guide.version });\n }\n this.persistState();\n this.sendDurably(`checklist:${guide.id}:progress:${this.anonymousId}`, `/checklists/${encodeURIComponent(guide.id)}/progress`, { anonymousId: this.anonymousId, userId: this.user?.id || null, guideVersion: guide.version, completedTaskIds: progress.completedTaskIds, completed: !!progress.completedAt });\n this.emitter.emit(\"checklist:task\", { guide, task, progress: this.getChecklistProgress(guide.id) });\n if (complete) {\n this.emitter.emit(\"checklist:complete\", guide);\n const w = this.checklists.get(guide.id);\n if (w) w.open = true;\n }\n this.notify();\n }\n\n private completeChecklistTasksBy(kind: ChecklistTask[\"completion\"], value: string | PublishedGuide): void {\n if (!this.config) return;\n for (const guide of this.config.guides) {\n for (const task of guide.config.checklist?.tasks ?? []) {\n if (task.completion !== kind || !task.completionValue) continue;\n let hit = false;\n if (kind === \"event\") hit = value === task.completionValue;\n else if (kind === \"url_visited\") hit = screenMatches(screenPath(task.completionValue), value as string) || screenMatches(task.completionValue, value as string);\n else if (kind === \"guide_completed\") hit = (value as PublishedGuide).id === task.completionValue || (value as PublishedGuide).key === task.completionValue;\n else if (kind === \"click\") hit = guidelyIdFromSelector(task.completionValue) === value;\n if (hit) this.markTaskDone(guide, task);\n }\n }\n }\n\n openChecklist(idOrKey: string): void {\n this.whenHydrated(() => {\n const guide = this.findGuide(idOrKey);\n if (!guide?.config.checklist) return;\n if (!this.checklists.has(guide.id)) {\n const p = this.state.checklists[guide.id];\n if (p?.dismissedAt) {\n delete p.dismissedAt;\n this.persistState();\n }\n this.showChecklist(guide, true);\n }\n this.setChecklistOpen(guide.id, true);\n });\n }\n\n closeChecklist(idOrKey: string): void {\n const guide = this.findGuide(idOrKey);\n if (guide) this.setChecklistOpen(guide.id, false);\n }\n\n // ---------------------------------------------------------------------------\n // Public guide controls\n // ---------------------------------------------------------------------------\n\n /** Starts a guide by id or key, bypassing targeting and frequency rules. */\n startGuide(idOrKey: string, options: { stepId?: string } = {}): boolean {\n const guide = this.findGuide(idOrKey);\n if (!guide) {\n this.reportError(new Error(`[Guidely] startGuide: unknown guide \"${idOrKey}\"`));\n return false;\n }\n if (guide.kind === \"checklist\") {\n this.openChecklist(guide.id);\n return true;\n }\n if (this.hasExclusive()) this.stopGuide();\n this.flows.get(guide.id)?.controller.destroy();\n this.flows.delete(guide.id);\n this.show(guide, true, options.stepId);\n return true;\n }\n\n /** Stops the active guide silently (no dismiss event). */\n stopGuide(): void {\n const a = this.active;\n if (a) {\n this.active = null;\n a.controller.destroy();\n }\n if (this.activeSurvey) {\n this.activeSurvey = null;\n this.surveyView = null;\n }\n this.notify();\n }\n\n /** Dismisses the active guide (records a dismissal). */\n dismissGuide(): void {\n if (this.active) this.active.controller.dismiss();\n else if (this.activeSurvey) this.finishSurvey(\"dismissed\");\n }\n\n getActiveGuide(): PublishedGuide | null {\n return this.hasExclusive();\n }\n\n getGuides(): ReadonlyArray<PublishedGuide> {\n return this.config?.guides ?? [];\n }\n\n isGuideCompleted(idOrKey: string): boolean {\n const guide = this.findGuide(idOrKey);\n return !!this.state.guides[guide?.id ?? idOrKey]?.completedAt;\n }\n\n /** Impressions, completion and dismissal for a guide. */\n getGuideState(idOrKey: string): GuideLocalState {\n const guide = this.findGuide(idOrKey);\n return { impressions: 0, ...(this.state.guides[guide?.id ?? idOrKey] ?? {}) };\n }\n\n openResourceCenter(): void {\n // With Scout on, help lives in the messenger's Help tab (one launcher, as on the web).\n if (this.messenger) return this.openMessenger(\"help\");\n if (!this.getResourceCenter()) {\n this.log(\"openResourceCenter: the resource center is not enabled or published for this environment\");\n return;\n }\n if (this.resourceCenterOpen) return;\n this.resourceCenterOpen = true;\n // Entries stay marked \"New\" while it is open; the launcher badge clears now.\n this.announcementsSeenAtOpen = this.state.announcementsSeenAt ?? null;\n if (this.getAnnouncements().length) {\n this.state.announcementsSeenAt = nowIso();\n this.persistState();\n }\n this.enqueue(\"resource_center_opened\");\n this.emitter.emit(\"resource-center:open\");\n this.notify();\n }\n\n closeResourceCenter(): void {\n if (this.messenger) return this.closeMessenger();\n if (!this.resourceCenterOpen) return;\n this.resourceCenterOpen = false;\n this.notify();\n }\n\n // ---------------------------------------------------------------------------\n // Scout messenger\n // ---------------------------------------------------------------------------\n\n /** Creates or removes the messenger to match the config (on only when enabled for this platform). */\n private syncMessenger(): void {\n const cfg = this.config?.messenger;\n if (cfg?.enabled) {\n if (this.messenger) this.messenger.updateConfig(cfg);\n else {\n this.messenger = new Messenger(cfg, {\n baseUrl: this.options.apiUrl,\n publicKey: this.options.projectId,\n store: this.store,\n fetch: this.options.fetch ?? fetch,\n streamPost: (this.options.fetch ? null : xhrStreamPost()) ?? fetchStreamPost(this.options.fetch ?? fetch),\n anonymousId: () => this.anonymousId,\n userId: () => this.user?.id || null,\n pageUrl: () => (this.collectUrls() && this.screenName ? this.currentUrl() : undefined),\n onOpen: () => {\n this.enqueue(\"messenger_opened\");\n this.emitter.emit(\"messenger:open\");\n },\n onMessage: (message, conversation) => this.emitter.emit(\"conversation:message\", { message, conversation }),\n onStartGuide: (key) => this.setTimer(() => this.startGuide(key), 0),\n onError: (err) => this.log(\"messenger\", err instanceof Error ? err.message : err),\n health: this.api.health,\n locale: () => this.articleLocale(),\n });\n this.resourceCenterOpen = false;\n }\n } else if (this.messenger) {\n this.messenger.destroy();\n this.messenger = null;\n }\n this.notify();\n }\n\n /** The Scout messenger store when Scout is on for this platform (rendered by the overlay). */\n getMessenger(): Messenger | null {\n return this.messenger;\n }\n\n /** Where the visitor dragged the messenger bubble on this device, or null to use the configured spot. */\n getMessengerLauncherPlacement(): LauncherPlacement | null {\n return parsePlacement(this.store.get(LAUNCHER_PLACEMENT_KEY));\n }\n\n /** Remembers the bubble's spot on this device (in memory only when no `storage` was passed). */\n setMessengerLauncherPlacement(placement: LauncherPlacement): void {\n this.store.set(LAUNCHER_PLACEMENT_KEY, serializePlacement(placement));\n }\n\n /** Opens the Scout messenger, optionally on a tab. No-op when Scout is off for this platform. */\n openMessenger(tab?: MessengerTab): void {\n this.whenHydrated(() => this.messenger?.open(tab));\n }\n\n closeMessenger(): void {\n this.messenger?.close();\n }\n\n /** Opens a new messenger conversation, optionally pre-filling the message. */\n showNewMessage(text?: string): void {\n this.whenHydrated(() => this.messenger?.showNewMessage(text));\n }\n\n // ---------------------------------------------------------------------------\n // Feature flags\n // ---------------------------------------------------------------------------\n\n /** Boolean flag value for the current user; `fallback` (default `false`) until loaded or when missing. */\n isFeatureEnabled(key: string, fallback = false): boolean {\n return this.flags.isEnabled(key, fallback);\n }\n\n /** Flag value for the current user; `fallback` when missing or of a different type. */\n getFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return this.flags.getValue(key, fallback);\n }\n\n /** Flag value plus why it was served (reason, rule, variation, experiment). */\n getFeatureDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return this.flags.getDetails(key, fallback);\n }\n\n /** Calls `cb` whenever flag values may have changed. Returns an unsubscribe function. */\n onFlagsChange(cb: () => void): () => void {\n return this.flags.subscribe(cb);\n }\n\n /** Device facts on every screen view, read by the Pages devices / browsers breakdowns. */\n private deviceProperties(): Record<string, string> {\n const d = this.bridge.device;\n return { platform: d.platform, deviceType: d.deviceType, os: d.platform, ...(d.osVersion ? { osVersion: d.osVersion } : {}) };\n }\n\n /** Attributes flags are evaluated with: identity, traits, account, audiences, screen and device. */\n private flagContext(): Attributes {\n const d = this.bridge.device;\n const account = this.user?.account;\n return {\n platform: d.platform,\n deviceType: d.deviceType,\n locale: d.locale,\n appVersion: this.options.appVersion ?? d.appVersion,\n osVersion: d.osVersion,\n environment: this.options.environment,\n ...(this.screenName ? { screen: this.screenName, path: this.currentUrl() } : {}),\n ...(this.user?.traits ?? {}),\n id: this.user?.id || this.anonymousId || undefined,\n anonymousId: this.anonymousId || undefined,\n account: account ? { ...(account.traits ?? {}), id: account.id } : undefined,\n $audiences: [...this.state.audienceIds],\n };\n }\n\n private syncFlagAttributes(): void {\n if (!this.destroyed) this.flags?.setContextAttributes(this.flagContext());\n }\n\n /** `experiment_viewed`, once per session and assignment, through the event queue (consent applies). */\n private trackExposure(result: EvaluationResult): void {\n const exp = result.inExperiment ? result.experiment : undefined;\n if (!exp || this.destroyed) return;\n this.whenHydrated(() => {\n const key = `${this.session.id}|${exp.key}|${exp.hashValue}|${exp.variationId}`;\n if (this.exposures.has(key)) return;\n if (this.exposures.size > 500) this.exposures.clear();\n this.exposures.add(key);\n this.enqueue(\"experiment_viewed\", { properties: { experimentKey: exp.key, variationId: exp.variationId, flagKey: result.key, hashAttribute: exp.hashAttribute, ...(exp.variationName ? { variationName: exp.variationName } : {}) } });\n });\n }\n\n on<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): () => void {\n return this.emitter.on(event, cb);\n }\n\n off<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): void {\n this.emitter.off(event, cb);\n }\n\n isClientReady(): boolean {\n return this.isReady;\n }\n\n /** Snapshot for debugging. */\n getState() {\n return {\n ready: this.isReady,\n destroyed: this.destroyed,\n anonymousId: this.anonymousId,\n user: this.user,\n consent: this.consent,\n screen: this.screenName,\n configVersion: this.config?.configVersion ?? null,\n guides: this.getGuides().map((g) => ({ id: g.id, key: g.key, kind: g.kind })),\n activeGuide: this.active ? { id: this.active.guide.id, key: this.active.guide.key, ...this.active.controller.getState() } : this.activeSurvey ? { id: this.activeSurvey.guide.id, key: this.activeSurvey.guide.key } : null,\n queued: this.queued.map((q) => q.guide.key),\n widgets: [...this.flows.keys(), ...this.checklists.keys()],\n guideState: this.state.guides,\n checklists: this.state.checklists,\n audienceIds: this.state.audienceIds,\n session: this.session,\n pendingEvents: this.queue?.size ?? 0,\n pendingWrites: this.outbox?.size ?? 0,\n targets: this.targets.ids(),\n flagsReady: this.flags.isReady(),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Internals\n // ---------------------------------------------------------------------------\n\n private persistState(): void {\n writeJson(this.store, KEYS.state(this.options.projectId), this.state);\n }\n\n private persistSession(): void {\n this.session.lastActiveAt = nowIso();\n writeJson(this.store, KEYS.session, this.session);\n }\n\n private reportError(err: unknown): void {\n const error = err instanceof Error ? err : new Error(String(err));\n this.log(\"error\", error.message);\n try {\n this.options.onError?.(error);\n } catch {\n /* ignore */\n }\n this.emitter.emit(\"error\", error);\n }\n\n private log(...args: unknown[]): void {\n if (this.options.debug && typeof console !== \"undefined\") console.log(\"[Guidely]\", ...args);\n }\n}\n\n/**\n * Keeps only the guides (and A/B control groups) enabled for this platform (the server already\n * filters; older caches may not be), and drops code blocks: they never run on React Native.\n */\nfunction forPlatform(config: SdkConfigResponse, platform: string): SdkConfigResponse {\n const keep = (g: PublishedGuide) => supportsPlatform(g.config, platform);\n const holdouts = config.guideHoldouts?.filter((h) => keep(h.guide)).map((h) => ({ ...h, guide: withoutCode(h.guide) }));\n return { ...config, guides: config.guides.filter(keep).map(withoutCode), ...(holdouts ? { guideHoldouts: holdouts } : {}) };\n}\n\n/** The guide without code-block steps' JavaScript (`step.code`), which mobile SDKs never execute. */\nfunction withoutCode(guide: PublishedGuide): PublishedGuide {\n if (!guide.config.steps.some((s) => s.code)) return guide;\n return { ...guide, config: { ...guide.config, steps: guide.config.steps.map(({ code: _code, ...step }) => step) } };\n}\n","import type { Insets } from \"./position\";\n\n/**\n * Where the visitor dragged the Scout bubble on this device: the side edge it snapped to and how\n * high it sits, as a fraction of the allowed range (0 = the default bottom position, 1 = highest).\n */\nexport interface LauncherPlacement {\n side: \"left\" | \"right\";\n fraction: number;\n}\n\n/** The window the bubble moves in. `defaultBottom` is today's gap between its bottom edge and the window bottom. */\nexport interface LauncherFrame {\n width: number;\n height: number;\n insets: Insets;\n size: number;\n defaultBottom: number;\n}\n\n/** Top-left corner of the bubble in window coordinates. */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Storage key (device-wide, like `guidely:anon`; the same on iOS, Android and Flutter). */\nexport const LAUNCHER_PLACEMENT_KEY = \"guidely:messenger.launcher\";\n/** Gap kept between the bubble and the safe-area edges. */\nexport const LAUNCHER_MARGIN = 16;\n/** Finger travel before a touch on the bubble becomes a drag instead of a tap. */\nexport const LAUNCHER_DRAG_THRESHOLD = 8;\n\nconst clamp = (v: number, min: number, max: number) => Math.min(max, Math.max(min, v));\n\n/** Left edge of the bubble when it rests on `side`. */\nexport function sideX(f: LauncherFrame, side: LauncherPlacement[\"side\"]): number {\n return side === \"left\" ? f.insets.left + LAUNCHER_MARGIN : f.width - f.insets.right - LAUNCHER_MARGIN - f.size;\n}\n\n/** Resting range of the bubble's top edge: `max` is the default bottom position (never lower), `min` the highest. */\nexport function verticalRange(f: LauncherFrame): { min: number; max: number } {\n const max = f.height - f.defaultBottom - f.size;\n return { min: Math.min(max, f.insets.top + LAUNCHER_MARGIN), max };\n}\n\n/** Keeps a dragged bubble inside the safe area. */\nexport function clampToSafeArea(f: LauncherFrame, p: Point): Point {\n const left = f.insets.left + LAUNCHER_MARGIN;\n const top = f.insets.top + LAUNCHER_MARGIN;\n return {\n x: clamp(p.x, left, Math.max(left, f.width - f.insets.right - LAUNCHER_MARGIN - f.size)),\n y: clamp(p.y, top, Math.max(top, f.height - f.insets.bottom - LAUNCHER_MARGIN - f.size)),\n };\n}\n\n/** Where a bubble dropped at `p` comes to rest: the nearer side edge, at the drop height clamped to the resting range. */\nexport function snapPlacement(f: LauncherFrame, p: Point): LauncherPlacement {\n const { min, max } = verticalRange(f);\n const side = p.x + f.size / 2 < f.width / 2 ? \"left\" : \"right\";\n return { side, fraction: max > min ? (max - clamp(p.y, min, max)) / (max - min) : 0 };\n}\n\n/** Top-left corner for a placement in this frame (re-clamped, so it survives rotation and size changes). */\nexport function placementPoint(f: LauncherFrame, placement: LauncherPlacement): Point {\n const { min, max } = verticalRange(f);\n return { x: sideX(f, placement.side), y: max - clamp(placement.fraction, 0, 1) * (max - min) };\n}\n\n/** Reads a stored placement; anything malformed reads as none, so the bubble sits where it always did. */\nexport function parsePlacement(raw: string | null | undefined): LauncherPlacement | null {\n if (!raw) return null;\n try {\n const v = JSON.parse(raw) as Partial<LauncherPlacement> | null;\n if (!v || typeof v !== \"object\" || (v.side !== \"left\" && v.side !== \"right\") || typeof v.fraction !== \"number\" || !Number.isFinite(v.fraction)) return null;\n return { side: v.side, fraction: clamp(v.fraction, 0, 1) };\n } catch {\n return null;\n }\n}\n\nexport function serializePlacement(p: LauncherPlacement): string {\n return JSON.stringify({ side: p.side, fraction: Math.round(clamp(p.fraction, 0, 1) * 1e4) / 1e4 });\n}\n","import type { AutocaptureSettings, HeatmapPoint } from \"@guidelytech/shared\";\nimport type { Rect } from \"./targets\";\n\n/** `autocapture` option: `false` turns every capability off, an object turns single ones off. */\nexport type AutocaptureOption = boolean | Partial<AutocaptureSettings>;\n\n/** A tap moves at most this far (points) and lasts less than {@link TAP_MAX_MS} (the replay definition). */\nexport const TAP_SLOP = 10;\nexport const TAP_MAX_MS = 1000;\n\n/** Points per `heatmap` event. */\nexport const HEATMAP_MAX_POINTS = 40;\n\n/** The element a tap resolved to (or the view it hit), as `click` properties need it. */\nexport interface TapElement {\n selector: string;\n /** Component / host name (`Pressable`, `TouchableOpacity`, `Text`, `View`). */\n tag: string;\n /** Visible label; already empty for text fields and masked content. */\n text?: string;\n /** Window frame of the element, for the position inside it (heatmaps). */\n measure?: () => Promise<Rect | null>;\n}\n\n/** One observed tap, reported by the provider's touch observer. */\nexport interface TapInfo {\n /** Window coordinates in points. */\n x: number;\n y: number;\n /** When the tap ended (ms since epoch); defaults to now. */\n t?: number;\n /** Innermost interactive element under the tap (touchable, `Pressable`, `accessibilityRole=\"button\"`…), if found. */\n element?: TapElement | null;\n /** The view the tap hit, used for rage taps and heatmaps when there is no interactive element. */\n hit?: TapElement | null;\n}\n\n/** `click` / `rage_click` properties on mobile (`ClickProperties` on the web plus `platform`). */\nexport interface TapProperties {\n selector: string;\n tag: string;\n text?: string;\n x: number;\n y: number;\n platform: string;\n count?: number;\n}\n\n/** Quotes an attribute-selector value: `\"` and `\\` escaped with `\\`. */\nexport function quoteValue(value: string): string {\n return `\"${value.replace(/[\"\\\\]/g, \"\\\\$&\")}\"`;\n}\n\n/** `[name=\"value\"]`. */\nexport function attrSelector(name: string, value: string): string {\n return `[${name}=${quoteValue(value)}]`.slice(0, 300);\n}\n\n/** Visible text for analytics: whitespace collapsed, trimmed, at most 100 UTF-16 units. */\nexport function cleanText(text: string | null | undefined): string | undefined {\n const t = (text ?? \"\").replace(/\\s+/g, \" \").trim();\n return t ? t.slice(0, 100) : undefined;\n}\n\n/** Builds `click` properties for an element. */\nexport function tapProperties(el: TapElement, x: number, y: number, platform: string, maskAll: boolean): TapProperties {\n const props: TapProperties = { selector: el.selector.slice(0, 300), tag: el.tag || \"View\", x: Math.round(x) || 0, y: Math.round(y) || 0, platform };\n const text = maskAll ? undefined : cleanText(el.text);\n if (text) props.text = text;\n return props;\n}\n\nconst r2 = (n: number) => Math.round(Math.min(1, Math.max(0, n)) * 100) / 100;\n\n/** One heatmap point: window x/y, the element selector and the position inside its frame (0–1). */\nexport function heatmapPoint(x: number, y: number, el: TapElement | null, rect: Rect | null, rage: boolean): HeatmapPoint {\n const p: HeatmapPoint = { k: rage ? \"r\" : \"c\", x: Math.round(x) || 0, y: Math.round(y) || 0 };\n const s = el?.selector.slice(0, 120);\n if (s) p.s = s;\n if (s && rect && rect.width > 0 && rect.height > 0) {\n p.rx = r2((x - rect.x) / rect.width);\n p.ry = r2((y - rect.y) / rect.height);\n }\n return p;\n}\n\n/**\n * Detects rage taps: 3+ taps within 1s (each within 1s of the previous) and 30pt of the burst's\n * first tap, reported once per burst. Same semantics as the web SDK's `RageClickDetector`\n * (conformance vectors: `rageClicks` in `mobile/conformance/vectors.json`).\n */\nexport class RageClickDetector {\n private clicks: Array<{ x: number; y: number; t: number }> = [];\n private fired = false;\n\n constructor(\n private readonly threshold = 3,\n private readonly windowMs = 1000,\n private readonly radius = 30,\n ) {}\n\n /** Taps in the current burst once it has fired (rage), otherwise 0. */\n get burst(): number {\n return this.fired ? this.clicks.length : 0;\n }\n\n /** Records a tap; returns the tap count when it completes a burst, otherwise 0. */\n add(x: number, y: number, t: number): number {\n const first = this.clicks[0];\n const last = this.clicks[this.clicks.length - 1];\n if (!first || !last || t - last.t > this.windowMs || Math.hypot(x - first.x, y - first.y) > this.radius) {\n this.clicks = [];\n this.fired = false;\n }\n this.clicks = this.clicks.filter((c) => t - c.t <= this.windowMs);\n this.clicks.push({ x, y, t });\n if (this.fired || this.clicks.length < this.threshold) return 0;\n this.fired = true;\n return this.clicks.length;\n }\n}\n\n/** Tap positions on the current screen, sent as one `heatmap` event per batch (40 points, screen change, background). */\nexport class HeatmapBuffer {\n /** Screen path the buffered points belong to. */\n url = \"\";\n points: HeatmapPoint[] = [];\n\n /** Adds a tap (`burst` > 0 marks it and the burst's previous taps as rage); true when the batch is full. */\n add(url: string, point: HeatmapPoint, burst: number): boolean {\n this.url = url;\n for (let i = Math.max(0, this.points.length - burst + 1); i < this.points.length; i++) (this.points[i] as HeatmapPoint).k = \"r\";\n this.points.push(point);\n return this.points.length >= HEATMAP_MAX_POINTS;\n }\n\n /** Empties the buffer, returning what was in it. */\n take(): { url: string; points: HeatmapPoint[] } | null {\n const points = this.points;\n this.points = [];\n return points.length ? { url: this.url, points } : null;\n }\n}\n\n/**\n * Tracks one primary-pointer touch and decides whether it was a tap. Feed it the touch events the\n * provider observes; `end` returns the tap position (window points) or null.\n */\nexport class TapTracker {\n private start: { x: number; y: number; t: number; id: unknown } | null = null;\n private moved = 0;\n\n /** A finger went down. A second finger while one is tracked cancels the gesture (not a tap). */\n begin(x: number, y: number, t: number, touches: number, id?: unknown): void {\n if (this.start || touches > 1) {\n this.start = null;\n return;\n }\n this.start = { x, y, t, id };\n this.moved = 0;\n }\n\n move(x: number, y: number, id?: unknown): void {\n const s = this.start;\n if (s && (id === undefined || s.id === undefined || id === s.id)) this.moved = Math.max(this.moved, Math.hypot(x - s.x, y - s.y));\n }\n\n /** The finger lifted: the tap position when it moved ≤ 10pt and lasted < 1s, else null. */\n end(x: number, y: number, t: number, id?: unknown): { x: number; y: number } | null {\n const s = this.start;\n if (!s || (id !== undefined && s.id !== undefined && id !== s.id)) return null;\n this.start = null;\n const moved = Math.max(this.moved, Math.hypot(x - s.x, y - s.y));\n return moved <= TAP_SLOP && t - s.t < TAP_MAX_MS ? { x, y } : null;\n }\n\n cancel(): void {\n this.start = null;\n }\n}\n","import { guidelyIdFromSelector } from \"@guidelytech/shared/runtime\";\nimport type { SelectorStrategy } from \"@guidelytech/shared\";\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A mounted `<GuidelyTarget>`; `measure` returns its frame in window coordinates. */\nexport interface TargetHandle {\n measure(): Promise<Rect | null>;\n /**\n * Screen the view lives on (from `GuidelyScreenScope`). Navigators keep inactive screens mounted\n * and laid out, so a target on another screen would otherwise measure as visible.\n */\n screen?: string | null;\n}\n\nexport class TargetTimeoutError extends Error {\n constructor(ids: string[]) {\n super(`[Guidely] target not found: ${ids.join(\", \") || \"(no mobile-compatible selector)\"}`);\n this.name = \"TargetTimeoutError\";\n }\n}\n\n/**\n * The Guidely ids a step target can match on mobile, in order: `guidely-id` and `id` strategies\n * by value, CSS / data-attribute strategies when they name a single id (`#x`, `[data-guidely-id=x]`).\n */\nexport function targetIdsFor(selectors: SelectorStrategy[]): string[] {\n const ids: string[] = [];\n for (const s of selectors) {\n let id: string | null = null;\n if (s.kind === \"guidely-id\" || s.kind === \"id\") id = s.value.trim().replace(/^#/, \"\") || null;\n else if (s.kind === \"css\" || s.kind === \"data-attr\") id = guidelyIdFromSelector(s.value);\n if (id && !ids.includes(id)) ids.push(id);\n }\n return ids;\n}\n\n/** Registry of mounted targets. One per client; `<GuidelyTarget>` registers itself on mount. */\nexport class TargetRegistry {\n private readonly targets = new Map<string, TargetHandle[]>();\n private readonly changeListeners = new Set<() => void>();\n private readonly tapListeners = new Set<(id: string) => void>();\n private viewport: { width: number; height: number } | null = null;\n private screen: string | null = null;\n\n register(id: string, handle: TargetHandle): () => void {\n const list = this.targets.get(id) ?? [];\n list.push(handle);\n this.targets.set(id, list);\n this.changed();\n return () => {\n const cur = this.targets.get(id);\n if (!cur) return;\n const next = cur.filter((h) => h !== handle);\n if (next.length) this.targets.set(id, next);\n else this.targets.delete(id);\n this.changed();\n };\n }\n\n /** Window size used for the on-screen check. */\n setViewport(width: number, height: number): void {\n this.viewport = { width, height };\n }\n\n /** The current screen; targets scoped to other screens are treated as hidden. */\n setScreen(name: string | null): void {\n if (name === this.screen) return;\n this.screen = name;\n this.changed();\n }\n\n has(id: string): boolean {\n return this.targets.has(id);\n }\n\n ids(): string[] {\n return Array.from(this.targets.keys());\n }\n\n /** Call when a target's layout may have changed (onLayout, scroll). */\n changed(): void {\n for (const cb of Array.from(this.changeListeners)) {\n try {\n cb();\n } catch {\n /* listener errors never break registration */\n }\n }\n }\n\n onChange(cb: () => void): () => void {\n this.changeListeners.add(cb);\n return () => this.changeListeners.delete(cb);\n }\n\n tapped(id: string): void {\n for (const cb of Array.from(this.tapListeners)) {\n try {\n cb(id);\n } catch {\n /* ignore */\n }\n }\n }\n\n onTap(cb: (id: string) => void): () => void {\n this.tapListeners.add(cb);\n return () => this.tapListeners.delete(cb);\n }\n\n /** Frame of a visible target (the most recently mounted visible one when an id is used twice), else null. */\n async measure(id: string): Promise<Rect | null> {\n const list = this.targets.get(id) ?? [];\n for (let i = list.length - 1; i >= 0; i--) {\n const handle = list[i] as TargetHandle;\n if (handle.screen && this.screen && handle.screen !== this.screen) continue;\n const r = await this.measureHandle(handle);\n if (r) return r;\n }\n return null;\n }\n\n private async measureHandle(handle: TargetHandle): Promise<Rect | null> {\n try {\n const r = await handle.measure();\n if (!r || !(r.width > 0) || !(r.height > 0)) return null;\n const vp = this.viewport;\n if (vp && (r.x + r.width <= 0 || r.y + r.height <= 0 || r.x >= vp.width || r.y >= vp.height)) return null;\n return r;\n } catch {\n return null;\n }\n }\n\n /**\n * The registered target on the current screen whose visible frame contains the point (window\n * coordinates); the smallest one when targets are nested. Frames that do not answer within\n * `timeoutMs` are skipped.\n */\n async hitTest(x: number, y: number, timeoutMs = 500): Promise<{ id: string; rect: Rect } | null> {\n const candidates: Array<{ id: string; handle: TargetHandle }> = [];\n this.targets.forEach((list, id) => {\n for (const handle of list) if (!(handle.screen && this.screen && handle.screen !== this.screen)) candidates.push({ id, handle });\n });\n if (!candidates.length) return null;\n const rects = await Promise.all(\n candidates.map(\n ({ handle }) =>\n new Promise<Rect | null>((resolve) => {\n const timer = setTimeout(() => resolve(null), timeoutMs);\n void this.measureHandle(handle).then((r) => {\n clearTimeout(timer);\n resolve(r);\n });\n }),\n ),\n );\n let best: { id: string; rect: Rect } | null = null;\n rects.forEach((r, i) => {\n if (!r || x < r.x || y < r.y || x > r.x + r.width || y > r.y + r.height) return;\n if (!best || r.width * r.height < best.rect.width * best.rect.height) best = { id: (candidates[i] as { id: string }).id, rect: r };\n });\n return best;\n }\n\n /** First of `ids` that is mounted and visible. */\n async resolve(ids: string[]): Promise<{ id: string; rect: Rect } | null> {\n for (const id of ids) {\n const rect = await this.measure(id);\n if (rect) return { id, rect };\n }\n return null;\n }\n\n /** Resolves when one of `ids` is visible; `timeoutMs` 0 waits forever. Re-checks on registry changes and every 300ms. */\n waitFor(ids: string[], options: { timeoutMs: number; signal?: AbortSignal }): Promise<{ id: string; rect: Rect }> {\n return new Promise((resolve, reject) => {\n let done = false;\n let checking = false;\n let again = false;\n const timers: Array<ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>> = [];\n const finish = (fn: () => void) => {\n if (done) return;\n done = true;\n off();\n timers.forEach((t) => clearTimeout(t as ReturnType<typeof setTimeout>));\n timers.forEach((t) => clearInterval(t as ReturnType<typeof setInterval>));\n options.signal?.removeEventListener?.(\"abort\", onAbort);\n fn();\n };\n const check = async () => {\n if (done) return;\n if (checking) {\n again = true;\n return;\n }\n checking = true;\n const hit = ids.length ? await this.resolve(ids) : null;\n checking = false;\n if (hit) return finish(() => resolve(hit));\n if (again) {\n again = false;\n void check();\n }\n };\n const onAbort = () => finish(() => reject(Object.assign(new Error(\"aborted\"), { name: \"AbortError\" })));\n if (options.signal?.aborted) return onAbort();\n options.signal?.addEventListener?.(\"abort\", onAbort);\n const off = this.onChange(() => void check());\n timers.push(setInterval(() => void check(), 300));\n if (options.timeoutMs > 0) timers.push(setTimeout(() => finish(() => reject(new TargetTimeoutError(ids))), options.timeoutMs));\n void check();\n });\n }\n}\n","import { evaluateRules, guidelyIdFromSelector, matchUrlPattern } from \"@guidelytech/shared/runtime\";\nimport type { EventName, GuideStep, PublishedGuide, StepButton, TargetingContext } from \"@guidelytech/shared\";\nimport { targetIdsFor, type TargetRegistry } from \"./targets\";\n\n/**\n * Headless port of `@guidelytech/guide-runtime`'s `runGuide`: walks steps, waits for targets,\n * handles advancement, branches, multi-screen steps, buttons and back history. Instead of touching\n * a DOM it reports the step to show through `onRender`, and the React Native overlay draws it.\n */\n\nexport interface RuntimeEvent {\n name: EventName;\n stepId?: string;\n stepIndex?: number;\n properties?: Record<string, unknown>;\n}\n\nexport type GuideEndReason = \"completed\" | \"dismissed\" | \"skipped\" | \"destroyed\";\nexport type GuideStatus = \"idle\" | \"running\" | \"waiting_url\" | \"waiting_target\" | \"ended\";\n\nexport interface RenderedStep {\n step: GuideStep;\n index: number;\n total: number;\n canGoBack: boolean;\n targetId: string | null;\n asModal: boolean;\n}\n\nexport interface ControllerOptions {\n targets: TargetRegistry;\n ctx: () => TargetingContext;\n /** Current screen path (`/Deals`). */\n currentUrl: () => string;\n onEvent: (event: RuntimeEvent) => void;\n onRender: (step: RenderedStep) => void;\n onClear: () => void;\n onNavigate: (url: string) => void;\n onAction: (action: \"start_guide\" | \"event\" | \"open_resource_center\", value?: string) => void;\n onEnd: (reason: GuideEndReason) => void;\n onError?: (err: unknown) => void;\n eventBus: { on(name: string, cb: () => void): () => void };\n startAtStep?: string;\n}\n\nexport interface GuideController {\n readonly guide: PublishedGuide;\n start(): void;\n next(): void;\n back(): void;\n goTo(stepId: string): void;\n dismiss(): void;\n complete(): void;\n skip(): void;\n press(button: StepButton): void;\n /** Re-evaluate a step waiting for a screen (call after `screen()`). */\n resume(): void;\n destroy(): void;\n getState(): { status: GuideStatus; stepId: string | null; stepIndex: number; total: number };\n}\n\nconst ANCHORED = new Set([\"tooltip\", \"popover\", \"spotlight\", \"hotspot\"]);\nexport const isAnchoredStep = (step: GuideStep) => ANCHORED.has(step.type);\n/** Same rule as `visibleButtons` in `@guidelytech/shared`: no Back button without a previous step. */\nexport function visibleButtons(step: GuideStep, canGoBack: boolean): StepButton[] {\n return canGoBack ? step.buttons : step.buttons.filter((b) => b.action !== \"back\");\n}\n\n/** `urlMatches` from the web runtime, for screen paths: a pattern without `?`/`#` ignores the query. */\nexport function screenMatches(pattern: string | undefined | null, url: string): boolean {\n if (!pattern) return true;\n if (matchUrlPattern(pattern, url)) return true;\n if (!pattern.includes(\"?\") && !pattern.includes(\"#\")) return matchUrlPattern(pattern, url.split(/[?#]/)[0] ?? url);\n return false;\n}\n\nexport function runGuide(guide: PublishedGuide, o: ControllerOptions): GuideController {\n const steps = guide.config.steps;\n const total = steps.length;\n const onError = o.onError ?? (() => {});\n let status: GuideStatus = \"idle\";\n let index = -1;\n let pendingIndex = -1;\n let rendered = false;\n let started = false;\n let stepDone = false;\n let ended = false;\n const history: number[] = [];\n const stepCleanups: Array<() => void> = [];\n\n const emit = (name: EventName, step?: GuideStep | null, stepIndex?: number, properties?: Record<string, unknown>) => {\n try {\n o.onEvent({ name, stepId: step?.id, stepIndex, properties });\n } catch (err) {\n onError(err);\n }\n };\n\n const clearStep = () => {\n stepCleanups.splice(0).forEach((fn) => {\n try {\n fn();\n } catch {\n /* ignore */\n }\n });\n if (rendered) {\n rendered = false;\n try {\n o.onClear();\n } catch (err) {\n onError(err);\n }\n }\n stepDone = false;\n };\n\n const end = (reason: GuideEndReason) => {\n if (ended) return;\n ended = true;\n const step = steps[index];\n clearStep();\n status = \"ended\";\n if (reason === \"completed\") emit(\"guide_completed\", step, index);\n else if (reason === \"dismissed\") emit(\"guide_dismissed\", step, index);\n else if (reason === \"skipped\") emit(\"guide_skipped\", step, index);\n try {\n o.onEnd(reason);\n } catch (err) {\n onError(err);\n }\n };\n\n const completeStep = () => {\n if (stepDone || index < 0) return;\n stepDone = true;\n emit(\"step_completed\", steps[index], index);\n };\n\n const goNext = (overrideStepId?: string) => {\n const step = steps[index];\n let target = -1;\n const ctx = o.ctx();\n if (step) {\n for (const branch of step.branches) {\n if (evaluateRules(branch.when, ctx)) {\n target = steps.findIndex((s) => s.id === branch.goTo);\n if (target >= 0) break;\n }\n }\n }\n if (target < 0 && overrideStepId) target = steps.findIndex((s) => s.id === overrideStepId);\n if (target < 0) target = index + 1;\n if (target >= total) return end(\"completed\");\n history.push(index);\n showStep(target, 1);\n };\n\n const advance = () => {\n if (ended) return;\n completeStep();\n goNext();\n };\n\n const press = (b: StepButton) => {\n try {\n switch (b.action) {\n case \"next\":\n completeStep();\n goNext(b.value);\n break;\n case \"back\":\n controller.back();\n break;\n case \"dismiss\":\n end(\"dismissed\");\n break;\n case \"complete\":\n completeStep();\n end(\"completed\");\n break;\n case \"skip\":\n end(\"skipped\");\n break;\n case \"url\":\n completeStep();\n o.onNavigate(b.value || \"\");\n if (index + 1 >= total) end(\"completed\");\n else goNext();\n break;\n case \"start_guide\":\n completeStep();\n end(\"completed\");\n o.onAction(\"start_guide\", b.value);\n break;\n case \"event\":\n o.onAction(\"event\", b.value);\n break;\n case \"open_resource_center\":\n o.onAction(\"open_resource_center\", b.value);\n break;\n default:\n break;\n }\n } catch (err) {\n onError(err);\n }\n };\n\n const setupAdvance = (step: GuideStep, targetId: string | null) => {\n const modes = step.advanceOn === \"any\" ? [\"element_click\", \"element_visible\", \"event\", \"delay\"] : [step.advanceOn];\n for (const mode of modes) {\n // The editor documents an empty element value as \"use the step target\".\n const id = guidelyIdFromSelector(step.advanceValue) ?? (mode === \"element_click\" ? targetId : null);\n if (mode === \"element_click\" && id) {\n stepCleanups.push(o.targets.onTap((tapped) => tapped === id && advance()));\n } else if (mode === \"element_visible\" && id) {\n const ac = new AbortController();\n stepCleanups.push(() => ac.abort());\n o.targets.waitFor([id], { timeoutMs: 0, signal: ac.signal }).then(() => !ac.signal.aborted && advance(), () => {});\n } else if (mode === \"event\" && step.advanceValue) {\n stepCleanups.push(o.eventBus.on(step.advanceValue, advance));\n } else if (mode === \"delay\") {\n const t = setTimeout(advance, step.advanceDelayMs ?? 3000);\n stepCleanups.push(() => clearTimeout(t));\n }\n }\n };\n\n const render = (step: GuideStep, targetId: string | null, asModal = false) => {\n if (ended) return;\n status = \"running\";\n try {\n o.onRender({ step, index, total, canGoBack: history.length > 0 || index > 0, targetId, asModal });\n rendered = true;\n } catch (err) {\n onError(err);\n if (index + 1 < total) return goNext();\n return end(\"skipped\");\n }\n if (!started) {\n started = true;\n emit(\"guide_started\", step, index);\n }\n emit(\"step_viewed\", step, index, asModal ? { fallback: \"show_as_modal\" } : undefined);\n setupAdvance(step, targetId);\n };\n\n const applyFallback = (step: GuideStep, direction: 1 | -1) => {\n const fallback = step.target?.fallback ?? \"skip\";\n emit(\"step_viewed\", step, index, { fallback, targetMissing: true });\n if (fallback === \"show_as_modal\") return render(step, null, true);\n if (fallback === \"end_guide\") return end(\"skipped\");\n const nextIndex = index + direction;\n if (nextIndex < 0) return showStep(0, 1);\n if (nextIndex >= total) return end(\"completed\");\n showStep(nextIndex, direction);\n };\n\n function showStep(i: number, direction: 1 | -1 = 1): void {\n if (ended) return;\n clearStep();\n if (i < 0) i = 0;\n if (i >= total) return end(\"completed\");\n index = i;\n const step = steps[i] as GuideStep;\n if (step.targeting && step.targeting.rules.length && !evaluateRules(step.targeting, o.ctx())) {\n const nextIndex = i + direction;\n if (nextIndex >= total) return end(\"completed\");\n if (nextIndex < 0) return;\n return showStep(nextIndex, direction);\n }\n if (step.url && !screenMatches(step.url, o.currentUrl())) {\n status = \"waiting_url\";\n pendingIndex = i;\n return;\n }\n pendingIndex = -1;\n if (isAnchoredStep(step) && step.target) {\n status = \"waiting_target\";\n const ids = targetIdsFor(step.target.selectors);\n if (!ids.length) return applyFallback(step, direction);\n const ac = new AbortController();\n stepCleanups.push(() => ac.abort());\n const timeoutMs = step.target.fallback === \"wait\" ? 0 : step.target.waitMs;\n o.targets.waitFor(ids, { timeoutMs, signal: ac.signal }).then(\n (hit) => {\n if (ac.signal.aborted || ended) return;\n render(step, hit.id);\n },\n (err) => {\n if (ac.signal.aborted || ended || (err as Error)?.name === \"AbortError\") return;\n applyFallback(step, direction);\n },\n );\n return;\n }\n render(step, null);\n }\n\n const controller: GuideController = {\n guide,\n start() {\n if (status !== \"idle\") return;\n emit(\"guide_viewed\");\n if (total === 0) return end(\"completed\");\n let startIndex = o.startAtStep ? steps.findIndex((s) => s.id === o.startAtStep) : 0;\n if (startIndex < 0) startIndex = 0;\n showStep(startIndex, 1);\n },\n next() {\n if (ended || index < 0) return;\n completeStep();\n goNext();\n },\n back() {\n if (ended) return;\n const prev = history.pop();\n if (prev == null) {\n if (index > 0) showStep(index - 1, -1);\n return;\n }\n showStep(prev, -1);\n },\n goTo(stepId) {\n const i = steps.findIndex((s) => s.id === stepId);\n if (i >= 0 && !ended) {\n if (index >= 0) history.push(index);\n showStep(i, 1);\n }\n },\n dismiss: () => end(\"dismissed\"),\n complete() {\n completeStep();\n end(\"completed\");\n },\n skip: () => end(\"skipped\"),\n press,\n resume() {\n if (ended) return;\n if (status === \"waiting_url\" && pendingIndex >= 0) return showStep(pendingIndex, 1);\n const step = steps[index];\n if (step?.url && status === \"running\" && !screenMatches(step.url, o.currentUrl())) showStep(index, 1);\n },\n destroy() {\n if (ended) return;\n ended = true;\n clearStep();\n status = \"ended\";\n try {\n o.onEnd(\"destroyed\");\n } catch (err) {\n onError(err);\n }\n },\n getState: () => ({ status, stepId: steps[index]?.id ?? null, stepIndex: index, total }),\n };\n return controller;\n}\n","import type {\n ConversationLookupResponse,\n ConversationMessagesResponse,\n MessengerConfig,\n MessengerConversation,\n MessengerMessage,\n ResourceCenterArticle,\n SdkArticlesResponse,\n StartConversationResponse,\n} from \"@guidelytech/shared\";\nimport { KEYS, isServerFailure, readJson, writeJson, type KeyValueStore, type ServerHealth } from \"@guidelytech/sdk-core/headless\";\n\n/**\n * Scout messenger for React Native: the transport of `@guidelytech/sdk-core`'s messenger-api plus\n * the conversation state the web widget keeps, as a headless store the overlay renders.\n */\n\nexport type MessengerTab = \"home\" | \"messages\" | \"help\";\nexport type MessengerView = { kind: \"tab\"; tab: MessengerTab } | { kind: \"thread\"; conversationId: string | null } | { kind: \"article\"; articleId: string; from: MessengerView };\n\nexport interface MessengerThread {\n conversation: MessengerConversation | null;\n messages: MessengerMessage[];\n /** Reply text streamed so far, by message id (before the final `done` message arrives). */\n streaming: Record<string, string>;\n sending: boolean;\n error: string | null;\n /** Text to pre-fill in the composer (`showNewMessage(text)`). */\n draft: string;\n}\n\nexport interface MessengerSnapshot {\n config: MessengerConfig;\n open: boolean;\n view: MessengerView;\n conversations: MessengerConversation[];\n thread: MessengerThread | null;\n /** Conversations with unread replies. */\n unread: number;\n articles: SdkArticlesResponse | null;\n article: ResourceCenterArticle | null;\n}\n\nconst TOKEN_HEADER = \"X-Guidely-Conversation\";\nconst MAX_STORED = 50;\n\ninterface StoredConversation {\n id: string;\n token: string;\n}\n\n/** Incremental `text/event-stream` parser: `event:` + single-line JSON `data:`, `:` comments ignored. */\nexport function createSseParser(onEvent: (event: string, data: unknown) => void) {\n let buffer = \"\";\n const dispatch = (raw: string) => {\n let event = \"message\";\n const data: string[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) continue;\n const i = line.indexOf(\":\");\n const field = i < 0 ? line : line.slice(0, i);\n const value = i < 0 ? \"\" : line.slice(i + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n }\n if (!data.length) return;\n try {\n onEvent(event, JSON.parse(data.join(\"\\n\")));\n } catch {\n /* ignore malformed events */\n }\n };\n return {\n feed(chunk: string) {\n buffer += chunk.replace(/\\r\\n?/g, \"\\n\");\n let sep: number;\n while ((sep = buffer.indexOf(\"\\n\\n\")) >= 0) {\n dispatch(buffer.slice(0, sep));\n buffer = buffer.slice(sep + 2);\n }\n },\n end() {\n if (buffer.trim()) dispatch(buffer);\n buffer = \"\";\n },\n };\n}\n\nexport interface HttpResult {\n status: number;\n /** JSON body when the server answered with JSON. */\n json: unknown;\n}\n\n/**\n * POST that streams server-sent events as they arrive. React Native's `fetch` cannot read a body\n * incrementally, but its `XMLHttpRequest` reports partial `responseText` on progress events.\n */\nexport type StreamPost = (url: string, headers: Record<string, string>, body: unknown, onChunk: (text: string) => void) => Promise<HttpResult & { streamed: boolean }>;\n\n/** Reply streams: the response must start within this long, and then never go quiet longer than the idle limit (the server sends a keepalive every 15 s). */\nexport const STREAM_RESPONSE_TIMEOUT_MS = 30_000;\nexport const STREAM_IDLE_TIMEOUT_MS = 60_000;\n\nexport function xhrStreamPost(): StreamPost | null {\n if (typeof XMLHttpRequest === \"undefined\") return null;\n return (url, headers, body, onChunk) =>\n new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n let seen = 0;\n let streamed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer) clearTimeout(timer);\n fn();\n };\n // No overall timeout (Scout replies can take a while), but a server that never answers or goes\n // silent mid-reply aborts the request instead of leaving the composer spinning forever.\n const arm = (ms: number, what: string) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n settle(() => reject(new Error(`Scout ${what} timed out`)));\n xhr.abort();\n }, ms);\n };\n const pump = () => {\n const type = xhr.getResponseHeader(\"content-type\") || \"\";\n if (!type.includes(\"text/event-stream\")) return;\n streamed = true;\n const text = xhr.responseText || \"\";\n if (text.length > seen) {\n onChunk(text.slice(seen));\n seen = text.length;\n }\n };\n xhr.open(\"POST\", url);\n for (const [k, v] of Object.entries(headers)) xhr.setRequestHeader(k, v);\n xhr.onreadystatechange = () => {\n if (!settled && xhr.readyState >= 2 && xhr.readyState < 4) arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n };\n xhr.onprogress = () => {\n if (settled) return;\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n pump();\n };\n xhr.onload = () =>\n settle(() => {\n pump();\n let json: unknown = null;\n if (!streamed) {\n try {\n json = JSON.parse(xhr.responseText || \"null\");\n } catch {\n json = null;\n }\n }\n resolve({ status: xhr.status, json, streamed });\n });\n xhr.onerror = () => settle(() => reject(new Error(\"Network request failed\")));\n arm(STREAM_RESPONSE_TIMEOUT_MS, \"request\");\n xhr.send(JSON.stringify(body));\n });\n}\n\n/** The parts of a streaming `fetch` body read below; React Native's types (no DOM lib) don't declare them. */\ninterface ByteReader {\n read(): Promise<{ done: boolean; value?: Uint8Array }>;\n}\ninterface TextDecoderLike {\n decode(input?: Uint8Array, options?: { stream?: boolean }): string;\n}\n\n/** A streaming reader for the body, or null when the `fetch` or the runtime (no `TextDecoder`) can't stream it. */\nfunction bodyReader(res: Response): { reader: ByteReader; decoder: TextDecoderLike } | null {\n const body = (res as { body?: { getReader?: () => ByteReader } | null }).body;\n const Decoder = (globalThis as { TextDecoder?: new () => TextDecoderLike }).TextDecoder;\n return body && typeof body.getReader === \"function\" && Decoder ? { reader: body.getReader(), decoder: new Decoder() } : null;\n}\n\n/** Fallback (tests, platforms without XHR): reads the body as it arrives when the `fetch` exposes a stream, otherwise waits for all of it. Same timeouts as {@link xhrStreamPost}. */\nexport function fetchStreamPost(fetchImpl: typeof fetch): StreamPost {\n return async (url, headers, body, onChunk) => {\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let timedOut = \"\";\n // Rejects on its own too, for `fetch` implementations that ignore the abort signal.\n let fail: (err: Error) => void = () => {};\n const expired = new Promise<never>((_, reject) => (fail = reject));\n expired.catch(() => {});\n const arm = (ms: number, what: string) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timedOut = what;\n ac?.abort();\n fail(new Error(`Scout ${what} timed out`));\n }, ms);\n };\n const race = <T>(p: Promise<T>) => Promise.race([p, expired]);\n arm(STREAM_RESPONSE_TIMEOUT_MS, \"request\");\n try {\n const res = await race(fetchImpl(url, { method: \"POST\", headers, body: JSON.stringify(body), signal: ac?.signal }));\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n const type = res.headers.get(\"content-type\") || \"\";\n const sse = type.includes(\"text/event-stream\");\n const streaming = sse ? bodyReader(res) : null;\n if (streaming) {\n const { reader, decoder } = streaming;\n for (;;) {\n const { done, value } = await race(reader.read());\n if (value) {\n arm(STREAM_IDLE_TIMEOUT_MS, \"reply\");\n onChunk(decoder.decode(value, { stream: true }));\n }\n if (done) break;\n }\n const rest = decoder.decode();\n if (rest) onChunk(rest);\n return { status: res.status, json: null, streamed: true };\n }\n const text = await race(res.text());\n if (sse) {\n onChunk(text);\n return { status: res.status, json: null, streamed: true };\n }\n let json: unknown = null;\n try {\n json = JSON.parse(text || \"null\");\n } catch {\n json = null;\n }\n return { status: res.status, json, streamed: false };\n } catch (err) {\n throw timedOut ? new Error(`Scout ${timedOut} timed out`) : err;\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n}\n\nexport interface MessengerDeps {\n baseUrl: string;\n publicKey: string;\n store: KeyValueStore;\n fetch: typeof fetch;\n streamPost: StreamPost;\n anonymousId: () => string;\n userId: () => string | null;\n /** Screen path to attach to new conversations (omitted when URL collection is off). */\n pageUrl: () => string | undefined;\n onOpen: () => void;\n onMessage: (message: MessengerMessage, conversation: MessengerConversation) => void;\n onStartGuide: (key: string) => void;\n onError: (err: unknown) => void;\n /** The SDK API's circuit breaker, told how each reply stream went. */\n health?: ServerHealth;\n /** The help center's language when it isn't the default; translated articles are fetched with `?locale=`. */\n locale?: () => string | undefined;\n /** Poll intervals (ms): open thread, and unread badge otherwise. */\n pollMs?: { thread: number; background: number };\n}\n\nconst byNewest = (a: MessengerConversation, b: MessengerConversation) => Date.parse(b.lastMessageAt) - Date.parse(a.lastMessageAt);\n\nexport class Messenger {\n private snapshot: MessengerSnapshot;\n private readonly listeners = new Set<() => void>();\n private threadTimer: ReturnType<typeof setTimeout> | null = null;\n private backgroundTimer: ReturnType<typeof setInterval> | null = null;\n private foreground = true;\n private destroyed = false;\n private readonly poll: { thread: number; background: number };\n\n constructor(\n config: MessengerConfig,\n private readonly deps: MessengerDeps,\n ) {\n this.poll = deps.pollMs ?? { thread: 5000, background: 60000 };\n this.snapshot = { config, open: false, view: { kind: \"tab\", tab: \"home\" }, conversations: [], thread: null, unread: 0, articles: null, article: null };\n void this.refreshConversations();\n this.startBackgroundPolling();\n }\n\n // -------------------------------------------------------------------------- state\n\n getSnapshot(): MessengerSnapshot {\n return this.snapshot;\n }\n\n subscribe(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n private set(patch: Partial<MessengerSnapshot>): void {\n if (this.destroyed) return;\n const next = { ...this.snapshot, ...patch };\n next.unread = next.conversations.filter((c) => c.unread > 0).length;\n this.snapshot = next;\n for (const cb of Array.from(this.listeners)) {\n try {\n cb();\n } catch (err) {\n this.deps.onError(err);\n }\n }\n }\n\n private setThread(patch: Partial<MessengerThread>): void {\n const t = this.snapshot.thread;\n if (!t) return;\n this.set({ thread: { ...t, ...patch } });\n }\n\n updateConfig(config: MessengerConfig): void {\n this.set({ config });\n }\n\n // -------------------------------------------------------------------------- tokens\n\n private stored(): StoredConversation[] {\n const list = readJson<StoredConversation[]>(this.deps.store, KEYS.conversations(this.deps.publicKey), []);\n return Array.isArray(list) ? list.filter((c) => c && typeof c.id === \"string\" && typeof c.token === \"string\") : [];\n }\n\n private remember(id: string, token: string): void {\n writeJson(this.deps.store, KEYS.conversations(this.deps.publicKey), [{ id, token }, ...this.stored().filter((c) => c.id !== id)].slice(0, MAX_STORED));\n }\n\n private tokenFor(id: string): string {\n return this.stored().find((c) => c.id === id)?.token ?? \"\";\n }\n\n /** Forgets every conversation (logout). */\n forgetAll(): void {\n this.deps.store.remove(KEYS.conversations(this.deps.publicKey));\n this.stopThreadPolling();\n this.set({ open: false, view: { kind: \"tab\", tab: \"home\" }, conversations: [], thread: null, article: null });\n }\n\n // -------------------------------------------------------------------------- http\n\n private url(path: string, params: Record<string, string | undefined> = {}): string {\n const query = Object.entries({ key: this.deps.publicKey, ...params })\n .filter((e): e is [string, string] => e[1] != null)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n return `${this.deps.baseUrl.replace(/\\/$/, \"\")}/api/v1/sdk${path}?${query}`;\n }\n\n private headers(extra: Record<string, string> = {}): Record<string, string> {\n return { \"X-Guidely-Key\": this.deps.publicKey, Accept: \"application/json\", \"Content-Type\": \"application/json\", ...extra };\n }\n\n private async request<T>(method: \"GET\" | \"POST\", path: string, opts: { body?: unknown; params?: Record<string, string | undefined>; conversationId?: string } = {}): Promise<T> {\n const headers = this.headers(opts.conversationId ? { [TOKEN_HEADER]: this.tokenFor(opts.conversationId) } : {});\n const res = await this.deps.fetch(this.url(path, opts.params), { method, headers, body: opts.body === undefined ? undefined : JSON.stringify(opts.body) });\n if (!res.ok) throw new Error(`Request failed (${res.status})`);\n return (await res.json()) as T;\n }\n\n // -------------------------------------------------------------------------- navigation\n\n open(tab?: MessengerTab): void {\n const wasOpen = this.snapshot.open;\n this.set({ open: true, ...(tab ? { view: { kind: \"tab\", tab } as MessengerView } : {}) });\n if (!wasOpen) {\n this.deps.onOpen();\n void this.refreshConversations();\n }\n if (tab === \"help\" || this.snapshot.view.kind === \"tab\") this.onView();\n }\n\n close(): void {\n this.stopThreadPolling();\n this.set({ open: false });\n }\n\n setTab(tab: MessengerTab): void {\n this.stopThreadPolling();\n this.set({ view: { kind: \"tab\", tab }, thread: null });\n this.onView();\n }\n\n private onView(): void {\n const v = this.snapshot.view;\n if (v.kind === \"tab\" && v.tab === \"help\" && !this.snapshot.articles) void this.loadArticles();\n if (v.kind === \"tab\" && v.tab === \"messages\") void this.refreshConversations();\n }\n\n /** Opens a new thread (optionally pre-filling the composer). */\n showNewMessage(text = \"\"): void {\n this.stopThreadPolling();\n if (!this.snapshot.open) this.deps.onOpen();\n this.set({ open: true, view: { kind: \"thread\", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft: text } });\n }\n\n async openConversation(id: string): Promise<void> {\n const known = this.snapshot.conversations.find((c) => c.id === id) ?? null;\n this.stopThreadPolling();\n this.set({ open: true, view: { kind: \"thread\", conversationId: id }, thread: { conversation: known, messages: [], streaming: {}, sending: false, error: null, draft: \"\" } });\n try {\n const res = await this.request<ConversationMessagesResponse>(\"GET\", `/conversations/${encodeURIComponent(id)}/messages`, { conversationId: id });\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 }, messages: res.messages });\n } catch (err) {\n this.setThread({ error: \"Couldn't load this conversation.\" });\n this.deps.onError(err);\n }\n this.scheduleThreadPoll();\n }\n\n back(): void {\n const v = this.snapshot.view;\n if (v.kind === \"article\") return this.set({ view: v.from, article: null });\n this.setTab(this.snapshot.thread?.conversation ? \"messages\" : \"home\");\n }\n\n // -------------------------------------------------------------------------- conversations\n\n private upsertConversation(c: MessengerConversation): void {\n const list = [c, ...this.snapshot.conversations.filter((x) => x.id !== c.id)].sort(byNewest);\n this.set({ conversations: list });\n }\n\n private markRead(c: MessengerConversation): void {\n this.upsertConversation({ ...c, unread: 0 });\n }\n\n async refreshConversations(): Promise<void> {\n const stored = this.stored();\n if (!stored.length) return;\n try {\n const res = await this.request<ConversationLookupResponse>(\"POST\", \"/conversations/lookup\", { body: { tokens: stored.map((c) => c.token) } });\n const known = new Set(res.conversations.map((c) => c.id));\n // Drop tokens the server no longer knows (deleted by retention).\n if (stored.some((c) => !known.has(c.id))) writeJson(this.deps.store, KEYS.conversations(this.deps.publicKey), stored.filter((c) => known.has(c.id)));\n const openId = this.snapshot.view.kind === \"thread\" ? this.snapshot.view.conversationId : null;\n const list = res.conversations.map(({ token: _token, ...c }) => (c.id === openId && this.snapshot.open ? { ...c, unread: 0 } : c)).sort(byNewest);\n this.set({ conversations: list });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n /** Sends the composer text: starts a conversation or posts to the open one. Streams Scout's reply. */\n async send(text: string): Promise<void> {\n const body = text.trim().slice(0, 4000);\n const thread = this.snapshot.thread;\n if (!body || !thread || thread.sending) return;\n this.setThread({ sending: true, error: null, draft: \"\" });\n const conversationId = thread.conversation?.id ?? null;\n const path = conversationId ? `/conversations/${encodeURIComponent(conversationId)}/messages` : \"/conversations\";\n const payload = conversationId ? { message: body } : { anonymousId: this.deps.anonymousId(), userId: this.deps.userId(), message: body, pageUrl: this.deps.pageUrl() };\n const headers = { ...this.headers(conversationId ? { [TOKEN_HEADER]: this.tokenFor(conversationId) } : {}), Accept: \"text/event-stream, application/json\" };\n let finished = false;\n const parser = createSseParser((event, data) => {\n if (event === \"conversation\") {\n const d = data as StartConversationResponse;\n this.remember(d.conversation.id, d.token);\n this.markRead(d.conversation);\n this.set({ view: { kind: \"thread\", conversationId: d.conversation.id } });\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n d.messages.forEach((m) => this.addMessage(m));\n } else if (event === \"message\") this.addMessage(data as MessengerMessage);\n else if (event === \"delta\") {\n const d = data as { messageId: string; text: string };\n const t = this.snapshot.thread;\n if (t) this.setThread({ streaming: { ...t.streaming, [d.messageId]: (t.streaming[d.messageId] ?? \"\") + d.text } });\n } else if (event === \"done\") {\n finished = true;\n const d = data as { message: MessengerMessage | null; conversation: MessengerConversation };\n if (d.message) this.addMessage(d.message);\n this.markRead(d.conversation);\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n } else if (event === \"error\") {\n this.setThread({ error: (data as { message?: string })?.message ?? \"Something went wrong\" });\n }\n });\n try {\n let res: HttpResult & { streamed: boolean };\n try {\n res = await this.deps.streamPost(this.url(path), headers, payload, (chunk) => parser.feed(chunk));\n } catch (err) {\n this.deps.health?.failure();\n throw err;\n }\n if (isServerFailure(res.status)) this.deps.health?.failure();\n else this.deps.health?.success();\n parser.end();\n if (res.status < 200 || res.status >= 300) throw new Error(`Request failed (${res.status})`);\n if (!res.streamed && res.json) {\n const d = res.json as StartConversationResponse | ConversationMessagesResponse;\n if (\"token\" in d) {\n this.remember(d.conversation.id, d.token);\n this.set({ view: { kind: \"thread\", conversationId: d.conversation.id } });\n }\n this.markRead(d.conversation);\n this.setThread({ conversation: { ...d.conversation, unread: 0 } });\n d.messages.forEach((m) => this.addMessage(m));\n } else if (res.streamed && !finished) this.setThread({ error: \"The reply was interrupted. Pull to refresh in a moment.\" });\n } catch (err) {\n this.setThread({ error: \"Your message wasn't sent. Check your connection and try again.\", draft: body });\n this.deps.onError(err);\n } finally {\n const t = this.snapshot.thread;\n if (t) this.setThread({ sending: false, streaming: {} });\n this.scheduleThreadPoll();\n }\n }\n\n private addMessage(m: MessengerMessage): void {\n const t = this.snapshot.thread;\n if (!t) return;\n const exists = t.messages.some((x) => x.id === m.id);\n const messages = exists ? t.messages.map((x) => (x.id === m.id ? m : x)) : [...t.messages, m];\n const streaming = { ...t.streaming };\n if (m.status !== \"pending\") delete streaming[m.id];\n this.setThread({ messages, streaming });\n if (!exists && m.status !== \"pending\" && (m.author === \"scout\" || m.author === \"agent\") && t.conversation) this.deps.onMessage(m, t.conversation);\n }\n\n async handoff(): Promise<void> {\n const id = this.snapshot.thread?.conversation?.id;\n if (!id) return;\n try {\n const res = await this.request<ConversationMessagesResponse>(\"POST\", `/conversations/${encodeURIComponent(id)}/handoff`, { body: {}, conversationId: id });\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 } });\n res.messages.forEach((m) => this.addMessage(m));\n } catch (err) {\n this.setThread({ error: \"Couldn't reach the team. Try again.\" });\n this.deps.onError(err);\n }\n }\n\n async rate(rating: number): Promise<void> {\n const c = this.snapshot.thread?.conversation;\n if (!c) return;\n this.setThread({ conversation: { ...c, rating } });\n try {\n await this.request(\"POST\", `/conversations/${encodeURIComponent(c.id)}/rating`, { body: { rating }, conversationId: c.id });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n startGuide(key: string): void {\n this.close();\n this.deps.onStartGuide(key);\n }\n\n // -------------------------------------------------------------------------- help\n\n async loadArticles(): Promise<void> {\n try {\n this.set({ articles: await this.request<SdkArticlesResponse>(\"GET\", \"/articles\") });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n async openArticle(id: string): Promise<void> {\n const from = this.snapshot.view.kind === \"article\" ? this.snapshot.view.from : this.snapshot.view;\n this.stopThreadPolling();\n this.set({ open: true, view: { kind: \"article\", articleId: id, from }, article: null });\n try {\n const locale = this.deps.locale?.();\n const res = await this.request<{ article: ResourceCenterArticle }>(\"GET\", `/articles/${encodeURIComponent(id)}`, locale ? { params: { locale } } : {});\n this.set({ article: res.article });\n } catch (err) {\n this.deps.onError(err);\n }\n }\n\n async search(q: string): Promise<ResourceCenterArticle[]> {\n try {\n return (await this.request<{ articles: ResourceCenterArticle[] }>(\"GET\", \"/resource-center/search\", { params: { q } })).articles;\n } catch {\n return [];\n }\n }\n\n // -------------------------------------------------------------------------- polling\n\n /** Called with app foreground/background changes; polling only runs in the foreground. */\n setForeground(active: boolean): void {\n this.foreground = active;\n if (!active) {\n this.stopThreadPolling();\n return;\n }\n void this.refreshConversations();\n if (this.snapshot.open && this.snapshot.view.kind === \"thread\") this.scheduleThreadPoll();\n }\n\n private startBackgroundPolling(): void {\n this.backgroundTimer = setInterval(() => {\n if (this.foreground && !(this.snapshot.open && this.snapshot.view.kind === \"thread\")) void this.refreshConversations();\n }, this.poll.background);\n }\n\n private scheduleThreadPoll(): void {\n this.stopThreadPolling();\n if (this.destroyed || !this.foreground) return;\n this.threadTimer = setTimeout(() => void this.pollThread(), this.poll.thread);\n }\n\n private stopThreadPolling(): void {\n if (this.threadTimer) clearTimeout(this.threadTimer);\n this.threadTimer = null;\n }\n\n private async pollThread(): Promise<void> {\n const t = this.snapshot.thread;\n const id = t?.conversation?.id;\n if (!t || !id || !this.snapshot.open || t.sending) return this.scheduleThreadPoll();\n const since = t.messages[t.messages.length - 1]?.createdAt;\n try {\n const res = await this.request<ConversationMessagesResponse>(\"GET\", `/conversations/${encodeURIComponent(id)}/messages`, { params: { since }, conversationId: id });\n if (this.snapshot.thread?.conversation?.id !== id) return;\n this.markRead(res.conversation);\n this.setThread({ conversation: { ...res.conversation, unread: 0 } });\n res.messages.forEach((m) => this.addMessage(m));\n } catch (err) {\n this.deps.onError(err);\n }\n this.scheduleThreadPoll();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.stopThreadPolling();\n if (this.backgroundTimer) clearInterval(this.backgroundTimer);\n this.listeners.clear();\n }\n}\n","import { randomId } from \"@guidelytech/shared/runtime\";\nimport { backoffMs, type ServerHealth } from \"@guidelytech/sdk-core/headless\";\nimport type { Rect } from \"./targets\";\n\n// Session replay (mobile/SPEC.md \"Session replay\"): rrweb events built from masked screenshots and\n// touches, buffered and uploaded like the web ReplayController. A port of the Android SDK's\n// `core/Replay.kt`; the screenshots come from the native `@guidelytech/react-native-replay` module.\n\n/** One captured screen: a masked JPEG (base64) at 1 px per point, and the viewport in points. */\nexport interface ReplayFrame {\n base64: string;\n width: number;\n height: number;\n /** Window position (points) of the React root view that touch coordinates are relative to. */\n originX?: number;\n originY?: number;\n}\n\n/** What the capturer must paint over in the next frame. */\nexport interface ReplayCaptureOptions {\n maskAllText: boolean;\n maskAllImages: boolean;\n /** Window rects (points) of targets whose Guidely id is in `settings.replay.blockSelectors`. */\n blockRects: Rect[];\n}\n\n/** Captures the app's visible windows; resolves null when there is nothing to capture. */\nexport type ScreenCapturer = (options: ReplayCaptureOptions) => Promise<ReplayFrame | null>;\n\nexport type TouchPhase = \"down\" | \"move\" | \"up\" | \"cancel\";\n\n/** Fixed rrweb document (ids 1–8, see the SPEC) whose single `img` (id 8) shows the current screenshot. */\nexport const RrwebEvents = {\n IMG_ID: 8,\n TOUCH_START: 7,\n TOUCH_END: 9,\n CLICK: 2,\n CSS: \"html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden;background:#000}img{display:block;width:100%;height:100%;object-fit:contain}\",\n\n dataUrl(base64: string): string {\n return `data:image/jpeg;base64,${base64}`;\n },\n\n meta(timestamp: number, href: string, width: number, height: number): string {\n return JSON.stringify({ type: 4, data: { href, width, height }, timestamp });\n },\n\n fullSnapshot(timestamp: number, dataUrl: string, width: number, height: number): string {\n const style = { type: 2, id: 5, tagName: \"style\", attributes: {}, childNodes: [{ type: 3, id: 6, textContent: RrwebEvents.CSS, isStyle: true }] };\n const img = { type: 2, id: 8, tagName: \"img\", attributes: { src: dataUrl, width, height, alt: \"\" }, childNodes: [] };\n const html = { type: 2, id: 3, tagName: \"html\", attributes: {}, childNodes: [{ type: 2, id: 4, tagName: \"head\", attributes: {}, childNodes: [style] }, { type: 2, id: 7, tagName: \"body\", attributes: {}, childNodes: [img] }] };\n const node = { type: 0, id: 1, childNodes: [{ type: 1, id: 2, name: \"html\", publicId: \"\", systemId: \"\" }, html] };\n return JSON.stringify({ type: 2, data: { node, initialOffset: { left: 0, top: 0 } }, timestamp });\n },\n\n frame(timestamp: number, dataUrl: string): string {\n return JSON.stringify({ type: 3, data: { source: 0, texts: [], attributes: [{ id: 8, attributes: { src: dataUrl } }], removes: [], adds: [] }, timestamp });\n },\n\n /** MouseInteraction (source 2): 7 TouchStart, 9 TouchEnd, 2 Click. */\n interaction(timestamp: number, type: number, x: number, y: number): string {\n return JSON.stringify({ type: 3, data: { source: 2, type, id: 8, x: round1(x), y: round1(y) }, timestamp });\n },\n\n touchMove(timestamp: number, x: number, y: number): string {\n return JSON.stringify({ type: 3, data: { source: 6, positions: [{ x: round1(x), y: round1(y), id: 8, timeOffset: 0 }] }, timestamp });\n },\n\n custom(timestamp: number, tag: string, payload: Record<string, unknown>): string {\n return JSON.stringify({ type: 5, data: { tag, payload }, timestamp });\n },\n};\n\nconst round1 = (v: number) => Math.round(v * 10) / 10;\n\n/** Per-upload metadata (`ReplayChunk` minus `sessionId` / `windowId` / `seq` / `events`). */\nexport interface ReplayChunkMeta {\n anonymousId: string;\n userId: string | null;\n url?: string;\n device: { type: string; os: string };\n viewport?: { width: number; height: number };\n sdk: { name: string; version: string };\n}\n\ninterface Chunk {\n sessionId: string;\n meta: ReplayChunkMeta;\n events: string[];\n bytes: number;\n seq?: number;\n}\n\ntype UploadResult = \"ok\" | \"drop\" | \"retry\" | \"disabled\";\n\nexport interface ReplayUploaderOptions {\n /** `POST /replay` URL. */\n url: () => string;\n fetch: () => typeof fetch | null;\n meta: () => ReplayChunkMeta;\n onDisabled: (sessionId: string) => void;\n health?: ServerHealth;\n log?: (message: string) => void;\n flushIntervalMs?: number;\n maxBufferBytes?: number;\n maxQueuedBytes?: number;\n maxAttempts?: number;\n slowRetryMs?: number;\n}\n\n/** Uploads still running after this long are aborted and retried. */\nconst UPLOAD_TIMEOUT_MS = 30_000;\n\n/**\n * Buffers rrweb events (JSON strings) and uploads them with `POST /replay`. The buffer is sealed every\n * 10 s, above ~1 MB, on {@link flush} (stop, background) and when the session changes. Chunks go out\n * one at a time as plain JSON (Hermes has no gzip, and base64 JPEGs barely compress); `seq` is\n * assigned per session on a chunk's first attempt and kept for its retries. 2xx removes the chunk\n * (`{disabled:true}` drops that session's chunks), 4xx other than 429 drops it, anything else retries\n * with backoff, then about once a minute. The backlog is capped at ~5 MB (oldest first, never the\n * chunk in flight).\n */\nexport class ReplayUploader {\n readonly windowId = randomId(16);\n private buffer: Chunk | null = null;\n private queue: Chunk[] = [];\n private queuedBytes = 0;\n private seqs = new Map<string, number>();\n private inflight: Chunk | null = null;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private destroyed = false;\n private readonly offRecover: (() => void) | null;\n\n constructor(private readonly opts: ReplayUploaderOptions) {\n this.offRecover =\n opts.health?.onRecover?.(() => {\n this.clearRetry();\n this.attempt = 0;\n this.flush();\n }) ?? null;\n }\n\n get pendingChunks(): number {\n return this.queue.length;\n }\n\n get bufferedEvents(): number {\n return this.buffer?.events.length ?? 0;\n }\n\n push(sessionId: string, json: string): void {\n if (this.destroyed) return;\n if (this.buffer && this.buffer.sessionId !== sessionId) this.seal();\n const chunk = this.buffer ?? (this.buffer = { sessionId, meta: this.opts.meta(), events: [], bytes: 0 });\n chunk.events.push(json);\n chunk.bytes += json.length;\n if (chunk.bytes > (this.opts.maxBufferBytes ?? 1_000_000)) this.flush();\n else if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n this.flush();\n }, this.opts.flushIntervalMs ?? 10_000);\n }\n }\n\n /** Seals the buffer and uploads the backlog (one chunk at a time). */\n flush(): void {\n if (this.destroyed) return;\n this.seal();\n if (this.retryTimer || this.inflight || !this.queue.length) return;\n void this.sendNext();\n }\n\n /** Drops everything buffered or queued (consent withdrawn, server disabled replay). */\n discard(): void {\n this.buffer = null;\n this.queue = [];\n this.queuedBytes = 0;\n this.clearFlushTimer();\n this.clearRetry();\n this.attempt = 0;\n }\n\n /** Uploads what is left once; no retries afterwards. */\n destroy(): void {\n this.flush();\n this.destroyed = true;\n this.offRecover?.();\n this.clearFlushTimer();\n this.clearRetry();\n }\n\n private clearFlushTimer(): void {\n if (this.flushTimer) clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n private clearRetry(): void {\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n private scheduleRetry(ms: number): void {\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n this.flush();\n }, ms);\n }\n\n private seal(): void {\n this.clearFlushTimer();\n const chunk = this.buffer;\n this.buffer = null;\n if (!chunk || !chunk.events.length) return;\n this.queue.push(chunk);\n this.queuedBytes += chunk.bytes;\n const max = this.opts.maxQueuedBytes ?? 5_000_000;\n while (this.queuedBytes > max && this.queue.length > 1) {\n const i = this.inflight && this.queue[0] === this.inflight ? 1 : 0;\n const [dropped] = this.queue.splice(i, 1);\n if (!dropped) break;\n this.queuedBytes -= dropped.bytes;\n this.opts.log?.(`replay backlog full: dropped a chunk of ${dropped.events.length} events`);\n }\n }\n\n private nextSeq(chunk: Chunk): number {\n if (chunk.seq === undefined) {\n const seq = this.seqs.get(chunk.sessionId) ?? 0;\n this.seqs.set(chunk.sessionId, seq + 1);\n chunk.seq = seq;\n }\n return chunk.seq;\n }\n\n body(chunk: Chunk): string {\n const head = JSON.stringify({ sessionId: chunk.sessionId, windowId: this.windowId, seq: this.nextSeq(chunk), ...chunk.meta });\n return `${head.slice(0, -1)},\"events\":[${chunk.events.join(\",\")}]}`;\n }\n\n private async sendNext(): Promise<void> {\n const chunk = this.queue[0];\n if (!chunk) return;\n // The API is down: wait for its circuit instead of uploading into the void.\n const wait = this.destroyed ? 0 : (this.opts.health?.waitMs() ?? 0);\n if (wait > 0) return this.scheduleRetry(wait);\n this.inflight = chunk;\n const result = await this.upload(this.body(chunk));\n this.onResult(chunk, result);\n }\n\n private async upload(json: string): Promise<UploadResult> {\n const f = this.opts.fetch();\n if (!f) return \"drop\";\n const ac = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timer = ac ? setTimeout(() => ac.abort(), UPLOAD_TIMEOUT_MS) : null;\n try {\n let res: Response;\n try {\n res = await f(this.opts.url(), { method: \"POST\", body: json, headers: { \"Content-Type\": \"application/json\" }, signal: ac?.signal });\n } catch {\n this.opts.health?.failure();\n return \"retry\";\n }\n if (res.status === 429 || res.status >= 500) this.opts.health?.failure();\n else this.opts.health?.success();\n if (res.ok) {\n const data = (await res.json().catch(() => null)) as { disabled?: boolean } | null;\n return data?.disabled ? \"disabled\" : \"ok\";\n }\n return res.status >= 400 && res.status < 500 && res.status !== 429 ? \"drop\" : \"retry\";\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n private onResult(chunk: Chunk, result: UploadResult): void {\n if (this.inflight === chunk) this.inflight = null;\n if (result === \"retry\" && this.queue.includes(chunk)) {\n if (!this.destroyed) {\n // Quick retries first, then about once a minute (or as long as the circuit says).\n const max = this.opts.maxAttempts ?? 5;\n this.attempt = Math.min(this.attempt + 1, max);\n const delay = this.attempt >= max ? (this.opts.slowRetryMs ?? 60_000) : backoffMs(this.attempt - 1, 1000, 8000);\n return this.scheduleRetry(Math.max(delay, this.opts.health?.waitMs() ?? 0));\n }\n this.opts.log?.(\"replay upload failed after the recorder stopped; dropping the chunk\");\n }\n this.attempt = 0;\n this.remove(chunk);\n if (result === \"disabled\") {\n for (const c of this.queue.slice()) if (c.sessionId === chunk.sessionId) this.remove(c);\n if (this.buffer?.sessionId === chunk.sessionId) this.buffer = null;\n this.opts.onDisabled(chunk.sessionId);\n }\n // Keeps draining after destroy() so the last chunks still go out (without retries).\n if (this.queue.length && !this.retryTimer && !this.inflight) void this.sendNext();\n }\n\n private remove(chunk: Chunk): void {\n const i = this.queue.indexOf(chunk);\n if (i >= 0) {\n this.queue.splice(i, 1);\n this.queuedBytes -= chunk.bytes;\n }\n }\n}\n\nexport interface SessionRecorderOptions {\n capturer: ScreenCapturer;\n uploader: ReplayUploader;\n /** Time between screenshots (minimum 500 ms). */\n intervalMs: number;\n captureOptions: () => Promise<ReplayCaptureOptions> | ReplayCaptureOptions;\n href: () => string;\n now?: () => number;\n onError?: (err: unknown) => void;\n}\n\n/** Delay of the capture after a touch ends. */\nexport const TOUCH_SETTLE_MS = 200;\n/** Unchanged captures before the interval stretches. */\nexport const IDLE_FRAMES = 3;\n/** Longest stretched interval. */\nexport const MAX_IDLE_INTERVAL_MS = 5000;\n\n/**\n * Records one session at a time: a frame every interval while in the foreground, skipping frames\n * identical to the previous one; keyframes (Meta + FullSnapshot) for the first frame, a viewport\n * change, the first frame after the foreground returns and after `screen()`, mutations otherwise,\n * plus touches and Guidely markers. No capture while a finger is down; one {@link TOUCH_SETTLE_MS}\n * after every touch ends; after {@link IDLE_FRAMES} unchanged captures the interval stretches to\n * `min(4 × interval, 5 s)` until a changed frame, touch, `screen()` or Guidely event.\n */\nexport class SessionRecorder {\n private readonly intervalMs: number;\n private readonly now: () => number;\n private sid: string | null = null;\n private foreground = true;\n private generation = 0;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private timerDue = 0;\n private capturing = false;\n private needKeyframe = true;\n private hasKeyframe = false;\n private lastFrame: string | null = null;\n private unchanged = 0;\n private captureSoon = false;\n private pendingCustom: Array<[number, Record<string, unknown>]> = [];\n private touchDown = false;\n private downX = 0;\n private downY = 0;\n private downAt = 0;\n private maxDistance = 0;\n private lastMoveAt = 0;\n private originX = 0;\n private originY = 0;\n /** Viewport of the last frame (points), for chunk metadata. */\n viewportWidth = 0;\n viewportHeight = 0;\n\n constructor(private readonly opts: SessionRecorderOptions) {\n this.intervalMs = Math.max(500, opts.intervalMs);\n this.now = opts.now ?? Date.now;\n }\n\n get sessionId(): string | null {\n return this.sid;\n }\n\n get isRecording(): boolean {\n return this.sid !== null;\n }\n\n get currentIntervalMs(): number {\n return this.unchanged >= IDLE_FRAMES ? Math.max(this.intervalMs, Math.min(4 * this.intervalMs, MAX_IDLE_INTERVAL_MS)) : this.intervalMs;\n }\n\n /** Starts (or keeps) recording `sessionId`; another session stops the current one first (uploading it). */\n start(sessionId: string): void {\n if (this.sid === sessionId) return;\n if (this.sid !== null) this.stop(false);\n this.sid = sessionId;\n this.generation++;\n this.needKeyframe = true;\n this.hasKeyframe = false;\n this.lastFrame = null;\n this.unchanged = 0;\n this.captureSoon = false;\n this.pendingCustom = [];\n this.touchDown = false;\n if (this.foreground) this.schedule(0);\n }\n\n /** Stops recording; buffered events are uploaded unless `discard`. */\n stop(discard: boolean): void {\n if (this.sid === null) return;\n this.sid = null;\n this.generation++;\n this.clearTimer();\n this.capturing = false;\n this.pendingCustom = [];\n this.touchDown = false;\n if (discard) this.opts.uploader.discard();\n else this.opts.uploader.flush();\n }\n\n /** App backgrounded: no captures; uploads what is buffered. */\n pause(): void {\n this.foreground = false;\n this.clearTimer();\n this.generation++;\n this.capturing = false;\n this.touchDown = false;\n this.opts.uploader.flush();\n }\n\n /** App foregrounded: resume with a keyframe. */\n resume(): void {\n if (this.foreground) return;\n this.foreground = true;\n this.needKeyframe = true;\n this.unchanged = 0;\n if (this.sid !== null) this.schedule(0);\n }\n\n /** A new screen: the next frame is a keyframe with the new href. */\n onScreen(): void {\n if (this.sid === null) return;\n this.needKeyframe = true;\n this.activity();\n }\n\n private activity(): void {\n const wasIdle = this.unchanged >= IDLE_FRAMES;\n this.unchanged = 0;\n if (wasIdle && this.sid !== null && this.foreground && !this.capturing && !this.touchDown) this.schedule(this.intervalMs, true);\n }\n\n /** Adds the `guidely` marker for an analytics event. */\n addGuidelyEvent(name: string, customName?: string, guideId?: string): void {\n const id = this.sid;\n if (id === null) return;\n const payload: Record<string, unknown> = { name };\n if (customName) payload.customName = customName;\n if (guideId) payload.guideId = guideId;\n this.activity();\n const now = this.now();\n // Until the first keyframe the player has nothing to attach events to: hold them briefly.\n if (!this.hasKeyframe) {\n if (this.pendingCustom.length < 50) this.pendingCustom.push([now, payload]);\n return;\n }\n this.opts.uploader.push(id, RrwebEvents.custom(now, \"guidely\", payload));\n }\n\n /** A primary-pointer touch at (x, y) points from the React root view. */\n touch(phase: TouchPhase, rootX: number, rootY: number): void {\n const id = this.sid;\n if (id === null || !this.foreground) return;\n const x = rootX + this.originX;\n const y = rootY + this.originY;\n const now = this.now();\n const emit = this.hasKeyframe;\n const push = (json: string) => emit && this.opts.uploader.push(id, json);\n switch (phase) {\n case \"down\":\n this.touchDown = true;\n this.unchanged = 0;\n this.downX = x;\n this.downY = y;\n this.downAt = now;\n this.maxDistance = 0;\n this.lastMoveAt = now;\n push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_START, x, y));\n return;\n case \"move\":\n if (!this.touchDown) return;\n this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));\n if (now - this.lastMoveAt < 50) return;\n this.lastMoveAt = now;\n push(RrwebEvents.touchMove(now, x, y));\n return;\n default:\n if (!this.touchDown) return;\n this.touchDown = false;\n this.unchanged = 0;\n this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));\n push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_END, x, y));\n if (phase === \"up\" && this.maxDistance <= 10 && now - this.downAt < 1000) push(RrwebEvents.interaction(now, RrwebEvents.CLICK, x, y));\n // Show the result of the touch soon.\n if (this.capturing) this.captureSoon = true;\n else this.schedule(TOUCH_SETTLE_MS, true);\n }\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n\n /** Schedules the next capture `delay` ms from now, or keeps an earlier one when `ifSooner`. */\n private schedule(delay: number, ifSooner = false): void {\n const due = this.now() + delay;\n if (ifSooner && this.timer && this.timerDue <= due) return;\n this.clearTimer();\n this.timerDue = due;\n const gen = this.generation;\n this.timer = setTimeout(() => {\n this.timer = null;\n if (gen === this.generation) void this.tick();\n }, delay);\n }\n\n private async tick(): Promise<void> {\n if (this.sid === null || !this.foreground || this.capturing) return;\n if (this.touchDown) {\n // A capture would compete with the app's drag / scroll; touch end schedules one.\n this.schedule(this.intervalMs);\n return;\n }\n this.capturing = true;\n this.captureSoon = false;\n const gen = this.generation;\n let frame: ReplayFrame | null = null;\n try {\n frame = await this.opts.capturer(await this.opts.captureOptions());\n } catch (err) {\n this.opts.onError?.(err);\n }\n if (gen !== this.generation) return;\n this.capturing = false;\n // Stamped on delivery so events stay in timestamp order within a chunk.\n if (frame) this.onFrame(frame, this.now());\n if (this.sid !== null && this.foreground) this.schedule(this.captureSoon ? TOUCH_SETTLE_MS : this.currentIntervalMs);\n }\n\n private onFrame(frame: ReplayFrame, at: number): void {\n const id = this.sid;\n if (id === null || !(frame.width > 0) || !(frame.height > 0) || !frame.base64) return;\n const sizeChanged = frame.width !== this.viewportWidth || frame.height !== this.viewportHeight;\n const keyframe = this.needKeyframe || !this.hasKeyframe || sizeChanged;\n if (!keyframe && this.lastFrame === frame.base64) {\n this.unchanged++;\n return;\n }\n this.unchanged = 0;\n this.lastFrame = frame.base64;\n this.originX = frame.originX ?? 0;\n this.originY = frame.originY ?? 0;\n this.viewportWidth = frame.width;\n this.viewportHeight = frame.height;\n const url = RrwebEvents.dataUrl(frame.base64);\n const up = this.opts.uploader;\n if (!keyframe) return up.push(id, RrwebEvents.frame(at, url));\n this.needKeyframe = false;\n up.push(id, RrwebEvents.meta(at, this.opts.href(), frame.width, frame.height));\n up.push(id, RrwebEvents.fullSnapshot(at, url, frame.width, frame.height));\n if (!this.hasKeyframe) {\n this.hasKeyframe = true;\n for (const [ts, payload] of this.pendingCustom) up.push(id, RrwebEvents.custom(Math.max(ts, at), \"guidely\", payload));\n this.pendingCustom = [];\n }\n }\n}\n","import type { KeyValueStore } from \"@guidelytech/sdk-core/headless\";\nimport type { GuidelyStorage } from \"./types\";\n\n/**\n * Synchronous key/value view over asynchronous storage (AsyncStorage). Keys are loaded once with\n * {@link hydrate}; reads come from memory and writes go to memory immediately and to storage in the\n * background, so the engine can keep the web SDK's synchronous storage model. Never throws.\n */\nexport class PersistentStore implements KeyValueStore {\n private readonly cache = new Map<string, string>();\n private chain: Promise<unknown> = Promise.resolve();\n\n constructor(\n private readonly backing: GuidelyStorage | null,\n private readonly onError: (err: unknown) => void = () => {},\n ) {}\n\n async hydrate(keys: string[]): Promise<void> {\n if (!this.backing) return;\n await Promise.all(\n keys.map(async (k) => {\n try {\n const v = await this.backing!.getItem(k);\n if (v != null && !this.cache.has(k)) this.cache.set(k, v);\n } catch (err) {\n this.onError(err);\n }\n }),\n );\n }\n\n get(key: string): string | null {\n return this.cache.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n if (this.cache.get(key) === value) return;\n this.cache.set(key, value);\n this.write(() => this.backing?.setItem(key, value));\n }\n\n remove(key: string): void {\n if (!this.cache.has(key)) return;\n this.cache.delete(key);\n this.write(() => this.backing?.removeItem(key));\n }\n\n /** Resolves once every pending write has reached the backing storage. */\n flush(): Promise<void> {\n return this.chain.then(() => undefined);\n }\n\n private write(op: () => Promise<void> | void | undefined): void {\n if (!this.backing) return;\n // Serialised so a later write of the same key can never land before an earlier one.\n this.chain = this.chain.then(async () => {\n try {\n await op();\n } catch (err) {\n this.onError(err);\n }\n });\n }\n}\n","/**\n * Host app and OS versions, read from native modules the app already links (never imported, so none\n * of them is a dependency): `@guidelytech/react-native-replay`, `expo-application`, then\n * `react-native-device-info`. React Native itself has no API for the app's own version.\n */\n\nexport interface AppVersionInfo {\n /** `CFBundleShortVersionString` / `versionName`. */\n appVersion?: string;\n /** `CFBundleVersion` / `versionCode`. */\n appBuild?: string;\n}\n\n/** Where the lookups read from; the provider passes React Native's objects, tests pass fakes. */\nexport interface NativeSources {\n platform: { OS: string; Version?: string | number; constants?: Record<string, unknown> };\n nativeModules: Record<string, unknown>;\n /** `globalThis.expo.modules` in Expo SDK 50+ apps. */\n expoModules?: Record<string, unknown>;\n}\n\ntype Module = Record<string, unknown> & { getConstants?: () => Record<string, unknown> };\n\nfunction text(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n if (typeof value !== \"string\") return undefined;\n const v = value.trim();\n return v ? v.slice(0, 64) : undefined;\n}\n\n/**\n * Reads one constant: from `getConstants()` (TurboModules, new architecture), else the module's own\n * property (old architecture, Expo modules). Properties are read by name because JSI host objects\n * do not enumerate them.\n */\nfunction constant(mod: unknown, key: string): unknown {\n if (!mod || (typeof mod !== \"object\" && typeof mod !== \"function\")) return undefined;\n const m = mod as Module;\n try {\n const fromGetter = typeof m.getConstants === \"function\" ? m.getConstants()?.[key] : undefined;\n return fromGetter ?? m[key];\n } catch {\n // A module that throws here is treated as absent.\n return undefined;\n }\n}\n\nfunction read(mod: unknown, versionKey: string, buildKey: string): AppVersionInfo | null {\n const appVersion = text(constant(mod, versionKey));\n if (!appVersion) return null;\n const appBuild = text(constant(mod, buildKey));\n return { appVersion, ...(appBuild ? { appBuild } : {}) };\n}\n\n/** True inside Expo Go, where `expo-application` reports Expo Go's own version rather than the app's. */\nfunction inExpoGo(src: NativeSources): boolean {\n const c = src.expoModules?.ExponentConstants ?? src.nativeModules.ExponentConstants;\n return constant(c, \"executionEnvironment\") === \"storeClient\" || constant(c, \"appOwnership\") === \"expo\";\n}\n\n/** The host app's version and build, or `{}` when no linked module knows them. */\nexport function detectAppVersion(src: NativeSources): AppVersionInfo {\n try {\n const expo = inExpoGo(src) ? null : (src.expoModules?.ExpoApplication ?? src.nativeModules.ExpoApplication);\n return (\n read(src.nativeModules.GuidelyReplay, \"appVersion\", \"appBuild\") ??\n read(expo, \"nativeApplicationVersion\", \"nativeBuildVersion\") ??\n read(src.nativeModules.RNDeviceInfo, \"appVersion\", \"buildNumber\") ??\n {}\n );\n } catch {\n return {};\n }\n}\n\n/** The OS version: `18.1` on iOS, `14` on Android (falling back to the API level). */\nexport function detectOsVersion(src: NativeSources): string | undefined {\n try {\n const c = src.platform.constants ?? {};\n if (src.platform.OS === \"android\") return text(c.Release) ?? text(src.platform.Version);\n return text(c.osVersion) ?? text(src.platform.Version);\n } catch {\n return undefined;\n }\n}\n","import { useMemo, useRef, type ReactNode } from \"react\";\nimport { View, type GestureResponderEvent, type ViewProps } from \"react-native\";\nimport { TapTracker } from \"../core/autocapture\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { TouchPhase } from \"../core/replay\";\nimport { resolveTapTarget, type ResolveOptions } from \"../core/viewTree\";\nimport { GuidelyOverlay } from \"./Overlay\";\n\nexport interface GuidelyMaskProps extends ViewProps {\n children?: ReactNode;\n}\n\n/** `nativeID` the native replay module looks for: views carrying it are painted over in recordings. */\nexport const GUIDELY_MASK_NATIVE_ID = \"guidely-mask\";\n\n/**\n * Keeps its children out of product analytics and session replay: taps inside it (or on an element\n * that contains it) are captured without `text`, and recordings paint over it. Renders a plain `View`\n * (its `nativeID` is how the native recorder finds it).\n */\nexport function GuidelyMask({ children, ...rest }: GuidelyMaskProps) {\n return (\n <View collapsable={false} {...rest} nativeID={GUIDELY_MASK_NATIVE_ID}>\n {children}\n </View>\n );\n}\n\nconst RESOLVE: ResolveOptions = {\n isIgnored: (type) => type === GuidelyOverlay,\n isMask: (type) => type === GuidelyMask,\n};\n\ntype TouchHandler = (e: GestureResponderEvent) => void;\n\n/**\n * Capture-phase touch handlers for the provider's root view. They only observe: they never claim\n * the responder, stop propagation or delay anything, so the app's own touch handling is unchanged.\n */\nexport function useTapObserver(client: GuidelyClient | null): Partial<Record<\"onTouchStartCapture\" | \"onTouchMoveCapture\" | \"onTouchEndCapture\" | \"onTouchCancelCapture\", TouchHandler>> {\n const clientRef = useRef(client);\n clientRef.current = client;\n return useMemo(() => {\n const tracker = new TapTracker();\n /** Identifier of the finger a recording follows (the first one down). */\n let replayPointer: number | string | null = null;\n const replay = (phase: TouchPhase, e: GestureResponderEvent) => {\n const c = clientRef.current;\n const n = e.nativeEvent;\n if (!c?.isRecordingTouches()) return void (replayPointer = null);\n if (phase === \"down\") {\n if (replayPointer !== null) return;\n replayPointer = n.identifier;\n } else if (n.identifier !== replayPointer) return;\n if (phase === \"up\" || phase === \"cancel\") replayPointer = null;\n c.recordTouch(phase, n.pageX, n.pageY);\n };\n const guard = (fn: TouchHandler): TouchHandler => (e) => {\n try {\n fn(e);\n } catch {\n tracker.cancel(); // never throw into the app's touch handling\n }\n };\n return {\n onTouchStartCapture: guard((e) => {\n replay(\"down\", e);\n const n = e.nativeEvent;\n if (!clientRef.current?.isTapCaptureOn()) return tracker.cancel();\n tracker.begin(n.pageX, n.pageY, Date.now(), Array.isArray(n.touches) ? n.touches.length : 1, n.identifier);\n }),\n onTouchMoveCapture: guard((e) => {\n replay(\"move\", e);\n tracker.move(e.nativeEvent.pageX, e.nativeEvent.pageY, e.nativeEvent.identifier);\n }),\n onTouchEndCapture: guard((e) => {\n replay(\"up\", e);\n const n = e.nativeEvent;\n const tap = tracker.end(n.pageX, n.pageY, Date.now(), n.identifier);\n const c = clientRef.current;\n if (!tap || !c) return;\n // Resolved now: the event's target is released after dispatch and the view may unmount.\n const r = resolveTapTarget(e, RESOLVE);\n if (!r.ignored) c.recordTap({ x: tap.x, y: tap.y, t: Date.now(), element: r.element, hit: r.hit });\n }),\n onTouchCancelCapture: guard((e) => {\n replay(\"cancel\", e);\n tracker.cancel();\n }),\n };\n }, []);\n}\n","/**\n * Best-effort identification of the view a tap landed on, from React's component tree.\n *\n * React Native has no public \"which component is under this point\" API, so the touch observer\n * reads the event's target fiber (`event._targetInst`, or the host instance's internal handle) and\n * walks it. Everything here is defensive: React internals can change between versions, and any\n * surprise yields \"unknown\" instead of an exception.\n */\nimport { attrSelector, cleanText, type TapElement } from \"./autocapture\";\nimport type { Rect } from \"./targets\";\n\n/** The fields of a React fiber this module reads. */\nexport interface FiberLike {\n tag?: number;\n type?: unknown;\n memoizedProps?: any;\n return?: FiberLike | null;\n child?: FiberLike | null;\n sibling?: FiberLike | null;\n stateNode?: any;\n}\n\nexport interface ResolveOptions {\n /** Guidely's own UI (overlay): taps inside it are never captured. */\n isIgnored?: (type: unknown) => boolean;\n /** `<GuidelyMask>`: text inside (or around) it is never captured. */\n isMask?: (type: unknown) => boolean;\n}\n\nexport interface ResolvedTap {\n /** The tap landed in Guidely's own UI. */\n ignored: boolean;\n /** Innermost interactive element (touchable / `Pressable` / `onPress` / `accessibilityRole=\"button\"`…). */\n element: TapElement | null;\n /** The view that was hit (its nearest named component), for rage taps and heatmaps. */\n hit: TapElement | null;\n}\n\nconst HOST_TEXT = 6;\nconst MAX_ANCESTORS = 500;\nconst MAX_TEXT_NODES = 300;\nconst INTERACTIVE_ROLES = new Set([\"button\", \"link\", \"tab\", \"menuitem\", \"checkbox\", \"switch\", \"radio\", \"togglebutton\", \"imagebutton\", \"option\", \"combobox\", \"adjustable\"]);\nconst TEXT_INPUT_HOST = /TextInput/i;\n/** Wrappers that say nothing about where a view is. */\nconst NOISE = /^(Anonymous|Unknown|ForwardRef|Memo|Context|Provider|Consumer|Fragment|StrictMode|Suspense|Profiler)$|Context$|Provider$|Consumer$/;\n\nconst isFiber = (v: unknown): v is FiberLike => !!v && typeof v === \"object\" && \"return\" in (v as object) && \"memoizedProps\" in (v as object);\n\n/** The tap target's fiber from a React Native touch event, or null. */\nexport function fiberFromEvent(event: unknown): FiberLike | null {\n try {\n const e = event as { _targetInst?: unknown; target?: unknown } | null;\n if (isFiber(e?._targetInst)) return e._targetInst;\n const target = e?.target as Record<string | symbol, unknown> | null | undefined;\n if (!target || typeof target !== \"object\") return null;\n for (const key of [\"__internalInstanceHandle\", \"_internalInstanceHandle\", \"_internalFiberInstanceHandleDEV\"]) if (isFiber(target[key])) return target[key] as FiberLike;\n for (const sym of Object.getOwnPropertySymbols(target)) if (sym.description === \"internalInstanceHandle\" && isFiber(target[sym])) return target[sym] as FiberLike;\n } catch {\n /* unknown renderer internals */\n }\n return null;\n}\n\n/** Component name of a fiber type (`Pressable`, `TouchableOpacity`, `Text`…); null for host components and anonymous wrappers. */\nexport function componentName(type: unknown, depth = 0): string | null {\n if (!type || depth > 3) return null;\n if (typeof type === \"function\") {\n const f = type as { displayName?: unknown; name?: unknown };\n const n = typeof f.displayName === \"string\" && f.displayName ? f.displayName : typeof f.name === \"string\" ? f.name : \"\";\n return n || null;\n }\n if (typeof type === \"object\") {\n const o = type as { displayName?: unknown; render?: unknown; type?: unknown };\n if (typeof o.displayName === \"string\" && o.displayName) return o.displayName;\n return componentName(o.render, depth + 1) ?? componentName(o.type, depth + 1);\n }\n return null;\n}\n\nconst isHost = (f: FiberLike) => typeof f.type === \"string\";\nconst isTextInput = (f: FiberLike) => (typeof f.type === \"string\" ? TEXT_INPUT_HOST.test(f.type) : componentName(f.type) === \"TextInput\");\n\nfunction isInteractive(props: any): \"press\" | \"role\" | null {\n if (!props || typeof props !== \"object\") return null;\n if (typeof props.onPress === \"function\" || typeof props.onLongPress === \"function\") return \"press\";\n const role = props.accessibilityRole ?? props.role;\n return typeof role === \"string\" && INTERACTIVE_ROLES.has(role) ? \"role\" : null;\n}\n\n/** First host-component fiber at or below `f` along first children. */\nfunction firstHost(f: FiberLike): FiberLike | null {\n let cur: FiberLike | null | undefined = f;\n for (let i = 0; cur && i < 30; i++, cur = cur.child) if (isHost(cur)) return cur;\n return null;\n}\n\n/** `[nativeID=\"…\"]` / `[testID=\"…\"]` from the component's or its host view's props. */\nfunction idSelector(f: FiberLike): string | null {\n const host = firstHost(f);\n const sources = [f.memoizedProps, host?.memoizedProps];\n for (const key of [\"nativeID\", \"testID\"]) {\n for (const p of sources) {\n const v = p && typeof p === \"object\" ? p[key] : undefined;\n if (typeof v === \"string\" && v) return attrSelector(key, v);\n }\n }\n return null;\n}\n\n/** Short component path, at most 4 named levels, innermost last, `Name:nth-of-type(n)` when siblings share the type. */\nexport function pathSelector(f: FiberLike): string {\n const parts: string[] = [];\n let cur: FiberLike | null | undefined = f;\n for (let i = 0; cur && parts.length < 4 && i < MAX_ANCESTORS; i++, cur = cur.return) {\n if (isHost(cur)) continue;\n const name = componentName(cur.type);\n if (!name || NOISE.test(name)) continue;\n let same = 0;\n let index = 0;\n for (let s: FiberLike | null | undefined = cur.return?.child, n = 0; s && n < 500; s = s.sibling, n++) {\n if (s.type !== cur.type) continue;\n same += 1;\n if (s === cur) index = same;\n }\n parts.unshift(same > 1 && index ? `${name}:nth-of-type(${index})` : name);\n }\n return parts.join(\" > \").slice(0, 300) || \"View\";\n}\n\n/** Visible text below `f` (raw text nodes), skipping text fields; `masked` when a mask is inside. */\nfunction subtreeText(f: FiberLike, opts: ResolveOptions): { text: string; masked: boolean } {\n const out: string[] = [];\n let visited = 0;\n let masked = false;\n const walk = (node: FiberLike | null | undefined): void => {\n for (let n = node; n && visited < MAX_TEXT_NODES && !masked; n = n.sibling) {\n visited += 1;\n if (opts.isMask?.(n.type)) {\n masked = true;\n return;\n }\n if (isTextInput(n)) continue;\n if (n.tag === HOST_TEXT && (typeof n.memoizedProps === \"string\" || typeof n.memoizedProps === \"number\")) out.push(String(n.memoizedProps));\n else walk(n.child);\n }\n };\n if (opts.isMask?.(f.type)) return { text: \"\", masked: true };\n walk(f.child);\n return { text: out.join(\" \"), masked };\n}\n\n/** Window frame of a host view (Paper instance, Fabric public instance, or the Fabric UI manager). */\nfunction measureHost(host: FiberLike): Promise<Rect | null> {\n return new Promise((resolve) => {\n let settled = false;\n const done = (r: Rect | null) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(r);\n };\n const timer = setTimeout(() => done(null), 500);\n const cb = (x: number, y: number, width: number, height: number) => done(Number.isFinite(x) && Number.isFinite(y) && width > 0 && height > 0 ? { x, y, width, height } : null);\n try {\n const sn = host.stateNode;\n const pub = sn?.canonical?.publicInstance ?? sn;\n if (pub && typeof pub.measureInWindow === \"function\") return pub.measureInWindow(cb);\n const ui = (globalThis as { nativeFabricUIManager?: { measureInWindow?: (node: unknown, callback: (x: number, y: number, width: number, height: number) => void) => void } }).nativeFabricUIManager;\n if (sn?.node && typeof ui?.measureInWindow === \"function\") return ui.measureInWindow(sn.node, cb);\n } catch {\n /* fall through */\n }\n done(null);\n });\n}\n\nfunction describe(f: FiberLike, masked: boolean, opts: ResolveOptions, withText: boolean): TapElement {\n const props = f.memoizedProps && typeof f.memoizedProps === \"object\" ? f.memoizedProps : {};\n const host = firstHost(f);\n const el: TapElement = { selector: idSelector(f) ?? pathSelector(f), tag: componentName(f.type) ?? \"View\" };\n if (withText && !masked) {\n const sub = subtreeText(f, opts);\n if (!sub.masked) {\n const hostProps = host?.memoizedProps && typeof host.memoizedProps === \"object\" ? host.memoizedProps : {};\n const label = props.accessibilityLabel ?? props[\"aria-label\"] ?? hostProps.accessibilityLabel ?? hostProps[\"aria-label\"];\n const text = cleanText(sub.text) ?? (typeof label === \"string\" ? cleanText(label) : undefined);\n if (text) el.text = text;\n }\n }\n if (host) el.measure = () => measureHost(host);\n return el;\n}\n\n/**\n * Resolves a tap from its target fiber: whether it hit Guidely's UI, the innermost interactive\n * element (a component with `onPress` / `onLongPress`; else one with an interactive\n * `accessibilityRole`) and the hit view. Taps inside a `TextInput` have no interactive element.\n */\nexport function resolveFiber(target: FiberLike | null, opts: ResolveOptions = {}): ResolvedTap {\n const none: ResolvedTap = { ignored: false, element: null, hit: null };\n if (!target) return none;\n try {\n let press: FiberLike | null = null;\n let role: FiberLike | null = null;\n let hitFiber: FiberLike | null = null;\n let stopped = false;\n // A mask anywhere on the path from the tapped view to the root hides the text.\n let masked = false;\n for (let f: FiberLike | null | undefined = target, i = 0; f && i < MAX_ANCESTORS; f = f.return, i++) {\n if (opts.isIgnored?.(f.type)) return { ignored: true, element: null, hit: null };\n if (opts.isMask?.(f.type)) masked = true;\n if (stopped) continue;\n if (isTextInput(f)) {\n stopped = true;\n continue;\n }\n if (isHost(f)) continue;\n const name = componentName(f.type);\n if (!hitFiber && name && !NOISE.test(name)) hitFiber = f;\n const kind = isInteractive(f.memoizedProps);\n if (kind === \"press\") {\n press = f;\n stopped = true;\n } else if (kind === \"role\" && !role) role = f;\n }\n const element = press ?? role;\n return {\n ignored: false,\n element: element ? describe(element, masked, opts, true) : null,\n hit: hitFiber ? describe(hitFiber, masked, opts, componentName(hitFiber.type) === \"Text\") : null,\n };\n } catch {\n return none;\n }\n}\n\n/** {@link resolveFiber} for a touch event; never throws. */\nexport function resolveTapTarget(event: unknown, opts: ResolveOptions = {}): ResolvedTap {\n return resolveFiber(fiberFromEvent(event), opts);\n}\n","import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Platform, Pressable, StatusBar, StyleSheet, Text, useColorScheme, useWindowDimensions, View } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { Insets } from \"../core/position\";\nimport { Checklist } from \"./Checklist\";\nimport { LAUNCHER_SIZE, MessengerLauncher, MessengerSheet } from \"./Messenger\";\nimport { ResourceCenter } from \"./ResourceCenter\";\nimport { StepLayer, type LayerGeometry } from \"./StepLayer\";\nimport { Survey } from \"./Survey\";\nimport { palette } from \"./theme\";\n\n/** Best-effort safe-area insets when the app does not pass real ones (e.g. from react-native-safe-area-context). */\nfunction defaultInsets(width: number, height: number): Insets {\n if (Platform.OS === \"ios\") {\n const notch = Math.max(width, height) >= 812 && !Platform.isPad;\n const landscape = width > height;\n return { top: landscape ? 0 : notch ? 50 : 20, bottom: notch ? (landscape ? 21 : 34) : 0, left: landscape && notch ? 44 : 0, right: landscape && notch ? 44 : 0 };\n }\n return { top: StatusBar.currentHeight ?? 24, bottom: 16, left: 0, right: 0 };\n}\n\nexport interface OverlayProps {\n client: GuidelyClient;\n insets?: Partial<Insets>;\n /** Distance of the checklist launcher above the bottom inset (clears tab bars). */\n launcherOffset: number;\n}\n\n/**\n * Draws everything the client wants on screen, above the app. `pointerEvents=\"box-none\"` keeps the\n * app fully interactive except where guide UI (or a modal backdrop) is shown.\n */\nexport function GuidelyOverlay({ client, insets: insetsProp, launcherOffset }: OverlayProps) {\n const ui = useSyncExternalStore(\n useCallback((cb) => client.subscribeUi(cb), [client]),\n () => client.getUiState(),\n () => client.getUiState(),\n );\n const { width, height } = useWindowDimensions();\n const scheme = useColorScheme();\n const ref = useRef<View>(null);\n const [origin, setOrigin] = useState({ x: 0, y: 0 });\n\n useEffect(() => {\n client.targets.setViewport(width, height);\n }, [client, width, height]);\n\n const measureOrigin = useCallback(() => {\n ref.current?.measureInWindow?.((x, y) => {\n if (Number.isFinite(x) && Number.isFinite(y)) setOrigin((o) => (o.x === x && o.y === y ? o : { x, y }));\n });\n }, []);\n\n const insets: Insets = { ...defaultInsets(width, height), ...insetsProp };\n const geometry: LayerGeometry = { origin, viewport: { width, height }, insets };\n const basePalette = palette(ui.theme, scheme);\n const messenger = ui.messenger ? client.getMessenger() : null;\n const showRcLauncher = !messenger && !!client.options.showResourceCenterLauncher && !!client.getResourceCenter();\n // \"What's new\" entries published since the visitor last opened the resource center.\n const unread = showRcLauncher ? client.getUnreadAnnouncements() : 0;\n const messengerLeft = messenger?.getSnapshot().config.launcher.position === \"bottom-left\";\n // The chat bubble stacks above a checklist launcher on the same side.\n const checklistOnSameSide = ui.checklists.some((c) => (c.guide.config.checklist?.position === \"bottom-left\") === messengerLeft) && client.options.showChecklistLauncher !== false;\n // Default bubble position, and the lowest a dragged bubble may rest (clears tab bars).\n const messengerBottom = insets.bottom + launcherOffset + (checklistOnSameSide ? 56 : 0);\n\n return (\n <View ref={ref} collapsable={false} pointerEvents=\"box-none\" style={StyleSheet.absoluteFill} onLayout={measureOrigin}>\n {ui.checklists.map((c) => (\n <Checklist key={c.guide.id} view={c} client={client} palette={palette(client.themeFor(c.guide), scheme)} geometry={geometry} showLauncher={client.options.showChecklistLauncher !== false} launcherBottom={launcherOffset} />\n ))}\n {showRcLauncher ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={rcLauncherLabel(client)}\n onPress={() => client.openResourceCenter()}\n style={[styles.rc, client.getResourceCenter()?.launcher.position === \"bottom-left\" ? { left: insets.left + 16 } : { right: insets.right + 16 }, { bottom: insets.bottom + launcherOffset + (ui.checklists.length ? 56 : 0), backgroundColor: basePalette.primary }]}\n >\n <Text style={[styles.rcText, { color: basePalette.onPrimary }]}>?</Text>\n {unread ? (\n <View pointerEvents=\"none\" style={[styles.rcBadge, { borderColor: basePalette.primary }]}>\n <Text style={styles.rcBadgeText}>{unread > 9 ? \"9+\" : unread}</Text>\n </View>\n ) : null}\n </Pressable>\n ) : null}\n {messenger && client.options.showMessengerLauncher !== false ? (\n <MessengerLauncher\n store={messenger}\n client={client}\n palette={basePalette}\n style={[messengerLeft ? { left: insets.left + 16 } : { right: insets.right + 16 }, { bottom: messengerBottom }]}\n frame={{ width, height, insets, size: LAUNCHER_SIZE, defaultBottom: messengerBottom }}\n defaultSide={messengerLeft ? \"left\" : \"right\"}\n />\n ) : null}\n {ui.survey ? <Survey view={ui.survey} client={client} palette={palette(client.themeFor(ui.survey.guide), scheme)} geometry={geometry} /> : null}\n {ui.steps.map((s) => (\n <StepLayer key={s.key} view={s} client={client} palette={palette(client.themeFor(s.guide), scheme, s.guide.config.appearance)} geometry={geometry} />\n ))}\n {messenger ? <MessengerSheet store={messenger} client={client} palette={basePalette} topInset={insets.top} bottomInset={insets.bottom} /> : <ResourceCenter client={client} palette={basePalette} open={ui.resourceCenterOpen} topInset={insets.top} bottomInset={insets.bottom} />}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n rc: { position: \"absolute\", width: 48, height: 48, borderRadius: 24, alignItems: \"center\", justifyContent: \"center\", elevation: 8, shadowColor: \"#000\", shadowOpacity: 0.2, shadowRadius: 10, shadowOffset: { width: 0, height: 4 } },\n rcText: { fontSize: 22, fontWeight: \"800\" },\n rcBadge: { position: \"absolute\", top: -4, right: -4, minWidth: 20, height: 20, paddingHorizontal: 5, borderRadius: 10, borderWidth: 2, backgroundColor: \"#dc2626\", alignItems: \"center\", justifyContent: \"center\" },\n rcBadgeText: { color: \"#ffffff\", fontSize: 11, fontWeight: \"800\" },\n});\n\nfunction rcLauncherLabel(client: GuidelyClient): string {\n const label = client.getResourceCenter()?.launcher.label || \"Help\";\n const unread = client.getUnreadAnnouncements();\n return unread ? `${label} (${unread} new update${unread === 1 ? \"\" : \"s\"})` : label;\n}\n","import { Pressable, ScrollView, StyleSheet, Text, View } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { ChecklistView } from \"../core/types\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { LayerGeometry } from \"./StepLayer\";\nimport type { Palette } from \"./theme\";\n\n/** Floating launcher pill + task panel for one checklist guide. */\nexport function Checklist({ view, client, palette: p, geometry, showLauncher, launcherBottom }: { view: ChecklistView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry; showLauncher: boolean; launcherBottom: number }) {\n const config = view.guide.config.checklist;\n if (!config) return null;\n const done = new Set(view.progress.completedTaskIds);\n const total = config.tasks.length;\n const completed = config.tasks.filter((t) => done.has(t.id)).length;\n const finished = !!view.progress.completedAt;\n const left = config.position === \"bottom-left\";\n const { insets, viewport } = geometry;\n const side = left ? { left: insets.left + 16 } : { right: insets.right + 16 };\n const width = Math.min(viewport.width - insets.left - insets.right - 32, 360);\n const nextOpen = config.ordered ? config.tasks.find((t) => !done.has(t.id))?.id : undefined;\n const bottom = insets.bottom + launcherBottom;\n\n return (\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n {view.open ? (\n <Surface palette={p} style={[styles.panel, side, { width, bottom: bottom + (showLauncher ? 56 : 0), maxHeight: viewport.height - insets.top - bottom - 80 }]}>\n <View accessibilityViewIsModal style={styles.panelInner}>\n <View style={styles.head}>\n <View style={styles.flex}>\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {finished ? config.completionTitle : config.launcherLabel}\n </Text>\n <Text style={[styles.sub, { color: p.muted }]}>\n {completed} of {total} complete\n </Text>\n </View>\n <CloseButton palette={p} onPress={() => client.setChecklistOpen(view.guide.id, false)} label=\"Close checklist\" />\n </View>\n <View style={[styles.bar, { backgroundColor: p.surface }]} accessibilityRole=\"progressbar\" accessibilityValue={{ min: 0, max: total, now: completed }}>\n <View style={[styles.fill, { backgroundColor: p.primary, width: `${total ? (completed / total) * 100 : 0}%` }]} />\n </View>\n {finished && config.completionBody ? <RichText html={config.completionBody} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n <ScrollView style={styles.tasks} contentContainerStyle={styles.tasksContent}>\n {config.tasks.map((task) => {\n const isDone = done.has(task.id);\n const locked = !!nextOpen && !isDone && task.id !== nextOpen;\n return (\n <Pressable\n key={task.id}\n disabled={locked}\n accessibilityRole=\"button\"\n accessibilityState={{ checked: isDone, disabled: locked }}\n accessibilityLabel={`${task.title}${isDone ? \", done\" : \"\"}`}\n onPress={() => client.checklistTaskPressed(view.guide.id, task.id)}\n style={({ pressed }) => [styles.task, { borderColor: p.border, opacity: locked ? 0.5 : pressed ? 0.7 : 1 }]}\n >\n <View style={[styles.check, isDone ? { backgroundColor: p.primary, borderColor: p.primary } : { borderColor: p.border }]}>{isDone ? <Text style={[styles.tick, { color: p.onPrimary }]}>✓</Text> : null}</View>\n <View style={styles.flex}>\n <Text style={[styles.taskTitle, { color: p.text, fontFamily: p.fontFamily }, isDone && { textDecorationLine: \"line-through\", color: p.muted }]}>\n {task.title}\n {!task.required ? <Text style={{ color: p.muted, fontWeight: \"400\" }}> (optional)</Text> : null}\n </Text>\n {task.description ? <Text style={[styles.taskDesc, { color: p.muted }]}>{task.description}</Text> : null}\n </View>\n </Pressable>\n );\n })}\n </ScrollView>\n {config.dismissible ? <GButton label={finished ? \"Close for good\" : \"Dismiss checklist\"} variant=\"ghost\" palette={p} onPress={() => client.dismissChecklist(view.guide.id)} style={styles.dismiss} /> : null}\n </View>\n </Surface>\n ) : null}\n {showLauncher ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={`${config.launcherLabel}, ${completed} of ${total} complete`}\n accessibilityState={{ expanded: view.open }}\n onPress={() => client.setChecklistOpen(view.guide.id, !view.open)}\n style={({ pressed }) => [styles.launcher, side, { bottom, backgroundColor: p.primary, opacity: pressed ? 0.85 : 1 }]}\n >\n <View style={[styles.count, { borderColor: p.onPrimary }]}>\n <Text style={[styles.countText, { color: p.onPrimary }]}>{finished ? \"✓\" : `${completed}/${total}`}</Text>\n </View>\n <Text style={[styles.launcherText, { color: p.onPrimary, fontFamily: p.fontFamily }]} numberOfLines={1}>\n {config.launcherLabel}\n </Text>\n </Pressable>\n ) : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n panel: { position: \"absolute\" },\n panelInner: { padding: 16, gap: 10, flexShrink: 1 },\n head: { flexDirection: \"row\", alignItems: \"flex-start\", gap: 8 },\n title: { fontSize: 17, fontWeight: \"700\" },\n sub: { fontSize: 13, marginTop: 2 },\n bar: { height: 6, borderRadius: 3, overflow: \"hidden\" },\n fill: { height: 6, borderRadius: 3 },\n tasks: { flexGrow: 0 },\n tasksContent: { gap: 8 },\n task: { flexDirection: \"row\", gap: 10, alignItems: \"flex-start\", borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, padding: 10 },\n check: { width: 22, height: 22, borderRadius: 11, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\", marginTop: 1 },\n tick: { fontSize: 13, fontWeight: \"800\" },\n taskTitle: { fontSize: 15, fontWeight: \"600\" },\n taskDesc: { fontSize: 13, marginTop: 2 },\n dismiss: { alignSelf: \"center\" },\n launcher: {\n position: \"absolute\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 8,\n paddingVertical: 10,\n paddingHorizontal: 14,\n borderRadius: 24,\n shadowColor: \"#000\",\n shadowOpacity: 0.22,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 4 },\n elevation: 8,\n maxWidth: 240,\n },\n count: { minWidth: 30, height: 22, borderRadius: 11, borderWidth: 1.5, alignItems: \"center\", justifyContent: \"center\", paddingHorizontal: 4 },\n countText: { fontSize: 11, fontWeight: \"700\" },\n launcherText: { fontSize: 14, fontWeight: \"700\", flexShrink: 1 },\n});\n","import type { ReactNode } from \"react\";\nimport { Pressable, StyleSheet, Text, View, type StyleProp, type ViewStyle } from \"react-native\";\nimport type { Palette } from \"./theme\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"link\";\n\nexport function GButton({ label, variant = \"primary\", onPress, palette: p, style, accessibilityHint, disabled }: { label: string; variant?: ButtonVariant; onPress: () => void; palette: Palette; style?: StyleProp<ViewStyle>; accessibilityHint?: string; disabled?: boolean }) {\n const filled = variant === \"primary\";\n const outlined = variant === \"secondary\";\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n accessibilityHint={accessibilityHint}\n accessibilityState={{ disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n hitSlop={6}\n style={({ pressed }) => [\n styles.btn,\n { borderRadius: Math.min(p.radius, 10), opacity: disabled ? 0.5 : pressed ? 0.75 : 1 },\n filled && { backgroundColor: p.primary },\n outlined && { borderWidth: 1, borderColor: p.border, backgroundColor: p.background },\n variant === \"link\" && styles.link,\n style,\n ]}\n >\n <Text style={[styles.btnText, { color: filled ? p.onPrimary : variant === \"link\" ? p.primary : variant === \"ghost\" ? p.muted : p.text, fontFamily: p.fontFamily }, variant === \"link\" && styles.underline]} numberOfLines={1}>\n {label}\n </Text>\n </Pressable>\n );\n}\n\nexport function CloseButton({ onPress, palette: p, label = \"Close\" }: { onPress: () => void; palette: Palette; label?: string }) {\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={10} style={({ pressed }) => [styles.close, { opacity: pressed ? 0.6 : 1 }]}>\n <Text style={[styles.closeText, { color: p.muted }]}>×</Text>\n </Pressable>\n );\n}\n\n/** Rounded surface with a soft shadow. */\nexport function Surface({ palette: p, children, style }: { palette: Palette; children: ReactNode; style?: StyleProp<ViewStyle> }) {\n return <View style={[styles.surface, { backgroundColor: p.background, borderRadius: p.radius, borderColor: p.border }, style]}>{children}</View>;\n}\n\nconst styles = StyleSheet.create({\n btn: { minHeight: 36, paddingHorizontal: 14, paddingVertical: 8, alignItems: \"center\", justifyContent: \"center\" },\n link: { paddingHorizontal: 4 },\n btnText: { fontSize: 14, fontWeight: \"600\" },\n underline: { textDecorationLine: \"underline\" },\n close: { width: 28, height: 28, alignItems: \"center\", justifyContent: \"center\", marginTop: -4, marginRight: -6 },\n closeText: { fontSize: 24, lineHeight: 26, fontWeight: \"400\" },\n surface: {\n borderWidth: StyleSheet.hairlineWidth,\n shadowColor: \"#000\",\n shadowOpacity: 0.18,\n shadowRadius: 18,\n shadowOffset: { width: 0, height: 8 },\n elevation: 10,\n },\n});\n","import { useEffect, useMemo, useState } from \"react\";\nimport { Image, Modal, Platform, Pressable, ScrollView, StyleSheet, Text, View, type NativeScrollEvent, type NativeSyntheticEvent, type TextStyle } from \"react-native\";\nimport { parseHtml, type PdfPage, type TextBlock, type TextRun } from \"../core/html\";\nimport type { Palette } from \"./theme\";\n\nconst MONO = Platform.select({ ios: \"Menlo\", android: \"monospace\", default: \"monospace\" });\nconst HEADING_SIZE = [0, 20, 17, 15] as const;\n\nfunction runStyle(run: TextRun, p: Palette): TextStyle {\n return {\n fontWeight: run.bold ? \"700\" : undefined,\n fontStyle: run.italic ? \"italic\" : undefined,\n textDecorationLine: run.underline || run.href ? \"underline\" : undefined,\n fontFamily: run.code ? MONO : undefined,\n backgroundColor: run.code ? p.surface : undefined,\n color: run.href ? p.primary : undefined,\n };\n}\n\n/** Full-width image that keeps its aspect ratio (from width/height attributes, else measured). */\nfunction BodyImage({ block, palette: p }: { block: TextBlock; palette: Palette }) {\n const [ratio, setRatio] = useState(block.width && block.height ? block.width / block.height : 16 / 9);\n useEffect(() => {\n if (block.width && block.height) return;\n let live = true;\n Image.getSize(block.src as string, (w, h) => live && w > 0 && h > 0 && setRatio(w / h), () => {});\n return () => {\n live = false;\n };\n }, [block.src, block.width, block.height]);\n return <Image source={{ uri: block.src }} accessible accessibilityRole=\"image\" accessibilityLabel={block.alt || undefined} resizeMode=\"contain\" style={[styles.image, { aspectRatio: ratio, backgroundColor: p.surface }]} />;\n}\n\n/** Videos open outside the app (the browser or the provider's app) rather than playing inline. */\nfunction BodyVideo({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n return (\n <Pressable accessibilityRole=\"link\" accessibilityLabel={block.alt} onPress={() => onLink(block.href as string)} style={({ pressed }) => [styles.video, { borderColor: p.border, backgroundColor: p.surface, opacity: pressed ? 0.7 : 1 }]}>\n <Text style={[styles.play, { color: p.primary }]}>▶</Text>\n <Text style={{ color: p.primary, fontFamily: p.fontFamily, fontWeight: \"600\" }}>{block.alt}</Text>\n </Pressable>\n );\n}\n\n/** A4 portrait, for pages without a stored size. */\nconst PAGE_RATIO = 1 / 1.414;\nconst pageRatio = (p: PdfPage) => (p.width && p.height ? p.width / p.height : PAGE_RATIO);\n\nfunction PdfBadge() {\n return (\n <View style={styles.badge}>\n <Text style={styles.badgeText}>PDF</Text>\n </View>\n );\n}\n\n/** A PDF that couldn't be shown page by page: a card that opens it. */\nfunction BodyFile({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n return (\n <Pressable accessibilityRole=\"link\" accessibilityLabel={`${block.alt}, PDF`} onPress={() => onLink(block.href as string)} style={({ pressed }) => [styles.video, { borderColor: p.border, backgroundColor: p.surface, opacity: pressed ? 0.7 : 1 }]}>\n <PdfBadge />\n <Text numberOfLines={2} ellipsizeMode=\"middle\" style={[styles.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: \"600\" }]}>{block.alt}</Text>\n </Pressable>\n );\n}\n\n/**\n * A PDF read in place: its pages swipe sideways with a page counter, and a tap opens every page in a\n * full-screen reader with the original PDF one button away. Nothing downloads.\n */\nfunction BodyPdf({ block, palette: p, onLink }: { block: TextBlock; palette: Palette; onLink: (url: string) => void }) {\n const pages = block.pages ?? [];\n const [width, setWidth] = useState(0);\n const [index, setIndex] = useState(0);\n const [reading, setReading] = useState(false);\n // Every page gets the tallest page's height, so swiping never resizes the article.\n const height = width ? Math.max(...pages.map((pg) => width / pageRatio(pg))) : 0;\n const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => width && setIndex(Math.round(e.nativeEvent.contentOffset.x / width));\n return (\n <View style={[styles.pdf, { borderColor: p.border, backgroundColor: p.surface }]}>\n <Pressable accessibilityRole=\"button\" accessibilityLabel={`Read ${block.alt} full screen`} onPress={() => setReading(true)} style={({ pressed }) => [styles.pdfHeader, { opacity: pressed ? 0.7 : 1 }]}>\n <PdfBadge />\n <Text numberOfLines={1} ellipsizeMode=\"middle\" style={[styles.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: \"600\" }]}>{block.alt}</Text>\n <Text style={{ color: p.muted, fontSize: 16 }}>⤢</Text>\n </Pressable>\n <View style={styles.pdfPages} onLayout={(e) => setWidth(e.nativeEvent.layout.width)}>\n {width > 0 && (\n <ScrollView horizontal pagingEnabled showsHorizontalScrollIndicator={false} onScroll={onScroll} scrollEventThrottle={32} accessibilityLabel={`${block.alt}, page ${index + 1} of ${pages.length}`}>\n {pages.map((pg, i) => (\n <Pressable key={i} onPress={() => setReading(true)} accessibilityRole=\"imagebutton\" accessibilityLabel={pg.alt || `Page ${i + 1}`} accessibilityHint=\"Opens the document full screen\" style={{ width, height, alignItems: \"center\", justifyContent: \"center\" }}>\n <Image source={{ uri: pg.src }} resizeMode=\"contain\" style={[styles.page, { width: Math.min(width, height * pageRatio(pg)), aspectRatio: pageRatio(pg) }]} />\n </Pressable>\n ))}\n </ScrollView>\n )}\n {pages.length > 1 && (\n <View pointerEvents=\"none\" style={styles.count}>\n <Text style={styles.countText}>{index + 1} / {pages.length}</Text>\n </View>\n )}\n </View>\n <Modal visible={reading} animationType=\"slide\" presentationStyle=\"fullScreen\" onRequestClose={() => setReading(false)}>\n <View style={styles.reader}>\n <View style={styles.readerBar}>\n <Text numberOfLines={1} ellipsizeMode=\"middle\" style={[styles.flex, styles.readerTitle]} accessibilityRole=\"header\">{block.alt}</Text>\n <Pressable accessibilityRole=\"link\" onPress={() => onLink(block.href as string)} style={styles.readerBtn}>\n <Text style={styles.readerBtnText}>Open PDF ↗</Text>\n </Pressable>\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Close\" onPress={() => setReading(false)} style={styles.readerBtn}>\n <Text style={styles.readerBtnText}>Done</Text>\n </Pressable>\n </View>\n <ScrollView contentContainerStyle={styles.readerPages}>\n {pages.map((pg, i) => (\n <Image key={i} source={{ uri: pg.src }} accessible accessibilityLabel={pg.alt || `Page ${i + 1}`} resizeMode=\"contain\" style={[styles.readerPage, { aspectRatio: pageRatio(pg) }]} />\n ))}\n </ScrollView>\n </View>\n </Modal>\n </View>\n );\n}\n\n/** Renders a sanitized HTML guide body with native Text. Links call `onLink`. */\nexport function RichText({ html, palette: p, onLink, size = 15 }: { html: string; palette: Palette; onLink: (url: string) => void; size?: number }) {\n const blocks = useMemo(() => parseHtml(html), [html]);\n if (!blocks.length) return null;\n const base: TextStyle = { color: p.text, fontSize: size, lineHeight: Math.round(size * 1.42), fontFamily: p.fontFamily };\n return (\n <View style={styles.wrap}>\n {blocks.map((b, i) => {\n if (b.kind === \"image\") return <BodyImage key={i} block={b} palette={p} />;\n if (b.kind === \"video\") return <BodyVideo key={i} block={b} palette={p} onLink={onLink} />;\n if (b.kind === \"pdf\") return <BodyPdf key={i} block={b} palette={p} onLink={onLink} />;\n if (b.kind === \"file\") return <BodyFile key={i} block={b} palette={p} onLink={onLink} />;\n const runs = b.runs.map((r, j) => (\n <Text key={j} style={runStyle(r, p)} onPress={r.href ? () => onLink(r.href as string) : undefined} accessibilityRole={r.href ? \"link\" : undefined}>\n {r.text}\n </Text>\n ));\n if (b.kind === \"list-item\") {\n return (\n <View key={i} style={[styles.li, { paddingLeft: (b.level - 1) * 14 }]}>\n <Text style={[base, styles.marker]}>{b.marker}</Text>\n <Text style={[base, styles.flex]}>{runs}</Text>\n </View>\n );\n }\n if (b.kind === \"heading\") {\n const fs = HEADING_SIZE[b.level as 1 | 2 | 3] ?? 15;\n return (\n <Text key={i} accessibilityRole=\"header\" style={[base, { fontSize: fs, lineHeight: Math.round(fs * 1.3), fontWeight: \"700\" }]}>\n {runs}\n </Text>\n );\n }\n return (\n <Text key={i} style={[base, b.kind === \"quote\" && { borderLeftWidth: 3, borderLeftColor: p.border, paddingLeft: 8, color: p.muted }]}>\n {runs}\n </Text>\n );\n })}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n wrap: { gap: 6 },\n li: { flexDirection: \"row\", gap: 6 },\n marker: { minWidth: 14 },\n flex: { flex: 1 },\n image: { width: \"100%\", borderRadius: 6 },\n video: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingVertical: 12, paddingHorizontal: 14, borderWidth: 1, borderRadius: 8 },\n play: { fontSize: 14 },\n badge: { backgroundColor: \"#e5484d\", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 3 },\n badgeText: { color: \"#fff\", fontSize: 9, fontWeight: \"700\", letterSpacing: 0.4 },\n pdf: { borderWidth: 1, borderRadius: 10, overflow: \"hidden\" },\n pdfHeader: { flexDirection: \"row\", alignItems: \"center\", gap: 8, minHeight: 44, paddingHorizontal: 12 },\n pdfPages: { marginHorizontal: 10, marginBottom: 10 },\n page: { backgroundColor: \"#fff\", borderRadius: 3 },\n count: { position: \"absolute\", right: 8, bottom: 8, backgroundColor: \"rgba(17,17,17,0.72)\", borderRadius: 999, paddingHorizontal: 8, paddingVertical: 2 },\n countText: { color: \"#fff\", fontSize: 11, fontWeight: \"500\", fontVariant: [\"tabular-nums\"] },\n reader: { flex: 1, backgroundColor: \"#0b0b0d\" },\n readerBar: { flexDirection: \"row\", alignItems: \"center\", gap: 8, paddingTop: Platform.OS === \"ios\" ? 52 : 12, paddingBottom: 10, paddingHorizontal: 16 },\n readerTitle: { color: \"#fff\", fontSize: 16, fontWeight: \"600\" },\n readerBtn: { minHeight: 36, justifyContent: \"center\", paddingHorizontal: 12, borderRadius: 8, backgroundColor: \"rgba(255,255,255,0.12)\" },\n readerBtnText: { color: \"#fff\", fontWeight: \"600\" },\n readerPages: { gap: 12, paddingHorizontal: 12, paddingBottom: 32 },\n readerPage: { width: \"100%\", backgroundColor: \"#fff\", borderRadius: 2 },\n});\n","import { PDF_BLOCK_CLASS, isAllowedEmbedSrc, isFileLink, isSafeMediaUrl, toEmbedUrl } from \"@guidelytech/shared/runtime\";\n\n/**\n * Tiny, tolerant HTML → rich-text converter for guide bodies (already sanitized server-side).\n * Supports p, div, br, strong/b, em/i, u, a, code, ul/ol/li, h1–h6 and blockquote; every other tag\n * is reduced to its text. `img` becomes an image block, and `video` / canonical embed `iframe`s\n * become video blocks (shown as a link that opens the video). A PDF (`div.gd-pdf`: its link and its\n * pages as images) becomes one pdf block, and a lone file link (`a.gd-file`) a file block. Output is\n * plain data so it can be unit-tested without React Native.\n */\n\nexport interface PdfPage {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n}\n\nexport interface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n code?: boolean;\n href?: string;\n}\n\nexport interface TextBlock {\n kind: \"paragraph\" | \"heading\" | \"list-item\" | \"quote\" | \"image\" | \"video\" | \"pdf\" | \"file\";\n /** Heading level 1–3, list nesting depth from 1. */\n level: number;\n /** For list items: the bullet (\"•\") or number (\"1.\") to show. */\n marker?: string;\n runs: TextRun[];\n /** Image blocks: http(s) or data:image source. */\n src?: string;\n /** Image alt text, a video's label, or a PDF's file name. */\n alt?: string;\n /** Video, pdf and file blocks: the page or file to open. */\n href?: string;\n /** Pdf blocks: the rendered pages, in order. */\n pages?: PdfPage[];\n /** Image intrinsic size from `width`/`height`, when present. */\n width?: number;\n height?: number;\n}\n\nconst ENTITIES: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \" \", mdash: \"—\", ndash: \"–\", hellip: \"…\", rsquo: \"’\", lsquo: \"‘\", rdquo: \"”\", ldquo: \"“\", copy: \"©\", reg: \"®\", trade: \"™\", times: \"×\", rarr: \"→\", larr: \"←\", bull: \"•\" };\n\nexport function decodeEntities(s: string): string {\n return s.replace(/&(#x[0-9a-f]+|#\\d+|[a-z]+);/gi, (m, e: string) => {\n if (e[0] === \"#\") {\n const code = e[1] === \"x\" || e[1] === \"X\" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);\n return Number.isFinite(code) && code > 0 && code < 0x110000 ? String.fromCodePoint(code) : m;\n }\n return ENTITIES[e.toLowerCase()] ?? m;\n });\n}\n\nconst BLOCK_TAGS = new Set([\"p\", \"div\", \"section\", \"article\", \"header\", \"footer\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"li\", \"blockquote\", \"ul\", \"ol\", \"table\", \"tr\", \"pre\"]);\nconst SKIP_TAGS = new Set([\"script\", \"style\", \"head\", \"title\", \"svg\", \"template\", \"iframe\", \"video\"]);\nconst PROVIDER_LABEL = { youtube: \"Watch on YouTube\", vimeo: \"Watch on Vimeo\", loom: \"Watch on Loom\", wistia: \"Watch video\" } as const;\n\nfunction attr(attrs: string, name: string): string | undefined {\n const m = attrs.match(new RegExp(`\\\\b${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, \"i\"));\n return m ? decodeEntities(m[2] ?? m[3] ?? m[4] ?? \"\") : undefined;\n}\n\nexport function parseHtml(html: string): TextBlock[] {\n const blocks: TextBlock[] = [];\n const style = { bold: 0, italic: 0, underline: 0, code: 0 };\n const hrefs: string[] = [];\n const lists: Array<{ ordered: boolean; n: number }> = [];\n let current: TextBlock | null = null;\n let skipping: string | null = null;\n /** Inside a `div.gd-pdf`: nesting depth of divs, the PDF link, its name and the pages so far. */\n let pdf: { depth: number; href?: string; name: string; inLink: boolean; pages: PdfPage[] } | null = null;\n /** Inside a lone `a.gd-file`: its target and text so far. */\n let fileLink: { href: string; name: string } | null = null;\n\n const media = (block: Omit<TextBlock, \"level\" | \"runs\">) => {\n flush();\n blocks.push({ level: 1, runs: [], ...block });\n };\n const flush = () => {\n if (current) {\n // Trim surrounding whitespace of the block; drop empty blocks.\n const runs = current.runs;\n while (runs.length && !runs[0]!.text.trim()) runs.shift();\n while (runs.length && !runs[runs.length - 1]!.text.trim()) runs.pop();\n if (runs.length) {\n runs[0]!.text = runs[0]!.text.replace(/^[ \\t\\n]+/, \"\");\n runs[runs.length - 1]!.text = runs[runs.length - 1]!.text.replace(/[ \\t\\n]+$/, \"\");\n blocks.push(current);\n }\n }\n current = null;\n };\n const open = (kind: TextBlock[\"kind\"], level = 1, marker?: string) => {\n flush();\n current = { kind, level, marker, runs: [] };\n };\n const push = (text: string) => {\n if (!text) return;\n if (!current) current = { kind: \"paragraph\", level: 1, runs: [] };\n const run: TextRun = { text };\n if (style.bold) run.bold = true;\n if (style.italic) run.italic = true;\n if (style.underline) run.underline = true;\n if (style.code) run.code = true;\n if (hrefs.length) run.href = hrefs[hrefs.length - 1];\n const last = current.runs[current.runs.length - 1];\n if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text += text;\n else current.runs.push(run);\n };\n\n const size = (attrs: string, name: string) => {\n const n = Number(attr(attrs, name));\n return n > 0 ? n : undefined;\n };\n const endPdf = (p: NonNullable<typeof pdf>) => {\n const name = p.name.replace(/\\s+/g, \" \").trim();\n if (p.href && p.pages.length) media({ kind: \"pdf\", href: p.href, alt: name || \"PDF\", pages: p.pages });\n else if (p.href) media({ kind: \"file\", href: p.href, alt: name || \"Open PDF\" });\n else for (const page of p.pages) media({ kind: \"image\", src: page.src, alt: page.alt, ...(page.width && page.height ? { width: page.width, height: page.height } : {}) });\n };\n\n const re = /<!--[\\s\\S]*?-->|<\\/?([a-zA-Z][a-zA-Z0-9]*)\\b([^>]*)>|([^<]+|<)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(html || \"\"))) {\n const [token, rawTag, attrs = \"\", text] = m;\n if (text !== undefined) {\n if (skipping) continue;\n if (pdf) {\n if (pdf.inLink) pdf.name += decodeEntities(text);\n continue;\n }\n if (fileLink) {\n fileLink.name += decodeEntities(text);\n continue;\n }\n push(decodeEntities(text.replace(/\\s+/g, \" \")));\n continue;\n }\n if (!rawTag) continue; // comment\n const tag = rawTag.toLowerCase();\n const closing = token.startsWith(\"</\");\n if (skipping) {\n if (closing && tag === skipping) skipping = null;\n continue;\n }\n if (SKIP_TAGS.has(tag)) {\n if (closing) continue;\n if (tag === \"iframe\") {\n const src = attr(attrs, \"src\");\n const embed = isAllowedEmbedSrc(src) ? toEmbedUrl(src!) : null;\n if (embed) media({ kind: \"video\", href: embed.watchUrl, alt: PROVIDER_LABEL[embed.provider] });\n } else if (tag === \"video\") {\n const src = attr(attrs, \"src\");\n if (isSafeMediaUrl(src)) media({ kind: \"video\", href: src, alt: \"Play video\" });\n }\n if (!token.endsWith(\"/>\")) skipping = tag;\n continue;\n }\n if (pdf) {\n if (tag === \"div\") {\n pdf.depth += closing ? -1 : 1;\n if (pdf.depth === 0) {\n endPdf(pdf);\n pdf = null;\n }\n } else if (tag === \"a\") {\n if (closing) pdf.inLink = false;\n else if (!pdf.href && isFileLink(attr(attrs, \"class\"), attr(attrs, \"href\"))) {\n pdf.href = attr(attrs, \"href\");\n pdf.inLink = true;\n }\n } else if (tag === \"img\" && !closing) {\n const src = attr(attrs, \"src\");\n const w = size(attrs, \"width\");\n const h = size(attrs, \"height\");\n if (isSafeMediaUrl(src)) pdf.pages.push({ src: src!, alt: attr(attrs, \"alt\") ?? \"\", ...(w && h ? { width: w, height: h } : {}) });\n }\n continue;\n }\n if (fileLink) {\n if (closing && tag === \"a\") {\n media({ kind: \"file\", href: fileLink.href, alt: fileLink.name.replace(/\\s+/g, \" \").trim() || \"Open PDF\" });\n fileLink = null;\n }\n continue;\n }\n if (!closing && tag === \"div\" && (attr(attrs, \"class\") ?? \"\").split(/\\s+/).includes(PDF_BLOCK_CLASS)) {\n flush();\n pdf = { depth: 1, name: \"\", inLink: false, pages: [] };\n continue;\n }\n if (!closing && tag === \"a\" && isFileLink(attr(attrs, \"class\"), attr(attrs, \"href\"))) {\n flush();\n fileLink = { href: attr(attrs, \"href\")!, name: \"\" };\n continue;\n }\n if (closing) {\n if (tag === \"b\" || tag === \"strong\") style.bold = Math.max(0, style.bold - 1);\n else if (tag === \"i\" || tag === \"em\") style.italic = Math.max(0, style.italic - 1);\n else if (tag === \"u\") style.underline = Math.max(0, style.underline - 1);\n else if (tag === \"code\") style.code = Math.max(0, style.code - 1);\n else if (tag === \"a\") hrefs.pop();\n else if (tag === \"ul\" || tag === \"ol\") {\n lists.pop();\n flush();\n } else if (BLOCK_TAGS.has(tag)) flush();\n continue;\n }\n switch (tag) {\n case \"br\":\n push(\"\\n\");\n break;\n case \"b\":\n case \"strong\":\n style.bold += 1;\n break;\n case \"i\":\n case \"em\":\n style.italic += 1;\n break;\n case \"u\":\n style.underline += 1;\n break;\n case \"code\":\n style.code += 1;\n break;\n case \"a\":\n hrefs.push(attr(attrs, \"href\") ?? \"\");\n break;\n case \"ul\":\n case \"ol\":\n flush();\n lists.push({ ordered: tag === \"ol\", n: 0 });\n break;\n case \"li\": {\n const list = lists[lists.length - 1];\n if (list) list.n += 1;\n open(\"list-item\", Math.max(1, lists.length), list?.ordered ? `${list.n}.` : \"•\");\n break;\n }\n case \"h1\":\n case \"h2\":\n case \"h3\":\n case \"h4\":\n case \"h5\":\n case \"h6\":\n open(\"heading\", Math.min(3, Number(tag[1])));\n break;\n case \"blockquote\":\n open(\"quote\");\n break;\n default:\n if (BLOCK_TAGS.has(tag)) open(\"paragraph\");\n else if (tag === \"img\") {\n const src = attr(attrs, \"src\") ?? \"\";\n const alt = attr(attrs, \"alt\") ?? \"\";\n if (isSafeMediaUrl(src) || /^data:image\\//i.test(src)) {\n const w = Number(attr(attrs, \"width\"));\n const h = Number(attr(attrs, \"height\"));\n media({ kind: \"image\", src, alt, ...(w > 0 && h > 0 ? { width: w, height: h } : {}) });\n } else if (alt) push(alt);\n }\n }\n }\n if (pdf) endPdf(pdf);\n if (fileLink) media({ kind: \"file\", href: fileLink.href, alt: fileLink.name.replace(/\\s+/g, \" \").trim() || \"Open PDF\" });\n flush();\n return blocks;\n}\n\n/** Plain-text rendering of an HTML body (accessibility labels, previews). */\nexport function htmlToText(html: string): string {\n return parseHtml(html)\n .map((b) => (b.kind === \"image\" || b.kind === \"video\" || b.kind === \"pdf\" || b.kind === \"file\" ? (b.alt ?? \"\") : (b.marker ? `${b.marker} ` : \"\") + b.runs.map((r) => r.text).join(\"\")))\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport { AccessibilityInfo, ActivityIndicator, Animated, Easing, Keyboard, Modal, PanResponder, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from \"react-native\";\nimport type { MessengerConversation, MessengerMessage, ResourceCenterArticle } from \"@guidelytech/shared\";\nimport { isArticleListed, resourceCenterSections } from \"@guidelytech/shared/runtime\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { clampToSafeArea, LAUNCHER_DRAG_THRESHOLD, placementPoint, snapPlacement, type LauncherFrame, type LauncherPlacement, type Point } from \"../core/launcherPlacement\";\nimport type { Messenger as MessengerStore, MessengerTab } from \"../core/messenger\";\nimport { CloseButton, GButton } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\nfunction useMessenger(store: MessengerStore) {\n return useSyncExternalStore(\n useCallback((cb) => store.subscribe(cb), [store]),\n () => store.getSnapshot(),\n () => store.getSnapshot(),\n );\n}\n\n/**\n * Keyboard height on iOS. KeyboardAvoidingView measures relative to a pageSheet modal rather than\n * the screen and under-shifts; the sheet reaches the bottom of the screen, so padding by the\n * keyboard height is exact. Android resizes the modal window itself.\n */\nfunction useKeyboardHeight(): number {\n const [h, setH] = useState(0);\n useEffect(() => {\n if (Platform.OS !== \"ios\") return;\n const show = Keyboard.addListener(\"keyboardWillShow\", (e) => setH(e.endCoordinates.height));\n const hide = Keyboard.addListener(\"keyboardWillHide\", () => setH(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n return h;\n}\n\nfunction ago(iso: string): string {\n const s = Math.max(0, (Date.now() - Date.parse(iso)) / 1000);\n if (s < 60) return \"now\";\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n}\n\n/** Diameter of the chat bubble. */\nexport const LAUNCHER_SIZE = 54;\n\nfunction useReduceMotion(): boolean {\n const [on, setOn] = useState(false);\n useEffect(() => {\n let live = true;\n AccessibilityInfo.isReduceMotionEnabled?.()\n .then((v) => live && setOn(v))\n .catch(() => {});\n const sub = AccessibilityInfo.addEventListener?.(\"reduceMotionChanged\", setOn);\n return () => {\n live = false;\n sub?.remove();\n };\n }, []);\n return on;\n}\n\n/**\n * Round chat bubble with an unread badge. `style` pins it to the configured corner; a drag (more than a few px, so taps\n * still open the messenger) moves it, and on release it snaps to the nearer side edge at the drop\n * height. The spot is remembered on this device and drawn as a translation from the corner, so\n * until the visitor drags, placement is exactly the configured one.\n */\nexport function MessengerLauncher({ store, client, palette: p, style, frame, defaultSide }: { store: MessengerStore; client: GuidelyClient; palette: Palette; style: object; frame: LauncherFrame; defaultSide: LauncherPlacement[\"side\"] }) {\n const snap = useMessenger(store);\n const reduceMotion = useReduceMotion();\n const [placement, setPlacement] = useState(() => client.getMessengerLauncherPlacement());\n const pan = useRef(new Animated.ValueXY()).current;\n const offset = useRef<Point>({ x: 0, y: 0 });\n const dragging = useRef(false);\n // Read by the (once-created) responder, so it always sees the current window and preferences.\n const live = useRef({ frame, defaultSide, reduceMotion });\n live.current = { frame, defaultSide, reduceMotion };\n\n // Re-applies the remembered spot whenever the window, insets or bottom offset change (rotation).\n // A layout effect, so a remembered spot never flashes in the configured corner first.\n const { width, height, size, defaultBottom } = frame;\n const { top, bottom, left, right } = frame.insets;\n useLayoutEffect(() => {\n if (dragging.current) return;\n const f = live.current.frame;\n const anchor = placementPoint(f, { side: defaultSide, fraction: 0 });\n const at = placement ? placementPoint(f, placement) : anchor;\n offset.current = { x: at.x - anchor.x, y: at.y - anchor.y };\n pan.setValue(offset.current);\n }, [pan, placement, defaultSide, width, height, size, defaultBottom, top, bottom, left, right]);\n\n const responder = useMemo(() => {\n const moved = (g: { dx: number; dy: number }) => Math.hypot(g.dx, g.dy) > LAUNCHER_DRAG_THRESHOLD;\n // Offsets are from the configured corner (`style`), where the bubble's top-left is `anchor()`.\n const anchor = () => placementPoint(live.current.frame, { side: live.current.defaultSide, fraction: 0 });\n let start: Point = { x: 0, y: 0 };\n const follow = (g: { dx: number; dy: number }): Point => {\n const a = anchor();\n const at = clampToSafeArea(live.current.frame, { x: a.x + start.x + g.dx, y: a.y + start.y + g.dy });\n return { x: at.x - a.x, y: at.y - a.y };\n };\n const drop = (g: { dx: number; dy: number }) => {\n const a = anchor();\n const d = follow(g);\n const next = snapPlacement(live.current.frame, { x: a.x + d.x, y: a.y + d.y });\n const at = placementPoint(live.current.frame, next);\n const to = { x: at.x - a.x, y: at.y - a.y };\n offset.current = to;\n client.setMessengerLauncherPlacement(next);\n const done = ({ finished }: { finished: boolean }) => {\n // Not finished = grabbed again mid-snap; that drag is still in charge.\n if (finished) dragging.current = false;\n setPlacement(next);\n };\n if (live.current.reduceMotion) {\n pan.setValue(to);\n done({ finished: true });\n } else Animated.timing(pan, { toValue: to, duration: 300, easing: Easing.out(Easing.cubic), useNativeDriver: true }).start(done);\n };\n return PanResponder.create({\n // Taps stay with the Pressable; only a real drag is taken (which cancels its press).\n onMoveShouldSetPanResponderCapture: (_, g) => moved(g),\n onMoveShouldSetPanResponder: (_, g) => moved(g),\n onPanResponderGrant: () => {\n dragging.current = true;\n start = offset.current;\n pan.stopAnimation((v) => {\n if (Number.isFinite(v?.x) && Number.isFinite(v?.y)) start = v;\n });\n },\n onPanResponderMove: (_, g) => pan.setValue(follow(g)),\n onPanResponderRelease: (_, g) => drop(g),\n onPanResponderTerminate: (_, g) => drop(g),\n onPanResponderTerminationRequest: () => false,\n });\n }, [client, pan]);\n\n if (snap.open) return null;\n const label = snap.unread ? `Open ${snap.config.name}, ${snap.unread} unread` : `Open ${snap.config.name}`;\n return (\n <Animated.View {...responder.panHandlers} style={[styles.launcherWrap, style, { transform: pan.getTranslateTransform() }]}>\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={() => !dragging.current && store.open()} style={({ pressed }) => [styles.launcher, { backgroundColor: p.primary, opacity: pressed ? 0.85 : 1 }]}>\n <Text style={[styles.launcherIcon, { color: p.onPrimary }]}>💬</Text>\n {snap.unread ? (\n <View style={styles.badge}>\n <Text style={styles.badgeText}>{snap.unread}</Text>\n </View>\n ) : null}\n </Pressable>\n </Animated.View>\n );\n}\n\n/** The messenger sheet: Home, Messages and Help tabs, threads and articles. */\nexport function MessengerSheet({ store, client, palette: p, topInset, bottomInset }: { store: MessengerStore; client: GuidelyClient; palette: Palette; topInset: number; bottomInset: number }) {\n const snap = useMessenger(store);\n const keyboard = useKeyboardHeight();\n const v = snap.view;\n const title = v.kind === \"thread\" ? snap.thread?.conversation?.subject || \"New conversation\" : v.kind === \"article\" ? \"\" : v.tab === \"home\" ? snap.config.name : v.tab === \"messages\" ? \"Messages\" : \"Help\";\n return (\n <Modal visible={snap.open} animationType=\"slide\" presentationStyle={Platform.OS === \"ios\" ? \"pageSheet\" : \"fullScreen\"} onRequestClose={() => (v.kind === \"tab\" ? store.close() : store.back())}>\n <View style={[styles.sheet, { backgroundColor: p.background, paddingTop: Platform.OS === \"ios\" ? 8 : topInset, paddingBottom: keyboard }]}>\n <View style={[styles.header, { borderColor: p.border }]}>\n {v.kind !== \"tab\" ? (\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Back\" onPress={() => store.back()} hitSlop={10}>\n <Text style={[styles.back, { color: p.primary }]}>‹ Back</Text>\n </Pressable>\n ) : null}\n <Text accessibilityRole=\"header\" numberOfLines={1} style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {title}\n </Text>\n <CloseButton palette={p} onPress={() => store.close()} label={`Close ${snap.config.name}`} />\n </View>\n <View style={styles.flex}>\n {v.kind === \"thread\" ? <Thread store={store} palette={p} bottomInset={keyboard ? 0 : bottomInset} /> : v.kind === \"article\" ? <Article article={snap.article} palette={p} client={client} /> : v.tab === \"home\" ? <Home store={store} palette={p} /> : v.tab === \"messages\" ? <Conversations store={store} palette={p} /> : <Help store={store} client={client} palette={p} />}\n </View>\n {v.kind === \"tab\" && !keyboard ? <Tabs store={store} active={v.tab} palette={p} bottomInset={bottomInset} /> : null}\n </View>\n </Modal>\n );\n}\n\nfunction Tabs({ store, active, palette: p, bottomInset }: { store: MessengerStore; active: MessengerTab; palette: Palette; bottomInset: number }) {\n const unread = useMessenger(store).unread;\n const tabs: Array<[MessengerTab, string, string]> = [\n [\"home\", \"⌂\", \"Home\"],\n [\"messages\", \"\\u2709\\uFE0E\", \"Messages\"],\n [\"help\", \"?\", \"Help\"],\n ];\n return (\n <View accessibilityRole=\"tablist\" style={[styles.tabs, { borderColor: p.border, paddingBottom: Math.max(8, bottomInset) }]}>\n {tabs.map(([tab, icon, label]) => {\n const on = tab === active;\n return (\n <Pressable key={tab} accessibilityRole=\"tab\" accessibilityState={{ selected: on }} accessibilityLabel={tab === \"messages\" && unread ? `${label}, ${unread} unread` : label} onPress={() => store.setTab(tab)} style={styles.tab}>\n <Text style={[styles.tabIcon, { color: on ? p.primary : p.muted }]}>{icon}</Text>\n <Text style={[styles.tabLabel, { color: on ? p.primary : p.muted }]}>{label}</Text>\n {tab === \"messages\" && unread ? <View style={[styles.dot, styles.tabDot]} /> : null}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nfunction Home({ store, palette: p }: { store: MessengerStore; palette: Palette }) {\n const snap = useMessenger(store);\n const recent = snap.conversations[0];\n const [q, setQ] = useState(\"\");\n return (\n <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps=\"handled\">\n <View style={[styles.hero, { backgroundColor: p.primary, borderRadius: p.radius }]}>\n <Text style={[styles.heroTitle, { color: p.onPrimary }]}>{snap.config.greeting || `Hi! I'm ${snap.config.name}.`}</Text>\n <Text style={[styles.heroSub, { color: p.onPrimary }]}>{snap.config.aiAvailable ? `${snap.config.name} answers right away${snap.config.handoffEnabled ? \", and the team is here when you need a person\" : \"\"}.` : \"The team usually replies within a few hours.\"}</Text>\n </View>\n <GButton label=\"Send us a message\" palette={p} onPress={() => store.showNewMessage()} style={styles.fullWidth} />\n {recent ? (\n <View style={styles.section}>\n <Text style={[styles.sectionTitle, { color: p.muted }]}>RECENT</Text>\n <ConversationRow c={recent} palette={p} onPress={() => void store.openConversation(recent.id)} />\n </View>\n ) : null}\n <View style={styles.section}>\n <Text style={[styles.sectionTitle, { color: p.muted }]}>SEARCH FOR HELP</Text>\n <TextInput\n value={q}\n onChangeText={setQ}\n onSubmitEditing={() => {\n pendingSearch.current = q;\n store.setTab(\"help\");\n }}\n returnKeyType=\"search\"\n placeholder=\"Search articles\"\n placeholderTextColor={p.muted}\n accessibilityLabel=\"Search help articles\"\n style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]}\n />\n </View>\n </ScrollView>\n );\n}\n\n/** Carries a search typed on Home over to the Help tab. */\nconst pendingSearch: { current: string } = { current: \"\" };\n\nfunction ConversationRow({ c, palette: p, onPress }: { c: MessengerConversation; palette: Palette; onPress: () => void }) {\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={`${c.subject || \"Conversation\"}${c.unread ? \", unread\" : \"\"}`} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text numberOfLines={1} style={[styles.rowTitle, { color: p.text }]}>\n {c.subject || \"Conversation\"}\n </Text>\n <Text numberOfLines={1} style={[styles.rowSub, { color: p.muted }]}>\n {c.lastMessagePreview || (c.status === \"closed\" ? \"Closed\" : \" \")}\n </Text>\n </View>\n <View style={styles.rowEnd}>\n <Text style={[styles.time, { color: p.muted }]}>{ago(c.lastMessageAt)}</Text>\n {c.unread ? <View style={[styles.dot, { backgroundColor: p.primary }]} /> : null}\n </View>\n </Pressable>\n );\n}\n\nfunction Conversations({ store, palette: p }: { store: MessengerStore; palette: Palette }) {\n const snap = useMessenger(store);\n return (\n <ScrollView contentContainerStyle={styles.content}>\n {snap.conversations.length ? snap.conversations.map((c) => <ConversationRow key={c.id} c={c} palette={p} onPress={() => void store.openConversation(c.id)} />) : <Text style={[styles.empty, { color: p.muted }]}>No conversations yet.</Text>}\n <GButton label=\"New conversation\" palette={p} onPress={() => store.showNewMessage()} style={styles.fullWidth} />\n </ScrollView>\n );\n}\n\nfunction Bubble({ m, text, name, palette: p, onArticle, onGuide }: { m: MessengerMessage; text: string; name: string; palette: Palette; onArticle: (id: string) => void; onGuide: (key: string) => void }) {\n if (m.author === \"system\")\n return (\n <Text accessibilityRole=\"text\" style={[styles.system, { color: p.muted }]}>\n {text}\n </Text>\n );\n const mine = m.author === \"user\";\n return (\n <View style={[styles.bubbleWrap, mine ? styles.mine : styles.theirs]}>\n {!mine ? <Text style={[styles.author, { color: p.muted }]}>{m.author === \"agent\" ? m.authorName || \"Team\" : name}</Text> : null}\n <View style={[styles.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }]}>\n {m.status === \"pending\" && !text ? <TypingDots color={p.muted} /> : <Text style={[styles.bubbleText, { color: mine ? p.onPrimary : p.text }]}>{text}</Text>}\n </View>\n {m.citations.length || m.suggestedGuides.length ? (\n <View style={styles.chips}>\n {m.citations.map((c) => (\n <Pressable key={c.articleId} accessibilityRole=\"link\" accessibilityLabel={`Article: ${c.title}`} onPress={() => onArticle(c.articleId)} style={[styles.chip, { borderColor: p.border }]}>\n <Text style={[styles.chipText, { color: p.text }]}>📄 {c.title}</Text>\n </Pressable>\n ))}\n {m.suggestedGuides.map((g) => (\n <Pressable key={g.key} accessibilityRole=\"button\" accessibilityLabel={`Show me: ${g.name}`} onPress={() => onGuide(g.key)} style={[styles.chip, { borderColor: p.primary }]}>\n <Text style={[styles.chipText, { color: p.primary }]}>▶ Show me: {g.name}</Text>\n </Pressable>\n ))}\n </View>\n ) : null}\n </View>\n );\n}\n\nfunction TypingDots({ color }: { color: string }) {\n return <ActivityIndicator size=\"small\" color={color} accessibilityLabel=\"Typing\" />;\n}\n\nfunction Thread({ store, palette: p, bottomInset }: { store: MessengerStore; palette: Palette; bottomInset: number }) {\n const snap = useMessenger(store);\n const t = snap.thread;\n const [text, setText] = useState(t?.draft ?? \"\");\n const scroll = useRef<ScrollView>(null);\n const convo = t?.conversation ?? null;\n useEffect(() => {\n if (t?.draft) setText(t.draft);\n }, [t?.draft]);\n const streamingIds = useMemo(() => Object.keys(t?.streaming ?? {}).filter((id) => !t?.messages.some((m) => m.id === id)), [t]);\n if (!t) return null;\n const send = () => {\n const value = text;\n setText(\"\");\n void store.send(value);\n };\n const canHandoff = snap.config.handoffEnabled && snap.config.aiAvailable && convo?.status === \"bot\" && !t.sending;\n return (\n <View style={styles.flex}>\n <ScrollView ref={scroll} contentContainerStyle={styles.thread} onContentSizeChange={() => scroll.current?.scrollToEnd({ animated: true })} keyboardShouldPersistTaps=\"handled\">\n {!t.messages.length && !t.sending ? <Text style={[styles.empty, { color: p.muted }]}>{snap.config.greeting || \"Ask us anything.\"}</Text> : null}\n {t.messages.map((m) => (\n <Bubble key={m.id} m={m} text={t.streaming[m.id] ?? m.body} name={snap.config.name} palette={p} onArticle={(id) => void store.openArticle(id)} onGuide={(k) => store.startGuide(k)} />\n ))}\n {streamingIds.map((id) => (\n <Bubble key={id} m={{ id, author: \"scout\", body: \"\", citations: [], suggestedGuides: [], status: \"pending\", createdAt: new Date().toISOString() }} text={t.streaming[id] ?? \"\"} name={snap.config.name} palette={p} onArticle={() => {}} onGuide={() => {}} />\n ))}\n {t.sending && !streamingIds.length && snap.config.aiAvailable && t.messages.length ? <TypingDots color={p.muted} /> : null}\n {t.error ? (\n <Text accessibilityLiveRegion=\"polite\" style={styles.error}>\n {t.error}\n </Text>\n ) : null}\n {convo?.status === \"closed\" && convo.rating == null ? <Rating palette={p} onRate={(n) => void store.rate(n)} /> : null}\n {convo?.status === \"closed\" && convo.rating != null ? <Text style={[styles.system, { color: p.muted }]}>Thanks for rating this conversation.</Text> : null}\n </ScrollView>\n {canHandoff ? <GButton label=\"Talk to a person\" variant=\"secondary\" palette={p} onPress={() => void store.handoff()} style={styles.handoff} /> : null}\n <View style={[styles.composer, { borderColor: p.border, paddingBottom: Math.max(10, bottomInset) }]}>\n <TextInput\n value={text}\n onChangeText={(v) => setText(v.slice(0, 4000))}\n placeholder={convo ? \"Reply…\" : \"Write a message…\"}\n placeholderTextColor={p.muted}\n multiline\n accessibilityLabel=\"Message\"\n style={[styles.input, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(18, p.radius + 6) }]}\n />\n <GButton label=\"Send\" palette={p} onPress={send} disabled={!text.trim() || t.sending} />\n </View>\n </View>\n );\n}\n\nfunction Rating({ palette: p, onRate }: { palette: Palette; onRate: (n: number) => void }) {\n return (\n <View style={styles.rating}>\n <Text style={[styles.ratingTitle, { color: p.text }]}>How did we do?</Text>\n <View accessibilityRole=\"radiogroup\" style={styles.stars}>\n {[1, 2, 3, 4, 5].map((n) => (\n <Pressable key={n} accessibilityRole=\"radio\" accessibilityLabel={`${n} of 5`} onPress={() => onRate(n)} hitSlop={6}>\n <Text style={[styles.star, { color: p.primary }]}>★</Text>\n </Pressable>\n ))}\n </View>\n </View>\n );\n}\n\nfunction Help({ store, client, palette: p }: { store: MessengerStore; client: GuidelyClient; palette: Palette }) {\n const snap = useMessenger(store);\n const rc = client.getResourceCenter();\n const [q, setQ] = useState(pendingSearch.current);\n const [results, setResults] = useState<ResourceCenterArticle[] | null>(null);\n const [faq, setFaq] = useState<string | null>(null);\n useEffect(() => {\n pendingSearch.current = \"\";\n }, []);\n useEffect(() => {\n const query = q.trim();\n if (query.length < 2) return setResults(null);\n let alive = true;\n const t = setTimeout(() => void store.search(query).then((r) => alive && setResults(r)), 250);\n return () => {\n alive = false;\n clearTimeout(t);\n };\n }, [q, store]);\n const guides = client.getGuides();\n const recommended = (rc?.recommendedGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g);\n const articles = snap.articles;\n const row = (key: string, title: string, sub: string | undefined, onPress: () => void, icon = \"›\") => (\n <Pressable key={key} accessibilityRole=\"button\" accessibilityLabel={title} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text style={[styles.rowTitle, { color: p.text }]}>{title}</Text>\n {sub ? (\n <Text numberOfLines={2} style={[styles.rowSub, { color: p.muted }]}>\n {sub}\n </Text>\n ) : null}\n </View>\n <Text style={[styles.chev, { color: p.muted }]}>{icon}</Text>\n </Pressable>\n );\n const open = (a: { id: string; externalUrl?: string | null }) => (a.externalUrl ? client.navigate(a.externalUrl) : void store.openArticle(a.id));\n const section = (title: string, children: React.ReactNode) => (\n <View key={title} style={styles.section}>\n <Text accessibilityRole=\"header\" style={[styles.sectionTitle, { color: p.muted }]}>\n {title.toUpperCase()}\n </Text>\n {children}\n </View>\n );\n const audiences = client.getAudienceIds();\n const sections = resourceCenterSections(articles?.collections ?? [], articles?.articles ?? [], audiences);\n const modules = client.getHelpModules();\n const searchOn = modules.includes(\"search\");\n const listed = searchOn ? results?.filter((a) => isArticleListed(articles?.collections ?? [], a, audiences)) : undefined;\n const checklists = (rc?.checklistGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind === \"checklist\");\n const renderModule = (id: (typeof modules)[number]) => {\n switch (id) {\n case \"guides\":\n return recommended.length ? section(\"Recommended\", recommended.map((g) => row(g.id, g.name, undefined, () => store.startGuide(g.key), \"▶\"))) : null;\n case \"checklists\":\n return checklists.length ? section(\"Checklists\", checklists.map((g) => row(g.id, g.name, undefined, () => store.startGuide(g.key), \"☑\"))) : null;\n case \"articles\":\n return (\n <>\n {!articles ? <ActivityIndicator color={p.muted} /> : null}\n {sections.map((s) => section(s.collection ? s.path.join(\" › \") : \"Articles\", s.articles.map((a) => row(a.id, a.title, a.summary, () => open(a)))))}\n </>\n );\n case \"faqs\":\n return rc?.faqs.length\n ? section(\n \"FAQ\",\n rc.faqs.map((f) => (\n <View key={f.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <Pressable accessibilityRole=\"button\" accessibilityState={{ expanded: faq === f.id }} onPress={() => setFaq(faq === f.id ? null : f.id)} style={styles.faqHead}>\n <Text style={[styles.rowTitle, styles.flex, { color: p.text }]}>{f.question}</Text>\n <Text style={[styles.chev, { color: p.muted }]}>{faq === f.id ? \"−\" : \"+\"}</Text>\n </Pressable>\n {faq === f.id ? <RichText html={f.answer} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n </View>\n )),\n )\n : null;\n case \"links\":\n return rc?.links.length ? section(\"Links\", rc.links.map((l) => row(l.id, l.label, undefined, () => client.navigate(l.url), \"↗\"))) : null;\n default:\n return null; // \"search\" renders above the sections\n }\n };\n return (\n <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps=\"handled\">\n {searchOn ? <TextInput value={q} onChangeText={setQ} placeholder=\"Search articles\" placeholderTextColor={p.muted} accessibilityLabel=\"Search help articles\" returnKeyType=\"search\" style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]} /> : null}\n {listed ? (\n section(`Results for “${q.trim()}”`, listed.length ? listed.map((a) => row(a.id, a.title, a.summary, () => open(a))) : <Text style={[styles.rowSub, { color: p.muted }]}>No articles found.</Text>)\n ) : (\n <>\n {modules\n .filter((id) => id !== \"search\")\n .map((id) => (\n <Fragment key={id}>{renderModule(id)}</Fragment>\n ))}\n </>\n )}\n </ScrollView>\n );\n}\n\nfunction Article({ article, palette: p, client }: { article: ResourceCenterArticle | null; palette: Palette; client: GuidelyClient }) {\n if (!article) return <ActivityIndicator style={styles.loading} color={p.muted} />;\n return (\n <ScrollView contentContainerStyle={styles.content}>\n <Text accessibilityRole=\"header\" style={[styles.articleTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {article.title}\n </Text>\n <RichText html={article.body} palette={p} onLink={(u) => client.navigate(u)} />\n </ScrollView>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n launcherWrap: { position: \"absolute\", width: LAUNCHER_SIZE, height: LAUNCHER_SIZE, elevation: 8 },\n launcher: { width: LAUNCHER_SIZE, height: LAUNCHER_SIZE, borderRadius: 27, alignItems: \"center\", justifyContent: \"center\", elevation: 8, shadowColor: \"#000\", shadowOpacity: 0.22, shadowRadius: 12, shadowOffset: { width: 0, height: 4 } },\n launcherIcon: { fontSize: 24 },\n badge: { position: \"absolute\", top: -2, right: -2, minWidth: 20, height: 20, borderRadius: 10, backgroundColor: \"#dc2626\", alignItems: \"center\", justifyContent: \"center\", paddingHorizontal: 5, borderWidth: 2, borderColor: \"#ffffff\" },\n badgeText: { color: \"#ffffff\", fontSize: 11, fontWeight: \"800\" },\n sheet: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\", gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: StyleSheet.hairlineWidth },\n back: { fontSize: 16, fontWeight: \"600\" },\n title: { flex: 1, fontSize: 18, fontWeight: \"700\" },\n tabs: { flexDirection: \"row\", borderTopWidth: StyleSheet.hairlineWidth, paddingTop: 8 },\n tab: { flex: 1, alignItems: \"center\", gap: 2 },\n tabIcon: { fontSize: 18 },\n tabLabel: { fontSize: 11, fontWeight: \"600\" },\n tabDot: { position: \"absolute\", top: 0, right: \"34%\", backgroundColor: \"#dc2626\" },\n dot: { width: 8, height: 8, borderRadius: 4 },\n content: { padding: 16, gap: 16 },\n hero: { padding: 18, gap: 6 },\n heroTitle: { fontSize: 20, fontWeight: \"800\" },\n heroSub: { fontSize: 14, opacity: 0.9 },\n fullWidth: { alignSelf: \"stretch\" },\n section: { gap: 8 },\n sectionTitle: { fontSize: 12, fontWeight: \"700\", letterSpacing: 0.6 },\n search: { height: 42, paddingHorizontal: 12, fontSize: 15 },\n row: { flexDirection: \"row\", alignItems: \"center\", gap: 10, borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, paddingVertical: 12, paddingHorizontal: 12 },\n rowTitle: { fontSize: 15, fontWeight: \"600\" },\n rowSub: { fontSize: 13, marginTop: 2 },\n rowEnd: { alignItems: \"flex-end\", gap: 6 },\n time: { fontSize: 12 },\n chev: { fontSize: 18 },\n empty: { textAlign: \"center\", paddingVertical: 24, fontSize: 14 },\n faq: { flexDirection: \"column\", alignItems: \"stretch\" },\n faqHead: { flexDirection: \"row\", alignItems: \"center\", gap: 10 },\n thread: { padding: 16, gap: 12 },\n system: { textAlign: \"center\", fontSize: 12, paddingHorizontal: 24 },\n bubbleWrap: { maxWidth: \"86%\", gap: 4 },\n mine: { alignSelf: \"flex-end\", alignItems: \"flex-end\" },\n theirs: { alignSelf: \"flex-start\", alignItems: \"flex-start\" },\n author: { fontSize: 12, fontWeight: \"600\", marginLeft: 4 },\n bubble: { paddingHorizontal: 14, paddingVertical: 10 },\n bubbleText: { fontSize: 15, lineHeight: 21 },\n chips: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 6 },\n chip: { borderWidth: 1, borderRadius: 14, paddingHorizontal: 10, paddingVertical: 5 },\n chipText: { fontSize: 13, fontWeight: \"600\" },\n error: { color: \"#dc2626\", fontSize: 13, textAlign: \"center\" },\n handoff: { alignSelf: \"center\", marginBottom: 8 },\n composer: { flexDirection: \"row\", alignItems: \"flex-end\", gap: 8, paddingHorizontal: 12, paddingTop: 10, borderTopWidth: StyleSheet.hairlineWidth },\n input: { flex: 1, minHeight: 40, maxHeight: 120, paddingHorizontal: 14, paddingTop: 10, paddingBottom: 10, fontSize: 15 },\n rating: { alignItems: \"center\", gap: 6, paddingVertical: 8 },\n ratingTitle: { fontSize: 15, fontWeight: \"600\" },\n stars: { flexDirection: \"row\", gap: 8 },\n star: { fontSize: 30 },\n articleTitle: { fontSize: 22, fontWeight: \"700\" },\n loading: { marginTop: 40 },\n});\n","import { Fragment, useEffect, useMemo, useState } from \"react\";\nimport { Modal, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from \"react-native\";\nimport type { ResourceCenterAnnouncement, ResourceCenterArticle } from \"@guidelytech/shared\";\nimport { isArticleListed, resourceCenterSections } from \"@guidelytech/shared/runtime\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { CloseButton } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\n/**\n * Full-height sheet: \"What's new\", search, recommended guides, checklists, collections, links and FAQs,\n * in the order (and with the visibility) of the resource center's modules.\n */\nexport function ResourceCenter({ client, palette: p, open, topInset, bottomInset }: { client: GuidelyClient; palette: Palette; open: boolean; topInset: number; bottomInset: number }) {\n const rc = client.getResourceCenter();\n const [query, setQuery] = useState(\"\");\n const [results, setResults] = useState<ResourceCenterArticle[] | null>(null);\n const [article, setArticle] = useState<ResourceCenterArticle | null>(null);\n const [faq, setFaq] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setQuery(\"\");\n setResults(null);\n setArticle(null);\n }\n }, [open]);\n useEffect(() => {\n const q = query.trim();\n if (q.length < 2) {\n setResults(null);\n return;\n }\n let alive = true;\n const t = setTimeout(() => {\n void client.searchResourceCenter(q).then((r) => alive && setResults(r));\n }, 250);\n return () => {\n alive = false;\n clearTimeout(t);\n };\n }, [client, query]);\n\n const guides = client.getGuides();\n const recommended = useMemo(() => (rc?.recommendedGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind !== \"checklist\"), [rc, guides]);\n const checklists = useMemo(() => (rc?.checklistGuideIds ?? []).map((id) => guides.find((g) => g.id === id || g.key === id)).filter((g): g is NonNullable<typeof g> => !!g && g.kind === \"checklist\"), [rc, guides]);\n if (!rc) return null;\n\n const close = () => client.closeResourceCenter();\n const modules = client.getResourceCenterModules();\n const announcements = client.getAnnouncements();\n const openArticle = (a: ResourceCenterArticle) => {\n if (a.externalUrl) return client.navigate(a.externalUrl);\n client.articleViewed(a);\n setArticle(a);\n };\n const row = (key: string, title: string, subtitle: string | undefined, onPress: () => void, icon = \"›\") => (\n <Pressable key={key} accessibilityRole=\"button\" accessibilityLabel={title} onPress={onPress} style={({ pressed }) => [styles.row, { borderColor: p.border, opacity: pressed ? 0.7 : 1 }]}>\n <View style={styles.flex}>\n <Text style={[styles.rowTitle, { color: p.text, fontFamily: p.fontFamily }]}>{title}</Text>\n {subtitle ? (\n <Text style={[styles.rowSub, { color: p.muted }]} numberOfLines={2}>\n {subtitle}\n </Text>\n ) : null}\n </View>\n <Text style={[styles.chev, { color: p.muted }]}>{icon}</Text>\n </Pressable>\n );\n const section = (title: string, children: React.ReactNode) => (\n <View style={styles.section} key={title}>\n <Text accessibilityRole=\"header\" style={[styles.sectionTitle, { color: p.muted }]}>\n {title.toUpperCase()}\n </Text>\n {children}\n </View>\n );\n // Nested collections read as \"Billing › Invoices\"; targeted articles show only to their audiences.\n const audiences = client.getAudienceIds();\n const sections = resourceCenterSections(rc.collections, rc.articles, audiences);\n const listed = modules.includes(\"search\") ? results?.filter((a) => isArticleListed(rc.collections, a, audiences)) : undefined;\n const link = (label: string, onPress: () => void) => (\n <Pressable key={label} accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={8}>\n <Text style={[styles.link, { color: p.primary }]}>{label}</Text>\n </Pressable>\n );\n // \"What's new\" entries published since the last visit keep a \"New\" mark while the sheet is open.\n const announcement = (a: ResourceCenterAnnouncement) => {\n const linked = a.articleId ? rc.articles.find((x) => x.id === a.articleId) : undefined;\n const isNew = client.isAnnouncementNew(a);\n return (\n <View key={a.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <View style={styles.faqHead}>\n <Text accessibilityRole=\"header\" style={[styles.rowTitle, styles.flex, { color: p.text, fontFamily: p.fontFamily }]}>\n {a.title}\n </Text>\n {isNew ? <Text style={[styles.badge, { color: p.onPrimary, backgroundColor: p.primary }]}>NEW</Text> : null}\n </View>\n {a.body ? <RichText html={a.body} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n {a.guideId || linked || a.url ? (\n <View style={styles.links}>\n {a.guideId ? link(\"Show me\", () => (close(), client.startGuide(a.guideId as string))) : null}\n {linked ? link(\"Read more\", () => openArticle(linked)) : null}\n {a.url ? link(a.linkLabel || \"Learn more\", () => client.navigate(a.url as string)) : null}\n </View>\n ) : null}\n </View>\n );\n };\n const renderModule = (id: (typeof modules)[number]) => {\n switch (id) {\n case \"announcements\":\n return announcements.length ? section(\"What's new\", announcements.map(announcement)) : null;\n case \"guides\":\n return recommended.length ? section(\"Recommended\", recommended.map((g) => row(g.id, g.name, undefined, () => (close(), client.startGuide(g.id)), \"▶\"))) : null;\n case \"checklists\":\n return checklists.length ? section(\"Checklists\", checklists.map((g) => row(g.id, g.name, undefined, () => (close(), client.openChecklist(g.id)), \"☑\"))) : null;\n case \"articles\":\n return sections.map((s) => section(s.collection ? s.path.join(\" › \") : \"Articles\", s.articles.map((a) => row(a.id, a.title, a.summary, () => openArticle(a)))));\n case \"faqs\":\n return rc.faqs.length\n ? section(\n \"FAQ\",\n rc.faqs.map((f) => (\n <View key={f.id} style={[styles.row, styles.faq, { borderColor: p.border }]}>\n <Pressable accessibilityRole=\"button\" accessibilityState={{ expanded: faq === f.id }} onPress={() => setFaq(faq === f.id ? null : f.id)} style={styles.faqHead}>\n <Text style={[styles.rowTitle, styles.flex, { color: p.text }]}>{f.question}</Text>\n <Text style={[styles.chev, { color: p.muted }]}>{faq === f.id ? \"−\" : \"+\"}</Text>\n </Pressable>\n {faq === f.id ? <RichText html={f.answer} palette={p} onLink={(u) => client.navigate(u)} size={14} /> : null}\n </View>\n )),\n )\n : null;\n case \"links\":\n return rc.links.length ? section(\"Links\", rc.links.map((l) => row(l.id, l.label, undefined, () => client.navigate(l.url), \"↗\"))) : null;\n default:\n return null; // \"search\" renders above the sections\n }\n };\n\n return (\n <Modal visible={open} animationType=\"slide\" presentationStyle={Platform.OS === \"ios\" ? \"pageSheet\" : \"fullScreen\"} onRequestClose={() => (article ? setArticle(null) : close())}>\n <View style={[styles.sheet, { backgroundColor: p.background, paddingTop: Platform.OS === \"ios\" ? 8 : topInset }]}>\n <View style={[styles.header, { borderColor: p.border }]}>\n {article ? (\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Back\" onPress={() => setArticle(null)} hitSlop={10}>\n <Text style={[styles.back, { color: p.primary }]}>‹ Back</Text>\n </Pressable>\n ) : null}\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]} numberOfLines={1}>\n {article ? \"\" : rc.title}\n </Text>\n <CloseButton palette={p} onPress={close} label=\"Close help\" />\n </View>\n {article ? (\n <ScrollView contentContainerStyle={[styles.content, { paddingBottom: bottomInset + 24 }]}>\n <Text accessibilityRole=\"header\" style={[styles.articleTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {article.title}\n </Text>\n <RichText html={article.body} palette={p} onLink={(u) => client.navigate(u)} />\n </ScrollView>\n ) : (\n <ScrollView contentContainerStyle={[styles.content, { paddingBottom: bottomInset + 24 }]} keyboardShouldPersistTaps=\"handled\">\n {modules.includes(\"search\") ? (\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search help articles\"\n placeholderTextColor={p.muted}\n accessibilityLabel=\"Search help articles\"\n clearButtonMode=\"while-editing\"\n returnKeyType=\"search\"\n style={[styles.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }]}\n />\n ) : null}\n {listed ? (\n section(\n `Results for “${query.trim()}”`,\n listed.length ? listed.map((a) => row(a.id, a.title, a.summary, () => openArticle(a))) : <Text style={[styles.rowSub, { color: p.muted }]}>No articles found.</Text>,\n )\n ) : (\n <>\n {modules.filter((id) => id !== \"search\").map((id) => (\n <Fragment key={id}>{renderModule(id)}</Fragment>\n ))}\n </>\n )}\n </ScrollView>\n )}\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n sheet: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\", gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: StyleSheet.hairlineWidth },\n back: { fontSize: 16, fontWeight: \"600\" },\n title: { flex: 1, fontSize: 18, fontWeight: \"700\" },\n content: { padding: 16, gap: 18 },\n search: { height: 42, paddingHorizontal: 12, fontSize: 15 },\n section: { gap: 8 },\n sectionTitle: { fontSize: 12, fontWeight: \"700\", letterSpacing: 0.6 },\n row: { flexDirection: \"row\", alignItems: \"center\", gap: 10, borderWidth: StyleSheet.hairlineWidth, borderRadius: 10, paddingVertical: 12, paddingHorizontal: 12 },\n rowTitle: { fontSize: 15, fontWeight: \"600\" },\n rowSub: { fontSize: 13, marginTop: 2 },\n chev: { fontSize: 18 },\n faq: { flexDirection: \"column\", alignItems: \"stretch\" },\n faqHead: { flexDirection: \"row\", alignItems: \"center\", gap: 10 },\n articleTitle: { fontSize: 22, fontWeight: \"700\" },\n badge: { fontSize: 10, fontWeight: \"800\", letterSpacing: 0.5, paddingHorizontal: 6, paddingVertical: 2, borderRadius: 6, overflow: \"hidden\" },\n links: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 16, marginTop: 4 },\n link: { fontSize: 14, fontWeight: \"600\" },\n});\n","import { useEffect, useRef, useState } from \"react\";\nimport { AccessibilityInfo, Animated, Easing, Pressable, StyleSheet, View, type LayoutChangeEvent } from \"react-native\";\nimport { positionCard, type Insets, type Side } from \"../core/position\";\nimport type { Rect } from \"../core/targets\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { StepView } from \"../core/types\";\nimport { announcement, StepCard } from \"./StepCard\";\nimport type { Palette } from \"./theme\";\n\nexport interface LayerGeometry {\n /** Overlay origin in window coordinates (targets are measured in window coordinates). */\n origin: { x: number; y: number };\n viewport: { width: number; height: number };\n insets: Insets;\n}\n\n/** Tracks a target's frame (relative to the overlay) while a step is shown: layout changes, scrolling, rotation. */\nfunction useTargetRect(client: GuidelyClient, targetId: string | null, origin: { x: number; y: number }): Rect | null {\n const [rect, setRect] = useState<Rect | null>(null);\n useEffect(() => {\n if (!targetId) {\n setRect(null);\n return;\n }\n let alive = true;\n const measure = async () => {\n const r = await client.targets.measure(targetId);\n if (!alive) return;\n setRect((prev) => {\n const next = r ? { x: r.x - origin.x, y: r.y - origin.y, width: r.width, height: r.height } : null;\n if (prev && next && Math.abs(prev.x - next.x) < 0.5 && Math.abs(prev.y - next.y) < 0.5 && prev.width === next.width && prev.height === next.height) return prev;\n return next;\n });\n };\n void measure();\n const off = client.targets.onChange(() => void measure());\n const timer = setInterval(() => void measure(), 250);\n return () => {\n alive = false;\n off();\n clearInterval(timer);\n };\n }, [client, targetId, origin.x, origin.y]);\n return rect;\n}\n\nfunction useFadeIn(key: string) {\n const opacity = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n opacity.setValue(0);\n Animated.timing(opacity, { toValue: 1, duration: 160, easing: Easing.out(Easing.quad), useNativeDriver: true }).start();\n }, [key, opacity]);\n return opacity;\n}\n\nexport function StepLayer({ view, client, palette: p, geometry }: { view: StepView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry }) {\n const { step } = view;\n const rect = useTargetRect(client, view.asModal ? null : view.targetId, geometry.origin);\n const opacity = useFadeIn(view.key);\n const { viewport, insets } = geometry;\n const cardWidth = Math.min(viewport.width - 32, step.width ?? 340);\n\n useEffect(() => {\n if (step.type === \"hotspot\" && !view.expanded) return;\n AccessibilityInfo.announceForAccessibility?.(announcement(view));\n }, [view.key, view.expanded]);\n\n const backdrop = (children?: React.ReactNode) => (\n <Pressable accessible={false} style={[StyleSheet.absoluteFill, { backgroundColor: p.overlay }]} onPress={() => client.backdropPressed(view.guide.id)}>\n {children}\n </Pressable>\n );\n\n // Modal-like: real modals, steps whose target is missing (fallback), and step types without an anchor.\n const anchored = !view.asModal && [\"tooltip\", \"popover\", \"spotlight\", \"hotspot\"].includes(step.type);\n if (!anchored && step.type === \"banner\") {\n const top = step.position.startsWith(\"top\");\n return (\n <Animated.View pointerEvents=\"box-none\" style={[styles.banner, top ? { top: insets.top + 8 } : { bottom: insets.bottom + 8 }, { left: insets.left + 8, right: insets.right + 8, opacity }]}>\n <StepCard view={view} client={client} palette={p} width={viewport.width - insets.left - insets.right - 16} compact />\n </Animated.View>\n );\n }\n if (!anchored && step.type === \"slideout\") {\n const wide = viewport.width >= 600;\n const right = !step.position.endsWith(\"left\");\n const width = wide ? Math.min(380, cardWidth) : viewport.width - insets.left - insets.right - 24;\n return (\n <Animated.View pointerEvents=\"box-none\" style={[styles.abs, { bottom: insets.bottom + 12, opacity }, wide ? (right ? { right: insets.right + 16 } : { left: insets.left + 16 }) : { left: insets.left + 12 }]}>\n <StepCard view={view} client={client} palette={p} width={width} />\n </Animated.View>\n );\n }\n if (!anchored) {\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, styles.center, { opacity }]}>\n {step.showOverlay ? backdrop() : null}\n <StepCard view={view} client={client} palette={p} width={Math.min(viewport.width - 40, step.width ?? 360)} />\n </Animated.View>\n );\n }\n if (!rect) return null;\n\n if (step.type === \"hotspot\") {\n const size = step.hotspot?.size ?? 14;\n return (\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n <Hotspot x={rect.x + rect.width - size / 2} y={rect.y - size / 2} size={size} pulse={step.hotspot?.pulse ?? true} color={p.primary} onPress={() => client.toggleHotspot(view.guide.id)} label={step.title || \"Show tip\"} />\n {view.expanded ? <Anchored view={view} client={client} palette={p} geometry={geometry} rect={rect} width={cardWidth} /> : null}\n </View>\n );\n }\n\n if (step.type === \"spotlight\") {\n const pad = step.spotlightPadding;\n const hole = { x: rect.x - pad, y: rect.y - pad, width: rect.width + pad * 2, height: rect.height + pad * 2 };\n const r = Math.max(0, Math.min(12, p.radius, hole.width / 2, hole.height / 2));\n const shade = { backgroundColor: p.overlay };\n const press = () => client.backdropPressed(view.guide.id);\n // Corner pieces dim what lies inside the hole's rectangle but outside its rounded corners.\n const corners: Array<[number, number, number, number]> = [\n [hole.x, hole.y, -r, -r],\n [hole.x + hole.width - r, hole.y, -2 * r, -r],\n [hole.x, hole.y + hole.height - r, -r, -2 * r],\n [hole.x + hole.width - r, hole.y + hole.height - r, -2 * r, -2 * r],\n ];\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { opacity }]}>\n {/* Four panes around the hole: the highlighted element itself stays tappable. */}\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, right: 0, top: 0, height: Math.max(0, hole.y) }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, right: 0, top: hole.y + hole.height, bottom: 0 }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: 0, width: Math.max(0, hole.x), top: hole.y, height: hole.height }]} />\n <Pressable accessible={false} onPress={press} style={[styles.abs, shade, { left: hole.x + hole.width, right: 0, top: hole.y, height: hole.height }]} />\n {r > 0\n ? corners.map(([left, top, dx, dy], i) => (\n <View key={i} pointerEvents=\"none\" style={[styles.abs, { left, top, width: r, height: r, overflow: \"hidden\" }]}>\n <View style={[styles.abs, { left: dx, top: dy, width: 4 * r, height: 4 * r, borderRadius: 2 * r, borderWidth: r, borderColor: p.overlay }]} />\n </View>\n ))\n : null}\n <View pointerEvents=\"none\" style={[styles.abs, { left: hole.x, top: hole.y, width: hole.width, height: hole.height, borderRadius: r, borderWidth: 2, borderColor: p.primary }]} />\n <Anchored view={view} client={client} palette={p} geometry={geometry} rect={hole} width={cardWidth} />\n </Animated.View>\n );\n }\n\n return (\n <Animated.View pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { opacity }]}>\n {step.showOverlay ? backdrop() : null}\n <Anchored view={view} client={client} palette={p} geometry={geometry} rect={rect} width={cardWidth} />\n </Animated.View>\n );\n}\n\nconst ARROW = 12;\n\n/** A card placed next to `rect` with an arrow pointing at it. */\nfunction Anchored({ view, client, palette: p, geometry, rect, width }: { view: StepView; client: GuidelyClient; palette: Palette; geometry: LayerGeometry; rect: Rect; width: number }) {\n const [height, setHeight] = useState(0);\n const onLayout = (e: LayoutChangeEvent) => setHeight(Math.round(e.nativeEvent.layout.height));\n const offset = view.step.offset + ARROW / 2;\n const pos = positionCard(rect, { width, height: height || 120 }, geometry.viewport, geometry.insets, view.step.placement, offset);\n return (\n <View pointerEvents=\"box-none\" style={[styles.abs, { left: pos.x, top: pos.y, width, opacity: height ? 1 : 0 }]} onLayout={onLayout}>\n <Arrow side={pos.side} at={pos.arrow} color={p.background} border={p.border} />\n <StepCard view={view} client={client} palette={p} width={width} />\n </View>\n );\n}\n\nfunction Arrow({ side, at, color, border }: { side: Side; at: number; color: string; border: string }) {\n const half = ARROW / 2;\n const place =\n side === \"bottom\" ? { top: -half, left: at - half } : side === \"top\" ? { bottom: -half, left: at - half } : side === \"right\" ? { left: -half, top: at - half } : { right: -half, top: at - half };\n return <View pointerEvents=\"none\" style={[styles.abs, styles.arrow, place, { backgroundColor: color, borderColor: border }]} />;\n}\n\nfunction Hotspot({ x, y, size, pulse, color, onPress, label }: { x: number; y: number; size: number; pulse: boolean; color: string; onPress: () => void; label: string }) {\n const scale = useRef(new Animated.Value(0)).current;\n const [reduceMotion, setReduceMotion] = useState(false);\n useEffect(() => {\n let alive = true;\n AccessibilityInfo.isReduceMotionEnabled?.().then((v) => alive && setReduceMotion(v), () => {});\n return () => {\n alive = false;\n };\n }, []);\n useEffect(() => {\n if (!pulse || reduceMotion) return;\n const loop = Animated.loop(Animated.timing(scale, { toValue: 1, duration: 1400, easing: Easing.out(Easing.ease), useNativeDriver: true }));\n loop.start();\n return () => loop.stop();\n }, [pulse, reduceMotion, scale]);\n return (\n <Pressable accessibilityRole=\"button\" accessibilityLabel={label} onPress={onPress} hitSlop={14} style={[styles.abs, { left: x, top: y, width: size, height: size }]}>\n {pulse && !reduceMotion ? (\n <Animated.View\n pointerEvents=\"none\"\n style={[styles.abs, { width: size, height: size, borderRadius: size / 2, backgroundColor: color, opacity: scale.interpolate({ inputRange: [0, 1], outputRange: [0.55, 0] }), transform: [{ scale: scale.interpolate({ inputRange: [0, 1], outputRange: [1, 2.6] }) }] }]}\n />\n ) : null}\n <View style={{ width: size, height: size, borderRadius: size / 2, backgroundColor: color, borderWidth: 2, borderColor: \"#ffffff\" }} />\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create({\n abs: { position: \"absolute\" },\n center: { alignItems: \"center\", justifyContent: \"center\" },\n banner: { position: \"absolute\" },\n arrow: { width: ARROW, height: ARROW, transform: [{ rotate: \"45deg\" }], borderWidth: StyleSheet.hairlineWidth },\n});\n","import type { Placement } from \"@guidelytech/shared\";\nimport type { Rect } from \"./targets\";\n\nexport type Side = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface Insets {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\nexport interface CardPosition {\n x: number;\n y: number;\n side: Side;\n /** Arrow centre along the card edge facing the target (px from the card's left/top). */\n arrow: number;\n}\n\nconst MARGIN = 12;\nconst ARROW_INSET = 18;\n\nconst opposite: Record<Side, Side> = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" };\n\n/**\n * Places a card of `size` next to `target` inside `viewport` minus `insets`, honouring the step's\n * placement when it fits and flipping (then falling back to below/above) when it does not.\n */\nexport function positionCard(target: Rect, size: { width: number; height: number }, viewport: { width: number; height: number }, insets: Insets, placement: Placement, offset: number): CardPosition {\n const [rawSide, align] = placement.split(\"-\") as [Side | \"auto\", \"start\" | \"end\" | undefined];\n const fits = (side: Side) => {\n switch (side) {\n case \"bottom\":\n return target.y + target.height + offset + size.height <= viewport.height - insets.bottom - MARGIN;\n case \"top\":\n return target.y - offset - size.height >= insets.top + MARGIN;\n case \"right\":\n return target.x + target.width + offset + size.width <= viewport.width - insets.right - MARGIN;\n case \"left\":\n return target.x - offset - size.width >= insets.left + MARGIN;\n }\n };\n const order: Side[] = rawSide === \"auto\" ? [\"bottom\", \"top\"] : [rawSide, opposite[rawSide], \"bottom\", \"top\"];\n const space = { top: target.y - insets.top, bottom: viewport.height - insets.bottom - (target.y + target.height) };\n const side = order.find(fits) ?? (space.bottom >= space.top ? \"bottom\" : \"top\");\n\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n if (side === \"top\" || side === \"bottom\") {\n const cx = target.x + target.width / 2;\n let x = align === \"start\" ? target.x : align === \"end\" ? target.x + target.width - size.width : cx - size.width / 2;\n x = clamp(x, insets.left + MARGIN, Math.max(insets.left + MARGIN, viewport.width - insets.right - MARGIN - size.width));\n let y = side === \"bottom\" ? target.y + target.height + offset : target.y - offset - size.height;\n y = clamp(y, insets.top + MARGIN, Math.max(insets.top + MARGIN, viewport.height - insets.bottom - MARGIN - size.height));\n return { x, y, side, arrow: clamp(cx - x, ARROW_INSET, size.width - ARROW_INSET) };\n }\n const cy = target.y + target.height / 2;\n let y = align === \"start\" ? target.y : align === \"end\" ? target.y + target.height - size.height : cy - size.height / 2;\n y = clamp(y, insets.top + MARGIN, Math.max(insets.top + MARGIN, viewport.height - insets.bottom - MARGIN - size.height));\n const x = side === \"right\" ? target.x + target.width + offset : target.x - offset - size.width;\n return { x, y, side, arrow: clamp(cy - y, ARROW_INSET, size.height - ARROW_INSET) };\n}\n","import { Image, StyleSheet, Text, View, type StyleProp, type ViewStyle } from \"react-native\";\nimport { htmlToText } from \"../core/html\";\nimport { visibleButtons } from \"../core/controller\";\nimport type { StepView } from \"../core/types\";\nimport type { GuidelyClient } from \"../core/client\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { Palette } from \"./theme\";\n\n/** Title, image, rich-text body, progress, close and buttons for one step. */\nexport function StepCard({ view, client, palette: p, width, style, compact }: { view: StepView; client: GuidelyClient; palette: Palette; width: number; style?: StyleProp<ViewStyle>; compact?: boolean }) {\n const { step, guide } = view;\n const buttons = visibleButtons(step, view.canGoBack);\n // Custom HTML steps have no chrome on the web; on mobile they become a plain card.\n const body = step.type === \"custom\" ? step.customHtml || step.body : step.body;\n const showProgress = step.showProgress && view.total > 1;\n const onLink = (url: string) => client.navigate(url);\n return (\n <Surface palette={p} style={[{ width }, style]}>\n <View accessible={false} accessibilityViewIsModal={view.asModal || step.type === \"modal\"} style={compact ? styles.compact : styles.inner}>\n {step.imageUrl ? (\n // An empty description marks the image as decorative: screen readers skip it.\n <Image\n source={{ uri: step.imageUrl }}\n style={[styles.image, { borderRadius: Math.max(0, p.radius - 4) }]}\n resizeMode=\"cover\"\n accessibilityIgnoresInvertColors\n {...(step.imageAlt?.trim() ? { accessible: true, accessibilityRole: \"image\" as const, accessibilityLabel: step.imageAlt.trim() } : { accessible: false, importantForAccessibility: \"no\" as const })}\n />\n ) : null}\n {step.title ? (\n <View style={styles.header}>\n <Text accessibilityRole=\"header\" style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}>\n {step.title}\n </Text>\n {step.showClose ? <CloseButton palette={p} onPress={() => client.closeStep(guide.id)} label=\"Dismiss guide\" /> : null}\n </View>\n ) : null}\n {body ? (\n // Without a title the close button floats beside the body instead of taking a row.\n <View style={!step.title && step.showClose ? styles.bodyBesideClose : undefined}>\n <RichText html={body} palette={p} onLink={onLink} />\n </View>\n ) : null}\n {!step.title && step.showClose ? (\n <View style={compact ? styles.floatingCloseCompact : styles.floatingClose}>\n <CloseButton palette={p} onPress={() => client.closeStep(guide.id)} label=\"Dismiss guide\" />\n </View>\n ) : null}\n {showProgress || buttons.length ? (\n <View style={styles.footer}>\n {showProgress ? (\n <Text style={[styles.progress, { color: p.muted }]} accessibilityLabel={`Step ${view.index + 1} of ${view.total}`}>\n {view.index + 1} of {view.total}\n </Text>\n ) : (\n <View style={styles.flex} />\n )}\n <View style={styles.buttons}>\n {buttons.map((b) => (\n <GButton key={b.id} label={b.label} variant={b.variant} palette={p} onPress={() => client.pressButton(guide.id, b)} />\n ))}\n </View>\n </View>\n ) : null}\n </View>\n </Surface>\n );\n}\n\n/** Text read by screen readers when a step appears. */\nexport function announcement(view: StepView): string {\n const parts = [view.step.title, htmlToText(view.step.body)].filter(Boolean);\n if (view.total > 1) parts.push(`Step ${view.index + 1} of ${view.total}`);\n return parts.join(\". \");\n}\n\nconst styles = StyleSheet.create({\n inner: { padding: 16, gap: 10 },\n compact: { paddingHorizontal: 14, paddingVertical: 10, gap: 6 },\n image: { width: \"100%\", height: 140, marginBottom: 2 },\n header: { flexDirection: \"row\", alignItems: \"flex-start\", gap: 8 },\n title: { flex: 1, fontSize: 17, fontWeight: \"700\", lineHeight: 22 },\n flex: { flex: 1 },\n bodyBesideClose: { paddingRight: 24 },\n floatingClose: { position: \"absolute\", top: 16, right: 16 },\n floatingCloseCompact: { position: \"absolute\", top: 10, right: 14 },\n footer: { flexDirection: \"row\", alignItems: \"center\", gap: 8, marginTop: 4, flexWrap: \"wrap\" },\n progress: { flex: 1, fontSize: 12, fontWeight: \"500\" },\n buttons: { flexDirection: \"row\", gap: 8, flexWrap: \"wrap\", justifyContent: \"flex-end\" },\n});\n","import { useEffect, useState } from \"react\";\nimport {\n AccessibilityInfo,\n KeyboardAvoidingView,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n Text,\n TextInput,\n View,\n} from \"react-native\";\nimport { isQuestionVisible, type SurveyAnswers } from \"@guidelytech/shared/runtime\";\nimport type { SurveyQuestion } from \"@guidelytech/shared\";\nimport type { GuidelyClient } from \"../core/client\";\nimport type { SurveyView } from \"../core/types\";\nimport { CloseButton, GButton, Surface } from \"./primitives\";\nimport { RichText } from \"./RichText\";\nimport type { LayerGeometry } from \"./StepLayer\";\nimport type { Palette } from \"./theme\";\n\n/** Survey card: every visible question at once (like the web SDK), required checks, thank-you state. */\nexport function Survey({\n view,\n client,\n palette: p,\n geometry,\n}: {\n view: SurveyView;\n client: GuidelyClient;\n palette: Palette;\n geometry: LayerGeometry;\n}) {\n const config = view.guide.config.survey;\n const [answers, setAnswers] = useState<SurveyAnswers>({});\n const [error, setError] = useState(\"\");\n useEffect(() => {\n setAnswers({});\n setError(\"\");\n AccessibilityInfo.announceForAccessibility?.(\n `Survey: ${config?.questions[0]?.title ?? view.guide.name}`,\n );\n }, [view.key]);\n if (!config) return null;\n const { insets, viewport } = geometry;\n const width = Math.min(viewport.width - insets.left - insets.right - 24, 420);\n const centered = config.position === \"center\";\n\n const set = (id: string, value: SurveyAnswers[string] | undefined) =>\n setAnswers((prev) => {\n const next = { ...prev };\n if (value === undefined) delete next[id];\n else next[id] = value;\n // Hidden follow-ups lose their answers, as on the web.\n for (const q of config.questions)\n if (!isQuestionVisible(q, next) && next[q.id] !== undefined) delete next[q.id];\n return next;\n });\n const submit = () => {\n const missing = config.questions.filter(\n (q) => q.required && isQuestionVisible(q, answers) && answers[q.id] === undefined,\n );\n if (missing.length) {\n setError(`Please answer: ${missing.map((q) => q.title).join(\", \")}`);\n return;\n }\n setError(\"\");\n client.submitSurvey(view.guide.id, { ...answers });\n };\n const close = () => client.closeSurvey(view.guide.id);\n\n return (\n // KeyboardAvoidingView owns its bottom padding, so the safe-area padding lives on an inner view.\n <KeyboardAvoidingView\n pointerEvents=\"box-none\"\n behavior={Platform.OS === \"ios\" ? \"padding\" : undefined}\n style={StyleSheet.absoluteFill}\n >\n {centered ? (\n <Pressable\n accessible={false}\n style={[StyleSheet.absoluteFill, { backgroundColor: p.overlay }]}\n onPress={close}\n />\n ) : null}\n <View\n pointerEvents=\"box-none\"\n style={[\n styles.fill,\n centered ? styles.center : styles.bottom,\n !centered && { paddingBottom: insets.bottom + 12 },\n ]}\n >\n <Surface\n palette={p}\n style={{ width, maxHeight: viewport.height - insets.top - insets.bottom - 40 }}\n >\n {view.submitted ? (\n <View style={styles.inner}>\n <Text\n accessibilityRole=\"header\"\n style={[styles.title, { color: p.text, fontFamily: p.fontFamily }]}\n >\n {config.thankYouTitle}\n </Text>\n {config.thankYouBody ? (\n <RichText\n html={config.thankYouBody}\n palette={p}\n onLink={(u) => client.navigate(u)}\n />\n ) : null}\n <GButton label=\"Done\" palette={p} onPress={close} style={styles.end} />\n </View>\n ) : (\n <ScrollView contentContainerStyle={styles.inner} keyboardShouldPersistTaps=\"handled\">\n {config.questions\n .filter((q) => isQuestionVisible(q, answers))\n .map((q, i) => (\n <View key={q.id} style={styles.question}>\n <View style={styles.head}>\n <Text style={[styles.qTitle, { color: p.text, fontFamily: p.fontFamily }]}>\n {q.title}\n {!q.required ? (\n <Text style={{ color: p.muted, fontWeight: \"400\" }}> (optional)</Text>\n ) : null}\n </Text>\n {i === 0 ? (\n <CloseButton palette={p} onPress={close} label=\"Dismiss survey\" />\n ) : null}\n </View>\n {q.description ? (\n <Text style={[styles.desc, { color: p.muted }]}>{q.description}</Text>\n ) : null}\n <QuestionInput\n q={q}\n value={answers[q.id]}\n onChange={(v) => set(q.id, v)}\n palette={p}\n />\n </View>\n ))}\n {error ? (\n <Text accessibilityLiveRegion=\"polite\" style={[styles.error]}>\n {error}\n </Text>\n ) : null}\n <GButton label=\"Submit\" palette={p} onPress={submit} style={styles.end} />\n </ScrollView>\n )}\n </Surface>\n </View>\n </KeyboardAvoidingView>\n );\n}\n\nfunction QuestionInput({\n q,\n value,\n onChange,\n palette: p,\n}: {\n q: SurveyQuestion;\n value: SurveyAnswers[string] | undefined;\n onChange: (v: SurveyAnswers[string] | undefined) => void;\n palette: Palette;\n}) {\n const chip = (selected: boolean) => [\n styles.chip,\n {\n borderColor: selected ? p.primary : p.border,\n backgroundColor: selected ? p.primary : p.background,\n borderRadius: Math.min(8, p.radius),\n },\n ];\n const chipText = (selected: boolean) => [\n styles.chipText,\n { color: selected ? p.onPrimary : p.text },\n ];\n switch (q.type) {\n case \"nps\":\n case \"csat\": {\n const min = q.type === \"nps\" ? 0 : 1;\n const max = q.type === \"nps\" ? 10 : (q.scaleMax ?? 5);\n const values = Array.from({ length: max - min + 1 }, (_, i) => min + i);\n return (\n <View>\n <View style={styles.scale} accessibilityRole=\"radiogroup\" accessibilityLabel={q.title}>\n {values.map((n) => (\n <Pressable\n key={n}\n accessibilityRole=\"radio\"\n accessibilityState={{ selected: value === n }}\n accessibilityLabel={String(n)}\n onPress={() => onChange(n)}\n style={[...chip(value === n), styles.scaleItem]}\n >\n <Text style={chipText(value === n)}>{n}</Text>\n </Pressable>\n ))}\n </View>\n {q.lowLabel || q.highLabel ? (\n <View style={styles.labels}>\n <Text style={[styles.small, { color: p.muted }]}>{q.lowLabel}</Text>\n <Text style={[styles.small, { color: p.muted }]}>{q.highLabel}</Text>\n </View>\n ) : null}\n </View>\n );\n }\n case \"rating\": {\n const max = q.scaleMax ?? 5;\n return (\n <View style={styles.stars} accessibilityRole=\"radiogroup\" accessibilityLabel={q.title}>\n {Array.from({ length: max }, (_, i) => i + 1).map((n) => (\n <Pressable\n key={n}\n accessibilityRole=\"radio\"\n accessibilityLabel={`${n} of ${max}`}\n accessibilityState={{ selected: value === n }}\n onPress={() => onChange(n)}\n hitSlop={4}\n >\n <Text\n style={[\n styles.star,\n { color: typeof value === \"number\" && n <= value ? p.primary : p.border },\n ]}\n >\n ★\n </Text>\n </Pressable>\n ))}\n </View>\n );\n }\n case \"thumbs\":\n return (\n <View style={styles.row} accessibilityRole=\"radiogroup\">\n {[\n [true, \"👍\", \"Thumbs up\"],\n [false, \"👎\", \"Thumbs down\"],\n ].map(([val, icon, label]) => (\n <Pressable\n key={String(val)}\n accessibilityRole=\"radio\"\n accessibilityLabel={label as string}\n accessibilityState={{ selected: value === val }}\n onPress={() => onChange(val as boolean)}\n style={[...chip(value === val), styles.thumb]}\n >\n <Text style={styles.thumbText}>{icon as string}</Text>\n </Pressable>\n ))}\n </View>\n );\n case \"single_choice\":\n case \"multiple_choice\": {\n const multi = q.type === \"multiple_choice\";\n const selected = new Set(\n multi\n ? ((value as string[] | undefined) ?? [])\n : value !== undefined\n ? [String(value)]\n : [],\n );\n return (\n <View style={styles.choices}>\n {q.options.map((o) => {\n const on = selected.has(o.id);\n return (\n <Pressable\n key={o.id}\n accessibilityRole={multi ? \"checkbox\" : \"radio\"}\n accessibilityState={{ checked: on }}\n accessibilityLabel={o.label}\n onPress={() => {\n if (!multi) return onChange(o.id);\n const next = new Set(selected);\n if (on) next.delete(o.id);\n else next.add(o.id);\n onChange(next.size ? Array.from(next) : undefined);\n }}\n style={[\n styles.choice,\n { borderColor: on ? p.primary : p.border, borderRadius: Math.min(10, p.radius) },\n ]}\n >\n <View\n style={[\n styles.dot,\n multi && styles.box,\n {\n borderColor: on ? p.primary : p.border,\n backgroundColor: on ? p.primary : \"transparent\",\n },\n ]}\n />\n <Text style={[styles.choiceText, { color: p.text }]}>{o.label}</Text>\n </Pressable>\n );\n })}\n </View>\n );\n }\n case \"text\":\n default:\n return (\n <TextInput\n accessibilityLabel={q.title}\n multiline\n value={typeof value === \"string\" ? value : \"\"}\n onChangeText={(t) => onChange(t ? t.slice(0, 5000) : undefined)}\n placeholder={q.placeholder || \"\"}\n placeholderTextColor={p.muted}\n style={[\n styles.input,\n {\n color: p.text,\n borderColor: p.border,\n borderRadius: Math.min(10, p.radius),\n backgroundColor: p.surface,\n },\n ]}\n />\n );\n }\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n center: { alignItems: \"center\", justifyContent: \"center\" },\n bottom: { alignItems: \"center\", justifyContent: \"flex-end\" },\n inner: { padding: 16, gap: 14 },\n title: { fontSize: 17, fontWeight: \"700\" },\n end: { alignSelf: \"flex-end\" },\n question: { gap: 8 },\n head: { flexDirection: \"row\", gap: 8, alignItems: \"flex-start\" },\n qTitle: { flex: 1, fontSize: 15, fontWeight: \"600\", lineHeight: 20 },\n desc: { fontSize: 13 },\n scale: { flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 },\n scaleItem: { flexGrow: 1, flexBasis: 26 },\n chip: {\n borderWidth: 1,\n minHeight: 36,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: 4,\n },\n chipText: { fontSize: 14, fontWeight: \"600\" },\n labels: { flexDirection: \"row\", justifyContent: \"space-between\", marginTop: 4 },\n small: { fontSize: 12 },\n stars: { flexDirection: \"row\", gap: 6 },\n star: { fontSize: 30 },\n row: { flexDirection: \"row\", gap: 10 },\n thumb: { width: 56, height: 44 },\n thumbText: { fontSize: 22 },\n choices: { gap: 8 },\n choice: {\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n borderWidth: 1,\n paddingVertical: 10,\n paddingHorizontal: 12,\n },\n dot: { width: 18, height: 18, borderRadius: 9, borderWidth: 2 },\n box: { borderRadius: 4 },\n choiceText: { fontSize: 15, flex: 1 },\n input: { minHeight: 80, borderWidth: 1, padding: 10, fontSize: 15, textAlignVertical: \"top\" },\n error: { color: \"#dc2626\", fontSize: 13 },\n});\n","import type { ProjectTheme } from \"@guidelytech/shared\";\n\nexport interface Palette {\n primary: string;\n onPrimary: string;\n background: string;\n text: string;\n muted: string;\n border: string;\n surface: string;\n radius: number;\n overlay: string;\n fontFamily?: string;\n}\n\nconst DARK = { background: \"#18181b\", text: \"#f4f4f5\", muted: \"#a1a1aa\", border: \"#3f3f46\", surface: \"#27272a\" };\n\nfunction luminance(hex: string): number {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex);\n if (!m) return 1;\n const n = parseInt(m[1] as string, 16);\n const ch = [(n >> 16) & 255, (n >> 8) & 255, n & 255].map((c) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * (ch[0] as number) + 0.7152 * (ch[1] as number) + 0.0722 * (ch[2] as number);\n}\n\nfunction mix(hex: string, alpha: number): string {\n const a = Math.round(Math.max(0, Math.min(1, alpha)) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return /^#[0-9a-f]{6}$/i.test(hex) ? `${hex}${a}` : hex;\n}\n\n/** RN only understands a few system font names; web font stacks like \"Inter, system-ui\" are ignored. */\nfunction nativeFont(stack?: string): string | undefined {\n const first = stack?.split(\",\")[0]?.trim().replace(/^[\"']|[\"']$/g, \"\");\n if (!first || /^(system-ui|-apple-system|sans-serif|serif|monospace|inter|ui-sans-serif)$/i.test(first)) return undefined;\n return first;\n}\n\n/**\n * Colours for guide UI. The project theme is designed for light backgrounds; `dark` (or `auto` with a\n * dark system scheme) swaps background/text unless the guide set explicit colours.\n */\nexport function palette(theme: Partial<ProjectTheme> & { dark?: \"light\" | \"dark\" | \"auto\"; overlayOpacity?: number }, systemScheme: string | null | undefined, explicit?: { backgroundColor?: string; textColor?: string }): Palette {\n const primary = theme.primaryColor ?? \"#4f46e5\";\n const wantsDark = theme.dark === \"dark\" || (theme.dark === \"auto\" && systemScheme === \"dark\");\n const dark = wantsDark && !explicit?.backgroundColor;\n const background = dark ? DARK.background : (theme.backgroundColor ?? \"#ffffff\");\n const text = dark ? DARK.text : (theme.textColor ?? \"#111827\");\n return {\n primary,\n onPrimary: luminance(primary) > 0.45 ? \"#111827\" : \"#ffffff\",\n background,\n text,\n muted: dark ? DARK.muted : mix(text, 0.65),\n border: dark ? DARK.border : mix(text, 0.12),\n surface: dark ? DARK.surface : mix(text, 0.05),\n radius: theme.borderRadius ?? 12,\n overlay: `rgba(15, 23, 42, ${theme.overlayOpacity ?? 0.55})`,\n fontFamily: nativeFont(theme.fontFamily),\n };\n}\n","import { createContext, useCallback, useContext, useEffect, useRef, type ReactNode } from \"react\";\nimport { View, type GestureResponderEvent, type LayoutChangeEvent, type StyleProp, type ViewProps, type ViewStyle } from \"react-native\";\nimport type { GuidelyClient } from \"../core/client\";\n\nexport const GuidelyContext = createContext<GuidelyClient | null>(null);\n\n/** Name of the screen a subtree belongs to; see {@link GuidelyScreenScope}. */\nexport const GuidelyScreenContext = createContext<string | null>(null);\n\n/**\n * Declares which screen its children are on, so targets on screens that are mounted but not\n * visible (inactive tabs, screens under a stack) are never used. `name` must match what you pass\n * to `screen()`. With React Navigation, use {@link guidelyScreenLayout} instead of wrapping by hand.\n */\nexport function GuidelyScreenScope({ name, children }: { name: string; children?: ReactNode }) {\n return <GuidelyScreenContext.Provider value={name}>{children}</GuidelyScreenContext.Provider>;\n}\n\n/**\n * React Navigation 7 `screenLayout`: scopes every screen of a navigator to its route name.\n * `<Tab.Navigator screenLayout={guidelyScreenLayout}>`.\n */\nexport function guidelyScreenLayout({ route, children }: { route: { name: string }; children: ReactNode }) {\n return <GuidelyScreenScope name={route.name}>{children}</GuidelyScreenScope>;\n}\n\nconst TAP_SLOP = 10;\n\n/**\n * Props to spread on an existing view so guides can point at it, without adding a wrapper:\n * `const target = useGuidelyTarget(\"new-deal-button\"); <Pressable {...target}>…</Pressable>`.\n * Taps are observed, never intercepted.\n */\nexport function useGuidelyTarget(id: string) {\n const client = useContext(GuidelyContext);\n const screen = useContext(GuidelyScreenContext);\n const ref = useRef<View>(null);\n const start = useRef<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!client || !id) return;\n return client.targets.register(id, {\n screen,\n measure: () =>\n new Promise((resolve) => {\n const node = ref.current;\n if (!node || typeof node.measureInWindow !== \"function\") return resolve(null);\n node.measureInWindow((x, y, width, height) => resolve(Number.isFinite(x) ? { x, y, width, height } : null));\n }),\n });\n }, [client, id, screen]);\n\n const onLayout = useCallback(() => client?.targets.changed(), [client]);\n const onTouchStart = useCallback((e: GestureResponderEvent) => {\n start.current = { x: e.nativeEvent.pageX, y: e.nativeEvent.pageY };\n }, []);\n const onTouchEnd = useCallback(\n (e: GestureResponderEvent) => {\n const s = start.current;\n start.current = null;\n // A drag or scroll that happens to end on the view is not a tap.\n if (s && Math.abs(e.nativeEvent.pageX - s.x) < TAP_SLOP && Math.abs(e.nativeEvent.pageY - s.y) < TAP_SLOP) client?.targets.tapped(id);\n },\n [client, id],\n );\n return { ref, collapsable: false as const, onLayout, onTouchStart, onTouchEnd };\n}\n\nexport interface GuidelyTargetProps extends ViewProps {\n /** The Guidely id guides use to find this view (`data-guidely-id` on the web). */\n id: string;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Marks a view as a guide target. Wraps children in a `View`; give it `style={{ alignSelf: \"flex-start\" }}`\n * (or use {@link useGuidelyTarget}) when the wrapper should not stretch to its parent's width.\n */\nexport function GuidelyTarget({ id, children, onLayout, onTouchStart, onTouchEnd, ...rest }: GuidelyTargetProps) {\n const t = useGuidelyTarget(id);\n return (\n <View\n {...rest}\n ref={t.ref}\n collapsable={false}\n onLayout={(e: LayoutChangeEvent) => {\n t.onLayout();\n onLayout?.(e);\n }}\n onTouchStart={(e) => {\n t.onTouchStart(e);\n onTouchStart?.(e);\n }}\n onTouchEnd={(e) => {\n t.onTouchEnd(e);\n onTouchEnd?.(e);\n }}\n >\n {children}\n </View>\n );\n}\n"],"mappings":"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","names":["import_react","import_react_native","import_flags","attr","str","has","missing","__publicField","__publicField","import_flags","clamp","text","STREAM_RESPONSE_TIMEOUT_MS","STREAM_IDLE_TIMEOUT_MS","text","rec","text","import_react","import_react_native","text","import_react","import_react_native","import_react_native","import_react_native","import_jsx_runtime","import_react","import_react_native","text","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_react_native","import_jsx_runtime","styles","text","import_react","import_react_native","import_jsx_runtime","styles","announcement","import_react","import_react_native","side","clamp","x","y","import_react_native","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_react_native","import_jsx_runtime","missing","styles","text","import_jsx_runtime","styles","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","TAP_SLOP","import_flags","import_jsx_runtime","styles"]}
|