reflet-sdk 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"handler-C9tdKcl0.js","names":["TRAILING_SLASHES","QUERY_OR_HASH"],"sources":["../src/devtools/server/json-response.ts","../src/devtools/server/request-guard.ts","../src/devtools/server/connect/connectable-host.ts","../src/devtools/server/connect/connection-store.ts","../src/devtools/server/connect/board-credential.ts","../src/devtools/server/connect/html-page.ts","../src/devtools/server/connect/pending-connects.ts","../src/devtools/server/connect/connect-routes.ts","../src/devtools/server/options.ts","../src/devtools/server/reflet-proxy.ts","../src/devtools/server/source/code-search.ts","../src/devtools/server/source/project-roots.ts","../src/devtools/server/source/jsx-range.ts","../src/devtools/server/source/server-frame.ts","../src/devtools/server/source/source-file.ts","../src/devtools/server/handler.ts"],"sourcesContent":["import type { DevtoolsErrorBody } from \"../protocol\";\n\nexport type DevtoolsOutcome<T> =\n | { ok: true; value: T }\n | { error: string; ok: false; status: number };\n\nexport const JSON_RESPONSE_HEADERS = {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n};\n\nexport function jsonTextResponse(\n text: string | null,\n status: number\n): Response {\n return new Response(text, { headers: JSON_RESPONSE_HEADERS, status });\n}\n\nexport function jsonResponse(body: unknown, status = 200): Response {\n return jsonTextResponse(JSON.stringify(body), status);\n}\n\nexport function errorResponse(error: string, status: number): Response {\n const body: DevtoolsErrorBody = { error };\n return jsonResponse(body, status);\n}\n\nexport function failure<T>(error: string, status: number): DevtoolsOutcome<T> {\n return { error, ok: false, status };\n}\n","import { DEVTOOLS_REQUEST_HEADER } from \"../protocol\";\nimport { errorResponse } from \"./json-response\";\n\nconst LOOPBACK_HOSTNAMES = [\"localhost\", \"[::1]\"];\nconst LOOPBACK_IPV4 = /^127(?:\\.\\d{1,3}){3}$/;\nconst IPV4_MAPPED_PREFIX = \"::ffff:\";\nconst TRUSTED_FETCH_SITES = [\"same-origin\", \"none\"];\n\nfunction hostnameOf(request: Request): string | null {\n const host = request.headers.get(\"host\") ?? new URL(request.url).host;\n try {\n return new URL(`http://${host}`).hostname.toLowerCase();\n } catch {\n return null;\n }\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n return (\n LOOPBACK_HOSTNAMES.includes(hostname) ||\n hostname.endsWith(\".localhost\") ||\n LOOPBACK_IPV4.test(hostname)\n );\n}\n\nexport function isLoopbackAddress(address: string | undefined): boolean {\n if (!address) {\n return false;\n }\n const ipv4 = address.startsWith(IPV4_MAPPED_PREFIX)\n ? address.slice(IPV4_MAPPED_PREFIX.length)\n : address;\n return address === \"::1\" || LOOPBACK_IPV4.test(ipv4);\n}\n\n/**\n * The Host check stops DNS rebinding: a hostile domain resolved to 127.0.0.1\n * is same-origin with itself, so origin checks alone would let it through.\n * Host and header checks only stop browsers; keeping other machines out is the\n * job of a dev server bound to loopback.\n */\nexport function rejectUntrustedHost(\n request: Request,\n allowedHosts: string[]\n): Response | null {\n const hostname = hostnameOf(request);\n const isAllowedHost =\n hostname !== null &&\n (isLoopbackHostname(hostname) || allowedHosts.includes(hostname));\n if (!isAllowedHost) {\n return errorResponse(\n \"Reflet devtools only answers on localhost. Add other dev hostnames to allowedHosts or REFLET_DEVTOOLS_HOSTS.\",\n 403\n );\n }\n return null;\n}\n\nexport function rejectUntrustedCaller(\n request: Request,\n allowedHosts: string[]\n): Response | null {\n if (request.headers.get(DEVTOOLS_REQUEST_HEADER) !== \"1\") {\n return errorResponse(\n `Reflet devtools requests must send the ${DEVTOOLS_REQUEST_HEADER} header.`,\n 403\n );\n }\n\n const fetchSite = request.headers.get(\"sec-fetch-site\");\n const hostname = hostnameOf(request);\n // Browsers omit Sec-Fetch-Site only outside secure contexts: a plain-HTTP allowed host, never loopback.\n const mayOmitFetchSite =\n hostname !== null &&\n allowedHosts.includes(hostname) &&\n !isLoopbackHostname(hostname);\n const isTrustedSite =\n fetchSite === null\n ? mayOmitFetchSite\n : TRUSTED_FETCH_SITES.includes(fetchSite);\n if (!isTrustedSite) {\n return errorResponse(\n \"Reflet devtools only answers requests from the app's own origin.\",\n 403\n );\n }\n\n return null;\n}\n","import { isLoopbackHostname } from \"../request-guard\";\n\n/** Mirrors the backend redirect allowlist, which stays the authority; this only decides whether Connect is offered. */\nexport function isConnectableHost(hostname: string): boolean {\n return isLoopbackHostname(hostname) || hostname.endsWith(\".test\");\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\n\nconst storedConnectionSchema = z.object({\n apiUrl: z.url(),\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_dev_\"),\n});\nexport type StoredConnection = z.infer<typeof storedConnectionSchema>;\n\nconst connectionsDirectory = () => join(homedir(), \".reflet\", \"devtools\");\n\nfunction connectionFile(root: string, apiUrl: string) {\n const key = createHash(\"sha256\")\n .update(JSON.stringify([root, apiUrl]))\n .digest(\"hex\");\n return join(connectionsDirectory(), `${key}.json`);\n}\n\nexport async function readConnection(\n root: string,\n apiUrl: string\n): Promise<StoredConnection | null> {\n try {\n const connection = storedConnectionSchema.parse(\n JSON.parse(await readFile(connectionFile(root, apiUrl), \"utf8\"))\n );\n return connection.apiUrl === apiUrl ? connection : null;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nexport async function saveConnection(\n root: string,\n connection: StoredConnection\n): Promise<void> {\n await mkdir(connectionsDirectory(), { mode: 0o700, recursive: true });\n const file = connectionFile(root, connection.apiUrl);\n const temporaryFile = `${file}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporaryFile, `${JSON.stringify(connection)}\\n`, {\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(temporaryFile, file);\n } finally {\n await rm(temporaryFile, { force: true });\n }\n}\n\nexport async function removeConnection(\n root: string,\n apiUrl: string,\n rejectedToken?: string\n): Promise<StoredConnection | null> {\n const removed = await readConnection(root, apiUrl);\n if (!removed || (rejectedToken && removed.token !== rejectedToken)) {\n return null;\n }\n await rm(connectionFile(root, apiUrl), { force: true });\n return removed;\n}\n","import type { BoardAccess } from \"../../protocol\";\nimport type { ResolvedDevtoolsOptions } from \"../options\";\nimport { isConnectableHost } from \"./connectable-host\";\nimport { readConnection } from \"./connection-store\";\n\nexport interface BoardCredential {\n isStored: boolean;\n token: string;\n}\n\nexport async function boardCredential(\n settings: ResolvedDevtoolsOptions\n): Promise<BoardCredential | null> {\n if (settings.secretKey) {\n return { isStored: false, token: settings.secretKey };\n }\n const connection = await readConnection(settings.root, settings.apiUrl);\n return connection ? { isStored: true, token: connection.token } : null;\n}\n\nexport async function boardAccess(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<BoardAccess> {\n if (settings.secretKey) {\n return { kind: \"secretKey\" };\n }\n const connection = await readConnection(settings.root, settings.apiUrl);\n if (connection) {\n return { kind: \"connected\", organizationName: connection.organizationName };\n }\n return {\n canConnect: isConnectableHost(new URL(request.url).hostname),\n kind: \"disconnected\",\n };\n}\n","const HTML_ESCAPES: Record<string, string> = {\n \"'\": \"&#39;\",\n '\"': \"&quot;\",\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n};\nconst HTML_SPECIAL_CHARACTERS = /[&<>\"']/g;\n\nconst escapeHtml = (text: string): string =>\n text.replace(\n HTML_SPECIAL_CHARACTERS,\n (character) => HTML_ESCAPES[character] ?? character\n );\n\nexport function htmlPage(\n title: string,\n message: string,\n status: number\n): Response {\n const safeTitle = escapeHtml(title);\n const body = `<!doctype html>\n<html lang=\"en\">\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>${safeTitle} · Reflet devtools</title></head>\n<body style=\"margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;font-family:system-ui,sans-serif;background:#fafafa;color:#18181b\">\n<main style=\"max-width:28rem;padding:1.5rem\">\n<h1 style=\"font-size:1.25rem;margin:0 0 .5rem\">${safeTitle}</h1>\n<p style=\"margin:0;line-height:1.5;color:#52525b\">${escapeHtml(message)}</p>\n</main>\n</body>\n</html>\n`;\n return new Response(body, {\n headers: {\n \"cache-control\": \"no-store\",\n \"content-security-policy\":\n \"default-src 'none'; style-src 'unsafe-inline'\",\n \"content-type\": \"text/html; charset=utf-8\",\n \"referrer-policy\": \"no-referrer\",\n \"x-content-type-options\": \"nosniff\",\n },\n status,\n });\n}\n","import { createHash, randomBytes } from \"node:crypto\";\n\ninterface ConnectBinding {\n apiUrl: string;\n redirectUri: string;\n root: string;\n}\n\ninterface PendingConnect {\n binding: ConnectBinding;\n codeVerifier: string;\n startedAt: number;\n}\n\nconst PENDING_CONNECT_TTL_MS = 10 * 60_000;\nconst MAX_PENDING_CONNECTS = 10;\ndeclare global {\n // Preserve pending connects across dev server module reloads.\n var refletDevtoolsPendingConnects: Map<string, PendingConnect> | undefined;\n}\n\nfunction pendingConnects(): Map<string, PendingConnect> {\n globalThis.refletDevtoolsPendingConnects ??= new Map();\n return globalThis.refletDevtoolsPendingConnects;\n}\n\nexport function beginConnect(binding: ConnectBinding): {\n codeChallenge: string;\n codeVerifier: string;\n state: string;\n} {\n const state = randomBytes(32).toString(\"base64url\");\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n const codeChallenge = createHash(\"sha256\")\n .update(codeVerifier)\n .digest(\"base64url\");\n\n const pending = pendingConnects();\n while (pending.size >= MAX_PENDING_CONNECTS) {\n const oldestState = pending.keys().next().value;\n if (oldestState === undefined) {\n break;\n }\n pending.delete(oldestState);\n }\n pending.set(state, { binding, codeVerifier, startedAt: Date.now() });\n\n return { codeChallenge, codeVerifier, state };\n}\n\nexport function takeConnect(\n state: string,\n binding: ConnectBinding\n): { codeVerifier: string } | null {\n const pending = pendingConnects();\n const connect = pending.get(state);\n if (!connect) {\n return null;\n }\n if (Date.now() - connect.startedAt > PENDING_CONNECT_TTL_MS) {\n pending.delete(state);\n return null;\n }\n const matchesServer =\n connect.binding.root === binding.root &&\n connect.binding.apiUrl === binding.apiUrl &&\n connect.binding.redirectUri === binding.redirectUri;\n if (!matchesServer) {\n return null;\n }\n pending.delete(state);\n return { codeVerifier: connect.codeVerifier };\n}\n","import { z } from \"zod\";\nimport {\n type ConnectStartResponse,\n DEVTOOLS_ENDPOINTS,\n DEVTOOLS_ROUTE_BASE,\n type DisconnectResponse,\n} from \"../../protocol\";\nimport { errorResponse, jsonResponse } from \"../json-response\";\nimport type { ResolvedDevtoolsOptions } from \"../options\";\nimport { isConnectableHost } from \"./connectable-host\";\nimport { removeConnection, saveConnection } from \"./connection-store\";\nimport { htmlPage } from \"./html-page\";\nimport { beginConnect, takeConnect } from \"./pending-connects\";\n\nconst publicKeySchema = z.object({\n publicKey: z.string().startsWith(\"fb_pub_\").max(200),\n});\nconst tokenExchangeSchema = z.object({\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_dev_\"),\n});\nconst upstreamErrorSchema = z.object({ error: z.string() });\n\nconst redirectUriFor = (request: Request): string =>\n `${new URL(request.url).origin}${DEVTOOLS_ROUTE_BASE}${DEVTOOLS_ENDPOINTS.connectCallback}`;\n\nasync function readPublicKey(request: Request): Promise<string | null> {\n const parsed = publicKeySchema.safeParse(\n await request.json().catch(() => null)\n );\n return parsed.success ? parsed.data.publicKey : null;\n}\n\nasync function readJson(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nexport async function startConnect(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const publicKey = await readPublicKey(request);\n if (!publicKey) {\n return errorResponse(\n \"Pass the widget's fb_pub_ public key to connect.\",\n 400\n );\n }\n if (settings.secretKey) {\n return errorResponse(\n \"REFLET_SECRET_KEY is set, so this dev server already reaches your board.\",\n 409\n );\n }\n if (!isConnectableHost(new URL(request.url).hostname)) {\n return errorResponse(\n \"Connecting from the browser works on localhost, *.localhost and *.test. Set REFLET_SECRET_KEY instead.\",\n 403\n );\n }\n\n const { codeChallenge, state } = beginConnect({\n apiUrl: settings.apiUrl,\n redirectUri: redirectUriFor(request),\n root: settings.root,\n });\n const authorizeUrl = new URL(\"/auth/devtools\", settings.appUrl);\n authorizeUrl.searchParams.set(\"public_key\", publicKey);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUriFor(request));\n authorizeUrl.searchParams.set(\"state\", state);\n authorizeUrl.searchParams.set(\"code_challenge\", codeChallenge);\n return jsonResponse({\n authorizeUrl: authorizeUrl.toString(),\n } satisfies ConnectStartResponse);\n}\n\nexport async function finishConnect(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const { searchParams } = new URL(request.url);\n const code = searchParams.get(\"code\");\n const state = searchParams.get(\"state\");\n const pending =\n code && state\n ? takeConnect(state, {\n apiUrl: settings.apiUrl,\n redirectUri: redirectUriFor(request),\n root: settings.root,\n })\n : null;\n if (!(code && pending)) {\n return htmlPage(\n \"Link expired\",\n \"This connect link expired or was already used. Start again from the Board tab.\",\n 400\n );\n }\n\n let upstream: Response;\n try {\n upstream = await fetch(`${settings.apiUrl}/api/v1/devtools/token`, {\n body: JSON.stringify({\n code,\n codeVerifier: pending.codeVerifier,\n redirectUri: redirectUriFor(request),\n }),\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal: AbortSignal.timeout(10_000),\n });\n } catch {\n return htmlPage(\n \"Connection failed\",\n `Could not reach Reflet at ${settings.apiUrl}.`,\n 502\n );\n }\n\n const payload = await readJson(upstream);\n if (!upstream.ok) {\n return htmlPage(\n \"Connection refused\",\n upstreamErrorSchema.safeParse(payload).data?.error ??\n \"Reflet refused this connect code.\",\n 400\n );\n }\n const exchange = tokenExchangeSchema.safeParse(payload);\n if (!exchange.success) {\n return htmlPage(\n \"Connection failed\",\n \"Reflet answered with an unexpected response.\",\n 502\n );\n }\n\n await saveConnection(settings.root, {\n apiUrl: settings.apiUrl,\n organizationName: exchange.data.organizationName,\n token: exchange.data.token,\n });\n return htmlPage(\n \"Connected\",\n `Connected to ${exchange.data.organizationName}. Go back to your app: the Board tab is ready.`,\n 200\n );\n}\n\nasync function revokeUpstream(apiUrl: string, token: string): Promise<boolean> {\n try {\n const response = await fetch(`${apiUrl}/api/v1/devtools/revoke`, {\n headers: { Authorization: `Bearer ${token}` },\n method: \"POST\",\n signal: AbortSignal.timeout(10_000),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function disconnect(\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const removed = await removeConnection(settings.root, settings.apiUrl);\n const revoked = removed\n ? await revokeUpstream(removed.apiUrl, removed.token)\n : false;\n return jsonResponse({ revoked } satisfies DisconnectResponse);\n}\n","import { resolve } from \"node:path\";\nimport { DEFAULT_API_URL } from \"../../client\";\nimport { EDITORS, type EditorId } from \"../protocol\";\n\nexport interface DevtoolsServerOptions {\n /** Dev hostnames besides localhost, e.g. `app.test`. Falls back to REFLET_DEVTOOLS_HOSTS, comma-separated. */\n allowedHosts?: string[];\n /** Reflet API origin. Falls back to REFLET_API_URL, then the hosted API. */\n apiUrl?: string;\n /** Reflet web app origin for Connect. Falls back to REFLET_APP_URL, then https://www.reflet.app. */\n appUrl?: string;\n /** Editor that \"open in editor\" links target. Falls back to REFLET_EDITOR. */\n editor?: EditorId;\n /** App directory source paths resolve against. Defaults to the working directory. */\n root?: string;\n /** Falls back to REFLET_SECRET_KEY. Never sent to the browser. */\n secretKey?: string;\n}\n\nexport type DevtoolsEnv = Readonly<Record<string, string | undefined>>;\n\nexport interface ResolvedDevtoolsOptions {\n allowedHosts: string[];\n apiUrl: string;\n appUrl: string;\n editor: EditorId;\n root: string;\n secretKey: string | null;\n}\n\nconst DEFAULT_APP_URL = \"https://www.reflet.app\";\nconst DEFAULT_EDITOR: EditorId = \"vscode\";\nconst TRAILING_SLASHES = /\\/+$/;\n\nfunction isEditorId(value: string | undefined): value is EditorId {\n return EDITORS.some((editor) => editor === value);\n}\n\nfunction presentValue(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction resolveEditor(\n optionEditor: string | undefined,\n envEditor: string | undefined\n): EditorId {\n if (isEditorId(optionEditor)) {\n return optionEditor;\n }\n const normalizedEnvEditor = presentValue(envEditor)?.toLowerCase();\n return isEditorId(normalizedEnvEditor) ? normalizedEnvEditor : DEFAULT_EDITOR;\n}\n\nexport function resolveDevtoolsOptions(\n options: DevtoolsServerOptions,\n env: DevtoolsEnv\n): ResolvedDevtoolsOptions {\n const apiUrl =\n presentValue(options.apiUrl) ??\n presentValue(env.REFLET_API_URL) ??\n DEFAULT_API_URL;\n const appUrl =\n presentValue(options.appUrl) ??\n presentValue(env.REFLET_APP_URL) ??\n DEFAULT_APP_URL;\n\n return {\n allowedHosts: (\n options.allowedHosts ??\n presentValue(env.REFLET_DEVTOOLS_HOSTS)?.split(\",\") ??\n []\n )\n .map((host) => host.trim().toLowerCase())\n .filter(Boolean),\n apiUrl: apiUrl.replace(TRAILING_SLASHES, \"\"),\n appUrl: appUrl.replace(TRAILING_SLASHES, \"\"),\n editor: resolveEditor(options.editor, env.REFLET_EDITOR),\n root: resolve(presentValue(options.root) ?? process.cwd()),\n secretKey:\n presentValue(options.secretKey) ??\n presentValue(env.REFLET_SECRET_KEY) ??\n null,\n };\n}\n","import { PROXIED_API_PATHS } from \"../protocol\";\nimport { errorResponse, JSON_RESPONSE_HEADERS } from \"./json-response\";\n\ntype ProxiedApiPath = (typeof PROXIED_API_PATHS)[number];\n\nconst CREATE_FEEDBACK_PATH: ProxiedApiPath = \"/api/v1/feedback/create\";\nconst MISSING_BOARD_ACCESS_ERROR =\n \"Connect to Reflet from the devtools Board tab, or set REFLET_SECRET_KEY in the dev server environment.\";\nconst BODYLESS_STATUSES = [204, 205, 304];\n\nexport interface RefletProxyTarget {\n apiUrl: string;\n token: string | null;\n}\n\ntype ForwardedBody = { body: string | undefined } | { error: string };\n\nfunction isProxiedApiPath(path: string): path is ProxiedApiPath {\n return PROXIED_API_PATHS.some((proxiedPath) => proxiedPath === path);\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function readForwardedBody(\n request: Request,\n apiPath: ProxiedApiPath\n): Promise<ForwardedBody> {\n if (request.method !== \"POST\") {\n return { body: undefined };\n }\n const text = await request.text();\n if (apiPath !== CREATE_FEEDBACK_PATH) {\n return { body: text || undefined };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(text);\n } catch {\n return { error: \"Feedback must be a JSON object.\" };\n }\n if (!isJsonObject(payload)) {\n return { error: \"Feedback must be a JSON object.\" };\n }\n return { body: JSON.stringify({ ...payload, internal: true }) };\n}\n\n/** Forwards an allowlisted Reflet API call with the board token; devtools notes are always internal. */\nexport async function proxyToReflet(\n request: Request,\n apiPath: string,\n target: RefletProxyTarget\n): Promise<Response> {\n if (!isProxiedApiPath(apiPath)) {\n return errorResponse(\n `Reflet devtools does not forward ${apiPath || \"/\"}.`,\n 404\n );\n }\n if (!target.token) {\n return errorResponse(MISSING_BOARD_ACCESS_ERROR, 503);\n }\n if (request.method !== \"GET\" && request.method !== \"POST\") {\n return errorResponse(`${request.method} is not supported here.`, 405);\n }\n\n const forwarded = await readForwardedBody(request, apiPath);\n if (\"error\" in forwarded) {\n return errorResponse(forwarded.error, 400);\n }\n\n const { search } = new URL(request.url);\n let upstream: Response;\n try {\n upstream = await fetch(`${target.apiUrl}${apiPath}${search}`, {\n body: forwarded.body,\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${target.token}`,\n \"Content-Type\": \"application/json\",\n },\n method: request.method,\n signal: AbortSignal.timeout(15_000),\n });\n } catch {\n return errorResponse(`Could not reach Reflet at ${target.apiUrl}.`, 502);\n }\n\n return new Response(\n BODYLESS_STATUSES.includes(upstream.status) ? null : upstream.body,\n { headers: JSON_RESPONSE_HEADERS, status: upstream.status }\n );\n}\n","import { type ExecFileException, execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport type { CodeMatch, CodeSearchResult } from \"../../protocol\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\n\nconst MIN_QUERY_LENGTH = 2;\nconst MAX_QUERY_LENGTH = 200;\nconst MAX_MATCHES = 20;\nconst PREVIEW_LENGTH = 160;\nconst PREVIEW_LEAD = 40;\nconst SEARCH_TIMEOUT_MS = 4000;\nconst MAX_OUTPUT_BYTES = 1_048_576;\nconst NO_MATCHES_EXIT_CODE = 1;\nconst NOT_A_REPOSITORY_EXIT_CODE = 128;\nconst SEARCHED_FILES = [\n \"*.tsx\",\n \"*.jsx\",\n \"*.ts\",\n \"*.js\",\n \"*.vue\",\n \"*.svelte\",\n \"*.astro\",\n \"*.mdx\",\n];\nconst LINE_BREAK = /[\\r\\n]/;\n\ninterface GitGrepRun {\n error: ExecFileException | null;\n stdout: string;\n}\n\nfunction runGitGrep(workspaceRoot: string, query: string): Promise<GitGrepRun> {\n const args = [\n \"grep\",\n \"-n\",\n \"-z\",\n \"-I\",\n \"-F\",\n \"--no-color\",\n \"--untracked\",\n \"-e\",\n query,\n \"--\",\n ...SEARCHED_FILES,\n ];\n return new Promise((resolveRun) => {\n execFile(\n \"git\",\n args,\n {\n cwd: workspaceRoot,\n encoding: \"utf8\",\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: SEARCH_TIMEOUT_MS,\n },\n (error, stdout) => resolveRun({ error, stdout })\n );\n });\n}\n\nfunction previewLine(content: string, query: string): string {\n const text = content.trim();\n if (text.length <= PREVIEW_LENGTH) {\n return text;\n }\n const matchIndex = text.indexOf(query);\n const start = Math.max(\n 0,\n Math.min(matchIndex - PREVIEW_LEAD, text.length - PREVIEW_LENGTH)\n );\n const end = start + PREVIEW_LENGTH;\n const head = start > 0 ? \"…\" : \"\";\n const tail = end < text.length ? \"…\" : \"\";\n return `${head}${text.slice(start, end)}${tail}`;\n}\n\nfunction parseMatches(\n stdout: string,\n workspaceRoot: string,\n query: string\n): CodeMatch[] {\n const matches: CodeMatch[] = [];\n for (const record of stdout.split(\"\\n\")) {\n const [path, lineText, content] = record.split(\"\\0\");\n const line = Number(lineText);\n const isComplete =\n path !== undefined && content !== undefined && Number.isInteger(line);\n if (isComplete && !path.split(\"/\").includes(\"node_modules\")) {\n matches.push({\n absolutePath: join(workspaceRoot, path),\n line,\n path,\n preview: previewLine(content, query),\n });\n if (matches.length === MAX_MATCHES) {\n break;\n }\n }\n }\n return matches;\n}\n\nfunction describeGitFailure(error: ExecFileException): DevtoolsOutcome<never> {\n if (error.code === \"ENOENT\") {\n return failure(\"Code search needs git installed on the dev server.\", 503);\n }\n if (error.code === NOT_A_REPOSITORY_EXIT_CODE) {\n return failure(\n \"Code search needs the app to live in a git repository.\",\n 503\n );\n }\n if (error.killed) {\n return failure(\"Code search timed out.\", 504);\n }\n return failure(`Code search failed: ${error.message}`, 500);\n}\n\nexport async function searchCode(\n workspaceRoot: string,\n rawQuery: string\n): Promise<DevtoolsOutcome<CodeSearchResult>> {\n const query = rawQuery.trim();\n if (query.length < MIN_QUERY_LENGTH || query.length > MAX_QUERY_LENGTH) {\n return failure(\n `Search for ${MIN_QUERY_LENGTH} to ${MAX_QUERY_LENGTH} characters.`,\n 400\n );\n }\n if (LINE_BREAK.test(query)) {\n return failure(\"Search for a single line of text.\", 400);\n }\n\n const { error, stdout } = await runGitGrep(workspaceRoot, query);\n const matches = parseMatches(stdout, workspaceRoot, query);\n const hasNoMatches = error?.code === NO_MATCHES_EXIT_CODE;\n if (!error || hasNoMatches || matches.length > 0) {\n return { ok: true, value: { matches } };\n }\n return describeGitFailure(error);\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ProjectRoots {\n /** The app directory, where the dev server runs. */\n root: string;\n /** Nearest ancestor of the app directory holding `.git`, else the app directory. */\n workspaceRoot: string;\n}\n\nexport function resolveProjectRoots(appRoot: string): ProjectRoots {\n const resolvedRoot = resolve(appRoot);\n const root = existsSync(resolvedRoot)\n ? realpathSync(resolvedRoot)\n : resolvedRoot;\n\n for (let directory = root; ; directory = dirname(directory)) {\n if (existsSync(join(directory, \".git\"))) {\n return { root, workspaceRoot: directory };\n }\n if (dirname(directory) === directory) {\n return { root, workspaceRoot: root };\n }\n }\n}\n","import type { LineRange } from \"../../protocol\";\n\nconst FAILED = -1;\nconst MAX_TAG_LOOKBACK = 2;\nconst TAG_NAME_START = /[A-Za-z_$]/;\nconst TAG_NAME_CHAR = /[\\w$.:-]/;\nconst IDENTIFIER_CHAR = /[\\w$]/;\nconst WHITESPACE = /\\s/;\nconst JSX_EXPRESSION_LEAD = /[([{,;=?:&|!>]/;\nconst JSX_KEYWORD_LEADS = [\"return\", \"yield\", \"default\", \"await\"];\n\ninterface OpeningTag {\n end: number;\n name: string;\n selfClosing: boolean;\n}\n\nfunction isTagStart(code: string, index: number): boolean {\n if (code.charAt(index) !== \"<\") {\n return false;\n }\n const next = code.charAt(index + 1);\n return next === \">\" || TAG_NAME_START.test(next);\n}\n\nfunction startsJsxInExpression(code: string, index: number): boolean {\n let cursor = index - 1;\n while (cursor >= 0 && WHITESPACE.test(code.charAt(cursor))) {\n cursor -= 1;\n }\n if (cursor < 0) {\n return true;\n }\n const previous = code.charAt(cursor);\n if (JSX_EXPRESSION_LEAD.test(previous)) {\n return true;\n }\n let wordStart = cursor;\n while (wordStart > 0 && IDENTIFIER_CHAR.test(code.charAt(wordStart - 1))) {\n wordStart -= 1;\n }\n return JSX_KEYWORD_LEADS.includes(code.slice(wordStart, cursor + 1));\n}\n\nfunction skipJsString(code: string, index: number): number {\n const quote = code.charAt(index);\n let cursor = index + 1;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"\\\\\") {\n cursor += 2;\n } else if (char === quote) {\n return cursor + 1;\n } else if (char === \"\\n\") {\n return index + 1;\n } else {\n cursor += 1;\n }\n }\n return index + 1;\n}\n\nfunction skipTemplate(code: string, index: number): number {\n let cursor = index + 1;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"\\\\\") {\n cursor += 2;\n } else if (char === \"`\") {\n return cursor + 1;\n } else if (char === \"$\" && code.charAt(cursor + 1) === \"{\") {\n cursor = skipJsExpression(code, cursor + 1);\n if (cursor === FAILED) {\n return FAILED;\n }\n } else {\n cursor += 1;\n }\n }\n return FAILED;\n}\n\nfunction skipJsToken(code: string, index: number): number {\n const char = code.charAt(index);\n const next = code.charAt(index + 1);\n if (char === '\"' || char === \"'\") {\n return skipJsString(code, index);\n }\n if (char === \"`\") {\n return skipTemplate(code, index);\n }\n if (char === \"/\" && next === \"/\") {\n const lineEnd = code.indexOf(\"\\n\", index);\n return lineEnd === -1 ? code.length : lineEnd;\n }\n if (char === \"/\" && next === \"*\") {\n const commentEnd = code.indexOf(\"*/\", index + 2);\n return commentEnd === -1 ? FAILED : commentEnd + 2;\n }\n if (isTagStart(code, index) && startsJsxInExpression(code, index)) {\n return skipElement(code, index);\n }\n return index + 1;\n}\n\nfunction skipJsExpression(code: string, index: number): number {\n let depth = 0;\n let cursor = index;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"{\" || char === \"}\") {\n depth += char === \"{\" ? 1 : -1;\n cursor += 1;\n if (depth === 0) {\n return cursor;\n }\n } else {\n cursor = skipJsToken(code, cursor);\n if (cursor === FAILED) {\n return FAILED;\n }\n }\n }\n return FAILED;\n}\n\nfunction skipTypeArguments(code: string, index: number): number {\n let depth = 0;\n for (let cursor = index; cursor < code.length; cursor += 1) {\n const char = code.charAt(cursor);\n if (char === \"<\") {\n depth += 1;\n } else if (char === \">\") {\n depth -= 1;\n if (depth === 0) {\n return cursor + 1;\n }\n }\n }\n return FAILED;\n}\n\nfunction skipAttributeToken(code: string, index: number): number {\n const char = code.charAt(index);\n if (char === \"{\") {\n return skipJsExpression(code, index);\n }\n if (char === '\"' || char === \"'\") {\n const closingQuote = code.indexOf(char, index + 1);\n return closingQuote === -1 ? FAILED : closingQuote + 1;\n }\n return index + 1;\n}\n\nfunction readTagName(code: string, index: number): number {\n let cursor = index;\n while (TAG_NAME_CHAR.test(code.charAt(cursor))) {\n cursor += 1;\n }\n return cursor;\n}\n\nfunction readOpeningTag(code: string, index: number): OpeningTag | null {\n const nameEnd = readTagName(code, index + 1);\n const name = code.slice(index + 1, nameEnd);\n let cursor =\n code.charAt(nameEnd) === \"<\" ? skipTypeArguments(code, nameEnd) : nameEnd;\n\n while (cursor !== FAILED && cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \">\") {\n return { end: cursor + 1, name, selfClosing: false };\n }\n if (char === \"/\" && code.charAt(cursor + 1) === \">\") {\n return { end: cursor + 2, name, selfClosing: true };\n }\n cursor = skipAttributeToken(code, cursor);\n }\n return null;\n}\n\nfunction readClosingTagEnd(code: string, index: number, name: string): number {\n let cursor = index + 2;\n while (WHITESPACE.test(code.charAt(cursor))) {\n cursor += 1;\n }\n const nameEnd = readTagName(code, cursor);\n if (code.slice(cursor, nameEnd) !== name) {\n return FAILED;\n }\n cursor = nameEnd;\n while (WHITESPACE.test(code.charAt(cursor))) {\n cursor += 1;\n }\n return code.charAt(cursor) === \">\" ? cursor + 1 : FAILED;\n}\n\nfunction skipChildren(code: string, index: number, name: string): number {\n let cursor = index;\n while (cursor !== FAILED && cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"<\" && code.charAt(cursor + 1) === \"/\") {\n return readClosingTagEnd(code, cursor, name);\n }\n if (char === \"{\") {\n cursor = skipJsExpression(code, cursor);\n } else if (isTagStart(code, cursor)) {\n cursor = skipElement(code, cursor);\n } else {\n cursor += 1;\n }\n }\n return FAILED;\n}\n\nfunction skipElement(code: string, index: number): number {\n const tag = readOpeningTag(code, index);\n if (!tag) {\n return FAILED;\n }\n return tag.selfClosing ? tag.end : skipChildren(code, tag.end, tag.name);\n}\n\nfunction lineOffset(code: string, line: number): number {\n if (!Number.isInteger(line) || line < 1) {\n return FAILED;\n }\n let offset = 0;\n for (let current = 1; current < line; current += 1) {\n const newline = code.indexOf(\"\\n\", offset);\n if (newline === -1) {\n return FAILED;\n }\n offset = newline + 1;\n }\n return offset;\n}\n\nfunction findTagStart(\n code: string,\n lineStart: number,\n lineEnd: number,\n column: number\n): number {\n const origin = Math.min(lineStart + Math.max(column, 0), lineEnd);\n for (let back = 0; back <= MAX_TAG_LOOKBACK; back += 1) {\n const candidate = origin - back;\n if (candidate >= lineStart && isTagStart(code, candidate)) {\n return candidate;\n }\n }\n for (let candidate = origin + 1; candidate < lineEnd; candidate += 1) {\n if (isTagStart(code, candidate)) {\n return candidate;\n }\n }\n return FAILED;\n}\n\nfunction countNewlines(code: string, from: number, to: number): number {\n let count = 0;\n let newline = code.indexOf(\"\\n\", from);\n while (newline !== -1 && newline < to) {\n count += 1;\n newline = code.indexOf(\"\\n\", newline + 1);\n }\n return count;\n}\n\n/** Lines spanned by the JSX element at a 1-based line and 0-based column. */\nexport function jsxElementLines(\n code: string,\n line: number,\n column: number\n): LineRange | null {\n const lineStart = lineOffset(code, line);\n if (lineStart === FAILED) {\n return null;\n }\n const newline = code.indexOf(\"\\n\", lineStart);\n const lineEnd = newline === -1 ? code.length : newline;\n const tagStart = findTagStart(code, lineStart, lineEnd, column);\n if (tagStart === FAILED) {\n return null;\n }\n const elementEnd = skipElement(code, tagStart);\n if (elementEnd === FAILED) {\n return null;\n }\n return {\n end: line + countNewlines(code, tagStart, elementEnd - 1),\n start: line,\n };\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { SourceMap } from \"node:module\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\nimport type { SourceRequest } from \"./source-file\";\n\nconst SERVER_FRAME_PREFIX = /^(?:about|rsc):\\/\\/React\\/Server\\//;\nconst QUERY_OR_HASH = /[?#].*$/;\nconst SOURCE_MAPPING_URL = /\\/\\/# sourceMappingURL=(\\S+)\\s*$/;\nconst MAX_MAP_BYTES = 50 * 1_048_576;\n\nconst mapCache = new Map<string, { map: SourceMap; mtimeMs: number }>();\n\nexport function isServerFrame(fileName: string): boolean {\n return SERVER_FRAME_PREFIX.test(fileName);\n}\n\nfunction isInside(path: string, root: string): boolean {\n const fromRoot = relative(root, path);\n return (\n fromRoot !== \"\" &&\n !fromRoot.startsWith(\"..\") &&\n !fromRoot.includes(`..${sep}`)\n );\n}\n\nasync function mapPathFor(chunkPath: string): Promise<string> {\n const code = await readFile(chunkPath, \"utf8\");\n const declared = SOURCE_MAPPING_URL.exec(code)?.[1];\n return declared\n ? join(dirname(chunkPath), decodeURIComponent(declared))\n : `${chunkPath}.map`;\n}\n\nasync function loadMap(mapPath: string): Promise<SourceMap> {\n const { mtimeMs, size } = await stat(mapPath);\n if (size > MAX_MAP_BYTES) {\n throw new Error(\"source map too large\");\n }\n const cached = mapCache.get(mapPath);\n if (cached?.mtimeMs === mtimeMs) {\n return cached.map;\n }\n const map = new SourceMap(JSON.parse(await readFile(mapPath, \"utf8\")));\n mapCache.set(mapPath, { map, mtimeMs });\n return map;\n}\n\n/**\n * Server Components stamp their elements with frames into the dev server's\n * own chunks (`about://React/Server/file:///…/.next/…`); the browser cannot\n * fetch those maps, so they are resolved here from disk.\n */\nexport async function mapServerFrame(\n request: SourceRequest,\n workspaceRoot: string\n): Promise<DevtoolsOutcome<SourceRequest>> {\n const unreadable = failure<SourceRequest>(\n \"This element comes from a Server Component whose source map could not be read.\",\n 404\n );\n if (request.line === null) {\n return unreadable;\n }\n try {\n const chunkUrl = request.fileName\n .replace(SERVER_FRAME_PREFIX, \"\")\n .replace(QUERY_OR_HASH, \"\");\n const chunkPath = await realpath(fileURLToPath(chunkUrl));\n if (!isInside(chunkPath, workspaceRoot)) {\n return failure<SourceRequest>(\n \"Reflet devtools only reads files inside your repository.\",\n 403\n );\n }\n const map = await loadMap(await mapPathFor(chunkPath));\n const origin = map.findOrigin(request.line, (request.column ?? 0) + 1);\n if (!(\"fileName\" in origin)) {\n return unreadable;\n }\n return {\n ok: true,\n value: {\n column: origin.columnNumber - 1,\n fileName: origin.fileName,\n line: origin.lineNumber,\n },\n };\n } catch {\n return unreadable;\n }\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { extname, isAbsolute, join, relative, sep } from \"node:path\";\nimport type { SourceFile } from \"../../protocol\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\nimport { jsxElementLines } from \"./jsx-range\";\nimport type { ProjectRoots } from \"./project-roots\";\nimport { isServerFrame, mapServerFrame } from \"./server-frame\";\n\nconst MAX_SOURCE_BYTES = 1_048_576;\nconst MAX_FILE_NAME_LENGTH = 2048;\nconst MAX_NORMALIZE_PASSES = 8;\nconst SOURCE_EXTENSIONS = [\n \".astro\",\n \".cjs\",\n \".js\",\n \".jsx\",\n \".mdx\",\n \".mjs\",\n \".svelte\",\n \".ts\",\n \".tsx\",\n \".vue\",\n];\nconst EXTENSION_REFUSAL = `Reflet devtools only reads source files (${SOURCE_EXTENSIONS.join(\", \")}).`;\nconst OUTSIDE_WORKSPACE_REFUSAL =\n \"Reflet devtools only reads files inside your repository.\";\nconst NODE_MODULES_REFUSAL =\n \"Reflet devtools does not read files inside node_modules.\";\nconst QUERY_OR_HASH = /[?#].*$/;\nconst TURBOPACK_MODULE_SUFFIX = /(?: \\[[\\w-]+\\])+(?: \\([\\w-]+\\))*$/;\nconst URL_PREFIXES = [/^file:\\/\\//, /^https?:\\/\\/[^/]*/];\nconst BUNDLER_PREFIXES = [\n /^rsc:\\/\\/React\\/[^/]+\\//,\n /^webpack-internal:\\/{2,}/,\n /^webpack:\\/\\/[^/]*\\//,\n /^turbopack:\\/{2,}/,\n /^\\[project\\]\\//,\n /^\\(app-pages-browser\\)\\//,\n /^\\([\\w-]+\\)\\/(?=\\.\\/)/,\n /^\\/@fs(?=\\/)/,\n /^\\.\\//,\n];\n\ninterface LocatedFile {\n realPath: string;\n relativePath: string;\n size: number;\n}\n\ntype CandidateCheck =\n | ({ kind: \"found\" } & LocatedFile)\n | { kind: \"missing\" }\n | { kind: \"refused\"; reason: string };\n\nexport interface SourceRequest {\n column: number | null;\n fileName: string;\n line: number | null;\n}\n\nfunction decodePath(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\nfunction stripFirstPrefix(fileName: string, prefixes: RegExp[]): string {\n for (const prefix of prefixes) {\n if (prefix.test(fileName)) {\n return fileName.replace(prefix, \"\");\n }\n }\n return fileName;\n}\n\n/** Turns a file name from a React debug stack into a filesystem path. */\nexport function normalizeSourceFileName(rawFileName: string): string {\n let fileName = rawFileName\n .trim()\n .replace(QUERY_OR_HASH, \"\")\n .replace(TURBOPACK_MODULE_SUFFIX, \"\");\n let isUrlEncoded = false;\n\n for (let pass = 0; pass < MAX_NORMALIZE_PASSES; pass += 1) {\n const withoutUrl = stripFirstPrefix(fileName, URL_PREFIXES);\n isUrlEncoded ||= withoutUrl !== fileName;\n const stripped = stripFirstPrefix(withoutUrl, BUNDLER_PREFIXES);\n if (stripped === fileName) {\n break;\n }\n fileName = stripped;\n }\n\n return isUrlEncoded ? decodePath(fileName) : fileName;\n}\n\nfunction candidatePaths(fileName: string, roots: ProjectRoots): string[] {\n const candidates = [\n join(roots.root, fileName),\n join(roots.workspaceRoot, fileName),\n ];\n if (isAbsolute(fileName)) {\n candidates.unshift(fileName);\n }\n return [...new Set(candidates)];\n}\n\nfunction isSourceExtension(path: string): boolean {\n return SOURCE_EXTENSIONS.includes(extname(path).toLowerCase());\n}\n\nfunction workspaceRelativePath(\n realPath: string,\n workspaceRoot: string\n): string | null {\n const relativePath = relative(workspaceRoot, realPath);\n const escapes =\n relativePath === \"\" ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath);\n return escapes ? null : relativePath.split(sep).join(\"/\");\n}\n\nasync function checkCandidate(\n candidate: string,\n workspaceRoot: string\n): Promise<CandidateCheck> {\n let realPath: string;\n let size: number;\n try {\n realPath = await realpath(candidate);\n const stats = await stat(realPath);\n if (!stats.isFile()) {\n return { kind: \"missing\" };\n }\n size = stats.size;\n } catch {\n return { kind: \"missing\" };\n }\n\n const relativePath = workspaceRelativePath(realPath, workspaceRoot);\n if (relativePath === null) {\n return { kind: \"refused\", reason: OUTSIDE_WORKSPACE_REFUSAL };\n }\n if (relativePath.split(\"/\").includes(\"node_modules\")) {\n return { kind: \"refused\", reason: NODE_MODULES_REFUSAL };\n }\n if (!isSourceExtension(realPath)) {\n return { kind: \"refused\", reason: EXTENSION_REFUSAL };\n }\n return { kind: \"found\", realPath, relativePath, size };\n}\n\nasync function locateSourceFile(\n fileName: string,\n roots: ProjectRoots\n): Promise<DevtoolsOutcome<LocatedFile>> {\n let refusal: string | null = null;\n for (const candidate of candidatePaths(fileName, roots)) {\n const check = await checkCandidate(candidate, roots.workspaceRoot);\n if (check.kind === \"found\") {\n return { ok: true, value: check };\n }\n if (check.kind === \"refused\") {\n refusal ??= check.reason;\n }\n }\n if (refusal) {\n return failure(refusal, 403);\n }\n return failure(`Could not find ${fileName} in ${roots.workspaceRoot}.`, 404);\n}\n\n/** Server-map columns can point past the line; the element then starts at its first tag. */\nfunction columnWithinLine(code: string, line: number, column: number | null) {\n const text = code.split(\"\\n\")[line - 1] ?? \"\";\n return column !== null && column < text.length ? column : null;\n}\n\nexport async function readSourceFile(\n frame: SourceRequest,\n roots: ProjectRoots\n): Promise<DevtoolsOutcome<SourceFile>> {\n if (\n frame.fileName.length > MAX_FILE_NAME_LENGTH ||\n frame.fileName.includes(\"\\0\")\n ) {\n return failure(\"That source file name is not a valid path.\", 400);\n }\n const mapped = isServerFrame(frame.fileName)\n ? await mapServerFrame(frame, roots.workspaceRoot)\n : { ok: true as const, value: frame };\n if (!mapped.ok) {\n return mapped;\n }\n const request = mapped.value;\n const fileName = normalizeSourceFileName(request.fileName);\n if (!fileName) {\n return failure(\"A source file name is required.\", 400);\n }\n if (!isSourceExtension(fileName)) {\n return failure(EXTENSION_REFUSAL, 403);\n }\n\n const located = await locateSourceFile(fileName, roots);\n if (!located.ok) {\n return located;\n }\n const { realPath, relativePath, size } = located.value;\n if (size > MAX_SOURCE_BYTES) {\n return failure(\n `${relativePath} is larger than 1 MB, too big to preview.`,\n 413\n );\n }\n\n const code = await readFile(realPath, \"utf8\");\n const column =\n request.line === null\n ? request.column\n : columnWithinLine(code, request.line, request.column);\n const elementLines =\n request.line === null\n ? null\n : jsxElementLines(code, request.line, column ?? 0);\n\n return {\n ok: true,\n value: {\n absolutePath: realPath,\n code,\n column,\n elementLines,\n line: request.line,\n path: relativePath,\n },\n };\n}\n","import {\n DEVTOOLS_ENDPOINTS,\n DEVTOOLS_ROUTE_BASE,\n DEVTOOLS_STATUS_MARKER,\n type DevtoolsStatus,\n} from \"../protocol\";\nimport { boardAccess, boardCredential } from \"./connect/board-credential\";\nimport {\n disconnect,\n finishConnect,\n startConnect,\n} from \"./connect/connect-routes\";\nimport { removeConnection } from \"./connect/connection-store\";\nimport {\n type DevtoolsOutcome,\n errorResponse,\n jsonResponse,\n} from \"./json-response\";\nimport {\n type DevtoolsEnv,\n type DevtoolsServerOptions,\n type ResolvedDevtoolsOptions,\n resolveDevtoolsOptions,\n} from \"./options\";\nimport { proxyToReflet } from \"./reflet-proxy\";\nimport { rejectUntrustedCaller, rejectUntrustedHost } from \"./request-guard\";\nimport { searchCode } from \"./source/code-search\";\nimport { type ProjectRoots, resolveProjectRoots } from \"./source/project-roots\";\nimport { readSourceFile } from \"./source/source-file\";\n\nexport type DevtoolsHandler = (request: Request) => Promise<Response>;\n\nconst TRAILING_SLASHES = /\\/+$/;\n\nconst ENDPOINT_METHODS: Record<string, \"GET\" | \"POST\"> = {\n [DEVTOOLS_ENDPOINTS.connectCallback]: \"GET\",\n [DEVTOOLS_ENDPOINTS.connectStart]: \"POST\",\n [DEVTOOLS_ENDPOINTS.disconnect]: \"POST\",\n [DEVTOOLS_ENDPOINTS.search]: \"GET\",\n [DEVTOOLS_ENDPOINTS.source]: \"GET\",\n [DEVTOOLS_ENDPOINTS.status]: \"GET\",\n};\n\nfunction outcomeResponse<T>(outcome: DevtoolsOutcome<T>): Response {\n return outcome.ok\n ? jsonResponse(outcome.value)\n : errorResponse(outcome.error, outcome.status);\n}\n\nfunction routeSubPath(pathname: string): string | null {\n const baseIndex = pathname.indexOf(DEVTOOLS_ROUTE_BASE);\n if (baseIndex === -1) {\n return null;\n }\n return pathname\n .slice(baseIndex + DEVTOOLS_ROUTE_BASE.length)\n .replace(TRAILING_SLASHES, \"\");\n}\n\nfunction readInteger(value: string | null, minimum: number): number | null {\n if (value === null || value === \"\") {\n return null;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) && parsed >= minimum ? parsed : null;\n}\n\nasync function proxyWithBoardCredential(\n request: Request,\n apiPath: string,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const credential = await boardCredential(settings);\n const response = await proxyToReflet(request, apiPath, {\n apiUrl: settings.apiUrl,\n token: credential?.token ?? null,\n });\n if (credential?.isStored && response.status === 401) {\n await removeConnection(settings.root, settings.apiUrl, credential.token);\n }\n return response;\n}\n\nasync function routeRequest(\n request: Request,\n subPath: string | null,\n settings: ResolvedDevtoolsOptions,\n projectRoots: () => ProjectRoots\n): Promise<Response> {\n const url = new URL(request.url);\n\n if (subPath?.startsWith(`${DEVTOOLS_ENDPOINTS.proxy}/`)) {\n const apiPath = subPath.slice(DEVTOOLS_ENDPOINTS.proxy.length);\n return await proxyWithBoardCredential(request, apiPath, settings);\n }\n\n const requiredMethod = subPath ? ENDPOINT_METHODS[subPath] : undefined;\n if (requiredMethod && request.method !== requiredMethod) {\n return errorResponse(\n `${subPath} only answers ${requiredMethod} requests.`,\n 405\n );\n }\n\n switch (subPath) {\n case DEVTOOLS_ENDPOINTS.status:\n return jsonResponse({\n board: await boardAccess(request, settings),\n editor: settings.editor,\n marker: DEVTOOLS_STATUS_MARKER,\n } satisfies DevtoolsStatus);\n case DEVTOOLS_ENDPOINTS.connectStart:\n return await startConnect(request, settings);\n case DEVTOOLS_ENDPOINTS.connectCallback:\n return await finishConnect(request, settings);\n case DEVTOOLS_ENDPOINTS.disconnect:\n return await disconnect(settings);\n case DEVTOOLS_ENDPOINTS.source:\n return outcomeResponse(\n await readSourceFile(\n {\n column: readInteger(url.searchParams.get(\"column\"), 0),\n fileName: url.searchParams.get(\"file\") ?? \"\",\n line: readInteger(url.searchParams.get(\"line\"), 1),\n },\n projectRoots()\n )\n );\n case DEVTOOLS_ENDPOINTS.search:\n return outcomeResponse(\n await searchCode(\n projectRoots().workspaceRoot,\n url.searchParams.get(\"q\") ?? \"\"\n )\n );\n default:\n return errorResponse(\n `No Reflet devtools endpoint at ${url.pathname}.`,\n 404\n );\n }\n}\n\nexport function createDevtoolsHandler(\n options: DevtoolsServerOptions = {},\n env: DevtoolsEnv = process.env\n): DevtoolsHandler {\n const settings = resolveDevtoolsOptions(options, env);\n let roots: ProjectRoots | null = null;\n const projectRoots = (): ProjectRoots => {\n roots ??= resolveProjectRoots(settings.root);\n return roots;\n };\n\n return async (request) => {\n const hostRejection = rejectUntrustedHost(request, settings.allowedHosts);\n if (hostRejection) {\n return hostRejection;\n }\n const subPath = routeSubPath(new URL(request.url).pathname);\n const isConnectCallback =\n request.method === \"GET\" &&\n subPath === DEVTOOLS_ENDPOINTS.connectCallback;\n const callerRejection = isConnectCallback\n ? null\n : rejectUntrustedCaller(request, settings.allowedHosts);\n if (callerRejection) {\n return callerRejection;\n }\n try {\n return await routeRequest(request, subPath, settings, projectRoots);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return errorResponse(`Reflet devtools route failed: ${reason}`, 500);\n }\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"picker-Rh-hsxyX.js","names":["MAX_TEXT_LENGTH","truncate","EDGE_GAP"],"sources":["../src/feedback/core/capture.ts","../src/feedback/core/react-source.ts","../src/feedback/core/redact.ts","../src/feedback/core/element-selector.ts","../src/feedback/core/page-context.ts","../src/feedback/types.ts","../src/feedback/core/annotations.ts","../src/feedback/ui/icons.tsx","../src/feedback/ui/widget-events.ts","../src/feedback/core/arrow-geometry.ts","../src/feedback/core/annotation-renderer.ts","../src/feedback/ui/selection-outline.tsx","../src/feedback/ui/visible-viewport.ts","../src/feedback/ui/floating/use-floating-position.ts","../src/feedback/core/submission/upload-screenshots.ts","../src/feedback/core/submit.ts","../src/feedback/ui/floating/element-walk.ts","../src/feedback/ui/picker.tsx"],"sourcesContent":["import type { CapturedImage } from \"../types\";\n\n/** Marks every node the widget owns, so captures never include the panel. */\nexport const WIDGET_MARKER = \"data-reflet-widget\";\n\nconst MAX_PIXEL_RATIO = 2;\nconst DEFAULT_MAX_WIDTH = 2400;\nconst MAX_INLINE_BYTES = 3_000_000;\nconst TRANSPARENT_PIXEL =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\";\nconst EXTERNAL_URL = /^(https?:)?\\/\\//i;\nconst CSS_URL = /url\\((['\"]?)([^)'\"]+)\\1\\)/g;\n\n/**\n * snapdom reloads cross-origin images with `crossOrigin=anonymous`; when that\n * reload fails to decode (cached copy without CORS headers — Convex storage\n * does this) its fallback promise never settles and the capture hangs forever.\n * Fetching the bytes ourselves and swapping in data URLs for the duration of\n * the capture starves that path: data URLs always decode.\n */\ninterface SourceSwap {\n element: Element;\n name: string;\n value: string | null;\n}\n\nfunction isExternalImageUrl(url: string): boolean {\n if (!url || url.startsWith(\"data:\") || url.startsWith(\"blob:\")) {\n return false;\n }\n if (!EXTERNAL_URL.test(url)) {\n return false;\n }\n try {\n return new URL(url, window.location.href).origin !== window.location.origin;\n } catch {\n return false;\n }\n}\n\nfunction toDataUrl(url: string): Promise<string | null> {\n return new Promise((resolve) => {\n fetch(url, { mode: \"cors\" })\n .then(async (response) => {\n if (!response.ok) {\n resolve(null);\n return;\n }\n const blob = await response.blob();\n if (blob.size === 0 || blob.size > MAX_INLINE_BYTES) {\n resolve(null);\n return;\n }\n const reader = new FileReader();\n reader.onload = () =>\n resolve(typeof reader.result === \"string\" ? reader.result : null);\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(blob);\n })\n .catch(() => resolve(null));\n });\n}\n\nconst PNG_NORMALIZE_TIMEOUT = 750;\nconst CAPTURE_TIMEOUT = 10_000;\nconst ANIMATION_SETTLE_TIMEOUT = 1000;\n\n/** The widget is excluded from every capture, so its own motion (a pulsing pin) is not worth waiting for. */\nfunction isWidgetAnimation(animation: Animation): boolean {\n const target =\n animation.effect instanceof KeyframeEffect ? animation.effect.target : null;\n const root = target?.getRootNode();\n return root instanceof ShadowRoot && root.host.hasAttribute(WIDGET_MARKER);\n}\n/**\n * Tiles and sections routinely animate in or reflow (grid drags, entrance\n * transitions); a capture taken mid-flight freezes them displaced. Waits for\n * animations touching the page to finish, capped so an infinite spinner can\n * never stall the report.\n */\nasync function waitForPageAnimations(): Promise<void> {\n if (typeof document.getAnimations !== \"function\") {\n return;\n }\n const start = performance.now();\n while (performance.now() - start < ANIMATION_SETTLE_TIMEOUT) {\n const running = document\n .getAnimations()\n .filter(\n (animation) =>\n animation.playState === \"running\" && !isWidgetAnimation(animation)\n );\n if (running.length === 0) {\n return;\n }\n await Promise.race([\n Promise.allSettled(running.map((animation) => animation.finished)),\n new Promise((resolve) => setTimeout(resolve, 150)),\n ]);\n }\n}\n\n/**\n * snapdom awaits `decode()` on images created with `decoding=\"sync\"` — a\n * promise Chrome 151 sometimes never settles (observed for cross-origin\n * webp, cached or inlined). Re-encoding through a canvas yields a PNG data\n * url, which decodes reliably; the load itself goes through `onload`, never\n * `decode()`.\n */\nfunction normalizeToPng(dataUrl: string): Promise<string | null> {\n return new Promise((resolve) => {\n const image = new Image();\n const timeout = setTimeout(() => resolve(dataUrl), PNG_NORMALIZE_TIMEOUT);\n image.onload = () => {\n clearTimeout(timeout);\n try {\n if (image.naturalWidth === 0 || image.naturalHeight === 0) {\n resolve(null);\n return;\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = image.naturalWidth;\n canvas.height = image.naturalHeight;\n const context = canvas.getContext(\"2d\");\n if (!context) {\n resolve(dataUrl);\n return;\n }\n context.drawImage(image, 0, 0);\n resolve(canvas.toDataURL(\"image/png\"));\n } catch {\n resolve(null);\n }\n };\n image.onerror = () => {\n clearTimeout(timeout);\n resolve(null);\n };\n image.src = dataUrl;\n });\n}\n\nasync function toInlineUrl(url: string): Promise<string | null> {\n const dataUrl = await toDataUrl(url);\n if (!dataUrl) {\n return null;\n }\n return normalizeToPng(dataUrl);\n}\n\nfunction remember(swaps: SourceSwap[], element: Element, name: string): void {\n swaps.push({ element, name, value: element.getAttribute(name) });\n}\n\nasync function inlineImgSource(\n img: HTMLImageElement,\n swaps: SourceSwap[]\n): Promise<void> {\n const src = img.getAttribute(\"src\");\n if (!(src && isExternalImageUrl(src))) {\n return;\n }\n\n const dataUrl = await toInlineUrl(src);\n if (dataUrl) {\n if (img.hasAttribute(\"srcset\")) {\n remember(swaps, img, \"srcset\");\n img.removeAttribute(\"srcset\");\n }\n if (img.hasAttribute(\"sizes\")) {\n remember(swaps, img, \"sizes\");\n img.removeAttribute(\"sizes\");\n }\n }\n remember(swaps, img, \"src\");\n img.setAttribute(\"src\", dataUrl ?? TRANSPARENT_PIXEL);\n}\n\nasync function inlineBackgroundImages(\n element: Element,\n swaps: SourceSwap[]\n): Promise<void> {\n const style = element.getAttribute(\"style\");\n if (!style) {\n return;\n }\n const urls = [...style.matchAll(CSS_URL)].map((match) => match[2] ?? \"\");\n if (!urls.some(isExternalImageUrl)) {\n return;\n }\n\n let next = style;\n for (const url of urls) {\n if (!isExternalImageUrl(url)) {\n continue;\n }\n const dataUrl = await toInlineUrl(url);\n next = next.split(url).join(dataUrl ?? TRANSPARENT_PIXEL);\n }\n if (next !== style) {\n remember(swaps, element, \"style\");\n element.setAttribute(\"style\", next);\n }\n}\n\n/**\n * Swaps every cross-origin image under `root` for a data URL so the capture\n * cannot hit snapdom's decode-failure hang. Returns the undo list — always\n * run it, even after a failed capture.\n */\nexport async function inlineExternalImages(\n root: Element\n): Promise<SourceSwap[]> {\n const swaps: SourceSwap[] = [];\n\n for (const img of [...root.querySelectorAll(\"img\")]) {\n await inlineImgSource(img, swaps);\n }\n for (const el of [...root.querySelectorAll(\"[style*='url(']\")]) {\n await inlineBackgroundImages(el, swaps);\n }\n\n return swaps;\n}\n\nexport function restoreInlinedImages(swaps: SourceSwap[]): void {\n for (const swap of swaps) {\n if (swap.value === null) {\n swap.element.removeAttribute(swap.name);\n } else {\n swap.element.setAttribute(swap.name, swap.value);\n }\n }\n}\n\nexport interface CaptureOptions {\n /** Capture this element instead of the visible viewport. */\n element?: Element;\n excludeSelectors?: string[];\n maxWidth?: number;\n /** Hard cap for one capture attempt before falling back. Default 10s. */\n timeout?: number;\n}\n\ninterface SnapdomOptions {\n cache: \"disabled\";\n clip?: \"viewport\";\n dpr: number;\n embedFonts: boolean;\n exclude: string[];\n fast: boolean;\n filter?: (element: Element) => boolean;\n reconcile: boolean;\n}\n\nexport function buildSnapdomOptions(options: {\n devicePixelRatio?: number;\n element?: Element;\n excludeSelectors?: string[];\n filter?: (element: Element) => boolean;\n}): SnapdomOptions {\n const ratio = options.devicePixelRatio ?? 1;\n\n return {\n cache: \"disabled\",\n clip: options.element ? undefined : \"viewport\",\n dpr: Math.min(Math.max(ratio || 1, 1), MAX_PIXEL_RATIO),\n embedFonts: true,\n exclude: [`[${WIDGET_MARKER}]`, ...(options.excludeSelectors ?? [])],\n fast: true,\n filter: options.filter,\n reconcile: true,\n };\n}\n\nexport function fitWithin(\n size: { height: number; width: number },\n maxWidth: number\n): { height: number; scale: number; width: number } {\n if (size.width <= maxWidth) {\n return { height: size.height, scale: 1, width: size.width };\n }\n\n const scale = maxWidth / size.width;\n return {\n height: Math.max(1, Math.round(size.height * scale)),\n scale,\n width: maxWidth,\n };\n}\n\nfunction toBlob(canvas: HTMLCanvasElement): Promise<Blob | null> {\n return new Promise((resolve) => {\n canvas.toBlob(resolve, \"image/png\");\n });\n}\n\nfunction downscale(\n canvas: HTMLCanvasElement,\n target: { height: number; width: number }\n): HTMLCanvasElement {\n const resized = document.createElement(\"canvas\");\n resized.width = target.width;\n resized.height = target.height;\n\n const context = resized.getContext(\"2d\");\n if (!context) {\n return canvas;\n }\n\n context.imageSmoothingQuality = \"high\";\n context.drawImage(canvas, 0, 0, target.width, target.height);\n return resized;\n}\n\n/** Wraps a rendered canvas as an owned capture, downscaled to `maxWidth`. */\nexport async function capturedFromCanvas(\n source: HTMLCanvasElement,\n maxWidth: number\n): Promise<CapturedImage | null> {\n const fitted = fitWithin(\n { height: source.height, width: source.width },\n maxWidth\n );\n const output = fitted.scale === 1 ? source : downscale(source, fitted);\n\n const blob = await toBlob(output);\n if (!blob) {\n return null;\n }\n\n return {\n blob,\n height: output.height,\n mimeType: \"image/png\",\n objectUrl: URL.createObjectURL(blob),\n width: output.width,\n };\n}\n\n/**\n * Renders what the user is looking at right now.\n *\n * Runs off the DOM rather than `getDisplayMedia` on purpose: a screen-share\n * permission prompt on every report would cost more reports than it captures.\n * Returns null instead of throwing — a screenshot is never worth losing the\n * written feedback.\n */\nexport async function captureViewport(\n options: CaptureOptions = {}\n): Promise<CapturedImage | null> {\n try {\n const { snapdom } = await import(\"@zumer/snapdom\");\n const target = options.element ?? document.documentElement;\n await waitForPageAnimations();\n const swaps = await inlineExternalImages(target);\n\n const shoot = (withoutImages = false): Promise<HTMLCanvasElement> => {\n const attempt = snapdom.toCanvas(\n target,\n buildSnapdomOptions({\n devicePixelRatio: window.devicePixelRatio,\n element: options.element,\n excludeSelectors: options.excludeSelectors,\n filter: withoutImages\n ? (element) => element.tagName !== \"IMG\"\n : undefined,\n })\n );\n attempt.catch(() => undefined);\n return Promise.race([\n attempt,\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"capture timed out\")),\n options.timeout ?? CAPTURE_TIMEOUT\n )\n ),\n ]);\n };\n\n let canvas: HTMLCanvasElement;\n try {\n canvas = await shoot();\n } catch {\n canvas = await shoot(true);\n } finally {\n restoreInlinedImages(swaps);\n }\n\n return await capturedFromCanvas(\n canvas,\n options.maxWidth ?? DEFAULT_MAX_WIDTH\n );\n } catch {\n return null;\n }\n}\n\nexport function releaseCapture(image: CapturedImage | null | undefined): void {\n if (image) {\n URL.revokeObjectURL(image.objectUrl);\n }\n}\n","const FIBER_KEY_PREFIXES = [\"__reactFiber$\", \"__reactInternalInstance$\"];\nconst MEMO_TYPE = Symbol.for(\"react.memo\");\nconst FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\");\n\nconst MAX_STACK_DEPTH = 6;\nconst MAX_FIBER_WALK = 60;\nconst MAX_OWNER_WALK = 8;\nconst MIN_NAME_LENGTH = 4;\nconst CAPITALIZED = /^[A-Z]/;\nconst WORD_INSIDE = /[a-z]{2}/;\n\nconst ORIGIN_PREFIX = /^[a-z][\\w+.-]*:\\/\\/[^/]*/i;\nconst WEBPACK_PREFIX = /^webpack-internal:\\/{2,}(\\.\\/)?/;\nconst STACK_LOCATION = /([^\\s()]+):(\\d+):(\\d+)\\)?\\s*$/;\nconst NON_SOURCE_FRAME =\n /node_modules|\\/_next\\/|\\/chunks?\\/|\\/\\.vite\\/|\\/dist\\/|\\/build\\/|hot-update/;\nconst SOURCE_EXTENSION = /\\.(?:[cm]?[jt]sx?)$/;\nconst SOURCE_ROOT_MARKERS = [\n \"src\",\n \"app\",\n \"pages\",\n \"components\",\n \"features\",\n \"lib\",\n];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/** React attaches the fiber under a randomly suffixed key on the host node. */\nexport function getFiberFromNode(node: Node): unknown {\n for (const key of Object.getOwnPropertyNames(node)) {\n for (const prefix of FIBER_KEY_PREFIXES) {\n if (key.startsWith(prefix)) {\n return Reflect.get(node, key) ?? null;\n }\n }\n }\n return null;\n}\n\nfunction readName(value: unknown): string | null {\n if (typeof value !== \"function\" && !isRecord(value)) {\n return null;\n }\n\n const displayName = Reflect.get(value, \"displayName\");\n if (typeof displayName === \"string\" && displayName) {\n return displayName;\n }\n\n const name = Reflect.get(value, \"name\");\n return typeof name === \"string\" && name ? name : null;\n}\n\n/**\n * Minified bundles hand out names like `Ur` or `Sn`. Reporting those as the\n * owning component actively misleads an agent, so only real words get through.\n */\nfunction isMeaningfulName(name: string): boolean {\n if (name.includes(\"/\") || name.includes(\"_\")) {\n return true;\n }\n\n return (\n name.length >= MIN_NAME_LENGTH &&\n CAPITALIZED.test(name) &&\n WORD_INSIDE.test(name)\n );\n}\n\nfunction componentName(type: unknown, depth = 0): string | null {\n if (typeof type === \"string\" || type === null || depth > 3) {\n return null;\n }\n\n if (isRecord(type)) {\n const marker = Reflect.get(type, \"$$typeof\");\n if (marker === MEMO_TYPE) {\n return componentName(Reflect.get(type, \"type\"), depth + 1);\n }\n if (marker === FORWARD_REF_TYPE) {\n return componentName(Reflect.get(type, \"render\"), depth + 1);\n }\n }\n\n const name = readName(type);\n return name && isMeaningfulName(name) ? name : null;\n}\n\n/** Component names owning the fiber, innermost first. */\nexport function resolveComponentStack(fiber: unknown): string[] {\n const stack: string[] = [];\n let current = fiber;\n let steps = 0;\n\n while (isRecord(current) && steps < MAX_FIBER_WALK) {\n const name =\n componentName(Reflect.get(current, \"type\")) ??\n componentName(Reflect.get(current, \"elementType\"));\n\n if (name && stack.at(-1) !== name) {\n stack.push(name);\n if (stack.length >= MAX_STACK_DEPTH) {\n break;\n }\n }\n\n current = Reflect.get(current, \"return\");\n steps++;\n }\n\n return stack;\n}\n\nexport function shortenSourcePath(raw: string): string {\n const path = raw\n .replace(WEBPACK_PREFIX, \"\")\n .replace(ORIGIN_PREFIX, \"\")\n .split(\"?\")[0];\n if (!path) {\n return raw;\n }\n\n for (const marker of SOURCE_ROOT_MARKERS) {\n if (path.startsWith(`${marker}/`)) {\n return path;\n }\n const index = path.lastIndexOf(`/${marker}/`);\n if (index !== -1) {\n return path.slice(index + 1);\n }\n }\n\n return path.split(\"/\").filter(Boolean).slice(-3).join(\"/\");\n}\n\nfunction formatLocation(\n fileName: string,\n line: number,\n column?: number\n): string {\n const base = `${shortenSourcePath(fileName)}:${line}`;\n return column === undefined ? base : `${base}:${column}`;\n}\n\nfunction fromDebugSource(source: unknown): string | undefined {\n if (!isRecord(source)) {\n return;\n }\n\n const fileName = Reflect.get(source, \"fileName\");\n const lineNumber = Reflect.get(source, \"lineNumber\");\n if (typeof fileName !== \"string\" || typeof lineNumber !== \"number\") {\n return;\n }\n\n const columnNumber = Reflect.get(source, \"columnNumber\");\n return formatLocation(\n fileName,\n lineNumber,\n typeof columnNumber === \"number\" ? columnNumber : undefined\n );\n}\n\nfunction fromDebugStack(stack: unknown): string | undefined {\n const raw = isRecord(stack) ? Reflect.get(stack, \"stack\") : stack;\n if (typeof raw !== \"string\") {\n return;\n }\n\n for (const line of raw.split(\"\\n\")) {\n const match = STACK_LOCATION.exec(line);\n const file = match?.[1];\n if (!(match && file) || NON_SOURCE_FRAME.test(file)) {\n continue;\n }\n\n const path = file.replace(ORIGIN_PREFIX, \"\").split(\"?\")[0] ?? \"\";\n if (!SOURCE_EXTENSION.test(path)) {\n continue;\n }\n\n return formatLocation(path, Number(match[2]), Number(match[3]));\n }\n}\n\n/**\n * `src/components/login-form.tsx:46:19` when the React build exposes it.\n * Production bundles strip debug info — callers must treat this as optional.\n */\nexport function resolveSourceLocation(fiber: unknown): string | undefined {\n let current = fiber;\n let steps = 0;\n\n while (isRecord(current) && steps < MAX_OWNER_WALK) {\n const located =\n fromDebugSource(Reflect.get(current, \"_debugSource\")) ??\n fromDebugStack(Reflect.get(current, \"_debugStack\"));\n if (located) {\n return located;\n }\n\n current = Reflect.get(current, \"_debugOwner\");\n steps++;\n }\n}\n\nexport function inspectReactElement(element: Element): {\n componentStack: string[];\n sourceLocation?: string;\n} {\n const fiber = getFiberFromNode(element);\n return {\n componentStack: resolveComponentStack(fiber),\n sourceLocation: resolveSourceLocation(fiber),\n };\n}\n","/**\n * The picked element's markup leaves the reporter's browser and ends up in an\n * agent prompt, so it is scrubbed here: typed-in values, credentials and\n * anything marked `data-reflet-redact` never make the trip.\n */\n\nconst EMAIL = /[\\w.%+-]+@[\\w.-]+\\.[a-z]{2,}/gi;\nconst LONG_TOKEN = /\\b[\\w-]{28,}\\b/g;\nconst OPAQUE_URI = /^(?:data|blob|javascript):/i;\nconst WHITESPACE_RUN = /\\s+/g;\nconst URL_QUERY = /[?#]/;\n\nconst REDACTED = \"[redacted]\";\nconst ELLIPSIS = \"…\";\nexport const REDACT_ATTRIBUTE = \"data-reflet-redact\";\n\nconst MAX_ATTRIBUTE_LENGTH = 120;\nconst MAX_TEXT_LENGTH = 200;\nconst MAX_CHILD_DEPTH = 3;\nconst MAX_CLONED_NODES = 400;\n\nconst DROPPED_TAGS = new Set([\"script\", \"style\", \"noscript\", \"template\"]);\nconst VALUE_HOLDERS = new Set([\"input\", \"textarea\", \"select\", \"option\"]);\nconst URL_ATTRIBUTES = new Set([\n \"src\",\n \"srcset\",\n \"href\",\n \"poster\",\n \"action\",\n \"formaction\",\n]);\n\nfunction truncate(value: string, max: number): string {\n return value.length <= max ? value : `${value.slice(0, max - 1)}${ELLIPSIS}`;\n}\n\n/** Emails and token-shaped strings, wherever they appear in reported text. */\nexport function maskSecrets(value: string): string {\n return value.replace(EMAIL, REDACTED).replace(LONG_TOKEN, REDACTED);\n}\n\nconst SENSITIVE_PARAM =\n /token|secret|pass(?:word|wd)?|pwd|auth|jwt|credential|session|sid|key|email|ssn|otp|code|signature|nonce/i;\nconst LEADING_QUESTION_MARK = /^\\?/;\n\nfunction decoded(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\n/**\n * Query strings carry signed-in state (`?token=…`, `?userEmail=…`) straight\n * into stored reports and agent prompts. Values of anything credential- or\n * identity-shaped are masked; every other byte of the address stays intact.\n */\nexport function redactUrl(href: string): string {\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return maskSecrets(href);\n }\n\n const pairs = url.search\n .replace(LEADING_QUESTION_MARK, \"\")\n .split(\"&\")\n .filter(Boolean);\n if (\n !pairs.some((pair) =>\n SENSITIVE_PARAM.test(decoded(pair.split(\"=\")[0] ?? \"\"))\n )\n ) {\n return href;\n }\n\n const kept = pairs.map((pair) => {\n const equals = pair.indexOf(\"=\");\n if (\n equals === -1 ||\n !SENSITIVE_PARAM.test(decoded(pair.slice(0, equals)))\n ) {\n return pair;\n }\n return `${pair.slice(0, equals)}=${REDACTED}`;\n });\n\n const query = kept.join(\"&\");\n return `${url.origin}${url.pathname}${query ? `?${query}` : \"\"}${url.hash}`;\n}\n\nfunction sanitizeUrl(value: string): string {\n if (OPAQUE_URI.test(value)) {\n return `${value.slice(0, value.indexOf(\":\"))}:${ELLIPSIS}`;\n }\n return value.split(URL_QUERY)[0] ?? value;\n}\n\nfunction sanitizeAttributes(element: Element): void {\n const holdsTypedValue = VALUE_HOLDERS.has(element.localName);\n\n for (const { name, value } of Array.from(element.attributes)) {\n if (holdsTypedValue && name === \"value\") {\n element.removeAttribute(name);\n continue;\n }\n\n const cleaned = URL_ATTRIBUTES.has(name)\n ? sanitizeUrl(value)\n : maskSecrets(value);\n element.setAttribute(name, truncate(cleaned, MAX_ATTRIBUTE_LENGTH));\n }\n}\n\nfunction collapse(element: Element): void {\n element.replaceChildren(element.ownerDocument.createTextNode(ELLIPSIS));\n}\n\nfunction sanitizeTree(element: Element, depth: number): void {\n sanitizeAttributes(element);\n\n if (element.hasAttribute(REDACT_ATTRIBUTE)) {\n element.replaceChildren(element.ownerDocument.createTextNode(REDACTED));\n return;\n }\n\n if (element.localName === \"svg\") {\n element.replaceChildren();\n return;\n }\n\n for (const child of Array.from(element.childNodes)) {\n if (child.nodeType === Node.COMMENT_NODE) {\n child.remove();\n continue;\n }\n\n if (child.nodeType === Node.TEXT_NODE) {\n child.textContent = truncate(\n maskSecrets(child.textContent ?? \"\"),\n MAX_TEXT_LENGTH\n );\n continue;\n }\n\n if (!(child instanceof Element)) {\n continue;\n }\n\n if (DROPPED_TAGS.has(child.localName)) {\n child.remove();\n continue;\n }\n\n if (depth >= MAX_CHILD_DEPTH) {\n sanitizeAttributes(child);\n collapse(child);\n continue;\n }\n\n sanitizeTree(child, depth + 1);\n }\n}\n\n/** Redacted `outerHTML`, shallow-cloned when the subtree is too large to be useful. */\nexport function sanitizeMarkup(element: Element, maxLength: number): string {\n const isSmallEnough =\n element.querySelectorAll(\"*\").length <= MAX_CLONED_NODES;\n const clone = element.cloneNode(isSmallEnough);\n if (!(clone instanceof Element)) {\n return \"\";\n }\n\n sanitizeTree(clone, 0);\n if (!isSmallEnough) {\n collapse(clone);\n }\n\n return truncate(clone.outerHTML.replace(WHITESPACE_RUN, \" \"), maxLength);\n}\n","import type { ElementRect, ElementSelection } from \"../../types\";\nimport { inspectReactElement } from \"./react-source\";\nimport { maskSecrets, sanitizeMarkup } from \"./redact\";\n\nconst SAFE_ID = /^[A-Za-z][\\w-]*$/;\nconst WHITESPACE = /\\s+/g;\nconst MAX_LABEL_LENGTH = 80;\nconst MAX_HTML_LENGTH = 600;\nconst MAX_TEXT_LENGTH = 300;\nconst MAX_REGION_LENGTH = 160;\nconst MAX_HANDLE_VALUE_LENGTH = 80;\nconst MAX_DEPTH = 12;\nconst MIN_PATH_SEGMENTS = 2;\n// Hard caps enforced by POST /api/v1/feedback/create — over them the whole\n// report is rejected, so clip here rather than lose the submission.\nconst MAX_SELECTOR_LENGTH = 600;\nconst MAX_SOURCE_LOCATION_LENGTH = 400;\nexport const MAX_SELECTION_COMMENT_LENGTH = 2000;\n\nconst TEST_ATTRIBUTES = [\n \"data-testid\",\n \"data-test-id\",\n \"data-test\",\n \"data-cy\",\n \"data-qa\",\n];\nconst NAMING_ATTRIBUTES = [\"name\", \"aria-label\"];\n\nconst LANDMARK_SELECTOR =\n 'dialog, [role=\"dialog\"], [role=\"alertdialog\"], main, nav, aside, header, footer, form, section, article';\nconst HEADING_SELECTOR = 'h1, h2, h3, h4, h5, h6, [role=\"heading\"]';\n\n/** Elements that start a new visual block — their text gets separated by a space. */\nconst BLOCK_TAGS = new Set([\n \"address\",\n \"article\",\n \"aside\",\n \"blockquote\",\n \"dd\",\n \"details\",\n \"div\",\n \"dl\",\n \"dt\",\n \"fieldset\",\n \"figcaption\",\n \"figure\",\n \"footer\",\n \"form\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"header\",\n \"hr\",\n \"li\",\n \"main\",\n \"nav\",\n \"ol\",\n \"p\",\n \"pre\",\n \"section\",\n \"summary\",\n \"table\",\n \"td\",\n \"th\",\n \"tr\",\n \"ul\",\n]);\n\nfunction visibleText(element: Element): string {\n const clone = element.cloneNode(true);\n if (!(clone instanceof Element)) {\n return \"\";\n }\n\n for (const node of clone.querySelectorAll(\"*\")) {\n if (BLOCK_TAGS.has(node.localName)) {\n node.before(clone.ownerDocument.createTextNode(\" \"));\n }\n }\n\n return collapseText(maskSecrets(clone.textContent ?? \"\"));\n}\n\nfunction isUnique(selector: string): boolean {\n try {\n return document.querySelectorAll(selector).length === 1;\n } catch {\n return false;\n }\n}\n\nfunction escapeAttributeValue(value: string): string {\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n\nfunction attributeHandle(\n element: Element,\n attribute: string,\n qualifier: string\n): string | null {\n const value = element.getAttribute(attribute);\n if (!value || value.length > MAX_HANDLE_VALUE_LENGTH) {\n return null;\n }\n\n const selector = `${qualifier}[${attribute}=\"${escapeAttributeValue(value)}\"]`;\n return isUnique(selector) ? selector : null;\n}\n\n/** Something an engineer would have written on purpose, unlike a positional path. */\nfunction uniqueHandle(element: Element): string | null {\n const id = element.getAttribute(\"id\");\n if (id && SAFE_ID.test(id) && isUnique(`#${id}`)) {\n return `#${id}`;\n }\n\n for (const attribute of TEST_ATTRIBUTES) {\n const handle = attributeHandle(element, attribute, \"\");\n if (handle) {\n return handle;\n }\n }\n\n for (const attribute of NAMING_ATTRIBUTES) {\n const handle = attributeHandle(element, attribute, element.localName);\n if (handle) {\n return handle;\n }\n }\n\n return null;\n}\n\nfunction positionalSegment(element: Element): string {\n const tag = element.localName;\n const parent = element.parentElement;\n if (!parent) {\n return tag;\n }\n\n const sameTag = Array.from(parent.children).filter(\n (child) => child.localName === tag\n );\n if (sameTag.length <= 1) {\n return tag;\n }\n\n return `${tag}:nth-of-type(${sameTag.indexOf(element) + 1})`;\n}\n\n/**\n * Shortest selector that still resolves back to `element` from the document.\n * Grows the path one ancestor at a time and stops as soon as it is unique, so\n * a stable handle anywhere up the tree replaces the whole positional chain.\n * A bare tag is never enough: positional paths keep a parent for context.\n */\nexport function buildSelector(element: Element): string {\n if (element === document.documentElement) {\n return \"html\";\n }\n if (element === document.body) {\n return \"body\";\n }\n\n const handle = uniqueHandle(element);\n if (handle) {\n return handle;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n for (let depth = 0; current && depth < MAX_DEPTH; depth++) {\n const ancestorHandle = current === element ? null : uniqueHandle(current);\n segments.unshift(ancestorHandle ?? positionalSegment(current));\n\n const candidate = segments.join(\" > \");\n const isAnchored = segments.length >= MIN_PATH_SEGMENTS;\n if (\n ancestorHandle ||\n current === document.body ||\n (isAnchored && isUnique(candidate))\n ) {\n return candidate;\n }\n\n current = current.parentElement;\n }\n\n return segments.join(\" > \");\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n\nfunction collapseText(value: string): string {\n return value.replace(WHITESPACE, \" \").trim();\n}\n\nfunction accessibleLabel(element: Element): string {\n const explicit =\n element.getAttribute(\"aria-label\") ??\n element.getAttribute(\"title\") ??\n element.getAttribute(\"alt\") ??\n element.getAttribute(\"placeholder\");\n if (explicit?.trim()) {\n return explicit.trim();\n }\n\n return collapseText(element.textContent ?? \"\");\n}\n\n/** Short human label such as `button \"Sign in\"` or `div.card`. */\nexport function describeElement(element: Element): string {\n const tag = element.localName;\n const label = maskSecrets(accessibleLabel(element));\n if (label) {\n return truncate(`${tag} \"${label}\"`, MAX_LABEL_LENGTH);\n }\n\n const firstClass = element.classList.item(0);\n return truncate(firstClass ? `${tag}.${firstClass}` : tag, MAX_LABEL_LENGTH);\n}\n\nfunction describeLandmark(element: Element): string | null {\n const landmark = element.parentElement?.closest(LANDMARK_SELECTOR);\n if (!landmark) {\n return null;\n }\n\n const name =\n landmark.getAttribute(\"aria-label\") ?? landmark.getAttribute(\"title\");\n return name?.trim()\n ? `${landmark.localName} \"${collapseText(name)}\"`\n : landmark.localName;\n}\n\nfunction headingAbove(element: Element): string | null {\n const scope = element.closest(LANDMARK_SELECTOR) ?? document.body;\n const probe = document.createRange();\n probe.selectNodeContents(element);\n probe.collapse(true);\n\n let closest: Element | null = null;\n for (const heading of scope.querySelectorAll(HEADING_SELECTOR)) {\n if (probe.comparePoint(heading, 0) < 0) {\n closest = heading;\n }\n }\n\n const text = collapseText(closest?.textContent ?? \"\");\n return text || null;\n}\n\n/**\n * Where the element sits from a reader's point of view — `dialog \"Members\" ›\n * Danger zone` says more to an agent than any DOM path can.\n */\nexport function describeRegion(element: Element): string | undefined {\n const landmark = describeLandmark(element);\n const heading = headingAbove(element);\n const parts = [landmark];\n\n if (heading && !landmark?.includes(`\"${heading}\"`)) {\n parts.push(heading);\n }\n\n const region = parts.filter((part) => part !== null).join(\" › \");\n return region ? truncate(maskSecrets(region), MAX_REGION_LENGTH) : undefined;\n}\n\nexport function getElementRect(element: Element): ElementRect {\n const rect = element.getBoundingClientRect();\n return {\n height: Math.round(rect.height),\n width: Math.round(rect.width),\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n };\n}\n\n/** Everything an agent needs to find the picked element back in the codebase. */\nexport function buildElementSelection(element: Element): ElementSelection {\n const { componentStack, sourceLocation } = inspectReactElement(element);\n const text = truncate(visibleText(element), MAX_TEXT_LENGTH);\n\n return {\n componentStack,\n html: sanitizeMarkup(element, MAX_HTML_LENGTH),\n label: describeElement(element),\n rect: getElementRect(element),\n region: describeRegion(element),\n selector: truncate(buildSelector(element), MAX_SELECTOR_LENGTH),\n sourceLocation: sourceLocation\n ? truncate(sourceLocation, MAX_SOURCE_LOCATION_LENGTH)\n : sourceLocation,\n text: text || undefined,\n };\n}\n","import type { FeedbackContext } from \"../../types\";\nimport { redactUrl } from \"./redact\";\n\ninterface AgentInfo {\n browser?: string;\n device: \"desktop\" | \"mobile\" | \"tablet\";\n os?: string;\n}\n\nconst BROWSER_PATTERNS: [string, RegExp][] = [\n [\"Edge\", /Edg(?:e|A|iOS)?\\/([\\d.]+)/],\n [\"Opera\", /OPR\\/([\\d.]+)/],\n [\"Samsung Internet\", /SamsungBrowser\\/([\\d.]+)/],\n [\"Firefox\", /(?:Firefox|FxiOS)\\/([\\d.]+)/],\n [\"Chrome\", /(?:Chrome|CriOS)\\/([\\d.]+)/],\n [\"Safari\", /Version\\/([\\d.]+).*Safari/],\n];\n\nconst OS_PATTERNS: [string, RegExp][] = [\n [\"iOS\", /iPhone|iPad|iPod/],\n [\"Android\", /Android/],\n [\"Windows\", /Windows NT/],\n [\"macOS\", /Mac OS X|Macintosh/],\n [\"ChromeOS\", /CrOS/],\n [\"Linux\", /Linux|X11/],\n];\n\nconst MOBILE_HINT = /Mobile|iPhone|iPod/;\nconst TABLET_HINT = /iPad|Tablet/;\nconst TRAILING_ZERO = /\\.0$/;\nconst ANDROID = /Android/;\n\nfunction shortenVersion(version: string): string {\n return version.split(\".\").slice(0, 2).join(\".\").replace(TRAILING_ZERO, \"\");\n}\n\nfunction detectDevice(userAgent: string): AgentInfo[\"device\"] {\n if (TABLET_HINT.test(userAgent)) {\n return \"tablet\";\n }\n if (MOBILE_HINT.test(userAgent)) {\n return \"mobile\";\n }\n return ANDROID.test(userAgent) ? \"tablet\" : \"desktop\";\n}\n\nexport function parseUserAgent(userAgent: string): AgentInfo {\n const info: AgentInfo = { device: detectDevice(userAgent) };\n\n for (const [name, pattern] of BROWSER_PATTERNS) {\n const version = pattern.exec(userAgent)?.[1];\n if (version) {\n info.browser = `${name} ${shortenVersion(version)}`;\n break;\n }\n }\n\n for (const [name, pattern] of OS_PATTERNS) {\n if (pattern.test(userAgent)) {\n info.os = name;\n break;\n }\n }\n\n return info;\n}\n\n// Hard caps enforced by POST /api/v1/feedback/create — over them the whole\n// report is rejected, so clip here rather than lose the submission.\nconst MAX_PAGE_TITLE_LENGTH = 300;\nconst MAX_URL_LENGTH = 2000;\nconst MAX_USER_AGENT_LENGTH = 600;\n\nfunction clip(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\nfunction optionalText(\n value: string | undefined,\n max: number\n): string | undefined {\n return value?.trim() ? clip(value, max) : undefined;\n}\n\nfunction resolveTimezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // Intl missing in some embedded webviews\n }\n}\n\n/** Everything about the page that a bug report needs and the DOM already knows. */\nexport function collectPageContext(options?: {\n sdkVersion?: string;\n}): FeedbackContext {\n const userAgent = navigator.userAgent;\n const agent = parseUserAgent(userAgent);\n\n return {\n browser: agent.browser,\n device: agent.device,\n language: navigator.language,\n os: agent.os,\n pageTitle: optionalText(document.title, MAX_PAGE_TITLE_LENGTH),\n referrer: optionalText(document.referrer, MAX_URL_LENGTH),\n screen: { height: window.screen.height, width: window.screen.width },\n scroll: { x: window.scrollX, y: window.scrollY },\n sdkVersion: options?.sdkVersion,\n timezone: resolveTimezone(),\n url: redactUrl(window.location.href),\n userAgent: clip(userAgent, MAX_USER_AGENT_LENGTH),\n viewport: {\n devicePixelRatio: window.devicePixelRatio,\n height: window.innerHeight,\n width: window.innerWidth,\n },\n };\n}\n","import type { ReactNode, RefObject } from \"react\";\nimport type { ElementSelection, FeedbackContext, RefletUser } from \"../types\";\n\nexport const SDK_VERSION = \"0.6.3\";\nexport const DEFAULT_WIDGET_OFFSET = 20;\n\nconst ANNOTATION_TOOLS = [\n \"pen\",\n \"arrow\",\n \"rectangle\",\n \"text\",\n \"spotlight\",\n \"highlight\",\n \"blur\",\n] as const;\n\nexport type AnnotationTool = (typeof ANNOTATION_TOOLS)[number];\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Annotation {\n color: string;\n end: Point;\n id: string;\n // Image pixels; pen only.\n points?: Point[];\n start: Point;\n text?: string;\n tool: AnnotationTool;\n}\n\nexport interface CapturedImage {\n blob: Blob;\n height: number;\n mimeType: string;\n // Caller revokes after capture is dropped.\n objectUrl: string;\n width: number;\n}\n\nexport interface ScreenshotDraft {\n annotations: Annotation[];\n context: FeedbackContext;\n id: string;\n image: CapturedImage;\n selectedNode?: Element;\n selection?: ElementSelection;\n source: \"automatic\" | \"manual\";\n}\n\nexport interface FeedbackWidgetLabels {\n annotateHint: string;\n attachElement: string;\n attachmentUploadFailed: string;\n attachScreenshot: string;\n back: string;\n cancel: string;\n captureFailed: string;\n capturing: string;\n clearAnnotations: string;\n descriptionPlaceholder: string;\n dismissForDays: string;\n done: string;\n elementNote: string;\n elementNotePlaceholder: string;\n emailInvalid: string;\n emailLabel: string;\n emailPlaceholder: string;\n emailPromptBody: string;\n emailPromptTitle: string;\n errorGeneric: string;\n errorTitleRequired: string;\n minimize: string;\n moreOptions: string;\n moveFeedback: string;\n pickAnother: string;\n pickElement: string;\n pickElementHint: string;\n recapture: string;\n removeScreenshot: string;\n resume: string;\n retakeHint: string;\n retryAttachments: string;\n screenshot: string;\n sendWithoutEmail: string;\n submit: string;\n successMessage: string;\n successTitle: string;\n title: string;\n titlePlaceholder: string;\n trigger: string;\n undo: string;\n}\n\nexport const DEFAULT_WIDGET_LABELS: FeedbackWidgetLabels = {\n annotateHint: \"Draw on the screenshot to point at the problem.\",\n attachElement: \"Attach this element\",\n attachmentUploadFailed:\n \"Your feedback was saved, but some screenshots are still pending. Retry to attach them.\",\n attachScreenshot: \"Attach a screenshot\",\n back: \"Back\",\n cancel: \"Cancel\",\n captureFailed: \"Screenshot unavailable. Try again or send without it.\",\n capturing: \"Taking screenshot…\",\n clearAnnotations: \"Clear drawing\",\n descriptionPlaceholder: \"What would you like to share?\",\n dismissForDays: \"Hide for {days} days\",\n done: \"Done\",\n elementNote: \"Comment on the picked element\",\n elementNotePlaceholder: \"What is wrong with this?\",\n emailInvalid: \"Enter a valid email address.\",\n emailLabel: \"Email\",\n emailPlaceholder: \"you@company.com\",\n emailPromptBody: \"We only use it to follow up on this report.\",\n emailPromptTitle: \"Add your email?\",\n errorGeneric: \"Something went wrong. Please try again.\",\n errorTitleRequired: \"Tell us a bit about it first.\",\n minimize: \"Minimize feedback\",\n moreOptions: \"More options\",\n moveFeedback: \"Move feedback\",\n pickAnother: \"Pick another\",\n pickElement: \"Point at an element\",\n pickElementHint: \"Pick the element you are talking about\",\n recapture: \"Retake\",\n removeScreenshot: \"Remove\",\n resume: \"Resume feedback\",\n retakeHint: \"Screenshot of this page\",\n retryAttachments: \"Retry attachments\",\n screenshot: \"Screenshot\",\n sendWithoutEmail: \"Send without email\",\n submit: \"Send feedback\",\n successMessage: \"We read every report. Thanks for taking the time.\",\n successTitle: \"Feedback sent\",\n title: \"Send feedback\",\n titlePlaceholder: \"Short summary\",\n trigger: \"Feedback\",\n undo: \"Undo\",\n};\n\nexport interface FeedbackTriggerProps {\n onClick: () => void;\n ref: RefObject<HTMLButtonElement | null>;\n}\n\nexport interface RefletFeedbackProps {\n baseUrl?: string;\n captureConsole?: boolean;\n captureOnOpen?: boolean;\n devtools?: boolean;\n dismissForDays?: number;\n enabled?: boolean;\n hotkey?: string | null;\n labels?: Partial<FeedbackWidgetLabels>;\n metadata?: Record<string, string>;\n offset?: number;\n onClose?: () => void;\n onDismiss?: (result: { until: number }) => void;\n onOpen?: () => void;\n onSubmit?: (result: { feedbackId: string }) => void;\n position?: \"bottom-left\" | \"bottom-right\" | \"top-left\" | \"top-right\";\n primaryColor?: string;\n publicKey?: string;\n renderTrigger?: (props: FeedbackTriggerProps) => ReactNode;\n theme?: \"auto\" | \"dark\" | \"light\";\n user?: RefletUser;\n userToken?: string;\n}\n\nexport type WidgetStep =\n | \"annotate\"\n | \"compose\"\n | \"email\"\n | \"picking\"\n | \"success\";\n","import type { ElementRect, ScreenshotAnnotation } from \"../../types\";\nimport type { Annotation, AnnotationTool, Point } from \"../types\";\n\nconst BOX_TOOLS: AnnotationTool[] = [\n \"text\",\n \"rectangle\",\n \"spotlight\",\n \"highlight\",\n \"blur\",\n];\nconst MIN_GESTURE_LENGTH = 8;\nconst DEFAULT_PATH_TOLERANCE = 2.5;\n\nexport function normalizeRect(start: Point, end: Point): ElementRect {\n return {\n height: Math.abs(end.y - start.y),\n width: Math.abs(end.x - start.x),\n x: Math.min(start.x, end.x),\n y: Math.min(start.y, end.y),\n };\n}\n\nexport function simplifyPath(\n points: Point[],\n tolerance = DEFAULT_PATH_TOLERANCE\n): Point[] {\n if (points.length < 3) {\n return points;\n }\n\n const [first, ...rest] = points;\n if (!first) {\n return points;\n }\n\n const kept: Point[] = [first];\n let anchor = first;\n\n for (const point of rest.slice(0, -1)) {\n if (Math.hypot(point.x - anchor.x, point.y - anchor.y) >= tolerance) {\n kept.push(point);\n anchor = point;\n }\n }\n\n const last = points.at(-1);\n if (last) {\n kept.push(last);\n }\n\n return kept;\n}\n\nexport function isDegenerate(annotation: Annotation): boolean {\n if (annotation.tool === \"text\") {\n return !annotation.text?.trim();\n }\n if (annotation.tool === \"pen\") {\n return (annotation.points?.length ?? 0) < 2;\n }\n\n const { start, end } = annotation;\n return Math.hypot(end.x - start.x, end.y - start.y) < MIN_GESTURE_LENGTH;\n}\n\nfunction toWire(annotation: Annotation): ScreenshotAnnotation {\n const { color, start, end, tool } = annotation;\n\n if (tool === \"pen\") {\n return {\n color,\n points: simplifyPath(annotation.points ?? []),\n type: tool,\n x: start.x,\n y: start.y,\n };\n }\n\n if (BOX_TOOLS.includes(tool)) {\n const rect = normalizeRect(start, end);\n return {\n color,\n height: rect.height,\n ...(tool === \"text\" ? { text: annotation.text } : {}),\n type: tool,\n width: rect.width,\n x: rect.x,\n y: rect.y,\n };\n }\n\n return {\n color,\n endX: end.x,\n endY: end.y,\n type: tool,\n x: start.x,\n y: start.y,\n };\n}\n\nexport function toWireAnnotations(\n annotations: Annotation[]\n): ScreenshotAnnotation[] {\n return annotations.filter((item) => !isDegenerate(item)).map(toWire);\n}\n","import type { ReactNode } from \"react\";\n\nexport function Svg({\n children,\n className,\n size = 16,\n}: {\n children: ReactNode;\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n aria-hidden=\"true\"\n className={className}\n fill=\"none\"\n height={size}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"1.8\"\n viewBox=\"0 0 24 24\"\n width={size}\n >\n {children}\n </svg>\n );\n}\n\nexport function ChatIcon({ className }: { className?: string }) {\n return (\n <Svg className={className} size={15}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </Svg>\n );\n}\n\nexport function CloseIcon({ className }: { className?: string }) {\n return (\n <Svg className={className}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </Svg>\n );\n}\n\nexport function CameraIcon() {\n return (\n <Svg>\n <path d=\"M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2l1.2-2h8.2l1.2 2h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z\" />\n <circle cx=\"12\" cy=\"13\" r=\"3.2\" />\n </Svg>\n );\n}\n\nexport function PencilIcon() {\n return (\n <Svg>\n <path d=\"M16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1 1-4z\" />\n </Svg>\n );\n}\n\nexport function TargetIcon() {\n return (\n <Svg>\n <path d=\"M12 3v3M12 18v3M3 12h3M18 12h3\" />\n <circle cx=\"12\" cy=\"12\" r=\"5\" />\n </Svg>\n );\n}\n\nexport function TrashIcon() {\n return (\n <Svg>\n <path d=\"M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13M10 11v5M14 11v5\" />\n </Svg>\n );\n}\n\nexport function ArrowIcon() {\n return (\n <Svg>\n <path d=\"M5 19 19 5M11 5h8v8\" />\n </Svg>\n );\n}\n\nexport function UndoIcon() {\n return (\n <Svg>\n <path d=\"M4 9h11a5 5 0 0 1 0 10h-5M4 9l4-4M4 9l4 4\" />\n </Svg>\n );\n}\n\nexport function CheckIcon({ size = 28 }: { size?: number }) {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={size}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2.4\"\n viewBox=\"0 0 24 24\"\n width={size}\n >\n <path d=\"m5 13 4 4L19 7\" />\n </svg>\n );\n}\n\nexport function GripIcon() {\n return (\n <Svg>\n <path d=\"M9 5h.01M15 5h.01M9 12h.01M15 12h.01M9 19h.01M15 19h.01\" />\n </Svg>\n );\n}\nexport function MinusIcon() {\n return (\n <Svg>\n <path d=\"M5 12h14\" />\n </Svg>\n );\n}\nexport function MoreIcon() {\n return (\n <Svg>\n <path d=\"M5 12h.01M12 12h.01M19 12h.01\" />\n </Svg>\n );\n}\n\nexport function ChevronDownIcon() {\n return (\n <Svg>\n <path d=\"m7 10 5 5 5-5\" />\n </Svg>\n );\n}\n\nexport function SquareIcon() {\n return (\n <Svg>\n <rect height=\"14\" rx=\"2\" width=\"14\" x=\"5\" y=\"5\" />\n </Svg>\n );\n}\nexport function TextIcon() {\n return (\n <Svg>\n <path d=\"M5 6V4h14v2M12 4v16M8 20h8\" />\n </Svg>\n );\n}\nexport function SpotlightIcon() {\n return (\n <Svg>\n <path d=\"M8 4H4v4M16 4h4v4M4 16v4h4M20 16v4h-4\" />\n <rect height=\"8\" rx=\"1\" width=\"8\" x=\"8\" y=\"8\" />\n </Svg>\n );\n}\nexport function HighlightIcon() {\n return (\n <Svg>\n <path d=\"M4 19h16M8 15l8-11 4 3-8 11-4-3ZM7 15l-2 3\" />\n </Svg>\n );\n}\nexport function BlurIcon() {\n return (\n <Svg>\n <rect height=\"14\" rx=\"2\" width=\"14\" x=\"5\" y=\"5\" />\n <path d=\"M8 8h8v8H8z\" />\n </Svg>\n );\n}\n","import { WIDGET_MARKER } from \"../core/capture\";\n\nconst REPLAYED_EVENTS = [\n \"keydown\",\n \"keyup\",\n \"keypress\",\n \"pointerdown\",\n \"mousedown\",\n \"touchstart\",\n \"touchend\",\n \"focusin\",\n] as const;\n\nfunction isWidgetNode(node: EventTarget): boolean {\n if (node instanceof ShadowRoot) {\n return node.host.hasAttribute(WIDGET_MARKER);\n }\n return node instanceof Element && node.hasAttribute(WIDGET_MARKER);\n}\n\nexport function startsInWidget(event: Event): boolean {\n return event.composedPath().some(isWidgetNode);\n}\n\nfunction readEventInit(event: Event): Record<string, unknown> {\n const init: Record<string, unknown> = {};\n let prototype: object | null = Object.getPrototypeOf(event);\n while (prototype && prototype !== Event.prototype) {\n for (const key of Object.keys(prototype)) {\n init[key] = Reflect.get(event, key);\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n return init;\n}\n\nfunction replayInsideWidget(event: Event): void {\n const target = event.composedPath()[0];\n if (!(target && startsInWidget(event))) {\n return;\n }\n\n const replay: Event = Reflect.construct(event.constructor, [\n event.type,\n {\n ...readEventInit(event),\n bubbles: event.bubbles,\n cancelable: event.cancelable,\n composed: false,\n },\n ]);\n event.stopImmediatePropagation();\n target.dispatchEvent(replay);\n if (replay.defaultPrevented) {\n event.preventDefault();\n }\n}\n\nfunction hideFocusLeavingForWidget(event: FocusEvent): void {\n const movesIntoWidget =\n event.relatedTarget !== null && isWidgetNode(event.relatedTarget);\n if (movesIntoWidget && !startsInWidget(event)) {\n event.stopImmediatePropagation();\n }\n}\n\n// Host shortcuts and outside-press dismissals see the shadow host as target, not our controls: stop widget events at window capture, replay them inside the shadow root.\n// Focus traps and close-on-blur popups would pull focus back from our fields: the host never learns focus left for the widget.\n// Import time = registered before any host capture listener added later.\nif (typeof window !== \"undefined\") {\n for (const type of REPLAYED_EVENTS) {\n window.addEventListener(type, replayInsideWidget, true);\n }\n window.addEventListener(\"focusout\", hideFocusLeavingForWidget, true);\n}\n\n// A replayed click would rerun its activation (submit, toggle), so the real one is stopped at the host once the widget has handled it.\nexport function stopClicksAtHost(host: Element): void {\n host.addEventListener(\"click\", (event) => event.stopPropagation());\n}\n\nexport function listenOnPageAndWidget(\n anchor: Node | null,\n type: string,\n listener: (event: Event) => void,\n capture = false\n): () => void {\n const widgetRoot = anchor?.getRootNode();\n const targets: EventTarget[] =\n widgetRoot instanceof ShadowRoot ? [document, widgetRoot] : [document];\n\n for (const target of targets) {\n target.addEventListener(type, listener, capture);\n }\n return () => {\n for (const target of targets) {\n target.removeEventListener(type, listener, capture);\n }\n };\n}\n\nexport function listenToKeydown(\n anchor: Node | null,\n onKeyDown: (event: KeyboardEvent) => void,\n capture = false\n): () => void {\n return listenOnPageAndWidget(\n anchor,\n \"keydown\",\n (event) => {\n if (event instanceof KeyboardEvent) {\n onKeyDown(event);\n }\n },\n capture\n );\n}\n","import type { Point } from \"../types\";\n\nexport function arrowOutline(\n start: Point,\n end: Point\n): {\n points: Point[];\n strokeWidth: number;\n} {\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const length = Math.hypot(dx, dy);\n if (length === 0) {\n return { points: [], strokeWidth: 0 };\n }\n\n const shaftWidth = Math.min(20, Math.max(6, length * 0.025), length * 0.2);\n const headLength = Math.min(length * 0.45, shaftWidth * 3);\n const headHalfWidth = headLength * 0.55;\n const shaftLength = length - headLength;\n const pointOnArrow = (along: number, across: number): Point => ({\n x: start.x + (dx * along - dy * across) / length,\n y: start.y + (dy * along + dx * across) / length,\n });\n\n return {\n points: [\n pointOnArrow(0, 0),\n pointOnArrow(shaftLength, -shaftWidth / 2),\n pointOnArrow(shaftLength, -headHalfWidth),\n { x: end.x, y: end.y },\n pointOnArrow(shaftLength, headHalfWidth),\n pointOnArrow(shaftLength, shaftWidth / 2),\n ],\n strokeWidth: Math.min(4, length * 0.02),\n };\n}\n","import type { ElementRect } from \"../../types\";\nimport type { Annotation, CapturedImage, Point } from \"../types\";\nimport { isDegenerate, normalizeRect } from \"./annotations\";\nimport { arrowOutline } from \"./arrow-geometry\";\nimport { capturedFromCanvas } from \"./capture\";\n\nconst STROKE_WIDTH = 3;\nconst HIGHLIGHT_ALPHA = 0.3;\nconst REDACTION_FILL = \"#111827\";\nconst PIXEL_BLOCK = 10;\n\nexport interface AnnotationCanvasContext {\n beginPath: () => void;\n canvas: { height: number; width: number };\n closePath: () => void;\n drawImage: (\n image: CanvasImageSource,\n dx: number,\n dy: number,\n dw: number,\n dh: number\n ) => void;\n fill: () => void;\n fillRect: (x: number, y: number, width: number, height: number) => void;\n fillStyle: string | CanvasGradient | CanvasPattern;\n fillText: (text: string, x: number, y: number) => void;\n font: string;\n globalAlpha: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n lineTo: (x: number, y: number) => void;\n lineWidth: number;\n moveTo: (x: number, y: number) => void;\n restore: () => void;\n save: () => void;\n stroke: () => void;\n strokeRect: (x: number, y: number, width: number, height: number) => void;\n strokeStyle: string | CanvasGradient | CanvasPattern;\n textBaseline: CanvasTextBaseline;\n}\n\nfunction scalePoint(point: Point, scale: number): Point {\n return { x: point.x * scale, y: point.y * scale };\n}\n\nfunction scaleRect(rect: ElementRect, scale: number): ElementRect {\n return {\n height: rect.height * scale,\n width: rect.width * scale,\n x: rect.x * scale,\n y: rect.y * scale,\n };\n}\n\nfunction isCanvasElement(value: unknown): value is HTMLCanvasElement {\n return (\n typeof HTMLCanvasElement !== \"undefined\" &&\n value instanceof HTMLCanvasElement\n );\n}\n\n// Downsample before repainting so redacted pixels cannot be recovered.\nfunction redact(context: AnnotationCanvasContext, rect: ElementRect): void {\n const source = context.canvas;\n const width = Math.max(1, Math.round(rect.width / PIXEL_BLOCK));\n const height = Math.max(1, Math.round(rect.height / PIXEL_BLOCK));\n\n if (isCanvasElement(source)) {\n const offscreen = document.createElement(\"canvas\");\n offscreen.width = width;\n offscreen.height = height;\n const offscreenContext = offscreen.getContext(\"2d\");\n\n if (offscreenContext) {\n offscreenContext.imageSmoothingEnabled = true;\n offscreenContext.drawImage(\n source,\n rect.x,\n rect.y,\n rect.width,\n rect.height,\n 0,\n 0,\n width,\n height\n );\n context.drawImage(offscreen, rect.x, rect.y, rect.width, rect.height);\n return;\n }\n }\n\n context.fillStyle = REDACTION_FILL;\n context.fillRect(rect.x, rect.y, rect.width, rect.height);\n}\n\nfunction drawArrow(\n context: AnnotationCanvasContext,\n annotation: Annotation,\n scale: number\n): void {\n const { points, strokeWidth } = arrowOutline(\n annotation.start,\n annotation.end\n );\n const [first, ...rest] = points.map((point) => scalePoint(point, scale));\n if (!first) {\n return;\n }\n\n context.beginPath();\n context.moveTo(first.x, first.y);\n for (const point of rest) {\n context.lineTo(point.x, point.y);\n }\n context.closePath();\n context.lineWidth = strokeWidth * scale;\n context.fill();\n context.stroke();\n}\n\nfunction drawPen(\n context: AnnotationCanvasContext,\n points: Point[],\n scale: number\n): void {\n const [first, ...rest] = points;\n if (!first) {\n return;\n }\n\n const head = scalePoint(first, scale);\n context.beginPath();\n context.moveTo(head.x, head.y);\n for (const point of rest) {\n const scaled = scalePoint(point, scale);\n context.lineTo(scaled.x, scaled.y);\n }\n context.stroke();\n}\n\nfunction drawSpotlight(\n context: AnnotationCanvasContext,\n rect: ElementRect\n): void {\n const { width, height } = context.canvas;\n context.save();\n context.fillStyle = REDACTION_FILL;\n context.globalAlpha = 0.55;\n context.fillRect(0, 0, width, rect.y);\n context.fillRect(\n 0,\n rect.y + rect.height,\n width,\n height - rect.y - rect.height\n );\n context.fillRect(0, rect.y, rect.x, rect.height);\n context.fillRect(\n rect.x + rect.width,\n rect.y,\n width - rect.x - rect.width,\n rect.height\n );\n context.restore();\n context.strokeRect(rect.x, rect.y, rect.width, rect.height);\n}\n\nfunction drawAnnotation(\n context: AnnotationCanvasContext,\n annotation: Annotation,\n scale: number\n): void {\n const { color, tool } = annotation;\n const rect = scaleRect(\n normalizeRect(annotation.start, annotation.end),\n scale\n );\n\n context.save();\n context.lineWidth = STROKE_WIDTH * scale;\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n context.strokeStyle = color;\n context.fillStyle = color;\n\n switch (tool) {\n case \"text\": {\n const lines = (annotation.text ?? \"\").split(\"\\n\");\n const lineHeight = rect.height / lines.length;\n context.font = `${lineHeight / 1.4}px ui-sans-serif, system-ui, sans-serif`;\n context.textBaseline = \"top\";\n for (const [index, line] of lines.entries()) {\n context.fillText(line, rect.x, rect.y + index * lineHeight);\n }\n break;\n }\n case \"pen\":\n drawPen(context, annotation.points ?? [], scale);\n break;\n case \"arrow\":\n drawArrow(context, annotation, scale);\n break;\n case \"spotlight\":\n drawSpotlight(context, rect);\n break;\n case \"rectangle\":\n context.strokeRect(rect.x, rect.y, rect.width, rect.height);\n break;\n case \"highlight\":\n context.globalAlpha = HIGHLIGHT_ALPHA;\n context.fillRect(rect.x, rect.y, rect.width, rect.height);\n break;\n default:\n redact(context, rect);\n break;\n }\n\n context.restore();\n}\n\nexport function drawAnnotations(\n context: AnnotationCanvasContext,\n annotations: Annotation[],\n options?: { scale?: number }\n): void {\n const scale = options?.scale ?? 1;\n for (const annotation of annotations) {\n if (!isDegenerate(annotation)) {\n drawAnnotation(context, annotation, scale);\n }\n }\n}\n\nfunction loadImage(url: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.onload = () => resolve(image);\n image.onerror = () => reject(new Error(\"Screenshot could not be decoded\"));\n image.src = url;\n });\n}\n\nexport async function renderAnnotatedImage(\n source: CapturedImage,\n annotations: Annotation[]\n): Promise<CapturedImage | null> {\n if (annotations.length === 0) {\n return null;\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = source.width;\n canvas.height = source.height;\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return null;\n }\n\n const image = await loadImage(source.objectUrl);\n context.drawImage(image, 0, 0, source.width, source.height);\n drawAnnotations(context, annotations);\n\n return await capturedFromCanvas(canvas, source.width);\n}\n","import { useEffect, useRef } from \"react\";\n\n/**\n * Keeps the picked element ringed while the reporter writes about it, so the\n * composer parked next to it is visibly about that element.\n */\nexport function SelectionOutline({ node }: { node: Element | null }) {\n const boxRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const box = boxRef.current;\n if (!(box && node)) {\n return;\n }\n\n let frame = 0;\n const draw = () => {\n frame = 0;\n const rect = node.getBoundingClientRect();\n const hidden =\n rect.width === 0 ||\n rect.height === 0 ||\n rect.bottom < 0 ||\n rect.top > window.innerHeight;\n box.style.opacity = hidden ? \"0\" : \"1\";\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n box.style.transform = `translate(${rect.left}px, ${rect.top}px)`;\n };\n const schedule = () => {\n frame ||= requestAnimationFrame(draw);\n };\n\n draw();\n const observer =\n typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(draw);\n observer?.observe(node);\n window.addEventListener(\"scroll\", schedule, {\n capture: true,\n passive: true,\n });\n window.addEventListener(\"resize\", schedule);\n\n return () => {\n cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener(\"scroll\", schedule, true);\n window.removeEventListener(\"resize\", schedule);\n };\n }, [node]);\n\n if (!node) {\n return null;\n }\n\n return <div aria-hidden=\"true\" className=\"selection-outline\" ref={boxRef} />;\n}\n","export interface VisibleViewport {\n bottom: number;\n height: number;\n left: number;\n right: number;\n top: number;\n width: number;\n}\n\n/**\n * The part of the page the reporter can actually see, in fixed-position\n * coordinates. On mobile the keyboard shrinks this without touching\n * `window.innerHeight`, so anything that must stay reachable measures here.\n */\nexport function visibleViewport(): VisibleViewport {\n const viewport = window.visualViewport;\n const left = viewport?.offsetLeft ?? 0;\n const top = viewport?.offsetTop ?? 0;\n const width = viewport?.width ?? window.innerWidth;\n const height = viewport?.height ?? window.innerHeight;\n return {\n bottom: window.innerHeight - top - height,\n height,\n left,\n right: window.innerWidth - left - width,\n top,\n width,\n };\n}\n\nexport function onViewportChange(update: () => void) {\n window.addEventListener(\"resize\", update);\n window.visualViewport?.addEventListener(\"resize\", update);\n window.visualViewport?.addEventListener(\"scroll\", update);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.visualViewport?.removeEventListener(\"resize\", update);\n window.visualViewport?.removeEventListener(\"scroll\", update);\n };\n}\n","import {\n type KeyboardEvent,\n type PointerEvent,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { Point, RefletFeedbackProps } from \"../../types\";\nimport { onViewportChange, visibleViewport } from \"../visible-viewport\";\n\nconst EDGE_GAP = 12;\nconst KEYBOARD_STEP = 24;\nconst KEY_DIRECTIONS: Record<string, Point> = {\n ArrowDown: { x: 0, y: KEYBOARD_STEP },\n ArrowLeft: { x: -KEYBOARD_STEP, y: 0 },\n ArrowRight: { x: KEYBOARD_STEP, y: 0 },\n ArrowUp: { x: 0, y: -KEYBOARD_STEP },\n};\n\nfunction clampPosition(\n point: Point,\n bounds: DOMRect,\n viewport = visibleViewport()\n): Point {\n return {\n x: Math.max(\n viewport.left + EDGE_GAP,\n Math.min(\n point.x,\n viewport.left + viewport.width - bounds.width - EDGE_GAP\n )\n ),\n y: Math.max(\n viewport.top + EDGE_GAP,\n Math.min(\n point.y,\n viewport.top + viewport.height - bounds.height - EDGE_GAP\n )\n ),\n };\n}\n\nfunction readStoredPosition(persistKey: string | undefined): Point | null {\n if (!persistKey || typeof localStorage === \"undefined\") {\n return null;\n }\n try {\n const stored: unknown = JSON.parse(\n localStorage.getItem(persistKey) ?? \"null\"\n );\n if (\n typeof stored === \"object\" &&\n stored !== null &&\n \"x\" in stored &&\n \"y\" in stored &&\n typeof stored.x === \"number\" &&\n typeof stored.y === \"number\"\n ) {\n return { x: stored.x, y: stored.y };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function useFloatingPosition<Root extends HTMLElement = HTMLDivElement>(\n corner: RefletFeedbackProps[\"position\"] = \"bottom-right\",\n isPanelOpen = false,\n {\n anchorSelector = \".root\",\n persistKey,\n }: { anchorSelector?: string; persistKey?: string } = {}\n) {\n const rootRef = useRef<Root>(null);\n const gesture = useRef<Point | null>(null);\n // Where the user put it (persisted) vs. where today's window lets it sit (never persisted).\n const [placement, setPlacement] = useState<Point | null>(() =>\n readStoredPosition(persistKey)\n );\n const [fittedAnchor, setFittedAnchor] = useState<Point | null>(null);\n const [positionedPanelOpen, setPositionedPanelOpen] = useState(isPanelOpen);\n const [viewport, setViewport] = useState(visibleViewport);\n const horizontalEdge = corner.endsWith(\"right\") ? \"right\" : \"left\";\n const verticalEdge = corner.startsWith(\"bottom\") ? \"bottom\" : \"top\";\n const position = fittedAnchor ?? placement;\n\n if (positionedPanelOpen !== isPanelOpen) {\n setPositionedPanelOpen(isPanelOpen);\n setPlacement(null);\n setFittedAnchor(null);\n }\n\n const anchorFor = useCallback(\n (point: Point, bounds: DOMRect): Point => {\n const fitted = clampPosition(point, bounds);\n const visible = visibleViewport();\n return {\n x:\n horizontalEdge === \"right\"\n ? visible.left + visible.width - fitted.x - bounds.width\n : fitted.x - visible.left,\n y:\n verticalEdge === \"bottom\"\n ? visible.top + visible.height - fitted.y - bounds.height\n : fitted.y - visible.top,\n };\n },\n [horizontalEdge, verticalEdge]\n );\n\n const moveTo = (point: Point, bounds: DOMRect) => {\n const anchor = anchorFor(point, bounds);\n setFittedAnchor(null);\n setPlacement((current) =>\n current?.x === anchor.x && current.y === anchor.y ? current : anchor\n );\n };\n\n // Every render, on the layout box: an entrance transform would read as overflow.\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || root.offsetWidth === 0) {\n return;\n }\n const bounds = new DOMRect(\n root.offsetLeft,\n root.offsetTop,\n root.offsetWidth,\n root.offsetHeight\n );\n const fitted = clampPosition(bounds, bounds, viewport);\n if (\n Math.abs(fitted.x - bounds.x) > 0.5 ||\n Math.abs(fitted.y - bounds.y) > 0.5\n ) {\n const anchor = anchorFor(fitted, bounds);\n setFittedAnchor((current) =>\n current?.x === anchor.x && current.y === anchor.y ? current : anchor\n );\n }\n });\n\n /** Back to the user's placement first; the layout effect then refits it to the new room. */\n useEffect(() => {\n const refit = () => setFittedAnchor(null);\n const observer =\n typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(refit);\n if (rootRef.current) {\n observer?.observe(rootRef.current);\n }\n const stopListening = onViewportChange(() => {\n setViewport(visibleViewport());\n refit();\n });\n return () => {\n observer?.disconnect();\n stopListening();\n };\n }, []);\n\n useEffect(() => {\n if (!persistKey) {\n return;\n }\n try {\n if (placement) {\n localStorage.setItem(persistKey, JSON.stringify(placement));\n } else {\n localStorage.removeItem(persistKey);\n }\n } catch {\n // Storage can be full or blocked; the position just won't survive a reload.\n }\n }, [persistKey, placement]);\n\n const onPointerDown = (event: PointerEvent<HTMLButtonElement>) => {\n const bounds = rootRef.current?.getBoundingClientRect();\n if (!bounds || event.button !== 0) {\n return;\n }\n event.currentTarget.setPointerCapture(event.pointerId);\n gesture.current = {\n x: event.clientX - bounds.x,\n y: event.clientY - bounds.y,\n };\n };\n const onPointerMove = (event: PointerEvent<HTMLButtonElement>) => {\n const bounds = rootRef.current?.getBoundingClientRect();\n const grab = gesture.current;\n if (\n !(\n bounds &&\n grab &&\n event.currentTarget.hasPointerCapture(event.pointerId)\n )\n ) {\n return;\n }\n moveTo({ x: event.clientX - grab.x, y: event.clientY - grab.y }, bounds);\n };\n const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n const direction = KEY_DIRECTIONS[event.key];\n const bounds = rootRef.current?.getBoundingClientRect();\n if (!(bounds && direction)) {\n return;\n }\n event.preventDefault();\n moveTo({ x: bounds.x + direction.x, y: bounds.y + direction.y }, bounds);\n };\n\n const viewportStyles = `${anchorSelector} { --rf-viewport-width: ${viewport.width}px; --rf-viewport-top: ${viewport.top}px; --rf-viewport-bottom: ${viewport.bottom}px; --rf-viewport-left: ${viewport.left}px; --rf-viewport-right: ${viewport.right}px; }`;\n const anchorStyles = position\n ? `${anchorSelector}[data-moved=\"true\"] { left: auto; right: auto; top: auto; bottom: auto; ${horizontalEdge}: ${position.x + viewport[horizontalEdge]}px; ${verticalEdge}: ${position.y + viewport[verticalEdge]}px; }`\n : \"\";\n return {\n handleProps: {\n onKeyDown,\n onLostPointerCapture: () => {\n gesture.current = null;\n },\n onPointerCancel: () => {\n gesture.current = null;\n },\n onPointerDown,\n onPointerMove,\n onPointerUp: () => {\n gesture.current = null;\n },\n },\n /** The user's own placement, independent of any temporary fit. */\n placement,\n /** Null while docked by CSS; non-null once moved by the user or fitted into the window. */\n position,\n resetPosition: () => {\n setPlacement(null);\n setFittedAnchor(null);\n },\n rootRef,\n styles: viewportStyles + anchorStyles,\n };\n}\n","import type { SaveScreenshotParams } from \"../../../types\";\nimport type { CapturedImage, ScreenshotDraft } from \"../../types\";\nimport { renderAnnotatedImage } from \"../annotation-renderer\";\nimport { toWireAnnotations } from \"../annotations\";\nimport { releaseCapture } from \"../capture\";\nimport type { FeedbackTransport, WidgetSubmission } from \"../submit\";\n\nexport type PreparedScreenshot = Omit<SaveScreenshotParams, \"feedbackId\">;\n\nasync function uploadImage(transport: FeedbackTransport, image: CapturedImage) {\n const { uploadUrl } = await transport.getScreenshotUploadUrl();\n return transport.uploadImage(uploadUrl, image);\n}\n\nasync function prepareScreenshot(\n transport: FeedbackTransport,\n screenshot: ScreenshotDraft,\n index: number\n): Promise<PreparedScreenshot> {\n const { image, annotations, context } = screenshot;\n const annotated =\n annotations.length > 0\n ? await renderAnnotatedImage(image, annotations)\n : null;\n if (annotations.length > 0 && !annotated) {\n throw new Error(\"Could not render your annotations. Please try again.\");\n }\n try {\n const storageId = await uploadImage(transport, image);\n const annotatedStorageId = annotated\n ? await uploadImage(transport, annotated)\n : undefined;\n return {\n annotatedStorageId,\n annotations:\n annotations.length > 0 ? toWireAnnotations(annotations) : undefined,\n captureSource: \"widget\",\n filename: `screenshot-${index + 1}.png`,\n height: image.height,\n mimeType: image.mimeType,\n pageUrl: context.url,\n size: image.blob.size,\n storageId,\n width: image.width,\n };\n } finally {\n releaseCapture(annotated);\n }\n}\n\nexport async function uploadScreenshots(\n transport: FeedbackTransport,\n submission: WidgetSubmission\n) {\n const results = await Promise.allSettled(\n submission.screenshots.map((screenshot, index) =>\n prepareScreenshot(transport, screenshot, index)\n )\n );\n return results.map((result) => {\n if (result.status === \"rejected\") {\n throw result.reason;\n }\n return result.value;\n });\n}\n","import type { Reflet } from \"../../client\";\nimport type {\n CreateFeedbackParams,\n CreateFeedbackResponse,\n FeedbackContext,\n SaveScreenshotParams,\n} from \"../../types\";\nimport type { CapturedImage, ScreenshotDraft } from \"../types\";\nimport {\n type PreparedScreenshot,\n uploadScreenshots,\n} from \"./submission/upload-screenshots\";\n\nconst MAX_TITLE_LENGTH = 100;\nconst NEWLINE = /\\r?\\n/;\n\nexport interface FeedbackTransport {\n create: (params: CreateFeedbackParams) => Promise<CreateFeedbackResponse>;\n getScreenshotUploadUrl: () => Promise<{ uploadUrl: string }>;\n saveScreenshot: (\n params: SaveScreenshotParams\n ) => Promise<{ screenshotId: string }>;\n uploadImage: (uploadUrl: string, image: CapturedImage) => Promise<string>;\n}\n\nexport interface WidgetSubmission {\n context: FeedbackContext;\n email?: string;\n isAnonymous: boolean;\n message: string;\n screenshots: ScreenshotDraft[];\n}\n\nexport interface SubmitResult {\n feedbackId: string;\n pendingScreenshots: PreparedScreenshot[];\n}\n\nexport function deriveTitle(message: string): string {\n const firstLine =\n message\n .split(NEWLINE)\n .map((line) => line.trim())\n .find(Boolean) ?? \"\";\n\n if (firstLine.length <= MAX_TITLE_LENGTH) {\n return firstLine;\n }\n\n const clipped = firstLine.slice(0, MAX_TITLE_LENGTH - 1);\n const lastSpace = clipped.lastIndexOf(\" \");\n return `${(lastSpace > 0 ? clipped.slice(0, lastSpace) : clipped).trimEnd()}…`;\n}\n\nexport function buildDescription(params: {\n email?: string;\n isAnonymous: boolean;\n message: string;\n}): string {\n const { email, isAnonymous, message } = params;\n const contact = isAnonymous && email ? `\\n\\n---\\nContact: ${email}` : \"\";\n\n return `${message.trim()}${contact}`;\n}\n\nexport async function attachPreparedScreenshots(\n transport: FeedbackTransport,\n result: SubmitResult\n): Promise<SubmitResult> {\n const results = await Promise.allSettled(\n result.pendingScreenshots.map((screenshot) =>\n transport.saveScreenshot({\n ...screenshot,\n feedbackId: result.feedbackId,\n })\n )\n );\n const pendingScreenshots = result.pendingScreenshots.filter(\n (_, index) => results[index]?.status === \"rejected\"\n );\n return { feedbackId: result.feedbackId, pendingScreenshots };\n}\n\nasync function createReportWithScreenshots(\n transport: FeedbackTransport,\n submission: WidgetSubmission,\n pendingScreenshots: PreparedScreenshot[]\n) {\n const { feedbackId } = await transport.create({\n context: submission.context,\n description: buildDescription(submission),\n title: deriveTitle(submission.message),\n });\n return attachPreparedScreenshots(transport, {\n feedbackId,\n pendingScreenshots,\n });\n}\n\nexport async function submitWidgetFeedback(\n transport: FeedbackTransport,\n submission: WidgetSubmission\n): Promise<SubmitResult> {\n const title = deriveTitle(submission.message);\n if (!title) {\n throw new Error(\"Please describe your feedback before sending it.\");\n }\n const pendingScreenshots = await uploadScreenshots(transport, submission);\n return createReportWithScreenshots(transport, submission, pendingScreenshots);\n}\n\nfunction isStorageResponse(value: unknown): value is { storageId: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof Reflect.get(value, \"storageId\") === \"string\"\n );\n}\n\nexport async function uploadImageBlob(\n uploadUrl: string,\n image: Pick<CapturedImage, \"blob\" | \"mimeType\">\n): Promise<string> {\n const response = await fetch(uploadUrl, {\n body: image.blob,\n headers: { \"Content-Type\": image.mimeType },\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(`Screenshot upload failed (${response.status})`);\n }\n\n const payload: unknown = await response.json();\n if (!isStorageResponse(payload)) {\n throw new Error(\"Screenshot upload returned no storage id\");\n }\n\n return payload.storageId;\n}\n\nexport function createFeedbackTransport(client: Reflet): FeedbackTransport {\n return {\n create: (params) => client.create(params),\n getScreenshotUploadUrl: () => client.getScreenshotUploadUrl(),\n saveScreenshot: (params) => client.saveScreenshot(params),\n uploadImage: uploadImageBlob,\n };\n}\n","import { WIDGET_MARKER } from \"../../core/capture\";\n\ntype SiblingDirection = \"nextElementSibling\" | \"previousElementSibling\";\n\nconst ARROW_SIBLING: Record<string, SiblingDirection> = {\n ArrowLeft: \"previousElementSibling\",\n ArrowRight: \"nextElementSibling\",\n};\n\nexport const AIM_KEYS = [\n \"Tab\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"ArrowLeft\",\n \"ArrowRight\",\n];\n\nexport function isWidgetOwned(element: Element): boolean {\n return element.closest(`[${WIDGET_MARKER}]`) !== null;\n}\n\nfunction isPickable(element: Element | null): boolean {\n if (\n !element ||\n element === document.documentElement ||\n isWidgetOwned(element)\n ) {\n return false;\n }\n const rect = element.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n}\n\nfunction pickableElements(): Element[] {\n return Array.from(document.body.querySelectorAll(\"*\")).filter(isPickable);\n}\n\nfunction documentStep(from: Element, backwards: boolean): Element | null {\n const all = pickableElements();\n const index = all.indexOf(from);\n if (all.length === 0) {\n return null;\n }\n if (index === -1) {\n return all[0] ?? null;\n }\n return all[(index + (backwards ? -1 : 1) + all.length) % all.length] ?? null;\n}\n\nfunction climb(from: Element): Element | null {\n let candidate = from.parentElement;\n while (candidate && !isPickable(candidate)) {\n candidate = candidate.parentElement;\n }\n return candidate;\n}\n\nfunction descend(from: Element): Element | null {\n let candidate = from.firstElementChild;\n while (candidate && !isPickable(candidate)) {\n candidate = candidate.nextElementSibling;\n }\n return candidate;\n}\n\nfunction sibling(from: Element, direction: SiblingDirection): Element | null {\n let candidate = from[direction];\n while (candidate && !isPickable(candidate)) {\n candidate = candidate[direction];\n }\n return candidate;\n}\n\nexport function stepAim(\n from: Element | null,\n key: string,\n backwards: boolean\n): Element | null {\n if (!(from && isPickable(from))) {\n return pickableElements()[0] ?? null;\n }\n if (key === \"Tab\") {\n return documentStep(from, backwards);\n }\n if (key === \"ArrowUp\") {\n return climb(from);\n }\n if (key === \"ArrowDown\") {\n return descend(from);\n }\n const direction = ARROW_SIBLING[key];\n return direction ? sibling(from, direction) : null;\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n describeElement,\n describeRegion,\n MAX_SELECTION_COMMENT_LENGTH,\n} from \"../core/element-selector\";\nimport { getFiberFromNode, resolveComponentStack } from \"../core/react-source\";\nimport type { FeedbackWidgetLabels } from \"../types\";\nimport { AIM_KEYS, isWidgetOwned, stepAim } from \"./floating/element-walk\";\nimport { ArrowIcon } from \"./icons\";\nimport {\n onViewportChange,\n type VisibleViewport,\n visibleViewport,\n} from \"./visible-viewport\";\nimport { listenToKeydown, startsInWidget } from \"./widget-events\";\n\nconst LABEL_HEIGHT = 24;\nconst LABEL_GAP = 6;\nconst NOTE_GAP = 10;\nconst EDGE_GAP = 12;\n\ninterface HoverTarget {\n componentName?: string;\n element: Element;\n label: string;\n rect: DOMRect;\n region?: string;\n}\n\nfunction elementUnder(x: number, y: number): Element | null {\n const element = document.elementFromPoint(x, y);\n if (!element || isWidgetOwned(element)) {\n return null;\n }\n return element;\n}\n\nfunction describeTarget(element: Element): HoverTarget {\n return {\n componentName: resolveComponentStack(getFiberFromNode(element))[0],\n element,\n label: describeElement(element),\n rect: element.getBoundingClientRect(),\n region: describeRegion(element),\n };\n}\n\ninterface CardSize {\n height: number;\n width: number;\n}\n\nfunction noteCardPosition(\n rect: DOMRect,\n view: VisibleViewport,\n card: CardSize\n) {\n const viewLeft = view.left + EDGE_GAP;\n const viewRight = view.left + view.width - EDGE_GAP;\n const viewTop = view.top + EDGE_GAP;\n const viewBottom = view.top + view.height - EDGE_GAP;\n const fitLeft = (left: number) =>\n Math.max(viewLeft, Math.min(left, viewRight - card.width));\n const fitTop = (top: number) =>\n Math.max(viewTop, Math.min(top, viewBottom - card.height));\n\n const below = rect.bottom + NOTE_GAP;\n if (below >= viewTop && below + card.height <= viewBottom) {\n return { left: fitLeft(rect.left), top: below };\n }\n const above = rect.top - NOTE_GAP - card.height;\n if (above >= viewTop && rect.top <= viewBottom) {\n return { left: fitLeft(rect.left), top: above };\n }\n const besideTop = fitTop(rect.top);\n const right = rect.right + NOTE_GAP;\n if (right + card.width <= viewRight) {\n return { left: right, top: besideTop };\n }\n const left = rect.left - NOTE_GAP - card.width;\n if (left >= viewLeft) {\n return { left, top: besideTop };\n }\n return {\n left: fitLeft(rect.left),\n top: fitTop(Math.min(rect.bottom, viewBottom) - card.height),\n };\n}\n\nfunction labelTop(rect: DOMRect, view: VisibleViewport): number {\n const above = rect.top - LABEL_HEIGHT - LABEL_GAP;\n if (above >= view.top) {\n return above;\n }\n const below = rect.bottom + LABEL_GAP;\n if (below + LABEL_HEIGHT <= view.top + view.height) {\n return below;\n }\n return Math.max(rect.top, view.top) + LABEL_GAP;\n}\n\nconst APPLE_PLATFORM = /Mac|iPhone|iPad/;\n\nexport interface PickerInspect {\n /** Shown on the note card; Shift+click or Shift+Enter skips the card. */\n label: string;\n onInspect: (element: Element) => void;\n}\n\n/** ⌘C on the aimed element, or the note card's button with its note. */\nexport interface PickerCopy {\n label: string;\n onCopy: (element: Element, note: string) => void;\n}\n\nexport function ElementPicker({\n copy,\n inspect,\n labels,\n onCancel,\n onPick,\n}: {\n copy?: PickerCopy;\n inspect?: PickerInspect;\n labels: FeedbackWidgetLabels;\n onCancel: () => void;\n onPick: (element: Element, note: string) => void;\n}) {\n const [target, setTarget] = useState<HoverTarget | null>(null);\n const [pinned, setPinned] = useState<HoverTarget | null>(null);\n const [note, setNote] = useState(\"\");\n const [noteSize, setNoteSize] = useState<CardSize>({ height: 0, width: 0 });\n const pickerRef = useRef<HTMLDivElement>(null);\n const noteCardRef = useRef<HTMLFormElement>(null);\n const noteRef = useRef<HTMLTextAreaElement>(null);\n const pinnedRef = useRef(false);\n const [view, setView] = useState(visibleViewport);\n const aimRef = useRef<Element | null>(null);\n\n useEffect(() => onViewportChange(() => setView(visibleViewport())), []);\n\n useLayoutEffect(() => {\n const card = noteCardRef.current;\n if (pinned && card) {\n setNoteSize({ height: card.offsetHeight, width: card.offsetWidth });\n }\n }, [pinned]);\n\n useEffect(() => {\n pinnedRef.current = pinned !== null;\n if (pinned) {\n noteRef.current?.focus({ preventScroll: true });\n }\n }, [pinned]);\n\n useEffect(() => {\n aimRef.current = target?.element ?? null;\n }, [target]);\n\n useEffect(() => {\n const swallow = (event: Event) => {\n if (startsInWidget(event)) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n };\n\n const pin = (element: Element, wantsCode: boolean) => {\n if (wantsCode && inspect) {\n inspect.onInspect(element);\n } else {\n setPinned(describeTarget(element));\n }\n };\n\n const aimAt = (x: number, y: number) => {\n const element = elementUnder(x, y);\n if (!element) {\n return;\n }\n\n setTarget((current) =>\n current?.element === element\n ? { ...current, rect: element.getBoundingClientRect() }\n : describeTarget(element)\n );\n };\n\n const onMove = (event: PointerEvent) => {\n if (pinnedRef.current || startsInWidget(event)) {\n return;\n }\n aimAt(event.clientX, event.clientY);\n };\n\n const onPointerDown = (event: PointerEvent) => {\n if (startsInWidget(event)) {\n return;\n }\n swallow(event);\n // Touch has no hover: the press itself is what aims.\n if (!pinnedRef.current) {\n aimAt(event.clientX, event.clientY);\n }\n };\n\n const onPointerUp = (event: PointerEvent) => {\n if (startsInWidget(event)) {\n return;\n }\n swallow(event);\n if (pinnedRef.current) {\n return;\n }\n const element = elementUnder(event.clientX, event.clientY);\n if (element) {\n pin(element, event.shiftKey);\n }\n };\n\n const moveAim = (key: string, backwards: boolean) => {\n const next = stepAim(aimRef.current, key, backwards);\n if (!next) {\n return;\n }\n next.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n aimRef.current = next;\n setTarget(describeTarget(next));\n };\n\n const onEscape = () => {\n if (pinnedRef.current) {\n setPinned(null);\n setNote(\"\");\n return;\n }\n onCancel();\n };\n\n const copyAimed = (event: KeyboardEvent): boolean => {\n const aimed = aimRef.current;\n const wantsCopy =\n (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"c\";\n if (!(wantsCopy && copy && aimed)) {\n return false;\n }\n swallow(event);\n copy.onCopy(aimed, \"\");\n return true;\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n swallow(event);\n onEscape();\n return;\n }\n if (pinnedRef.current || startsInWidget(event) || copyAimed(event)) {\n return;\n }\n if (event.key === \"Enter\") {\n swallow(event);\n if (aimRef.current) {\n pin(aimRef.current, event.shiftKey);\n }\n return;\n }\n if (!AIM_KEYS.includes(event.key)) {\n return;\n }\n swallow(event);\n moveAim(event.key, event.shiftKey);\n };\n\n const onScroll = () => {\n setTarget((current) =>\n current\n ? { ...current, rect: current.element.getBoundingClientRect() }\n : current\n );\n setPinned((current) =>\n current\n ? { ...current, rect: current.element.getBoundingClientRect() }\n : current\n );\n };\n\n // Window capture: runs before the host's own capture listeners on document.\n window.addEventListener(\"pointermove\", onMove, true);\n window.addEventListener(\"pointerdown\", onPointerDown, true);\n window.addEventListener(\"pointerup\", onPointerUp, true);\n window.addEventListener(\"mousedown\", swallow, true);\n window.addEventListener(\"mouseup\", swallow, true);\n window.addEventListener(\"click\", swallow, true);\n const stopListeningToKeys = listenToKeydown(\n pickerRef.current,\n onKeyDown,\n true\n );\n window.addEventListener(\"scroll\", onScroll, {\n capture: true,\n passive: true,\n });\n\n const previousCursor = document.body.style.cursor;\n document.body.style.cursor = \"crosshair\";\n\n return () => {\n window.removeEventListener(\"pointermove\", onMove, true);\n window.removeEventListener(\"pointerdown\", onPointerDown, true);\n window.removeEventListener(\"pointerup\", onPointerUp, true);\n window.removeEventListener(\"mousedown\", swallow, true);\n window.removeEventListener(\"mouseup\", swallow, true);\n window.removeEventListener(\"click\", swallow, true);\n stopListeningToKeys();\n window.removeEventListener(\"scroll\", onScroll, true);\n document.body.style.cursor = previousCursor;\n };\n }, [copy, inspect, onCancel]);\n\n const shown = pinned ?? target;\n const rect = shown?.rect;\n\n return (\n <div className=\"picker\" ref={pickerRef}>\n {rect && (\n <div\n className=\"picker-box\"\n data-pinned={pinned !== null}\n style={{\n height: rect.height,\n translate: `${rect.left}px ${rect.top}px`,\n width: rect.width,\n }}\n />\n )}\n {rect && target && !pinned && (\n <div\n className=\"picker-label\"\n style={{\n translate: `${Math.max(4, rect.left)}px ${labelTop(rect, view)}px`,\n }}\n >\n <strong>\n {target.componentName ? `<${target.componentName}>` : target.label}\n </strong>\n {target.region && <span>{target.region}</span>}\n </div>\n )}\n\n {pinned ? (\n <form\n className=\"picker-note glass\"\n onSubmit={(event) => {\n event.preventDefault();\n onPick(pinned.element, note.trim());\n }}\n ref={noteCardRef}\n style={noteCardPosition(pinned.rect, view, noteSize)}\n >\n <p className=\"picker-note-target\">\n <strong>\n {pinned.componentName\n ? `<${pinned.componentName}>`\n : pinned.label}\n </strong>\n {pinned.region && <span>{pinned.region}</span>}\n </p>\n <textarea\n aria-label={labels.elementNote}\n maxLength={MAX_SELECTION_COMMENT_LENGTH}\n onChange={(event) => setNote(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n onPick(pinned.element, note.trim());\n }\n }}\n placeholder={labels.elementNotePlaceholder}\n ref={noteRef}\n rows={2}\n value={note}\n />\n <div className=\"picker-note-actions\">\n <button\n className=\"picker-cancel\"\n onClick={() => {\n setPinned(null);\n setNote(\"\");\n }}\n type=\"button\"\n >\n {labels.pickAnother}\n </button>\n {inspect && (\n <button\n className=\"picker-cancel\"\n onClick={() => inspect.onInspect(pinned.element)}\n type=\"button\"\n >\n {inspect.label}\n </button>\n )}\n {copy && (\n <button\n className=\"picker-cancel\"\n onClick={() => copy.onCopy(pinned.element, note.trim())}\n type=\"button\"\n >\n {copy.label}\n </button>\n )}\n <button\n aria-label={labels.attachElement}\n className=\"submit\"\n title={labels.attachElement}\n type=\"submit\"\n >\n <ArrowIcon />\n </button>\n </div>\n </form>\n ) : (\n <div className=\"picker-hint\">\n <span className=\"picker-instruction\">\n {labels.pickElementHint} <kbd>Tab</kbd>\n <kbd>Enter</kbd>\n {inspect && <kbd>⇧ Click</kbd>}\n {copy && (\n <kbd>\n {APPLE_PLATFORM.test(navigator.userAgent) ? \"⌘C\" : \"Ctrl C\"}\n </kbd>\n )}\n <kbd>Esc</kbd>\n </span>\n <button className=\"picker-cancel\" onClick={onCancel} type=\"button\">\n {labels.cancel}\n </button>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"z-index-CIb4-3Fy.js","names":[],"sources":["../src/react-context.tsx","../src/z-index.ts"],"sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { Reflet } from \"./client\";\nimport type { RefletConfig, RefletUser } from \"./types\";\n\n// ============================================\n// Context Types\n// ============================================\n\nexport interface RefletContextValue {\n baseUrl?: string;\n client: Reflet;\n isReady: boolean;\n publicKey: string;\n setUser: (user: RefletUser | undefined) => void;\n user: RefletUser | undefined;\n userToken: string | undefined;\n}\n\n// ============================================\n// Context\n// ============================================\n\nexport const RefletContext = createContext<RefletContextValue | null>(null);\n\n// ============================================\n// Provider\n// ============================================\n\nexport interface RefletProviderProps {\n /** API base URL (optional, defaults to Reflet production API) */\n baseUrl?: string;\n /** Children */\n children: ReactNode;\n /** Your organization's public API key */\n publicKey: string;\n /** Initial user identification */\n user?: RefletUser;\n /** Pre-signed user token (alternative to user) */\n userToken?: string;\n}\n\nfunction subscribeToNothing(): () => void {\n return () => undefined;\n}\n\n/**\n * Provider component for Reflet SDK\n *\n * @example\n * ```tsx\n * import { RefletProvider } from 'reflet-sdk/react';\n *\n * function App() {\n * return (\n * <RefletProvider\n * publicKey=\"fb_pub_xxx\"\n * user={{ id: 'user_123', email: 'user@example.com', name: 'John' }}\n * >\n * <YourApp />\n * </RefletProvider>\n * );\n * }\n * ```\n */\nexport function RefletProvider({\n publicKey,\n baseUrl,\n user: initialUser,\n userToken,\n children,\n}: RefletProviderProps) {\n const [user, setUser] = useState<RefletUser | undefined>(initialUser);\n const isReady = useSyncExternalStore(\n subscribeToNothing,\n () => true,\n () => false\n );\n\n const client = useMemo(() => {\n const config: RefletConfig = {\n baseUrl,\n publicKey,\n user,\n userToken,\n };\n return new Reflet(config);\n }, [publicKey, baseUrl, user, userToken]);\n\n // Update client when user changes\n useEffect(() => {\n if (userToken) {\n client.setUserToken(userToken);\n } else {\n client.setUser(user);\n }\n }, [client, user, userToken]);\n\n const value = useMemo(\n () => ({\n baseUrl,\n client,\n isReady,\n publicKey,\n setUser,\n user,\n userToken,\n }),\n [client, publicKey, baseUrl, isReady, user, userToken]\n );\n\n return (\n <RefletContext.Provider value={value}>{children}</RefletContext.Provider>\n );\n}\n\n// ============================================\n// Hook to access context\n// ============================================\n\nexport function useRefletContext(): RefletContextValue {\n const context = useContext(RefletContext);\n if (!context) {\n throw new Error(\"useRefletContext must be used within a RefletProvider\");\n }\n return context;\n}\n\nexport function useRefletClient(): Reflet {\n const { client } = useRefletContext();\n return client;\n}\n","export const REFLET_Z_INDEX = {\n annotatorOverlay: 2_147_483_001,\n captureHalo: 2_147_482_999,\n devtoolsBar: 2_147_483_647,\n dialogContent: 2_147_482_991,\n dialogOverlay: 2_147_482_990,\n elementPicker: 2_147_483_647,\n widgetRoot: 2_147_483_000,\n} as const;\n"],"mappings":";;;;AA8BA,MAAa,gBAAgB,cAAyC,IAAI;AAmB1E,SAAS,qBAAiC;CACxC,aAAa,KAAA;AACf;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,eAAe,EAC7B,WACA,SACA,MAAM,aACN,WACA,YACsB;CACtB,MAAM,CAAC,MAAM,WAAW,SAAiC,WAAW;CACpE,MAAM,UAAU,qBACd,0BACM,YACA,KACR;CAEA,MAAM,SAAS,cAAc;EAO3B,OAAO,IAAI,OAAO;GALhB;GACA;GACA;GACA;EAEqB,CAAC;CAC1B,GAAG;EAAC;EAAW;EAAS;EAAM;CAAS,CAAC;CAGxC,gBAAgB;EACd,IAAI,WACF,OAAO,aAAa,SAAS;OAE7B,OAAO,QAAQ,IAAI;CAEvB,GAAG;EAAC;EAAQ;EAAM;CAAS,CAAC;CAE5B,MAAM,QAAQ,eACL;EACL;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EAAC;EAAQ;EAAW;EAAS;EAAS;EAAM;CAAS,CACvD;CAEA,OACE,oBAAC,cAAc,UAAf;EAA+B;EAAQ;CAAiC,CAAA;AAE5E;AAMA,SAAgB,mBAAuC;CACrD,MAAM,UAAU,WAAW,aAAa;CACxC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,uDAAuD;CAEzE,OAAO;AACT;AAEA,SAAgB,kBAA0B;CACxC,MAAM,EAAE,WAAW,iBAAiB;CACpC,OAAO;AACT;;;AC1IA,MAAa,iBAAiB;CAC5B,kBAAkB;CAClB,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CACf,YAAY;AACd"}