@designfever/web-review-kit 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +77 -179
  2. package/dist/{chunk-U5K2YGGL.js → chunk-I76WEDLA.js} +2248 -2722
  3. package/dist/chunk-I76WEDLA.js.map +1 -0
  4. package/dist/index.cjs +2346 -2603
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +10 -6
  7. package/dist/index.d.ts +10 -6
  8. package/dist/index.js +220 -7
  9. package/dist/index.js.map +1 -1
  10. package/dist/react-shell.cjs +8953 -6632
  11. package/dist/react-shell.cjs.map +1 -1
  12. package/dist/react-shell.d.cts +8 -3
  13. package/dist/react-shell.d.ts +8 -3
  14. package/dist/react-shell.js +5956 -3636
  15. package/dist/react-shell.js.map +1 -1
  16. package/dist/{types-D_mNjOHx.d.cts → types-Cf2x5ky6.d.cts} +8 -14
  17. package/dist/{types-D_mNjOHx.d.ts → types-Cf2x5ky6.d.ts} +8 -14
  18. package/dist/vite.cjs +186 -0
  19. package/dist/vite.cjs.map +1 -0
  20. package/dist/vite.d.cts +16 -0
  21. package/dist/vite.d.ts +16 -0
  22. package/dist/vite.js +161 -0
  23. package/dist/vite.js.map +1 -0
  24. package/docs/README.md +21 -30
  25. package/docs/adaptor.sample.ts +182 -0
  26. package/docs/architecture.md +125 -0
  27. package/docs/db-setup.md +253 -0
  28. package/docs/figma-overlay.md +52 -0
  29. package/docs/grid-overlay.md +38 -0
  30. package/docs/installation.md +108 -40
  31. package/package.json +22 -6
  32. package/dist/chunk-U5K2YGGL.js.map +0 -1
  33. package/docs/adapter-handoff.md +0 -146
  34. package/docs/concept.md +0 -102
  35. package/docs/df-sheet-adapter.md +0 -336
  36. package/docs/df-sheet-next.md +0 -222
  37. package/docs/initial-plan.md +0 -226
  38. package/docs/package-split-checkpoint.md +0 -79
  39. package/docs/presence-handoff.md +0 -138
  40. package/docs/review-feedback-2026-06-20.md +0 -267
  41. package/docs/smoke-baseline-2026-06-20.md +0 -41
  42. package/docs/stabilize-ui-work-guide.md +0 -243
  43. package/docs/supabase-presence.md +0 -198
  44. package/docs/supabase-review-items.md +0 -365
  45. package/docs/supabase.md +0 -205
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/route.ts","../src/status.ts","../src/adapters/local.ts","../src/adapters/df-sheet.ts","../src/adapters/supabase.ts","../src/core/overlay-style.ts","../src/core/review-scope.ts","../src/core/web-review-kit-app.ts"],"sourcesContent":["import type { ReviewItem } from './types';\n\nexport function getItemRouteKey(\n item: Pick<ReviewItem, 'routeKey' | 'normalizedPath'>\n) {\n return item.routeKey || normalizeRoutePath(item.normalizedPath);\n}\n\nexport function normalizeRoutePath(pathname: string) {\n const [pathWithoutQuery] = pathname.split(/[?#]/);\n const path = (pathWithoutQuery || '/').replace(/\\/index\\.html$/, '/');\n return path.startsWith('/') ? path : `/${path}`;\n}\n","import type { ReviewItemStatus, ReviewWorkflowStatus } from './types';\n\nexport const REVIEW_WORKFLOW_STATUS_OPTIONS: Array<{\n value: ReviewWorkflowStatus;\n label: string;\n}> = [\n { value: 'todo', label: '작업전' },\n { value: 'doing', label: '작업중' },\n { value: 'review', label: '검토 필요' },\n { value: 'hold', label: '보류' },\n { value: 'done', label: '완료' },\n];\n\nexport function normalizeReviewItemStatus(\n status: ReviewItemStatus | undefined\n): ReviewWorkflowStatus {\n if (status === 'resolved') return 'done';\n if (status === 'open' || !status) return 'todo';\n return status;\n}\n\nexport function matchesReviewItemStatus(\n itemStatus: ReviewItemStatus | undefined,\n queryStatus: ReviewItemStatus\n) {\n return (\n normalizeReviewItemStatus(itemStatus) === normalizeReviewItemStatus(queryStatus)\n );\n}\n","import { getItemRouteKey } from '../route';\nimport { matchesReviewItemStatus } from '../status';\nimport type {\n LocalAdapterOptions,\n ReviewItem,\n WebReviewKitAdapter,\n} from '../types';\n\nconst DEFAULT_STORAGE_KEY = 'df-web-review-kit:items';\n\nexport function localAdapter(\n options: LocalAdapterOptions = {}\n): WebReviewKitAdapter {\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const write = (items: ReviewItem[]) => {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n };\n\n const read = (): ReviewItem[] => {\n if (typeof window === 'undefined') return [];\n\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return [];\n\n try {\n const value = JSON.parse(raw);\n if (!Array.isArray(value)) return [];\n\n let changed = false;\n const items = value.flatMap((item) => {\n const normalized = normalizeStoredReviewItem(item);\n if (!normalized || normalized !== item) changed = true;\n return normalized ? [normalized] : [];\n });\n const numberedItems = ensureStoredReviewNumbers(items);\n if (numberedItems !== items) changed = true;\n\n if (changed) write(numberedItems);\n return numberedItems;\n } catch {\n return [];\n }\n };\n\n return {\n async get(id) {\n return read().find((item) => item.id === id) ?? null;\n },\n\n async list(query) {\n return read().filter((item) => {\n if (item.projectId !== query.projectId) return false;\n const queryRouteKey = query.routeKey ?? query.normalizedPath;\n if (\n queryRouteKey &&\n getItemRouteKey(item) !== queryRouteKey\n ) {\n return false;\n }\n if (query.status && !matchesReviewItemStatus(item.status, query.status)) {\n return false;\n }\n return true;\n });\n },\n\n async create(item) {\n const items = read();\n items.unshift(item);\n write(items);\n return item;\n },\n\n async update(id, patch) {\n const items = read();\n const index = items.findIndex((item) => item.id === id);\n\n if (index < 0) {\n throw new Error(`Review item not found: ${id}`);\n }\n\n const next: ReviewItem = {\n ...items[index],\n ...patch,\n id,\n createdAt: items[index].createdAt,\n updatedAt: new Date().toISOString(),\n };\n\n items[index] = next;\n write(items);\n return next;\n },\n\n async remove(id) {\n write(read().filter((item) => item.id !== id));\n },\n };\n}\n\nfunction normalizeStoredReviewItem(value: unknown): ReviewItem | undefined {\n if (!value || typeof value !== 'object') return undefined;\n\n const raw = value as Omit<ReviewItem, 'kind'> & {\n kind?: string;\n screenshot?: unknown;\n };\n const kind =\n raw.kind === 'text' ? 'note' :\n raw.kind === 'capture' ? 'area' :\n raw.kind;\n\n if (kind !== 'note' && kind !== 'area') return undefined;\n\n const { screenshot: _screenshot, ...item } = raw;\n\n if (kind === raw.kind && _screenshot === undefined) {\n return raw as ReviewItem;\n }\n\n return {\n ...item,\n kind,\n } as ReviewItem;\n}\n\nfunction ensureStoredReviewNumbers(items: ReviewItem[]) {\n const usedNumbers = new Set<number>();\n let maxNumber = 0;\n let changed = false;\n\n items.forEach((item) => {\n const number = normalizeReviewNumber(item.reviewNumber);\n if (!number) {\n changed = true;\n return;\n }\n\n if (usedNumbers.has(number)) {\n changed = true;\n return;\n }\n\n usedNumbers.add(number);\n maxNumber = Math.max(maxNumber, number);\n });\n\n if (!changed) return items;\n\n let nextNumber = maxNumber + 1;\n const assignedNumbers = new Set<number>();\n const numberById = new Map<string, number>();\n\n [...items]\n .sort((a, b) => {\n const createdOrder = a.createdAt.localeCompare(b.createdAt);\n if (createdOrder !== 0) return createdOrder;\n return a.id.localeCompare(b.id);\n })\n .forEach((item) => {\n const storedNumber = normalizeReviewNumber(item.reviewNumber);\n const reviewNumber =\n storedNumber && !assignedNumbers.has(storedNumber)\n ? storedNumber\n : nextNumber++;\n\n assignedNumbers.add(reviewNumber);\n numberById.set(item.id, reviewNumber);\n });\n\n return items.map((item) => {\n const reviewNumber = numberById.get(item.id);\n return item.reviewNumber === reviewNumber ? item : { ...item, reviewNumber };\n });\n}\n\nfunction normalizeReviewNumber(value: unknown) {\n if (typeof value !== 'number') return undefined;\n if (!Number.isInteger(value) || value < 1) return undefined;\n return value;\n}\n","import type {\n DfSheetAdapterOptions,\n ReviewItem,\n ReviewItemKind,\n ReviewItemStatus,\n WebReviewKitAdapter,\n} from '../types';\n\nexport const DF_SHEET_REVIEW_SOURCE = 'df-web-review-kit';\nconst REVIEW_METADATA_VERSION = 1;\n\ntype DfSheetIssue = {\n id: string;\n project_id: string;\n page_id?: string | null;\n title: string;\n description?: string | null;\n status?: string | null;\n priority?: string | null;\n links?: string | null;\n review_metadata?: unknown;\n created_at: string;\n updated_at?: string | null;\n};\n\ntype DfSheetApiResponse<T> = {\n success: boolean;\n data?: T;\n message?: string;\n error?: string;\n};\n\ntype ReviewMetadata = Partial<ReviewItem> & {\n source?: string;\n schema?: string;\n version?: number;\n reviewProjectId?: string;\n reviewUrl?: string;\n};\n\nexport function dfSheetAdapter(\n options: DfSheetAdapterOptions\n): WebReviewKitAdapter {\n return {\n async get(id) {\n const issue = await requestDfSheet<DfSheetIssue>(\n `/api/issues/${encodeURIComponent(id)}`,\n options\n );\n return issueToReviewItem(issue, options);\n },\n\n async list(query) {\n const params = new URLSearchParams();\n params.set('project_id', options.projectId);\n params.set('page_id', options.pageId);\n params.set('review_source', options.source ?? DF_SHEET_REVIEW_SOURCE);\n if (query.routeKey ?? query.normalizedPath) {\n params.set('review_route_key', query.routeKey ?? query.normalizedPath ?? '');\n }\n\n const issues = await requestDfSheet<DfSheetIssue[]>(\n `/api/issues?${params.toString()}`,\n options\n );\n return issues.flatMap((issue) => {\n const item = issueToReviewItem(issue, options);\n return item ? [item] : [];\n });\n },\n\n async create(item) {\n const metadata = createReviewMetadata(item, options);\n const draftDescription = buildIssueDescription(item, metadata);\n const created = await requestDfSheet<DfSheetIssue>('/api/issues', options, {\n method: 'POST',\n body: JSON.stringify({\n project_id: options.projectId,\n page_id: options.pageId,\n title: buildIssueTitle(item),\n description: draftDescription,\n type: options.issueType ?? 'task',\n types: [options.issueType ?? 'task'],\n status: 'todo',\n priority: options.priority ?? 'medium',\n links: metadata.reviewUrl ?? null,\n review_metadata: metadata,\n }),\n });\n\n const externalIssueId = created.id;\n const externalIssueUrl = buildIssueUrl(options, externalIssueId);\n const finalMetadata: ReviewMetadata = {\n ...metadata,\n externalIssueId,\n externalIssueUrl,\n reviewUrl: buildReviewUrl(item, options, externalIssueId),\n submittedAt: new Date().toISOString(),\n submitStatus: 'submitted',\n };\n\n const patched = await requestDfSheet<DfSheetIssue>(\n `/api/issues/${encodeURIComponent(externalIssueId)}`,\n options,\n {\n method: 'PATCH',\n body: JSON.stringify({\n description: buildIssueDescription(item, finalMetadata),\n links: finalMetadata.reviewUrl,\n review_metadata: finalMetadata,\n }),\n }\n );\n\n return issueToReviewItem(patched, options) ?? {\n ...item,\n id: externalIssueId,\n externalIssueId,\n externalIssueUrl,\n submittedAt: finalMetadata.submittedAt,\n submitStatus: 'submitted',\n updatedAt: finalMetadata.submittedAt ?? item.updatedAt,\n };\n },\n\n async update() {\n throw new Error('df-sheet review items are read-only in review-kit.');\n },\n\n async remove() {\n throw new Error('df-sheet review items are read-only in review-kit.');\n },\n };\n}\n\nfunction createReviewMetadata(\n item: ReviewItem,\n options: DfSheetAdapterOptions\n): ReviewMetadata {\n return {\n source: options.source ?? DF_SHEET_REVIEW_SOURCE,\n schema: DF_SHEET_REVIEW_SOURCE,\n version: REVIEW_METADATA_VERSION,\n reviewProjectId: options.reviewProjectId ?? item.projectId,\n id: item.id,\n reviewNumber: item.reviewNumber,\n projectId: item.projectId,\n routeKey: item.routeKey,\n pageUrl: item.pageUrl,\n originalUrl: item.originalUrl,\n normalizedPath: item.normalizedPath,\n scope: item.scope,\n kind: item.kind,\n title: item.title,\n comment: item.comment,\n status: item.status,\n viewport: item.viewport,\n devicePixelRatio: item.devicePixelRatio,\n scroll: item.scroll,\n anchor: item.anchor,\n marker: item.marker,\n selection: item.selection,\n createdAt: item.createdAt,\n updatedAt: item.updatedAt,\n reviewUrl: buildReviewUrl(item, options),\n };\n}\n\nfunction issueToReviewItem(\n issue: DfSheetIssue,\n options: DfSheetAdapterOptions\n): ReviewItem | null {\n const metadata = getReviewMetadata(issue);\n if (!metadata) return null;\n\n const routeKey = metadata.routeKey ?? metadata.normalizedPath ?? '/';\n const now = new Date().toISOString();\n\n return {\n id: issue.id,\n reviewNumber: metadata.reviewNumber,\n projectId:\n metadata.reviewProjectId ?? metadata.projectId ?? options.reviewProjectId ?? options.projectId,\n routeKey,\n pageUrl:\n metadata.pageUrl ??\n metadata.originalUrl ??\n toAbsoluteReviewUrl(routeKey),\n originalUrl: metadata.originalUrl,\n normalizedPath: metadata.normalizedPath ?? routeKey,\n scope: metadata.scope,\n kind: normalizeKind(metadata.kind),\n title: metadata.title ?? issue.title,\n comment: metadata.comment ?? issue.title,\n status: mapIssueStatus(issue.status ?? metadata.status),\n viewport: metadata.viewport ?? { width: 390, height: 720 },\n devicePixelRatio: metadata.devicePixelRatio,\n scroll: metadata.scroll,\n anchor: metadata.anchor,\n marker: metadata.marker,\n selection: metadata.selection,\n externalIssueId: issue.id,\n externalIssueUrl:\n metadata.externalIssueUrl ?? buildIssueUrl(options, issue.id),\n submittedAt: metadata.submittedAt ?? issue.created_at,\n submitStatus: 'submitted',\n createdAt: metadata.createdAt ?? issue.created_at ?? now,\n updatedAt: issue.updated_at ?? metadata.updatedAt ?? issue.created_at ?? now,\n };\n}\n\nfunction getReviewMetadata(issue: DfSheetIssue): ReviewMetadata | null {\n const metadata = issue.review_metadata;\n if (!metadata || typeof metadata !== 'object') return null;\n\n const value = metadata as ReviewMetadata;\n if (value.source !== DF_SHEET_REVIEW_SOURCE) return null;\n return value;\n}\n\nasync function requestDfSheet<T>(\n path: string,\n options: DfSheetAdapterOptions,\n init: RequestInit = {}\n) {\n const url = new URL(path, getDfSheetBaseUrl(options)).toString();\n const headers = new Headers(init.headers);\n headers.set('Accept', 'application/json');\n if (init.body && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json');\n }\n if (options.token) {\n headers.set('Authorization', `Bearer ${options.token}`);\n }\n\n const response = await fetch(url, {\n ...init,\n headers,\n credentials: 'include',\n });\n const json = (await response.json().catch(() => null)) as\n | DfSheetApiResponse<T>\n | null;\n\n if (!response.ok || !json?.success || json.data === undefined) {\n throw new Error(\n json?.message ?? json?.error ?? `df-sheet request failed: ${response.status}`\n );\n }\n\n return json.data;\n}\n\nfunction getDfSheetBaseUrl(options: DfSheetAdapterOptions) {\n const baseUrl = options.baseUrl?.trim();\n if (baseUrl) return baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n\n if (typeof window !== 'undefined') return window.location.origin;\n return 'http://localhost';\n}\n\nfunction buildIssueTitle(item: ReviewItem) {\n const reviewId = formatReviewItemIndexId(item);\n const idPrefix = reviewId ? `${reviewId} ` : '';\n const prefix = item.kind === 'area' ? '[Area]' : '[Note]';\n const summary = item.title || item.comment.split('\\n')[0] || 'Review item';\n return `${idPrefix}${prefix} ${summary}`.slice(0, 120);\n}\n\nfunction buildIssueDescription(item: ReviewItem, metadata: ReviewMetadata) {\n const reviewId = formatReviewItemIndexId(item);\n\n return [\n 'df-web-review-kit issue',\n '',\n reviewId ? `Review ID: ${reviewId}` : null,\n `Kind: ${item.kind}`,\n `Page: ${item.routeKey || item.normalizedPath || '/'}`,\n `Viewport: ${Math.round(item.viewport.width)}x${Math.round(item.viewport.height)}`,\n item.scroll ? `Scroll: ${Math.round(item.scroll.x)},${Math.round(item.scroll.y)}` : null,\n item.anchor?.selector ? `Selector: ${item.anchor.selector}` : null,\n item.marker?.viewport\n ? `Point: ${Math.round(item.marker.viewport.x)},${Math.round(item.marker.viewport.y)}`\n : null,\n item.selection?.viewport\n ? `Area: ${Math.round(item.selection.viewport.x)},${Math.round(item.selection.viewport.y)},${Math.round(item.selection.viewport.width)},${Math.round(item.selection.viewport.height)}`\n : null,\n metadata.reviewUrl ? `Review link: ${metadata.reviewUrl}` : null,\n '',\n 'Note:',\n item.comment,\n ]\n .filter((line): line is string => line !== null)\n .join('\\n');\n}\n\nfunction formatReviewItemIndexId(item: Pick<ReviewItem, 'id' | 'reviewNumber'>) {\n if (typeof item.reviewNumber === 'number' && item.reviewNumber > 0) {\n return `#${item.reviewNumber}`;\n }\n\n return /^\\d+$/.test(item.id) ? `#${item.id}` : undefined;\n}\n\nfunction buildReviewUrl(\n item: ReviewItem,\n options: DfSheetAdapterOptions,\n issueId?: string\n) {\n if (typeof window === 'undefined') return undefined;\n\n const prefix = options.reviewPathPrefix ?? '/review';\n const url = new URL(prefix, window.location.origin);\n url.searchParams.set('source', 'df-sheet');\n url.searchParams.set('target', item.routeKey || item.normalizedPath || '/');\n url.searchParams.set('w', String(Math.round(item.viewport.width)));\n url.searchParams.set('h', String(Math.round(item.viewport.height)));\n if (issueId) url.searchParams.set('item', issueId);\n return url.toString();\n}\n\nfunction buildIssueUrl(options: DfSheetAdapterOptions, issueId: string) {\n const path = `/projects/${options.projectId}/issues/${issueId}`;\n return options.baseUrl ? new URL(path, getDfSheetBaseUrl(options)).toString() : path;\n}\n\nfunction toAbsoluteReviewUrl(path: string) {\n if (typeof window === 'undefined') return path;\n return new URL(path, window.location.origin).toString();\n}\n\nfunction normalizeKind(value: unknown): ReviewItemKind {\n return value === 'area' ? 'area' : 'note';\n}\n\nfunction mapIssueStatus(value: unknown): ReviewItemStatus {\n if (value === 'done' || value === 'review' || value === 'todo') return value;\n if (value === 'in_progress') return 'doing';\n if (value === 'on_hold') return 'hold';\n return 'todo';\n}\n","import { normalizeReviewItemStatus } from '../status';\nimport type {\n ReviewItem,\n ReviewItemQuery,\n ReviewItemStatus,\n ReviewSource,\n SupabaseReviewAdapterOptions,\n WebReviewKitAdapter,\n} from '../types';\n\nconst DEFAULT_SUPABASE_REVIEW_TABLE = 'review_items';\nconst DEFAULT_SUPABASE_REVIEW_SOURCE = 'supabase';\nconst DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC = 'create_review_item';\n\ntype SupabaseReviewRow = {\n id: string;\n project_id: string;\n route_key: string;\n source: string;\n review_number?: number | null;\n status: string;\n item: unknown;\n created_at: string;\n updated_at: string;\n};\n\ntype SupabaseResponse<T> = {\n data: T | null;\n error: { message?: string; code?: string } | null;\n};\n\nexport function supabaseAdapter(\n options: SupabaseReviewAdapterOptions\n): WebReviewKitAdapter {\n const tableName = options.table ?? DEFAULT_SUPABASE_REVIEW_TABLE;\n const source = options.source ?? DEFAULT_SUPABASE_REVIEW_SOURCE;\n\n const fromTable = () => options.client.from(tableName);\n\n return {\n async get(id) {\n const row = await unwrapResponse<SupabaseReviewRow | null>(\n fromTable().select('*').eq('id', id).maybeSingle(),\n 'supabase get review item'\n );\n\n return row ? rowToReviewItem(row, options) : null;\n },\n\n async list(query) {\n let request = fromTable()\n .select('*')\n .eq('project_id', query.projectId)\n .eq('source', query.source ?? source);\n const routeKey = query.routeKey ?? query.normalizedPath;\n\n if (routeKey) {\n request = request.eq('route_key', routeKey);\n }\n if (query.status) {\n request = request.eq(\n 'status',\n normalizeReviewItemStatus(query.status)\n );\n }\n\n const rows = await unwrapResponse<SupabaseReviewRow[]>(\n request.order('updated_at', { ascending: false }),\n 'supabase list review items'\n );\n\n return (rows ?? []).flatMap((row) => {\n const item = rowToReviewItem(row, options);\n return item ? [item] : [];\n });\n },\n\n async create(item) {\n const nextItem = normalizeItemForSupabaseCreate(item, source, options);\n\n if (options.unsafeClientReviewNumberFallback) {\n return createItemWithClientReviewNumber(\n nextItem,\n source,\n options,\n fromTable\n );\n }\n\n return createItemWithRpc(nextItem, source, options);\n },\n\n async update(id, patch) {\n const current = await this.get(id);\n if (!current) throw new Error(`Review item not found: ${id}`);\n\n const nextStatus = patch.status\n ? normalizeReviewItemStatus(patch.status)\n : current.status;\n const nextItem: ReviewItem = {\n ...current,\n ...patch,\n id,\n status: nextStatus,\n createdAt: current.createdAt,\n updatedAt: new Date().toISOString(),\n };\n const patchRow = itemToRowPatch(nextItem, source, options);\n const updated = await unwrapResponse<SupabaseReviewRow>(\n fromTable().update(patchRow).eq('id', id).select('*').single(),\n 'supabase update review item'\n );\n\n return rowToReviewItem(updated, options) ?? nextItem;\n },\n\n async remove(id) {\n await unwrapResponse<null>(\n fromTable().delete().eq('id', id),\n 'supabase delete review item'\n );\n },\n };\n}\n\nfunction normalizeItemForSupabaseCreate(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): ReviewItem {\n const now = new Date().toISOString();\n const id = createSupabaseReviewItemId();\n const normalizedStatus = normalizeReviewItemStatus(item.status);\n const routeKey = item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const nextItem: ReviewItem = {\n ...item,\n id,\n reviewNumber: undefined,\n projectId: options.projectId,\n routeKey,\n normalizedPath: item.normalizedPath || routeKey,\n viewport,\n status: normalizedStatus,\n externalIssueId: id,\n externalIssueUrl: buildSupabaseReviewUrl(\n { routeKey, normalizedPath: item.normalizedPath || routeKey, viewport },\n source,\n options,\n id\n ),\n submittedAt: item.submittedAt ?? now,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: now,\n updatedAt: now,\n };\n\n return {\n ...nextItem,\n externalIssueUrl:\n nextItem.externalIssueUrl ??\n buildSupabaseReviewUrl(nextItem, source, options),\n };\n}\n\nasync function createItemWithRpc(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const rpcName =\n options.createRpc ?? DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC;\n\n if (!options.client.rpc) {\n throw new Error(\n `supabase create review item: ${rpcName} rpc is required`\n );\n }\n\n const row = await unwrapResponse<SupabaseReviewRow>(\n options.client.rpc(rpcName, {\n p_id: item.id,\n p_project_id: options.projectId,\n p_route_key: item.routeKey || item.normalizedPath || '/',\n p_source: source,\n p_status: normalizeReviewItemStatus(item.status),\n p_item: item,\n }),\n `supabase create review item rpc ${rpcName}`\n );\n\n return rowToReviewItem(row, options) ?? item;\n}\n\nasync function createItemWithClientReviewNumber(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions,\n fromTable: () => any\n) {\n for (let attempt = 0; attempt < 5; attempt += 1) {\n const reviewNumber = await getNextReviewNumber(\n options.projectId,\n source,\n fromTable\n );\n const nextItem: ReviewItem = { ...item, reviewNumber };\n const row = itemToRow(nextItem, source, options);\n const created = await fromTable().insert(row).select('*').single();\n\n if (!created.error) {\n return rowToReviewItem(created.data, options) ?? nextItem;\n }\n\n if (created.error.code === '23505' && attempt < 4) {\n continue;\n }\n\n throw new Error(\n `supabase create review item: ${\n created.error.message ?? created.error.code ?? 'failed'\n }`\n );\n }\n\n throw new Error('supabase create review item: failed');\n}\n\nasync function getNextReviewNumber(\n projectId: string,\n source: ReviewSource,\n fromTable: () => any\n) {\n const rows = await unwrapResponse<Array<{ review_number: number | null }>>(\n fromTable()\n .select('review_number')\n .eq('project_id', projectId)\n .eq('source', source)\n .order('review_number', { ascending: false })\n .limit(1),\n 'supabase get next review number'\n );\n const maxNumber = normalizeReviewNumber(rows?.[0]?.review_number) ?? 0;\n return maxNumber + 1;\n}\n\nfunction itemToRow(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): SupabaseReviewRow {\n const now = new Date().toISOString();\n const updatedAt = item.updatedAt || now;\n\n return {\n id: item.id,\n project_id: options.projectId,\n route_key: item.routeKey || item.normalizedPath || '/',\n source,\n review_number: item.reviewNumber ?? null,\n status: normalizeReviewItemStatus(item.status),\n item: {\n ...item,\n projectId: options.projectId,\n status: normalizeReviewItemStatus(item.status),\n updatedAt,\n },\n created_at: item.createdAt || now,\n updated_at: updatedAt,\n };\n}\n\nfunction itemToRowPatch(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const row = itemToRow(item, source, options);\n return {\n route_key: row.route_key,\n review_number: row.review_number,\n status: row.status,\n item: row.item,\n updated_at: row.updated_at,\n };\n}\n\nfunction rowToReviewItem(\n row: SupabaseReviewRow,\n options: SupabaseReviewAdapterOptions\n): ReviewItem | null {\n if (!row.item || typeof row.item !== 'object') return null;\n\n const item = row.item as Partial<ReviewItem>;\n const status = normalizeReviewItemStatus(\n (row.status || item.status || 'todo') as ReviewItemStatus\n );\n const routeKey = row.route_key || item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const now = new Date().toISOString();\n\n return {\n ...(item as ReviewItem),\n id: row.id,\n reviewNumber: row.review_number ?? item.reviewNumber,\n projectId: row.project_id || item.projectId || options.projectId,\n routeKey,\n pageUrl: item.pageUrl || toAbsoluteReviewUrl(routeKey),\n normalizedPath: item.normalizedPath || routeKey,\n kind: item.kind === 'area' ? 'area' : 'note',\n comment: item.comment || '',\n status,\n viewport,\n externalIssueId: item.externalIssueId ?? row.id,\n externalIssueUrl:\n item.externalIssueUrl ??\n buildSupabaseReviewUrl(\n { routeKey, normalizedPath: routeKey, viewport },\n row.source,\n options,\n row.id\n ),\n submittedAt: item.submittedAt ?? row.created_at,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: item.createdAt ?? row.created_at ?? now,\n updatedAt: row.updated_at ?? item.updatedAt ?? now,\n };\n}\n\nasync function unwrapResponse<T>(\n request: Promise<SupabaseResponse<T>> | SupabaseResponse<T>,\n label: string\n) {\n const { data, error } = await request;\n if (error) {\n throw new Error(`${label}: ${error.message ?? error.code ?? 'failed'}`);\n }\n return data as T;\n}\n\nfunction buildSupabaseReviewUrl(\n item: Pick<ReviewItem, 'routeKey' | 'normalizedPath' | 'viewport'>,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions,\n itemId?: string\n) {\n if (typeof window === 'undefined') return undefined;\n\n const prefix = options.reviewPathPrefix ?? '/review';\n const url = new URL(prefix, window.location.origin);\n url.searchParams.set('source', source);\n url.searchParams.set('target', item.routeKey || item.normalizedPath || '/');\n url.searchParams.set('w', String(Math.round(item.viewport.width)));\n url.searchParams.set('h', String(Math.round(item.viewport.height)));\n if (itemId) url.searchParams.set('item', itemId);\n return url.toString();\n}\n\nfunction toAbsoluteReviewUrl(path: string) {\n if (typeof window === 'undefined') return path;\n return new URL(path, window.location.origin).toString();\n}\n\nfunction normalizeReviewNumber(value: unknown) {\n if (typeof value !== 'number') return undefined;\n if (!Number.isInteger(value) || value < 1) return undefined;\n return value;\n}\n\nfunction createSupabaseReviewItemId() {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return `review-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n","export function createStyleElement() {\n const style = document.createElement('style');\n style.textContent = `\n :host {\n color-scheme: dark;\n --df-review-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n --df-review-font-size-2xs: 10px;\n --df-review-font-size-xs: 11px;\n --df-review-font-size-sm: 12px;\n --df-review-font-size-md: 13px;\n --df-review-font-size-xl: 15px;\n --df-review-space-1: 4px;\n --df-review-space-1-5: 6px;\n --df-review-space-2: 8px;\n --df-review-space-2-5: 10px;\n --df-review-space-3: 12px;\n --df-review-space-3-5: 14px;\n --df-review-space-4: 16px;\n --df-review-control-height-sm: 32px;\n --df-review-control-height-md: 34px;\n --df-review-radius-xs: 3px;\n --df-review-radius-sm: 6px;\n --df-review-radius-md: 8px;\n --df-review-radius-pill: 999px;\n --df-review-color-canvas: #111820;\n --df-review-color-panel: #1f2428;\n --df-review-color-panel-strong: #15191d;\n --df-review-color-control: #2c3338;\n --df-review-color-control-hover: #3b444b;\n --df-review-color-border: rgba(255, 255, 255, 0.14);\n --df-review-color-border-strong: rgba(255, 255, 255, 0.18);\n --df-review-color-text: #f7f7f2;\n --df-review-color-text-muted: rgba(247, 247, 242, 0.62);\n --df-review-color-text-subtle: rgba(247, 247, 242, 0.46);\n --df-review-color-accent: #d7ff5f;\n --df-review-color-accent-contrast: #171b1e;\n --df-review-color-accent-soft: rgba(215, 255, 95, 0.16);\n --df-review-color-accent-ring: rgba(215, 255, 95, 0.6);\n --df-review-color-area: #63d7c7;\n --df-review-color-error: #ffb7a7;\n --df-review-shadow-panel: 0 18px 48px rgba(0, 0, 0, 0.34);\n --df-review-shadow-popover: 0 16px 38px rgba(0, 0, 0, 0.32);\n --df-review-shadow-highlight: 0 10px 30px rgba(0, 0, 0, 0.22);\n font-family: var(--df-review-font-sans);\n }\n\n * {\n box-sizing: border-box;\n }\n\n .dfwr-shell {\n display: none;\n position: fixed;\n inset: 0;\n z-index: 500;\n pointer-events: none;\n }\n\n .dfwr-shell.is-open {\n display: block;\n }\n\n .dfwr-panel {\n position: fixed;\n right: 16px;\n top: 16px;\n z-index: 3;\n width: min(380px, calc(100vw - 32px));\n max-height: calc(100vh - 32px);\n overflow: auto;\n pointer-events: auto;\n color: var(--df-review-color-text);\n background: var(--df-review-color-panel);\n border: 1px solid var(--df-review-color-border);\n border-radius: var(--df-review-radius-md);\n box-shadow: var(--df-review-shadow-panel);\n }\n\n .dfwr-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 14px 10px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n }\n\n .dfwr-title {\n font-size: 15px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .dfwr-meta {\n max-width: 292px;\n margin-top: 4px;\n overflow: hidden;\n color: rgba(247, 247, 242, 0.56);\n font-size: var(--df-review-font-size-xs);\n line-height: 1.35;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .dfwr-toolbar,\n .dfwr-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 12px 14px;\n }\n\n .dfwr-body,\n .dfwr-list {\n padding: 0 14px 14px;\n }\n\n .dfwr-list {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n padding-top: 12px;\n }\n\n .dfwr-button,\n .dfwr-icon-button {\n appearance: none;\n border: 1px solid var(--df-review-color-border-strong);\n background: var(--df-review-color-control);\n color: var(--df-review-color-text);\n cursor: pointer;\n font: inherit;\n }\n\n .dfwr-button {\n min-height: var(--df-review-control-height-md);\n padding: 0 12px;\n border-radius: var(--df-review-radius-sm);\n font-size: var(--df-review-font-size-sm);\n font-weight: 650;\n }\n\n .dfwr-button:hover,\n .dfwr-icon-button:hover,\n .dfwr-button.is-active {\n border-color: rgba(255, 255, 255, 0.4);\n background: var(--df-review-color-control-hover);\n }\n\n .dfwr-button.is-primary {\n border-color: var(--df-review-color-accent);\n background: var(--df-review-color-accent);\n color: var(--df-review-color-accent-contrast);\n }\n\n .dfwr-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: var(--df-review-control-height-sm);\n padding: 0 8px;\n border-radius: var(--df-review-radius-sm);\n font-size: var(--df-review-font-size-xs);\n font-weight: 700;\n line-height: 1;\n text-transform: uppercase;\n }\n\n .dfwr-marker-layer {\n position: fixed;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n }\n\n .dfwr-area-preview-layer {\n position: fixed;\n inset: 0;\n z-index: 3;\n pointer-events: none;\n }\n\n .dfwr-selection-highlight {\n position: fixed;\n z-index: 1;\n border: 2px solid #d7ff5f;\n border-radius: var(--df-review-radius-xs);\n background: rgba(215, 255, 95, 0.08);\n box-shadow:\n 0 0 0 1px rgba(31, 36, 40, 0.72),\n 0 0 0 9999px rgba(0, 0, 0, 0.12),\n 0 10px 30px rgba(0, 0, 0, 0.22);\n animation: dfwr-selection-pulse 900ms ease 0s 2;\n }\n\n .dfwr-selection-highlight.is-draft {\n border-color: #63d7c7;\n background: rgba(99, 215, 199, 0.1);\n box-shadow:\n 0 0 0 1px rgba(31, 36, 40, 0.72),\n 0 0 0 9999px rgba(0, 0, 0, 0.08),\n 0 10px 30px rgba(0, 0, 0, 0.2);\n animation: none;\n }\n\n .dfwr-dom-hover {\n position: fixed;\n z-index: 2;\n border: 1px solid #d7ff5f;\n border-radius: var(--df-review-radius-xs);\n background: rgba(215, 255, 95, 0.1);\n box-shadow:\n 0 0 0 1px rgba(31, 36, 40, 0.72),\n 0 0 0 9999px rgba(0, 0, 0, 0.08);\n pointer-events: none;\n }\n\n .dfwr-dom-hover[hidden] {\n display: none;\n }\n\n .dfwr-bound-marker,\n .dfwr-item-scope {\n --dfwr-scope: #7cc7ff;\n --dfwr-scope-rgb: 124, 199, 255;\n }\n\n .dfwr-bound-marker.is-scope-tablet,\n .dfwr-item-scope.is-scope-tablet {\n --dfwr-scope: #63d7c7;\n --dfwr-scope-rgb: 99, 215, 199;\n }\n\n .dfwr-bound-marker.is-scope-desktop,\n .dfwr-item-scope.is-scope-desktop {\n --dfwr-scope: #f3b75f;\n --dfwr-scope-rgb: 243, 183, 95;\n }\n\n .dfwr-bound-marker.is-scope-wide,\n .dfwr-item-scope.is-scope-wide {\n --dfwr-scope: #c99cff;\n --dfwr-scope-rgb: 201, 156, 255;\n }\n\n .dfwr-bound-marker.is-scope-dom,\n .dfwr-item-scope.is-scope-dom {\n --dfwr-scope: #ff8f61;\n --dfwr-scope-rgb: 255, 143, 97;\n }\n\n .dfwr-item-target-highlight,\n .dfwr-item-target-label {\n --dfwr-item-color: #7cc7ff;\n --dfwr-item-color-rgb: 124, 199, 255;\n }\n\n .dfwr-item-target-highlight.is-mode-area,\n .dfwr-item-target-label.is-mode-area {\n --dfwr-item-color: #63d7c7;\n --dfwr-item-color-rgb: 99, 215, 199;\n }\n\n .dfwr-item-target-highlight.is-mode-dom,\n .dfwr-item-target-label.is-mode-dom {\n --dfwr-item-color: #ff8f61;\n --dfwr-item-color-rgb: 255, 143, 97;\n }\n\n .dfwr-item-target-highlight {\n position: fixed;\n z-index: 2;\n border: 2px solid var(--dfwr-item-color);\n border-radius: 4px;\n background: rgba(var(--dfwr-item-color-rgb), 0.08);\n box-shadow:\n 0 0 0 1px rgba(31, 36, 40, 0.78),\n 0 0 0 9999px rgba(0, 0, 0, 0.08),\n 0 12px 30px rgba(0, 0, 0, 0.24);\n pointer-events: none;\n }\n\n .dfwr-item-target-highlight.is-fallback {\n border-style: dashed;\n }\n\n .dfwr-item-target-highlight.is-highlighted {\n border-width: 3px;\n background: rgba(var(--dfwr-item-color-rgb), 0.12);\n }\n\n .dfwr-item-target-highlight.is-highlighted::after {\n content: \"\";\n position: absolute;\n inset: -6px;\n border: 2px solid var(--dfwr-item-color);\n border-radius: var(--df-review-radius-md);\n opacity: 0;\n animation: dfwr-target-ring-blink 1000ms ease-in-out infinite;\n pointer-events: none;\n }\n\n .dfwr-item-target-label {\n position: fixed;\n z-index: 3;\n display: inline-flex;\n align-items: center;\n min-width: 24px;\n height: 20px;\n padding: 0 7px;\n border: 1px solid var(--dfwr-item-color);\n border-radius: 4px;\n background: var(--dfwr-item-color);\n box-shadow:\n 0 0 0 3px rgba(var(--dfwr-item-color-rgb), 0.2),\n 0 8px 18px rgba(0, 0, 0, 0.28);\n color: #111820;\n font-size: var(--df-review-font-size-2xs);\n font-weight: 900;\n line-height: 1;\n pointer-events: none;\n }\n\n .dfwr-item-target-label.is-highlighted {\n animation: dfwr-selected-blink 1000ms ease-in-out infinite;\n }\n\n .dfwr-bound-marker {\n position: fixed;\n z-index: 2;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n min-width: 28px;\n height: 22px;\n padding: 0 6px;\n transform: translate(-50%, -50%);\n border: 1px solid var(--dfwr-scope);\n border-radius: var(--df-review-radius-pill);\n background: var(--df-review-color-panel);\n box-shadow: 0 0 0 4px rgba(var(--dfwr-scope-rgb), 0.18);\n color: var(--dfwr-scope);\n font-size: var(--df-review-font-size-2xs);\n font-weight: 800;\n }\n\n .dfwr-bound-marker.is-highlighted {\n min-width: 32px;\n height: 26px;\n border-width: 2px;\n box-shadow:\n 0 0 0 5px rgba(var(--dfwr-scope-rgb), 0.22),\n 0 12px 26px rgba(0, 0, 0, 0.34);\n animation: dfwr-selected-blink 1000ms ease-in-out infinite;\n }\n\n .dfwr-bound-marker.is-fallback {\n border-style: dashed;\n }\n\n .dfwr-bound-marker.is-note-callout,\n .dfwr-bound-marker.is-note-callout.is-highlighted {\n --dfwr-scope: #7cc7ff;\n --dfwr-scope-rgb: 124, 199, 255;\n min-width: 0;\n width: 0;\n height: 0;\n padding: 0;\n transform: none;\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n color: var(--dfwr-scope);\n animation: none;\n overflow: visible;\n }\n\n .dfwr-bound-marker.is-note-callout::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 0;\n width: 8px;\n height: 8px;\n transform: translate(-50%, -50%);\n border: 2px solid #111820;\n border-radius: var(--df-review-radius-pill);\n background: var(--dfwr-scope);\n box-shadow:\n 0 0 0 3px rgba(var(--dfwr-scope-rgb), 0.22),\n 0 6px 16px rgba(0, 0, 0, 0.28);\n }\n\n .dfwr-bound-marker.is-note-callout.is-highlighted::before {\n animation: dfwr-note-dot-pulse 1000ms ease-in-out infinite;\n }\n\n .dfwr-bound-marker.is-note-callout .dfwr-bound-marker-icon {\n position: absolute;\n left: 0;\n top: 0;\n width: 31px;\n height: 2px;\n transform: rotate(-42deg);\n transform-origin: left center;\n border-radius: var(--df-review-radius-pill);\n background: currentColor;\n opacity: 1;\n }\n\n .dfwr-bound-marker.is-note-callout .dfwr-bound-marker-icon::before,\n .dfwr-bound-marker.is-note-callout .dfwr-bound-marker-icon::after {\n display: none;\n }\n\n .dfwr-bound-marker.is-note-callout .dfwr-bound-marker-number {\n position: absolute;\n left: 24px;\n top: -41px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 20px;\n padding: 0 7px;\n border: 1px solid var(--dfwr-scope);\n border-radius: 4px;\n background: var(--dfwr-scope);\n box-shadow:\n 0 0 0 3px rgba(var(--dfwr-scope-rgb), 0.18),\n 0 8px 18px rgba(0, 0, 0, 0.28);\n color: #111820;\n text-align: center;\n line-height: 1;\n white-space: nowrap;\n }\n\n .dfwr-bound-marker.is-note-callout.is-highlighted .dfwr-bound-marker-icon,\n .dfwr-bound-marker.is-note-callout.is-highlighted .dfwr-bound-marker-number {\n animation: dfwr-selected-blink 1000ms ease-in-out infinite;\n }\n\n .dfwr-area-preview-layer .dfwr-bound-marker {\n border-color: #63d7c7;\n background: var(--df-review-color-panel);\n box-shadow:\n 0 0 0 5px rgba(99, 215, 199, 0.2),\n 0 12px 26px rgba(0, 0, 0, 0.3);\n color: #63d7c7;\n }\n\n .dfwr-bound-marker-icon {\n position: relative;\n display: inline-block;\n width: 10px;\n height: 10px;\n flex: 0 0 auto;\n }\n\n .dfwr-bound-marker-icon::before,\n .dfwr-bound-marker-icon::after {\n content: \"\";\n position: absolute;\n display: block;\n }\n\n .dfwr-bound-marker-icon::before {\n inset: 1px 2px;\n border: 1.5px solid currentColor;\n border-radius: 2px;\n }\n\n .dfwr-bound-marker.is-scope-mobile .dfwr-bound-marker-icon::before {\n inset: 0 2.5px;\n border-radius: 2px;\n }\n\n .dfwr-bound-marker.is-scope-tablet .dfwr-bound-marker-icon::before {\n inset: 0.5px 1.5px;\n border-radius: 2px;\n }\n\n .dfwr-bound-marker.is-scope-desktop .dfwr-bound-marker-icon::before {\n inset: 1px 0 3px;\n border-radius: 1px;\n }\n\n .dfwr-bound-marker.is-scope-desktop .dfwr-bound-marker-icon::after {\n left: 3px;\n right: 3px;\n bottom: 0;\n height: 1.5px;\n background: currentColor;\n }\n\n .dfwr-bound-marker.is-scope-wide .dfwr-bound-marker-icon::before {\n inset: 2px 0;\n border-radius: 1px;\n }\n\n .dfwr-bound-marker.is-scope-dom .dfwr-bound-marker-icon::before {\n inset: 2px;\n border-radius: 1px;\n transform: rotate(45deg);\n }\n\n .dfwr-bound-marker-number {\n min-width: 6px;\n text-align: center;\n line-height: 1;\n }\n\n .dfwr-note-draft {\n position: fixed;\n inset: 0;\n z-index: 4;\n pointer-events: none;\n }\n\n .dfwr-note-pin {\n appearance: none;\n position: fixed;\n z-index: 5;\n width: 18px;\n height: 18px;\n padding: 0;\n transform: translate(-50%, -50%);\n border: 2px solid #1f2428;\n border-radius: var(--df-review-radius-pill);\n background: var(--df-review-color-accent);\n box-shadow:\n 0 0 0 4px rgba(215, 255, 95, 0.22),\n 0 8px 18px rgba(0, 0, 0, 0.28);\n cursor: grab;\n pointer-events: auto;\n }\n\n .dfwr-note-pin:active {\n cursor: grabbing;\n }\n\n .dfwr-note-popover {\n position: fixed;\n z-index: 4;\n width: min(320px, calc(100vw - 24px));\n padding: 12px;\n pointer-events: auto;\n color: var(--df-review-color-text);\n background: var(--df-review-color-panel);\n border: 1px solid rgba(215, 255, 95, 0.56);\n border-radius: var(--df-review-radius-md);\n box-shadow: var(--df-review-shadow-popover);\n }\n\n .dfwr-area-draft {\n position: fixed;\n right: 16px;\n top: 16px;\n z-index: 4;\n width: min(360px, calc(100vw - 32px));\n max-height: calc(100vh - 32px);\n overflow: auto;\n padding: 12px;\n pointer-events: auto;\n color: var(--df-review-color-text);\n background: var(--df-review-color-panel);\n border: 1px solid rgba(215, 255, 95, 0.56);\n border-radius: var(--df-review-radius-md);\n box-shadow: var(--df-review-shadow-popover);\n }\n\n .dfwr-note-popover .dfwr-actions {\n padding: 0;\n }\n\n .dfwr-area-draft .dfwr-actions {\n padding: 0;\n }\n\n .dfwr-form {\n display: grid;\n gap: 10px;\n }\n\n .dfwr-textarea {\n width: 100%;\n min-height: 92px;\n resize: vertical;\n border: 1px solid rgba(255, 255, 255, 0.16);\n border-radius: var(--df-review-radius-sm);\n padding: 10px;\n color: var(--df-review-color-text);\n background: var(--df-review-color-panel-strong);\n font: inherit;\n font-size: var(--df-review-font-size-md);\n line-height: 1.45;\n }\n\n .dfwr-textarea:focus {\n outline: 2px solid var(--df-review-color-accent-ring);\n outline-offset: 1px;\n }\n\n .dfwr-empty,\n .dfwr-error {\n margin: 0;\n color: rgba(247, 247, 242, 0.62);\n font-size: var(--df-review-font-size-sm);\n line-height: 1.45;\n }\n\n .dfwr-error {\n color: var(--df-review-color-error);\n }\n\n .dfwr-preview,\n .dfwr-thumb {\n display: block;\n width: 100%;\n border: 1px solid var(--df-review-color-border);\n border-radius: var(--df-review-radius-sm);\n object-fit: cover;\n background: var(--df-review-color-canvas);\n }\n\n .dfwr-preview {\n max-height: 180px;\n }\n\n .dfwr-thumb {\n max-height: 120px;\n margin-top: 10px;\n }\n\n .dfwr-list-heading {\n margin-bottom: 10px;\n color: rgba(247, 247, 242, 0.74);\n font-size: var(--df-review-font-size-sm);\n font-weight: 700;\n }\n\n .dfwr-item {\n display: flex;\n gap: 12px;\n justify-content: space-between;\n padding: 12px 0;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n cursor: pointer;\n }\n\n .dfwr-item:first-of-type {\n border-top: 0;\n }\n\n .dfwr-item:focus-visible {\n outline: 2px solid rgba(215, 255, 95, 0.72);\n outline-offset: 4px;\n }\n\n .dfwr-item-body {\n min-width: 0;\n flex: 1;\n }\n\n .dfwr-item-badges {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n }\n\n .dfwr-item-scope,\n .dfwr-item-kind {\n display: inline-flex;\n align-items: center;\n min-height: 20px;\n border-radius: var(--df-review-radius-pill);\n padding: 0 7px;\n font-size: var(--df-review-font-size-2xs);\n font-weight: 800;\n line-height: 1;\n letter-spacing: 0;\n text-transform: uppercase;\n }\n\n .dfwr-item-scope {\n border: 1px solid rgba(var(--dfwr-scope-rgb), 0.38);\n background: rgba(var(--dfwr-scope-rgb), 0.12);\n color: var(--dfwr-scope);\n }\n\n .dfwr-item-kind {\n border: 1px solid rgba(255, 255, 255, 0.12);\n background: rgba(255, 255, 255, 0.05);\n color: rgba(247, 247, 242, 0.64);\n }\n\n .dfwr-item-comment {\n margin: 4px 0;\n color: var(--df-review-color-text);\n font-size: var(--df-review-font-size-md);\n line-height: 1.42;\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n }\n\n .dfwr-item-date {\n color: rgba(247, 247, 242, 0.46);\n font-size: var(--df-review-font-size-xs);\n }\n\n .dfwr-item-actions {\n display: flex;\n flex-direction: column;\n gap: 6px;\n flex: 0 0 auto;\n }\n\n .dfwr-text-layer,\n .dfwr-element-layer,\n .dfwr-area-layer {\n position: fixed;\n inset: 0;\n z-index: 1;\n pointer-events: auto;\n }\n\n .dfwr-text-layer {\n cursor: crosshair;\n background: rgba(0, 0, 0, 0.06);\n }\n\n .dfwr-element-layer {\n cursor: cell;\n background: rgba(0, 0, 0, 0.06);\n }\n\n .dfwr-area-layer {\n cursor: crosshair;\n background: rgba(0, 0, 0, 0.22);\n }\n\n .dfwr-area-box {\n position: fixed;\n z-index: 2;\n width: 0;\n height: 0;\n border: 1px solid #d7ff5f;\n background: rgba(215, 255, 95, 0.16);\n box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.18);\n }\n\n @keyframes dfwr-marker-pulse {\n 0% {\n transform: translate(-50%, -50%) scale(0.92);\n }\n 45% {\n transform: translate(-50%, -50%) scale(1.1);\n }\n 100% {\n transform: translate(-50%, -50%) scale(1);\n }\n }\n\n @keyframes dfwr-note-dot-pulse {\n 0% {\n transform: translate(-50%, -50%) scale(0.88);\n }\n 45% {\n transform: translate(-50%, -50%) scale(1.3);\n }\n 100% {\n transform: translate(-50%, -50%) scale(1);\n }\n }\n\n @keyframes dfwr-selected-blink {\n 0%,\n 100% {\n opacity: 0.78;\n }\n 50% {\n opacity: 1;\n }\n }\n\n @keyframes dfwr-target-ring-blink {\n 0%,\n 100% {\n opacity: 0;\n transform: scale(0.98);\n }\n 50% {\n opacity: 0.82;\n transform: scale(1);\n }\n }\n\n @keyframes dfwr-selection-pulse {\n 0% {\n opacity: 0.72;\n }\n 45% {\n opacity: 1;\n }\n 100% {\n opacity: 0.86;\n }\n }\n\n @media (max-width: 520px) {\n .dfwr-panel {\n right: 8px;\n top: 8px;\n width: calc(100vw - 16px);\n max-height: calc(100vh - 16px);\n }\n }\n `;\n return style;\n}\n","import type {\n NumberedReviewItem,\n ReviewItem,\n ReviewItemScope,\n ReviewViewportPreset,\n ViewportSize,\n} from '../types';\n\nexport const DEFAULT_REVIEW_VIEWPORTS: ReviewViewportPreset[] = [\n { label: 'Mobile', width: 390, height: 720, scope: 'mobile' },\n { label: 'Tablet', width: 768, height: 1024, scope: 'tablet' },\n { label: 'Desktop', width: 1440, height: 900, scope: 'desktop' },\n { label: 'Wide', width: 1980, height: 1080, scope: 'wide' },\n];\n\nconst REVIEW_SCOPE_LABELS: Record<ReviewItemScope, string> = {\n mobile: 'Mobile',\n tablet: 'Tablet',\n desktop: 'Desktop',\n wide: 'Wide',\n dom: 'Element',\n};\n\nconst normalizeReviewItemScope = (value: unknown): ReviewItemScope | undefined => {\n if (value === 'element') return 'dom';\n if (\n value === 'mobile' ||\n value === 'tablet' ||\n value === 'desktop' ||\n value === 'wide' ||\n value === 'dom'\n ) {\n return value;\n }\n\n return undefined;\n};\n\nconst getViewportPresetDistance = (\n preset: ReviewViewportPreset,\n viewport: ViewportSize\n) =>\n Math.abs(preset.width - viewport.width) +\n Math.abs(preset.height - viewport.height);\n\nconst inferViewportScope = (\n preset: ReviewViewportPreset\n): Exclude<ReviewItemScope, 'dom'> => {\n if (preset.scope) return preset.scope;\n\n const label = preset.label.toLowerCase();\n\n if (label.includes('mobile') || label.includes('phone')) return 'mobile';\n if (label.includes('tablet') || label.includes('pad')) return 'tablet';\n if (\n label.includes('wide') ||\n label.includes('1980') ||\n label.includes('1940') ||\n label.includes('1920')\n ) {\n return 'wide';\n }\n if (label.includes('desktop')) return 'desktop';\n if (preset.width >= 1800) return 'wide';\n if (preset.width >= 1000) return 'desktop';\n if (preset.width >= 700) return 'tablet';\n return 'mobile';\n};\n\nexport function findReviewViewportPreset(\n viewport: ViewportSize,\n presets: ReviewViewportPreset[] = DEFAULT_REVIEW_VIEWPORTS\n) {\n const fallback = presets[0] ?? DEFAULT_REVIEW_VIEWPORTS[0];\n const exact = presets.find(\n (preset) =>\n preset.width === viewport.width && preset.height === viewport.height\n );\n\n if (exact) return exact;\n\n return presets.reduce((closest, preset) => {\n const closestDistance = getViewportPresetDistance(closest, viewport);\n const presetDistance = getViewportPresetDistance(preset, viewport);\n return presetDistance < closestDistance ? preset : closest;\n }, fallback);\n}\n\nexport function getReviewViewportScope(\n viewport: ViewportSize,\n presets: ReviewViewportPreset[] = DEFAULT_REVIEW_VIEWPORTS\n): Exclude<ReviewItemScope, 'dom'> {\n return inferViewportScope(findReviewViewportPreset(viewport, presets));\n}\n\nexport function getReviewItemScope(\n item: ReviewItem,\n presets: ReviewViewportPreset[] = DEFAULT_REVIEW_VIEWPORTS\n): ReviewItemScope {\n const scope = normalizeReviewItemScope(item.scope);\n if (scope && scope !== 'dom') return scope;\n return getReviewViewportScope(item.viewport, presets);\n}\n\nexport function getReviewItemScopeLabel(\n item: ReviewItem,\n presets: ReviewViewportPreset[] = DEFAULT_REVIEW_VIEWPORTS\n) {\n const scope = getReviewItemScope(item, presets);\n if (scope === 'dom') return REVIEW_SCOPE_LABELS.dom;\n\n const preset = findReviewViewportPreset(item.viewport, presets);\n return preset.label || REVIEW_SCOPE_LABELS[scope];\n}\n\nexport function getNumberedReviewItems(\n items: ReviewItem[],\n presets: ReviewViewportPreset[] = DEFAULT_REVIEW_VIEWPORTS\n): NumberedReviewItem[] {\n const numbers = new Map<string, number>();\n const usedNumbers = new Set<number>();\n let nextNumber = getNextReviewItemNumber(items);\n\n [...items]\n .sort((a, b) => {\n const createdOrder = a.createdAt.localeCompare(b.createdAt);\n if (createdOrder !== 0) return createdOrder;\n return a.id.localeCompare(b.id);\n })\n .forEach((item) => {\n const storedNumber = getReviewItemNumber(item);\n const number =\n storedNumber && !usedNumbers.has(storedNumber)\n ? storedNumber\n : nextNumber++;\n\n usedNumbers.add(number);\n numbers.set(item.id, number);\n });\n\n return items.map((item) => {\n const scope = getReviewItemScope(item, presets);\n const label = getReviewItemScopeLabel(item, presets);\n const number = numbers.get(item.id) ?? 0;\n\n return {\n item,\n scope,\n label,\n number,\n displayLabel: `#${number}`,\n };\n });\n}\n\nexport function getReviewItemNumber(item: Pick<ReviewItem, 'reviewNumber'>) {\n return normalizeReviewNumber(item.reviewNumber);\n}\n\nexport function getNextReviewItemNumber(\n items: Array<Pick<ReviewItem, 'reviewNumber'>>\n) {\n const maxNumber = items.reduce((max, item) => {\n const number = getReviewItemNumber(item);\n return number ? Math.max(max, number) : max;\n }, 0);\n\n return maxNumber + 1;\n}\n\nfunction normalizeReviewNumber(value: unknown) {\n if (typeof value !== 'number') return undefined;\n if (!Number.isInteger(value) || value < 1) return undefined;\n return value;\n}\n","import { localAdapter } from '../adapters/local';\nimport { normalizeRoutePath } from '../route';\nimport type {\n DomAnchor,\n DomAnchorCandidate,\n DomSourceHint,\n NumberedReviewItem,\n RelativeSelection,\n ReviewItem,\n ReviewItemScope,\n ReviewMarker,\n ReviewMode,\n ReviewPoint,\n ReviewSelection,\n ViewportSize,\n WebReviewKitAdapter,\n WebReviewKitController,\n WebReviewKitOptions,\n} from '../types';\nimport { createStyleElement } from './overlay-style';\nimport {\n getNextReviewItemNumber,\n getNumberedReviewItems,\n getReviewViewportScope,\n} from './review-scope';\n\ninterface ViewportSelection {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\ninterface AreaDraft {\n viewport: ViewportSize;\n anchor?: DomAnchor;\n marker?: ReviewMarker;\n selection?: ReviewSelection;\n}\n\ninterface NoteDraft {\n viewport: ViewportSize;\n anchor?: DomAnchor;\n marker: ReviewMarker;\n selection?: ReviewSelection;\n comment?: string;\n}\n\ninterface ReviewEnvironment {\n window: Window;\n document: Document;\n viewportRect: {\n left: number;\n top: number;\n width: number;\n height: number;\n };\n overlayRect: {\n left: number;\n top: number;\n width: number;\n height: number;\n };\n}\n\ntype ReviewItemHighlightMode = 'note' | 'area' | 'dom';\ninterface ReviewItemHighlightSelection {\n viewport: ViewportSelection;\n isBound: boolean;\n}\n\nconst ROOT_ID = 'df-web-review-kit-root';\nconst INTERNAL_QUERY_PARAMS = ['__dfwr_target'];\nexport function createWebReviewKit(\n options: WebReviewKitOptions\n): WebReviewKitController {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return createNoopController();\n }\n\n const app = new WebReviewKitApp(options);\n app.mount();\n\n return {\n open: () => app.open(),\n close: () => app.close(),\n toggle: () => app.toggle(),\n setMode: (mode) => app.setMode(mode),\n getMode: () => app.getMode(),\n highlightItem: (itemId) => app.highlightItem(itemId),\n setHiddenItemIds: (itemIds) => app.setHiddenItemIds(itemIds),\n reload: () => app.reload(),\n getItems: () => app.getItems(),\n destroy: () => app.destroy(),\n };\n}\n\nclass WebReviewKitApp {\n private readonly adapter: WebReviewKitAdapter;\n private readonly hotkey: string;\n private root?: HTMLDivElement;\n private shadow?: ShadowRoot;\n private panel?: HTMLDivElement;\n private isOpen = false;\n private mode: ReviewMode = 'idle';\n private items: ReviewItem[] = [];\n private noteDraft?: NoteDraft;\n private areaDraft?: AreaDraft;\n private isSelectingArea = false;\n private highlightedItemId?: string;\n private hiddenItemIds?: Set<string>;\n private renderFrame?: number;\n\n constructor(private readonly options: WebReviewKitOptions) {\n this.adapter = options.adapter ?? localAdapter();\n this.hotkey = options.hotkeys?.qa ?? 'Shift+Q';\n }\n\n mount() {\n if (this.root) return;\n\n const existing = document.getElementById(ROOT_ID);\n if (existing) existing.remove();\n\n this.root = document.createElement('div');\n this.root.id = ROOT_ID;\n this.root.style.display = 'contents';\n\n this.shadow = this.root.attachShadow({ mode: 'open' });\n document.body.appendChild(this.root);\n document.addEventListener('keydown', this.handleKeyDown, true);\n window.addEventListener('scroll', this.handleViewportChange, true);\n window.addEventListener('resize', this.handleViewportChange);\n\n this.render();\n }\n\n destroy() {\n document.removeEventListener('keydown', this.handleKeyDown, true);\n window.removeEventListener('scroll', this.handleViewportChange, true);\n window.removeEventListener('resize', this.handleViewportChange);\n if (this.renderFrame) {\n window.cancelAnimationFrame(this.renderFrame);\n this.renderFrame = undefined;\n }\n this.root?.remove();\n this.root = undefined;\n this.shadow = undefined;\n }\n\n open() {\n if (this.isOpen) return;\n\n this.isOpen = true;\n void this.reload();\n }\n\n close() {\n this.isOpen = false;\n this.setModeState('idle');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.isSelectingArea = false;\n this.render();\n }\n\n toggle() {\n if (this.isOpen) {\n this.close();\n return;\n }\n\n this.open();\n }\n\n setMode(mode: ReviewMode) {\n if (!this.isOpen) {\n this.isOpen = true;\n }\n\n this.setModeState(this.mode === mode ? 'idle' : mode);\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.render();\n }\n\n getMode() {\n return this.mode;\n }\n\n getItems() {\n return this.items;\n }\n\n highlightItem(itemId?: string) {\n if (!itemId) {\n this.clearHighlightedItem();\n return;\n }\n\n if (!this.isOpen) {\n this.isOpen = true;\n }\n\n this.highlightedItemId = itemId;\n this.render();\n }\n\n setHiddenItemIds(itemIds?: string[]) {\n this.hiddenItemIds = itemIds ? new Set(itemIds) : undefined;\n this.updateHiddenItemsStyle();\n }\n\n private clearHighlightedItem() {\n if (!this.highlightedItemId) return;\n\n this.highlightedItemId = undefined;\n this.render();\n }\n\n private createHiddenItemsStyleElement() {\n const style = document.createElement('style');\n style.dataset.dfwrHiddenItems = 'true';\n style.textContent = this.getHiddenItemsCss();\n return style;\n }\n\n private updateHiddenItemsStyle() {\n if (!this.shadow) return;\n\n let style = this.shadow.querySelector<HTMLStyleElement>(\n 'style[data-dfwr-hidden-items=\"true\"]'\n );\n if (!style) {\n style = this.createHiddenItemsStyleElement();\n this.shadow.prepend(style);\n return;\n }\n\n style.textContent = this.getHiddenItemsCss();\n }\n\n private getHiddenItemsCss() {\n if (!this.hiddenItemIds?.size) return '';\n\n return Array.from(this.hiddenItemIds)\n .map(\n (itemId) =>\n `[data-review-item-id=\"${cssEscape(itemId)}\"] { display: none !important; }`\n )\n .join('\\n');\n }\n\n private setModeState(mode: ReviewMode) {\n if (this.mode === mode) return;\n\n this.mode = mode;\n this.options.onModeChange?.(mode);\n }\n\n private cancelMode() {\n if (\n this.mode === 'idle' &&\n !this.noteDraft &&\n !this.areaDraft &&\n !this.isSelectingArea\n ) {\n return false;\n }\n\n this.setModeState('idle');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.isSelectingArea = false;\n this.render();\n return true;\n }\n\n private readonly handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && this.cancelMode()) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (!isHotkey(event, this.hotkey)) return;\n\n event.preventDefault();\n event.stopPropagation();\n this.toggle();\n };\n\n private readonly handleViewportChange = () => {\n if (!this.isOpen || this.renderFrame) return;\n\n this.renderFrame = window.requestAnimationFrame(() => {\n this.renderFrame = undefined;\n this.render();\n });\n };\n\n private getEnvironment(): ReviewEnvironment | undefined {\n const target =\n typeof this.options.target === 'function'\n ? this.options.target()\n : this.options.target;\n\n if (!target) {\n return {\n window,\n document,\n viewportRect: {\n left: 0,\n top: 0,\n width: window.innerWidth,\n height: window.innerHeight,\n },\n overlayRect: {\n left: 0,\n top: 0,\n width: window.innerWidth,\n height: window.innerHeight,\n },\n };\n }\n\n try {\n const rect = target.getViewportRect?.() ?? {\n left: 0,\n top: 0,\n width: target.window.innerWidth,\n height: target.window.innerHeight,\n };\n const overlayRect = target.getOverlayRect?.() ?? rect;\n\n return {\n window: target.window,\n document: target.document,\n viewportRect: {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n },\n overlayRect: {\n left: overlayRect.left,\n top: overlayRect.top,\n width: overlayRect.width,\n height: overlayRect.height,\n },\n };\n } catch {\n return undefined;\n }\n }\n\n async reload() {\n const environment = this.getEnvironment();\n if (!environment) return this.items;\n\n this.items = await this.adapter.list({\n projectId: this.options.projectId,\n routeKey: getRouteKey(environment),\n });\n this.options.onItemsChange?.(this.items);\n if (this.isOpen) {\n this.render();\n }\n return this.items;\n }\n\n private render() {\n if (!this.shadow) return;\n\n this.shadow.replaceChildren();\n this.shadow.append(createStyleElement());\n this.shadow.append(this.createHiddenItemsStyleElement());\n\n const shell = document.createElement('div');\n shell.className = `dfwr-shell${this.isOpen ? ' is-open' : ''}`;\n shell.setAttribute('aria-hidden', this.isOpen ? 'false' : 'true');\n\n if (this.options.ui?.panel !== false) {\n this.panel = document.createElement('div');\n this.panel.className = 'dfwr-panel';\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'Web review kit');\n\n this.panel.append(\n this.createHeader(),\n this.createToolbar(),\n this.createBody(),\n this.createList()\n );\n\n shell.append(this.panel);\n } else {\n this.panel = undefined;\n }\n\n shell.append(this.createMarkerLayer());\n\n if (this.isOpen && (this.mode === 'note' || this.mode === 'element')) {\n shell.append(\n this.noteDraft\n ? this.createNotePopover(this.noteDraft)\n : this.mode === 'element'\n ? this.createElementLayer()\n : this.createNoteLayer()\n );\n }\n\n if (this.isOpen && this.mode === 'area' && !this.areaDraft) {\n shell.append(this.createAreaLayer());\n }\n\n if (\n this.isOpen &&\n this.mode === 'area' &&\n this.areaDraft &&\n this.options.ui?.panel === false\n ) {\n if (this.areaDraft.selection) {\n shell.append(this.createAreaDraftOverlay(this.areaDraft));\n }\n shell.append(this.createAreaDraftPopover(this.areaDraft));\n }\n\n this.shadow.append(shell);\n }\n\n private createHeader() {\n const header = document.createElement('div');\n header.className = 'dfwr-header';\n\n const title = document.createElement('div');\n title.className = 'dfwr-title';\n title.textContent = 'Review Kit';\n\n const meta = document.createElement('div');\n meta.className = 'dfwr-meta';\n meta.textContent = getRouteKey(this.getEnvironment());\n\n const titleGroup = document.createElement('div');\n titleGroup.append(title, meta);\n\n const close = document.createElement('button');\n close.className = 'dfwr-icon-button';\n close.type = 'button';\n close.textContent = 'x';\n close.setAttribute('aria-label', 'Close');\n close.addEventListener('click', () => this.close());\n\n header.append(titleGroup, close);\n return header;\n }\n\n private createToolbar() {\n const toolbar = document.createElement('div');\n toolbar.className = 'dfwr-toolbar';\n\n toolbar.append(\n this.createToolbarButton('Note', this.mode === 'note', () => {\n this.setModeState(this.mode === 'note' ? 'idle' : 'note');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.render();\n }),\n this.createToolbarButton('Element', this.mode === 'element', () => {\n this.setModeState(this.mode === 'element' ? 'idle' : 'element');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.render();\n }),\n this.createToolbarButton(\n this.isSelectingArea ? 'Selecting' : 'Area',\n this.mode === 'area',\n () => {\n this.setModeState(this.mode === 'area' ? 'idle' : 'area');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.render();\n }\n ),\n this.createToolbarButton('Refresh', false, () => {\n void this.reload();\n })\n );\n\n return toolbar;\n }\n\n private createToolbarButton(\n label: string,\n active: boolean,\n onClick: () => void\n ) {\n const button = document.createElement('button');\n button.className = `dfwr-button${active ? ' is-active' : ''}`;\n button.type = 'button';\n button.textContent = label;\n button.addEventListener('click', onClick);\n return button;\n }\n\n private createBody() {\n const body = document.createElement('div');\n body.className = 'dfwr-body';\n\n if (this.mode === 'idle') {\n const empty = document.createElement('p');\n empty.className = 'dfwr-empty';\n empty.textContent = 'Add a note or mark an area.';\n body.append(empty);\n return body;\n }\n\n if (this.mode === 'note' || this.mode === 'element') {\n body.append(this.createNoteBody());\n return body;\n }\n\n body.append(this.createAreaForm());\n return body;\n }\n\n private createNoteBody() {\n const empty = document.createElement('p');\n empty.className = 'dfwr-empty';\n empty.textContent = this.noteDraft\n ? 'Write the note in the page box.'\n : this.mode === 'element'\n ? 'Click an element to add QA.'\n : 'Click on the page to place a note.';\n return empty;\n }\n\n private createNotePopover(draft: NoteDraft) {\n const environment = this.getEnvironment();\n const group = document.createElement('div');\n group.className = 'dfwr-note-draft';\n if (!environment) return group;\n\n const hostPoint = toHostPoint(draft.marker.viewport, environment);\n\n if (draft.selection) {\n group.append(\n this.createSelectionHighlight(\n toViewportSelection(draft.selection.viewport),\n environment,\n true\n )\n );\n }\n\n const pin = document.createElement('button');\n pin.className = 'dfwr-note-pin';\n pin.type = 'button';\n pin.setAttribute('aria-label', 'Move note point');\n pin.style.left = `${hostPoint.x}px`;\n pin.style.top = `${hostPoint.y}px`;\n\n const popover = document.createElement('div');\n const position = getPopoverPosition(hostPoint, environment);\n\n popover.className = 'dfwr-note-popover';\n popover.style.left = `${position.left}px`;\n popover.style.top = `${position.top}px`;\n\n const form = document.createElement('form');\n form.className = 'dfwr-form';\n\n const meta = document.createElement('div');\n meta.className = 'dfwr-item-date';\n meta.textContent = formatNoteDraftMeta(draft);\n\n const textarea = document.createElement('textarea');\n textarea.className = 'dfwr-textarea';\n textarea.placeholder = 'Review comment';\n textarea.rows = 4;\n textarea.value = draft.comment ?? '';\n textarea.addEventListener('input', () => {\n if (!this.noteDraft) return;\n this.noteDraft = {\n ...this.noteDraft,\n comment: textarea.value,\n };\n });\n\n const actions = this.createFormActions('Save note', () => {\n const comment = textarea.value.trim();\n if (!comment) return;\n void this.createItem({\n kind: 'note',\n comment,\n viewport: draft.viewport,\n anchor: draft.anchor,\n marker: draft.marker,\n selection: draft.selection,\n });\n });\n\n form.append(meta, textarea, actions);\n popover.append(form);\n group.append(pin, popover);\n\n this.attachDraftPinDrag(pin, popover, meta, textarea);\n\n window.setTimeout(() => textarea.focus(), 0);\n\n return group;\n }\n\n private createAreaForm() {\n const form = document.createElement('form');\n form.className = 'dfwr-form';\n\n if (!this.areaDraft) {\n const empty = document.createElement('p');\n empty.className = 'dfwr-empty';\n empty.textContent = 'Drag on the page to select an area.';\n form.append(empty);\n return form;\n }\n\n const meta = document.createElement('div');\n meta.className = 'dfwr-item-date';\n meta.textContent = formatAreaDraftMeta(this.areaDraft);\n form.append(meta);\n\n const textarea = document.createElement('textarea');\n textarea.className = 'dfwr-textarea';\n textarea.placeholder = 'Area comment';\n textarea.rows = 4;\n\n const actions = this.createFormActions('Save area', () => {\n const comment = textarea.value.trim();\n if (!comment || !this.areaDraft) return;\n void this.createItem({\n kind: 'area',\n comment,\n viewport: this.areaDraft.viewport,\n anchor: this.areaDraft.anchor,\n marker: this.areaDraft.marker,\n selection: this.areaDraft.selection,\n });\n });\n\n form.append(textarea, actions);\n return form;\n }\n\n private createAreaDraftOverlay(draft: AreaDraft) {\n const layer = document.createElement('div');\n layer.className = 'dfwr-area-preview-layer';\n\n const environment = this.getEnvironment();\n if (!environment || !draft.selection) return layer;\n\n const selection = toViewportSelection(draft.selection.viewport);\n layer.append(this.createSelectionHighlight(selection, environment, true));\n\n if (draft.marker) {\n const hostPoint = toHostPoint(draft.marker.viewport, environment);\n layer.append(\n this.createMarkerElement(\n undefined,\n hostPoint,\n '•',\n getReviewViewportScope(\n draft.viewport,\n this.options.viewports?.presets\n ),\n true,\n true\n )\n );\n }\n\n return layer;\n }\n\n private createAreaDraftPopover(draft: AreaDraft) {\n const environment = this.getEnvironment();\n const popover = document.createElement('div');\n popover.className = 'dfwr-area-draft';\n if (environment && draft.selection) {\n const selection = toHostSelection(\n toViewportSelection(draft.selection.viewport),\n environment\n );\n const position = getAreaPopoverPosition(selection, environment);\n popover.style.left = `${position.left}px`;\n popover.style.top = `${position.top}px`;\n popover.style.right = 'auto';\n }\n popover.append(this.createAreaForm());\n return popover;\n }\n\n private createFormActions(saveLabel: string, onSave: () => void) {\n const actions = document.createElement('div');\n actions.className = 'dfwr-actions';\n\n const save = document.createElement('button');\n save.className = 'dfwr-button is-primary';\n save.type = 'button';\n save.textContent = saveLabel;\n save.addEventListener('click', onSave);\n\n const cancel = document.createElement('button');\n cancel.className = 'dfwr-button';\n cancel.type = 'button';\n cancel.textContent = 'Cancel';\n cancel.addEventListener('click', () => {\n this.setModeState('idle');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.render();\n });\n\n actions.append(save, cancel);\n return actions;\n }\n\n private createList() {\n const section = document.createElement('div');\n section.className = 'dfwr-list';\n\n const heading = document.createElement('div');\n heading.className = 'dfwr-list-heading';\n heading.textContent = `Review items (${this.items.length})`;\n section.append(heading);\n\n if (this.items.length === 0) {\n const empty = document.createElement('p');\n empty.className = 'dfwr-empty';\n empty.textContent = 'No review items on this page.';\n section.append(empty);\n return section;\n }\n\n for (const numberedItem of getNumberedReviewItems(\n this.items,\n this.options.viewports?.presets\n )) {\n section.append(this.createListItem(numberedItem));\n }\n\n return section;\n }\n\n private createListItem(numberedItem: NumberedReviewItem) {\n const { item } = numberedItem;\n const row = document.createElement('article');\n row.className = 'dfwr-item';\n row.tabIndex = 0;\n row.setAttribute('role', 'button');\n row.setAttribute(\n 'aria-label',\n `Restore review item: ${item.title ?? item.comment}`\n );\n row.addEventListener('click', () => {\n void this.restoreItem(item);\n });\n row.addEventListener('keydown', (event) => {\n if (event.key !== 'Enter' && event.key !== ' ') return;\n\n event.preventDefault();\n void this.restoreItem(item);\n });\n\n const body = document.createElement('div');\n body.className = 'dfwr-item-body';\n\n const badges = document.createElement('div');\n badges.className = 'dfwr-item-badges';\n\n const scope = document.createElement('div');\n scope.className = `dfwr-item-scope is-scope-${numberedItem.scope}`;\n scope.textContent = numberedItem.displayLabel;\n\n const kind = document.createElement('div');\n kind.className = 'dfwr-item-kind';\n kind.textContent = item.kind;\n badges.append(scope, kind);\n\n const comment = document.createElement('p');\n comment.className = 'dfwr-item-comment';\n comment.textContent = item.comment;\n\n const date = document.createElement('time');\n date.className = 'dfwr-item-date';\n date.dateTime = item.createdAt;\n date.textContent = formatItemMeta(item);\n\n body.append(badges, comment, date);\n\n const actions = document.createElement('div');\n actions.className = 'dfwr-item-actions';\n actions.addEventListener('click', (event) => event.stopPropagation());\n actions.addEventListener('keydown', (event) => event.stopPropagation());\n\n const remove = document.createElement('button');\n remove.className = 'dfwr-icon-button';\n remove.type = 'button';\n remove.textContent = 'x';\n remove.setAttribute('aria-label', 'Delete');\n remove.addEventListener('click', (event) => {\n event.stopPropagation();\n void this.adapter\n .remove(item.id)\n .then(() => this.reload());\n });\n\n actions.append(remove);\n row.append(body, actions);\n return row;\n }\n\n private createMarkerLayer() {\n const layer = document.createElement('div');\n layer.className = 'dfwr-marker-layer';\n const environment = this.getEnvironment();\n if (!environment) return layer;\n\n const currentScope = getReviewViewportScope(\n getViewportSize(environment),\n this.options.viewports?.presets\n );\n\n getNumberedReviewItems(\n this.items,\n this.options.viewports?.presets\n ).forEach((numberedItem) => {\n const { item, scope, number, displayLabel } = numberedItem;\n if (!shouldShowMarkerForScope(scope, currentScope)) {\n return;\n }\n\n const isHighlighted = item.id === this.highlightedItemId;\n const highlightMode = getReviewItemHighlightMode(item);\n if (highlightMode !== 'note') {\n const selection = getItemHighlightSelection(item, environment);\n if (selection) {\n layer.append(\n ...this.createItemHighlightElements(\n selection.viewport,\n environment,\n item,\n String(number),\n selection.isBound,\n isHighlighted\n )\n );\n return;\n }\n }\n\n const point = getBoundMarkerPoint(item, environment);\n if (!point || !isPointInViewport(point.viewport, environment)) {\n return;\n }\n\n const hostPoint = toHostPoint(point.viewport, environment);\n const marker = this.createMarkerElement(\n item.id,\n hostPoint,\n String(number),\n scope,\n point.isBound,\n isHighlighted,\n highlightMode === 'note' ? 'note' : 'default'\n );\n marker.title = `${displayLabel} / ${item.comment}\\n${formatItemMeta(item)}`;\n layer.append(marker);\n });\n\n return layer;\n }\n\n private createItemHighlightElements(\n selection: ViewportSelection,\n environment: ReviewEnvironment,\n item: ReviewItem,\n label: string,\n isBound: boolean,\n isHighlighted: boolean\n ) {\n const rect = toHostSelection(selection, environment);\n const mode = getReviewItemHighlightMode(item);\n const highlight = document.createElement('div');\n highlight.className = [\n 'dfwr-item-target-highlight',\n `is-mode-${mode}`,\n isBound ? 'is-bound' : 'is-fallback',\n isHighlighted ? 'is-highlighted' : '',\n ]\n .filter(Boolean)\n .join(' ');\n highlight.style.left = `${rect.left}px`;\n highlight.style.top = `${rect.top}px`;\n highlight.style.width = `${rect.width}px`;\n highlight.style.height = `${rect.height}px`;\n highlight.dataset.reviewItemId = item.id;\n\n const labelElement = document.createElement('div');\n labelElement.className = [\n 'dfwr-item-target-label',\n `is-mode-${mode}`,\n isHighlighted ? 'is-highlighted' : '',\n ]\n .filter(Boolean)\n .join(' ');\n labelElement.textContent = `#${label}`;\n labelElement.style.left = `${Math.max(4, rect.left)}px`;\n labelElement.style.top = `${Math.max(4, rect.top - 24)}px`;\n labelElement.dataset.reviewItemId = item.id;\n\n return [highlight, labelElement];\n }\n\n private createSelectionHighlight(\n selection: ViewportSelection,\n environment: ReviewEnvironment,\n isDraft: boolean\n ) {\n const rect = toHostSelection(selection, environment);\n const highlight = document.createElement('div');\n highlight.className = `dfwr-selection-highlight${\n isDraft ? ' is-draft' : ''\n }`;\n highlight.style.left = `${rect.left}px`;\n highlight.style.top = `${rect.top}px`;\n highlight.style.width = `${rect.width}px`;\n highlight.style.height = `${rect.height}px`;\n return highlight;\n }\n\n private createMarkerElement(\n itemId: string | undefined,\n hostPoint: ReviewPoint,\n label: string,\n scope: ReviewItemScope,\n isBound: boolean,\n isHighlighted: boolean,\n variant: 'default' | 'note' = 'default'\n ) {\n const isNoteCallout = variant === 'note';\n const marker = document.createElement('div');\n marker.className = [\n 'dfwr-bound-marker',\n isNoteCallout ? 'is-note-callout' : '',\n `is-scope-${scope}`,\n isBound ? 'is-bound' : 'is-fallback',\n isHighlighted ? 'is-highlighted' : '',\n ]\n .filter(Boolean)\n .join(' ');\n marker.style.left = `${hostPoint.x}px`;\n marker.style.top = `${hostPoint.y}px`;\n marker.dataset.scope = scope;\n if (itemId) {\n marker.dataset.reviewItemId = itemId;\n }\n\n const iconElement = document.createElement('span');\n iconElement.className = 'dfwr-bound-marker-icon';\n iconElement.setAttribute('aria-hidden', 'true');\n const labelElement = document.createElement('span');\n labelElement.className = 'dfwr-bound-marker-number';\n labelElement.textContent = isNoteCallout ? `#${label}` : label;\n marker.append(iconElement, labelElement);\n\n return marker;\n }\n\n private attachDraftPinDrag(\n pin: HTMLButtonElement,\n popover: HTMLDivElement,\n meta: HTMLDivElement,\n textarea: HTMLTextAreaElement\n ) {\n let isDragging = false;\n\n const moveDraftUi = (hostPoint: ReviewPoint) => {\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const nextPoint = clampPoint(toTargetPoint(hostPoint, environment), environment);\n const nextHostPoint = toHostPoint(nextPoint, environment);\n const position = getPopoverPosition(nextHostPoint, environment);\n\n pin.style.left = `${nextHostPoint.x}px`;\n pin.style.top = `${nextHostPoint.y}px`;\n popover.style.left = `${position.left}px`;\n popover.style.top = `${position.top}px`;\n\n if (!this.noteDraft) return;\n\n this.noteDraft = {\n ...this.noteDraft,\n marker: {\n ...this.noteDraft.marker,\n viewport: roundPoint(nextPoint),\n },\n comment: textarea.value,\n };\n meta.textContent = formatNoteDraftMeta(this.noteDraft);\n };\n\n pin.addEventListener('pointerdown', (event) => {\n if (event.button !== 0) return;\n\n event.preventDefault();\n event.stopPropagation();\n isDragging = true;\n pin.setPointerCapture(event.pointerId);\n });\n\n pin.addEventListener('pointermove', (event) => {\n if (!isDragging || !pin.hasPointerCapture(event.pointerId)) return;\n\n event.preventDefault();\n moveDraftUi({\n x: event.clientX,\n y: event.clientY,\n });\n });\n\n pin.addEventListener('pointerup', (event) => {\n if (!isDragging || !pin.hasPointerCapture(event.pointerId)) return;\n\n event.preventDefault();\n event.stopPropagation();\n isDragging = false;\n pin.releasePointerCapture(event.pointerId);\n\n const nextPoint = toTargetPointFromHostEvent(event, this.getEnvironment());\n void (this.mode === 'element'\n ? this.bindElementDraftToPoint(nextPoint, textarea.value)\n : this.bindNoteDraftToPoint(nextPoint, textarea.value));\n });\n }\n\n private createNoteLayer() {\n const layer = document.createElement('div');\n layer.className = 'dfwr-text-layer';\n const environment = this.getEnvironment();\n\n if (environment) {\n placeLayerOverTarget(layer, environment);\n }\n\n layer.addEventListener('pointerdown', (event) => {\n if (event.button !== 0) return;\n event.preventDefault();\n void this.createNoteDraft(\n toTargetPointFromHostEvent(event, this.getEnvironment())\n );\n });\n\n return layer;\n }\n\n private createElementLayer() {\n const layer = document.createElement('div');\n layer.className = 'dfwr-element-layer';\n const environment = this.getEnvironment();\n const hover = document.createElement('div');\n hover.className = 'dfwr-dom-hover';\n hover.hidden = true;\n layer.append(hover);\n\n if (environment) {\n placeLayerOverTarget(layer, environment);\n }\n\n const updateHover = (point: ReviewPoint) => {\n const nextEnvironment = this.getEnvironment();\n if (!nextEnvironment) return;\n\n const anchor = getDomAnchorFromPoint(\n clampPoint(point, nextEnvironment),\n this.options.anchors?.attribute,\n nextEnvironment\n );\n const selection = anchor\n ? getElementViewportSelection(anchor, nextEnvironment)\n : undefined;\n\n if (!selection) {\n hover.hidden = true;\n return;\n }\n\n const rect = toHostSelection(selection, nextEnvironment);\n hover.hidden = false;\n hover.style.left = `${rect.left}px`;\n hover.style.top = `${rect.top}px`;\n hover.style.width = `${rect.width}px`;\n hover.style.height = `${rect.height}px`;\n };\n\n layer.addEventListener('pointermove', (event) => {\n updateHover(toTargetPointFromHostEvent(event, this.getEnvironment()));\n });\n\n layer.addEventListener('pointerleave', () => {\n hover.hidden = true;\n });\n\n layer.addEventListener('pointerdown', (event) => {\n if (event.button !== 0) return;\n event.preventDefault();\n void this.createElementDraft(\n toTargetPointFromHostEvent(event, this.getEnvironment())\n );\n });\n\n return layer;\n }\n\n private async createNoteDraft(point: ReviewPoint) {\n await this.bindNoteDraftToPoint(point);\n }\n\n private async createElementDraft(point: ReviewPoint) {\n await this.bindElementDraftToPoint(point);\n }\n\n private async bindNoteDraftToPoint(point: ReviewPoint, comment?: string) {\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const viewport = getViewportSize(environment);\n const nextPoint = clampPoint(point, environment);\n\n const draft = await this.withOverlayHidden(() => {\n const selection = getPointSelection(nextPoint);\n const anchor = getDomAnchor(\n selection,\n this.options.anchors?.attribute,\n environment\n );\n const marker: ReviewMarker = {\n viewport: roundPoint(nextPoint),\n relative: anchor\n ? getRelativePoint(nextPoint, anchor, environment)\n : undefined,\n };\n\n return {\n viewport,\n anchor,\n marker,\n comment,\n };\n });\n\n this.noteDraft = draft;\n this.render();\n }\n\n private async bindElementDraftToPoint(point: ReviewPoint, comment?: string) {\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const viewport = getViewportSize(environment);\n const nextPoint = clampPoint(point, environment);\n\n const draft = await this.withOverlayHidden(() => {\n const anchor = getDomAnchorFromPoint(\n nextPoint,\n this.options.anchors?.attribute,\n environment\n );\n const elementSelection = anchor\n ? getElementViewportSelection(anchor, environment)\n : undefined;\n const selection = elementSelection ?? getPointSelection(nextPoint);\n const markerPoint = getSelectionCenter(selection);\n const reviewSelection = elementSelection\n ? {\n viewport: toPublicSelection(elementSelection),\n relative: getRelativeSelection(\n elementSelection,\n anchor as DomAnchor,\n environment\n ),\n }\n : undefined;\n const marker: ReviewMarker = {\n viewport: roundPoint(markerPoint),\n relative: anchor\n ? getRelativePoint(markerPoint, anchor, environment)\n : undefined,\n };\n\n return {\n viewport,\n anchor,\n marker,\n selection: reviewSelection,\n comment,\n };\n });\n\n this.noteDraft = draft;\n this.render();\n }\n\n private createAreaLayer() {\n const layer = document.createElement('div');\n layer.className = 'dfwr-area-layer';\n const environment = this.getEnvironment();\n\n if (environment) {\n placeLayerOverTarget(layer, environment);\n }\n\n const box = document.createElement('div');\n box.className = 'dfwr-area-box';\n layer.append(box);\n\n let startX = 0;\n let startY = 0;\n let selection: ViewportSelection | undefined;\n\n const updateBox = (event: PointerEvent) => {\n const nextPoint = toTargetPointFromHostEvent(\n event,\n this.getEnvironment()\n );\n const left = Math.min(startX, nextPoint.x);\n const top = Math.min(startY, nextPoint.y);\n const width = Math.abs(nextPoint.x - startX);\n const height = Math.abs(nextPoint.y - startY);\n const hostPoint = toHostPoint(\n { x: left, y: top },\n this.getEnvironment()\n );\n\n selection = { left, top, width, height };\n box.style.left = `${hostPoint.x}px`;\n box.style.top = `${hostPoint.y}px`;\n box.style.width = `${width}px`;\n box.style.height = `${height}px`;\n };\n\n layer.addEventListener('pointerdown', (event) => {\n event.preventDefault();\n layer.setPointerCapture(event.pointerId);\n const startPoint = toTargetPointFromHostEvent(\n event,\n this.getEnvironment()\n );\n startX = startPoint.x;\n startY = startPoint.y;\n updateBox(event);\n });\n\n layer.addEventListener('pointermove', (event) => {\n if (!layer.hasPointerCapture(event.pointerId)) return;\n updateBox(event);\n });\n\n layer.addEventListener('pointerup', (event) => {\n if (!layer.hasPointerCapture(event.pointerId)) return;\n layer.releasePointerCapture(event.pointerId);\n updateBox(event);\n\n if (!selection || selection.width < 8 || selection.height < 8) return;\n\n this.isSelectingArea = true;\n this.render();\n void this.createAreaDraft(selection);\n });\n\n return layer;\n }\n\n private async createAreaDraft(selection: ViewportSelection) {\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const viewport = getViewportSize(environment);\n\n this.areaDraft = await this.withOverlayHidden(() => {\n const anchor = getDomAnchor(\n selection,\n this.options.anchors?.attribute,\n environment\n );\n const relativeSelection = anchor\n ? getRelativeSelection(selection, anchor, environment)\n : undefined;\n const marker = createSelectionCenterMarker(\n selection,\n anchor,\n environment\n );\n const reviewSelection: ReviewSelection = {\n viewport: toPublicSelection(selection),\n relative: relativeSelection,\n };\n\n return {\n viewport,\n anchor,\n marker,\n selection: reviewSelection,\n };\n });\n this.isSelectingArea = false;\n this.setModeState('area');\n this.render();\n }\n\n private async withOverlayHidden<T>(callback: () => Promise<T> | T) {\n if (!this.root) return callback();\n\n const previousDisplay = this.root.style.display;\n this.root.style.display = 'none';\n\n try {\n return await callback();\n } finally {\n this.root.style.display = previousDisplay;\n }\n }\n\n private async createItem(\n input: Pick<ReviewItem, 'kind' | 'comment'> &\n Partial<\n Pick<ReviewItem, 'scope' | 'viewport' | 'anchor' | 'marker' | 'selection'>\n >\n ) {\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const now = new Date().toISOString();\n const routeKey = getRouteKey(environment);\n const viewport = input.viewport ?? getViewportSize(environment);\n const reviewNumber = await this.getNextReviewNumber();\n const item: ReviewItem = {\n id: createId(),\n reviewNumber,\n projectId: this.options.projectId,\n routeKey,\n pageUrl: getPageUrl(environment),\n originalUrl: getOriginalUrl(environment),\n normalizedPath: routeKey,\n scope:\n input.scope ??\n getReviewViewportScope(viewport, this.options.viewports?.presets),\n kind: input.kind,\n title: input.comment.split('\\n')[0]?.slice(0, 80),\n comment: input.comment,\n status: 'todo',\n viewport,\n devicePixelRatio: environment.window.devicePixelRatio || 1,\n scroll: {\n x: environment.window.scrollX,\n y: environment.window.scrollY,\n },\n anchor: input.anchor,\n marker: input.marker,\n selection: input.selection,\n createdAt: now,\n updatedAt: now,\n };\n\n await this.adapter.create(item);\n this.setModeState('idle');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n this.highlightItem(item.id);\n await this.reload();\n }\n\n private async getNextReviewNumber() {\n const items = await this.adapter.list({\n projectId: this.options.projectId,\n });\n return getNextReviewItemNumber(items);\n }\n\n private async restoreItem(item: ReviewItem) {\n this.setModeState('idle');\n this.noteDraft = undefined;\n this.areaDraft = undefined;\n\n if (this.options.onRestoreItem) {\n await this.options.onRestoreItem(item);\n return;\n }\n\n const environment = this.getEnvironment();\n if (!environment) return;\n\n const scroll = item.scroll;\n if (scroll) {\n runWithAutoScrollBehavior(environment.document, () => {\n setDocumentScrollInstantly(environment, scroll);\n });\n await waitForNextFrame(environment);\n }\n\n this.highlightItem(item.id);\n this.render();\n }\n}\n\nfunction rectanglesIntersect(\n a: ViewportSelection,\n b: ViewportSelection\n) {\n return (\n a.left < b.left + b.width &&\n a.left + a.width > b.left &&\n a.top < b.top + b.height &&\n a.top + a.height > b.top\n );\n}\n\nfunction waitForNextFrame(environment?: ReviewEnvironment) {\n return new Promise<void>((resolve) => {\n (environment?.window ?? window).requestAnimationFrame(() => resolve());\n });\n}\n\nfunction getDomAnchor(\n selection: ViewportSelection,\n configuredAttribute = 'data-qa-id',\n environment: ReviewEnvironment\n): DomAnchor | undefined {\n const x = selection.left + selection.width / 2;\n const y = selection.top + selection.height / 2;\n return getDomAnchorFromPoint({ x, y }, configuredAttribute, environment);\n}\n\nfunction getDomAnchorFromPoint(\n point: ReviewPoint,\n configuredAttribute = 'data-qa-id',\n environment: ReviewEnvironment\n): DomAnchor | undefined {\n const target = environment.document.elementFromPoint(point.x, point.y);\n if (!target) return undefined;\n\n const candidates = createAnchorCandidates(target, configuredAttribute);\n const primary = candidates[0];\n if (!primary) return undefined;\n\n return {\n ...primary,\n candidates,\n htmlSnippet: getElementHtmlSnippet(\n getAnchorSourceElement(target, primary, configuredAttribute) ?? target\n ),\n source: getDomSourceHint(target),\n };\n}\n\nfunction getElementViewportSelection(\n anchor: DomAnchor,\n environment: ReviewEnvironment\n): ViewportSelection | undefined {\n const element = getAnchorElement(anchor, environment);\n if (!element) return undefined;\n\n const rect = element.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return undefined;\n\n return {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n };\n}\n\nfunction createAnchorCandidates(\n target: Element,\n configuredAttribute: string\n): DomAnchorCandidate[] {\n const candidates: DomAnchorCandidate[] = [];\n\n const anchoredByAttribute = target.closest(`[${configuredAttribute}]`);\n if (anchoredByAttribute) {\n const value = anchoredByAttribute.getAttribute(configuredAttribute);\n if (value) {\n candidates.push({\n selector: `[${configuredAttribute}=\"${cssEscape(value)}\"]`,\n strategy: 'configured-attribute',\n confidence: 0.98,\n textFingerprint: getTextFingerprint(anchoredByAttribute),\n });\n }\n }\n\n if (isMeaningfulId(target.id)) {\n candidates.push({\n selector: `#${cssEscape(target.id)}`,\n strategy: 'id',\n confidence: 0.94,\n textFingerprint: getTextFingerprint(target),\n });\n }\n\n const targetClassName = getMeaningfulClassName(target);\n if (targetClassName) {\n candidates.push({\n selector: `${target.tagName.toLowerCase()}.${cssEscape(targetClassName)}`,\n strategy: 'class',\n confidence: 0.82,\n textFingerprint: getTextFingerprint(target),\n });\n }\n\n candidates.push({\n selector: getDomPath(target),\n strategy: 'dom-path',\n confidence: 0.9,\n textFingerprint: getTextFingerprint(target),\n });\n\n const parent = target.parentElement;\n const anchoredById = parent\n ? findClosest(parent, (element) => isMeaningfulId(element.id))\n : undefined;\n if (anchoredById?.id) {\n candidates.push({\n selector: `#${cssEscape(anchoredById.id)}`,\n strategy: 'id',\n confidence: 0.72,\n textFingerprint: getTextFingerprint(anchoredById),\n });\n }\n\n const anchoredByClass = parent\n ? findClosest(parent, (element) => Boolean(getMeaningfulClassName(element)))\n : undefined;\n const className = anchoredByClass\n ? getMeaningfulClassName(anchoredByClass)\n : undefined;\n\n if (anchoredByClass && className) {\n candidates.push({\n selector: `${anchoredByClass.tagName.toLowerCase()}.${cssEscape(\n className\n )}`,\n strategy: 'class',\n confidence: 0.58,\n textFingerprint: getTextFingerprint(anchoredByClass),\n });\n }\n\n return dedupeAnchorCandidates(candidates);\n}\n\nfunction getAnchorSourceElement(\n target: Element,\n candidate: DomAnchorCandidate,\n configuredAttribute: string\n) {\n if (candidate.strategy === 'configured-attribute') {\n return target.closest(`[${configuredAttribute}]`);\n }\n\n if (candidate.strategy === 'dom-path') return target;\n\n try {\n return target.closest(candidate.selector);\n } catch {\n return target;\n }\n}\n\nfunction getElementHtmlSnippet(element: Element, maxLength = 1000) {\n const html = decodeHtmlEntities(element.outerHTML.replace(/\\s+/g, ' ').trim());\n if (html.length <= maxLength) return html;\n return `${html.slice(0, maxLength - 3)}...`;\n}\n\nfunction decodeHtmlEntities(value: string) {\n return value.replace(\n /&(#\\d+|#x[\\da-f]+|lt|gt|quot|apos|amp);/gi,\n (match, entity: string) => {\n const normalized = entity.toLowerCase();\n\n if (normalized === 'lt') return '<';\n if (normalized === 'gt') return '>';\n if (normalized === 'quot') return '\"';\n if (normalized === 'apos') return \"'\";\n if (normalized === 'amp') return '&';\n\n const codePoint = normalized.startsWith('#x')\n ? Number.parseInt(normalized.slice(2), 16)\n : Number.parseInt(normalized.slice(1), 10);\n\n return Number.isFinite(codePoint)\n ? String.fromCodePoint(codePoint)\n : match;\n }\n );\n}\n\nfunction getDomSourceHint(target: Element): DomSourceHint | undefined {\n const sourceElement = target.closest(\n '[data-file], [data-component], [data-section-index], [data-section-id]'\n );\n if (!sourceElement) return undefined;\n\n const dataset = (sourceElement as HTMLElement).dataset;\n const source: DomSourceHint = {\n component: dataset.component,\n file: dataset.file,\n sectionId: dataset.sectionId,\n sectionIndex: dataset.sectionIndex,\n };\n\n return Object.values(source).some(Boolean) ? source : undefined;\n}\n\nfunction getRelativeSelection(\n selection: ViewportSelection,\n anchor: DomAnchor | string,\n environment: ReviewEnvironment\n): RelativeSelection | undefined {\n const element = getAnchorElement(anchor, environment);\n if (!element) return undefined;\n\n const rect = element.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n return {\n x: roundRatio((selection.left - rect.left) / rect.width),\n y: roundRatio((selection.top - rect.top) / rect.height),\n width: roundRatio(selection.width / rect.width),\n height: roundRatio(selection.height / rect.height),\n };\n}\n\nfunction getRelativePoint(\n point: ReviewPoint,\n anchor: DomAnchor | string,\n environment: ReviewEnvironment\n): ReviewPoint | undefined {\n const element = getAnchorElement(anchor, environment);\n if (!element) return undefined;\n\n const rect = element.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n return {\n x: roundRatio((point.x - rect.left) / rect.width),\n y: roundRatio((point.y - rect.top) / rect.height),\n };\n}\n\nfunction getBoundMarkerPoint(\n item: ReviewItem,\n environment: ReviewEnvironment\n) {\n const marker = getItemMarker(item);\n if (!marker) return undefined;\n\n if (item.anchor && marker.relative) {\n const resolved = resolveAnchorElement(item.anchor, environment);\n const element = resolved?.element;\n\n if (element) {\n const rect = element.getBoundingClientRect();\n\n if (rect.width > 0 && rect.height > 0) {\n return {\n viewport: roundPoint({\n x: rect.left + rect.width * marker.relative.x,\n y: rect.top + rect.height * marker.relative.y,\n }),\n isBound: true,\n confidence: resolved.confidence,\n selector: resolved.candidate.selector,\n };\n }\n }\n }\n\n const sourceScroll = item.scroll ?? { x: 0, y: 0 };\n\n return {\n viewport: roundPoint({\n x: marker.viewport.x + sourceScroll.x - environment.window.scrollX,\n y: marker.viewport.y + sourceScroll.y - environment.window.scrollY,\n }),\n isBound: false,\n confidence: 0,\n };\n}\n\nfunction getBoundSelection(item: ReviewItem, environment: ReviewEnvironment) {\n const selection = getItemSelection(item);\n if (!selection?.viewport) return undefined;\n\n if (item.anchor && selection.relative) {\n const resolved = resolveAnchorElement(item.anchor, environment);\n const element = resolved?.element;\n\n if (element) {\n const rect = element.getBoundingClientRect();\n\n if (rect.width > 0 && rect.height > 0) {\n return {\n viewport: {\n left: rect.left + rect.width * selection.relative.x,\n top: rect.top + rect.height * selection.relative.y,\n width: rect.width * selection.relative.width,\n height: rect.height * selection.relative.height,\n },\n isBound: true,\n confidence: resolved.confidence,\n selector: resolved.candidate.selector,\n };\n }\n }\n }\n\n const sourceScroll = item.scroll ?? { x: 0, y: 0 };\n const viewportSelection = toViewportSelection(selection.viewport);\n\n return {\n viewport: {\n left: viewportSelection.left + sourceScroll.x - environment.window.scrollX,\n top: viewportSelection.top + sourceScroll.y - environment.window.scrollY,\n width: viewportSelection.width,\n height: viewportSelection.height,\n },\n isBound: false,\n confidence: 0,\n };\n}\n\nfunction getItemHighlightSelection(\n item: ReviewItem,\n environment: ReviewEnvironment\n): ReviewItemHighlightSelection | undefined {\n if (item.kind === 'area') {\n return getVisibleHighlightSelection(\n [\n getBoundSelection(item, environment),\n getAnchorHighlightSelection(item, environment),\n getPointHighlightSelection(item, environment),\n ],\n environment\n );\n }\n\n if (isDomReviewItem(item)) {\n return getVisibleHighlightSelection(\n [\n getAnchorHighlightSelection(item, environment),\n getBoundSelection(item, environment),\n getPointHighlightSelection(item, environment),\n ],\n environment\n );\n }\n\n return getVisibleHighlightSelection(\n [\n getAnchorHighlightSelection(item, environment),\n getBoundSelection(item, environment),\n getPointHighlightSelection(item, environment),\n ],\n environment\n );\n}\n\nfunction getAnchorHighlightSelection(\n item: ReviewItem,\n environment: ReviewEnvironment\n): ReviewItemHighlightSelection | undefined {\n if (!item.anchor) return undefined;\n\n const viewport = getElementViewportSelection(item.anchor, environment);\n if (!viewport) return undefined;\n\n return {\n viewport,\n isBound: true,\n };\n}\n\nfunction getPointHighlightSelection(\n item: ReviewItem,\n environment: ReviewEnvironment\n): ReviewItemHighlightSelection | undefined {\n const point = getBoundMarkerPoint(item, environment);\n if (!point) return undefined;\n\n const size = 16;\n return {\n viewport: {\n left: point.viewport.x - size / 2,\n top: point.viewport.y - size / 2,\n width: size,\n height: size,\n },\n isBound: point.isBound,\n };\n}\n\nfunction getVisibleHighlightSelection(\n candidates: Array<ReviewItemHighlightSelection | undefined>,\n environment: ReviewEnvironment\n): ReviewItemHighlightSelection | undefined {\n return candidates.find(\n (candidate): candidate is ReviewItemHighlightSelection =>\n Boolean(candidate && isSelectionInViewport(candidate.viewport, environment))\n );\n}\n\nfunction getReviewItemHighlightMode(\n item: ReviewItem\n): ReviewItemHighlightMode {\n if (isDomReviewItem(item)) return 'dom';\n if (item.kind === 'area') return 'area';\n return 'note';\n}\n\nfunction isDomReviewItem(item: ReviewItem) {\n return (\n item.scope === 'dom' ||\n (item.kind === 'note' && Boolean(item.anchor && getItemSelection(item)))\n );\n}\n\nfunction getItemMarker(item: ReviewItem): ReviewMarker | undefined {\n if (item.marker) return item.marker;\n\n const selection = getItemSelection(item);\n if (!selection?.viewport) return undefined;\n\n return {\n viewport: roundPoint(getSelectionCenter(selection.viewport)),\n relative: selection.relative\n ? roundPoint(getSelectionCenter(selection.relative))\n : undefined,\n };\n}\n\nfunction getItemSelection(item: ReviewItem): ReviewSelection | undefined {\n const value = item.selection as ReviewSelection | RelativeSelection | undefined;\n if (!value) return undefined;\n\n if ('viewport' in value && isRelativeSelection(value.viewport)) {\n return value;\n }\n\n if (isRelativeSelection(value)) {\n return {\n viewport: value,\n };\n }\n\n return undefined;\n}\n\nfunction shouldShowMarkerForScope(\n scope: ReviewItemScope,\n currentScope: ReviewItemScope\n) {\n return scope === currentScope;\n}\n\nfunction createSelectionCenterMarker(\n selection: ViewportSelection,\n anchor: DomAnchor | undefined,\n environment: ReviewEnvironment\n): ReviewMarker {\n const centerPoint = getSelectionCenter(selection);\n\n return {\n viewport: roundPoint(centerPoint),\n relative: anchor ? getRelativePoint(centerPoint, anchor, environment) : undefined,\n };\n}\n\nfunction getAnchorElement(\n anchor: DomAnchor | string,\n environment: ReviewEnvironment\n) {\n return typeof anchor === 'string'\n ? queryAnchorElement(anchor, environment)\n : resolveAnchorElement(anchor, environment)?.element;\n}\n\nfunction resolveAnchorElement(\n anchor: DomAnchor,\n environment: ReviewEnvironment\n) {\n const matches = getAnchorCandidates(anchor).flatMap((candidate) => {\n const match = queryBestAnchorCandidate(\n candidate,\n candidate.textFingerprint ?? anchor.textFingerprint,\n environment\n );\n\n if (!match) return [];\n\n const confidence = roundRatio(\n (candidate.confidence ?? 0.5) * match.score\n );\n\n return [{\n element: match.element,\n candidate,\n confidence,\n }];\n });\n\n return matches.sort((a, b) => b.confidence - a.confidence)[0];\n}\n\nfunction getAnchorCandidates(anchor: DomAnchor) {\n return dedupeAnchorCandidates([\n anchor,\n ...(anchor.candidates ?? []),\n ]);\n}\n\nfunction dedupeAnchorCandidates(candidates: DomAnchorCandidate[]) {\n const seen = new Set<string>();\n\n return candidates.filter((candidate) => {\n const key = `${candidate.strategy}:${candidate.selector}`;\n if (seen.has(key)) return false;\n\n seen.add(key);\n return true;\n });\n}\n\nfunction queryBestAnchorCandidate(\n candidate: DomAnchorCandidate,\n textFingerprint: string | undefined,\n environment: ReviewEnvironment\n) {\n const elements = queryAnchorElements(candidate.selector, environment);\n if (elements.length === 0) return undefined;\n if (!textFingerprint) {\n return {\n element: elements[0],\n score: 1,\n };\n }\n\n return elements\n .map((element) => ({\n element,\n score: getTextFingerprintScore(\n textFingerprint,\n getTextFingerprint(element)\n ),\n }))\n .sort((a, b) => b.score - a.score)[0];\n}\n\nfunction queryAnchorElement(selector: string, environment: ReviewEnvironment) {\n return queryAnchorElements(selector, environment)[0];\n}\n\nfunction queryAnchorElements(selector: string, environment: ReviewEnvironment) {\n try {\n return Array.from(environment.document.querySelectorAll(selector));\n } catch {\n return [];\n }\n}\n\nfunction getPointSelection(point: ReviewPoint): ViewportSelection {\n return {\n left: point.x,\n top: point.y,\n width: 1,\n height: 1,\n };\n}\n\nfunction toViewportSelection(selection: RelativeSelection): ViewportSelection {\n return {\n left: selection.x,\n top: selection.y,\n width: selection.width,\n height: selection.height,\n };\n}\n\nfunction toPublicSelection(selection: ViewportSelection): RelativeSelection {\n return {\n x: Math.round(selection.left),\n y: Math.round(selection.top),\n width: Math.round(selection.width),\n height: Math.round(selection.height),\n };\n}\n\nfunction getSelectionCenter(\n selection: ViewportSelection | RelativeSelection\n): ReviewPoint {\n if ('left' in selection) {\n return {\n x: selection.left + selection.width / 2,\n y: selection.top + selection.height / 2,\n };\n }\n\n return {\n x: selection.x + selection.width / 2,\n y: selection.y + selection.height / 2,\n };\n}\n\nfunction isRelativeSelection(value: unknown): value is RelativeSelection {\n if (!value || typeof value !== 'object') return false;\n\n const selection = value as Partial<RelativeSelection>;\n return (\n typeof selection.x === 'number' &&\n typeof selection.y === 'number' &&\n typeof selection.width === 'number' &&\n typeof selection.height === 'number'\n );\n}\n\nfunction findClosest(\n start: Element,\n predicate: (element: Element) => boolean\n) {\n let element: Element | null = start;\n const root = start.ownerDocument.documentElement;\n\n while (element && element !== root) {\n if (predicate(element)) return element;\n element = element.parentElement;\n }\n\n return undefined;\n}\n\nfunction getDomPath(element: Element) {\n const parts: string[] = [];\n let current: Element | null = element;\n const ownerDocument = element.ownerDocument;\n\n while (\n current &&\n current !== ownerDocument.body &&\n current !== ownerDocument.documentElement\n ) {\n const parent: Element | null = current.parentElement;\n const tag = current.tagName.toLowerCase();\n\n if (!parent) {\n parts.unshift(tag);\n break;\n }\n\n const currentTagName = current.tagName;\n const siblings: Element[] = Array.from(parent.children).filter(\n (child) => child.tagName === currentTagName\n );\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-of-type(${index})`);\n current = parent;\n }\n\n return `body > ${parts.join(' > ')}`;\n}\n\nfunction getTextFingerprint(element: Element) {\n const text = element.textContent?.replace(/\\s+/g, ' ').trim();\n return text ? text.slice(0, 120) : undefined;\n}\n\nfunction getTextFingerprintScore(expected?: string, actual?: string) {\n if (!expected) return 1;\n if (!actual) return 0.5;\n if (expected === actual) return 1;\n if (actual.includes(expected) || expected.includes(actual)) return 0.82;\n\n const expectedTokens = getFingerprintTokens(expected);\n const actualTokens = new Set(getFingerprintTokens(actual));\n if (expectedTokens.length === 0 || actualTokens.size === 0) return 0.5;\n\n const matches = expectedTokens.filter((token) => actualTokens.has(token));\n return clamp(matches.length / expectedTokens.length, 0.25, 0.76);\n}\n\nfunction getFingerprintTokens(value: string) {\n return value\n .toLowerCase()\n .split(/[\\s/|,.:;()[\\]{}\"'`~!?<>]+/)\n .map((token) => token.trim())\n .filter((token) => token.length > 1);\n}\n\nfunction isMeaningfulId(value: string) {\n const normalized = value.trim().toLowerCase();\n if (normalized.length <= 1) return false;\n\n return ![\n 'app',\n 'main',\n 'page',\n 'root',\n '__next',\n '__nuxt',\n ].includes(normalized);\n}\n\nfunction getMeaningfulClassName(element: Element) {\n return Array.from(element.classList).find((name) => isMeaningfulClass(name));\n}\n\nfunction isMeaningfulClass(value: string) {\n const normalized = value.trim();\n if (\n [\n 'absolute',\n 'block',\n 'contents',\n 'fixed',\n 'flex',\n 'grid',\n 'hidden',\n 'relative',\n 'sticky',\n ].includes(normalized)\n ) {\n return false;\n }\n\n return (\n normalized.length > 2 &&\n !normalized.includes(':') &&\n !/^(aspect|basis|bg|border|bottom|col|content|delay|duration|ease|font|from|gap|grow|h|inset|items|justify|leading|left|m|max-h|max-w|mb|ml|mr|mt|mx|my|min-h|min-w|object|opacity|order|origin|overflow|p|pb|pl|place|pointer|pr|pt|px|py|right|rotate|rounded|row|scale|self|shadow|shrink|text|to|top|tracking|transition|translate|via|w|z)-/.test(\n normalized\n ) &&\n !normalized.startsWith('mq-')\n );\n}\n\nfunction isHotkey(event: KeyboardEvent, hotkey: string) {\n const parts = hotkey\n .split('+')\n .map((part) => part.trim().toLowerCase())\n .filter(Boolean);\n const key = parts.find(\n (part) => !['shift', 'ctrl', 'control', 'alt', 'meta', 'cmd'].includes(part)\n );\n\n if (!key) return false;\n if (parts.includes('shift') !== event.shiftKey) return false;\n if (\n (parts.includes('ctrl') || parts.includes('control')) !== event.ctrlKey\n ) {\n return false;\n }\n if (parts.includes('alt') !== event.altKey) return false;\n if ((parts.includes('meta') || parts.includes('cmd')) !== event.metaKey) {\n return false;\n }\n\n return isHotkeyKey(event, key);\n}\n\nfunction isHotkeyKey(event: KeyboardEvent, key: string) {\n const normalizedKey = key.toLowerCase();\n\n if (event.key.toLowerCase() === normalizedKey) return true;\n\n if (getHotkeyCode(normalizedKey) === event.code) return true;\n\n const aliases: Record<string, string[]> = {\n q: ['ㅂ', 'ㅃ'],\n };\n\n return aliases[normalizedKey]?.includes(event.key) ?? false;\n}\n\nfunction getHotkeyCode(key: string) {\n if (/^[a-z]$/.test(key)) return `Key${key.toUpperCase()}`;\n if (/^[0-9]$/.test(key)) return `Digit${key}`;\n return undefined;\n}\n\nfunction getPageUrl(environment?: ReviewEnvironment) {\n const location = environment?.window.location ?? window.location;\n const search = getPublicSearch(location);\n return `${location.origin}${location.pathname}${search}${location.hash}`;\n}\n\nfunction getOriginalUrl(environment?: ReviewEnvironment) {\n const location = environment?.window.location ?? window.location;\n const search = getPublicSearch(location);\n return `${location.origin}${location.pathname}${search}${location.hash}`;\n}\n\nfunction getRouteKey(environment?: ReviewEnvironment) {\n const location = environment?.window.location ?? window.location;\n return normalizeRoutePath(location.pathname);\n}\n\nfunction getNormalizedPath(environment?: ReviewEnvironment) {\n return getRouteKey(environment);\n}\n\nfunction getPublicSearch(location: Location) {\n const params = new URLSearchParams(location.search);\n\n INTERNAL_QUERY_PARAMS.forEach((key) => params.delete(key));\n\n const value = params.toString();\n return value ? `?${value}` : '';\n}\n\nfunction createId() {\n if ('randomUUID' in crypto) return crypto.randomUUID();\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction formatDate(value: string) {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n\n return date.toLocaleString(undefined, {\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nfunction formatAreaDraftMeta(draft: AreaDraft) {\n const parts = [`viewport ${formatSize(draft.viewport)}`];\n\n if (draft.selection) {\n parts.push(`rect ${formatSelection(draft.selection.viewport)}`);\n }\n\n if (draft.marker) {\n parts.push(`point ${formatPoint(draft.marker.viewport)}`);\n }\n\n return parts.join(' / ');\n}\n\nfunction formatNoteDraftMeta(draft: NoteDraft) {\n const parts = [\n `viewport ${formatSize(draft.viewport)}`,\n `point ${formatPoint(draft.marker.viewport)}`,\n ];\n\n if (draft.anchor) {\n parts.push(formatAnchorMeta(draft.anchor));\n }\n\n return parts.join(' / ');\n}\n\nfunction formatItemMeta(item: ReviewItem) {\n const parts = [formatDate(item.createdAt)];\n const marker = getItemMarker(item);\n const selection = getItemSelection(item);\n\n if (item.viewport) {\n parts.push(`viewport ${formatSize(item.viewport)}`);\n }\n\n if (marker) {\n parts.push(`point ${formatPoint(marker.viewport)}`);\n }\n\n if (selection) {\n parts.push(`rect ${formatSelection(selection.viewport)}`);\n }\n\n if (item.anchor) {\n parts.push(formatAnchorMeta(item.anchor));\n }\n\n return parts.join(' / ');\n}\n\nfunction formatSize(size: ViewportSize) {\n return `${Math.round(size.width)}x${Math.round(size.height)}`;\n}\n\nfunction formatPoint(point: ReviewPoint) {\n return `${Math.round(point.x)},${Math.round(point.y)}`;\n}\n\nfunction formatSelection(selection: RelativeSelection) {\n return [\n Math.round(selection.x),\n Math.round(selection.y),\n Math.round(selection.width),\n Math.round(selection.height),\n ].join(',');\n}\n\nfunction formatAnchorMeta(anchor: DomAnchor) {\n const parts = [`dom ${anchor.strategy}`];\n\n if (typeof anchor.confidence === 'number') {\n parts.push(`${Math.round(anchor.confidence * 100)}%`);\n }\n\n const candidates = getAnchorCandidates(anchor);\n if (candidates.length > 1) {\n parts.push(`${candidates.length} candidates`);\n }\n\n return parts.join(' ');\n}\n\nfunction getViewportSize(environment?: ReviewEnvironment): ViewportSize {\n const targetWindow = environment?.window ?? window;\n return {\n width: targetWindow.innerWidth,\n height: targetWindow.innerHeight,\n };\n}\n\nfunction roundPoint(point: ReviewPoint): ReviewPoint {\n return {\n x: Math.round(point.x),\n y: Math.round(point.y),\n };\n}\n\nfunction runWithAutoScrollBehavior(\n targetDocument: Document,\n callback: () => void\n) {\n const elements = [\n targetDocument.documentElement,\n targetDocument.body,\n ].filter((element): element is HTMLElement => Boolean(element));\n const previousValues = elements.map((element) => element.style.scrollBehavior);\n\n elements.forEach((element) => {\n element.style.scrollBehavior = 'auto';\n });\n\n try {\n callback();\n } finally {\n elements.forEach((element, index) => {\n element.style.scrollBehavior = previousValues[index] ?? '';\n });\n }\n}\n\nfunction setDocumentScrollInstantly(\n environment: ReviewEnvironment,\n position: { x: number; y: number }\n) {\n const scrollElement = environment.document.scrollingElement as HTMLElement | null;\n\n if (scrollElement) {\n scrollElement.scrollLeft = Math.max(0, Math.round(position.x));\n scrollElement.scrollTop = Math.max(0, Math.round(position.y));\n return;\n }\n\n environment.window.scrollTo(\n Math.max(0, Math.round(position.x)),\n Math.max(0, Math.round(position.y))\n );\n}\n\nfunction isPointInViewport(\n point: ReviewPoint,\n environment?: ReviewEnvironment\n) {\n const viewport = getViewportSize(environment);\n return (\n point.x >= 0 &&\n point.y >= 0 &&\n point.x <= viewport.width &&\n point.y <= viewport.height\n );\n}\n\nfunction isSelectionInViewport(\n selection: ViewportSelection,\n environment?: ReviewEnvironment\n) {\n const viewport = getViewportSize(environment);\n return rectanglesIntersect(selection, {\n left: 0,\n top: 0,\n width: viewport.width,\n height: viewport.height,\n });\n}\n\nfunction clampPoint(point: ReviewPoint, environment?: ReviewEnvironment) {\n const viewport = getViewportSize(environment);\n return {\n x: clamp(point.x, 0, viewport.width),\n y: clamp(point.y, 0, viewport.height),\n };\n}\n\nfunction getPopoverPosition(\n point: ReviewPoint,\n environment?: ReviewEnvironment,\n options?: {\n width?: number;\n estimatedHeight?: number;\n offset?: number;\n }\n) {\n const bounds = getPopoverBounds(environment);\n const margin = 12;\n const width = Math.min(\n options?.width ?? 320,\n Math.max(240, bounds.width - margin * 2)\n );\n const estimatedHeight = options?.estimatedHeight ?? 178;\n const offset = options?.offset ?? 12;\n\n return {\n left: clamp(\n point.x + offset,\n bounds.left + margin,\n bounds.left + bounds.width - width - margin\n ),\n top: clamp(\n point.y + offset,\n bounds.top + margin,\n bounds.top + bounds.height - estimatedHeight - margin\n ),\n };\n}\n\nfunction getAreaPopoverPosition(\n selection: ViewportSelection,\n environment: ReviewEnvironment\n) {\n return getPopoverPosition(\n {\n x: selection.left + selection.width,\n y: selection.top,\n },\n environment,\n {\n width: 360,\n estimatedHeight: 206,\n }\n );\n}\n\nfunction getPopoverBounds(environment?: ReviewEnvironment) {\n if (!environment) {\n return {\n left: 0,\n top: 0,\n width: window.innerWidth,\n height: window.innerHeight,\n };\n }\n\n return environment.overlayRect;\n}\n\nfunction toHostPoint(point: ReviewPoint, environment?: ReviewEnvironment) {\n if (!environment) return point;\n\n return {\n x: point.x + environment.viewportRect.left,\n y: point.y + environment.viewportRect.top,\n };\n}\n\nfunction toHostSelection(\n selection: ViewportSelection,\n environment: ReviewEnvironment\n): ViewportSelection {\n return {\n left: selection.left + environment.viewportRect.left,\n top: selection.top + environment.viewportRect.top,\n width: selection.width,\n height: selection.height,\n };\n}\n\nfunction toTargetPoint(point: ReviewPoint, environment?: ReviewEnvironment) {\n if (!environment) return point;\n\n return {\n x: point.x - environment.viewportRect.left,\n y: point.y - environment.viewportRect.top,\n };\n}\n\nfunction toTargetPointFromHostEvent(\n event: Pick<PointerEvent, 'clientX' | 'clientY'>,\n environment?: ReviewEnvironment\n) {\n return toTargetPoint(\n {\n x: event.clientX,\n y: event.clientY,\n },\n environment\n );\n}\n\nfunction placeLayerOverTarget(\n layer: HTMLElement,\n environment: ReviewEnvironment\n) {\n layer.style.left = `${environment.viewportRect.left}px`;\n layer.style.top = `${environment.viewportRect.top}px`;\n layer.style.width = `${environment.viewportRect.width}px`;\n layer.style.height = `${environment.viewportRect.height}px`;\n layer.style.right = 'auto';\n layer.style.bottom = 'auto';\n}\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), Math.max(min, max));\n}\n\nfunction roundRatio(value: number) {\n return Math.round(value * 10000) / 10000;\n}\n\nfunction cssEscape(value: string) {\n if ('CSS' in window && typeof window.CSS.escape === 'function') {\n return window.CSS.escape(value);\n }\n\n return value.replace(/[^a-zA-Z0-9_-]/g, '\\\\$&');\n}\n\nfunction createNoopController(): WebReviewKitController {\n return {\n open() {},\n close() {},\n toggle() {},\n setMode() {},\n getMode() {\n return 'idle';\n },\n highlightItem() {},\n setHiddenItemIds() {},\n async reload() {\n return [];\n },\n getItems() {\n return [];\n },\n destroy() {},\n };\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["normalizeReviewNumber","toAbsoluteReviewUrl","normalizeReviewNumber"]}
@@ -1,146 +0,0 @@
1
- # review-kit adapter handoff
2
-
3
- ## 목적
4
-
5
- `df-web-review-kit`를 Lexus repo 안에서 검증한 뒤 별도 package repo로 옮기기 위한 handoff 문서다.
6
-
7
- 현재 방향은 review shell/core와 저장소를 분리하고, project page에서는 adapter array만 선언해서 local, remote, Supabase 같은 저장소를 교체 가능하게 만드는 것이다.
8
-
9
- ## 현재 상태
10
-
11
- - Mount 위치: `page/review/index.tsx`
12
- - Package 위치: `packages/df-web-review-kit`
13
- - 현재 source: `local`, `df-sheet`
14
- - 현재 shell-facing adapter config: array
15
- - core-facing internal adapter: 기존 `WebReviewKitAdapter`
16
- - local item id: uuid
17
- - local 표시 번호: 개인 draft용 `reviewNumber`
18
- - remote 표시 번호: remote source가 새로 배정하는 canonical `reviewNumber`
19
- - remote submit 성공 시 local item은 삭제하고, remote source에서 새 canonical id/number item으로 조회한다.
20
-
21
- 현재 public shell adapter는 generic `update`를 노출하지 않는다.
22
-
23
- ```ts
24
- type ReviewShellAdapter = {
25
- label: ReviewSource;
26
- pageId?: string;
27
- get: WebReviewKitAdapter['get'];
28
- list: WebReviewKitAdapter['list'];
29
- create: WebReviewKitAdapter['create'];
30
- statusOptions?: readonly ReviewShellStatusOption[];
31
- updateStatus?: (input: ReviewShellUpdateStatusInput) => Promise<ReviewItem>;
32
- syncSubmission?: (input: ReviewShellSyncSubmissionInput) => Promise<ReviewItem>;
33
- remove?: WebReviewKitAdapter['remove'];
34
- };
35
- ```
36
-
37
- 의도:
38
-
39
- - `create`: QA 생성 또는 remote 등록
40
- - `list/get`: source별 QA 조회와 deep link restore
41
- - `statusOptions + updateStatus`: 상태 변경 UI
42
- - `remove`: 삭제 버튼 노출 조건
43
- - `syncSubmission`: remote 등록 중/실패 상태를 local item에 임시 기록하는 좁은 bookkeeping
44
-
45
- ## 결정된 원칙
46
-
47
- - shell public adapter에는 generic `update`를 넣지 않는다.
48
- - 상태 변경은 `updateStatus`로만 다룬다.
49
- - `statusIndex`는 identity가 아니라 외부 시스템 매핑 보조값이다.
50
- - 저장 기준은 stable status value다.
51
- - source가 기능을 제공하지 않으면 shell은 해당 버튼/UI를 숨기거나 readonly badge로 보여준다.
52
- - `local`은 생성, 상태 변경, 삭제, remote submit 중/실패 상태 기록을 담당한다.
53
- - `df-sheet`는 현재 review-kit 안에서는 remote 등록과 읽기 중심으로 둔다.
54
-
55
- ## Supabase adapter
56
-
57
- Supabase adapter를 하나 붙이면 adapter 계약 검증에 좋다. df-sheet보다 DB schema를 직접 통제할 수 있어서 `statusOptions`, `updateStatus`, `remove`의 동작 경계를 확인하기 쉽다.
58
-
59
- 초기 source 이름은 `supabase`로 잡았다.
60
-
61
- ```ts
62
- {
63
- label: 'supabase',
64
- get,
65
- list,
66
- create,
67
- statusOptions,
68
- updateStatus,
69
- remove,
70
- }
71
- ```
72
-
73
- 현재 구현:
74
-
75
- - Adapter: `packages/df-web-review-kit/src/adapters/supabase.ts`
76
- - Lexus wiring: `page/review/index.tsx`
77
- - SQL/runbook: `packages/df-web-review-kit/docs/supabase-review-items.md`
78
- - `ReviewSource`는 string 확장 가능 타입으로 풀었다.
79
- - route query의 `source` 처리는 `source !== 'local'` 기준으로 일반화했다.
80
- - shell은 adapter array의 첫 non-local adapter를 remote source로 사용한다.
81
- - source별 list title, empty text도 label 기반으로 바꿨다.
82
-
83
- ## Supabase schema
84
-
85
- 브라우저에서 직접 붙이는 빠른 검증은 anon key + RLS 기준으로 시작한다. service role key는 브라우저에 절대 넣지 않는다.
86
-
87
- 현재 schema/runbook은 `supabase-review-items.md`가 source of truth다.
88
-
89
- 핵심 구조:
90
-
91
- - `review_items`: QA row. 실제 review item payload는 `item jsonb`에 저장한다.
92
- - `review_project_counters`: `(project_id, source)`별 다음 `review_number`를 보관한다.
93
- - `create_review_item`: counter row를 짧게 증가시키고 canonical `review_number`를 item에 주입해서 insert한다.
94
-
95
- 주의:
96
-
97
- - 이 RLS는 dev 검증용이다.
98
- - production/package용으로는 Supabase Edge Function 또는 project-scoped backend proxy가 더 안전하다.
99
- - RLS 조건에 쓰는 컬럼에는 인덱스를 둔다.
100
-
101
- ## Supabase adapter draft
102
-
103
- Adapter option:
104
-
105
- ```ts
106
- type SupabaseReviewAdapterOptions = {
107
- url: string;
108
- anonKey: string;
109
- table?: string;
110
- projectId: string;
111
- source?: string;
112
- createRpc?: string;
113
- unsafeClientReviewNumberFallback?: boolean;
114
- };
115
- ```
116
-
117
- API mapping:
118
-
119
- - `get(id)`: `select().eq('id', id).maybeSingle()`
120
- - `list(query)`: `project_id`, `route_key`, optional `status` filter
121
- - `create(item)`: `create_review_item` RPC로 canonical id/number 발급 후 review item 반환
122
- - `updateStatus({ id, status })`: `status`, `updated_at`만 patch
123
- - `remove(id)`: row delete
124
-
125
- local `reviewNumber`는 사람별 draft 번호라 서로 겹칠 수 있다. remote submit 시 local 번호를 보존하지 않고 Supabase adapter가 새 `id`와 새 canonical `reviewNumber`를 배정한다.
126
-
127
- 현재 구현은 `create_review_item` RPC가 `review_project_counters` row를 `insert ... on conflict ... do update returning`으로 증가시켜 `review_number`를 발급하고 row를 insert한다. 동시 등록 충돌과 삭제 후 번호 재사용을 피하기 위한 구조다. `unsafeClientReviewNumberFallback` option을 켜면 예전 client `max(review_number) + 1` 방식을 쓸 수 있지만 dev 임시 용도다.
128
-
129
- ## 작업 순서
130
-
131
- 1. `ReviewSource`/route/source select를 adapter label 기반으로 일반화한다.
132
- 2. `supabaseAdapter` 파일을 추가한다.
133
- 3. `page/review/index.tsx`에 Supabase adapter config를 선택적으로 추가한다.
134
- 4. `.env` 예시를 문서화한다.
135
- 5. local, df-sheet, supabase source 전환을 브라우저에서 확인한다.
136
- 6. `pnpm --dir packages/df-web-review-kit typecheck`
137
- 7. `pnpm typecheck:review`
138
- 8. `pnpm review-kit:build`
139
-
140
- ## Open questions
141
-
142
- - Supabase는 dev 검증만 할지, package 정식 adapter로 포함할지.
143
- - remote source에서 delete를 허용할지.
144
- - remote source의 `reviewNumber`를 사람이 쓰는 canonical id로 확정할지.
145
- - auth를 anon+RLS로 유지할지, Edge Function/proxy로 감쌀지.
146
- - status option을 package default로 둘지, project page config에서만 주입할지.