@getdevteam/analytics-react-native 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -625,7 +625,7 @@ var styles = import_react_native3.StyleSheet.create({
625
625
 
626
626
  // src/index.ts
627
627
  var REACT_NATIVE_SDK_NAME = "@getdevteam/analytics-react-native";
628
- var REACT_NATIVE_SDK_VERSION = "0.3.0";
628
+ var REACT_NATIVE_SDK_VERSION = "0.3.1";
629
629
  function createAnalytics(config) {
630
630
  const client = (0, import_analytics_core2.createClient)({
631
631
  ...config,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/appState.ts","../src/context.ts","../src/feedback.ts","../src/storage.ts","../src/feedbackProvider.ts","../src/optionalPeers.ts"],"sourcesContent":["import {\n createClient,\n type ClientConfig,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\nimport { installAppStateFlush } from \"./appState\";\nimport { collectReactNativeContext } from \"./context\";\nimport {\n createFeedbackSender,\n type ReactNativeAnalyticsClient,\n type ReactNativeFeedbackOptions,\n} from \"./feedback\";\nimport { createAsyncStorageAdapter } from \"./storage\";\n\nexport const REACT_NATIVE_SDK_NAME = \"@getdevteam/analytics-react-native\";\nexport const REACT_NATIVE_SDK_VERSION = \"0.3.0\";\n\nexport interface ReactNativeAnalyticsConfig extends ClientConfig {\n context?: Partial<EventContext>;\n allowUserFeedback?: boolean;\n feedback?: ReactNativeFeedbackOptions;\n}\n\nexport function createAnalytics(config: ReactNativeAnalyticsConfig): ReactNativeAnalyticsClient {\n const client = createClient({\n ...config,\n storage: config.storage ?? createAsyncStorageAdapter(),\n });\n\n const reactNativeContext: EventContext = {\n sdk_name: REACT_NATIVE_SDK_NAME,\n sdk_version: REACT_NATIVE_SDK_VERSION,\n ...collectReactNativeContext(),\n ...config.context,\n };\n client.setContext(reactNativeContext);\n\n // Feedback reads the context at submit time, so it must track later\n // setContext calls. The core client keeps its merged copy private, so the\n // wrapper mirrors the merge (an undefined value deletes the key) here.\n let currentContext = reactNativeContext;\n const setContext = (partial: Partial<EventContext>): void => {\n client.setContext(partial);\n try {\n const next: EventContext = { ...currentContext };\n for (const [key, value] of Object.entries(partial)) {\n if (value === undefined) {\n delete next[key as keyof EventContext];\n } else {\n (next as Record<string, unknown>)[key] = value;\n }\n }\n currentContext = next;\n } catch {\n // mirrors the core client, whose setContext never throws into the host app\n }\n };\n\n const removeAppStateFlush = installAppStateFlush(client);\n\n const reportError = (error: unknown): void => {\n try {\n config.onError?.(error);\n } catch {\n // a throwing observer must never break the host app\n }\n };\n\n const submitFeedback = createFeedbackSender({\n host: config.host,\n key: config.key,\n fetch: config.fetch ?? defaultReactNativeFetch(),\n getDistinctId: () => client.getDistinctId(),\n getSessionId: () => client.getSessionId(),\n getContext: () => currentContext,\n onError: reportError,\n });\n\n return {\n ...client,\n setContext,\n submitFeedback,\n reportError,\n userFeedbackAllowed: config.allowUserFeedback === true,\n feedbackOptions: config.feedback ?? {},\n shutdown: async () => {\n removeAppStateFlush();\n await client.shutdown();\n },\n };\n}\n\nfunction defaultReactNativeFetch(): FetchLike | undefined {\n if (typeof fetch !== \"function\") return undefined;\n return (url, init) => fetch(url, init);\n}\n\nexport { installAppStateFlush } from \"./appState\";\nexport { collectReactNativeContext, osNameFromPlatform } from \"./context\";\nexport { createAsyncStorageAdapter } from \"./storage\";\nexport { FeedbackProvider, type FeedbackProviderProps } from \"./feedbackProvider\";\nexport type {\n FeedbackSubmission,\n ReactNativeAnalyticsClient,\n ReactNativeFeedbackOptions,\n} from \"./feedback\";\nexport type {\n AnalyticsClient,\n AnalyticsLogger,\n ClientConfig,\n EventContext,\n FetchLike,\n LogSeverity,\n Properties,\n StorageAdapter,\n} from \"@getdevteam/analytics-core\";\n","import { AppState, type AppStateStatus } from \"react-native\";\nimport type { AnalyticsClient } from \"@getdevteam/analytics-core\";\n\nexport function installAppStateFlush(client: AnalyticsClient): () => void {\n const onChange = (state: AppStateStatus): void => {\n if (state === \"background\" || state === \"inactive\") {\n void client.flush();\n }\n };\n const subscription = AppState.addEventListener(\"change\", onChange);\n return () => subscription.remove();\n}\n","import { Platform } from \"react-native\";\nimport type { EventContext } from \"@getdevteam/analytics-core\";\n\nexport function osNameFromPlatform(os: string): string {\n switch (os) {\n case \"ios\":\n return \"iOS\";\n case \"android\":\n return \"Android\";\n case \"macos\":\n return \"macOS\";\n case \"windows\":\n return \"Windows\";\n default:\n return os;\n }\n}\n\nexport function collectReactNativeContext(): EventContext {\n const context: EventContext = { platform: \"react-native\" };\n try {\n context.os_name = osNameFromPlatform(Platform.OS);\n context.os_version = String(Platform.Version);\n context.device_type = Platform.isTV ? \"tv\" : Platform.isPad ? \"tablet\" : \"mobile\";\n } catch {\n // Platform constants can be unavailable outside a real RN runtime; the platform tag alone still stands\n }\n return context;\n}\n","import {\n uuidV7,\n type AnalyticsClient,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\n\nexport interface ReactNativeFeedbackOptions {\n colors?: string[];\n accentColor?: string;\n buttonLabel?: string;\n title?: string;\n submitLabel?: string;\n commentPlaceholder?: string;\n successMessage?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n}\n\nexport interface FeedbackSubmission {\n text: string;\n screenshot?: string;\n screenshotContentType?: \"image/png\" | \"image/jpeg\";\n pageUrl?: string;\n}\n\nexport interface ReactNativeAnalyticsClient extends AnalyticsClient {\n /**\n * Sends one piece of user feedback to the ingest API. Resolves false (never\n * throws) when the input is invalid or the POST fails; failures also report\n * through onError.\n */\n submitFeedback(input: FeedbackSubmission): Promise<boolean>;\n /** Reports an SDK-internal failure to the configured onError observer; never throws. */\n reportError(error: unknown): void;\n readonly userFeedbackAllowed: boolean;\n readonly feedbackOptions: ReactNativeFeedbackOptions;\n}\n\nexport const FEEDBACK_DEFAULT_COLORS = [\"#f44336\", \"#4caf50\", \"#2196f3\", \"#ffeb3b\"];\nexport const FEEDBACK_DEFAULT_ACCENT = \"#5b9cf5\";\n\nconst MAX_TEXT_LENGTH = 10000;\nconst MAX_PAGE_URL_LENGTH = 2048;\n\nexport interface FeedbackSenderConfig {\n host: string;\n key: string;\n fetch: FetchLike | undefined;\n getDistinctId(): string;\n getSessionId(): string;\n getContext(): EventContext;\n onError(error: unknown): void;\n}\n\nexport function createFeedbackSender(\n config: FeedbackSenderConfig,\n): (input: FeedbackSubmission) => Promise<boolean> {\n const url = `${String(config.host ?? \"\").replace(/\\/+$/, \"\")}/v1/ingest/feedback`;\n return async (input) => {\n try {\n const text = typeof input?.text === \"string\" ? input.text.trim() : \"\";\n if (text.length === 0) {\n config.onError(new Error(\"feedback text must be a non-empty string\"));\n return false;\n }\n const body: Record<string, unknown> = {\n feedback_id: uuidV7(),\n text: text.slice(0, MAX_TEXT_LENGTH),\n };\n if (typeof input.screenshot === \"string\" && input.screenshot.length > 0) {\n body.screenshot = input.screenshot;\n body.screenshot_content_type = input.screenshotContentType ?? \"image/png\";\n }\n const distinctId = config.getDistinctId();\n if (distinctId) body.distinct_id = distinctId;\n const sessionId = config.getSessionId();\n if (sessionId) body.session_id = sessionId;\n if (typeof input.pageUrl === \"string\" && input.pageUrl.length > 0) {\n body.page_url = input.pageUrl.slice(0, MAX_PAGE_URL_LENGTH);\n }\n body.context = config.getContext();\n if (!config.fetch) throw new Error(\"fetch is not available in this environment\");\n const response = await config.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-DevTeam-Key\": config.key },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n config.onError(new Error(`feedback ingest responded ${response.status}`));\n return false;\n }\n return true;\n } catch (error) {\n config.onError(error);\n return false;\n }\n };\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport type { StorageAdapter } from \"@getdevteam/analytics-core\";\n\nexport function createAsyncStorageAdapter(): StorageAdapter {\n return {\n getItem: async (key) => {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n setItem: async (key, value) => {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // storage unavailable; queue persistence degrades gracefully\n }\n },\n removeItem: async (key) => {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n };\n}\n","import {\n createElement,\n Fragment,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Dimensions,\n Image,\n Modal,\n PanResponder,\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n type GestureResponderEvent,\n} from \"react-native\";\nimport {\n FEEDBACK_DEFAULT_ACCENT,\n FEEDBACK_DEFAULT_COLORS,\n type FeedbackSubmission,\n type ReactNativeAnalyticsClient,\n} from \"./feedback\";\nimport { loadSvg, loadViewShot } from \"./optionalPeers\";\n\nconst PEN_WIDTH = 5;\nconst SUCCESS_CLOSE_DELAY_MS = 1600;\n\ninterface ProviderStroke {\n points: Array<{ x: number; y: number }>;\n color: string;\n width: number;\n}\n\nexport interface FeedbackProviderProps {\n client: ReactNativeAnalyticsClient;\n children?: ReactNode;\n}\n\n// Wraps the app with an optional floating feedback button. Renders children\n// unchanged when the client was created without allowUserFeedback, and every\n// optional peer degrades instead of failing: no react-native-view-shot means\n// comment-only feedback, no react-native-svg means no drawing tools.\nexport function FeedbackProvider(props: FeedbackProviderProps): ReactElement {\n const options = props.client.feedbackOptions ?? {};\n const colors = options.colors && options.colors.length > 0 ? options.colors : FEEDBACK_DEFAULT_COLORS;\n const firstColor = colors[0] ?? FEEDBACK_DEFAULT_COLORS[0]!;\n const accent = options.accentColor ?? FEEDBACK_DEFAULT_ACCENT;\n\n const [visible, setVisible] = useState(false);\n const [screenshot, setScreenshot] = useState<string | undefined>(undefined);\n const [screenshotSize, setScreenshotSize] = useState<\n { width: number; height: number } | undefined\n >(undefined);\n const [comment, setComment] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);\n const [activeColor, setActiveColor] = useState(firstColor);\n const [, setStrokeVersion] = useState(0);\n\n const contentRef = useRef<unknown>(null);\n const previewRef = useRef<unknown>(null);\n const strokesRef = useRef<ProviderStroke[]>([]);\n const activeStrokeRef = useRef<ProviderStroke | undefined>(undefined);\n const activeColorRef = useRef(firstColor);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n // Bumped on every open and close: a submit resolving for an earlier modal\n // session (sent, then cancelled and reopened mid-flight) must not paint its\n // outcome into, or auto-close, the new draft.\n const sessionRef = useRef(0);\n\n useEffect(\n () => () => {\n if (closeTimerRef.current !== undefined) clearTimeout(closeTimerRef.current);\n },\n [],\n );\n\n const bumpStrokes = useCallback(() => setStrokeVersion((version) => version + 1), []);\n\n const panResponderRef = useRef(\n PanResponder.create({\n onStartShouldSetPanResponder: () => true,\n onMoveShouldSetPanResponder: () => true,\n onPanResponderGrant: (event: GestureResponderEvent) => {\n const { locationX, locationY } = event.nativeEvent;\n const stroke: ProviderStroke = {\n points: [{ x: locationX, y: locationY }],\n color: activeColorRef.current,\n width: PEN_WIDTH,\n };\n activeStrokeRef.current = stroke;\n strokesRef.current.push(stroke);\n bumpStrokes();\n },\n onPanResponderMove: (event: GestureResponderEvent) => {\n const stroke = activeStrokeRef.current;\n if (!stroke) return;\n stroke.points.push({ x: event.nativeEvent.locationX, y: event.nativeEvent.locationY });\n bumpStrokes();\n },\n onPanResponderRelease: () => {\n activeStrokeRef.current = undefined;\n },\n onPanResponderTerminate: () => {\n activeStrokeRef.current = undefined;\n },\n }),\n );\n\n const close = useCallback(() => {\n sessionRef.current += 1;\n if (closeTimerRef.current !== undefined) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = undefined;\n }\n setVisible(false);\n setScreenshot(undefined);\n setScreenshotSize(undefined);\n setComment(\"\");\n setSending(false);\n setSent(false);\n setErrorMessage(undefined);\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n }, []);\n\n const open = useCallback(async () => {\n sessionRef.current += 1;\n try {\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n activeColorRef.current = firstColor;\n setActiveColor(firstColor);\n setComment(\"\");\n setSent(false);\n setSending(false);\n setErrorMessage(undefined);\n let shot: string | undefined;\n const viewShot = loadViewShot();\n if (viewShot && contentRef.current) {\n try {\n shot = await viewShot.captureRef(contentRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (captureError) {\n props.client.reportError(captureError);\n shot = undefined;\n }\n }\n setScreenshotSize(shot ? await capturedImageSize(shot) : undefined);\n setScreenshot(shot);\n setVisible(true);\n } catch (openError) {\n props.client.reportError(openError);\n setScreenshotSize(undefined);\n setScreenshot(undefined);\n setVisible(true);\n }\n }, [firstColor, props.client]);\n\n const submit = useCallback(async () => {\n if (sending || sent) return;\n const text = comment.trim();\n if (text.length === 0) {\n setErrorMessage(\"Please add a short comment before sending.\");\n return;\n }\n const session = sessionRef.current;\n setSending(true);\n setErrorMessage(undefined);\n try {\n let finalScreenshot = screenshot;\n const viewShot = loadViewShot();\n if (screenshot && strokesRef.current.length > 0 && viewShot && previewRef.current) {\n try {\n finalScreenshot = await viewShot.captureRef(previewRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (flattenError) {\n // the drawing could not be flattened; fall back to the plain screenshot\n props.client.reportError(flattenError);\n }\n }\n const submission: FeedbackSubmission = { text };\n if (finalScreenshot) {\n submission.screenshot = finalScreenshot;\n submission.screenshotContentType = \"image/png\";\n }\n const ok = await props.client.submitFeedback(submission);\n if (sessionRef.current !== session) return;\n if (ok) {\n setSent(true);\n closeTimerRef.current = setTimeout(close, SUCCESS_CLOSE_DELAY_MS);\n } else {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } catch {\n if (sessionRef.current === session) {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } finally {\n if (sessionRef.current === session) {\n setSending(false);\n }\n }\n }, [close, comment, props.client, screenshot, sending, sent]);\n\n const undo = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current.pop();\n bumpStrokes();\n }, [bumpStrokes]);\n\n const clear = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current = [];\n bumpStrokes();\n }, [bumpStrokes]);\n\n if (props.client.userFeedbackAllowed !== true || typeof props.client.submitFeedback !== \"function\") {\n return createElement(Fragment, null, props.children);\n }\n\n const svg = loadSvg();\n // The captured image's own dimensions drive the preview's aspect ratio; the\n // window is only a fallback when the size lookup failed, since the captured\n // view can be smaller than the window (e.g. inside a SafeAreaView).\n const window = Dimensions.get(\"window\");\n const previewAspectRatio =\n screenshotSize && screenshotSize.height > 0\n ? screenshotSize.width / screenshotSize.height\n : window.height > 0\n ? window.width / window.height\n : 1;\n const positionStyle = options.position === \"bottom-left\" ? styles.fabLeft : styles.fabRight;\n\n // Submitting with strokes flattens the drawing by re-capturing previewRef,\n // so the frame chrome (border, rounded corners) lives on a wrapper outside\n // the ref and never bakes into the stored screenshot.\n const preview = screenshot\n ? createElement(\n View,\n {\n style: [styles.preview, { aspectRatio: previewAspectRatio }],\n testID: \"devteam-feedback-preview-frame\",\n },\n createElement(\n View,\n { ref: previewRef, collapsable: false, style: styles.previewSurface },\n createElement(Image, {\n source: { uri: `data:image/png;base64,${screenshot}` },\n style: styles.previewImage,\n resizeMode: \"stretch\",\n testID: \"devteam-feedback-preview\",\n }),\n svg\n ? createElement(\n View,\n { style: styles.drawLayer, ...panResponderRef.current.panHandlers },\n createElement(\n svg.Svg,\n { width: \"100%\", height: \"100%\" },\n ...strokesRef.current.map((stroke, index) =>\n createElement(svg.Polyline, {\n key: String(index),\n points: stroke.points.map((point) => `${point.x},${point.y}`).join(\" \"),\n fill: \"none\",\n stroke: stroke.color,\n strokeWidth: stroke.width,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n }),\n ),\n ),\n )\n : null,\n ),\n )\n : null;\n\n const tools =\n screenshot && svg\n ? createElement(\n View,\n { style: styles.tools },\n ...colors.map((color) =>\n createElement(Pressable, {\n key: color,\n accessibilityRole: \"button\",\n testID: `devteam-feedback-color-${color}`,\n onPress: () => {\n activeColorRef.current = color;\n setActiveColor(color);\n },\n style: [\n styles.swatch,\n { backgroundColor: color },\n activeColor === color ? styles.swatchActive : null,\n ],\n }),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-undo\",\n onPress: undo,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Undo\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-clear\",\n onPress: clear,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Clear\"),\n ),\n )\n : null;\n\n const modal = createElement(\n Modal,\n { visible, transparent: true, animationType: \"fade\", onRequestClose: close },\n createElement(\n View,\n { style: styles.backdrop },\n createElement(\n View,\n { style: styles.panel },\n createElement(Text, { style: styles.title }, options.title ?? \"Send feedback\"),\n preview,\n tools,\n createElement(TextInput, {\n multiline: true,\n value: comment,\n onChangeText: setComment,\n placeholder: options.commentPlaceholder ?? \"What went wrong, or what could be better?\",\n style: styles.input,\n testID: \"devteam-feedback-comment\",\n }),\n errorMessage\n ? createElement(Text, { style: styles.error, testID: \"devteam-feedback-error\" }, errorMessage)\n : null,\n sent\n ? createElement(\n Text,\n { style: styles.success, testID: \"devteam-feedback-success\" },\n options.successMessage ?? \"Thanks for the feedback!\",\n )\n : null,\n createElement(\n View,\n { style: styles.actions },\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-cancel\",\n onPress: close,\n style: styles.cancelButton,\n },\n createElement(Text, { style: styles.cancelLabel }, \"Cancel\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-submit\",\n disabled: sending || sent,\n onPress: () => {\n void submit();\n },\n style: [styles.submitButton, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.submitLabel }, options.submitLabel ?? \"Send\"),\n ),\n ),\n ),\n ),\n );\n\n return createElement(\n View,\n { style: styles.root },\n createElement(\n View,\n { ref: contentRef, collapsable: false, style: styles.content },\n props.children,\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-button\",\n onPress: () => {\n void open();\n },\n style: [styles.fab, positionStyle, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.fabLabel }, options.buttonLabel ?? \"Feedback\"),\n ),\n modal,\n );\n}\n\nfunction capturedImageSize(\n base64: string,\n): Promise<{ width: number; height: number } | undefined> {\n return new Promise((resolve) => {\n try {\n Image.getSize(\n `data:image/png;base64,${base64}`,\n (width, height) => resolve(width > 0 && height > 0 ? { width, height } : undefined),\n () => resolve(undefined),\n );\n } catch {\n resolve(undefined);\n }\n });\n}\n\nconst styles = StyleSheet.create({\n root: { flex: 1 },\n content: { flex: 1 },\n fab: {\n position: \"absolute\",\n bottom: 24,\n borderRadius: 999,\n paddingVertical: 10,\n paddingHorizontal: 18,\n elevation: 4,\n },\n fabRight: { right: 20 },\n fabLeft: { left: 20 },\n fabLabel: { color: \"#ffffff\", fontSize: 14, fontWeight: \"600\" },\n backdrop: {\n flex: 1,\n backgroundColor: \"rgba(15, 23, 42, 0.55)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n },\n panel: {\n width: \"100%\",\n maxWidth: 560,\n backgroundColor: \"#ffffff\",\n borderRadius: 12,\n padding: 16,\n gap: 10,\n },\n title: { fontSize: 16, fontWeight: \"600\", color: \"#1f2933\" },\n preview: {\n width: \"100%\",\n borderRadius: 8,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n overflow: \"hidden\",\n },\n previewSurface: { width: \"100%\", height: \"100%\" },\n previewImage: { width: \"100%\", height: \"100%\" },\n drawLayer: { position: \"absolute\", top: 0, right: 0, bottom: 0, left: 0 },\n tools: { flexDirection: \"row\", alignItems: \"center\", gap: 8 },\n swatch: { width: 24, height: 24, borderRadius: 12, borderWidth: 2, borderColor: \"transparent\" },\n swatchActive: { borderColor: \"#1f2933\" },\n toolButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 6,\n paddingVertical: 4,\n paddingHorizontal: 10,\n },\n toolLabel: { fontSize: 13, color: \"#1f2933\" },\n input: {\n minHeight: 72,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n padding: 10,\n color: \"#1f2933\",\n textAlignVertical: \"top\",\n },\n error: { color: \"#b91c1c\", fontSize: 13 },\n success: { color: \"#15803d\", fontSize: 14, fontWeight: \"600\" },\n actions: { flexDirection: \"row\", justifyContent: \"flex-end\", gap: 8 },\n cancelButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n paddingVertical: 8,\n paddingHorizontal: 14,\n },\n cancelLabel: { fontSize: 14, color: \"#1f2933\" },\n submitButton: { borderRadius: 8, paddingVertical: 8, paddingHorizontal: 16 },\n submitLabel: { fontSize: 14, fontWeight: \"600\", color: \"#ffffff\" },\n});\n","import type { ComponentType } from \"react\";\n\n// This file may be evaluated where `require` does not exist at all.\ndeclare const require: ((id: string) => unknown) | undefined;\n\nexport interface ViewShotCaptureOptions {\n format?: \"png\" | \"jpg\";\n quality?: number;\n result?: \"base64\" | \"tmpfile\" | \"data-uri\";\n}\n\nexport interface ViewShotModule {\n captureRef(ref: unknown, options?: ViewShotCaptureOptions): Promise<string>;\n}\n\nexport interface SvgModule {\n Svg: ComponentType<Record<string, unknown>>;\n Polyline: ComponentType<Record<string, unknown>>;\n}\n\ntype OptionalModuleLoader = (name: string) => unknown;\n\nlet testLoaderOverride: OptionalModuleLoader | undefined;\n\nexport function setOptionalModuleLoaderForTesting(loader: OptionalModuleLoader | undefined): void {\n testLoaderOverride = loader;\n}\n\n// Metro consumes the CJS build (the \"require\" export condition) and only\n// resolves string-literal specifiers - a `require(variable)` in a node_modules\n// package throws at runtime even when the peer IS installed - so each peer\n// gets its own literal require, kept directly inside a try/catch so\n// `transformer.allowOptionalDependencies` marks it optional and a missing peer\n// degrades instead of failing the bundle. esbuild's ESM output rewrites bare\n// `require` into a shim that throws at call time, so import-condition\n// consumers (react-native-web, Node ESM) land on the same degraded path\n// instead of crashing at load.\nfunction requireViewShot(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-view-shot\");\n } catch {\n return undefined;\n }\n}\n\nfunction requireSvg(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-svg\");\n } catch {\n return undefined;\n }\n}\n\nfunction loadOptionalModule(name: string, requirePeer: () => unknown): unknown {\n if (testLoaderOverride) {\n try {\n return testLoaderOverride(name);\n } catch {\n return undefined;\n }\n }\n return requirePeer();\n}\n\nexport function loadViewShot(): ViewShotModule | undefined {\n const loaded = loadOptionalModule(\"react-native-view-shot\", requireViewShot) as\n | { captureRef?: unknown; default?: { captureRef?: unknown } }\n | undefined;\n const captureRef = loaded?.captureRef ?? loaded?.default?.captureRef;\n if (typeof captureRef !== \"function\") return undefined;\n return { captureRef: captureRef as ViewShotModule[\"captureRef\"] };\n}\n\nexport function loadSvg(): SvgModule | undefined {\n const loaded = loadOptionalModule(\"react-native-svg\", requireSvg) as\n | { Svg?: unknown; Polyline?: unknown; default?: unknown }\n | undefined;\n const svg = loaded?.Svg ?? loaded?.default;\n const polyline = loaded?.Polyline;\n if (svg == null || polyline == null) return undefined;\n return {\n Svg: svg as SvgModule[\"Svg\"],\n Polyline: polyline as SvgModule[\"Polyline\"],\n };\n}\n"],"mappings":"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","names":["import_analytics_core","import_react_native","AsyncStorage","import_react_native"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/appState.ts","../src/context.ts","../src/feedback.ts","../src/storage.ts","../src/feedbackProvider.ts","../src/optionalPeers.ts"],"sourcesContent":["import {\n createClient,\n type ClientConfig,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\nimport { installAppStateFlush } from \"./appState\";\nimport { collectReactNativeContext } from \"./context\";\nimport {\n createFeedbackSender,\n type ReactNativeAnalyticsClient,\n type ReactNativeFeedbackOptions,\n} from \"./feedback\";\nimport { createAsyncStorageAdapter } from \"./storage\";\n\nexport const REACT_NATIVE_SDK_NAME = \"@getdevteam/analytics-react-native\";\nexport const REACT_NATIVE_SDK_VERSION = \"0.3.1\";\n\nexport interface ReactNativeAnalyticsConfig extends ClientConfig {\n context?: Partial<EventContext>;\n allowUserFeedback?: boolean;\n feedback?: ReactNativeFeedbackOptions;\n}\n\nexport function createAnalytics(config: ReactNativeAnalyticsConfig): ReactNativeAnalyticsClient {\n const client = createClient({\n ...config,\n storage: config.storage ?? createAsyncStorageAdapter(),\n });\n\n const reactNativeContext: EventContext = {\n sdk_name: REACT_NATIVE_SDK_NAME,\n sdk_version: REACT_NATIVE_SDK_VERSION,\n ...collectReactNativeContext(),\n ...config.context,\n };\n client.setContext(reactNativeContext);\n\n // Feedback reads the context at submit time, so it must track later\n // setContext calls. The core client keeps its merged copy private, so the\n // wrapper mirrors the merge (an undefined value deletes the key) here.\n let currentContext = reactNativeContext;\n const setContext = (partial: Partial<EventContext>): void => {\n client.setContext(partial);\n try {\n const next: EventContext = { ...currentContext };\n for (const [key, value] of Object.entries(partial)) {\n if (value === undefined) {\n delete next[key as keyof EventContext];\n } else {\n (next as Record<string, unknown>)[key] = value;\n }\n }\n currentContext = next;\n } catch {\n // mirrors the core client, whose setContext never throws into the host app\n }\n };\n\n const removeAppStateFlush = installAppStateFlush(client);\n\n const reportError = (error: unknown): void => {\n try {\n config.onError?.(error);\n } catch {\n // a throwing observer must never break the host app\n }\n };\n\n const submitFeedback = createFeedbackSender({\n host: config.host,\n key: config.key,\n fetch: config.fetch ?? defaultReactNativeFetch(),\n getDistinctId: () => client.getDistinctId(),\n getSessionId: () => client.getSessionId(),\n getContext: () => currentContext,\n onError: reportError,\n });\n\n return {\n ...client,\n setContext,\n submitFeedback,\n reportError,\n userFeedbackAllowed: config.allowUserFeedback === true,\n feedbackOptions: config.feedback ?? {},\n shutdown: async () => {\n removeAppStateFlush();\n await client.shutdown();\n },\n };\n}\n\nfunction defaultReactNativeFetch(): FetchLike | undefined {\n if (typeof fetch !== \"function\") return undefined;\n return (url, init) => fetch(url, init);\n}\n\nexport { installAppStateFlush } from \"./appState\";\nexport { collectReactNativeContext, osNameFromPlatform } from \"./context\";\nexport { createAsyncStorageAdapter } from \"./storage\";\nexport { FeedbackProvider, type FeedbackProviderProps } from \"./feedbackProvider\";\nexport type {\n FeedbackSubmission,\n ReactNativeAnalyticsClient,\n ReactNativeFeedbackOptions,\n} from \"./feedback\";\nexport type {\n AnalyticsClient,\n AnalyticsLogger,\n ClientConfig,\n EventContext,\n FetchLike,\n LogSeverity,\n Properties,\n StorageAdapter,\n} from \"@getdevteam/analytics-core\";\n","import { AppState, type AppStateStatus } from \"react-native\";\nimport type { AnalyticsClient } from \"@getdevteam/analytics-core\";\n\nexport function installAppStateFlush(client: AnalyticsClient): () => void {\n const onChange = (state: AppStateStatus): void => {\n if (state === \"background\" || state === \"inactive\") {\n void client.flush();\n }\n };\n const subscription = AppState.addEventListener(\"change\", onChange);\n return () => subscription.remove();\n}\n","import { Platform } from \"react-native\";\nimport type { EventContext } from \"@getdevteam/analytics-core\";\n\nexport function osNameFromPlatform(os: string): string {\n switch (os) {\n case \"ios\":\n return \"iOS\";\n case \"android\":\n return \"Android\";\n case \"macos\":\n return \"macOS\";\n case \"windows\":\n return \"Windows\";\n default:\n return os;\n }\n}\n\nexport function collectReactNativeContext(): EventContext {\n const context: EventContext = { platform: \"react-native\" };\n try {\n context.os_name = osNameFromPlatform(Platform.OS);\n context.os_version = String(Platform.Version);\n context.device_type = Platform.isTV ? \"tv\" : Platform.isPad ? \"tablet\" : \"mobile\";\n } catch {\n // Platform constants can be unavailable outside a real RN runtime; the platform tag alone still stands\n }\n return context;\n}\n","import {\n uuidV7,\n type AnalyticsClient,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\n\nexport interface ReactNativeFeedbackOptions {\n colors?: string[];\n accentColor?: string;\n buttonLabel?: string;\n title?: string;\n submitLabel?: string;\n commentPlaceholder?: string;\n successMessage?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n}\n\nexport interface FeedbackSubmission {\n text: string;\n screenshot?: string;\n screenshotContentType?: \"image/png\" | \"image/jpeg\";\n pageUrl?: string;\n}\n\nexport interface ReactNativeAnalyticsClient extends AnalyticsClient {\n /**\n * Sends one piece of user feedback to the ingest API. Resolves false (never\n * throws) when the input is invalid or the POST fails; failures also report\n * through onError.\n */\n submitFeedback(input: FeedbackSubmission): Promise<boolean>;\n /** Reports an SDK-internal failure to the configured onError observer; never throws. */\n reportError(error: unknown): void;\n readonly userFeedbackAllowed: boolean;\n readonly feedbackOptions: ReactNativeFeedbackOptions;\n}\n\nexport const FEEDBACK_DEFAULT_COLORS = [\"#f44336\", \"#4caf50\", \"#2196f3\", \"#ffeb3b\"];\nexport const FEEDBACK_DEFAULT_ACCENT = \"#5b9cf5\";\n\nconst MAX_TEXT_LENGTH = 10000;\nconst MAX_PAGE_URL_LENGTH = 2048;\n\nexport interface FeedbackSenderConfig {\n host: string;\n key: string;\n fetch: FetchLike | undefined;\n getDistinctId(): string;\n getSessionId(): string;\n getContext(): EventContext;\n onError(error: unknown): void;\n}\n\nexport function createFeedbackSender(\n config: FeedbackSenderConfig,\n): (input: FeedbackSubmission) => Promise<boolean> {\n const url = `${String(config.host ?? \"\").replace(/\\/+$/, \"\")}/v1/ingest/feedback`;\n return async (input) => {\n try {\n const text = typeof input?.text === \"string\" ? input.text.trim() : \"\";\n if (text.length === 0) {\n config.onError(new Error(\"feedback text must be a non-empty string\"));\n return false;\n }\n const body: Record<string, unknown> = {\n feedback_id: uuidV7(),\n text: text.slice(0, MAX_TEXT_LENGTH),\n };\n if (typeof input.screenshot === \"string\" && input.screenshot.length > 0) {\n body.screenshot = input.screenshot;\n body.screenshot_content_type = input.screenshotContentType ?? \"image/png\";\n }\n const distinctId = config.getDistinctId();\n if (distinctId) body.distinct_id = distinctId;\n const sessionId = config.getSessionId();\n if (sessionId) body.session_id = sessionId;\n if (typeof input.pageUrl === \"string\" && input.pageUrl.length > 0) {\n body.page_url = input.pageUrl.slice(0, MAX_PAGE_URL_LENGTH);\n }\n body.context = config.getContext();\n if (!config.fetch) throw new Error(\"fetch is not available in this environment\");\n const response = await config.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-DevTeam-Key\": config.key },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n config.onError(new Error(`feedback ingest responded ${response.status}`));\n return false;\n }\n return true;\n } catch (error) {\n config.onError(error);\n return false;\n }\n };\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport type { StorageAdapter } from \"@getdevteam/analytics-core\";\n\nexport function createAsyncStorageAdapter(): StorageAdapter {\n return {\n getItem: async (key) => {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n setItem: async (key, value) => {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // storage unavailable; queue persistence degrades gracefully\n }\n },\n removeItem: async (key) => {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n };\n}\n","import {\n createElement,\n Fragment,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Dimensions,\n Image,\n Modal,\n PanResponder,\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n type GestureResponderEvent,\n} from \"react-native\";\nimport {\n FEEDBACK_DEFAULT_ACCENT,\n FEEDBACK_DEFAULT_COLORS,\n type FeedbackSubmission,\n type ReactNativeAnalyticsClient,\n} from \"./feedback\";\nimport { loadSvg, loadViewShot } from \"./optionalPeers\";\n\nconst PEN_WIDTH = 5;\nconst SUCCESS_CLOSE_DELAY_MS = 1600;\n\ninterface ProviderStroke {\n points: Array<{ x: number; y: number }>;\n color: string;\n width: number;\n}\n\nexport interface FeedbackProviderProps {\n client: ReactNativeAnalyticsClient;\n children?: ReactNode;\n}\n\n// Wraps the app with an optional floating feedback button. Renders children\n// unchanged when the client was created without allowUserFeedback, and every\n// optional peer degrades instead of failing: no react-native-view-shot means\n// comment-only feedback, no react-native-svg means no drawing tools.\nexport function FeedbackProvider(props: FeedbackProviderProps): ReactElement {\n const options = props.client.feedbackOptions ?? {};\n const colors = options.colors && options.colors.length > 0 ? options.colors : FEEDBACK_DEFAULT_COLORS;\n const firstColor = colors[0] ?? FEEDBACK_DEFAULT_COLORS[0]!;\n const accent = options.accentColor ?? FEEDBACK_DEFAULT_ACCENT;\n\n const [visible, setVisible] = useState(false);\n const [screenshot, setScreenshot] = useState<string | undefined>(undefined);\n const [screenshotSize, setScreenshotSize] = useState<\n { width: number; height: number } | undefined\n >(undefined);\n const [comment, setComment] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);\n const [activeColor, setActiveColor] = useState(firstColor);\n const [, setStrokeVersion] = useState(0);\n\n const contentRef = useRef<unknown>(null);\n const previewRef = useRef<unknown>(null);\n const strokesRef = useRef<ProviderStroke[]>([]);\n const activeStrokeRef = useRef<ProviderStroke | undefined>(undefined);\n const activeColorRef = useRef(firstColor);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n // Bumped on every open and close: a submit resolving for an earlier modal\n // session (sent, then cancelled and reopened mid-flight) must not paint its\n // outcome into, or auto-close, the new draft.\n const sessionRef = useRef(0);\n\n useEffect(\n () => () => {\n if (closeTimerRef.current !== undefined) clearTimeout(closeTimerRef.current);\n },\n [],\n );\n\n const bumpStrokes = useCallback(() => setStrokeVersion((version) => version + 1), []);\n\n const panResponderRef = useRef(\n PanResponder.create({\n onStartShouldSetPanResponder: () => true,\n onMoveShouldSetPanResponder: () => true,\n onPanResponderGrant: (event: GestureResponderEvent) => {\n const { locationX, locationY } = event.nativeEvent;\n const stroke: ProviderStroke = {\n points: [{ x: locationX, y: locationY }],\n color: activeColorRef.current,\n width: PEN_WIDTH,\n };\n activeStrokeRef.current = stroke;\n strokesRef.current.push(stroke);\n bumpStrokes();\n },\n onPanResponderMove: (event: GestureResponderEvent) => {\n const stroke = activeStrokeRef.current;\n if (!stroke) return;\n stroke.points.push({ x: event.nativeEvent.locationX, y: event.nativeEvent.locationY });\n bumpStrokes();\n },\n onPanResponderRelease: () => {\n activeStrokeRef.current = undefined;\n },\n onPanResponderTerminate: () => {\n activeStrokeRef.current = undefined;\n },\n }),\n );\n\n const close = useCallback(() => {\n sessionRef.current += 1;\n if (closeTimerRef.current !== undefined) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = undefined;\n }\n setVisible(false);\n setScreenshot(undefined);\n setScreenshotSize(undefined);\n setComment(\"\");\n setSending(false);\n setSent(false);\n setErrorMessage(undefined);\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n }, []);\n\n const open = useCallback(async () => {\n sessionRef.current += 1;\n try {\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n activeColorRef.current = firstColor;\n setActiveColor(firstColor);\n setComment(\"\");\n setSent(false);\n setSending(false);\n setErrorMessage(undefined);\n let shot: string | undefined;\n const viewShot = loadViewShot();\n if (viewShot && contentRef.current) {\n try {\n shot = await viewShot.captureRef(contentRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (captureError) {\n props.client.reportError(captureError);\n shot = undefined;\n }\n }\n setScreenshotSize(shot ? await capturedImageSize(shot) : undefined);\n setScreenshot(shot);\n setVisible(true);\n } catch (openError) {\n props.client.reportError(openError);\n setScreenshotSize(undefined);\n setScreenshot(undefined);\n setVisible(true);\n }\n }, [firstColor, props.client]);\n\n const submit = useCallback(async () => {\n if (sending || sent) return;\n const text = comment.trim();\n if (text.length === 0) {\n setErrorMessage(\"Please add a short comment before sending.\");\n return;\n }\n const session = sessionRef.current;\n setSending(true);\n setErrorMessage(undefined);\n try {\n let finalScreenshot = screenshot;\n const viewShot = loadViewShot();\n if (screenshot && strokesRef.current.length > 0 && viewShot && previewRef.current) {\n try {\n finalScreenshot = await viewShot.captureRef(previewRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (flattenError) {\n // the drawing could not be flattened; fall back to the plain screenshot\n props.client.reportError(flattenError);\n }\n }\n const submission: FeedbackSubmission = { text };\n if (finalScreenshot) {\n submission.screenshot = finalScreenshot;\n submission.screenshotContentType = \"image/png\";\n }\n const ok = await props.client.submitFeedback(submission);\n if (sessionRef.current !== session) return;\n if (ok) {\n setSent(true);\n closeTimerRef.current = setTimeout(close, SUCCESS_CLOSE_DELAY_MS);\n } else {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } catch {\n if (sessionRef.current === session) {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } finally {\n if (sessionRef.current === session) {\n setSending(false);\n }\n }\n }, [close, comment, props.client, screenshot, sending, sent]);\n\n const undo = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current.pop();\n bumpStrokes();\n }, [bumpStrokes]);\n\n const clear = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current = [];\n bumpStrokes();\n }, [bumpStrokes]);\n\n if (props.client.userFeedbackAllowed !== true || typeof props.client.submitFeedback !== \"function\") {\n return createElement(Fragment, null, props.children);\n }\n\n const svg = loadSvg();\n // The captured image's own dimensions drive the preview's aspect ratio; the\n // window is only a fallback when the size lookup failed, since the captured\n // view can be smaller than the window (e.g. inside a SafeAreaView).\n const window = Dimensions.get(\"window\");\n const previewAspectRatio =\n screenshotSize && screenshotSize.height > 0\n ? screenshotSize.width / screenshotSize.height\n : window.height > 0\n ? window.width / window.height\n : 1;\n const positionStyle = options.position === \"bottom-left\" ? styles.fabLeft : styles.fabRight;\n\n // Submitting with strokes flattens the drawing by re-capturing previewRef,\n // so the frame chrome (border, rounded corners) lives on a wrapper outside\n // the ref and never bakes into the stored screenshot.\n const preview = screenshot\n ? createElement(\n View,\n {\n style: [styles.preview, { aspectRatio: previewAspectRatio }],\n testID: \"devteam-feedback-preview-frame\",\n },\n createElement(\n View,\n { ref: previewRef, collapsable: false, style: styles.previewSurface },\n createElement(Image, {\n source: { uri: `data:image/png;base64,${screenshot}` },\n style: styles.previewImage,\n resizeMode: \"stretch\",\n testID: \"devteam-feedback-preview\",\n }),\n svg\n ? createElement(\n View,\n { style: styles.drawLayer, ...panResponderRef.current.panHandlers },\n createElement(\n svg.Svg,\n { width: \"100%\", height: \"100%\" },\n ...strokesRef.current.map((stroke, index) =>\n createElement(svg.Polyline, {\n key: String(index),\n points: stroke.points.map((point) => `${point.x},${point.y}`).join(\" \"),\n fill: \"none\",\n stroke: stroke.color,\n strokeWidth: stroke.width,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n }),\n ),\n ),\n )\n : null,\n ),\n )\n : null;\n\n const tools =\n screenshot && svg\n ? createElement(\n View,\n { style: styles.tools },\n ...colors.map((color) =>\n createElement(Pressable, {\n key: color,\n accessibilityRole: \"button\",\n testID: `devteam-feedback-color-${color}`,\n onPress: () => {\n activeColorRef.current = color;\n setActiveColor(color);\n },\n style: [\n styles.swatch,\n { backgroundColor: color },\n activeColor === color ? styles.swatchActive : null,\n ],\n }),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-undo\",\n onPress: undo,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Undo\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-clear\",\n onPress: clear,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Clear\"),\n ),\n )\n : null;\n\n const modal = createElement(\n Modal,\n { visible, transparent: true, animationType: \"fade\", onRequestClose: close },\n createElement(\n View,\n { style: styles.backdrop },\n createElement(\n View,\n { style: styles.panel },\n createElement(Text, { style: styles.title }, options.title ?? \"Send feedback\"),\n preview,\n tools,\n createElement(TextInput, {\n multiline: true,\n value: comment,\n onChangeText: setComment,\n placeholder: options.commentPlaceholder ?? \"What went wrong, or what could be better?\",\n style: styles.input,\n testID: \"devteam-feedback-comment\",\n }),\n errorMessage\n ? createElement(Text, { style: styles.error, testID: \"devteam-feedback-error\" }, errorMessage)\n : null,\n sent\n ? createElement(\n Text,\n { style: styles.success, testID: \"devteam-feedback-success\" },\n options.successMessage ?? \"Thanks for the feedback!\",\n )\n : null,\n createElement(\n View,\n { style: styles.actions },\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-cancel\",\n onPress: close,\n style: styles.cancelButton,\n },\n createElement(Text, { style: styles.cancelLabel }, \"Cancel\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-submit\",\n disabled: sending || sent,\n onPress: () => {\n void submit();\n },\n style: [styles.submitButton, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.submitLabel }, options.submitLabel ?? \"Send\"),\n ),\n ),\n ),\n ),\n );\n\n return createElement(\n View,\n { style: styles.root },\n createElement(\n View,\n { ref: contentRef, collapsable: false, style: styles.content },\n props.children,\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-button\",\n onPress: () => {\n void open();\n },\n style: [styles.fab, positionStyle, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.fabLabel }, options.buttonLabel ?? \"Feedback\"),\n ),\n modal,\n );\n}\n\nfunction capturedImageSize(\n base64: string,\n): Promise<{ width: number; height: number } | undefined> {\n return new Promise((resolve) => {\n try {\n Image.getSize(\n `data:image/png;base64,${base64}`,\n (width, height) => resolve(width > 0 && height > 0 ? { width, height } : undefined),\n () => resolve(undefined),\n );\n } catch {\n resolve(undefined);\n }\n });\n}\n\nconst styles = StyleSheet.create({\n root: { flex: 1 },\n content: { flex: 1 },\n fab: {\n position: \"absolute\",\n bottom: 24,\n borderRadius: 999,\n paddingVertical: 10,\n paddingHorizontal: 18,\n elevation: 4,\n },\n fabRight: { right: 20 },\n fabLeft: { left: 20 },\n fabLabel: { color: \"#ffffff\", fontSize: 14, fontWeight: \"600\" },\n backdrop: {\n flex: 1,\n backgroundColor: \"rgba(15, 23, 42, 0.55)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n },\n panel: {\n width: \"100%\",\n maxWidth: 560,\n backgroundColor: \"#ffffff\",\n borderRadius: 12,\n padding: 16,\n gap: 10,\n },\n title: { fontSize: 16, fontWeight: \"600\", color: \"#1f2933\" },\n preview: {\n width: \"100%\",\n borderRadius: 8,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n overflow: \"hidden\",\n },\n previewSurface: { width: \"100%\", height: \"100%\" },\n previewImage: { width: \"100%\", height: \"100%\" },\n drawLayer: { position: \"absolute\", top: 0, right: 0, bottom: 0, left: 0 },\n tools: { flexDirection: \"row\", alignItems: \"center\", gap: 8 },\n swatch: { width: 24, height: 24, borderRadius: 12, borderWidth: 2, borderColor: \"transparent\" },\n swatchActive: { borderColor: \"#1f2933\" },\n toolButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 6,\n paddingVertical: 4,\n paddingHorizontal: 10,\n },\n toolLabel: { fontSize: 13, color: \"#1f2933\" },\n input: {\n minHeight: 72,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n padding: 10,\n color: \"#1f2933\",\n textAlignVertical: \"top\",\n },\n error: { color: \"#b91c1c\", fontSize: 13 },\n success: { color: \"#15803d\", fontSize: 14, fontWeight: \"600\" },\n actions: { flexDirection: \"row\", justifyContent: \"flex-end\", gap: 8 },\n cancelButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n paddingVertical: 8,\n paddingHorizontal: 14,\n },\n cancelLabel: { fontSize: 14, color: \"#1f2933\" },\n submitButton: { borderRadius: 8, paddingVertical: 8, paddingHorizontal: 16 },\n submitLabel: { fontSize: 14, fontWeight: \"600\", color: \"#ffffff\" },\n});\n","import type { ComponentType } from \"react\";\n\n// This file may be evaluated where `require` does not exist at all.\ndeclare const require: ((id: string) => unknown) | undefined;\n\nexport interface ViewShotCaptureOptions {\n format?: \"png\" | \"jpg\";\n quality?: number;\n result?: \"base64\" | \"tmpfile\" | \"data-uri\";\n}\n\nexport interface ViewShotModule {\n captureRef(ref: unknown, options?: ViewShotCaptureOptions): Promise<string>;\n}\n\nexport interface SvgModule {\n Svg: ComponentType<Record<string, unknown>>;\n Polyline: ComponentType<Record<string, unknown>>;\n}\n\ntype OptionalModuleLoader = (name: string) => unknown;\n\nlet testLoaderOverride: OptionalModuleLoader | undefined;\n\nexport function setOptionalModuleLoaderForTesting(loader: OptionalModuleLoader | undefined): void {\n testLoaderOverride = loader;\n}\n\n// Metro consumes the CJS build (the \"require\" export condition) and only\n// resolves string-literal specifiers - a `require(variable)` in a node_modules\n// package throws at runtime even when the peer IS installed - so each peer\n// gets its own literal require, kept directly inside a try/catch so\n// `transformer.allowOptionalDependencies` marks it optional and a missing peer\n// degrades instead of failing the bundle. esbuild's ESM output rewrites bare\n// `require` into a shim that throws at call time, so import-condition\n// consumers (react-native-web, Node ESM) land on the same degraded path\n// instead of crashing at load.\nfunction requireViewShot(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-view-shot\");\n } catch {\n return undefined;\n }\n}\n\nfunction requireSvg(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-svg\");\n } catch {\n return undefined;\n }\n}\n\nfunction loadOptionalModule(name: string, requirePeer: () => unknown): unknown {\n if (testLoaderOverride) {\n try {\n return testLoaderOverride(name);\n } catch {\n return undefined;\n }\n }\n return requirePeer();\n}\n\nexport function loadViewShot(): ViewShotModule | undefined {\n const loaded = loadOptionalModule(\"react-native-view-shot\", requireViewShot) as\n | { captureRef?: unknown; default?: { captureRef?: unknown } }\n | undefined;\n const captureRef = loaded?.captureRef ?? loaded?.default?.captureRef;\n if (typeof captureRef !== \"function\") return undefined;\n return { captureRef: captureRef as ViewShotModule[\"captureRef\"] };\n}\n\nexport function loadSvg(): SvgModule | undefined {\n const loaded = loadOptionalModule(\"react-native-svg\", requireSvg) as\n | { Svg?: unknown; Polyline?: unknown; default?: unknown }\n | undefined;\n const svg = loaded?.Svg ?? loaded?.default;\n const polyline = loaded?.Polyline;\n if (svg == null || polyline == null) return undefined;\n return {\n Svg: svg as SvgModule[\"Svg\"],\n Polyline: polyline as SvgModule[\"Polyline\"],\n };\n}\n"],"mappings":"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","names":["import_analytics_core","import_react_native","AsyncStorage","import_react_native"]}
package/dist/index.d.cts CHANGED
@@ -45,7 +45,7 @@ interface FeedbackProviderProps {
45
45
  declare function FeedbackProvider(props: FeedbackProviderProps): ReactElement;
46
46
 
47
47
  declare const REACT_NATIVE_SDK_NAME = "@getdevteam/analytics-react-native";
48
- declare const REACT_NATIVE_SDK_VERSION = "0.3.0";
48
+ declare const REACT_NATIVE_SDK_VERSION = "0.3.1";
49
49
  interface ReactNativeAnalyticsConfig extends ClientConfig {
50
50
  context?: Partial<EventContext>;
51
51
  allowUserFeedback?: boolean;
package/dist/index.d.ts CHANGED
@@ -45,7 +45,7 @@ interface FeedbackProviderProps {
45
45
  declare function FeedbackProvider(props: FeedbackProviderProps): ReactElement;
46
46
 
47
47
  declare const REACT_NATIVE_SDK_NAME = "@getdevteam/analytics-react-native";
48
- declare const REACT_NATIVE_SDK_VERSION = "0.3.0";
48
+ declare const REACT_NATIVE_SDK_VERSION = "0.3.1";
49
49
  interface ReactNativeAnalyticsConfig extends ClientConfig {
50
50
  context?: Partial<EventContext>;
51
51
  allowUserFeedback?: boolean;
package/dist/index.js CHANGED
@@ -612,7 +612,7 @@ var styles = StyleSheet.create({
612
612
 
613
613
  // src/index.ts
614
614
  var REACT_NATIVE_SDK_NAME = "@getdevteam/analytics-react-native";
615
- var REACT_NATIVE_SDK_VERSION = "0.3.0";
615
+ var REACT_NATIVE_SDK_VERSION = "0.3.1";
616
616
  function createAnalytics(config) {
617
617
  const client = createClient({
618
618
  ...config,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/appState.ts","../src/context.ts","../src/feedback.ts","../src/storage.ts","../src/feedbackProvider.ts","../src/optionalPeers.ts"],"sourcesContent":["import {\n createClient,\n type ClientConfig,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\nimport { installAppStateFlush } from \"./appState\";\nimport { collectReactNativeContext } from \"./context\";\nimport {\n createFeedbackSender,\n type ReactNativeAnalyticsClient,\n type ReactNativeFeedbackOptions,\n} from \"./feedback\";\nimport { createAsyncStorageAdapter } from \"./storage\";\n\nexport const REACT_NATIVE_SDK_NAME = \"@getdevteam/analytics-react-native\";\nexport const REACT_NATIVE_SDK_VERSION = \"0.3.0\";\n\nexport interface ReactNativeAnalyticsConfig extends ClientConfig {\n context?: Partial<EventContext>;\n allowUserFeedback?: boolean;\n feedback?: ReactNativeFeedbackOptions;\n}\n\nexport function createAnalytics(config: ReactNativeAnalyticsConfig): ReactNativeAnalyticsClient {\n const client = createClient({\n ...config,\n storage: config.storage ?? createAsyncStorageAdapter(),\n });\n\n const reactNativeContext: EventContext = {\n sdk_name: REACT_NATIVE_SDK_NAME,\n sdk_version: REACT_NATIVE_SDK_VERSION,\n ...collectReactNativeContext(),\n ...config.context,\n };\n client.setContext(reactNativeContext);\n\n // Feedback reads the context at submit time, so it must track later\n // setContext calls. The core client keeps its merged copy private, so the\n // wrapper mirrors the merge (an undefined value deletes the key) here.\n let currentContext = reactNativeContext;\n const setContext = (partial: Partial<EventContext>): void => {\n client.setContext(partial);\n try {\n const next: EventContext = { ...currentContext };\n for (const [key, value] of Object.entries(partial)) {\n if (value === undefined) {\n delete next[key as keyof EventContext];\n } else {\n (next as Record<string, unknown>)[key] = value;\n }\n }\n currentContext = next;\n } catch {\n // mirrors the core client, whose setContext never throws into the host app\n }\n };\n\n const removeAppStateFlush = installAppStateFlush(client);\n\n const reportError = (error: unknown): void => {\n try {\n config.onError?.(error);\n } catch {\n // a throwing observer must never break the host app\n }\n };\n\n const submitFeedback = createFeedbackSender({\n host: config.host,\n key: config.key,\n fetch: config.fetch ?? defaultReactNativeFetch(),\n getDistinctId: () => client.getDistinctId(),\n getSessionId: () => client.getSessionId(),\n getContext: () => currentContext,\n onError: reportError,\n });\n\n return {\n ...client,\n setContext,\n submitFeedback,\n reportError,\n userFeedbackAllowed: config.allowUserFeedback === true,\n feedbackOptions: config.feedback ?? {},\n shutdown: async () => {\n removeAppStateFlush();\n await client.shutdown();\n },\n };\n}\n\nfunction defaultReactNativeFetch(): FetchLike | undefined {\n if (typeof fetch !== \"function\") return undefined;\n return (url, init) => fetch(url, init);\n}\n\nexport { installAppStateFlush } from \"./appState\";\nexport { collectReactNativeContext, osNameFromPlatform } from \"./context\";\nexport { createAsyncStorageAdapter } from \"./storage\";\nexport { FeedbackProvider, type FeedbackProviderProps } from \"./feedbackProvider\";\nexport type {\n FeedbackSubmission,\n ReactNativeAnalyticsClient,\n ReactNativeFeedbackOptions,\n} from \"./feedback\";\nexport type {\n AnalyticsClient,\n AnalyticsLogger,\n ClientConfig,\n EventContext,\n FetchLike,\n LogSeverity,\n Properties,\n StorageAdapter,\n} from \"@getdevteam/analytics-core\";\n","import { AppState, type AppStateStatus } from \"react-native\";\nimport type { AnalyticsClient } from \"@getdevteam/analytics-core\";\n\nexport function installAppStateFlush(client: AnalyticsClient): () => void {\n const onChange = (state: AppStateStatus): void => {\n if (state === \"background\" || state === \"inactive\") {\n void client.flush();\n }\n };\n const subscription = AppState.addEventListener(\"change\", onChange);\n return () => subscription.remove();\n}\n","import { Platform } from \"react-native\";\nimport type { EventContext } from \"@getdevteam/analytics-core\";\n\nexport function osNameFromPlatform(os: string): string {\n switch (os) {\n case \"ios\":\n return \"iOS\";\n case \"android\":\n return \"Android\";\n case \"macos\":\n return \"macOS\";\n case \"windows\":\n return \"Windows\";\n default:\n return os;\n }\n}\n\nexport function collectReactNativeContext(): EventContext {\n const context: EventContext = { platform: \"react-native\" };\n try {\n context.os_name = osNameFromPlatform(Platform.OS);\n context.os_version = String(Platform.Version);\n context.device_type = Platform.isTV ? \"tv\" : Platform.isPad ? \"tablet\" : \"mobile\";\n } catch {\n // Platform constants can be unavailable outside a real RN runtime; the platform tag alone still stands\n }\n return context;\n}\n","import {\n uuidV7,\n type AnalyticsClient,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\n\nexport interface ReactNativeFeedbackOptions {\n colors?: string[];\n accentColor?: string;\n buttonLabel?: string;\n title?: string;\n submitLabel?: string;\n commentPlaceholder?: string;\n successMessage?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n}\n\nexport interface FeedbackSubmission {\n text: string;\n screenshot?: string;\n screenshotContentType?: \"image/png\" | \"image/jpeg\";\n pageUrl?: string;\n}\n\nexport interface ReactNativeAnalyticsClient extends AnalyticsClient {\n /**\n * Sends one piece of user feedback to the ingest API. Resolves false (never\n * throws) when the input is invalid or the POST fails; failures also report\n * through onError.\n */\n submitFeedback(input: FeedbackSubmission): Promise<boolean>;\n /** Reports an SDK-internal failure to the configured onError observer; never throws. */\n reportError(error: unknown): void;\n readonly userFeedbackAllowed: boolean;\n readonly feedbackOptions: ReactNativeFeedbackOptions;\n}\n\nexport const FEEDBACK_DEFAULT_COLORS = [\"#f44336\", \"#4caf50\", \"#2196f3\", \"#ffeb3b\"];\nexport const FEEDBACK_DEFAULT_ACCENT = \"#5b9cf5\";\n\nconst MAX_TEXT_LENGTH = 10000;\nconst MAX_PAGE_URL_LENGTH = 2048;\n\nexport interface FeedbackSenderConfig {\n host: string;\n key: string;\n fetch: FetchLike | undefined;\n getDistinctId(): string;\n getSessionId(): string;\n getContext(): EventContext;\n onError(error: unknown): void;\n}\n\nexport function createFeedbackSender(\n config: FeedbackSenderConfig,\n): (input: FeedbackSubmission) => Promise<boolean> {\n const url = `${String(config.host ?? \"\").replace(/\\/+$/, \"\")}/v1/ingest/feedback`;\n return async (input) => {\n try {\n const text = typeof input?.text === \"string\" ? input.text.trim() : \"\";\n if (text.length === 0) {\n config.onError(new Error(\"feedback text must be a non-empty string\"));\n return false;\n }\n const body: Record<string, unknown> = {\n feedback_id: uuidV7(),\n text: text.slice(0, MAX_TEXT_LENGTH),\n };\n if (typeof input.screenshot === \"string\" && input.screenshot.length > 0) {\n body.screenshot = input.screenshot;\n body.screenshot_content_type = input.screenshotContentType ?? \"image/png\";\n }\n const distinctId = config.getDistinctId();\n if (distinctId) body.distinct_id = distinctId;\n const sessionId = config.getSessionId();\n if (sessionId) body.session_id = sessionId;\n if (typeof input.pageUrl === \"string\" && input.pageUrl.length > 0) {\n body.page_url = input.pageUrl.slice(0, MAX_PAGE_URL_LENGTH);\n }\n body.context = config.getContext();\n if (!config.fetch) throw new Error(\"fetch is not available in this environment\");\n const response = await config.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-DevTeam-Key\": config.key },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n config.onError(new Error(`feedback ingest responded ${response.status}`));\n return false;\n }\n return true;\n } catch (error) {\n config.onError(error);\n return false;\n }\n };\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport type { StorageAdapter } from \"@getdevteam/analytics-core\";\n\nexport function createAsyncStorageAdapter(): StorageAdapter {\n return {\n getItem: async (key) => {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n setItem: async (key, value) => {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // storage unavailable; queue persistence degrades gracefully\n }\n },\n removeItem: async (key) => {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n };\n}\n","import {\n createElement,\n Fragment,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Dimensions,\n Image,\n Modal,\n PanResponder,\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n type GestureResponderEvent,\n} from \"react-native\";\nimport {\n FEEDBACK_DEFAULT_ACCENT,\n FEEDBACK_DEFAULT_COLORS,\n type FeedbackSubmission,\n type ReactNativeAnalyticsClient,\n} from \"./feedback\";\nimport { loadSvg, loadViewShot } from \"./optionalPeers\";\n\nconst PEN_WIDTH = 5;\nconst SUCCESS_CLOSE_DELAY_MS = 1600;\n\ninterface ProviderStroke {\n points: Array<{ x: number; y: number }>;\n color: string;\n width: number;\n}\n\nexport interface FeedbackProviderProps {\n client: ReactNativeAnalyticsClient;\n children?: ReactNode;\n}\n\n// Wraps the app with an optional floating feedback button. Renders children\n// unchanged when the client was created without allowUserFeedback, and every\n// optional peer degrades instead of failing: no react-native-view-shot means\n// comment-only feedback, no react-native-svg means no drawing tools.\nexport function FeedbackProvider(props: FeedbackProviderProps): ReactElement {\n const options = props.client.feedbackOptions ?? {};\n const colors = options.colors && options.colors.length > 0 ? options.colors : FEEDBACK_DEFAULT_COLORS;\n const firstColor = colors[0] ?? FEEDBACK_DEFAULT_COLORS[0]!;\n const accent = options.accentColor ?? FEEDBACK_DEFAULT_ACCENT;\n\n const [visible, setVisible] = useState(false);\n const [screenshot, setScreenshot] = useState<string | undefined>(undefined);\n const [screenshotSize, setScreenshotSize] = useState<\n { width: number; height: number } | undefined\n >(undefined);\n const [comment, setComment] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);\n const [activeColor, setActiveColor] = useState(firstColor);\n const [, setStrokeVersion] = useState(0);\n\n const contentRef = useRef<unknown>(null);\n const previewRef = useRef<unknown>(null);\n const strokesRef = useRef<ProviderStroke[]>([]);\n const activeStrokeRef = useRef<ProviderStroke | undefined>(undefined);\n const activeColorRef = useRef(firstColor);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n // Bumped on every open and close: a submit resolving for an earlier modal\n // session (sent, then cancelled and reopened mid-flight) must not paint its\n // outcome into, or auto-close, the new draft.\n const sessionRef = useRef(0);\n\n useEffect(\n () => () => {\n if (closeTimerRef.current !== undefined) clearTimeout(closeTimerRef.current);\n },\n [],\n );\n\n const bumpStrokes = useCallback(() => setStrokeVersion((version) => version + 1), []);\n\n const panResponderRef = useRef(\n PanResponder.create({\n onStartShouldSetPanResponder: () => true,\n onMoveShouldSetPanResponder: () => true,\n onPanResponderGrant: (event: GestureResponderEvent) => {\n const { locationX, locationY } = event.nativeEvent;\n const stroke: ProviderStroke = {\n points: [{ x: locationX, y: locationY }],\n color: activeColorRef.current,\n width: PEN_WIDTH,\n };\n activeStrokeRef.current = stroke;\n strokesRef.current.push(stroke);\n bumpStrokes();\n },\n onPanResponderMove: (event: GestureResponderEvent) => {\n const stroke = activeStrokeRef.current;\n if (!stroke) return;\n stroke.points.push({ x: event.nativeEvent.locationX, y: event.nativeEvent.locationY });\n bumpStrokes();\n },\n onPanResponderRelease: () => {\n activeStrokeRef.current = undefined;\n },\n onPanResponderTerminate: () => {\n activeStrokeRef.current = undefined;\n },\n }),\n );\n\n const close = useCallback(() => {\n sessionRef.current += 1;\n if (closeTimerRef.current !== undefined) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = undefined;\n }\n setVisible(false);\n setScreenshot(undefined);\n setScreenshotSize(undefined);\n setComment(\"\");\n setSending(false);\n setSent(false);\n setErrorMessage(undefined);\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n }, []);\n\n const open = useCallback(async () => {\n sessionRef.current += 1;\n try {\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n activeColorRef.current = firstColor;\n setActiveColor(firstColor);\n setComment(\"\");\n setSent(false);\n setSending(false);\n setErrorMessage(undefined);\n let shot: string | undefined;\n const viewShot = loadViewShot();\n if (viewShot && contentRef.current) {\n try {\n shot = await viewShot.captureRef(contentRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (captureError) {\n props.client.reportError(captureError);\n shot = undefined;\n }\n }\n setScreenshotSize(shot ? await capturedImageSize(shot) : undefined);\n setScreenshot(shot);\n setVisible(true);\n } catch (openError) {\n props.client.reportError(openError);\n setScreenshotSize(undefined);\n setScreenshot(undefined);\n setVisible(true);\n }\n }, [firstColor, props.client]);\n\n const submit = useCallback(async () => {\n if (sending || sent) return;\n const text = comment.trim();\n if (text.length === 0) {\n setErrorMessage(\"Please add a short comment before sending.\");\n return;\n }\n const session = sessionRef.current;\n setSending(true);\n setErrorMessage(undefined);\n try {\n let finalScreenshot = screenshot;\n const viewShot = loadViewShot();\n if (screenshot && strokesRef.current.length > 0 && viewShot && previewRef.current) {\n try {\n finalScreenshot = await viewShot.captureRef(previewRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (flattenError) {\n // the drawing could not be flattened; fall back to the plain screenshot\n props.client.reportError(flattenError);\n }\n }\n const submission: FeedbackSubmission = { text };\n if (finalScreenshot) {\n submission.screenshot = finalScreenshot;\n submission.screenshotContentType = \"image/png\";\n }\n const ok = await props.client.submitFeedback(submission);\n if (sessionRef.current !== session) return;\n if (ok) {\n setSent(true);\n closeTimerRef.current = setTimeout(close, SUCCESS_CLOSE_DELAY_MS);\n } else {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } catch {\n if (sessionRef.current === session) {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } finally {\n if (sessionRef.current === session) {\n setSending(false);\n }\n }\n }, [close, comment, props.client, screenshot, sending, sent]);\n\n const undo = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current.pop();\n bumpStrokes();\n }, [bumpStrokes]);\n\n const clear = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current = [];\n bumpStrokes();\n }, [bumpStrokes]);\n\n if (props.client.userFeedbackAllowed !== true || typeof props.client.submitFeedback !== \"function\") {\n return createElement(Fragment, null, props.children);\n }\n\n const svg = loadSvg();\n // The captured image's own dimensions drive the preview's aspect ratio; the\n // window is only a fallback when the size lookup failed, since the captured\n // view can be smaller than the window (e.g. inside a SafeAreaView).\n const window = Dimensions.get(\"window\");\n const previewAspectRatio =\n screenshotSize && screenshotSize.height > 0\n ? screenshotSize.width / screenshotSize.height\n : window.height > 0\n ? window.width / window.height\n : 1;\n const positionStyle = options.position === \"bottom-left\" ? styles.fabLeft : styles.fabRight;\n\n // Submitting with strokes flattens the drawing by re-capturing previewRef,\n // so the frame chrome (border, rounded corners) lives on a wrapper outside\n // the ref and never bakes into the stored screenshot.\n const preview = screenshot\n ? createElement(\n View,\n {\n style: [styles.preview, { aspectRatio: previewAspectRatio }],\n testID: \"devteam-feedback-preview-frame\",\n },\n createElement(\n View,\n { ref: previewRef, collapsable: false, style: styles.previewSurface },\n createElement(Image, {\n source: { uri: `data:image/png;base64,${screenshot}` },\n style: styles.previewImage,\n resizeMode: \"stretch\",\n testID: \"devteam-feedback-preview\",\n }),\n svg\n ? createElement(\n View,\n { style: styles.drawLayer, ...panResponderRef.current.panHandlers },\n createElement(\n svg.Svg,\n { width: \"100%\", height: \"100%\" },\n ...strokesRef.current.map((stroke, index) =>\n createElement(svg.Polyline, {\n key: String(index),\n points: stroke.points.map((point) => `${point.x},${point.y}`).join(\" \"),\n fill: \"none\",\n stroke: stroke.color,\n strokeWidth: stroke.width,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n }),\n ),\n ),\n )\n : null,\n ),\n )\n : null;\n\n const tools =\n screenshot && svg\n ? createElement(\n View,\n { style: styles.tools },\n ...colors.map((color) =>\n createElement(Pressable, {\n key: color,\n accessibilityRole: \"button\",\n testID: `devteam-feedback-color-${color}`,\n onPress: () => {\n activeColorRef.current = color;\n setActiveColor(color);\n },\n style: [\n styles.swatch,\n { backgroundColor: color },\n activeColor === color ? styles.swatchActive : null,\n ],\n }),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-undo\",\n onPress: undo,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Undo\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-clear\",\n onPress: clear,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Clear\"),\n ),\n )\n : null;\n\n const modal = createElement(\n Modal,\n { visible, transparent: true, animationType: \"fade\", onRequestClose: close },\n createElement(\n View,\n { style: styles.backdrop },\n createElement(\n View,\n { style: styles.panel },\n createElement(Text, { style: styles.title }, options.title ?? \"Send feedback\"),\n preview,\n tools,\n createElement(TextInput, {\n multiline: true,\n value: comment,\n onChangeText: setComment,\n placeholder: options.commentPlaceholder ?? \"What went wrong, or what could be better?\",\n style: styles.input,\n testID: \"devteam-feedback-comment\",\n }),\n errorMessage\n ? createElement(Text, { style: styles.error, testID: \"devteam-feedback-error\" }, errorMessage)\n : null,\n sent\n ? createElement(\n Text,\n { style: styles.success, testID: \"devteam-feedback-success\" },\n options.successMessage ?? \"Thanks for the feedback!\",\n )\n : null,\n createElement(\n View,\n { style: styles.actions },\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-cancel\",\n onPress: close,\n style: styles.cancelButton,\n },\n createElement(Text, { style: styles.cancelLabel }, \"Cancel\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-submit\",\n disabled: sending || sent,\n onPress: () => {\n void submit();\n },\n style: [styles.submitButton, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.submitLabel }, options.submitLabel ?? \"Send\"),\n ),\n ),\n ),\n ),\n );\n\n return createElement(\n View,\n { style: styles.root },\n createElement(\n View,\n { ref: contentRef, collapsable: false, style: styles.content },\n props.children,\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-button\",\n onPress: () => {\n void open();\n },\n style: [styles.fab, positionStyle, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.fabLabel }, options.buttonLabel ?? \"Feedback\"),\n ),\n modal,\n );\n}\n\nfunction capturedImageSize(\n base64: string,\n): Promise<{ width: number; height: number } | undefined> {\n return new Promise((resolve) => {\n try {\n Image.getSize(\n `data:image/png;base64,${base64}`,\n (width, height) => resolve(width > 0 && height > 0 ? { width, height } : undefined),\n () => resolve(undefined),\n );\n } catch {\n resolve(undefined);\n }\n });\n}\n\nconst styles = StyleSheet.create({\n root: { flex: 1 },\n content: { flex: 1 },\n fab: {\n position: \"absolute\",\n bottom: 24,\n borderRadius: 999,\n paddingVertical: 10,\n paddingHorizontal: 18,\n elevation: 4,\n },\n fabRight: { right: 20 },\n fabLeft: { left: 20 },\n fabLabel: { color: \"#ffffff\", fontSize: 14, fontWeight: \"600\" },\n backdrop: {\n flex: 1,\n backgroundColor: \"rgba(15, 23, 42, 0.55)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n },\n panel: {\n width: \"100%\",\n maxWidth: 560,\n backgroundColor: \"#ffffff\",\n borderRadius: 12,\n padding: 16,\n gap: 10,\n },\n title: { fontSize: 16, fontWeight: \"600\", color: \"#1f2933\" },\n preview: {\n width: \"100%\",\n borderRadius: 8,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n overflow: \"hidden\",\n },\n previewSurface: { width: \"100%\", height: \"100%\" },\n previewImage: { width: \"100%\", height: \"100%\" },\n drawLayer: { position: \"absolute\", top: 0, right: 0, bottom: 0, left: 0 },\n tools: { flexDirection: \"row\", alignItems: \"center\", gap: 8 },\n swatch: { width: 24, height: 24, borderRadius: 12, borderWidth: 2, borderColor: \"transparent\" },\n swatchActive: { borderColor: \"#1f2933\" },\n toolButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 6,\n paddingVertical: 4,\n paddingHorizontal: 10,\n },\n toolLabel: { fontSize: 13, color: \"#1f2933\" },\n input: {\n minHeight: 72,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n padding: 10,\n color: \"#1f2933\",\n textAlignVertical: \"top\",\n },\n error: { color: \"#b91c1c\", fontSize: 13 },\n success: { color: \"#15803d\", fontSize: 14, fontWeight: \"600\" },\n actions: { flexDirection: \"row\", justifyContent: \"flex-end\", gap: 8 },\n cancelButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n paddingVertical: 8,\n paddingHorizontal: 14,\n },\n cancelLabel: { fontSize: 14, color: \"#1f2933\" },\n submitButton: { borderRadius: 8, paddingVertical: 8, paddingHorizontal: 16 },\n submitLabel: { fontSize: 14, fontWeight: \"600\", color: \"#ffffff\" },\n});\n","import type { ComponentType } from \"react\";\n\n// This file may be evaluated where `require` does not exist at all.\ndeclare const require: ((id: string) => unknown) | undefined;\n\nexport interface ViewShotCaptureOptions {\n format?: \"png\" | \"jpg\";\n quality?: number;\n result?: \"base64\" | \"tmpfile\" | \"data-uri\";\n}\n\nexport interface ViewShotModule {\n captureRef(ref: unknown, options?: ViewShotCaptureOptions): Promise<string>;\n}\n\nexport interface SvgModule {\n Svg: ComponentType<Record<string, unknown>>;\n Polyline: ComponentType<Record<string, unknown>>;\n}\n\ntype OptionalModuleLoader = (name: string) => unknown;\n\nlet testLoaderOverride: OptionalModuleLoader | undefined;\n\nexport function setOptionalModuleLoaderForTesting(loader: OptionalModuleLoader | undefined): void {\n testLoaderOverride = loader;\n}\n\n// Metro consumes the CJS build (the \"require\" export condition) and only\n// resolves string-literal specifiers - a `require(variable)` in a node_modules\n// package throws at runtime even when the peer IS installed - so each peer\n// gets its own literal require, kept directly inside a try/catch so\n// `transformer.allowOptionalDependencies` marks it optional and a missing peer\n// degrades instead of failing the bundle. esbuild's ESM output rewrites bare\n// `require` into a shim that throws at call time, so import-condition\n// consumers (react-native-web, Node ESM) land on the same degraded path\n// instead of crashing at load.\nfunction requireViewShot(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-view-shot\");\n } catch {\n return undefined;\n }\n}\n\nfunction requireSvg(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-svg\");\n } catch {\n return undefined;\n }\n}\n\nfunction loadOptionalModule(name: string, requirePeer: () => unknown): unknown {\n if (testLoaderOverride) {\n try {\n return testLoaderOverride(name);\n } catch {\n return undefined;\n }\n }\n return requirePeer();\n}\n\nexport function loadViewShot(): ViewShotModule | undefined {\n const loaded = loadOptionalModule(\"react-native-view-shot\", requireViewShot) as\n | { captureRef?: unknown; default?: { captureRef?: unknown } }\n | undefined;\n const captureRef = loaded?.captureRef ?? loaded?.default?.captureRef;\n if (typeof captureRef !== \"function\") return undefined;\n return { captureRef: captureRef as ViewShotModule[\"captureRef\"] };\n}\n\nexport function loadSvg(): SvgModule | undefined {\n const loaded = loadOptionalModule(\"react-native-svg\", requireSvg) as\n | { Svg?: unknown; Polyline?: unknown; default?: unknown }\n | undefined;\n const svg = loaded?.Svg ?? loaded?.default;\n const polyline = loaded?.Polyline;\n if (svg == null || polyline == null) return undefined;\n return {\n Svg: svg as SvgModule[\"Svg\"],\n Polyline: polyline as SvgModule[\"Polyline\"],\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/appState.ts","../src/context.ts","../src/feedback.ts","../src/storage.ts","../src/feedbackProvider.ts","../src/optionalPeers.ts"],"sourcesContent":["import {\n createClient,\n type ClientConfig,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\nimport { installAppStateFlush } from \"./appState\";\nimport { collectReactNativeContext } from \"./context\";\nimport {\n createFeedbackSender,\n type ReactNativeAnalyticsClient,\n type ReactNativeFeedbackOptions,\n} from \"./feedback\";\nimport { createAsyncStorageAdapter } from \"./storage\";\n\nexport const REACT_NATIVE_SDK_NAME = \"@getdevteam/analytics-react-native\";\nexport const REACT_NATIVE_SDK_VERSION = \"0.3.1\";\n\nexport interface ReactNativeAnalyticsConfig extends ClientConfig {\n context?: Partial<EventContext>;\n allowUserFeedback?: boolean;\n feedback?: ReactNativeFeedbackOptions;\n}\n\nexport function createAnalytics(config: ReactNativeAnalyticsConfig): ReactNativeAnalyticsClient {\n const client = createClient({\n ...config,\n storage: config.storage ?? createAsyncStorageAdapter(),\n });\n\n const reactNativeContext: EventContext = {\n sdk_name: REACT_NATIVE_SDK_NAME,\n sdk_version: REACT_NATIVE_SDK_VERSION,\n ...collectReactNativeContext(),\n ...config.context,\n };\n client.setContext(reactNativeContext);\n\n // Feedback reads the context at submit time, so it must track later\n // setContext calls. The core client keeps its merged copy private, so the\n // wrapper mirrors the merge (an undefined value deletes the key) here.\n let currentContext = reactNativeContext;\n const setContext = (partial: Partial<EventContext>): void => {\n client.setContext(partial);\n try {\n const next: EventContext = { ...currentContext };\n for (const [key, value] of Object.entries(partial)) {\n if (value === undefined) {\n delete next[key as keyof EventContext];\n } else {\n (next as Record<string, unknown>)[key] = value;\n }\n }\n currentContext = next;\n } catch {\n // mirrors the core client, whose setContext never throws into the host app\n }\n };\n\n const removeAppStateFlush = installAppStateFlush(client);\n\n const reportError = (error: unknown): void => {\n try {\n config.onError?.(error);\n } catch {\n // a throwing observer must never break the host app\n }\n };\n\n const submitFeedback = createFeedbackSender({\n host: config.host,\n key: config.key,\n fetch: config.fetch ?? defaultReactNativeFetch(),\n getDistinctId: () => client.getDistinctId(),\n getSessionId: () => client.getSessionId(),\n getContext: () => currentContext,\n onError: reportError,\n });\n\n return {\n ...client,\n setContext,\n submitFeedback,\n reportError,\n userFeedbackAllowed: config.allowUserFeedback === true,\n feedbackOptions: config.feedback ?? {},\n shutdown: async () => {\n removeAppStateFlush();\n await client.shutdown();\n },\n };\n}\n\nfunction defaultReactNativeFetch(): FetchLike | undefined {\n if (typeof fetch !== \"function\") return undefined;\n return (url, init) => fetch(url, init);\n}\n\nexport { installAppStateFlush } from \"./appState\";\nexport { collectReactNativeContext, osNameFromPlatform } from \"./context\";\nexport { createAsyncStorageAdapter } from \"./storage\";\nexport { FeedbackProvider, type FeedbackProviderProps } from \"./feedbackProvider\";\nexport type {\n FeedbackSubmission,\n ReactNativeAnalyticsClient,\n ReactNativeFeedbackOptions,\n} from \"./feedback\";\nexport type {\n AnalyticsClient,\n AnalyticsLogger,\n ClientConfig,\n EventContext,\n FetchLike,\n LogSeverity,\n Properties,\n StorageAdapter,\n} from \"@getdevteam/analytics-core\";\n","import { AppState, type AppStateStatus } from \"react-native\";\nimport type { AnalyticsClient } from \"@getdevteam/analytics-core\";\n\nexport function installAppStateFlush(client: AnalyticsClient): () => void {\n const onChange = (state: AppStateStatus): void => {\n if (state === \"background\" || state === \"inactive\") {\n void client.flush();\n }\n };\n const subscription = AppState.addEventListener(\"change\", onChange);\n return () => subscription.remove();\n}\n","import { Platform } from \"react-native\";\nimport type { EventContext } from \"@getdevteam/analytics-core\";\n\nexport function osNameFromPlatform(os: string): string {\n switch (os) {\n case \"ios\":\n return \"iOS\";\n case \"android\":\n return \"Android\";\n case \"macos\":\n return \"macOS\";\n case \"windows\":\n return \"Windows\";\n default:\n return os;\n }\n}\n\nexport function collectReactNativeContext(): EventContext {\n const context: EventContext = { platform: \"react-native\" };\n try {\n context.os_name = osNameFromPlatform(Platform.OS);\n context.os_version = String(Platform.Version);\n context.device_type = Platform.isTV ? \"tv\" : Platform.isPad ? \"tablet\" : \"mobile\";\n } catch {\n // Platform constants can be unavailable outside a real RN runtime; the platform tag alone still stands\n }\n return context;\n}\n","import {\n uuidV7,\n type AnalyticsClient,\n type EventContext,\n type FetchLike,\n} from \"@getdevteam/analytics-core\";\n\nexport interface ReactNativeFeedbackOptions {\n colors?: string[];\n accentColor?: string;\n buttonLabel?: string;\n title?: string;\n submitLabel?: string;\n commentPlaceholder?: string;\n successMessage?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n}\n\nexport interface FeedbackSubmission {\n text: string;\n screenshot?: string;\n screenshotContentType?: \"image/png\" | \"image/jpeg\";\n pageUrl?: string;\n}\n\nexport interface ReactNativeAnalyticsClient extends AnalyticsClient {\n /**\n * Sends one piece of user feedback to the ingest API. Resolves false (never\n * throws) when the input is invalid or the POST fails; failures also report\n * through onError.\n */\n submitFeedback(input: FeedbackSubmission): Promise<boolean>;\n /** Reports an SDK-internal failure to the configured onError observer; never throws. */\n reportError(error: unknown): void;\n readonly userFeedbackAllowed: boolean;\n readonly feedbackOptions: ReactNativeFeedbackOptions;\n}\n\nexport const FEEDBACK_DEFAULT_COLORS = [\"#f44336\", \"#4caf50\", \"#2196f3\", \"#ffeb3b\"];\nexport const FEEDBACK_DEFAULT_ACCENT = \"#5b9cf5\";\n\nconst MAX_TEXT_LENGTH = 10000;\nconst MAX_PAGE_URL_LENGTH = 2048;\n\nexport interface FeedbackSenderConfig {\n host: string;\n key: string;\n fetch: FetchLike | undefined;\n getDistinctId(): string;\n getSessionId(): string;\n getContext(): EventContext;\n onError(error: unknown): void;\n}\n\nexport function createFeedbackSender(\n config: FeedbackSenderConfig,\n): (input: FeedbackSubmission) => Promise<boolean> {\n const url = `${String(config.host ?? \"\").replace(/\\/+$/, \"\")}/v1/ingest/feedback`;\n return async (input) => {\n try {\n const text = typeof input?.text === \"string\" ? input.text.trim() : \"\";\n if (text.length === 0) {\n config.onError(new Error(\"feedback text must be a non-empty string\"));\n return false;\n }\n const body: Record<string, unknown> = {\n feedback_id: uuidV7(),\n text: text.slice(0, MAX_TEXT_LENGTH),\n };\n if (typeof input.screenshot === \"string\" && input.screenshot.length > 0) {\n body.screenshot = input.screenshot;\n body.screenshot_content_type = input.screenshotContentType ?? \"image/png\";\n }\n const distinctId = config.getDistinctId();\n if (distinctId) body.distinct_id = distinctId;\n const sessionId = config.getSessionId();\n if (sessionId) body.session_id = sessionId;\n if (typeof input.pageUrl === \"string\" && input.pageUrl.length > 0) {\n body.page_url = input.pageUrl.slice(0, MAX_PAGE_URL_LENGTH);\n }\n body.context = config.getContext();\n if (!config.fetch) throw new Error(\"fetch is not available in this environment\");\n const response = await config.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-DevTeam-Key\": config.key },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n config.onError(new Error(`feedback ingest responded ${response.status}`));\n return false;\n }\n return true;\n } catch (error) {\n config.onError(error);\n return false;\n }\n };\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport type { StorageAdapter } from \"@getdevteam/analytics-core\";\n\nexport function createAsyncStorageAdapter(): StorageAdapter {\n return {\n getItem: async (key) => {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n setItem: async (key, value) => {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // storage unavailable; queue persistence degrades gracefully\n }\n },\n removeItem: async (key) => {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n };\n}\n","import {\n createElement,\n Fragment,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Dimensions,\n Image,\n Modal,\n PanResponder,\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n type GestureResponderEvent,\n} from \"react-native\";\nimport {\n FEEDBACK_DEFAULT_ACCENT,\n FEEDBACK_DEFAULT_COLORS,\n type FeedbackSubmission,\n type ReactNativeAnalyticsClient,\n} from \"./feedback\";\nimport { loadSvg, loadViewShot } from \"./optionalPeers\";\n\nconst PEN_WIDTH = 5;\nconst SUCCESS_CLOSE_DELAY_MS = 1600;\n\ninterface ProviderStroke {\n points: Array<{ x: number; y: number }>;\n color: string;\n width: number;\n}\n\nexport interface FeedbackProviderProps {\n client: ReactNativeAnalyticsClient;\n children?: ReactNode;\n}\n\n// Wraps the app with an optional floating feedback button. Renders children\n// unchanged when the client was created without allowUserFeedback, and every\n// optional peer degrades instead of failing: no react-native-view-shot means\n// comment-only feedback, no react-native-svg means no drawing tools.\nexport function FeedbackProvider(props: FeedbackProviderProps): ReactElement {\n const options = props.client.feedbackOptions ?? {};\n const colors = options.colors && options.colors.length > 0 ? options.colors : FEEDBACK_DEFAULT_COLORS;\n const firstColor = colors[0] ?? FEEDBACK_DEFAULT_COLORS[0]!;\n const accent = options.accentColor ?? FEEDBACK_DEFAULT_ACCENT;\n\n const [visible, setVisible] = useState(false);\n const [screenshot, setScreenshot] = useState<string | undefined>(undefined);\n const [screenshotSize, setScreenshotSize] = useState<\n { width: number; height: number } | undefined\n >(undefined);\n const [comment, setComment] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [sent, setSent] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);\n const [activeColor, setActiveColor] = useState(firstColor);\n const [, setStrokeVersion] = useState(0);\n\n const contentRef = useRef<unknown>(null);\n const previewRef = useRef<unknown>(null);\n const strokesRef = useRef<ProviderStroke[]>([]);\n const activeStrokeRef = useRef<ProviderStroke | undefined>(undefined);\n const activeColorRef = useRef(firstColor);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n // Bumped on every open and close: a submit resolving for an earlier modal\n // session (sent, then cancelled and reopened mid-flight) must not paint its\n // outcome into, or auto-close, the new draft.\n const sessionRef = useRef(0);\n\n useEffect(\n () => () => {\n if (closeTimerRef.current !== undefined) clearTimeout(closeTimerRef.current);\n },\n [],\n );\n\n const bumpStrokes = useCallback(() => setStrokeVersion((version) => version + 1), []);\n\n const panResponderRef = useRef(\n PanResponder.create({\n onStartShouldSetPanResponder: () => true,\n onMoveShouldSetPanResponder: () => true,\n onPanResponderGrant: (event: GestureResponderEvent) => {\n const { locationX, locationY } = event.nativeEvent;\n const stroke: ProviderStroke = {\n points: [{ x: locationX, y: locationY }],\n color: activeColorRef.current,\n width: PEN_WIDTH,\n };\n activeStrokeRef.current = stroke;\n strokesRef.current.push(stroke);\n bumpStrokes();\n },\n onPanResponderMove: (event: GestureResponderEvent) => {\n const stroke = activeStrokeRef.current;\n if (!stroke) return;\n stroke.points.push({ x: event.nativeEvent.locationX, y: event.nativeEvent.locationY });\n bumpStrokes();\n },\n onPanResponderRelease: () => {\n activeStrokeRef.current = undefined;\n },\n onPanResponderTerminate: () => {\n activeStrokeRef.current = undefined;\n },\n }),\n );\n\n const close = useCallback(() => {\n sessionRef.current += 1;\n if (closeTimerRef.current !== undefined) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = undefined;\n }\n setVisible(false);\n setScreenshot(undefined);\n setScreenshotSize(undefined);\n setComment(\"\");\n setSending(false);\n setSent(false);\n setErrorMessage(undefined);\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n }, []);\n\n const open = useCallback(async () => {\n sessionRef.current += 1;\n try {\n strokesRef.current = [];\n activeStrokeRef.current = undefined;\n activeColorRef.current = firstColor;\n setActiveColor(firstColor);\n setComment(\"\");\n setSent(false);\n setSending(false);\n setErrorMessage(undefined);\n let shot: string | undefined;\n const viewShot = loadViewShot();\n if (viewShot && contentRef.current) {\n try {\n shot = await viewShot.captureRef(contentRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (captureError) {\n props.client.reportError(captureError);\n shot = undefined;\n }\n }\n setScreenshotSize(shot ? await capturedImageSize(shot) : undefined);\n setScreenshot(shot);\n setVisible(true);\n } catch (openError) {\n props.client.reportError(openError);\n setScreenshotSize(undefined);\n setScreenshot(undefined);\n setVisible(true);\n }\n }, [firstColor, props.client]);\n\n const submit = useCallback(async () => {\n if (sending || sent) return;\n const text = comment.trim();\n if (text.length === 0) {\n setErrorMessage(\"Please add a short comment before sending.\");\n return;\n }\n const session = sessionRef.current;\n setSending(true);\n setErrorMessage(undefined);\n try {\n let finalScreenshot = screenshot;\n const viewShot = loadViewShot();\n if (screenshot && strokesRef.current.length > 0 && viewShot && previewRef.current) {\n try {\n finalScreenshot = await viewShot.captureRef(previewRef.current, {\n format: \"png\",\n quality: 0.9,\n result: \"base64\",\n });\n } catch (flattenError) {\n // the drawing could not be flattened; fall back to the plain screenshot\n props.client.reportError(flattenError);\n }\n }\n const submission: FeedbackSubmission = { text };\n if (finalScreenshot) {\n submission.screenshot = finalScreenshot;\n submission.screenshotContentType = \"image/png\";\n }\n const ok = await props.client.submitFeedback(submission);\n if (sessionRef.current !== session) return;\n if (ok) {\n setSent(true);\n closeTimerRef.current = setTimeout(close, SUCCESS_CLOSE_DELAY_MS);\n } else {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } catch {\n if (sessionRef.current === session) {\n setErrorMessage(\"Could not send feedback. Please try again.\");\n }\n } finally {\n if (sessionRef.current === session) {\n setSending(false);\n }\n }\n }, [close, comment, props.client, screenshot, sending, sent]);\n\n const undo = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current.pop();\n bumpStrokes();\n }, [bumpStrokes]);\n\n const clear = useCallback(() => {\n if (activeStrokeRef.current) return;\n strokesRef.current = [];\n bumpStrokes();\n }, [bumpStrokes]);\n\n if (props.client.userFeedbackAllowed !== true || typeof props.client.submitFeedback !== \"function\") {\n return createElement(Fragment, null, props.children);\n }\n\n const svg = loadSvg();\n // The captured image's own dimensions drive the preview's aspect ratio; the\n // window is only a fallback when the size lookup failed, since the captured\n // view can be smaller than the window (e.g. inside a SafeAreaView).\n const window = Dimensions.get(\"window\");\n const previewAspectRatio =\n screenshotSize && screenshotSize.height > 0\n ? screenshotSize.width / screenshotSize.height\n : window.height > 0\n ? window.width / window.height\n : 1;\n const positionStyle = options.position === \"bottom-left\" ? styles.fabLeft : styles.fabRight;\n\n // Submitting with strokes flattens the drawing by re-capturing previewRef,\n // so the frame chrome (border, rounded corners) lives on a wrapper outside\n // the ref and never bakes into the stored screenshot.\n const preview = screenshot\n ? createElement(\n View,\n {\n style: [styles.preview, { aspectRatio: previewAspectRatio }],\n testID: \"devteam-feedback-preview-frame\",\n },\n createElement(\n View,\n { ref: previewRef, collapsable: false, style: styles.previewSurface },\n createElement(Image, {\n source: { uri: `data:image/png;base64,${screenshot}` },\n style: styles.previewImage,\n resizeMode: \"stretch\",\n testID: \"devteam-feedback-preview\",\n }),\n svg\n ? createElement(\n View,\n { style: styles.drawLayer, ...panResponderRef.current.panHandlers },\n createElement(\n svg.Svg,\n { width: \"100%\", height: \"100%\" },\n ...strokesRef.current.map((stroke, index) =>\n createElement(svg.Polyline, {\n key: String(index),\n points: stroke.points.map((point) => `${point.x},${point.y}`).join(\" \"),\n fill: \"none\",\n stroke: stroke.color,\n strokeWidth: stroke.width,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n }),\n ),\n ),\n )\n : null,\n ),\n )\n : null;\n\n const tools =\n screenshot && svg\n ? createElement(\n View,\n { style: styles.tools },\n ...colors.map((color) =>\n createElement(Pressable, {\n key: color,\n accessibilityRole: \"button\",\n testID: `devteam-feedback-color-${color}`,\n onPress: () => {\n activeColorRef.current = color;\n setActiveColor(color);\n },\n style: [\n styles.swatch,\n { backgroundColor: color },\n activeColor === color ? styles.swatchActive : null,\n ],\n }),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-undo\",\n onPress: undo,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Undo\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-clear\",\n onPress: clear,\n style: styles.toolButton,\n },\n createElement(Text, { style: styles.toolLabel }, \"Clear\"),\n ),\n )\n : null;\n\n const modal = createElement(\n Modal,\n { visible, transparent: true, animationType: \"fade\", onRequestClose: close },\n createElement(\n View,\n { style: styles.backdrop },\n createElement(\n View,\n { style: styles.panel },\n createElement(Text, { style: styles.title }, options.title ?? \"Send feedback\"),\n preview,\n tools,\n createElement(TextInput, {\n multiline: true,\n value: comment,\n onChangeText: setComment,\n placeholder: options.commentPlaceholder ?? \"What went wrong, or what could be better?\",\n style: styles.input,\n testID: \"devteam-feedback-comment\",\n }),\n errorMessage\n ? createElement(Text, { style: styles.error, testID: \"devteam-feedback-error\" }, errorMessage)\n : null,\n sent\n ? createElement(\n Text,\n { style: styles.success, testID: \"devteam-feedback-success\" },\n options.successMessage ?? \"Thanks for the feedback!\",\n )\n : null,\n createElement(\n View,\n { style: styles.actions },\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-cancel\",\n onPress: close,\n style: styles.cancelButton,\n },\n createElement(Text, { style: styles.cancelLabel }, \"Cancel\"),\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-submit\",\n disabled: sending || sent,\n onPress: () => {\n void submit();\n },\n style: [styles.submitButton, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.submitLabel }, options.submitLabel ?? \"Send\"),\n ),\n ),\n ),\n ),\n );\n\n return createElement(\n View,\n { style: styles.root },\n createElement(\n View,\n { ref: contentRef, collapsable: false, style: styles.content },\n props.children,\n ),\n createElement(\n Pressable,\n {\n accessibilityRole: \"button\",\n testID: \"devteam-feedback-button\",\n onPress: () => {\n void open();\n },\n style: [styles.fab, positionStyle, { backgroundColor: accent }],\n },\n createElement(Text, { style: styles.fabLabel }, options.buttonLabel ?? \"Feedback\"),\n ),\n modal,\n );\n}\n\nfunction capturedImageSize(\n base64: string,\n): Promise<{ width: number; height: number } | undefined> {\n return new Promise((resolve) => {\n try {\n Image.getSize(\n `data:image/png;base64,${base64}`,\n (width, height) => resolve(width > 0 && height > 0 ? { width, height } : undefined),\n () => resolve(undefined),\n );\n } catch {\n resolve(undefined);\n }\n });\n}\n\nconst styles = StyleSheet.create({\n root: { flex: 1 },\n content: { flex: 1 },\n fab: {\n position: \"absolute\",\n bottom: 24,\n borderRadius: 999,\n paddingVertical: 10,\n paddingHorizontal: 18,\n elevation: 4,\n },\n fabRight: { right: 20 },\n fabLeft: { left: 20 },\n fabLabel: { color: \"#ffffff\", fontSize: 14, fontWeight: \"600\" },\n backdrop: {\n flex: 1,\n backgroundColor: \"rgba(15, 23, 42, 0.55)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n },\n panel: {\n width: \"100%\",\n maxWidth: 560,\n backgroundColor: \"#ffffff\",\n borderRadius: 12,\n padding: 16,\n gap: 10,\n },\n title: { fontSize: 16, fontWeight: \"600\", color: \"#1f2933\" },\n preview: {\n width: \"100%\",\n borderRadius: 8,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n overflow: \"hidden\",\n },\n previewSurface: { width: \"100%\", height: \"100%\" },\n previewImage: { width: \"100%\", height: \"100%\" },\n drawLayer: { position: \"absolute\", top: 0, right: 0, bottom: 0, left: 0 },\n tools: { flexDirection: \"row\", alignItems: \"center\", gap: 8 },\n swatch: { width: 24, height: 24, borderRadius: 12, borderWidth: 2, borderColor: \"transparent\" },\n swatchActive: { borderColor: \"#1f2933\" },\n toolButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 6,\n paddingVertical: 4,\n paddingHorizontal: 10,\n },\n toolLabel: { fontSize: 13, color: \"#1f2933\" },\n input: {\n minHeight: 72,\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n padding: 10,\n color: \"#1f2933\",\n textAlignVertical: \"top\",\n },\n error: { color: \"#b91c1c\", fontSize: 13 },\n success: { color: \"#15803d\", fontSize: 14, fontWeight: \"600\" },\n actions: { flexDirection: \"row\", justifyContent: \"flex-end\", gap: 8 },\n cancelButton: {\n borderWidth: 1,\n borderColor: \"#d3dce6\",\n borderRadius: 8,\n paddingVertical: 8,\n paddingHorizontal: 14,\n },\n cancelLabel: { fontSize: 14, color: \"#1f2933\" },\n submitButton: { borderRadius: 8, paddingVertical: 8, paddingHorizontal: 16 },\n submitLabel: { fontSize: 14, fontWeight: \"600\", color: \"#ffffff\" },\n});\n","import type { ComponentType } from \"react\";\n\n// This file may be evaluated where `require` does not exist at all.\ndeclare const require: ((id: string) => unknown) | undefined;\n\nexport interface ViewShotCaptureOptions {\n format?: \"png\" | \"jpg\";\n quality?: number;\n result?: \"base64\" | \"tmpfile\" | \"data-uri\";\n}\n\nexport interface ViewShotModule {\n captureRef(ref: unknown, options?: ViewShotCaptureOptions): Promise<string>;\n}\n\nexport interface SvgModule {\n Svg: ComponentType<Record<string, unknown>>;\n Polyline: ComponentType<Record<string, unknown>>;\n}\n\ntype OptionalModuleLoader = (name: string) => unknown;\n\nlet testLoaderOverride: OptionalModuleLoader | undefined;\n\nexport function setOptionalModuleLoaderForTesting(loader: OptionalModuleLoader | undefined): void {\n testLoaderOverride = loader;\n}\n\n// Metro consumes the CJS build (the \"require\" export condition) and only\n// resolves string-literal specifiers - a `require(variable)` in a node_modules\n// package throws at runtime even when the peer IS installed - so each peer\n// gets its own literal require, kept directly inside a try/catch so\n// `transformer.allowOptionalDependencies` marks it optional and a missing peer\n// degrades instead of failing the bundle. esbuild's ESM output rewrites bare\n// `require` into a shim that throws at call time, so import-condition\n// consumers (react-native-web, Node ESM) land on the same degraded path\n// instead of crashing at load.\nfunction requireViewShot(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-view-shot\");\n } catch {\n return undefined;\n }\n}\n\nfunction requireSvg(): unknown {\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"react-native-svg\");\n } catch {\n return undefined;\n }\n}\n\nfunction loadOptionalModule(name: string, requirePeer: () => unknown): unknown {\n if (testLoaderOverride) {\n try {\n return testLoaderOverride(name);\n } catch {\n return undefined;\n }\n }\n return requirePeer();\n}\n\nexport function loadViewShot(): ViewShotModule | undefined {\n const loaded = loadOptionalModule(\"react-native-view-shot\", requireViewShot) as\n | { captureRef?: unknown; default?: { captureRef?: unknown } }\n | undefined;\n const captureRef = loaded?.captureRef ?? loaded?.default?.captureRef;\n if (typeof captureRef !== \"function\") return undefined;\n return { captureRef: captureRef as ViewShotModule[\"captureRef\"] };\n}\n\nexport function loadSvg(): SvgModule | undefined {\n const loaded = loadOptionalModule(\"react-native-svg\", requireSvg) as\n | { Svg?: unknown; Polyline?: unknown; default?: unknown }\n | undefined;\n const svg = loaded?.Svg ?? loaded?.default;\n const polyline = loaded?.Polyline;\n if (svg == null || polyline == null) return undefined;\n return {\n Svg: svg as SvgModule[\"Svg\"],\n Polyline: polyline as SvgModule[\"Polyline\"],\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getdevteam/analytics-react-native",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "React Native SDK for the DevTeam analytics and logging platform.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  "typecheck": "tsc --noEmit"
36
36
  },
37
37
  "dependencies": {
38
- "@getdevteam/analytics-core": "0.2.0"
38
+ "@getdevteam/analytics-core": "0.3.1"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@react-native-async-storage/async-storage": ">=1.19.0",