@siteping/widget 0.10.1 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -2
- package/dist/{chunk-GP6ZPMBW.js → chunk-33HB3HZI.js} +3 -3
- package/dist/chunk-33HB3HZI.js.map +1 -0
- package/dist/de-MAGIJBFC.js +2 -0
- package/dist/de-MAGIJBFC.js.map +1 -0
- package/dist/es-HEVFJPRI.js +2 -0
- package/dist/{es-74ACSG45.js.map → es-HEVFJPRI.js.map} +1 -1
- package/dist/fr-OM2PHLDH.js +2 -0
- package/dist/fr-OM2PHLDH.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.global.js +91 -91
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +41 -41
- package/dist/index.js.map +1 -1
- package/dist/it-OQVYHKKV.js +2 -0
- package/dist/it-OQVYHKKV.js.map +1 -0
- package/dist/{panel-5ZGIFFJ4.js → panel-BSNEQHAQ.js} +2 -2
- package/dist/{panel-5ZGIFFJ4.js.map → panel-BSNEQHAQ.js.map} +1 -1
- package/dist/pt-VUUNL42H.js +2 -0
- package/dist/pt-VUUNL42H.js.map +1 -0
- package/dist/react.js +44 -44
- package/dist/react.js.map +1 -1
- package/dist/ru-NDWY7Y36.js +2 -0
- package/dist/ru-NDWY7Y36.js.map +1 -0
- package/dist/siteping-core.d.ts +1 -1
- package/dist/types.d.ts +41 -3
- package/package.json +2 -2
- package/dist/chunk-GP6ZPMBW.js.map +0 -1
- package/dist/de-MXWDD2BZ.js +0 -2
- package/dist/de-MXWDD2BZ.js.map +0 -1
- package/dist/es-74ACSG45.js +0 -2
- package/dist/fr-XAQKRFFY.js +0 -2
- package/dist/fr-XAQKRFFY.js.map +0 -1
- package/dist/it-4RBJ7CH6.js +0 -2
- package/dist/it-4RBJ7CH6.js.map +0 -1
- package/dist/pt-VNIESRZN.js +0 -2
- package/dist/pt-VNIESRZN.js.map +0 -1
- package/dist/ru-O4MZAQXF.js +0 -2
- package/dist/ru-O4MZAQXF.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.bun/@medv+finder@4.0.2/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/popup.ts","../src/screenshot.ts","../src/annotator.ts","../src/api-client.ts","../src/diagnostics/console-buffer.ts","../src/diagnostics/network-buffer.ts","../src/events.ts","../src/fab.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/resolver.ts","../src/markers.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts","../src/index.ts"],"names":["acceptedAttrNames","attr","name","value","nameIsOk","wordLike","valueIsOk","idName","className","tagName","finder","input","options","defaults","startTime","config","rootDocument","findRootDocument","foundPath","count","candidate","search","fPath","fallback","selector","unique","optimized","optimize","byPenalty","stack","paths","current","i","level","tie","node","combinations","words","word","element","elementId","index","indexOf","nthOfType","nth","nthChild","path","query","penalty","acc","a","b","parent","child","rootNode","css","newPath","STABLE_ATTRS","djb2","str","hash","generateFingerprint","childCount","siblingIdx","attrs","val","attrHash","scoreFingerprint","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","adjacentText","direction","prop","sibling","attempts","text","neighborText","prev","next","generateXPath","safeId","segments","tag","position","ANCHOR_KEY_ATTR","generateAnchor","cssSelector","xpath","textSnippet","textPrefix","textSuffix","fingerprint","neighbor","anchorKey","containsRect","el","rect","findAnchorElement","root","centerX","centerY","elementAtCenter","rectToPercentages","anchorBounds","TYPE_LABEL_KEYS","isMacPlatform","uaData","Popup","colors","t","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","option","btn","icon","parseSvg","bgColor","getTypeBgColor","getTypeColor","e","btnRow","typeButtons","type","key","labelSpan","setText","rectBounds","onSubmit","resolve","popupH","popupW","top","left","aboveTop","focusableEls","first","last","reduceMotion","container","buttons","isActive","color","enabled","result","submitter","spinner","cachedHtml2Canvas","warnedAboutMissingDep","loadHtml2Canvas","mod","err","clamp","min","max","roundPct","captureAnnotatedScreenshot","html2canvas","quality","maxWidth","padX","padY","docX","docY","docW","docH","capX","capY","capW","capH","region","canvas","ratio","targetW","targetH","scaled","ctx","Annotator","bus","enableScreenshot","drawMode","dot","style","instruction","cancelBtn","previouslyFocused","target","bounds","annotation","screenshotCache","formResult","touch","clientX","clientY","source","evt","x","y","w","h","pointRect","captureRect","capture","reject","cleanup","unsubSent","unsubError","unsubCancelled","reason","anchorElement","anchor","errorFromResponse","response","label","detail","message","SitepingAuthError","SitepingValidationError","SitepingError","networkErrorFromException","error","SitepingNetworkError","MAX_RETRIES","TIMEOUT_MS","RETRY_QUEUE_KEY","MAX_QUEUE_SIZE","resilientFetch","url","init","retries","attempt","controller","timeout","baseDelay","jitter","r","LOCK_NAME","withRetryLock","callback","readQueue","raw","parsed","queueForRetry","endpoint","payload","queue","normalizeName","normalizeEmail","flushRetryQueue","currentIdentity","toRetry","unrelated","dropped","entry","failed","remaining","parseJsonAs","ApiClient","projectName","screenshotRegion","rest","body","params","id","resolved","LEVELS","serializeArg","arg","seen","_key","formatArgs","args","out","ConsoleBuffer","maxEntries","original","buffer","wrapped","truncateUrl","urlString","NetworkBuffer","startedAt","t0","method","t1","proto","originalOpen","originalSend","meta","info","onEnd","status","EventBus","event","listener","set","fn","ITEM_GAP","ITEM_LABEL_KEYS","Fab","shadowRoot","isRight","ICON_LIST","ICON_EDIT","ICON_EYE","ICON_EYE_OFF","ICON_SITEPING","item","host","handleEscape","items","activeEl","currentIndex","nextIndex","displayText","ICON_CLOSE","svgStr","badge","unsubscribe","oldSvg","newSvg","STORAGE_KEY","isIdentity","hasOwn","email","getIdentity","saveIdentity","identity","editDistance","aLen","bLen","k","curr","j","prevDiag","tmp","similarity","maxLen","fuzzyIncludes","haystack","needle","minScore","nLen","best","capped","limit","window","MAX_SCAN_CANDIDATES","TEXT_MATCH_THRESHOLD","textMatches","resolveAnchor","escaped","smartScan","candidates","bestElement","bestScore","scoreCandidate","totalWeight","candidateText","contextScore","contextParts","prevText","nextText","candidateNeighbor","resolveAnnotation","resolution","absoluteRect","toAnchorData","toRectData","MARKER_OFFSET","markerPosition","clusterMarker","cluster","elIdx","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","tooltip","liveRegion","visible","mutations","hasRelevantMutation","m","isClosedStatus","validKeys","markerEl","cacheKey","cachedEl","anchorRect","pos","openCount","feedbacks","feedback","marker","allItems","used","itemI","itemJ","baseTop","baseLeft","isSolo","totalWidth","startLeft","topMarker","confidence","isResolved","number","typeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","feedbackId","highlight","StoreClient","store","record","flattenAnnotation","toResponse","total","toAnnotationResponse","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","buildStyles","cssVariables","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","Tooltip","locale","children","typeBg","createT","typeLabel","header","date","formatRelativeDate","tooltipRect","gap","isAbove","arrowLeft","instance","normaliseDiagnosticsOptions","skippedInstance","noop","normaliseDeepLinkOptions","launch","log","minViewportWidth","localeReady","loadLocale","scopeAnnotationsByUrl","getScope","diagnosticsOpts","consoleBuffer","networkBuffer","buildThemeColors","publicBus","client","fb","isTestEnv","shadowMode","shadow","sheet","markers","fab","panelInstance","panelPromise","destroyed","markerGeneration","loadPanel","prefetch","ric","pendingOpen","unsubToggle","open","p","annotator","onContextMenu","n","submitting","unsubAnnotation","data","screenshotDataUrl","promptIdentity","clientId","scope","diagnostics","initialScope","initialOptions","deepLinkOpts","initialLoadGeneration","f","focusId","matched","doRefresh","generation","opts","teardownNavigation","scopeKey","s","lastScopeKey","onLocationChange","prevKey","originalPushState","originalReplaceState","patchedPushState","patchedReplaceState","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","closeModal","onKeydown","submitBtn","focusableSelectors","ke","active","initSiteping"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAA,EA21BtF,UAAW,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;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","file":"index.js","sourcesContent":["// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nconst acceptedAttrNames = new Set(['role', 'name', 'aria-label', 'rel', 'href']);\n/** Check if attribute name and value are word-like. */\nexport function attr(name, value) {\n let nameIsOk = acceptedAttrNames.has(name);\n nameIsOk ||= name.startsWith('data-') && wordLike(name);\n let valueIsOk = wordLike(value) && value.length < 100;\n valueIsOk ||= value.startsWith('#') && wordLike(value.slice(1));\n return nameIsOk && valueIsOk;\n}\n/** Check if id name is word-like. */\nexport function idName(name) {\n return wordLike(name);\n}\n/** Check if class name is word-like. */\nexport function className(name) {\n return wordLike(name);\n}\n/** Check if tag name is word-like. */\nexport function tagName(name) {\n return true;\n}\n/** Finds unique CSS selectors for the given element. */\nexport function finder(input, options) {\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if (input.tagName.toLowerCase() === 'html') {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: idName,\n className: className,\n tagName: tagName,\n attr: attr,\n timeoutMs: 1000,\n seedMinLength: 3,\n optimizedMinLength: 2,\n maxNumberOfPathChecks: Infinity,\n };\n const startTime = new Date();\n const config = { ...defaults, ...options };\n const rootDocument = findRootDocument(config.root, defaults);\n let foundPath;\n let count = 0;\n for (const candidate of search(input, config, rootDocument)) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs ||\n count >= config.maxNumberOfPathChecks) {\n const fPath = fallback(input, rootDocument);\n if (!fPath) {\n throw new Error(`Timeout: Can't find a unique selector after ${config.timeoutMs}ms`);\n }\n return selector(fPath);\n }\n count++;\n if (unique(candidate, rootDocument)) {\n foundPath = candidate;\n break;\n }\n }\n if (!foundPath) {\n throw new Error(`Selector was not found.`);\n }\n const optimized = [\n ...optimize(foundPath, input, config, rootDocument, startTime),\n ];\n optimized.sort(byPenalty);\n if (optimized.length > 0) {\n return selector(optimized[0]);\n }\n return selector(foundPath);\n}\nfunction* search(input, config, rootDocument) {\n const stack = [];\n let paths = [];\n let current = input;\n let i = 0;\n while (current && current !== rootDocument) {\n const level = tie(current, config);\n for (const node of level) {\n node.level = i;\n }\n stack.push(level);\n current = current.parentElement;\n i++;\n paths.push(...combinations(stack));\n if (i >= config.seedMinLength) {\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n paths = [];\n }\n }\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n}\nfunction wordLike(name) {\n if (/^[a-z\\-]{3,}$/i.test(name)) {\n const words = name.split(/-|[A-Z]/);\n for (const word of words) {\n if (word.length <= 2) {\n return false;\n }\n if (/[^aeiou]{4,}/i.test(word)) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\nfunction tie(element, config) {\n const level = [];\n const elementId = element.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n level.push({\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n });\n }\n for (let i = 0; i < element.classList.length; i++) {\n const name = element.classList[i];\n if (config.className(name)) {\n level.push({\n name: '.' + CSS.escape(name),\n penalty: 1,\n });\n }\n }\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (config.attr(attr.name, attr.value)) {\n level.push({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 2,\n });\n }\n }\n const tagName = element.tagName.toLowerCase();\n if (config.tagName(tagName)) {\n level.push({\n name: tagName,\n penalty: 5,\n });\n const index = indexOf(element, tagName);\n if (index !== undefined) {\n level.push({\n name: nthOfType(tagName, index),\n penalty: 10,\n });\n }\n }\n const nth = indexOf(element);\n if (nth !== undefined) {\n level.push({\n name: nthChild(tagName, nth),\n penalty: 50,\n });\n }\n return level;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction byPenalty(a, b) {\n return penalty(a) - penalty(b);\n}\nfunction indexOf(input, tagName) {\n const parent = input.parentNode;\n if (!parent) {\n return undefined;\n }\n let child = parent.firstChild;\n if (!child) {\n return undefined;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE &&\n (tagName === undefined ||\n child.tagName.toLowerCase() === tagName)) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction fallback(input, rootDocument) {\n let i = 0;\n let current = input;\n const path = [];\n while (current && current !== rootDocument) {\n const tagName = current.tagName.toLowerCase();\n const index = indexOf(current, tagName);\n if (index === undefined) {\n return;\n }\n path.push({\n name: nthOfType(tagName, index),\n penalty: NaN,\n level: i,\n });\n current = current.parentElement;\n i++;\n }\n if (unique(path, rootDocument)) {\n return path;\n }\n}\nfunction nthChild(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-child(${index})`;\n}\nfunction nthOfType(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-of-type(${index})`;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction unique(path, rootDocument) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction* optimize(path, input, config, rootDocument, startTime) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs) {\n return;\n }\n const newPath = [...path];\n newPath.splice(i, 1);\n if (unique(newPath, rootDocument) &&\n rootDocument.querySelector(selector(newPath)) === input) {\n yield newPath;\n yield* optimize(newPath, input, config, rootDocument, startTime);\n }\n }\n }\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n // Hash stable attributes\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n const attrHash = attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n\n return `${childCount}:${siblingIdx}:${attrHash}`;\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling: Element | null = element[prop];\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text = sibling.textContent?.trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = sibling[prop];\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate siblings for disambiguation context. */\nexport function neighborText(element: Element): string {\n const prev = element.previousElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n const next = element.nextElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short\n */\nexport function generateXPath(element: Element): string {\n if (element.id) {\n const safeId = element.id.includes(\"'\") ? `concat('${element.id.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${element.id}'`;\n return `//${element.localName}[@id=${safeId}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n const safeId = current.id.includes(\"'\")\n ? `concat('${current.id.replace(/'/g, \"',\\\"'\\\",'\")}')`\n : `'${current.id}'`;\n segments.unshift(`/${tag}[@id=${safeId}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n return \"/html/body\" + segments.join(\"\");\n}\n","import { finder } from \"@medv/finder\";\nimport type { AnchorData, RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/** HTML attribute hosts use to mark stable semantic anchors. */\nexport const ANCHOR_KEY_ATTR = \"data-feedback-anchor\";\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Resolution priority (used by `resolveAnchor`):\n * 1. Semantic anchor (`data-feedback-anchor` on closest ancestor) — hosts opt\n * into stable, narrow anchors that survive viewport changes and refactors\n * 2. Element id\n * 3. CSS selector via @medv/finder\n * 4. XPath\n * 5. Smart scan (fingerprint + text + prefix/suffix + neighbor)\n */\nexport function generateAnchor(element: Element): AnchorData {\n const cssSelector = finder(element, {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n });\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n const semanticAncestor = element.closest(`[${ANCHOR_KEY_ATTR}]`);\n const anchorKey = semanticAncestor?.getAttribute(ANCHOR_KEY_ATTR) ?? null;\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName,\n elementId: element.id || undefined,\n anchorKey,\n };\n}\n\n/** Whether `el`'s bounding box fully contains `rect`. */\nfunction containsRect(el: Element, rect: DOMRect): boolean {\n const b = el.getBoundingClientRect();\n return b.left <= rect.x && b.top <= rect.y && b.right >= rect.x + rect.width && b.bottom >= rect.y + rect.height;\n}\n\n/**\n * Find the best DOM element to use as the rect's anchor.\n *\n * Priority:\n * 1. Closest ancestor with `data-feedback-anchor` whose bounds contain the rect —\n * semantic anchors are typically narrow section roots, so anchoring against\n * them keeps the percentage-based rect stable across viewport changes\n * instead of stretching to the width of `<main>` or `<body>`.\n * 2. Smallest ancestor that contains the rect (legacy behavior).\n * 3. `document.body` fallback — keeps percentages in [0, 1].\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const centerX = rect.x + rect.width / 2;\n const centerY = rect.y + rect.height / 2;\n\n const elementAtCenter = document.elementFromPoint(centerX, centerY);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n // Pass 1 — semantic anchor (host-controlled, most stable)\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n if (current.hasAttribute(ANCHOR_KEY_ATTR) && containsRect(current, rect)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Pass 2 — original behavior: smallest ancestor that contains the rect\n current = elementAtCenter;\n while (current && current !== document.body) {\n if (containsRect(current, rect)) return current;\n current = current.parentElement;\n }\n\n return document.body;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n// Map each feedback type to its translation key, so `refreshLabels()` can\n// re-localize the existing type buttons without re-rendering the popup.\nconst TYPE_LABEL_KEYS: Record<FeedbackType, keyof Translations> = {\n question: \"type.question\",\n change: \"type.change\",\n bug: \"type.bug\",\n other: \"type.other\",\n};\n\n/**\n * Detect whether the host platform uses ⌘+Enter (macOS) vs Ctrl+Enter.\n * Resolved at call time so we can recompute the popup hint when the locale\n * dictionary lands.\n */\nfunction isMacPlatform(): boolean {\n const uaData = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData;\n return uaData\n ? uaData.platform === \"macOS\"\n : (navigator.platform?.includes(\"Mac\") ?? /Macintosh|Mac OS X/i.test(navigator.userAgent));\n}\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n icon: string;\n}\n\n/**\n * Optional async hook called when the user clicks \"Send\". While the returned\n * promise is pending the popup stays visible in a submitting state (spinner\n * on the submit button, every other control disabled). On resolution the\n * popup closes and `show()` resolves with the submitted result; on rejection\n * the popup restores so the user can retry without re-entering the form.\n */\ntype PopupSubmitHandler = (result: PopupResult) => Promise<void>;\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private cancelBtn: HTMLButtonElement;\n private typeRow: HTMLElement;\n private submitLabel: HTMLSpanElement;\n private hint: HTMLElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n private onSubmit: PopupSubmitHandler | null = null;\n private submittingState = false;\n /** WAAPI handle for the running spinner — cancelled when submitting ends. */\n private spinnerAnimation: Animation | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: `\n position:fixed;\n z-index:${Z_INDEX_MAX};\n width:300px;\n padding:16px;\n border-radius:16px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border:1px solid ${this.colors.glassBorder};\n box-shadow:0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n opacity:0;\n transform:translateY(8px) scale(0.98);\n transition:opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n display:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n // Screenshot capture now runs while the popup is still visible (so the\n // spinner can show during the upload). Without this attribute the popup\n // would appear baked into the captured JPEG.\n this.root.setAttribute(\"data-siteping-ignore\", \"true\");\n // The dialog `aria-label` is bound by `applyLabels()` at the end of the\n // constructor, alongside every other `t()`-derived string.\n\n // Type selector grid (2x2). Labels are bound later by `applyLabels()` —\n // the constructor only builds the structure (icon + empty label span).\n const typeOptions: TypeOption[] = [\n { type: \"question\", icon: ICON_QUESTION },\n { type: \"change\", icon: ICON_CHANGE },\n { type: \"bug\", icon: ICON_BUG },\n { type: \"other\", icon: ICON_OTHER },\n ];\n this.typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n height:44px;\n border-radius:9999px;border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};cursor:pointer;\n display:flex;align-items:center;justify-content:center;gap:5px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;color:${this.colors.textTertiary};\n transition:all 0.2s ease;\n padding:0 12px;\n `;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n btn.appendChild(document.createElement(\"span\"));\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n if (this.submittingState) return;\n this.selectType(option.type, this.typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n this.typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = `\n width:100%;min-height:72px;max-height:152px;\n padding:10px 12px;border-radius:12px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBgHeavy};\n color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;line-height:1.5;resize:vertical;\n outline:none;transition:all 0.2s ease;\n box-sizing:border-box;\n `;\n this.textarea.maxLength = 5000;\n\n // Keyboard shortcut hint\n this.hint = el(\"div\", {\n style: `\n font-size:11px;color:${this.colors.textTertiary};\n text-align:right;margin-top:4px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n letter-spacing:0.01em;\n `,\n });\n\n this.textarea.addEventListener(\"focus\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (this.submittingState) return;\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n this.cancel();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n this.cancelBtn = document.createElement(\"button\");\n this.cancelBtn.style.cssText = `\n height:34px;padding:0 16px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n this.cancelBtn.addEventListener(\"click\", () => this.cancel());\n this.cancelBtn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.accent;\n this.cancelBtn.style.color = this.colors.accent;\n });\n this.cancelBtn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.border;\n this.cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:none;background:${this.colors.accentGradient};\n color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:600;cursor:pointer;\n opacity:0.35;pointer-events:none;\n transition:all 0.2s ease;\n box-shadow:0 2px 8px ${this.colors.accentGlow};\n display:inline-flex;align-items:center;justify-content:center;min-width:64px;\n `;\n // The submit label lives in its own <span> so the submitting-state spinner\n // can be appended/removed without disturbing it. `applyLabels()` binds its\n // text — never `setText` the button itself or it would wipe the spinner.\n this.submitLabel = document.createElement(\"span\");\n this.submitBtn.appendChild(this.submitLabel);\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(this.cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(this.typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(this.hint);\n this.root.appendChild(btnRow);\n document.body.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n }\n\n /**\n * Re-read every `t(...)`-derived label, placeholder, and aria-label from\n * the active translation function. Idempotent — call after the locale\n * dictionary has finished loading so the popup swaps from the English\n * fallback to the configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the dialog `aria-label`, the four type-button labels, the textarea\n * `placeholder` + `aria-label`, the `⌘+Enter` / `Ctrl+Enter` hint, and the\n * cancel/submit `textContent`. The single source of truth for which node\n * gets which `t()` string, shared by the constructor and `refreshLabels()`\n * so the two can never drift.\n */\n private applyLabels(): void {\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n const typeButtons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of typeButtons) {\n const type = btn.dataset.type as FeedbackType | undefined;\n if (!type) continue;\n const key = TYPE_LABEL_KEYS[type];\n if (!key) continue;\n const labelSpan = btn.querySelector<HTMLSpanElement>(\"span\");\n if (labelSpan) setText(labelSpan, this.t(key));\n }\n\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n setText(this.hint, isMacPlatform() ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n setText(this.cancelBtn, this.t(\"popup.cancel\"));\n // Target the label <span>, not the button — the button also hosts the\n // submitting-state spinner, which `setText` on the button would erase.\n setText(this.submitLabel, this.t(\"popup.submit\"));\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n *\n * When `onSubmit` is provided the popup stays visible while the handler\n * runs — the submit button shows a spinner, every other control is\n * disabled. On success the popup closes; on rejection it restores so the\n * user can retry without re-entering the form.\n */\n show(rectBounds: DOMRect, onSubmit?: PopupSubmitHandler): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.resolve = resolve;\n this.onSubmit = onSubmit ?? null;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.submittingState = false;\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n // Position: bottom-left of rect, 8px below\n const popupH = 220;\n const popupW = 300;\n let top = rectBounds.bottom + 8;\n let left = rectBounds.left;\n\n // Vertical: prefer below; fall back to above; otherwise clamp inside viewport\n if (top + popupH > window.innerHeight) {\n const aboveTop = rectBounds.top - popupH - 8;\n if (aboveTop >= 8) {\n top = aboveTop;\n } else {\n // Rect is taller than the viewport allows on either side —\n // clamp to keep the popup fully visible.\n top = window.innerHeight - popupH - 8;\n }\n }\n // Collision: flip right if not enough space on left\n if (left + popupW > window.innerWidth) {\n left = rectBounds.right - popupW;\n }\n left = Math.max(8, left);\n top = Math.max(8, top);\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n this.root.style.display = \"block\";\n\n // Install focus trap\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n // Trigger animation\n requestAnimationFrame(() => {\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n this.textarea.focus();\n });\n });\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.disabled = false;\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n btn.style.cursor = \"pointer\";\n }\n }\n\n private updateSubmitState(): void {\n if (this.submittingState) return;\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (this.submittingState) return;\n if (!this.selectedType || !this.textarea.value.trim()) return;\n\n const result: PopupResult = { type: this.selectedType, message: this.textarea.value.trim() };\n\n if (!this.onSubmit) {\n // Legacy fire-and-forget path: resolve immediately and hide.\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n return;\n }\n\n this.enterSubmittingState();\n const submitter = this.onSubmit;\n submitter(result)\n .then(() => {\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n })\n .catch(() => {\n // Restore the form so the user can edit and retry. The caller is\n // responsible for surfacing the error (live region / toast) — we\n // intentionally do not show inline error text in the popup.\n this.exitSubmittingState();\n });\n }\n\n private cancel(): void {\n if (this.submittingState) return;\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n /**\n * Swap the submit button's text for a spinner and freeze every other\n * control. Mirrors the panel's resolve/delete buttons (`sp-spinner--sm`)\n * but renders inline because the popup lives outside the Shadow DOM\n * and therefore can't reach the panel's CSS classes.\n */\n private enterSubmittingState(): void {\n this.submittingState = true;\n\n // Submit: spinner instead of text, keep button width stable\n this.submitLabel.style.display = \"none\";\n this.submitBtn.disabled = true;\n this.submitBtn.style.cursor = \"wait\";\n this.submitBtn.style.opacity = \"0.85\";\n this.submitBtn.setAttribute(\"aria-busy\", \"true\");\n this.submitBtn.appendChild(this.buildSpinner());\n\n // Cancel: dimmed and non-interactive — abandoning mid-upload would leak a\n // half-sent feedback on the server, so we hold the user until we know.\n this.cancelBtn.disabled = true;\n this.cancelBtn.style.opacity = \"0.5\";\n this.cancelBtn.style.cursor = \"not-allowed\";\n this.cancelBtn.style.pointerEvents = \"none\";\n\n // Textarea + type buttons: read-only\n this.textarea.disabled = true;\n this.textarea.style.opacity = \"0.6\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = true;\n btn.style.cursor = \"not-allowed\";\n btn.style.opacity = \"0.6\";\n }\n }\n\n private exitSubmittingState(): void {\n this.submittingState = false;\n\n // Submit — tear down the spinner: cancel the WAAPI animation explicitly\n // (it has `iterations: Infinity`, so it never ends on its own) before\n // removing the element it drives.\n this.spinnerAnimation?.cancel();\n this.spinnerAnimation = null;\n const spinner = this.submitBtn.querySelector<HTMLDivElement>('[data-role=\"sp-popup-spinner\"]');\n spinner?.remove();\n this.submitLabel.style.display = \"\";\n this.submitBtn.removeAttribute(\"aria-busy\");\n this.submitBtn.style.cursor = \"pointer\";\n\n // Cancel\n this.cancelBtn.disabled = false;\n this.cancelBtn.style.opacity = \"1\";\n this.cancelBtn.style.cursor = \"pointer\";\n this.cancelBtn.style.pointerEvents = \"auto\";\n\n // Textarea + type buttons\n this.textarea.disabled = false;\n this.textarea.style.opacity = \"1\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = false;\n btn.style.cursor = \"pointer\";\n btn.style.opacity = \"1\";\n }\n\n // Recompute submit enabled state from the (preserved) form fields\n this.updateSubmitState();\n }\n\n /**\n * Build a spinner element styled inline. Web Animations API drives the\n * rotation so we don't have to inject `@keyframes` into the host document.\n * Respects `prefers-reduced-motion`: omits the animation and falls back to\n * a static ring. The returned `Animation` handle is stored on the instance\n * so `exitSubmittingState()` can explicitly cancel it.\n */\n private buildSpinner(): HTMLDivElement {\n const spinner = document.createElement(\"div\");\n spinner.dataset.role = \"sp-popup-spinner\";\n spinner.style.cssText = `\n width:14px;height:14px;\n border:2px solid rgba(255,255,255,0.35);\n border-top-color:#fff;\n border-radius:50%;\n box-sizing:border-box;\n `;\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n // Web Animations API is available in every browser we target; the guard\n // is defensive for jsdom in tests, where `animate` may be undefined.\n if (!reduceMotion && typeof spinner.animate === \"function\") {\n this.spinnerAnimation = spinner.animate([{ transform: \"rotate(0deg)\" }, { transform: \"rotate(360deg)\" }], {\n duration: 600,\n iterations: Infinity,\n easing: \"linear\",\n });\n }\n return spinner;\n }\n\n private hideElement(): void {\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n // Make sure the submitting decoration doesn't leak into the next show()\n if (this.submittingState) this.exitSubmittingState();\n this.onSubmit = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(8px) scale(0.98)\";\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n setTimeout(() => {\n this.root.style.display = \"none\";\n }, 250);\n }\n\n destroy(): void {\n // Settle a pending `show()` promise so it cannot outlive teardown — a\n // `destroy()` mid-submit would otherwise leak the awaiting closure (and\n // whatever it retains: the annotation, the base64 screenshot). Resolving\n // with `null` reads as \"cancelled\", matching `cancel()`.\n if (this.submittingState) this.exitSubmittingState();\n this.resolve?.(null);\n this.resolve = null;\n this.onSubmit = null;\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.root.remove();\n }\n}\n","/**\n * Screenshot capture via html2canvas.\n *\n * `html2canvas` is a regular `dependency` of `@siteping/widget` — every\n * install gets it. We dynamic-import it so bundlers emit a separate chunk\n * loaded only when `enableScreenshot: true` triggers the first capture;\n * hosts that never enable screenshots pay only the disk-space cost.\n *\n * On capture failure (content-tainted canvas, version mismatch, missing 2D\n * context) we return `null` rather than throwing — the feedback is still\n * submitted, just without an image.\n */\n\nimport type { ScreenshotRegion } from \"@siteping/core\";\n\ntype Html2CanvasFn = (element: HTMLElement, options?: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\n\ninterface Html2CanvasOptions {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n useCORS?: boolean;\n allowTaint?: boolean;\n logging?: boolean;\n ignoreElements?: (element: Element) => boolean;\n}\n\nlet cachedHtml2Canvas: Html2CanvasFn | null | undefined; // undefined = not loaded yet, null = failed\nlet warnedAboutMissingDep = false;\n\nasync function loadHtml2Canvas(): Promise<Html2CanvasFn | null> {\n if (cachedHtml2Canvas !== undefined) return cachedHtml2Canvas;\n try {\n // Static dynamic import — bundlers (Vite, webpack, esbuild) resolve this\n // at build time and emit a separate chunk loaded only on first capture.\n // html2canvas ships as a regular dependency so this resolves on every\n // install. Earlier attempts to dodge static resolution via magic comments\n // silently broke production: bare specifiers can't be resolved at runtime\n // in browsers without import maps.\n const mod = (await import(\"html2canvas\")) as { default?: Html2CanvasFn } & Html2CanvasFn;\n cachedHtml2Canvas = (mod.default ?? mod) as Html2CanvasFn;\n return cachedHtml2Canvas;\n } catch (err) {\n cachedHtml2Canvas = null;\n if (!warnedAboutMissingDep) {\n warnedAboutMissingDep = true;\n console.warn(\n \"[siteping] html2canvas import failed unexpectedly. Capture is disabled for this session — feedbacks are still submitted, just without screenshots. Underlying error:\",\n err,\n );\n }\n return null;\n }\n}\n\nexport interface CaptureOptions {\n /** JPEG quality 0..1 (default 0.85). */\n quality?: number;\n /** Max output width in CSS pixels (default 1200). Wider canvases are downscaled. */\n maxWidth?: number;\n}\n\n/** Result of a contextual capture: the JPEG plus where the drawn rect sits in it. */\nexport interface AnnotatedScreenshot {\n /** Base64 JPEG `data:` URL of the padded capture area. */\n dataUrl: string;\n /** The drawn rect's position within the image, as fractions of its dimensions. */\n region: ScreenshotRegion;\n}\n\n/** Clamp `value` into `[min, max]`. */\nfunction clamp(min: number, value: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Round a fraction to 4 decimals and clamp it into [0, 1]. */\nfunction roundPct(value: number): number {\n return clamp(0, Math.round(value * 10_000) / 10_000, 1);\n}\n\n/**\n * Capture the drawn rect *plus surrounding context* as a JPEG data URL, and\n * report where the rect sits inside the image (`region`, as fractions of the\n * image dimensions) so dashboards can re-render the annotation on top.\n * Returns `null` on any failure — callers should not abort feedback submission.\n *\n * - Pads the rect by up to 60% of its own size (48px floor, 280/220px ceiling)\n * so reviewers see the UI around the annotation, not just its pixels\n * - Clamps the capture area to the document bounds (no blank margins)\n * - Excludes Siteping's own overlay elements via `ignoreElements`\n * - Honors devicePixelRatio for crisp captures, then downscales to `maxWidth`\n * — `region` is resolution-independent, so it survives the downscale\n * - JPEG at `quality` (0.85 = ~50–150 KB for a typical annotated area)\n */\nexport async function captureAnnotatedScreenshot(\n rect: DOMRect,\n options?: CaptureOptions,\n): Promise<AnnotatedScreenshot | null> {\n const html2canvas = await loadHtml2Canvas();\n if (!html2canvas) return null;\n\n const quality = options?.quality ?? 0.85;\n const maxWidth = options?.maxWidth ?? 1200;\n\n // Contextual padding, proportional to the rect with fixed floor/ceiling —\n // small rects still get enough context to be recognizable, huge rects\n // don't balloon the capture (CSS px).\n const padX = clamp(48, rect.width * 0.6, 280);\n const padY = clamp(48, rect.height * 0.6, 220);\n\n // Document coordinates of the drawn rect (rect is viewport-relative).\n const docX = window.scrollX + rect.x;\n const docY = window.scrollY + rect.y;\n\n // Clamp the padded capture area to the document bounds so html2canvas\n // never renders blank out-of-document margins.\n const docW = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);\n const docH = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);\n const capX = Math.max(0, docX - padX);\n const capY = Math.max(0, docY - padY);\n const capW = Math.min(docW, docX + rect.width + padX) - capX;\n const capH = Math.min(docH, docY + rect.height + padY) - capY;\n if (capW <= 0 || capH <= 0) return null;\n\n // Fractions are resolution-independent — computed once from CSS-px\n // geometry, they stay valid after the hi-DPI render and the downscale.\n const region: ScreenshotRegion = {\n xPct: roundPct((docX - capX) / capW),\n yPct: roundPct((docY - capY) / capH),\n wPct: roundPct(rect.width / capW),\n hPct: roundPct(rect.height / capH),\n };\n\n try {\n const canvas = await html2canvas(document.body, {\n x: capX,\n y: capY,\n width: capW,\n height: capH,\n scale: window.devicePixelRatio,\n useCORS: true,\n allowTaint: true,\n logging: false,\n ignoreElements: (element: Element) => {\n // Matched elements (and their descendants) are removed from the\n // render pass — the page underneath shows through. Two layers of\n // exclusion:\n //\n // 1. The widget's own shadow host (`<siteping-widget>`).\n // 2. Anything carrying `data-siteping-ignore=\"true\"` — the\n // documented host-facing masking attribute AND how widget\n // chrome that lives OUTSIDE the shadow host (annotator overlay\n // + toolbar + drawing rect, popup) opts itself out of capture.\n // Without (2) the accent-colored selection border ends up\n // baked into the JPEG.\n return (\n element.tagName === \"SITEPING-WIDGET\" ||\n element.closest?.(\"siteping-widget\") !== null ||\n element.getAttribute?.(\"data-siteping-ignore\") === \"true\"\n );\n },\n });\n\n if (canvas.width <= maxWidth) {\n return { dataUrl: canvas.toDataURL(\"image/jpeg\", quality), region };\n }\n\n // Downscale via an off-DOM canvas — keeps payload reasonable on\n // hi-DPI displays where the raw capture can be 2x–3x intended size.\n const ratio = maxWidth / canvas.width;\n const targetW = maxWidth;\n const targetH = Math.round(canvas.height * ratio);\n\n const scaled = document.createElement(\"canvas\");\n scaled.width = targetW;\n scaled.height = targetH;\n const ctx = scaled.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(canvas, 0, 0, targetW, targetH);\n return { dataUrl: scaled.toDataURL(\"image/jpeg\", quality), region };\n } catch (err) {\n console.warn(\"[siteping] Screenshot capture failed:\", err);\n return null;\n }\n}\n\n/** @internal — exposed for tests. Resets the dynamic-import cache. */\nexport function _resetScreenshotCacheForTests(): void {\n cachedHtml2Canvas = undefined;\n warnedAboutMissingDep = false;\n}\n","import type { AnnotationPayload, FeedbackType, ScreenshotRegion } from \"@siteping/core\";\nimport { INSTANT_ANNOTATION_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport { type AnnotatedScreenshot, captureAnnotatedScreenshot } from \"./screenshot.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n /**\n * Base64 JPEG `data:` URL captured by html2canvas, or null when capture\n * is disabled / failed / the peer dep is missing.\n */\n screenshotDataUrl?: string | null | undefined;\n /**\n * Where the drawn rect sits within the captured screenshot, as fractions\n * of the image dimensions — see `ScreenshotRegion`. Null whenever\n * `screenshotDataUrl` is null.\n */\n screenshotRegion?: ScreenshotRegion | null | undefined;\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n /**\n * True when the current annotation session was triggered by right-click\n * (instant comment) rather than the FAB draw flow. Controls whether the\n * toolbar is shown and whether cancel deactivates unconditionally.\n */\n private instantMode = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n /**\n * Reject handle for the in-flight `runSubmission` promise, or null when no\n * submission is pending. Serves two purposes: a non-null value means a\n * submission is in flight (so pointer-driven drawing is suppressed — the\n * popup is open), and `destroy()` calls it to settle the promise rather\n * than leaving the awaiting closure hung past teardown.\n */\n private rejectPendingSubmission: ((reason: Error) => void) | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly enableScreenshot: boolean = false,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n /**\n * True while the annotator is active (overlay/popup session in progress).\n * The launcher checks this before calling `preventDefault()` on the\n * `contextmenu` event so a right-click during an active session falls\n * through to the native menu instead of being silently swallowed.\n */\n get isBusy(): boolean {\n return this.isActive;\n }\n\n /**\n * Re-read every `t(...)`-derived label inside the popup. The annotator's\n * own toolbar text is created fresh on every `activate()` call, so only\n * the long-lived popup needs explicit re-localization here.\n */\n refreshLabels(): void {\n this.popup.refreshLabels();\n }\n\n /**\n * True while a submission is in flight (popup open, `runSubmission`\n * pending). Drawing a second rectangle in this window would orphan the\n * first `popup.show()` promise and start a second, concurrent\n * `runSubmission` — so all drawing entry points are no-ops while it holds.\n */\n private get submissionInFlight(): boolean {\n return this.rejectPendingSubmission !== null;\n }\n\n /**\n * Capture a contextual screenshot of the drawn rect (padded with the\n * surrounding UI, plus the rect's region within the image) when\n * `enableScreenshot` is on. Returns null on disable / capture failure /\n * missing peer dep — the feedback is always submitted regardless.\n */\n private async maybeCapture(rect: DOMRect): Promise<AnnotatedScreenshot | null> {\n if (!this.enableScreenshot) return null;\n return captureAnnotatedScreenshot(rect);\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n const drawMode = !this.instantMode;\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth.\n //\n // Overlay, toolbar and the drawn rectangle live on document.body, outside\n // the siteping-widget shadow host. Without the `data-siteping-ignore`\n // marker the screenshot predicate in screenshot.ts cannot reach them —\n // and the accent-colored selection border plus the page tint end up\n // baked into the captured JPEG. See issue #124.\n this.overlay = el(\"div\", {\n style: `\n position:fixed;inset:0;\n z-index:${Z_INDEX_MAX - 1};\n background:rgba(15, 23, 42, 0.04);\n cursor:${drawMode ? \"crosshair\" : \"default\"};\n `,\n });\n // The overlay is an interactive surface (draw with the pointer, Enter to\n // annotate the previously focused element, Escape to cancel) and receives\n // programmatic focus below — so it must be exposed to assistive tech, NOT\n // aria-hidden: focusing an aria-hidden element parks screen-reader users\n // on a node that announces nothing (axe \"aria-hidden-focus\", serious).\n this.overlay.setAttribute(\"role\", \"application\");\n this.overlay.setAttribute(\n \"aria-label\",\n drawMode ? this.t(\"annotator.instruction\") : this.t(\"annotator.instantInstruction\"),\n );\n this.overlay.setAttribute(\"data-siteping-ignore\", \"true\");\n\n // Toolbar — glassmorphism bar (suppressed in instant mode: the\n // \"Draw a rectangle\" copy is wrong when the composer is already open)\n if (drawMode) {\n this.toolbar = el(\"div\", {\n style: `\n position:fixed;top:0;left:0;right:0;\n z-index:${Z_INDEX_MAX};\n height:52px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border-bottom:1px solid ${this.colors.glassBorder};\n display:flex;align-items:center;justify-content:center;gap:16px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:14px;color:${this.colors.text};\n box-shadow:0 4px 16px ${this.colors.shadow};\n -webkit-font-smoothing:antialiased;\n `,\n });\n this.toolbar.setAttribute(\"data-siteping-ignore\", \"true\");\n\n const dot = el(\"span\", {\n style: `\n width:8px;height:8px;border-radius:50%;\n background:${this.colors.accent};\n box-shadow:0 0 8px ${this.colors.accentGlow};\n animation:pulse 1.5s ease-in-out infinite;\n `,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instruction = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;\" });\n setText(instruction, this.t(\"annotator.instruction\"));\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.deactivate());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instruction);\n this.toolbar.appendChild(cancelBtn);\n }\n\n if (drawMode) {\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the pre-activation focused element\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n }\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n document.body.appendChild(this.overlay);\n if (this.toolbar) document.body.appendChild(this.toolbar);\n\n // Move focus to the overlay so the keyboard-annotation path (Enter →\n // annotate the element that was focused before activation) actually\n // receives keydown — onOverlayKeyDown only fires when the overlay itself\n // is focused. The overlay has tabindex=0, and preActiveFocusElement was\n // captured at the top of activate(), before the overlay existed, so\n // focusing here doesn't clobber the keyboard target. (WCAG 2.1.1 Level A)\n this.overlay.focus({ preventScroll: true });\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.instantMode = false;\n const previouslyFocused = this.preActiveFocusElement;\n this.preActiveFocusElement = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n // Removing the focused overlay drops focus to <body> — hand it back to the\n // element that had it before activation (WCAG 2.4.3 focus order). When\n // activation came from the FAB menu this element is the shadow host and\n // focus() is a no-op; the Fab restores itself on annotation:end instead.\n if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) {\n previouslyFocused.focus({ preventScroll: true });\n }\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.deactivate();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the element that was focused before activation and creates a full-bounds\n * annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n // A submission is already running with the popup open — ignore so we\n // can't orphan the first `popup.show()` / `runSubmission` pair.\n if (this.submissionInFlight) return;\n\n const target = this.preActiveFocusElement;\n if (!target || !(target instanceof HTMLElement)) return;\n\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n // Submission stays inside the popup so the user gets a visible spinner\n // until the server confirms — see finishDrawing for the rationale.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n if (result) this.deactivate();\n };\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n // Suppress pointer-driven drawing while a submission is in flight: the\n // popup is open over the page, and starting a second rectangle would\n // orphan the first `popup.show()` promise (and its `runSubmission`).\n // This also closes a latent bug where drawing during the open popup\n // already overwrote `Popup.resolve`.\n if (this.submissionInFlight) return;\n\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n transition:box-shadow 0.15s ease;\n `,\n });\n // Excluded from screenshot capture (see overlay creation in activate()).\n this.drawingRect.setAttribute(\"data-siteping-ignore\", \"true\");\n this.overlay?.appendChild(this.drawingRect);\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (touch) await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < 10 || h < 10) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Build annotation payload BEFORE the popup opens — the overlay is still\n // up so `findAnchorElement` can briefly disable pointer events on it.\n const { annotation } = this.buildAnnotation(rectBounds);\n\n // Keep the drawn rectangle visible while the popup is open so the user\n // can see what they're sending feedback about — including while the\n // submit-spinner is running. We only remove it after the popup closes.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n /**\n * Instantly triggers the annotation popup at a specific location without\n * requiring the user to draw a rectangle. Used for right-click commenting.\n *\n * Entry is routed through the event bus (`annotation:start`) so the public\n * event contract (`onAnnotationStart` / `onAnnotationEnd`) is honoured —\n * hosts that pause analytics or chat widgets on annotation hooks see a\n * symmetric start/end pair regardless of entry path.\n */\n public async startInstantAnnotation(clientX: number, clientY: number): Promise<void> {\n // Guard: no-op while the annotator is active (overlay/popup session in\n // progress). `isActive` covers the entire window: draw mode in progress,\n // popup open for typing, and submission in flight. Without this a second\n // right-click (e.g. to paste in the textarea) would reset the form,\n // orphan the pending popup.show(), and leak the old drawing rect.\n if (this.isActive) return;\n\n // Set instant-mode flag BEFORE emitting annotation:start so activate()\n // (called by the bus handler) can read it and suppress the toolbar.\n this.instantMode = true;\n this.bus.emit(\"annotation:start\");\n\n // Build a small point-rect centered at the cursor for the marker/percentage\n // math. Clamped to viewport edges on all sides.\n const x = Math.max(0, Math.min(clientX - INSTANT_ANNOTATION_SIZE / 2, window.innerWidth - INSTANT_ANNOTATION_SIZE));\n const y = Math.max(\n 0,\n Math.min(clientY - INSTANT_ANNOTATION_SIZE / 2, window.innerHeight - INSTANT_ANNOTATION_SIZE),\n );\n const pointRect = new DOMRect(x, y, INSTANT_ANNOTATION_SIZE, INSTANT_ANNOTATION_SIZE);\n\n // Resolve the anchor element and build the annotation payload.\n // We also derive the capture rect from the anchor element's bounding box\n // (clamped to the viewport) so enableScreenshot produces a useful image\n // instead of a postage stamp.\n const { annotation, anchorBounds } = this.buildAnnotation(pointRect);\n\n // Use the anchor element's bounding box (clamped to viewport) for\n // screenshot capture so reviewers get meaningful context, not a 20×20 px\n // postage stamp.\n const left = Math.max(0, anchorBounds.left);\n const top = Math.max(0, anchorBounds.top);\n const captureRect = new DOMRect(\n left,\n top,\n Math.max(0, Math.min(anchorBounds.right, window.innerWidth) - left),\n Math.max(0, Math.min(anchorBounds.bottom, window.innerHeight) - top),\n );\n\n // Create a visual indicator at the click point\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n left:${x}px;\n top:${y}px;\n width:${INSTANT_ANNOTATION_SIZE}px;\n height:${INSTANT_ANNOTATION_SIZE}px;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n `,\n });\n this.drawingRect.setAttribute(\"data-siteping-ignore\", \"true\");\n this.overlay?.appendChild(this.drawingRect);\n\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n await this.popup.show(pointRect, (formResult) =>\n this.runSubmission(annotation, formResult, captureRect, screenshotCache),\n );\n\n // Instant flow: always deactivate on popup close — unlike the draw flow\n // where cancel keeps the session alive so the user can re-draw, there is\n // no draw phase to return to here. Leaving the overlay, scroll-lock and\n // toolbar up after cancel strands the user in a mode they never opted into.\n this.drawingRect?.remove();\n this.drawingRect = null;\n this.deactivate();\n }\n\n /**\n * Submit handler passed into `popup.show()`. Captures the screenshot once\n * (cached across retries) and emits `annotation:complete` on the bus, then\n * waits for one of three terminal signals:\n *\n * - `feedback:sent` — resolve (popup closes).\n * - `feedback:error` — reject with the genuine error (popup restores for\n * retry; the launcher surfaces the error to the host).\n * - `submission:cancelled` — reject as a silent abort (popup restores; no\n * error is surfaced — e.g. the user cancelled the identity prompt).\n *\n * Submissions are serialized by the drawing guards (`submissionInFlight`),\n * so exactly one `runSubmission` is ever live — the global outcome events\n * cannot cross-wire between submissions and need no correlation id.\n */\n private async runSubmission(\n annotation: AnnotationPayload,\n formResult: { type: FeedbackType; message: string },\n rectBounds: DOMRect,\n screenshotCache: { value?: AnnotatedScreenshot | null },\n ): Promise<void> {\n // Screenshot capture is the slow part. Capture once and reuse the\n // cached data URL + region on every retry — re-running html2canvas after\n // each failed submit would punish the user for a network blip.\n if (screenshotCache.value === undefined) {\n screenshotCache.value = await this.maybeCapture(rectBounds);\n }\n const capture = screenshotCache.value;\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n unsubSent();\n unsubError();\n unsubCancelled();\n this.rejectPendingSubmission = null;\n };\n const unsubSent = this.bus.on(\"feedback:sent\", () => {\n cleanup();\n resolve();\n });\n const unsubError = this.bus.on(\"feedback:error\", (err) => {\n cleanup();\n reject(err);\n });\n const unsubCancelled = this.bus.on(\"submission:cancelled\", () => {\n cleanup();\n // Silent abort — the popup restores but no error is surfaced.\n reject(new Error(\"Feedback submission cancelled\"));\n });\n\n // Expose the reject handle so `destroy()` mid-submit can settle this\n // promise instead of leaving the awaiting closure hung past teardown.\n this.rejectPendingSubmission = (reason) => {\n cleanup();\n reject(reason);\n };\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: formResult.type,\n message: formResult.message,\n screenshotDataUrl: capture?.dataUrl ?? null,\n screenshotRegion: capture?.region ?? null,\n });\n });\n }\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): { annotation: AnnotationPayload; anchorBounds: DOMRect } {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n const annotation = {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n return { annotation, anchorBounds };\n }\n destroy(): void {\n this.deactivate();\n // Settle an in-flight submission BEFORE tearing down the popup, so the\n // `runSubmission` promise cannot outlive teardown. The launcher's\n // `destroy()` also calls `bus.removeAll()`, which would otherwise strip\n // the terminal-event listeners and leave the promise — and the base64\n // screenshot it retains — hung forever.\n this.rejectPendingSubmission?.(new Error(\"Annotator destroyed during submission\"));\n this.popup.destroy();\n }\n}\n","import {\n type FeedbackPayload,\n type FeedbackResponse,\n type FeedbackResponseList,\n type FeedbackStatus,\n type FeedbackType,\n SitepingAuthError,\n SitepingError,\n SitepingNetworkError,\n SitepingValidationError,\n} from \"@siteping/core\";\nimport type { Identity } from \"./identity.js\";\n\n/**\n * Map a non-OK Response to the appropriate typed error.\n * - 401 / 403 → `SitepingAuthError`\n * - 4xx → `SitepingValidationError`\n * - 5xx (or anything else) → generic `SitepingError`\n *\n * We consume the response body via `.text()` so the caller can keep the\n * server-supplied message in the thrown error. `text()` is awaited inside\n * a try/catch because some upstreams return `Content-Length: 0` with a\n * non-text type and `.text()` rejects.\n */\nasync function errorFromResponse(response: Response, label: string): Promise<SitepingError> {\n // Match the legacy fallback string (\"Unknown error\") so host apps that\n // already grep error messages don't break on the migration.\n const text = await response.text().catch(() => \"Unknown error\");\n const detail = text ? `${response.status} ${text}` : `${response.status}`;\n const message = `${label}: ${detail}`;\n if (response.status === 401 || response.status === 403) return new SitepingAuthError(message);\n if (response.status >= 400 && response.status < 500) return new SitepingValidationError(message);\n return new SitepingError(message, \"SERVER\", false);\n}\n\n/**\n * Normalise an exception thrown by `fetch` (or our timeout AbortController)\n * into a `SitepingNetworkError`. We treat AbortErrors as network failures\n * because in our code path they always come from the internal timeout, not\n * a user-driven cancellation.\n */\nfunction networkErrorFromException(error: unknown, label: string): SitepingNetworkError {\n if (error instanceof SitepingNetworkError) return error;\n const detail = error instanceof Error ? error.message : String(error);\n return new SitepingNetworkError(`${label}: ${detail}`);\n}\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/** Options accepted by `WidgetClient.getFeedbacks`. */\nexport interface GetFeedbacksOptions {\n page?: number;\n limit?: number;\n type?: FeedbackType;\n /** Exact single-status filter. For \"any of a set\" (bucket) semantics, use `statuses`. */\n status?: FeedbackStatus;\n /**\n * Bucket status filter — matches feedbacks whose status is any of these\n * values. Serialized to the wire as `statuses=<csv>` and wins over the exact\n * `status` filter server-side. Used by the panel's binary Open/Resolved tabs.\n */\n statuses?: readonly FeedbackStatus[];\n search?: string;\n /** Restrict to feedbacks created on this exact URL (path). */\n url?: string;\n /** Restrict to feedbacks created on this URL pattern (e.g. `/orders/:orderId`). */\n urlPattern?: string;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\nasync function resilientFetch(url: string, init: RequestInit, retries = MAX_RETRIES): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n\n if (attempt === retries) return response;\n } catch (error) {\n clearTimeout(timeout);\n if (attempt === retries) throw error;\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n\n throw new Error(\"Max retries exceeded\");\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ninterface RetryEntry {\n endpoint: string;\n payload: FeedbackPayload;\n}\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\nfunction readQueue(): RetryEntry[] {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return [];\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n const queue = readQueue();\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n } catch {\n // localStorage full or unavailable — silently drop\n }\n });\n}\n\nfunction normalizeName(value: string): string {\n return value.trim();\n}\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Flush queued feedbacks for `endpoint`. When `currentIdentity` is provided,\n * entries whose stored author doesn't match it are dropped rather than replayed.\n * This prevents user A's offline feedback from being POSTed under user B's\n * identity after a session change. When omitted, all entries are replayed to\n * preserve the legacy behavior for callers that don't track identity.\n */\nexport async function flushRetryQueue(endpoint: string, currentIdentity?: Identity | null): Promise<void> {\n await withRetryLock(async () => {\n try {\n const queue = readQueue();\n if (queue.length === 0) return;\n\n const toRetry: RetryEntry[] = [];\n const unrelated: RetryEntry[] = [];\n let dropped = 0;\n\n for (const entry of queue) {\n if (entry.endpoint !== endpoint) {\n unrelated.push(entry);\n continue;\n }\n\n if (\n !currentIdentity ||\n (normalizeName(entry.payload.authorName) === normalizeName(currentIdentity.name) &&\n normalizeEmail(entry.payload.authorEmail) === normalizeEmail(currentIdentity.email))\n ) {\n toRetry.push(entry);\n } else {\n dropped += 1;\n }\n }\n\n if (toRetry.length === 0 && dropped === 0) return;\n\n if (dropped > 0) {\n console.debug(\"[siteping] flushRetryQueue: dropped\", dropped, \"stale entries (identity changed)\");\n }\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n for (const entry of toRetry) {\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(entry.payload),\n });\n if (!res.ok) {\n failed.push(entry);\n }\n } catch {\n failed.push(entry);\n }\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = unrelated.concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/** Parse a JSON body and assert its TypeScript shape — server-side Zod is the source of truth. */\nasync function parseJsonAs<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\nexport class ApiClient implements WidgetClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n // Only put `screenshotRegion` on the wire when a region was actually\n // captured — servers that predate the field would otherwise reject an\n // explicit `screenshotRegion: null` on every legacy capture.\n const { screenshotRegion, ...rest } = payload;\n const body: FeedbackPayload = screenshotRegion ? { ...rest, screenshotRegion } : rest;\n // Match the legacy contract: every failure path (network or HTTP) queues\n // for retry. Tests + host apps already rely on this — narrowing to\n // network-only would be a silent behaviour change.\n try {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to send feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to send feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n } catch (error) {\n // Queue the wire shape (region stripped when absent) so a later\n // flushRetryQueue replays exactly what a fresh POST would send.\n queueForRetry(this.endpoint, body);\n throw error;\n }\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const params = new URLSearchParams({ projectName });\n if (options?.page) params.set(\"page\", String(options.page));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.type) params.set(\"type\", options.type);\n if (options?.status) params.set(\"status\", options.status);\n if (options?.statuses?.length) params.set(\"statuses\", options.statuses.join(\",\"));\n if (options?.search) params.set(\"search\", options.search);\n if (options?.url) params.set(\"url\", options.url);\n if (options?.urlPattern) params.set(\"urlPattern\", options.urlPattern);\n\n let response: Response;\n try {\n response = await resilientFetch(`${this.endpoint}?${params.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to fetch feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to fetch feedbacks\");\n }\n\n return parseJsonAs<FeedbackResponseList>(response);\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to update feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to update feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete feedback\");\n }\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ projectName, deleteAll: true }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete all feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete all feedbacks\");\n }\n }\n}\n","/**\n * Console buffer — capture the last N `console.{log,info,warn,error}` calls\n * so they ship with every feedback submission.\n *\n * Why a ring buffer:\n * - **bounded memory** even on chatty pages (1000s of logs/min during dev),\n * - **last-N is the relevant slice** for debugging — what was happening just\n * before the user noticed the bug, not the full session history.\n *\n * Why monkey-patching instead of `console.dir`/Performance Timeline:\n * - host code already uses plain `console.*` everywhere, and many libraries\n * only emit through console (no other observable),\n * - patching is reversible via `dispose()` so the widget never leaves state\n * behind on `destroy()`.\n */\n\nconst DEFAULT_MAX_ENTRIES = 50;\nconst MAX_MESSAGE_LENGTH = 500;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface ConsoleEntry {\n level: \"log\" | \"info\" | \"warn\" | \"error\";\n /** ISO 8601 timestamp captured at log time. */\n timestamp: string;\n /** Best-effort string representation of the console args. */\n message: string;\n}\n\nconst LEVELS: Array<ConsoleEntry[\"level\"]> = [\"log\", \"info\", \"warn\", \"error\"];\n\n/**\n * Best-effort stringification that never throws.\n *\n * - `Error` → `Error: message\\nstack` (capped to 500 chars overall).\n * - circular / huge objects → fall back to `Object#toString()` or `\"[Unserializable]\"`.\n * - all output is truncated to `MAX_MESSAGE_LENGTH` so a single 5MB log\n * doesn't blow up the buffer (Slack-style 500 chars per row is plenty).\n */\nfunction serializeArg(arg: unknown): string {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n if (arg instanceof Error) {\n return `${arg.name}: ${arg.message}${arg.stack ? `\\n${arg.stack}` : \"\"}`;\n }\n try {\n // Replacer drops cycles + functions; functions stringify-default to\n // undefined and disappear from the output, which is the right call (we\n // don't want random function bodies in a feedback payload).\n const seen = new WeakSet<object>();\n return JSON.stringify(arg, (_key, value: unknown) => {\n if (typeof value === \"function\") return \"[Function]\";\n if (typeof value === \"symbol\") return value.toString();\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value as object)) return \"[Circular]\";\n seen.add(value as object);\n }\n return value;\n });\n } catch {\n try {\n return String(arg);\n } catch {\n return \"[Unserializable]\";\n }\n }\n}\n\nfunction formatArgs(args: readonly unknown[]): string {\n let out = \"\";\n for (let i = 0; i < args.length; i++) {\n if (i > 0) out += \" \";\n out += serializeArg(args[i]);\n if (out.length >= MAX_MESSAGE_LENGTH) break;\n }\n if (out.length > MAX_MESSAGE_LENGTH) {\n out = `${out.slice(0, MAX_MESSAGE_LENGTH - 1)}…`;\n }\n return out;\n}\n\n/**\n * Bounded ring buffer of console messages.\n *\n * Construction installs the wrappers immediately. `dispose()` restores the\n * originals exactly once (calling it twice is a no-op). Designed to be safe\n * against re-entrant or interleaved instances — each wrapper closes over the\n * original method, not over any global, so multiple buffers can coexist\n * (each captures its own copy of the args).\n */\nexport class ConsoleBuffer {\n private readonly maxEntries: number;\n private readonly entries: ConsoleEntry[] = [];\n private originals = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n // Guard against pathological values — 0 disables silently, negative\n // numbers fall through to the default, and absurdly large numbers are\n // capped so a misuse can't OOM the page.\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 1000);\n\n if (typeof console === \"undefined\") return;\n\n for (const level of LEVELS) {\n const original = (console as unknown as Record<string, ((...args: unknown[]) => void) | undefined>)[level];\n if (typeof original !== \"function\") continue;\n this.originals.set(level, original);\n\n const buffer = this;\n const wrapped = function (this: unknown, ...args: unknown[]): void {\n try {\n buffer.push(level, args);\n } catch {\n // Capturing must never break the host's console — swallow any\n // unexpected error from serialization so the original call\n // (right below) always still runs.\n }\n original.apply(this ?? console, args);\n };\n // Preserve the function name so devtools still show \"console.log\"\n // (browsers display the wrapper's name in stack traces).\n try {\n Object.defineProperty(wrapped, \"name\", { value: level });\n } catch {\n // Older engines reject defineProperty on function name — best-effort only.\n }\n (console as unknown as Record<string, unknown>)[level] = wrapped;\n }\n }\n\n private push(level: ConsoleEntry[\"level\"], args: readonly unknown[]): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push({\n level,\n timestamp: new Date().toISOString(),\n message: formatArgs(args),\n });\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): ConsoleEntry[] {\n return this.entries.slice();\n }\n\n /** Restore the original console methods. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (typeof console === \"undefined\") return;\n for (const [level, original] of this.originals) {\n try {\n (console as unknown as Record<string, unknown>)[level] = original;\n } catch {\n // Console may be frozen in exotic environments — leave the wrapper\n // in place; it still proxies to the original via closure.\n }\n }\n this.originals.clear();\n }\n}\n","/**\n * Network buffer — capture the last N failed `fetch` / `XMLHttpRequest`\n * calls (HTTP >= 400 or network error) so they ship with each feedback.\n *\n * Captures only failures because:\n * - successful requests are usually irrelevant for the \"this thing is\n * broken\" workflow,\n * - keeping the volume tiny means we can ship the full payload to the\n * server without bloating Postgres.\n *\n * Both wrappers preserve the original semantics — return values, throws,\n * AbortController behaviour, etc. The only side effect is recording a\n * `NetworkEntry` on failure.\n */\n\nconst DEFAULT_MAX_ENTRIES = 20;\nconst MAX_URL_LENGTH = 2000;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface NetworkEntry {\n url: string;\n method: string;\n /** HTTP status or 0 when the request never reached the server (network error / CORS / abort). */\n status: number;\n /** End-to-end duration in ms, rounded to the nearest integer. */\n durationMs: number;\n /** ISO 8601 timestamp at the moment the request was initiated. */\n timestamp: string;\n}\n\nfunction truncateUrl(url: string): string {\n if (url.length <= MAX_URL_LENGTH) return url;\n return `${url.slice(0, MAX_URL_LENGTH - 1)}…`;\n}\n\nfunction urlString(input: unknown): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.href;\n // `Request` instances expose `.url`\n if (typeof input === \"object\" && input !== null && \"url\" in (input as { url?: unknown })) {\n const candidate = (input as { url?: unknown }).url;\n if (typeof candidate === \"string\") return candidate;\n }\n try {\n return String(input);\n } catch {\n return \"(unknown)\";\n }\n}\n\n/**\n * Bounded ring buffer of failed network requests.\n *\n * Construction monkey-patches `globalThis.fetch` and `XMLHttpRequest` and\n * stores the originals for `dispose()`. Wrappers are designed so that\n * multiple instances can coexist (each captures independently into its own\n * buffer, and the last one disposed restores the chain correctly via the\n * stored originals).\n */\nexport class NetworkBuffer {\n private readonly maxEntries: number;\n private readonly entries: NetworkEntry[] = [];\n private originalFetch: typeof fetch | null = null;\n private originalXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private originalXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 500);\n this.installFetch();\n this.installXhr();\n }\n\n private push(entry: NetworkEntry): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push(entry);\n }\n\n private installFetch(): void {\n if (typeof globalThis.fetch !== \"function\") return;\n const original = globalThis.fetch;\n this.originalFetch = original;\n\n const wrapped: typeof fetch = async (input, init) => {\n const startedAt = new Date();\n const t0 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const url = truncateUrl(urlString(input));\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n\n try {\n const response = await original(input, init);\n if (!response.ok) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: response.status,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n }\n return response;\n } catch (err) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: 0,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n throw err;\n }\n };\n\n globalThis.fetch = wrapped;\n }\n\n private installXhr(): void {\n if (typeof XMLHttpRequest === \"undefined\") return;\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n this.originalXhrOpen = originalOpen;\n this.originalXhrSend = originalSend;\n const buffer = this;\n\n // Store the open metadata on the XHR instance via a side-channel WeakMap\n // so each request is fully isolated even with concurrent opens.\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string; startedAt: Date; t0: number }>();\n\n proto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n try {\n meta.set(this, {\n method: method.toUpperCase(),\n url: truncateUrl(urlString(url)),\n startedAt: new Date(),\n t0: typeof performance !== \"undefined\" ? performance.now() : Date.now(),\n });\n } catch {\n // Ignore — metadata is best-effort, the underlying open() still runs.\n }\n // XHR.open has two overloaded signatures (3-arg sync, 5-arg async with\n // user/password). Cast to a loose function shape to forward every arg\n // without re-enumerating the overloads here.\n const looseOpen = originalOpen as unknown as (this: XMLHttpRequest, ...a: unknown[]) => void;\n return looseOpen.call(this, method, url, ...rest);\n } as typeof proto.open;\n\n proto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const info = meta.get(this);\n if (info) {\n // `loadend` fires for both success and failure — we just inspect the\n // status to decide whether to log. Use `once: true` so a re-sent XHR\n // doesn't accumulate listeners.\n const onEnd = () => {\n try {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const status = this.status; // 0 on network error / abort\n if (status === 0 || status >= 400) {\n buffer.push({\n url: info.url,\n method: info.method,\n status,\n durationMs: Math.round(t1 - info.t0),\n timestamp: info.startedAt.toISOString(),\n });\n }\n } catch {\n // Listener must not throw — would surface as an \"Uncaught\" in\n // the host's console and pollute their logs.\n }\n };\n try {\n this.addEventListener(\"loadend\", onEnd, { once: true });\n } catch {\n // Older engines without options object — fall back to plain listener.\n try {\n this.addEventListener(\"loadend\", onEnd);\n } catch {\n // No-op\n }\n }\n }\n return originalSend.call(this, body ?? null);\n } as typeof proto.send;\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): NetworkEntry[] {\n return this.entries.slice();\n }\n\n /** Restore the original fetch + XHR methods. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n if (this.originalFetch && typeof globalThis.fetch === \"function\") {\n try {\n globalThis.fetch = this.originalFetch;\n } catch {\n // Best-effort\n }\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n try {\n if (this.originalXhrOpen) XMLHttpRequest.prototype.open = this.originalXhrOpen;\n if (this.originalXhrSend) XMLHttpRequest.prototype.send = this.originalXhrSend;\n } catch {\n // Best-effort\n }\n }\n }\n}\n","import type {\n FeedbackResponse,\n SitepingPublicEventListener,\n SitepingPublicEvents,\n SitepingUnsubscribe,\n} from \"@siteping/core\";\nimport type { AnnotationComplete } from \"./annotator.js\";\n\n/** Listener signature for a single key of an `EventBus` event map. */\nexport type EventListener<E extends Record<keyof E, unknown[]>, K extends keyof E> = (...args: E[K]) => void;\n\n/**\n * Lightweight typed `EventEmitter` — zero dependencies.\n *\n * The generic constraint guarantees each event maps to a tuple of argument\n * types, so subscribers and emitters share the exact same shape.\n */\nexport class EventBus<E extends Record<keyof E, unknown[]>> {\n private readonly listeners = new Map<keyof E, Set<EventListener<E, keyof E>>>();\n\n on<K extends keyof E>(event: K, listener: EventListener<E, K>): SitepingUnsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as EventListener<E, keyof E>);\n\n return () => {\n set?.delete(listener as EventListener<E, keyof E>);\n };\n }\n\n off<K extends keyof E>(event: K, listener: EventListener<E, K>): void {\n this.listeners.get(event)?.delete(listener as EventListener<E, keyof E>);\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n (fn as (...a: E[K]) => void)(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\n/** Full internal event map — broader than the public surface exposed to hosts. */\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [FeedbackResponse[\"id\"]];\n \"feedback:all-deleted\": [];\n \"feedback:error\": [Error];\n /** Emitted whenever the marker set changes — payload is the open (unresolved) count for the current page. */\n \"markers:changed\": [number];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [AnnotationComplete];\n /**\n * Internal-only: a feedback submission was aborted by a benign user action\n * (e.g. cancelling the identity prompt). Distinct from `feedback:error` so a\n * cancellation does not surface through the host's `onError` callback. Not\n * part of `PublicWidgetEvents` — never exposed to consumers.\n */\n \"submission:cancelled\": [];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n/**\n * Subset of `WidgetEvents` exposed to consumers via `SitepingInstance`.\n *\n * Kept structurally identical to `SitepingPublicEvents` from `@siteping/core`\n * so the launcher can bridge between the two without runtime casts. The\n * `satisfies` clause locks that contract at compile time — drift in either\n * side surfaces here.\n */\nexport type PublicWidgetEvents = SitepingPublicEvents;\n\n/** Re-export the listener signature for ergonomics on the widget side. */\nexport type PublicWidgetEventListener<K extends keyof PublicWidgetEvents> = SitepingPublicEventListener<K>;\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_CLOSE, ICON_EDIT, ICON_EYE, ICON_EYE_OFF, ICON_LIST, ICON_SITEPING } from \"./icons.js\";\n\n/** Closed set of radial menu item ids — keeps the label lookup exhaustive. */\ntype RadialItemId = \"chat\" | \"annotate\" | \"toggle-annotations\";\n\ninterface RadialItem {\n id: RadialItemId;\n icon: string;\n iconAlt?: string;\n}\n\nconst ITEM_GAP = 54;\n\n// Stable mapping between radial item ids and their translation keys. The\n// label is fully derived from this map via `t()`, so the constructor and\n// `applyLabels()` share one source of truth for which node gets which string.\nconst ITEM_LABEL_KEYS: Record<RadialItemId, keyof Translations> = {\n chat: \"fab.messages\",\n annotate: \"fab.annotate\",\n \"toggle-annotations\": \"fab.annotations\",\n};\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n const isRight = position === \"bottom-right\";\n\n // Vertical stack above the FAB. Icons:\n // - list → opens the feedback sidebar (panel of feedbacks).\n // - edit → creates a new annotation (the action).\n // - eye → toggles marker visibility on the page (state).\n // The marker-visibility toggle is opt-out via `config.showAnnotationsToggle`:\n // default `true` preserves historical behavior, `false` removes the item from\n // the menu entirely (no DOM, no keyboard slot, no click handler).\n this.items = [\n { id: \"chat\", icon: ICON_LIST },\n { id: \"annotate\", icon: ICON_EDIT },\n ];\n if (config.showAnnotationsToggle !== false) {\n this.items.push({ id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF });\n }\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n label.style.cssText = isRight\n ? \"position:absolute; right:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\"\n : \"position:absolute; left:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n\n // Close radial menu on click outside.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /**\n * Re-read every `t(...)`-derived label and aria-label from the active\n * translation function. Idempotent — call after the locale dictionary has\n * finished loading so the FAB labels swap from the English fallback to the\n * configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the FAB `aria-label`, each radial item's `aria-label`, and each\n * `.sp-radial-label` `textContent`. The single source of truth for which\n * node gets which `t()` string, shared by the constructor and\n * `refreshLabels()` so the two can never drift.\n */\n private applyLabels(): void {\n this.fab.setAttribute(\"aria-label\", this.t(\"fab.aria\"));\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n for (const btn of buttons) {\n const id = btn.dataset.itemId as RadialItemId | undefined;\n if (!id) continue;\n const key = ITEM_LABEL_KEYS[id];\n if (!key) continue;\n const label = this.t(key);\n btn.setAttribute(\"aria-label\", label);\n const labelSpan = btn.querySelector<HTMLSpanElement>(\".sp-radial-label\");\n if (labelSpan) setText(labelSpan, label);\n }\n }\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", this.t(\"fab.badge\").replace(\"{count}\", String(count)));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + ITEM_GAP * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: RadialItemId): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\": {\n // close() above re-focused the FAB, so the annotator can only capture\n // the shadow host as its pre-activation element — restoring focus is\n // on us: put keyboard users back on the FAB when the session ends.\n const unsubscribe = this.bus.on(\"annotation:end\", () => {\n unsubscribe();\n this.fab.focus();\n });\n this.bus.emit(\"annotation:start\");\n break;\n }\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n // Replace ONLY the icon SVG, not every child. The button also carries\n // the `<span class=\"sp-radial-label\">` hover label — `replaceChildren`\n // wiped it on the first click, killing the tooltip until reload.\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n const oldSvg = btn?.querySelector(\"svg\");\n if (oldSvg) {\n const newSvg = parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF);\n oldSvg.replaceWith(newSvg);\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick);\n this.root.remove();\n }\n}\n","import { hasOwn } from \"@siteping/core\";\n\nconst STORAGE_KEY = \"siteping_identity\";\n\nexport interface Identity {\n name: string;\n email: string;\n}\n\n/** Type guard — narrows an unknown value to `Identity` only when both fields are non-empty strings. */\nfunction isIdentity(value: unknown): value is Identity {\n if (!hasOwn(value, \"name\") || !hasOwn(value, \"email\")) return false;\n const name = (value as { name: unknown }).name;\n const email = (value as { email: unknown }).email;\n return typeof name === \"string\" && typeof email === \"string\" && name.length > 0 && email.length > 0;\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return isIdentity(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n * Uses Levenshtein distance, optimized for short strings (~50 chars).\n */\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are valid: i-1 in [0, aLen-1], j-1 in [0, bLen-1], loop bounds guarantee access\n const prevDiag = prev[i - 1] ?? 0;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] ?? 0, curr[i - 1] ?? 0);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] ?? 0; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Slides a window of `needle.length` over the haystack and returns the best\n * similarity score found. Returns 0 if below `minScore`.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const nLen = needle.length;\n\n // If needle is longer than haystack, compare directly\n if (nLen > haystack.length) {\n const score = similarity(haystack, needle);\n return score >= minScore ? score : 0;\n }\n\n let best = 0;\n\n // Cap haystack to avoid O(n²) on huge text nodes\n const capped = haystack.length > 500 ? haystack.slice(0, 500) : haystack;\n const limit = capped.length - nLen;\n\n for (let i = 0; i <= limit; i++) {\n const window = capped.slice(i, i + nLen);\n const score = similarity(window, needle);\n if (score > best) best = score;\n if (best >= 0.95) break;\n }\n\n return best >= minScore ? best : 0;\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { ANCHOR_KEY_ATTR } from \"./anchor.js\";\nimport { scoreFingerprint } from \"./fingerprint.js\";\nimport { fuzzyIncludes, similarity } from \"./fuzzy.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\n\nexport type ResolutionStrategy = \"anchorKey\" | \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/** Max elements to scan during smart fallback. */\nconst MAX_SCAN_CANDIDATES = 300;\n\n/** Minimum fuzzy text match score for CSS/XPath verification. */\nconst TEXT_MATCH_THRESHOLD = 0.3;\n\n/**\n * Verify that a resolved element's text content matches the stored snippet.\n * If no snippet is stored, returns true (no verification possible).\n * Uses fuzzy matching to tolerate minor text changes.\n */\nfunction textMatches(el: Element, anchor: AnchorData): boolean {\n if (!anchor.textSnippet) return true;\n const text = (el.textContent?.trim() ?? \"\").slice(0, 500);\n return fuzzyIncludes(text, anchor.textSnippet, 0.5) > TEXT_MATCH_THRESHOLD;\n}\n\n/**\n * Re-anchor an annotation using a multi-level fallback strategy\n * with text verification and confidence scoring.\n *\n * Resolution order:\n * 0. Semantic anchor key (`[data-feedback-anchor=\"X\"]`) — confidence 1.0\n * when host explicitly tagged the section. Tag name is NOT enforced —\n * hosts may legitimately refactor the wrapper element while keeping the\n * semantic key stable.\n * 1. getElementById + text verification — confidence 1.0\n * 2. CSS selector + text verification — confidence 0.95\n * 3. XPath + text verification — confidence 0.9\n * 4. Smart scan (fingerprint + text + prefix/suffix + neighbor) — up to 0.85\n *\n * Text verification prevents false matches when DOM elements are reordered.\n * Returns null if all strategies fail (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData): AnchorResolution | null {\n // Level 0: Semantic anchor key (host-controlled, most stable)\n if (anchor.anchorKey) {\n // Escape backslash and double-quote so an arbitrary key never breaks the selector\n const escaped = anchor.anchorKey.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const el = document.querySelector(`[${ANCHOR_KEY_ATTR}=\"${escaped}\"]`);\n // Skip tagName check — semantic anchor identifies a section, not a tag\n if (el && textMatches(el, anchor)) {\n return { element: el, confidence: 1.0, strategy: \"anchorKey\" };\n }\n } catch {\n // Invalid attribute value — fall through to next strategy\n }\n }\n\n // Level 1: Element ID (most stable, still verify text)\n if (anchor.elementId) {\n const el = document.getElementById(anchor.elementId);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 1.0, strategy: \"id\" };\n }\n }\n\n // Level 2: CSS Selector (with text verification)\n try {\n const el = document.querySelector(anchor.cssSelector);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.95, strategy: \"css\" };\n }\n } catch {\n // Invalid selector — skip\n }\n\n // Level 3: XPath (with text verification)\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n const el = result.singleNodeValue;\n if (el instanceof Element && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.9, strategy: \"xpath\" };\n }\n } catch {\n // Invalid XPath — skip\n }\n\n // Level 4: Smart scan — combine all available signals\n return smartScan(anchor);\n}\n\n/**\n * Scan DOM elements by tag and score each candidate using multiple signals:\n * fingerprint, text similarity, prefix/suffix context, neighbor text.\n *\n * Returns the best candidate above a 0.4 threshold, capped at 0.85 confidence\n * (smart scan is never 100% certain).\n */\nfunction smartScan(anchor: AnchorData): AnchorResolution | null {\n const tag = anchor.elementTag.toLowerCase();\n const candidates = document.querySelectorAll(tag);\n if (candidates.length === 0) return null;\n\n let bestElement: Element | null = null;\n let bestScore = 0;\n\n const limit = Math.min(candidates.length, MAX_SCAN_CANDIDATES);\n\n for (let i = 0; i < limit; i++) {\n const el = candidates[i];\n if (!el) continue;\n const score = scoreCandidate(el, anchor);\n if (score > bestScore) {\n bestScore = score;\n bestElement = el;\n if (bestScore >= 0.85) break;\n }\n }\n\n if (!bestElement || bestScore < 0.4) return null;\n\n return {\n element: bestElement,\n confidence: Math.min(bestScore, 0.85),\n strategy: \"scan\",\n };\n}\n\n/**\n * Score a candidate element against all stored anchor signals.\n *\n * Dynamic weighting — only active signals contribute, then normalized:\n * - Text snippet (fuzzy substring match): weight 40 (most reliable for reordering)\n * - Fingerprint (structural match): weight 20\n * - Prefix/suffix context: weight 20\n * - Neighbor text: weight 20\n */\nfunction scoreCandidate(candidate: Element, anchor: AnchorData): number {\n let score = 0;\n let totalWeight = 0;\n\n // Truncate to avoid O(n*m) explosion on huge text nodes\n const candidateText = (candidate.textContent?.trim() ?? \"\").slice(0, 500);\n\n // --- Text snippet (weight 40 — most important for reordered elements) ---\n if (anchor.textSnippet) {\n totalWeight += 40;\n score += fuzzyIncludes(candidateText, anchor.textSnippet, 0.5) * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (anchor.fingerprint) {\n totalWeight += 20;\n score += scoreFingerprint(candidate, anchor.fingerprint) * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (anchor.textPrefix || anchor.textSuffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (anchor.textPrefix) {\n const prevText = adjacentText(candidate, \"before\");\n contextScore += prevText ? similarity(prevText, anchor.textPrefix) : 0;\n contextParts++;\n }\n\n if (anchor.textSuffix) {\n const nextText = adjacentText(candidate, \"after\");\n contextScore += nextText ? similarity(nextText, anchor.textSuffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n score += (contextScore / contextParts) * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (anchor.neighborText) {\n totalWeight += 20;\n const candidateNeighbor = neighborText(candidate);\n score += candidateNeighbor ? similarity(candidateNeighbor, anchor.neighborText) * 20 : 0;\n }\n\n return totalWeight > 0 ? score / totalWeight : 0;\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(anchor: AnchorData, rect: RectData): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import { type AnchorData, type FeedbackResponse, isClosedStatus, type RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n anchorKey: a.anchorKey ?? null,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): { top: number; left: number } {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n elements: HTMLElement[];\n baseTop: number;\n baseLeft: number;\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n /** Last `openCount` broadcast via `markers:changed` (-1 = never emitted). */\n private lastOpenCount = -1;\n\n get count(): number {\n return this.entries.length;\n }\n\n get openCount(): number {\n let count = 0;\n for (const entry of this.entries) {\n // Anything not closed (open, in_progress) still needs attention.\n if (!isClosedStatus(entry.feedback.status)) count++;\n }\n return count;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly liveRegion: HTMLElement | null = null,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition();\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition();\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant\n // changes. Filtering short-circuits at the first non-widget mutation, so\n // even large batches stop after one DOM walk.\n //\n // The filter is applied unconditionally — earlier versions had a >20-batch\n // fast-path that skipped filtering, but that lets reposition self-trigger\n // when `repositionAll` re-renders the pinned highlight (showHighlight\n // appends N elements to `this.container`); a host page churning lots of\n // DOM (infinite scroll) would then loop at the 200ms debounce interval.\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition();\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters);\n }\n\n private scheduleReposition(): void {\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n if (cachedEl?.isConnected) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else {\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n }\n\n if (!resolved) {\n markerEl.style.display = \"none\";\n continue;\n }\n\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n\n this.applyClusterPositions();\n\n // Re-render the pinned highlight rectangle so it tracks the layout after\n // resize / SPA mutation. Marker dots reposition above; without this,\n // the highlight rect keeps its old pixel position and visibly drifts\n // away from the underlying content.\n if (this.pinnedFeedback) {\n this.showHighlight(this.pinnedFeedback);\n }\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n /**\n * Emit `markers:changed` only when the open count actually moved.\n *\n * Mutations that re-render the same set (panel search keystrokes, filter\n * toggles, \"load more\") all call `render()` without changing the page's\n * open count — emitting unconditionally would rebuild the FAB badge DOM on\n * every keystroke. The `-1` sentinel guarantees the first render still\n * emits, even when the page has zero open feedbacks.\n */\n private emitMarkersChanged(): void {\n const openCount = this.openCount;\n if (openCount === this.lastOpenCount) return;\n this.lastOpenCount = openCount;\n this.bus.emit(\"markers:changed\", openCount);\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n // Announce the number of visible markers to assistive tech (WCAG 4.1.3).\n // Skip the announcement when the host page has not provided a live\n // region (tests, embedded use cases) and when no marker is visible to\n // avoid noisy \"0 markers\" updates on every navigation.\n if (this.liveRegion && this.entries.length > 0) {\n this.liveRegion.textContent = this.t(\"marker.count\").replace(\"{count}\", String(this.entries.length));\n }\n this.emitMarkersChanged();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n this.emitMarkersChanged();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], baseTop: 0, baseLeft: 0 };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n const marker = this.createMarker(index, feedback, pos);\n this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n this.container.appendChild(marker);\n entry.elements.push(marker);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n const allItems: { entry: MarkerEntry; elIdx: number }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n allItems.push({ entry, elIdx: i });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.entry;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.entry;\n const dist = Math.sqrt((a.baseLeft - b.baseLeft) ** 2 + (a.baseTop - b.baseTop) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(b);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: `\n position:absolute;top:-6px;right:-6px;\n min-width:16px;height:16px;padding:0 4px;\n border-radius:9999px;\n background:${this.colors.accent};color:#fff;\n font-size:10px;font-weight:700;\n display:flex;align-items:center;justify-content:center;\n border:1.5px solid #fff;\n pointer-events:none;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n line-height:1;\n `,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = isClosedStatus(feedback.status);\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = this.t(\"marker.approximate\").replace(\"{confidence}\", String(Math.round(confidence * 100)));\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n // Closed feedbacks (resolved, wont_fix) render as muted checkmark markers.\n const isResolved = isClosedStatus(feedback.status);\n\n const marker = el(\"div\", {\n style: `\n position:absolute;\n top:${pos.top}px;\n left:${pos.left}px;\n width:26px;height:26px;\n border-radius:50%;\n background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};\n border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};\n display:flex;align-items:center;justify-content:center;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:11px;font-weight:700;\n color:${isResolved ? \"#94a3b8\" : typeColor};\n cursor:pointer;pointer-events:auto;\n box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};\n transition:top 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.15s ease, box-shadow 0.15s ease;\n user-select:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = this.t(\"marker.aria\")\n .replace(\"{number}\", String(number))\n .replace(\"{type}\", getTypeLabel(feedback.type, this.t))\n .replace(\"{message}\", truncatedMessage);\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n // WCAG 1.4.13 — tooltip must be reachable via keyboard (focus), not only\n // hover. Mirror mouseenter/mouseleave behaviour for focus/blur so a sighted\n // keyboard user gets the same affordance as a mouse user.\n marker.addEventListener(\"focus\", () => {\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"blur\", () => {\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n /**\n * Scroll the annotation into view, pin its highlight, and pulse its marker.\n *\n * Powers the `deepLink` config option and the public\n * `instance.focusFeedback(id)` method. Returns `false` when no entry\n * matches — caller logs that case, the manager stays silent.\n *\n * Scrolling uses the marker element's current document position via\n * `scrollIntoView`, not the original `scrollX/scrollY` captured at\n * annotation time. That keeps the focus correct after layout changes\n * (responsive breakpoints, lazy-loaded content) because the marker has\n * already been re-positioned to track the live anchor.\n */\n focusFeedback(feedbackId: string): boolean {\n const entry = this.entries.find((e) => e.feedback.id === feedbackId);\n if (!entry) return false;\n const markerEl = entry.elements[0];\n if (markerEl) {\n markerEl.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n this.pinHighlight(entry.feedback);\n this.highlight(feedbackId);\n return true;\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: `\n position:absolute;\n top:${rect.top + window.scrollY}px;\n left:${rect.left + window.scrollX}px;\n width:${rect.width}px;height:${rect.height}px;\n border:2px solid ${typeColor};\n background:${typeColor}0c;\n border-radius:8px;\n pointer-events:none;z-index:-1;\n opacity:0;\n box-shadow:0 0 16px ${typeColor}20;\n transition:opacity ${HIGHLIGHT_FADE}ms ease;\n `,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n type FeedbackResponseList,\n flattenAnnotation,\n type SitepingStore,\n} from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const record = await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n urlPattern: payload.urlPattern ?? null,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n screenshotDataUrl: payload.screenshotDataUrl ?? null,\n screenshotRegion: payload.screenshotRegion ?? null,\n diagnostics: payload.diagnostics ?? null,\n });\n\n return toResponse(record);\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n statuses: options?.statuses,\n search: options?.search,\n url: options?.url,\n urlPattern: options?.urlPattern,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, {\n status: resolved ? \"resolved\" : \"open\",\n resolvedAt: resolved ? new Date() : null,\n });\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n urlPattern: record.urlPattern ?? null,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n screenshotUrl: record.screenshotUrl ?? null,\n screenshotRegion: record.screenshotRegion ?? null,\n diagnostics: record.diagnostics ?? null,\n };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n anchorKey: ann.anchorKey ?? null,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = `\n /* ---- Keyframes ---- */\n\n @keyframes sp-fab-in {\n from {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n to {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes sp-fab-glow {\n 0%, 100% { box-shadow: 0 4px 20px var(--sp-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.08); }\n 50% { box-shadow: 0 4px 28px var(--sp-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.1); }\n }\n\n @keyframes sp-marker-in {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 60% {\n transform: scale(1.2);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n }\n }\n\n @keyframes sp-pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 var(--sp-accent-glow);\n }\n 70% {\n box-shadow: 0 0 0 8px transparent;\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n @keyframes sp-flash-bg {\n 0% { background-color: var(--sp-accent-light); }\n 100% { background-color: transparent; }\n }\n\n @keyframes sp-slide-up {\n from {\n transform: translateY(8px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n @keyframes sp-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes sp-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n /* ---- Animation classes ---- */\n\n .sp-anim-fab-in {\n animation: sp-fab-in 0.5s ${SPRING_LINEAR} both;\n }\n\n .sp-anim-marker-in {\n animation: sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;\n }\n\n .sp-anim-pulse {\n animation: sp-pulse-ring 0.7s ease-out;\n }\n\n .sp-anim-flash {\n animation: sp-flash-bg 0.5s ${EASE_OUT_QUART};\n }\n\n .sp-anim-slide-up {\n animation: sp-slide-up 0.3s ${EASE_OUT_EXPO} both;\n }\n\n .sp-anim-fade-in {\n animation: sp-fade-in 0.2s ease-out both;\n }\n\n /* ---- Transition utilities ---- */\n\n .sp-panel {\n transform: translateX(110%);\n transition: transform 0.4s ${EASE_OUT_EXPO};\n }\n\n .sp-panel.sp-panel--open {\n transform: translateX(0);\n }\n\n .sp-radial-item {\n opacity: 0;\n pointer-events: none;\n transform: translate(0, 0) scale(0.8);\n transition:\n transform 0.35s ${SPRING_OVERSHOOT},\n opacity 0.2s ease,\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n }\n\n .sp-radial-item.sp-radial-item--open {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Stagger delay via CSS custom property --sp-i */\n .sp-radial-item {\n transition-delay: calc(var(--sp-i, 0) * 50ms);\n }\n\n /* ---- Card stagger animation ---- */\n\n @keyframes sp-card-in {\n from {\n transform: translateY(12px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n .sp-card {\n animation: sp-card-in 0.35s ${EASE_OUT_EXPO} both;\n animation-delay: calc(var(--sp-card-i, 0) * 40ms);\n }\n\n /* ---- Loading spinner ---- */\n\n @keyframes sp-spin {\n to { transform: rotate(360deg); }\n }\n\n .sp-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--sp-border);\n border-top-color: var(--sp-accent);\n border-radius: 50%;\n animation: sp-spin 0.6s linear infinite;\n }\n\n /* ---- Badge bounce ---- */\n\n @keyframes sp-badge-in {\n 0% { transform: scale(0); }\n 60% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n }\n\n .sp-fab-badge {\n animation: sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n\n`;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return `\n :host {\n all: initial;\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n font-family: var(--sp-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--sp-text);\n /* Match native sub-controls (autofill, scrollbars, etc.) to the resolved theme */\n color-scheme: ${colors.bg === \"#ffffff\" ? \"light\" : \"dark\"};\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n ${cssVariables(colors)}\n\n /* Identity modal — theme-aware backdrop + panel */\n --sp-identity-bg: ${colors.glassBgHeavy};\n --sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ============================\n Focus visible (accessibility)\n ============================ */\n\n :focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: 2px;\n /* Double-ring against any background colour: the bg-coloured halo\n separates the accent ring from busy host-page surfaces. */\n box-shadow: 0 0 0 4px var(--sp-bg);\n }\n\n /* ============================\n FAB (Floating Action Button)\n ============================ */\n\n .sp-fab {\n position: fixed;\n width: 52px;\n height: 52px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-accent-gradient);\n color: #fff;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow:\n 0 4px 20px var(--sp-accent-glow),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.3s ease;\n outline: none;\n }\n\n .sp-fab:focus-visible {\n outline: 2px solid #fff;\n outline-offset: 3px;\n }\n\n .sp-fab:hover {\n transform: translateY(-2px) scale(1.05);\n box-shadow:\n 0 8px 28px var(--sp-accent-glow),\n 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .sp-fab:active {\n transform: translateY(0) scale(0.95);\n transition-duration: 0.1s;\n }\n\n .sp-fab--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-fab--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-fab svg {\n width: 22px;\n height: 22px;\n fill: currentColor;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n /* ---- FAB Badge ---- */\n\n .sp-fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: var(--sp-radius-full);\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid #fff;\n pointer-events: none;\n font-family: var(--sp-font);\n line-height: 1;\n }\n\n /* ============================\n Radial Menu\n ============================ */\n\n .sp-radial {\n position: fixed;\n pointer-events: none;\n width: 52px;\n height: 52px;\n }\n\n .sp-radial--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-radial--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-radial-item {\n position: absolute;\n left: 4px;\n bottom: 4px;\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n color: var(--sp-text);\n border: 1px solid var(--sp-glass-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--sp-shadow-md);\n font-size: 12px;\n font-weight: 600;\n }\n\n .sp-radial-item:hover,\n .sp-radial-item:focus-visible {\n background: rgba(255, 255, 255, 0.95);\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n box-shadow:\n var(--sp-shadow-md),\n 0 0 0 3px var(--sp-accent-light);\n outline: none;\n }\n\n .sp-radial-item svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n stroke: currentColor;\n fill: none;\n }\n\n .sp-radial-label {\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text);\n pointer-events: none;\n opacity: 0;\n padding: 4px 12px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n transform: translateX(4px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n\n .sp-radial-item:hover .sp-radial-label,\n .sp-radial-item:focus-visible .sp-radial-label {\n opacity: 1;\n transform: translateX(0);\n }\n\n /* ============================\n Panel (Side drawer)\n ============================ */\n\n .sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border-left: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n @media (max-width: 480px) {\n .sp-panel {\n width: 100vw;\n border-left: none;\n }\n }\n\n .sp-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: relative;\n z-index: 2;\n }\n\n .sp-panel-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-panel-close {\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n }\n\n .sp-panel-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-panel-close svg {\n width: 16px;\n height: 16px;\n }\n\n /* ============================\n Filters & Search\n ============================ */\n\n .sp-filters {\n padding: 16px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .sp-search-wrap {\n position: relative;\n margin-bottom: 12px;\n }\n\n .sp-search {\n width: 100%;\n height: 40px;\n padding: 0 12px 0 38px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 13px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-search::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-search:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--sp-text-tertiary);\n width: 16px;\n height: 16px;\n transition: color 0.2s ease;\n }\n\n .sp-search:focus ~ .sp-search-icon,\n .sp-search-wrap:focus-within .sp-search-icon {\n color: var(--sp-accent);\n }\n\n /* ============================\n Filter bar (type dropdown + status segmented)\n ============================ */\n\n .sp-filter-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n }\n\n /* ============================\n Type filter dropdown\n ============================ */\n\n .sp-filter-dropdown {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .sp-filter-dropdown-btn {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: var(--sp-glass-bg-heavy);\n\n display: inline-flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px 0 10px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-filter-dropdown-btn:hover {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--sp-chip-color) 14%, transparent);\n }\n\n .sp-filter-dropdown-btn--filtered {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-btn__icon svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-filter-dropdown-btn__label {\n display: inline-flex;\n align-items: baseline;\n gap: 6px;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sp-filter-dropdown-btn__prefix {\n color: var(--sp-text-tertiary);\n font-weight: 500;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .sp-filter-dropdown-btn__value {\n color: var(--sp-chip-color);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sp-filter-dropdown-btn__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-text-tertiary);\n transition: transform 0.18s ease, color 0.18s ease;\n }\n\n .sp-filter-dropdown-btn__chevron svg {\n width: 12px;\n height: 12px;\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron {\n transform: rotate(180deg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-filter-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-filter-menu-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .sp-filter-dropdown-option {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: transparent;\n\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: background 0.12s ease, color 0.12s ease;\n }\n\n .sp-filter-dropdown-option__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n flex-shrink: 0;\n border-radius: 6px;\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option__label {\n flex: 1;\n min-width: 0;\n }\n\n .sp-filter-dropdown-option__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__check svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-filter-dropdown-option--active {\n color: var(--sp-chip-color);\n font-weight: 600;\n }\n\n .sp-filter-dropdown-option--active:hover {\n background: var(--sp-chip-bg);\n }\n\n /* ============================\n Status segmented control\n ============================ */\n\n .sp-segmented {\n display: inline-flex;\n align-items: stretch;\n padding: 2px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n flex-shrink: 0;\n }\n\n .sp-segmented__btn {\n --sp-chip-color: var(--sp-text-tertiary);\n --sp-chip-bg: transparent;\n\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--sp-radius-full);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-segmented__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n transition: color 0.18s ease, transform 0.18s ease;\n }\n\n .sp-segmented__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-segmented__btn:hover {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn:hover .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--active {\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n font-weight: 600;\n box-shadow:\n inset 0 0 0 1px color-mix(in srgb, var(--sp-chip-color) 35%, transparent),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n\n .sp-segmented__btn--active .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: sp-segmented-pulse 2.4s ease-in-out infinite;\n }\n\n @keyframes sp-segmented-pulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(0.85); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sp-filter-dropdown-btn,\n .sp-filter-dropdown-btn__chevron,\n .sp-filter-dropdown-option,\n .sp-segmented__btn,\n .sp-segmented__icon {\n transition: none;\n }\n .sp-filter-dropdown-menu {\n animation: none;\n }\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: none;\n }\n }\n\n /* ============================\n Feedback Cards\n ============================ */\n\n .sp-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n }\n\n .sp-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-list::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-list::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n .sp-card {\n display: flex;\n padding: 14px 16px;\n margin-bottom: 6px;\n cursor: pointer;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xs);\n transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .sp-card:hover {\n background: var(--sp-bg);\n border-color: var(--sp-border);\n box-shadow: var(--sp-shadow-md);\n transform: translateY(-2px);\n }\n\n .sp-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 0.1s;\n }\n\n .sp-card-bar {\n width: 3px;\n border-radius: var(--sp-radius-full);\n margin-right: 14px;\n flex-shrink: 0;\n }\n\n .sp-card-body {\n flex: 1;\n min-width: 0;\n }\n\n .sp-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .sp-card-number {\n font-size: 12px;\n font-weight: 700;\n color: var(--sp-text-tertiary);\n font-variant-numeric: tabular-nums;\n }\n\n .sp-badge {\n padding: 2px 10px;\n border-radius: var(--sp-radius-full);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-card-date {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n margin-left: auto;\n }\n\n .sp-card-message {\n font-size: 13px;\n line-height: 1.5;\n color: var(--sp-text);\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .sp-card-message--expanded {\n -webkit-line-clamp: unset;\n }\n\n .sp-card-expand {\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-accent);\n cursor: pointer;\n background: none;\n border: none;\n padding: 4px 0;\n font-family: var(--sp-font);\n transition: opacity 0.15s ease;\n }\n\n .sp-card-expand:hover {\n opacity: 0.8;\n }\n\n .sp-card-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n }\n\n .sp-btn-resolve,\n .sp-btn-delete {\n padding: 8px 14px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-resolve svg,\n .sp-btn-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-btn-resolve:hover {\n border-color: #22c55e;\n color: #22c55e;\n background: rgba(34, 197, 94, 0.06);\n }\n\n .sp-btn-delete:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-resolve:disabled,\n .sp-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-spinner--sm {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Delete All (header) ---- */\n\n .sp-panel-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-btn-delete-all {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-delete-all svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-btn-delete-all:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-delete-all:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ---- Confirm Dialog ---- */\n\n .sp-confirm-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: ${Z_INDEX_MAX};\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n .sp-confirm-dialog {\n width: 340px;\n padding: 28px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n transform: translateY(8px) scale(0.97);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-confirm-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n margin-bottom: 8px;\n }\n\n .sp-confirm-message {\n font-size: 14px;\n color: var(--sp-text-secondary);\n line-height: 1.5;\n margin-bottom: 20px;\n }\n\n .sp-confirm-actions {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n }\n\n .sp-btn-danger {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: #ef4444;\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);\n }\n\n .sp-btn-danger:hover {\n background: #dc2626;\n box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);\n transform: translateY(-1px);\n }\n\n .sp-btn-danger:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-card--resolved {\n opacity: 0.5;\n }\n\n .sp-card--resolved .sp-card-message {\n text-decoration: line-through;\n text-decoration-color: var(--sp-text-tertiary);\n }\n\n /* ============================\n Loading State\n ============================ */\n\n .sp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n }\n\n /* ============================\n Identity Form\n ============================ */\n\n .sp-identity-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-input {\n width: 100%;\n height: 42px;\n padding: 0 14px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 14px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-input::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-input:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-input-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n margin-bottom: 6px;\n display: block;\n }\n\n /* ============================\n Buttons\n ============================ */\n\n .sp-btn-primary {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-btn-primary:hover {\n box-shadow: 0 4px 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-btn-primary:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-btn-primary:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n .sp-btn-ghost {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .sp-btn-ghost:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Empty State\n ============================ */\n\n .sp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 56px 24px;\n color: var(--sp-text-tertiary);\n text-align: center;\n gap: 8px;\n animation: sp-fade-in 0.3s ease-out both;\n }\n\n .sp-empty-text {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* ============================\n Load More\n ============================ */\n\n .sp-load-more-wrap {\n display: flex;\n justify-content: center;\n padding: 12px 0 4px;\n }\n\n .sp-btn-load-more {\n width: 100%;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-fab,\n .sp-radial-item,\n .sp-filter-dropdown-btn,\n .sp-segmented,\n .sp-segmented__btn,\n .sp-card,\n .sp-panel-close,\n .sp-search,\n .sp-btn-resolve,\n .sp-btn-delete,\n .sp-btn-delete-all,\n .sp-btn-primary,\n .sp-btn-ghost,\n .sp-btn-danger,\n .sp-card-expand,\n .sp-input,\n .sp-confirm-dialog {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-segmented__btn--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-filter-dropdown-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-filter-dropdown-option--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-fab:focus-visible,\n .sp-radial-item:focus-visible,\n .sp-filter-dropdown-btn:focus-visible,\n .sp-segmented__btn:focus-visible,\n .sp-filter-dropdown-option:focus-visible,\n .sp-panel-close:focus-visible,\n .sp-btn-resolve:focus-visible,\n .sp-btn-delete:focus-visible,\n .sp-btn-delete-all:focus-visible,\n .sp-btn-primary:focus-visible,\n .sp-btn-ghost:focus-visible,\n .sp-btn-danger:focus-visible,\n .sp-card-expand:focus-visible,\n .sp-input:focus-visible,\n .sp-search:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-panel {\n border: 2px solid ButtonText !important;\n }\n\n .sp-fab-badge {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-card-bar {\n background: ButtonText !important;\n }\n }\n\n ${ANIMATION_CSS}\n ${STATS_CSS}\n ${SORT_CSS}\n ${BULK_CSS}\n ${EXPORT_CSS}\n ${SHORTCUTS_CSS}\n ${DETAIL_CSS}\n `;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: `\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n max-width: 280px;\n padding: 12px 14px;\n border-radius: 14px;\n background: ${this.colors.glassBgHeavy};\n backdrop-filter: blur(24px);\n -webkit-backdrop-filter: blur(24px);\n border: 1px solid ${this.colors.glassBorder};\n box-shadow: 0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family: \"Inter\", system-ui, -apple-system, sans-serif;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(6px) scale(0.97);\n transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n visibility: hidden;\n -webkit-font-smoothing: antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: `\n position: absolute;\n width: 12px;\n height: 12px;\n background: ${this.colors.glassBgHeavy};\n border: 1px solid ${this.colors.glassBorder};\n transform: rotate(45deg);\n pointer-events: none;\n `,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelHide();\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: `\n padding:3px 10px;border-radius:9999px;\n font-size:11px;font-weight:600;\n color:${typeColor};background:${typeBg};\n letter-spacing:0.02em;\n `,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-right:1px solid ${this.colors.glassBorder};\n border-bottom:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n bottom:-6px;\n left:${arrowLeft}px;\n `;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-left:1px solid ${this.colors.glassBorder};\n border-top:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n top:-6px;\n left:${arrowLeft}px;\n `;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import type {\n DiagnosticsSnapshot,\n FeedbackPayload,\n PageScope,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEventListener,\n SitepingPublicEvents,\n} from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { MOBILE_BREAKPOINT, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { ConsoleBuffer } from \"./diagnostics/console-buffer.js\";\nimport { NetworkBuffer } from \"./diagnostics/network-buffer.js\";\nimport { EventBus, type PublicWidgetEvents, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createT, loadLocale, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport type { Panel as PanelType } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\ninterface NormalisedDiagnostics {\n console: boolean;\n network: boolean;\n maxConsoleEntries: number;\n maxNetworkEntries: number;\n}\n\n/**\n * Resolve `SitepingConfig.captureDiagnostics` into a normalised shape.\n *\n * - `undefined` / `false` → everything off (no monkey-patching).\n * - `true` → console + network on with the defaults (50 / 20).\n * - object → per-channel toggles + optional custom sizes; missing booleans\n * default to `true` so users can pass `{ maxConsoleEntries: 200 }` and\n * still get both channels.\n */\nfunction normaliseDiagnosticsOptions(value: SitepingConfig[\"captureDiagnostics\"]): NormalisedDiagnostics {\n if (value === undefined || value === false) {\n return { console: false, network: false, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n if (value === true) {\n return { console: true, network: true, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n return {\n console: value.console !== false,\n network: value.network !== false,\n maxConsoleEntries: typeof value.maxConsoleEntries === \"number\" ? value.maxConsoleEntries : 50,\n maxNetworkEntries: typeof value.maxNetworkEntries === \"number\" ? value.maxNetworkEntries : 20,\n };\n}\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n focusFeedback: () => false,\n on: () => noop,\n off: noop,\n };\n}\n\ninterface NormalisedDeepLink {\n enabled: boolean;\n param: string;\n}\n\n/**\n * Resolve `SitepingConfig.deepLink` into a normalised shape.\n *\n * - `undefined` / `false` → disabled, no URL parsing.\n * - `true` → enabled with default param name `siteping`.\n * - object → enabled with optional custom param name. A bare empty object\n * `{}` falls back to the default param so callers never need to repeat it.\n */\nfunction normaliseDeepLinkOptions(value: SitepingConfig[\"deepLink\"]): NormalisedDeepLink {\n if (value === undefined || value === false) return { enabled: false, param: \"siteping\" };\n if (value === true) return { enabled: true, param: \"siteping\" };\n return { enabled: true, param: value.param ?? \"siteping\" };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses)\n if (!config.forceShow) {\n try {\n // Check for Node/bundler production environment — avoid import.meta\n // which causes \"Critical dependency\" warnings in Next.js webpack builds\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n }\n\n // Guard: desktop only (viewport below the threshold = hidden). forceShow\n // bypasses this just like the production guard above; minViewportWidth lets\n // hosts tune (or disable, with 0) the threshold. Non-finite values (NaN from\n // an untyped script-tag consumer, Infinity) would silently break the `<`\n // comparison — fail back to the default instead. See issue #103.\n const minViewportWidth =\n typeof config.minViewportWidth === \"number\" && Number.isFinite(config.minViewportWidth)\n ? config.minViewportWidth\n : MOBILE_BREAKPOINT;\n if (!config.forceShow && window.innerWidth < minViewportWidth) {\n const reason = \"mobile\";\n console.info(\n `[siteping] Widget not loaded: viewport width < ${minViewportWidth}px (mobile not supported). Use forceShow: true or lower minViewportWidth to override.`,\n );\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n const locale = config.locale ?? \"en\";\n // Kick off the locale fetch immediately. English is bundled synchronously\n // and used as the fallback while the chunk is in flight. The launcher\n // awaits `localeReady` before rendering markers and re-localizes the FAB\n // and popup once the dictionary lands — both are mounted synchronously so\n // the widget is interactive immediately, but their labels start in the\n // English fallback until the chunk arrives.\n const localeReady: Promise<unknown> =\n locale === \"en\"\n ? Promise.resolve()\n : loadLocale(locale).catch(() => {\n /* fallback to English — already handled by createT */\n });\n const t = createT(locale);\n\n // Page scope — concrete URL + optional template, used to keep annotations\n // and panel results scoped to the current page. The widget calls this on\n // every initial markers load and on `instance.refresh()`, so SPA hosts can\n // re-fetch when the route changes.\n const scopeAnnotationsByUrl = config.scopeAnnotationsByUrl ?? true;\n const getScope = (): PageScope => {\n try {\n const result = config.getPageScope?.();\n if (result) return result;\n } catch (e) {\n log(\"getPageScope() threw, falling back to pathname:\", e);\n }\n return { url: window.location.pathname, urlPattern: null };\n };\n\n log(\"Initializing widget\", {\n projectName: config.projectName,\n theme: config.theme ?? \"light\",\n locale,\n scopeAnnotationsByUrl,\n });\n\n // Diagnostics — capture console + failed network at submit time when\n // `captureDiagnostics` is set. Buffers are installed eagerly so they\n // cover the entire session, then snapshotted in the annotation handler\n // below. We default to `false` even in dev to avoid surprise side\n // effects; users opt in via the config flag.\n const diagnosticsOpts = normaliseDiagnosticsOptions(config.captureDiagnostics);\n const consoleBuffer = diagnosticsOpts.console ? new ConsoleBuffer(diagnosticsOpts.maxConsoleEntries) : null;\n const networkBuffer = diagnosticsOpts.network ? new NetworkBuffer(diagnosticsOpts.maxNetworkEntries) : null;\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<PublicWidgetEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint).\n // The earlier guard guarantees one of `store` / `endpoint` is set; we\n // capture the chosen branch in a typed local so TypeScript narrows on\n // each side without resorting to a non-null assertion.\n const client: WidgetClient = (() => {\n if (config.store) return new StoreClient(config.store, config.projectName);\n const endpoint = config.endpoint;\n if (typeof endpoint !== \"string\" || endpoint.length === 0) {\n throw new Error(\"[siteping] internal invariant: endpoint must be a non-empty string in HTTP mode\");\n }\n return new ApiClient(endpoint, config.projectName);\n })();\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Bridge internal events to public bus\n bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb));\n bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id));\n bus.on(\"open\", () => publicBus.emit(\"panel:open\"));\n bus.on(\"close\", () => publicBus.emit(\"panel:close\"));\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n let isTestEnv = false;\n try {\n // Dynamic key prevents bundlers (tsup/esbuild) from statically replacing\n // process.env.NODE_ENV at build time — the widget needs runtime detection\n // so E2E tests can set globalThis.process = { env: { NODE_ENV: 'test' } }\n const envKey = \"NODE_\" + \"ENV\";\n if (typeof process !== \"undefined\" && process.env?.[envKey] === \"test\") {\n isTestEnv = true;\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n const shadowMode = isTestEnv ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n (shadow as unknown as DocumentFragment).appendChild(style);\n }\n\n document.body.appendChild(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t, liveRegion);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n\n // Keep the FAB unread-count badge in sync with the visible markers. Marker\n // mutations (initial render, addFeedback after submit, panel-driven resolve /\n // delete / bulk-delete via re-render) all emit `markers:changed`, so a single\n // listener covers every path that can change the open count.\n bus.on(\"markers:changed\", (openCount) => fab.updateBadge(openCount));\n\n // Lazy-load Panel on first use (FAB click, instance.open, etc.) to keep the\n // initial bundle small. Panel + sub-modules are ~14 KB gzip on their own.\n // Memoize the import promise so subsequent calls reuse the same instance.\n let panelInstance: PanelType | null = null;\n let panelPromise: Promise<PanelType> | null = null;\n let destroyed = false;\n // Monotonic token guarding the launcher's own marker renders (initial load +\n // doRefresh). The panel guards its own renders with an AbortController; the\n // two direct launcher paths share this counter so the *last-issued* fetch\n // wins, never the last to resolve. Without it, an SPA nav burst (or an\n // initial load racing the first navigation) could render a stale page's\n // markers out of order, since markers.render() is a full clear-and-rebuild.\n let markerGeneration = 0;\n async function loadPanel(): Promise<PanelType | null> {\n if (destroyed) return null;\n if (panelInstance) return panelInstance;\n if (!panelPromise) {\n panelPromise = import(\"./panel.js\").then((mod) => {\n if (destroyed) return null as unknown as PanelType;\n panelInstance = new mod.Panel(shadow, colors, bus, client, config.projectName, markers, t, locale, {\n getScope,\n scopeAnnotationsByUrl,\n });\n return panelInstance;\n });\n }\n return panelPromise;\n }\n\n // Prefetch Panel in idle time so the first FAB click doesn't pay the\n // network/parse cost of the dynamic import. The chunk still ships lazily\n // (saves first-paint gzip), but it's already warming up by the time the\n // user is likely to click. Falls back to setTimeout in browsers without\n // requestIdleCallback (Safari before 17).\n if (typeof window !== \"undefined\") {\n const prefetch = () => {\n if (!destroyed) void loadPanel();\n };\n const ric = (window as { requestIdleCallback?: (cb: () => void) => void }).requestIdleCallback;\n if (typeof ric === \"function\") ric(prefetch);\n else setTimeout(prefetch, 200);\n }\n\n // The FAB emits `panel:toggle` on chat click — we intercept here so the\n // launcher (which holds the lazy loader) can drive the Panel lifecycle.\n // Panel itself also subscribes to `panel:toggle` once loaded; once the\n // dynamic import resolves we manually call `p.open()` because the missed\n // initial emit can't be replayed.\n let pendingOpen = false;\n const unsubToggle = bus.on(\"panel:toggle\", (open) => {\n if (panelInstance) return; // Real Panel already handles subsequent toggles\n if (open) {\n pendingOpen = true;\n loadPanel()\n .then((p) => {\n if (p && pendingOpen) p.open();\n pendingOpen = false;\n })\n .catch((err) => log(\"Failed to lazy-load panel:\", err));\n } else {\n pendingOpen = false;\n }\n });\n\n const annotator = new Annotator(colors, bus, t, config.enableScreenshot ?? false);\n\n let onContextMenu: ((e: MouseEvent) => void) | null = null;\n if (config.enableRightClickComment) {\n onContextMenu = (e: MouseEvent) => {\n // Respect host pages that run their own custom context menus (grids,\n // editors). Element-level handlers fire before this document-level\n // listener, so if they called preventDefault() we yield.\n if (e.defaultPrevented) return;\n // Modifier-key escape hatch: Shift/Ctrl/Alt/Meta → native menu.\n if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return;\n // Exclude SitePing's own UI — right-clicking the FAB, panel, markers,\n // popup, or overlay must not hijack the event. composedPath() reaches\n // into the closed shadow root so all retargeted events are caught.\n const path = e.composedPath();\n if (\n path.some(\n (n) =>\n n === host ||\n (n instanceof Element && (n.hasAttribute(\"data-siteping-ignore\") || n.id === \"siteping-markers\")),\n )\n )\n return;\n // Don't swallow the event while the annotator is already active (e.g.\n // the user right-clicks to paste in the popup textarea). Fall through\n // to the native menu instead of silently consuming the event.\n if (annotator.isBusy) return;\n e.preventDefault();\n void annotator\n .startInstantAnnotation(e.clientX, e.clientY)\n .catch((err) => log(\"right-click annotation failed\", err));\n };\n document.addEventListener(\"contextmenu\", onContextMenu);\n }\n\n // Once the locale dictionary lands, swap the FAB + popup labels from the\n // English fallback to the configured language. `t` already resolves to the\n // loaded dictionary at call time, so the markers list rendered below (which\n // calls `t` lazily) only needs to wait on `localeReady` once.\n if (locale !== \"en\") {\n localeReady.then(() => {\n if (destroyed) return;\n fab.refreshLabels();\n annotator.refreshLabels();\n });\n }\n\n // Handle annotation completion via event bus (not DOM events).\n // Concurrency guard: a second `annotation:complete` while one is still in\n // flight must not start a duplicate submission. The Annotator already\n // serializes its own submissions (no second annotation can be drawn while\n // the popup is open), so this is defence-in-depth — but it must not *silently*\n // drop the event: a dropped event would leave any waiting `runSubmission`\n // listener hung forever. We emit `submission:cancelled` so the waiter\n // unblocks as a benign abort (the popup restores, `onError` is not called).\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) {\n bus.emit(\"submission:cancelled\");\n return;\n }\n submitting = true;\n try {\n const { annotation, type, message, screenshotDataUrl, screenshotRegion } = data;\n\n // Ensure identity — config wins (host-provided), then localStorage,\n // then prompt the user as a last resort. Host-provided identity is\n // not persisted: the host stays the source of truth on every render.\n let identity = config.identity ?? getIdentity();\n if (!identity) {\n identity = await promptIdentity(shadow, t);\n if (!identity) {\n // User cancelled the identity prompt. Emit `submission:cancelled`\n // (not `feedback:error`) so the popup's pending submit handler\n // unblocks and restores the form — cancelling a prompt is a benign\n // user action, so `config.onError` must not fire for it.\n bus.emit(\"submission:cancelled\");\n return;\n }\n saveIdentity(identity);\n }\n\n // crypto.randomUUID() throws in non-secure contexts (plain HTTP)\n const clientId = (() => {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n })();\n\n // Use scope.url as the single source of truth — same identifier the\n // panel filter and marker filter use. If we stored full URLs here while\n // filtering by pathname, freshly-created feedbacks would never match\n // their own scope filter and would vanish from the UI immediately.\n // Default scope.url is `window.location.pathname` (no query string,\n // so token/key/secret query params can't leak by construction). Hosts\n // that need origin or query in the identifier override `getPageScope`.\n const scope = getScope();\n\n // Snapshot the buffers right before submit so the captured slice\n // matches the moment the user clicked \"send\", not some earlier point.\n let diagnostics: DiagnosticsSnapshot | null = null;\n if (consoleBuffer || networkBuffer) {\n diagnostics = {\n console: consoleBuffer?.getEntries() ?? [],\n network: networkBuffer?.getEntries() ?? [],\n };\n }\n\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: scope.url,\n urlPattern: scope.urlPattern,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n screenshotDataUrl: screenshotDataUrl ?? null,\n screenshotRegion: screenshotRegion ?? null,\n diagnostics,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n // Compare against the scope captured before submit (route may have\n // changed during the network round-trip — re-reading scope here\n // would race with SPA navigation).\n if (!scopeAnnotationsByUrl || response.url === scope.url) {\n markers.addFeedback(response, markers.count + 1);\n }\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n // Only refresh the panel if it has been loaded — `refresh()` is a\n // no-op when the panel is closed, so skipping the dynamic import here\n // avoids loading 14 KB of code that would otherwise do nothing.\n if (panelInstance) await panelInstance.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load. We always pass the current page URL\n // when scopeAnnotationsByUrl is enabled so the server narrows results to the\n // current page — preventing annotations from one page accidentally rendering\n // on another (when CSS selectors happen to match unrelated elements).\n const initialScope = getScope();\n const initialOptions = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: initialScope.url } : { limit: PAGE_SIZE };\n const deepLinkOpts = normaliseDeepLinkOptions(config.deepLink);\n // Claim a generation for the initial load so a navigation that fires while\n // this fetch is in flight (doRefresh bumps the counter) supersedes it — the\n // old page's markers must never clobber the page the user navigated to.\n const initialLoadGeneration = ++markerGeneration;\n // Render markers only once both the feedbacks and the locale dictionary are\n // ready. Marker aria-labels are built via `t(...)` at render time — without\n // this `Promise.all`, a fast HTTP response could outrun a slow locale chunk\n // and freeze marker labels in the English fallback for non-English locales.\n Promise.all([client.getFeedbacks(config.projectName, initialOptions), localeReady])\n .then(([{ feedbacks }]) => {\n if (destroyed || markerGeneration !== initialLoadGeneration) return;\n // Defensive client-side filter — backend may not yet support the `url` query.\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === initialScope.url) : feedbacks;\n markers.render(visible);\n // Apply deeplink focus once markers exist. Failures here are\n // non-fatal — a malformed URL or an unknown ID just leaves the page\n // as the user found it, so log and move on.\n if (deepLinkOpts.enabled) {\n try {\n const focusId = new URLSearchParams(window.location.search).get(deepLinkOpts.param);\n if (focusId) {\n const matched = markers.focusFeedback(focusId);\n log(\n `deepLink ?${deepLinkOpts.param}=${focusId} ${matched ? \"focused\" : \"did not match a visible feedback\"}`,\n );\n }\n } catch (e) {\n log(\"deepLink parsing failed:\", e);\n }\n }\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint, config.identity ?? getIdentity())\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n // Re-fetch feedbacks for the *current* scope and update the UI. Shared by the\n // public `instance.refresh()` and the SPA navigation watcher below.\n //\n // When the panel is open, its own `refresh()` already runs `loadFeedbacks()`\n // which re-renders markers — a second fetch here would race with it (the\n // loser overwrites the winner's markers, off by a generation). So we delegate\n // when open, and fetch markers ourselves when closed (the panel won't, but\n // SPA hosts still need the new page's markers after a route change).\n //\n // Returns the in-flight promise (rejecting on fetch failure) so callers can\n // react — `instance.refresh()` swallows it (the public API never rejects onto\n // the host), the navigation watcher uses it to re-arm its dedup on failure.\n const doRefresh = (): Promise<void> => {\n // Bump first, before the open/closed split, so switching to panel-driven\n // rendering also invalidates any closed-panel fetch still in flight.\n const generation = ++markerGeneration;\n if (panelInstance?.isCurrentlyOpen) {\n return panelInstance.refresh();\n }\n const scope = getScope();\n const opts = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: scope.url } : { limit: PAGE_SIZE };\n return client.getFeedbacks(config.projectName, opts).then(({ feedbacks }) => {\n // Drop the result if a newer refresh superseded us (out-of-order\n // resolution), the widget was torn down, or the panel opened mid-flight\n // and now owns marker rendering itself.\n if (destroyed || generation !== markerGeneration || panelInstance?.isCurrentlyOpen) return;\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n markers.render(visible);\n });\n };\n\n // SPA route-change watcher. The widget is normally mounted once (singleton)\n // inside a persistent layout — e.g. a Next.js App Router `layout.tsx`, which\n // does NOT remount on client-side navigation. Without this, init runs once and\n // the panel list + markers stay frozen on the page where the widget first\n // mounted. We patch the History API (SPA routers call pushState/replaceState\n // rather than triggering popstate) and listen for popstate/hashchange, then\n // re-fetch only when the scope key actually changes. This re-fetches data\n // only — it deliberately does NOT re-focus/re-scroll (deep-link focus stays\n // initial-load only; see `deepLink`). Opt out with `watchNavigation: false`.\n let teardownNavigation: (() => void) | null = null;\n if (config.watchNavigation !== false && typeof window !== \"undefined\" && typeof history !== \"undefined\") {\n const scopeKey = (s: PageScope): string => `${s.url}\\n${s.urlPattern ?? \"\"}`;\n let lastScopeKey = scopeKey(initialScope);\n const onLocationChange = (): void => {\n if (destroyed) return;\n const key = scopeKey(getScope());\n // Same scope (e.g. query-only or hash-only nav under the default pathname\n // scope) — nothing to re-fetch. Guards against pushState storms too.\n if (key === lastScopeKey) return;\n const prevKey = lastScopeKey;\n lastScopeKey = key;\n log(\"SPA navigation detected — refreshing feedbacks for new scope\");\n doRefresh().catch(() => {\n // The refresh failed (network error). Roll the dedup key back so a\n // later nav *back* to this same scope retries instead of being\n // silently suppressed — unless a newer navigation already moved on.\n if (lastScopeKey === key) lastScopeKey = prevKey;\n });\n };\n\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n // Call through to the original first so `location` is already updated by the\n // time onLocationChange() reads getScope().\n const patchedPushState: typeof history.pushState = function (this: History, ...args) {\n originalPushState.apply(this, args);\n onLocationChange();\n };\n const patchedReplaceState: typeof history.replaceState = function (this: History, ...args) {\n originalReplaceState.apply(this, args);\n onLocationChange();\n };\n history.pushState = patchedPushState;\n history.replaceState = patchedReplaceState;\n window.addEventListener(\"popstate\", onLocationChange);\n window.addEventListener(\"hashchange\", onLocationChange);\n\n teardownNavigation = () => {\n window.removeEventListener(\"popstate\", onLocationChange);\n window.removeEventListener(\"hashchange\", onLocationChange);\n // Restore only if nobody patched on top of us — otherwise we'd clobber\n // another library's History wrapper. If a library did wrap on top, our\n // patch stays in the chain (and keeps its closure alive), but it's inert:\n // `destroyed` is already true above, so onLocationChange() is a no-op.\n if (history.pushState === patchedPushState) history.pushState = originalPushState;\n if (history.replaceState === patchedReplaceState) history.replaceState = originalReplaceState;\n };\n }\n\n instance = {\n destroy: () => {\n log(\"Destroying widget\");\n if (onContextMenu) {\n document.removeEventListener(\"contextmenu\", onContextMenu);\n }\n destroyed = true;\n pendingOpen = false;\n teardownNavigation?.();\n unsubAnnotation();\n unsubToggle();\n fab.destroy();\n panelInstance?.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n // Restore the original console / fetch / XHR so the host page isn't\n // left with patched globals after the widget tears itself down.\n consoleBuffer?.dispose();\n networkBuffer?.dispose();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n instance = null;\n },\n open: () => {\n // Emit synchronously so consumers wired through `onOpen` / `panel:open`\n // see the open event immediately, even before the Panel module has\n // finished loading on the first call.\n bus.emit(\"panel:toggle\", true);\n },\n close: () => {\n if (panelInstance) {\n panelInstance.close();\n } else {\n // Cancel a pending open before the panel has loaded.\n pendingOpen = false;\n }\n },\n focusFeedback: (feedbackId: string) => {\n // Returns false when no entry matches — unknown ID, feedback filtered\n // out by `scopeAnnotationsByUrl`, or markers not yet loaded (the\n // initial getFeedbacks is async, and the widget exposes no public\n // \"markers ready\" event today). Hosts that race against initial load\n // can retry, or trigger focus from a user gesture instead.\n return markers.focusFeedback(feedbackId);\n },\n // Public API must never reject onto the host — swallow the promise.\n refresh: () => {\n void doRefresh().catch(() => {});\n },\n // `PublicWidgetEvents` is a structural alias of `SitepingPublicEvents`, so\n // these on/off forwarders compose without any runtime cast.\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) =>\n publicBus.on(event, listener),\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => {\n publicBus.off(event, listener);\n },\n };\n\n return instance;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n // Move the shadow host to the end of <body> so the identity prompt wins\n // the source-order tiebreak against the feedback popup. Both elements\n // already sit at `Z_INDEX_MAX` (max int32 — no \\\"higher\\\"), and since #114\n // the popup stays visible during submission, so it can be on screen at\n // the moment `promptIdentity` runs. The popup is appended to `document.body`\n // later than the host during init, which made it win when z-indices tied.\n // Re-appending an existing node just moves it; no remount, no listener\n // loss, no visual jitter when the popup isn't open. See issue #126.\n const host = shadowRoot.host;\n if (host.parentNode) host.parentNode.appendChild(host);\n\n const backdrop = document.createElement(\"div\");\n backdrop.style.cssText = `\n position:fixed;inset:0;\n background:var(--sp-identity-overlay);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n display:flex;align-items:center;justify-content:center;\n z-index:${Z_INDEX_MAX};\n opacity:0;transition:opacity 0.25s ease;\n `;\n\n const modal = document.createElement(\"div\");\n modal.style.cssText = `\n width:340px;padding:28px;border-radius:var(--sp-radius-xl);\n background:var(--sp-identity-bg);\n backdrop-filter:blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter:blur(var(--sp-blur-heavy));\n border:1px solid var(--sp-glass-border);\n box-shadow:0 16px 48px var(--sp-shadow), 0 8px 16px var(--sp-shadow);\n font-family:var(--sp-font, \"Inter\",system-ui,-apple-system,sans-serif);\n color:var(--sp-text);\n transform:translateY(12px) scale(0.97);\n transition:transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n -webkit-font-smoothing:antialiased;\n `;\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;justify-content:flex-end;margin-top:20px;\";\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n modal.style.transform = \"translateY(12px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n emailInput.style.borderColor = \"var(--sp-type-bug, #ef4444)\";\n return;\n }\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n modal.style.transform = \"translateY(0) scale(1)\";\n nameInput.focus();\n });\n });\n}\n","import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n FeedbackPayload,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEvents,\n SitepingStore,\n} from \"@siteping/core\";\n\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.bun/@medv+finder@4.0.2/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/focus-tracker.ts","../src/popup.ts","../src/screenshot.ts","../src/annotator.ts","../src/api-client.ts","../src/diagnostics/console-buffer.ts","../src/diagnostics/network-buffer.ts","../src/events.ts","../src/fab.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/visibility.ts","../src/dom/resolver.ts","../src/markers.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts","../src/index.ts"],"names":["acceptedAttrNames","attr","name","value","nameIsOk","wordLike","valueIsOk","idName","className","tagName","finder","input","options","defaults","startTime","config","rootDocument","findRootDocument","foundPath","count","candidate","search","fPath","fallback","selector","unique","optimized","optimize","byPenalty","stack","paths","current","i","level","tie","node","combinations","words","word","element","elementId","index","indexOf","nthOfType","nth","nthChild","path","query","penalty","acc","a","b","parent","child","rootNode","css","newPath","STABLE_ATTRS","djb2","str","hash","generateFingerprint","childCount","siblingIdx","attrHash","attrs","val","scoreFingerprint","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","adjacentText","direction","prop","sibling","attempts","text","boundedTextEnd","boundedText","neighborText","prevSibling","nextSibling","prev","next","cap","out","walker","walk","generateXPath","safeId","segments","tag","position","ANCHOR_KEY_ATTR","generateAnchor","cssSelector","xpath","textSnippet","textPrefix","textSuffix","fingerprint","neighbor","anchorKey","containsRect","el","rect","findAnchorElement","root","centerX","centerY","elementAtCenter","rectToPercentages","anchorBounds","isWidgetChrome","createFocusTracker","host","lastPageFocus","onFocusIn","e","target","TYPE_LABEL_KEYS","isMacPlatform","uaData","Popup","colors","t","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","option","btn","icon","parseSvg","bgColor","getTypeBgColor","getTypeColor","btnRow","typeButtons","type","key","labelSpan","setText","rectBounds","onSubmit","resolve","popupH","popupW","top","left","aboveTop","focusableEls","first","last","reduceMotion","container","buttons","isActive","color","enabled","result","submitter","spinner","cachedHtml2Canvas","warnedAboutMissingDep","loadHtml2Canvas","mod","err","clamp","min","max","roundPct","captureAnnotatedScreenshot","html2canvas","quality","maxWidth","padX","padY","docX","docY","docW","docH","capX","capY","capW","capH","region","canvas","ratio","targetW","targetH","scaled","ctx","Annotator","bus","enableScreenshot","getFallbackTarget","drawMode","active","dot","style","instruction","cancelBtn","previouslyFocused","bounds","highlight","annotation","screenshotCache","formResult","touch","clientX","clientY","source","evt","x","y","w","h","pointRect","captureRect","capture","reject","cleanup","unsubSent","unsubError","unsubCancelled","reason","anchorElement","anchor","errorFromResponse","response","label","detail","message","SitepingAuthError","SitepingValidationError","SitepingError","networkErrorFromException","error","SitepingNetworkError","buildRequestHeaders","auth","json","merged","extra","MAX_RETRIES","TIMEOUT_MS","RETRY_QUEUE_KEY","MAX_QUEUE_SIZE","resilientFetch","url","init","retries","attempt","controller","timeout","baseDelay","jitter","r","LOCK_NAME","withRetryLock","callback","readQueue","raw","parsed","queueForRetry","endpoint","payload","queue","normalizeName","normalizeEmail","flushRetryQueue","currentIdentity","toRetry","unrelated","dropped","entry","failed","headers","remaining","parseJsonAs","ApiClient","projectName","screenshotRegion","rest","body","params","id","resolved","LEVELS","serializeArg","arg","seen","_key","formatArgs","args","ConsoleBuffer","maxEntries","original","buffer","wrapped","truncateUrl","urlString","NetworkBuffer","startedAt","t0","method","t1","proto","originalOpen","originalSend","meta","info","onEnd","status","EventBus","event","listener","set","fn","ITEM_GAP","ITEM_LABEL_KEYS","Fab","shadowRoot","isRight","ICON_LIST","ICON_EDIT","ICON_EYE","ICON_EYE_OFF","ICON_SITEPING","item","handleEscape","items","activeEl","currentIndex","nextIndex","displayText","ICON_CLOSE","svgStr","badge","unsubscribe","oldSvg","newSvg","STORAGE_KEY","isIdentity","hasOwn","email","getIdentity","saveIdentity","identity","normalizeText","s","collapseWhitespace","editDistance","aLen","bLen","k","curr","j","prevDiag","tmp","similarity","maxLen","sellersDistance","haystack","needle","best","hc","sub","del","ins","fuzzyIncludes","minScore","capped","bigramCounts","counts","diceAgainst","needleCounts","needleBigramTotal","textBigramTotal","matches","consumed","available","used","wordPairCounts","wordPairDiceAgainst","needlePairs","needlePairTotal","textPairTotal","STRICT_VISIBILITY_OPTIONS","classifyVisibility","visibilityFactor","cls","STRATEGY_PRIORS","MAX_PER_STRATEGY","SCAN_TOP_K","SCAN_HARD_CAP","CANDIDATE_TEXT_CAP","TEXT_FLOOR","STRONG_STRUCT","ACCEPT_SCAN","RAW_FIELD_CAP","STRONG_VERIFY","NEUTRAL_VERIFICATION","AMBIGUITY_EPSILON","boundedField","buildSignals","snippet","snippetWordPairs","snippetWordPairTotal","resolveAnchor","signals","pool","gatherSelectorCandidates","scored","strategy","scoreOne","bestFinal","strongVisibleMatch","c","verifiable","budget","sweepScanCandidates","accepted","isAcceptable","winner","disambiguate","confidenceOf","add","enforceTag","escaped","candidates","storedFp","limit","ranked","cheap","charDice","wordDice","diff","scores","verificationScore","visibility","totalWeight","candidateText","contextScore","contextParts","prevText","nextText","candidateNeighbor","sortedAccepted","contenders","resolveAnnotation","resolution","absoluteRect","toAnchorData","toRectData","MARKER_OFFSET","markerPosition","clusterMarker","cluster","elIdx","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","HIDDEN_RECHECK_MS","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","tooltip","liveRegion","visible","mutations","hasRelevantMutation","m","isClosedStatus","cause","recheckVisibility","resizeTick","now","scanBudget","validKeys","markerEl","cacheKey","cachedEl","backedOff","cacheUsable","anchorRect","pos","openCount","feedbacks","feedback","marker","allItems","itemI","itemJ","baseTop","baseLeft","isSolo","totalWidth","startLeft","topMarker","confidence","isResolved","number","typeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","feedbackId","StoreClient","store","record","flattenAnnotation","toResponse","total","toAnnotationResponse","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","buildStyles","cssVariables","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","Tooltip","locale","children","typeBg","createT","typeLabel","header","date","formatRelativeDate","tooltipRect","gap","isAbove","arrowLeft","instance","normaliseDiagnosticsOptions","skippedInstance","noop","readNodeEnv","normaliseDeepLinkOptions","launch","log","minViewportWidth","localeReady","loadLocale","scopeAnnotationsByUrl","getScope","diagnosticsOpts","consoleBuffer","networkBuffer","buildThemeColors","publicBus","client","fb","shadowMode","shadow","sheet","focusTracker","markers","fab","panelInstance","panelPromise","destroyed","markerGeneration","loadPanel","prefetch","ric","pendingOpen","unsubToggle","open","p","annotator","onContextMenu","n","submitting","unsubAnnotation","data","screenshotDataUrl","promptIdentity","clientId","scope","diagnostics","initialScope","initialOptions","deepLinkOpts","initialLoadGeneration","f","focusId","matched","doRefresh","generation","opts","teardownNavigation","scopeKey","lastScopeKey","onLocationChange","prevKey","originalPushState","originalReplaceState","patchedPushState","patchedReplaceState","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","closeModal","onKeydown","submitBtn","focusableSelectors","ke","initSiteping"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAA,EA21BtF,UAAW,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;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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","file":"index.js","sourcesContent":["// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nconst acceptedAttrNames = new Set(['role', 'name', 'aria-label', 'rel', 'href']);\n/** Check if attribute name and value are word-like. */\nexport function attr(name, value) {\n let nameIsOk = acceptedAttrNames.has(name);\n nameIsOk ||= name.startsWith('data-') && wordLike(name);\n let valueIsOk = wordLike(value) && value.length < 100;\n valueIsOk ||= value.startsWith('#') && wordLike(value.slice(1));\n return nameIsOk && valueIsOk;\n}\n/** Check if id name is word-like. */\nexport function idName(name) {\n return wordLike(name);\n}\n/** Check if class name is word-like. */\nexport function className(name) {\n return wordLike(name);\n}\n/** Check if tag name is word-like. */\nexport function tagName(name) {\n return true;\n}\n/** Finds unique CSS selectors for the given element. */\nexport function finder(input, options) {\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if (input.tagName.toLowerCase() === 'html') {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: idName,\n className: className,\n tagName: tagName,\n attr: attr,\n timeoutMs: 1000,\n seedMinLength: 3,\n optimizedMinLength: 2,\n maxNumberOfPathChecks: Infinity,\n };\n const startTime = new Date();\n const config = { ...defaults, ...options };\n const rootDocument = findRootDocument(config.root, defaults);\n let foundPath;\n let count = 0;\n for (const candidate of search(input, config, rootDocument)) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs ||\n count >= config.maxNumberOfPathChecks) {\n const fPath = fallback(input, rootDocument);\n if (!fPath) {\n throw new Error(`Timeout: Can't find a unique selector after ${config.timeoutMs}ms`);\n }\n return selector(fPath);\n }\n count++;\n if (unique(candidate, rootDocument)) {\n foundPath = candidate;\n break;\n }\n }\n if (!foundPath) {\n throw new Error(`Selector was not found.`);\n }\n const optimized = [\n ...optimize(foundPath, input, config, rootDocument, startTime),\n ];\n optimized.sort(byPenalty);\n if (optimized.length > 0) {\n return selector(optimized[0]);\n }\n return selector(foundPath);\n}\nfunction* search(input, config, rootDocument) {\n const stack = [];\n let paths = [];\n let current = input;\n let i = 0;\n while (current && current !== rootDocument) {\n const level = tie(current, config);\n for (const node of level) {\n node.level = i;\n }\n stack.push(level);\n current = current.parentElement;\n i++;\n paths.push(...combinations(stack));\n if (i >= config.seedMinLength) {\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n paths = [];\n }\n }\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n}\nfunction wordLike(name) {\n if (/^[a-z\\-]{3,}$/i.test(name)) {\n const words = name.split(/-|[A-Z]/);\n for (const word of words) {\n if (word.length <= 2) {\n return false;\n }\n if (/[^aeiou]{4,}/i.test(word)) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\nfunction tie(element, config) {\n const level = [];\n const elementId = element.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n level.push({\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n });\n }\n for (let i = 0; i < element.classList.length; i++) {\n const name = element.classList[i];\n if (config.className(name)) {\n level.push({\n name: '.' + CSS.escape(name),\n penalty: 1,\n });\n }\n }\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (config.attr(attr.name, attr.value)) {\n level.push({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 2,\n });\n }\n }\n const tagName = element.tagName.toLowerCase();\n if (config.tagName(tagName)) {\n level.push({\n name: tagName,\n penalty: 5,\n });\n const index = indexOf(element, tagName);\n if (index !== undefined) {\n level.push({\n name: nthOfType(tagName, index),\n penalty: 10,\n });\n }\n }\n const nth = indexOf(element);\n if (nth !== undefined) {\n level.push({\n name: nthChild(tagName, nth),\n penalty: 50,\n });\n }\n return level;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction byPenalty(a, b) {\n return penalty(a) - penalty(b);\n}\nfunction indexOf(input, tagName) {\n const parent = input.parentNode;\n if (!parent) {\n return undefined;\n }\n let child = parent.firstChild;\n if (!child) {\n return undefined;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE &&\n (tagName === undefined ||\n child.tagName.toLowerCase() === tagName)) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction fallback(input, rootDocument) {\n let i = 0;\n let current = input;\n const path = [];\n while (current && current !== rootDocument) {\n const tagName = current.tagName.toLowerCase();\n const index = indexOf(current, tagName);\n if (index === undefined) {\n return;\n }\n path.push({\n name: nthOfType(tagName, index),\n penalty: NaN,\n level: i,\n });\n current = current.parentElement;\n i++;\n }\n if (unique(path, rootDocument)) {\n return path;\n }\n}\nfunction nthChild(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-child(${index})`;\n}\nfunction nthOfType(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-of-type(${index})`;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction unique(path, rootDocument) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction* optimize(path, input, config, rootDocument, startTime) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs) {\n return;\n }\n const newPath = [...path];\n newPath.splice(i, 1);\n if (unique(newPath, rootDocument) &&\n rootDocument.querySelector(selector(newPath)) === input) {\n yield newPath;\n yield* optimize(newPath, input, config, rootDocument, startTime);\n }\n }\n }\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n return `${childCount}:${siblingIdx}:${attrHash(element)}`;\n}\n\n/**\n * Stable-attribute hash component of the fingerprint, exposed separately:\n * unlike the sibling-index component it is O(1) per element (no walk over\n * `parent.children`), so scan prefiltering can afford it on every candidate.\n */\nexport function attrHash(element: Element): string {\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n return attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\n/** Raw-char budget for sibling reads that only keep 32–40 chars — generous\n * headroom for leading/trailing whitespace that trimming discards. */\nconst SIBLING_READ_CAP = 256;\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n *\n * Sibling text is read through the bounded walkers, never `textContent` —\n * a sibling can be an arbitrarily large subtree (a whole `<section>`), and\n * serializing it wholesale to keep 32 chars is the dominant hidden cost of\n * candidate verification on big pages.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling: Element | null = element[prop];\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text =\n direction === \"before\"\n ? boundedTextEnd(sibling, SIBLING_READ_CAP).trim()\n : boundedText(sibling, SIBLING_READ_CAP).trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = sibling[prop];\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate siblings for disambiguation context. */\nexport function neighborText(element: Element): string {\n const prevSibling = element.previousElementSibling;\n const nextSibling = element.nextElementSibling;\n const prev = prevSibling ? boundedText(prevSibling, SIBLING_READ_CAP).trim().slice(0, 40) : \"\";\n const next = nextSibling ? boundedText(nextSibling, SIBLING_READ_CAP).trim().slice(0, 40) : \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n\n/**\n * First `cap` characters of an element's text, without serializing the whole\n * subtree. `textContent.slice(0, cap)` still pays for full subtree\n * serialization first — on a wrapper near the root that is the entire page\n * text, and repeated across scan candidates it degenerates to O(page²).\n * A TreeWalker yields the same text nodes in the same (tree) order and stops\n * as soon as the budget is reached.\n */\nexport function boundedText(element: Element, cap: number): string {\n let out = \"\";\n\n // Leaf fast path — the majority of scan candidates have no element\n // children; their text is the concatenation of their child text nodes,\n // no tree traversal machinery needed.\n if (element.firstElementChild === null) {\n for (const node of element.childNodes) {\n if (node.nodeType === 3) {\n out += (node as Text).data;\n if (out.length >= cap) break;\n }\n }\n return out.length > cap ? out.slice(0, cap) : out;\n }\n\n const walker = element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_TEXT);\n while (out.length < cap) {\n const node = walker.nextNode();\n if (!node) break;\n out += (node as Text).data;\n }\n return out.length > cap ? out.slice(0, cap) : out;\n}\n\n/**\n * Last `cap` characters of an element's text — the reverse-direction\n * counterpart of `boundedText` (TreeWalker only walks forward). Visits text\n * nodes in reverse tree order and stops once the budget is filled.\n */\nexport function boundedTextEnd(element: Element, cap: number): string {\n let out = \"\";\n const walk = (node: Node): boolean => {\n for (let child: Node | null = node.lastChild; child; child = child.previousSibling) {\n if (child.nodeType === 3) {\n out = (child as Text).data + out;\n if (out.length >= cap) return true;\n } else if (child.nodeType === 1 && walk(child)) {\n return true;\n }\n }\n return false;\n };\n walk(element);\n return out.length > cap ? out.slice(-cap) : out;\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short\n */\nexport function generateXPath(element: Element): string {\n if (element.id) {\n const safeId = element.id.includes(\"'\") ? `concat('${element.id.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${element.id}'`;\n return `//${element.localName}[@id=${safeId}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n const safeId = current.id.includes(\"'\")\n ? `concat('${current.id.replace(/'/g, \"',\\\"'\\\",'\")}')`\n : `'${current.id}'`;\n segments.unshift(`/${tag}[@id=${safeId}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n return \"/html/body\" + segments.join(\"\");\n}\n","import { finder } from \"@medv/finder\";\nimport type { AnchorData, RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/** HTML attribute hosts use to mark stable semantic anchors. */\nexport const ANCHOR_KEY_ATTR = \"data-feedback-anchor\";\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Resolution priority (used by `resolveAnchor`):\n * 1. Semantic anchor (`data-feedback-anchor` on closest ancestor) — hosts opt\n * into stable, narrow anchors that survive viewport changes and refactors\n * 2. Element id\n * 3. CSS selector via @medv/finder\n * 4. XPath\n * 5. Smart scan (fingerprint + text + prefix/suffix + neighbor)\n */\nexport function generateAnchor(element: Element): AnchorData {\n const cssSelector = finder(element, {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n });\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n const semanticAncestor = element.closest(`[${ANCHOR_KEY_ATTR}]`);\n const anchorKey = semanticAncestor?.getAttribute(ANCHOR_KEY_ATTR) ?? null;\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName,\n elementId: element.id || undefined,\n anchorKey,\n };\n}\n\n/** Whether `el`'s bounding box fully contains `rect`. */\nfunction containsRect(el: Element, rect: DOMRect): boolean {\n const b = el.getBoundingClientRect();\n return b.left <= rect.x && b.top <= rect.y && b.right >= rect.x + rect.width && b.bottom >= rect.y + rect.height;\n}\n\n/**\n * Find the best DOM element to use as the rect's anchor.\n *\n * Priority:\n * 1. Closest ancestor with `data-feedback-anchor` whose bounds contain the rect —\n * semantic anchors are typically narrow section roots, so anchoring against\n * them keeps the percentage-based rect stable across viewport changes\n * instead of stretching to the width of `<main>` or `<body>`.\n * 2. Smallest ancestor that contains the rect (legacy behavior).\n * 3. `document.body` fallback — keeps percentages in [0, 1].\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const centerX = rect.x + rect.width / 2;\n const centerY = rect.y + rect.height / 2;\n\n const elementAtCenter = document.elementFromPoint(centerX, centerY);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n // Pass 1 — semantic anchor (host-controlled, most stable)\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n if (current.hasAttribute(ANCHOR_KEY_ATTR) && containsRect(current, rect)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Pass 2 — original behavior: smallest ancestor that contains the rect\n current = elementAtCenter;\n while (current && current !== document.body) {\n if (containsRect(current, rect)) return current;\n current = current.parentElement;\n }\n\n return document.body;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","/**\n * Tracks the last *page* element the user focused, so FAB-launched keyboard\n * annotation has a real target: opening the radial menu moves focus into the\n * shadow root, which retargets `document.activeElement` to the 0x0\n * `<siteping-widget>` host — by the time the annotator activates, the element\n * the user actually cares about is no longer the active one. See issue #162.\n */\nexport interface FocusTracker {\n getLastPageFocus(): HTMLElement | null;\n destroy(): void;\n}\n\n/**\n * True when `el` belongs to the widget's own chrome rather than the host\n * page: the shadow host, body-level annotation overlay / toolbar / drawing\n * rect / popup (all carry `data-siteping-ignore`), the markers container\n * (whose markers are focusable but carry no ignore attribute), or the\n * tooltip. Host-independent (tagName/closest checks only) so the annotator\n * can share it without holding a host reference — mirrors the screenshot\n * `ignoreElements` predicate.\n *\n * Host pages may put `data-siteping-ignore` on their own elements to mask\n * them from screenshots — those are deliberately excluded from keyboard\n * annotation targeting too: an element opted out of capture shouldn't become\n * an annotation target through the Enter path.\n */\nexport function isWidgetChrome(el: Element): boolean {\n return (\n el.tagName === \"SITEPING-WIDGET\" ||\n el.closest(\"siteping-widget\") !== null ||\n el.closest('[data-siteping-ignore=\"true\"]') !== null ||\n el.closest(\"#siteping-markers\") !== null ||\n el.closest(\"#sp-tooltip\") !== null\n );\n}\n\nexport function createFocusTracker(host: HTMLElement): FocusTracker {\n let lastPageFocus: HTMLElement | null = null;\n\n const onFocusIn = (e: FocusEvent): void => {\n const target = e.target;\n if (!(target instanceof HTMLElement)) return;\n // <body> / <html> receive focus as a side effect of blurs and overlay\n // teardown — never something the user chose to annotate.\n if (target === document.body || target === document.documentElement) return;\n if (target === host || isWidgetChrome(target)) return;\n lastPageFocus = target;\n };\n\n document.addEventListener(\"focusin\", onFocusIn);\n\n return {\n getLastPageFocus(): HTMLElement | null {\n // Drop detached elements — annotating a node that left the DOM would\n // produce a dead anchor (and retaining it would leak the subtree).\n if (lastPageFocus && !lastPageFocus.isConnected) lastPageFocus = null;\n return lastPageFocus;\n },\n destroy(): void {\n // Both the listener and the reference must go: a retained document\n // listener would keep the tracked element alive past widget destroy.\n document.removeEventListener(\"focusin\", onFocusIn);\n lastPageFocus = null;\n },\n };\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n// Map each feedback type to its translation key, so `refreshLabels()` can\n// re-localize the existing type buttons without re-rendering the popup.\nconst TYPE_LABEL_KEYS: Record<FeedbackType, keyof Translations> = {\n question: \"type.question\",\n change: \"type.change\",\n bug: \"type.bug\",\n other: \"type.other\",\n};\n\n/**\n * Detect whether the host platform uses ⌘+Enter (macOS) vs Ctrl+Enter.\n * Resolved at call time so we can recompute the popup hint when the locale\n * dictionary lands.\n */\nfunction isMacPlatform(): boolean {\n const uaData = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData;\n return uaData\n ? uaData.platform === \"macOS\"\n : (navigator.platform?.includes(\"Mac\") ?? /Macintosh|Mac OS X/i.test(navigator.userAgent));\n}\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n icon: string;\n}\n\n/**\n * Optional async hook called when the user clicks \"Send\". While the returned\n * promise is pending the popup stays visible in a submitting state (spinner\n * on the submit button, every other control disabled). On resolution the\n * popup closes and `show()` resolves with the submitted result; on rejection\n * the popup restores so the user can retry without re-entering the form.\n */\ntype PopupSubmitHandler = (result: PopupResult) => Promise<void>;\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private cancelBtn: HTMLButtonElement;\n private typeRow: HTMLElement;\n private submitLabel: HTMLSpanElement;\n private hint: HTMLElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n private onSubmit: PopupSubmitHandler | null = null;\n private submittingState = false;\n /** WAAPI handle for the running spinner — cancelled when submitting ends. */\n private spinnerAnimation: Animation | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: `\n position:fixed;\n z-index:${Z_INDEX_MAX};\n width:300px;\n padding:16px;\n border-radius:16px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border:1px solid ${this.colors.glassBorder};\n box-shadow:0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n opacity:0;\n transform:translateY(8px) scale(0.98);\n transition:opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n display:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n // Screenshot capture now runs while the popup is still visible (so the\n // spinner can show during the upload). Without this attribute the popup\n // would appear baked into the captured JPEG.\n this.root.setAttribute(\"data-siteping-ignore\", \"true\");\n // The dialog `aria-label` is bound by `applyLabels()` at the end of the\n // constructor, alongside every other `t()`-derived string.\n\n // Type selector grid (2x2). Labels are bound later by `applyLabels()` —\n // the constructor only builds the structure (icon + empty label span).\n const typeOptions: TypeOption[] = [\n { type: \"question\", icon: ICON_QUESTION },\n { type: \"change\", icon: ICON_CHANGE },\n { type: \"bug\", icon: ICON_BUG },\n { type: \"other\", icon: ICON_OTHER },\n ];\n this.typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n height:44px;\n border-radius:9999px;border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};cursor:pointer;\n display:flex;align-items:center;justify-content:center;gap:5px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;color:${this.colors.textTertiary};\n transition:all 0.2s ease;\n padding:0 12px;\n `;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n btn.appendChild(document.createElement(\"span\"));\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n if (this.submittingState) return;\n this.selectType(option.type, this.typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n this.typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = `\n width:100%;min-height:72px;max-height:152px;\n padding:10px 12px;border-radius:12px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBgHeavy};\n color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;line-height:1.5;resize:vertical;\n outline:none;transition:all 0.2s ease;\n box-sizing:border-box;\n `;\n this.textarea.maxLength = 5000;\n\n // Keyboard shortcut hint\n this.hint = el(\"div\", {\n style: `\n font-size:11px;color:${this.colors.textTertiary};\n text-align:right;margin-top:4px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n letter-spacing:0.01em;\n `,\n });\n\n this.textarea.addEventListener(\"focus\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (this.submittingState) return;\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n this.cancel();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n this.cancelBtn = document.createElement(\"button\");\n this.cancelBtn.style.cssText = `\n height:34px;padding:0 16px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n this.cancelBtn.addEventListener(\"click\", () => this.cancel());\n this.cancelBtn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.accent;\n this.cancelBtn.style.color = this.colors.accent;\n });\n this.cancelBtn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.border;\n this.cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:none;background:${this.colors.accentGradient};\n color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:600;cursor:pointer;\n opacity:0.35;pointer-events:none;\n transition:all 0.2s ease;\n box-shadow:0 2px 8px ${this.colors.accentGlow};\n display:inline-flex;align-items:center;justify-content:center;min-width:64px;\n `;\n // The submit label lives in its own <span> so the submitting-state spinner\n // can be appended/removed without disturbing it. `applyLabels()` binds its\n // text — never `setText` the button itself or it would wipe the spinner.\n this.submitLabel = document.createElement(\"span\");\n this.submitBtn.appendChild(this.submitLabel);\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(this.cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(this.typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(this.hint);\n this.root.appendChild(btnRow);\n document.body.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n }\n\n /**\n * Re-read every `t(...)`-derived label, placeholder, and aria-label from\n * the active translation function. Idempotent — call after the locale\n * dictionary has finished loading so the popup swaps from the English\n * fallback to the configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the dialog `aria-label`, the four type-button labels, the textarea\n * `placeholder` + `aria-label`, the `⌘+Enter` / `Ctrl+Enter` hint, and the\n * cancel/submit `textContent`. The single source of truth for which node\n * gets which `t()` string, shared by the constructor and `refreshLabels()`\n * so the two can never drift.\n */\n private applyLabels(): void {\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n const typeButtons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of typeButtons) {\n const type = btn.dataset.type as FeedbackType | undefined;\n if (!type) continue;\n const key = TYPE_LABEL_KEYS[type];\n if (!key) continue;\n const labelSpan = btn.querySelector<HTMLSpanElement>(\"span\");\n if (labelSpan) setText(labelSpan, this.t(key));\n }\n\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n setText(this.hint, isMacPlatform() ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n setText(this.cancelBtn, this.t(\"popup.cancel\"));\n // Target the label <span>, not the button — the button also hosts the\n // submitting-state spinner, which `setText` on the button would erase.\n setText(this.submitLabel, this.t(\"popup.submit\"));\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n *\n * When `onSubmit` is provided the popup stays visible while the handler\n * runs — the submit button shows a spinner, every other control is\n * disabled. On success the popup closes; on rejection it restores so the\n * user can retry without re-entering the form.\n */\n show(rectBounds: DOMRect, onSubmit?: PopupSubmitHandler): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.resolve = resolve;\n this.onSubmit = onSubmit ?? null;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.submittingState = false;\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n // Position: bottom-left of rect, 8px below\n const popupH = 220;\n const popupW = 300;\n let top = rectBounds.bottom + 8;\n let left = rectBounds.left;\n\n // Vertical: prefer below; fall back to above; otherwise clamp inside viewport\n if (top + popupH > window.innerHeight) {\n const aboveTop = rectBounds.top - popupH - 8;\n if (aboveTop >= 8) {\n top = aboveTop;\n } else {\n // Rect is taller than the viewport allows on either side —\n // clamp to keep the popup fully visible.\n top = window.innerHeight - popupH - 8;\n }\n }\n // Collision: flip right if not enough space on left\n if (left + popupW > window.innerWidth) {\n left = rectBounds.right - popupW;\n }\n left = Math.max(8, left);\n top = Math.max(8, top);\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n this.root.style.display = \"block\";\n\n // Install focus trap\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n // Trigger animation\n requestAnimationFrame(() => {\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n this.textarea.focus();\n });\n });\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.disabled = false;\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n btn.style.cursor = \"pointer\";\n }\n }\n\n private updateSubmitState(): void {\n if (this.submittingState) return;\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (this.submittingState) return;\n if (!this.selectedType || !this.textarea.value.trim()) return;\n\n const result: PopupResult = { type: this.selectedType, message: this.textarea.value.trim() };\n\n if (!this.onSubmit) {\n // Legacy fire-and-forget path: resolve immediately and hide.\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n return;\n }\n\n this.enterSubmittingState();\n const submitter = this.onSubmit;\n submitter(result)\n .then(() => {\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n })\n .catch(() => {\n // Restore the form so the user can edit and retry. The caller is\n // responsible for surfacing the error (live region / toast) — we\n // intentionally do not show inline error text in the popup.\n this.exitSubmittingState();\n });\n }\n\n private cancel(): void {\n if (this.submittingState) return;\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n /**\n * Swap the submit button's text for a spinner and freeze every other\n * control. Mirrors the panel's resolve/delete buttons (`sp-spinner--sm`)\n * but renders inline because the popup lives outside the Shadow DOM\n * and therefore can't reach the panel's CSS classes.\n */\n private enterSubmittingState(): void {\n this.submittingState = true;\n\n // Submit: spinner instead of text, keep button width stable\n this.submitLabel.style.display = \"none\";\n this.submitBtn.disabled = true;\n this.submitBtn.style.cursor = \"wait\";\n this.submitBtn.style.opacity = \"0.85\";\n this.submitBtn.setAttribute(\"aria-busy\", \"true\");\n this.submitBtn.appendChild(this.buildSpinner());\n\n // Cancel: dimmed and non-interactive — abandoning mid-upload would leak a\n // half-sent feedback on the server, so we hold the user until we know.\n this.cancelBtn.disabled = true;\n this.cancelBtn.style.opacity = \"0.5\";\n this.cancelBtn.style.cursor = \"not-allowed\";\n this.cancelBtn.style.pointerEvents = \"none\";\n\n // Textarea + type buttons: read-only\n this.textarea.disabled = true;\n this.textarea.style.opacity = \"0.6\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = true;\n btn.style.cursor = \"not-allowed\";\n btn.style.opacity = \"0.6\";\n }\n }\n\n private exitSubmittingState(): void {\n this.submittingState = false;\n\n // Submit — tear down the spinner: cancel the WAAPI animation explicitly\n // (it has `iterations: Infinity`, so it never ends on its own) before\n // removing the element it drives.\n this.spinnerAnimation?.cancel();\n this.spinnerAnimation = null;\n const spinner = this.submitBtn.querySelector<HTMLDivElement>('[data-role=\"sp-popup-spinner\"]');\n spinner?.remove();\n this.submitLabel.style.display = \"\";\n this.submitBtn.removeAttribute(\"aria-busy\");\n this.submitBtn.style.cursor = \"pointer\";\n\n // Cancel\n this.cancelBtn.disabled = false;\n this.cancelBtn.style.opacity = \"1\";\n this.cancelBtn.style.cursor = \"pointer\";\n this.cancelBtn.style.pointerEvents = \"auto\";\n\n // Textarea + type buttons\n this.textarea.disabled = false;\n this.textarea.style.opacity = \"1\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = false;\n btn.style.cursor = \"pointer\";\n btn.style.opacity = \"1\";\n }\n\n // Recompute submit enabled state from the (preserved) form fields\n this.updateSubmitState();\n }\n\n /**\n * Build a spinner element styled inline. Web Animations API drives the\n * rotation so we don't have to inject `@keyframes` into the host document.\n * Respects `prefers-reduced-motion`: omits the animation and falls back to\n * a static ring. The returned `Animation` handle is stored on the instance\n * so `exitSubmittingState()` can explicitly cancel it.\n */\n private buildSpinner(): HTMLDivElement {\n const spinner = document.createElement(\"div\");\n spinner.dataset.role = \"sp-popup-spinner\";\n spinner.style.cssText = `\n width:14px;height:14px;\n border:2px solid rgba(255,255,255,0.35);\n border-top-color:#fff;\n border-radius:50%;\n box-sizing:border-box;\n `;\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n // Web Animations API is available in every browser we target; the guard\n // is defensive for jsdom in tests, where `animate` may be undefined.\n if (!reduceMotion && typeof spinner.animate === \"function\") {\n this.spinnerAnimation = spinner.animate([{ transform: \"rotate(0deg)\" }, { transform: \"rotate(360deg)\" }], {\n duration: 600,\n iterations: Infinity,\n easing: \"linear\",\n });\n }\n return spinner;\n }\n\n private hideElement(): void {\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n // Make sure the submitting decoration doesn't leak into the next show()\n if (this.submittingState) this.exitSubmittingState();\n this.onSubmit = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(8px) scale(0.98)\";\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n setTimeout(() => {\n this.root.style.display = \"none\";\n }, 250);\n }\n\n destroy(): void {\n // Settle a pending `show()` promise so it cannot outlive teardown — a\n // `destroy()` mid-submit would otherwise leak the awaiting closure (and\n // whatever it retains: the annotation, the base64 screenshot). Resolving\n // with `null` reads as \"cancelled\", matching `cancel()`.\n if (this.submittingState) this.exitSubmittingState();\n this.resolve?.(null);\n this.resolve = null;\n this.onSubmit = null;\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.root.remove();\n }\n}\n","/**\n * Screenshot capture via html2canvas.\n *\n * `html2canvas` is a regular `dependency` of `@siteping/widget` — every\n * install gets it. We dynamic-import it so bundlers emit a separate chunk\n * loaded only when `enableScreenshot: true` triggers the first capture;\n * hosts that never enable screenshots pay only the disk-space cost.\n *\n * On capture failure (content-tainted canvas, version mismatch, missing 2D\n * context) we return `null` rather than throwing — the feedback is still\n * submitted, just without an image.\n */\n\nimport type { ScreenshotRegion } from \"@siteping/core\";\n\ntype Html2CanvasFn = (element: HTMLElement, options?: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\n\ninterface Html2CanvasOptions {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n useCORS?: boolean;\n allowTaint?: boolean;\n logging?: boolean;\n ignoreElements?: (element: Element) => boolean;\n}\n\nlet cachedHtml2Canvas: Html2CanvasFn | null | undefined; // undefined = not loaded yet, null = failed\nlet warnedAboutMissingDep = false;\n\nasync function loadHtml2Canvas(): Promise<Html2CanvasFn | null> {\n if (cachedHtml2Canvas !== undefined) return cachedHtml2Canvas;\n try {\n // Static dynamic import — bundlers (Vite, webpack, esbuild) resolve this\n // at build time and emit a separate chunk loaded only on first capture.\n // html2canvas ships as a regular dependency so this resolves on every\n // install. Earlier attempts to dodge static resolution via magic comments\n // silently broke production: bare specifiers can't be resolved at runtime\n // in browsers without import maps.\n const mod = (await import(\"html2canvas\")) as { default?: Html2CanvasFn } & Html2CanvasFn;\n cachedHtml2Canvas = (mod.default ?? mod) as Html2CanvasFn;\n return cachedHtml2Canvas;\n } catch (err) {\n cachedHtml2Canvas = null;\n if (!warnedAboutMissingDep) {\n warnedAboutMissingDep = true;\n console.warn(\n \"[siteping] html2canvas import failed unexpectedly. Capture is disabled for this session — feedbacks are still submitted, just without screenshots. Underlying error:\",\n err,\n );\n }\n return null;\n }\n}\n\nexport interface CaptureOptions {\n /** JPEG quality 0..1 (default 0.85). */\n quality?: number;\n /** Max output width in CSS pixels (default 1200). Wider canvases are downscaled. */\n maxWidth?: number;\n}\n\n/** Result of a contextual capture: the JPEG plus where the drawn rect sits in it. */\nexport interface AnnotatedScreenshot {\n /** Base64 JPEG `data:` URL of the padded capture area. */\n dataUrl: string;\n /** The drawn rect's position within the image, as fractions of its dimensions. */\n region: ScreenshotRegion;\n}\n\n/** Clamp `value` into `[min, max]`. */\nfunction clamp(min: number, value: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Round a fraction to 4 decimals and clamp it into [0, 1]. */\nfunction roundPct(value: number): number {\n return clamp(0, Math.round(value * 10_000) / 10_000, 1);\n}\n\n/**\n * Capture the drawn rect *plus surrounding context* as a JPEG data URL, and\n * report where the rect sits inside the image (`region`, as fractions of the\n * image dimensions) so dashboards can re-render the annotation on top.\n * Returns `null` on any failure — callers should not abort feedback submission.\n *\n * - Pads the rect by up to 60% of its own size (48px floor, 280/220px ceiling)\n * so reviewers see the UI around the annotation, not just its pixels\n * - Clamps the capture area to the document bounds (no blank margins)\n * - Excludes Siteping's own overlay elements via `ignoreElements`\n * - Honors devicePixelRatio for crisp captures, then downscales to `maxWidth`\n * — `region` is resolution-independent, so it survives the downscale\n * - JPEG at `quality` (0.85 = ~50–150 KB for a typical annotated area)\n */\nexport async function captureAnnotatedScreenshot(\n rect: DOMRect,\n options?: CaptureOptions,\n): Promise<AnnotatedScreenshot | null> {\n const html2canvas = await loadHtml2Canvas();\n if (!html2canvas) return null;\n\n const quality = options?.quality ?? 0.85;\n const maxWidth = options?.maxWidth ?? 1200;\n\n // Contextual padding, proportional to the rect with fixed floor/ceiling —\n // small rects still get enough context to be recognizable, huge rects\n // don't balloon the capture (CSS px).\n const padX = clamp(48, rect.width * 0.6, 280);\n const padY = clamp(48, rect.height * 0.6, 220);\n\n // Document coordinates of the drawn rect (rect is viewport-relative).\n const docX = window.scrollX + rect.x;\n const docY = window.scrollY + rect.y;\n\n // Clamp the padded capture area to the document bounds so html2canvas\n // never renders blank out-of-document margins.\n const docW = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);\n const docH = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);\n const capX = Math.max(0, docX - padX);\n const capY = Math.max(0, docY - padY);\n const capW = Math.min(docW, docX + rect.width + padX) - capX;\n const capH = Math.min(docH, docY + rect.height + padY) - capY;\n if (capW <= 0 || capH <= 0) return null;\n\n // Fractions are resolution-independent — computed once from CSS-px\n // geometry, they stay valid after the hi-DPI render and the downscale.\n const region: ScreenshotRegion = {\n xPct: roundPct((docX - capX) / capW),\n yPct: roundPct((docY - capY) / capH),\n wPct: roundPct(rect.width / capW),\n hPct: roundPct(rect.height / capH),\n };\n\n try {\n const canvas = await html2canvas(document.body, {\n x: capX,\n y: capY,\n width: capW,\n height: capH,\n scale: window.devicePixelRatio,\n useCORS: true,\n allowTaint: true,\n logging: false,\n ignoreElements: (element: Element) => {\n // Matched elements (and their descendants) are removed from the\n // render pass — the page underneath shows through. Two layers of\n // exclusion:\n //\n // 1. The widget's own shadow host (`<siteping-widget>`).\n // 2. Anything carrying `data-siteping-ignore=\"true\"` — the\n // documented host-facing masking attribute AND how widget\n // chrome that lives OUTSIDE the shadow host (annotator overlay\n // + toolbar + drawing rect, popup) opts itself out of capture.\n // Without (2) the accent-colored selection border ends up\n // baked into the JPEG.\n return (\n element.tagName === \"SITEPING-WIDGET\" ||\n element.closest?.(\"siteping-widget\") !== null ||\n element.getAttribute?.(\"data-siteping-ignore\") === \"true\"\n );\n },\n });\n\n if (canvas.width <= maxWidth) {\n return { dataUrl: canvas.toDataURL(\"image/jpeg\", quality), region };\n }\n\n // Downscale via an off-DOM canvas — keeps payload reasonable on\n // hi-DPI displays where the raw capture can be 2x–3x intended size.\n const ratio = maxWidth / canvas.width;\n const targetW = maxWidth;\n const targetH = Math.round(canvas.height * ratio);\n\n const scaled = document.createElement(\"canvas\");\n scaled.width = targetW;\n scaled.height = targetH;\n const ctx = scaled.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(canvas, 0, 0, targetW, targetH);\n return { dataUrl: scaled.toDataURL(\"image/jpeg\", quality), region };\n } catch (err) {\n console.warn(\"[siteping] Screenshot capture failed:\", err);\n return null;\n }\n}\n\n/** @internal — exposed for tests. Resets the dynamic-import cache. */\nexport function _resetScreenshotCacheForTests(): void {\n cachedHtml2Canvas = undefined;\n warnedAboutMissingDep = false;\n}\n","import type { AnnotationPayload, FeedbackType, ScreenshotRegion } from \"@siteping/core\";\nimport { INSTANT_ANNOTATION_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { isWidgetChrome } from \"./focus-tracker.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport { type AnnotatedScreenshot, captureAnnotatedScreenshot } from \"./screenshot.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n /**\n * Base64 JPEG `data:` URL captured by html2canvas, or null when capture\n * is disabled / failed / the peer dep is missing.\n */\n screenshotDataUrl?: string | null | undefined;\n /**\n * Where the drawn rect sits within the captured screenshot, as fractions\n * of the image dimensions — see `ScreenshotRegion`. Null whenever\n * `screenshotDataUrl` is null.\n */\n screenshotRegion?: ScreenshotRegion | null | undefined;\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n /**\n * True when the current annotation session was triggered by right-click\n * (instant comment) rather than the FAB draw flow. Controls whether the\n * toolbar is shown and whether cancel deactivates unconditionally.\n */\n private instantMode = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n /**\n * Target of the keyboard (Enter) annotation path — the page element focused\n * at activation, or the focus tracker's fallback when activation came from\n * the widget's own chrome (FAB menu). Distinct from `preActiveFocusElement`,\n * which keeps its focus-restore role untouched. See issue #162.\n */\n private keyboardTarget: HTMLElement | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n /**\n * Reject handle for the in-flight `runSubmission` promise, or null when no\n * submission is pending. Serves two purposes: a non-null value means a\n * submission is in flight (so pointer-driven drawing is suppressed — the\n * popup is open), and `destroy()` calls it to settle the promise rather\n * than leaving the awaiting closure hung past teardown.\n */\n private rejectPendingSubmission: ((reason: Error) => void) | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly enableScreenshot: boolean = false,\n private readonly getFallbackTarget?: () => HTMLElement | null,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n /**\n * True while the annotator is active (overlay/popup session in progress).\n * The launcher checks this before calling `preventDefault()` on the\n * `contextmenu` event so a right-click during an active session falls\n * through to the native menu instead of being silently swallowed.\n */\n get isBusy(): boolean {\n return this.isActive;\n }\n\n /**\n * Re-read every `t(...)`-derived label inside the popup. The annotator's\n * own toolbar text is created fresh on every `activate()` call, so only\n * the long-lived popup needs explicit re-localization here.\n */\n refreshLabels(): void {\n this.popup.refreshLabels();\n }\n\n /**\n * True while a submission is in flight (popup open, `runSubmission`\n * pending). Drawing a second rectangle in this window would orphan the\n * first `popup.show()` promise and start a second, concurrent\n * `runSubmission` — so all drawing entry points are no-ops while it holds.\n */\n private get submissionInFlight(): boolean {\n return this.rejectPendingSubmission !== null;\n }\n\n /**\n * Capture a contextual screenshot of the drawn rect (padded with the\n * surrounding UI, plus the rect's region within the image) when\n * `enableScreenshot` is on. Returns null on disable / capture failure /\n * missing peer dep — the feedback is always submitted regardless.\n */\n private async maybeCapture(rect: DOMRect): Promise<AnnotatedScreenshot | null> {\n if (!this.enableScreenshot) return null;\n return captureAnnotatedScreenshot(rect);\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n const drawMode = !this.instantMode;\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Keyboard (Enter) target. FAB-launched sessions re-focus the FAB before\n // activation, so the active element here is only the widget's 0x0 shadow\n // host — fall back to the last page element the focus tracker recorded\n // instead of silently dead-ending the Enter path. See issue #162.\n const active = document.activeElement;\n this.keyboardTarget =\n active instanceof HTMLElement &&\n active !== document.body &&\n active !== document.documentElement &&\n !isWidgetChrome(active)\n ? active\n : (this.getFallbackTarget?.() ?? null);\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth.\n //\n // Overlay, toolbar and the drawn rectangle live on document.body, outside\n // the siteping-widget shadow host. Without the `data-siteping-ignore`\n // marker the screenshot predicate in screenshot.ts cannot reach them —\n // and the accent-colored selection border plus the page tint end up\n // baked into the captured JPEG. See issue #124.\n this.overlay = el(\"div\", {\n style: `\n position:fixed;inset:0;\n z-index:${Z_INDEX_MAX - 1};\n background:rgba(15, 23, 42, 0.04);\n cursor:${drawMode ? \"crosshair\" : \"default\"};\n `,\n });\n // The overlay is an interactive surface (draw with the pointer, Enter to\n // annotate the previously focused element, Escape to cancel) and receives\n // programmatic focus below — so it must be exposed to assistive tech, NOT\n // aria-hidden: focusing an aria-hidden element parks screen-reader users\n // on a node that announces nothing (axe \"aria-hidden-focus\", serious).\n this.overlay.setAttribute(\"role\", \"application\");\n this.overlay.setAttribute(\n \"aria-label\",\n drawMode ? this.t(\"annotator.instruction\") : this.t(\"annotator.instantInstruction\"),\n );\n this.overlay.setAttribute(\"data-siteping-ignore\", \"true\");\n\n // Toolbar — glassmorphism bar (suppressed in instant mode: the\n // \"Draw a rectangle\" copy is wrong when the composer is already open)\n if (drawMode) {\n this.toolbar = el(\"div\", {\n style: `\n position:fixed;top:0;left:0;right:0;\n z-index:${Z_INDEX_MAX};\n height:52px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border-bottom:1px solid ${this.colors.glassBorder};\n display:flex;align-items:center;justify-content:center;gap:16px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:14px;color:${this.colors.text};\n box-shadow:0 4px 16px ${this.colors.shadow};\n -webkit-font-smoothing:antialiased;\n `,\n });\n this.toolbar.setAttribute(\"data-siteping-ignore\", \"true\");\n\n const dot = el(\"span\", {\n style: `\n width:8px;height:8px;border-radius:50%;\n background:${this.colors.accent};\n box-shadow:0 0 8px ${this.colors.accentGlow};\n animation:pulse 1.5s ease-in-out infinite;\n `,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instruction = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;\" });\n setText(instruction, this.t(\"annotator.instruction\"));\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.deactivate());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instruction);\n this.toolbar.appendChild(cancelBtn);\n }\n\n if (drawMode) {\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the captured keyboard target\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n }\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n document.body.appendChild(this.overlay);\n if (this.toolbar) document.body.appendChild(this.toolbar);\n\n // Move focus to the overlay so the keyboard-annotation path (Enter →\n // annotate the captured keyboard target) actually receives keydown —\n // onOverlayKeyDown only fires when the overlay itself is focused. The\n // overlay has tabindex=0, and the keyboard target was captured at the top\n // of activate(), before the overlay existed, so focusing here doesn't\n // clobber it. (WCAG 2.1.1 Level A)\n this.overlay.focus({ preventScroll: true });\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.instantMode = false;\n const previouslyFocused = this.preActiveFocusElement;\n this.preActiveFocusElement = null;\n this.keyboardTarget = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n // Removing the focused overlay drops focus to <body> — hand it back to the\n // element that had it before activation (WCAG 2.4.3 focus order). When\n // activation came from the FAB menu this element is the shadow host and\n // focus() is a no-op; the Fab restores itself on annotation:end instead.\n if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) {\n previouslyFocused.focus({ preventScroll: true });\n }\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.deactivate();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the keyboard target captured at activation (the focused page element, or\n * the focus tracker's fallback for FAB-launched sessions) and creates a\n * full-bounds annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n // A submission is already running with the popup open — ignore so we\n // can't orphan the first `popup.show()` / `runSubmission` pair.\n if (this.submissionInFlight) return;\n // Mid-pointer-drag: the user is drawing — hijacking `drawingRect` for the\n // keyboard highlight here would corrupt the drag's geometry updates.\n if (this.isDrawing) return;\n\n const target = this.keyboardTarget;\n if (!target || !(target instanceof HTMLElement)) return;\n\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n // Highlight the target like a pointer-drawn rectangle so keyboard users\n // see what they're about to comment. Assigned to `drawingRect` so every\n // existing cleanup path (deactivate, screenshot exclusion, removal once\n // the popup closes) treats it exactly like the mouse path's rect.\n this.drawingRect?.remove();\n const highlight = this.createDrawingRect();\n highlight.style.left = `${bounds.x}px`;\n highlight.style.top = `${bounds.y}px`;\n highlight.style.width = `${bounds.width}px`;\n highlight.style.height = `${bounds.height}px`;\n this.drawingRect = highlight;\n this.overlay?.appendChild(highlight);\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n // Submission stays inside the popup so the user gets a visible spinner\n // until the server confirms — see finishDrawing for the rationale.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n // Suppress pointer-driven drawing while a submission is in flight: the\n // popup is open over the page, and starting a second rectangle would\n // orphan the first `popup.show()` promise (and its `runSubmission`).\n // This also closes a latent bug where drawing during the open popup\n // already overwrote `Popup.resolve`.\n if (this.submissionInFlight) return;\n\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = this.createDrawingRect();\n this.overlay?.appendChild(this.drawingRect);\n }\n\n /**\n * The accent-colored selection rectangle — shared by pointer drawing and\n * the keyboard (Enter) highlight so the two paths can't drift visually.\n * Excluded from screenshot capture (see overlay creation in activate()).\n */\n private createDrawingRect(): HTMLElement {\n const rect = el(\"div\", {\n style: `\n position:fixed;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n transition:box-shadow 0.15s ease;\n `,\n });\n rect.setAttribute(\"data-siteping-ignore\", \"true\");\n return rect;\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (touch) await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < 10 || h < 10) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Build annotation payload BEFORE the popup opens — the overlay is still\n // up so `findAnchorElement` can briefly disable pointer events on it.\n const { annotation } = this.buildAnnotation(rectBounds);\n\n // Keep the drawn rectangle visible while the popup is open so the user\n // can see what they're sending feedback about — including while the\n // submit-spinner is running. We only remove it after the popup closes.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n /**\n * Instantly triggers the annotation popup at a specific location without\n * requiring the user to draw a rectangle. Used for right-click commenting.\n *\n * Entry is routed through the event bus (`annotation:start`) so the public\n * event contract (`onAnnotationStart` / `onAnnotationEnd`) is honoured —\n * hosts that pause analytics or chat widgets on annotation hooks see a\n * symmetric start/end pair regardless of entry path.\n */\n public async startInstantAnnotation(clientX: number, clientY: number): Promise<void> {\n // Guard: no-op while the annotator is active (overlay/popup session in\n // progress). `isActive` covers the entire window: draw mode in progress,\n // popup open for typing, and submission in flight. Without this a second\n // right-click (e.g. to paste in the textarea) would reset the form,\n // orphan the pending popup.show(), and leak the old drawing rect.\n if (this.isActive) return;\n\n // Set instant-mode flag BEFORE emitting annotation:start so activate()\n // (called by the bus handler) can read it and suppress the toolbar.\n this.instantMode = true;\n this.bus.emit(\"annotation:start\");\n\n // Build a small point-rect centered at the cursor for the marker/percentage\n // math. Clamped to viewport edges on all sides.\n const x = Math.max(0, Math.min(clientX - INSTANT_ANNOTATION_SIZE / 2, window.innerWidth - INSTANT_ANNOTATION_SIZE));\n const y = Math.max(\n 0,\n Math.min(clientY - INSTANT_ANNOTATION_SIZE / 2, window.innerHeight - INSTANT_ANNOTATION_SIZE),\n );\n const pointRect = new DOMRect(x, y, INSTANT_ANNOTATION_SIZE, INSTANT_ANNOTATION_SIZE);\n\n // Resolve the anchor element and build the annotation payload.\n // We also derive the capture rect from the anchor element's bounding box\n // (clamped to the viewport) so enableScreenshot produces a useful image\n // instead of a postage stamp.\n const { annotation, anchorBounds } = this.buildAnnotation(pointRect);\n\n // Use the anchor element's bounding box (clamped to viewport) for\n // screenshot capture so reviewers get meaningful context, not a 20×20 px\n // postage stamp.\n const left = Math.max(0, anchorBounds.left);\n const top = Math.max(0, anchorBounds.top);\n const captureRect = new DOMRect(\n left,\n top,\n Math.max(0, Math.min(anchorBounds.right, window.innerWidth) - left),\n Math.max(0, Math.min(anchorBounds.bottom, window.innerHeight) - top),\n );\n\n // Create a visual indicator at the click point\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n left:${x}px;\n top:${y}px;\n width:${INSTANT_ANNOTATION_SIZE}px;\n height:${INSTANT_ANNOTATION_SIZE}px;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n `,\n });\n this.drawingRect.setAttribute(\"data-siteping-ignore\", \"true\");\n this.overlay?.appendChild(this.drawingRect);\n\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n await this.popup.show(pointRect, (formResult) =>\n this.runSubmission(annotation, formResult, captureRect, screenshotCache),\n );\n\n // Instant flow: always deactivate on popup close — unlike the draw flow\n // where cancel keeps the session alive so the user can re-draw, there is\n // no draw phase to return to here. Leaving the overlay, scroll-lock and\n // toolbar up after cancel strands the user in a mode they never opted into.\n this.drawingRect?.remove();\n this.drawingRect = null;\n this.deactivate();\n }\n\n /**\n * Submit handler passed into `popup.show()`. Captures the screenshot once\n * (cached across retries) and emits `annotation:complete` on the bus, then\n * waits for one of three terminal signals:\n *\n * - `feedback:sent` — resolve (popup closes).\n * - `feedback:error` — reject with the genuine error (popup restores for\n * retry; the launcher surfaces the error to the host).\n * - `submission:cancelled` — reject as a silent abort (popup restores; no\n * error is surfaced — e.g. the user cancelled the identity prompt).\n *\n * Submissions are serialized by the drawing guards (`submissionInFlight`),\n * so exactly one `runSubmission` is ever live — the global outcome events\n * cannot cross-wire between submissions and need no correlation id.\n */\n private async runSubmission(\n annotation: AnnotationPayload,\n formResult: { type: FeedbackType; message: string },\n rectBounds: DOMRect,\n screenshotCache: { value?: AnnotatedScreenshot | null },\n ): Promise<void> {\n // Screenshot capture is the slow part. Capture once and reuse the\n // cached data URL + region on every retry — re-running html2canvas after\n // each failed submit would punish the user for a network blip.\n if (screenshotCache.value === undefined) {\n screenshotCache.value = await this.maybeCapture(rectBounds);\n }\n const capture = screenshotCache.value;\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n unsubSent();\n unsubError();\n unsubCancelled();\n this.rejectPendingSubmission = null;\n };\n const unsubSent = this.bus.on(\"feedback:sent\", () => {\n cleanup();\n resolve();\n });\n const unsubError = this.bus.on(\"feedback:error\", (err) => {\n cleanup();\n reject(err);\n });\n const unsubCancelled = this.bus.on(\"submission:cancelled\", () => {\n cleanup();\n // Silent abort — the popup restores but no error is surfaced.\n reject(new Error(\"Feedback submission cancelled\"));\n });\n\n // Expose the reject handle so `destroy()` mid-submit can settle this\n // promise instead of leaving the awaiting closure hung past teardown.\n this.rejectPendingSubmission = (reason) => {\n cleanup();\n reject(reason);\n };\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: formResult.type,\n message: formResult.message,\n screenshotDataUrl: capture?.dataUrl ?? null,\n screenshotRegion: capture?.region ?? null,\n });\n });\n }\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): { annotation: AnnotationPayload; anchorBounds: DOMRect } {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n const annotation = {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n return { annotation, anchorBounds };\n }\n destroy(): void {\n this.deactivate();\n // Settle an in-flight submission BEFORE tearing down the popup, so the\n // `runSubmission` promise cannot outlive teardown. The launcher's\n // `destroy()` also calls `bus.removeAll()`, which would otherwise strip\n // the terminal-event listeners and leave the promise — and the base64\n // screenshot it retains — hung forever.\n this.rejectPendingSubmission?.(new Error(\"Annotator destroyed during submission\"));\n this.popup.destroy();\n }\n}\n","import {\n type FeedbackPayload,\n type FeedbackResponse,\n type FeedbackResponseList,\n type FeedbackStatus,\n type FeedbackType,\n SitepingAuthError,\n SitepingError,\n type SitepingHeadersOption,\n SitepingNetworkError,\n SitepingValidationError,\n} from \"@siteping/core\";\nimport type { Identity } from \"./identity.js\";\n\n/**\n * Map a non-OK Response to the appropriate typed error.\n * - 401 / 403 → `SitepingAuthError`\n * - 4xx → `SitepingValidationError`\n * - 5xx (or anything else) → generic `SitepingError`\n *\n * We consume the response body via `.text()` so the caller can keep the\n * server-supplied message in the thrown error. `text()` is awaited inside\n * a try/catch because some upstreams return `Content-Length: 0` with a\n * non-text type and `.text()` rejects.\n */\nasync function errorFromResponse(response: Response, label: string): Promise<SitepingError> {\n // Match the legacy fallback string (\"Unknown error\") so host apps that\n // already grep error messages don't break on the migration.\n const text = await response.text().catch(() => \"Unknown error\");\n const detail = text ? `${response.status} ${text}` : `${response.status}`;\n const message = `${label}: ${detail}`;\n if (response.status === 401 || response.status === 403) return new SitepingAuthError(message);\n if (response.status >= 400 && response.status < 500) return new SitepingValidationError(message);\n return new SitepingError(message, \"SERVER\", false);\n}\n\n/**\n * Normalise an exception thrown by `fetch` (or our timeout AbortController)\n * into a `SitepingNetworkError`. We treat AbortErrors as network failures\n * because in our code path they always come from the internal timeout, not\n * a user-driven cancellation.\n */\nfunction networkErrorFromException(error: unknown, label: string): SitepingNetworkError {\n if (error instanceof SitepingNetworkError) return error;\n const detail = error instanceof Error ? error.message : String(error);\n return new SitepingNetworkError(`${label}: ${detail}`);\n}\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/** Options accepted by `WidgetClient.getFeedbacks`. */\nexport interface GetFeedbacksOptions {\n page?: number;\n limit?: number;\n type?: FeedbackType;\n /** Exact single-status filter. For \"any of a set\" (bucket) semantics, use `statuses`. */\n status?: FeedbackStatus;\n /**\n * Bucket status filter — matches feedbacks whose status is any of these\n * values. Serialized to the wire as `statuses=<csv>` and wins over the exact\n * `status` filter server-side. Used by the panel's binary Open/Resolved tabs.\n */\n statuses?: readonly FeedbackStatus[];\n search?: string;\n /** Restrict to feedbacks created on this exact URL (path). */\n url?: string;\n /** Restrict to feedbacks created on this URL pattern (e.g. `/orders/:orderId`). */\n urlPattern?: string;\n}\n\n/** Auth options for `ApiClient` / `flushRetryQueue` (HTTP mode). */\nexport interface ApiClientAuth {\n /** Sent as `Authorization: Bearer <apiKey>` on every request. */\n apiKey?: string | undefined;\n /** Extra headers, static or per-request factory. An explicit `Authorization` entry wins over `apiKey`. */\n headers?: SitepingHeadersOption | undefined;\n}\n\n/**\n * Build the headers for one request — mirrors the dashboard's\n * `createEndpointSource` semantics: `Content-Type` when the request carries a\n * JSON body, then `Bearer` from `apiKey`, then `headers` merged on top so an\n * explicit `Authorization` wins.\n *\n * A function `headers` resolves once per call — retries inside\n * `resilientFetch` reuse the values for the whole retry sequence — up to\n * ~45s worst case with 4 attempts x 10s timeout plus backoff (the dashboard\n * has the same per-request semantics, without retries). A\n * throwing/rejecting factory fails the request like a network error.\n */\nexport async function buildRequestHeaders(auth: ApiClientAuth, json: boolean): Promise<Record<string, string>> {\n const merged: Record<string, string> = {};\n if (json) merged[\"Content-Type\"] = \"application/json\";\n if (auth.apiKey) merged.Authorization = `Bearer ${auth.apiKey}`;\n const extra = typeof auth.headers === \"function\" ? await auth.headers() : auth.headers;\n if (extra) Object.assign(merged, extra);\n return merged;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\nasync function resilientFetch(url: string, init: RequestInit, retries = MAX_RETRIES): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n\n if (attempt === retries) return response;\n } catch (error) {\n clearTimeout(timeout);\n if (attempt === retries) throw error;\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n\n throw new Error(\"Max retries exceeded\");\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ninterface RetryEntry {\n endpoint: string;\n payload: FeedbackPayload;\n}\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\nfunction readQueue(): RetryEntry[] {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return [];\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n const queue = readQueue();\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n } catch {\n // localStorage full or unavailable — silently drop\n }\n });\n}\n\nfunction normalizeName(value: string): string {\n return value.trim();\n}\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Flush queued feedbacks for `endpoint`. When `currentIdentity` is provided,\n * entries whose stored author doesn't match it are dropped rather than replayed.\n * This prevents user A's offline feedback from being POSTed under user B's\n * identity after a session change. When omitted, all entries are replayed to\n * preserve the legacy behavior for callers that don't track identity.\n *\n * `auth` headers resolve fresh at flush time (once per flush call) — queue\n * entries persist payloads only, never headers or token material.\n */\nexport async function flushRetryQueue(\n endpoint: string,\n currentIdentity?: Identity | null,\n auth: ApiClientAuth = {},\n): Promise<void> {\n await withRetryLock(async () => {\n try {\n const queue = readQueue();\n if (queue.length === 0) return;\n\n const toRetry: RetryEntry[] = [];\n const unrelated: RetryEntry[] = [];\n let dropped = 0;\n\n for (const entry of queue) {\n if (entry.endpoint !== endpoint) {\n unrelated.push(entry);\n continue;\n }\n\n if (\n !currentIdentity ||\n (normalizeName(entry.payload.authorName) === normalizeName(currentIdentity.name) &&\n normalizeEmail(entry.payload.authorEmail) === normalizeEmail(currentIdentity.email))\n ) {\n toRetry.push(entry);\n } else {\n dropped += 1;\n }\n }\n\n if (toRetry.length === 0 && dropped === 0) return;\n\n if (dropped > 0) {\n console.debug(\"[siteping] flushRetryQueue: dropped\", dropped, \"stale entries (identity changed)\");\n }\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n if (toRetry.length > 0) {\n const headers = await buildRequestHeaders(auth, true);\n for (const entry of toRetry) {\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(entry.payload),\n });\n if (!res.ok) {\n failed.push(entry);\n }\n } catch {\n failed.push(entry);\n }\n }\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = unrelated.concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/** Parse a JSON body and assert its TypeScript shape — server-side Zod is the source of truth. */\nasync function parseJsonAs<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\nexport class ApiClient implements WidgetClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n private readonly auth: ApiClientAuth = {},\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n // Only put `screenshotRegion` on the wire when a region was actually\n // captured — servers that predate the field would otherwise reject an\n // explicit `screenshotRegion: null` on every legacy capture.\n const { screenshotRegion, ...rest } = payload;\n const body: FeedbackPayload = screenshotRegion ? { ...rest, screenshotRegion } : rest;\n // Match the legacy contract: every failure path (network or HTTP) queues\n // for retry. Tests + host apps already rely on this — narrowing to\n // network-only would be a silent behaviour change.\n try {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"POST\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify(body),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to send feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to send feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n } catch (error) {\n // Queue the wire shape (region stripped when absent) so a later\n // flushRetryQueue replays exactly what a fresh POST would send.\n queueForRetry(this.endpoint, body);\n throw error;\n }\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const params = new URLSearchParams({ projectName });\n if (options?.page) params.set(\"page\", String(options.page));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.type) params.set(\"type\", options.type);\n if (options?.status) params.set(\"status\", options.status);\n if (options?.statuses?.length) params.set(\"statuses\", options.statuses.join(\",\"));\n if (options?.search) params.set(\"search\", options.search);\n if (options?.url) params.set(\"url\", options.url);\n if (options?.urlPattern) params.set(\"urlPattern\", options.urlPattern);\n\n let response: Response;\n try {\n // GET carries no body — only attach headers when auth produced some, so\n // the no-auth wire shape stays byte-identical to the legacy client.\n const headers = await buildRequestHeaders(this.auth, false);\n response = await resilientFetch(`${this.endpoint}?${params.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to fetch feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to fetch feedbacks\");\n }\n\n return parseJsonAs<FeedbackResponseList>(response);\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"PATCH\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to update feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to update feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ id, projectName: this.projectName }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete feedback\");\n }\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ projectName, deleteAll: true }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete all feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete all feedbacks\");\n }\n }\n}\n","/**\n * Console buffer — capture the last N `console.{log,info,warn,error}` calls\n * so they ship with every feedback submission.\n *\n * Why a ring buffer:\n * - **bounded memory** even on chatty pages (1000s of logs/min during dev),\n * - **last-N is the relevant slice** for debugging — what was happening just\n * before the user noticed the bug, not the full session history.\n *\n * Why monkey-patching instead of `console.dir`/Performance Timeline:\n * - host code already uses plain `console.*` everywhere, and many libraries\n * only emit through console (no other observable),\n * - patching is reversible via `dispose()` so the widget never leaves state\n * behind on `destroy()`.\n */\n\nconst DEFAULT_MAX_ENTRIES = 50;\nconst MAX_MESSAGE_LENGTH = 500;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface ConsoleEntry {\n level: \"log\" | \"info\" | \"warn\" | \"error\";\n /** ISO 8601 timestamp captured at log time. */\n timestamp: string;\n /** Best-effort string representation of the console args. */\n message: string;\n}\n\nconst LEVELS: Array<ConsoleEntry[\"level\"]> = [\"log\", \"info\", \"warn\", \"error\"];\n\n/**\n * Best-effort stringification that never throws.\n *\n * - `Error` → `Error: message\\nstack` (capped to 500 chars overall).\n * - circular / huge objects → fall back to `Object#toString()` or `\"[Unserializable]\"`.\n * - all output is truncated to `MAX_MESSAGE_LENGTH` so a single 5MB log\n * doesn't blow up the buffer (Slack-style 500 chars per row is plenty).\n */\nfunction serializeArg(arg: unknown): string {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n if (arg instanceof Error) {\n return `${arg.name}: ${arg.message}${arg.stack ? `\\n${arg.stack}` : \"\"}`;\n }\n try {\n // Replacer drops cycles + functions; functions stringify-default to\n // undefined and disappear from the output, which is the right call (we\n // don't want random function bodies in a feedback payload).\n const seen = new WeakSet<object>();\n return JSON.stringify(arg, (_key, value: unknown) => {\n if (typeof value === \"function\") return \"[Function]\";\n if (typeof value === \"symbol\") return value.toString();\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value as object)) return \"[Circular]\";\n seen.add(value as object);\n }\n return value;\n });\n } catch {\n try {\n return String(arg);\n } catch {\n return \"[Unserializable]\";\n }\n }\n}\n\nfunction formatArgs(args: readonly unknown[]): string {\n let out = \"\";\n for (let i = 0; i < args.length; i++) {\n if (i > 0) out += \" \";\n out += serializeArg(args[i]);\n if (out.length >= MAX_MESSAGE_LENGTH) break;\n }\n if (out.length > MAX_MESSAGE_LENGTH) {\n out = `${out.slice(0, MAX_MESSAGE_LENGTH - 1)}…`;\n }\n return out;\n}\n\n/**\n * Bounded ring buffer of console messages.\n *\n * Construction installs the wrappers immediately. `dispose()` restores the\n * originals exactly once (calling it twice is a no-op). Designed to be safe\n * against re-entrant or interleaved instances — each wrapper closes over the\n * original method, not over any global, so multiple buffers can coexist\n * (each captures its own copy of the args).\n */\nexport class ConsoleBuffer {\n private readonly maxEntries: number;\n private readonly entries: ConsoleEntry[] = [];\n private originals = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n // Guard against pathological values — 0 disables silently, negative\n // numbers fall through to the default, and absurdly large numbers are\n // capped so a misuse can't OOM the page.\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 1000);\n\n if (typeof console === \"undefined\") return;\n\n for (const level of LEVELS) {\n const original = (console as unknown as Record<string, ((...args: unknown[]) => void) | undefined>)[level];\n if (typeof original !== \"function\") continue;\n this.originals.set(level, original);\n\n const buffer = this;\n const wrapped = function (this: unknown, ...args: unknown[]): void {\n try {\n buffer.push(level, args);\n } catch {\n // Capturing must never break the host's console — swallow any\n // unexpected error from serialization so the original call\n // (right below) always still runs.\n }\n original.apply(this ?? console, args);\n };\n // Preserve the function name so devtools still show \"console.log\"\n // (browsers display the wrapper's name in stack traces).\n try {\n Object.defineProperty(wrapped, \"name\", { value: level });\n } catch {\n // Older engines reject defineProperty on function name — best-effort only.\n }\n (console as unknown as Record<string, unknown>)[level] = wrapped;\n }\n }\n\n private push(level: ConsoleEntry[\"level\"], args: readonly unknown[]): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push({\n level,\n timestamp: new Date().toISOString(),\n message: formatArgs(args),\n });\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): ConsoleEntry[] {\n return this.entries.slice();\n }\n\n /** Restore the original console methods. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (typeof console === \"undefined\") return;\n for (const [level, original] of this.originals) {\n try {\n (console as unknown as Record<string, unknown>)[level] = original;\n } catch {\n // Console may be frozen in exotic environments — leave the wrapper\n // in place; it still proxies to the original via closure.\n }\n }\n this.originals.clear();\n }\n}\n","/**\n * Network buffer — capture the last N failed `fetch` / `XMLHttpRequest`\n * calls (HTTP >= 400 or network error) so they ship with each feedback.\n *\n * Captures only failures because:\n * - successful requests are usually irrelevant for the \"this thing is\n * broken\" workflow,\n * - keeping the volume tiny means we can ship the full payload to the\n * server without bloating Postgres.\n *\n * Both wrappers preserve the original semantics — return values, throws,\n * AbortController behaviour, etc. The only side effect is recording a\n * `NetworkEntry` on failure.\n */\n\nconst DEFAULT_MAX_ENTRIES = 20;\nconst MAX_URL_LENGTH = 2000;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface NetworkEntry {\n url: string;\n method: string;\n /** HTTP status or 0 when the request never reached the server (network error / CORS / abort). */\n status: number;\n /** End-to-end duration in ms, rounded to the nearest integer. */\n durationMs: number;\n /** ISO 8601 timestamp at the moment the request was initiated. */\n timestamp: string;\n}\n\nfunction truncateUrl(url: string): string {\n if (url.length <= MAX_URL_LENGTH) return url;\n return `${url.slice(0, MAX_URL_LENGTH - 1)}…`;\n}\n\nfunction urlString(input: unknown): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.href;\n // `Request` instances expose `.url`\n if (typeof input === \"object\" && input !== null && \"url\" in (input as { url?: unknown })) {\n const candidate = (input as { url?: unknown }).url;\n if (typeof candidate === \"string\") return candidate;\n }\n try {\n return String(input);\n } catch {\n return \"(unknown)\";\n }\n}\n\n/**\n * Bounded ring buffer of failed network requests.\n *\n * Construction monkey-patches `globalThis.fetch` and `XMLHttpRequest` and\n * stores the originals for `dispose()`. Wrappers are designed so that\n * multiple instances can coexist (each captures independently into its own\n * buffer, and the last one disposed restores the chain correctly via the\n * stored originals).\n */\nexport class NetworkBuffer {\n private readonly maxEntries: number;\n private readonly entries: NetworkEntry[] = [];\n private originalFetch: typeof fetch | null = null;\n private originalXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private originalXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 500);\n this.installFetch();\n this.installXhr();\n }\n\n private push(entry: NetworkEntry): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push(entry);\n }\n\n private installFetch(): void {\n if (typeof globalThis.fetch !== \"function\") return;\n const original = globalThis.fetch;\n this.originalFetch = original;\n\n const wrapped: typeof fetch = async (input, init) => {\n const startedAt = new Date();\n const t0 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const url = truncateUrl(urlString(input));\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n\n try {\n const response = await original(input, init);\n if (!response.ok) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: response.status,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n }\n return response;\n } catch (err) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: 0,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n throw err;\n }\n };\n\n globalThis.fetch = wrapped;\n }\n\n private installXhr(): void {\n if (typeof XMLHttpRequest === \"undefined\") return;\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n this.originalXhrOpen = originalOpen;\n this.originalXhrSend = originalSend;\n const buffer = this;\n\n // Store the open metadata on the XHR instance via a side-channel WeakMap\n // so each request is fully isolated even with concurrent opens.\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string; startedAt: Date; t0: number }>();\n\n proto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n try {\n meta.set(this, {\n method: method.toUpperCase(),\n url: truncateUrl(urlString(url)),\n startedAt: new Date(),\n t0: typeof performance !== \"undefined\" ? performance.now() : Date.now(),\n });\n } catch {\n // Ignore — metadata is best-effort, the underlying open() still runs.\n }\n // XHR.open has two overloaded signatures (3-arg sync, 5-arg async with\n // user/password). Cast to a loose function shape to forward every arg\n // without re-enumerating the overloads here.\n const looseOpen = originalOpen as unknown as (this: XMLHttpRequest, ...a: unknown[]) => void;\n return looseOpen.call(this, method, url, ...rest);\n } as typeof proto.open;\n\n proto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const info = meta.get(this);\n if (info) {\n // `loadend` fires for both success and failure — we just inspect the\n // status to decide whether to log. Use `once: true` so a re-sent XHR\n // doesn't accumulate listeners.\n const onEnd = () => {\n try {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const status = this.status; // 0 on network error / abort\n if (status === 0 || status >= 400) {\n buffer.push({\n url: info.url,\n method: info.method,\n status,\n durationMs: Math.round(t1 - info.t0),\n timestamp: info.startedAt.toISOString(),\n });\n }\n } catch {\n // Listener must not throw — would surface as an \"Uncaught\" in\n // the host's console and pollute their logs.\n }\n };\n try {\n this.addEventListener(\"loadend\", onEnd, { once: true });\n } catch {\n // Older engines without options object — fall back to plain listener.\n try {\n this.addEventListener(\"loadend\", onEnd);\n } catch {\n // No-op\n }\n }\n }\n return originalSend.call(this, body ?? null);\n } as typeof proto.send;\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): NetworkEntry[] {\n return this.entries.slice();\n }\n\n /** Restore the original fetch + XHR methods. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n if (this.originalFetch && typeof globalThis.fetch === \"function\") {\n try {\n globalThis.fetch = this.originalFetch;\n } catch {\n // Best-effort\n }\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n try {\n if (this.originalXhrOpen) XMLHttpRequest.prototype.open = this.originalXhrOpen;\n if (this.originalXhrSend) XMLHttpRequest.prototype.send = this.originalXhrSend;\n } catch {\n // Best-effort\n }\n }\n }\n}\n","import type {\n FeedbackResponse,\n SitepingPublicEventListener,\n SitepingPublicEvents,\n SitepingUnsubscribe,\n} from \"@siteping/core\";\nimport type { AnnotationComplete } from \"./annotator.js\";\n\n/** Listener signature for a single key of an `EventBus` event map. */\nexport type EventListener<E extends Record<keyof E, unknown[]>, K extends keyof E> = (...args: E[K]) => void;\n\n/**\n * Lightweight typed `EventEmitter` — zero dependencies.\n *\n * The generic constraint guarantees each event maps to a tuple of argument\n * types, so subscribers and emitters share the exact same shape.\n */\nexport class EventBus<E extends Record<keyof E, unknown[]>> {\n private readonly listeners = new Map<keyof E, Set<EventListener<E, keyof E>>>();\n\n on<K extends keyof E>(event: K, listener: EventListener<E, K>): SitepingUnsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as EventListener<E, keyof E>);\n\n return () => {\n set?.delete(listener as EventListener<E, keyof E>);\n };\n }\n\n off<K extends keyof E>(event: K, listener: EventListener<E, K>): void {\n this.listeners.get(event)?.delete(listener as EventListener<E, keyof E>);\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n (fn as (...a: E[K]) => void)(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\n/** Full internal event map — broader than the public surface exposed to hosts. */\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [FeedbackResponse[\"id\"]];\n \"feedback:all-deleted\": [];\n \"feedback:error\": [Error];\n /** Emitted whenever the marker set changes — payload is the open (unresolved) count for the current page. */\n \"markers:changed\": [number];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [AnnotationComplete];\n /**\n * Internal-only: a feedback submission was aborted by a benign user action\n * (e.g. cancelling the identity prompt). Distinct from `feedback:error` so a\n * cancellation does not surface through the host's `onError` callback. Not\n * part of `PublicWidgetEvents` — never exposed to consumers.\n */\n \"submission:cancelled\": [];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n/**\n * Subset of `WidgetEvents` exposed to consumers via `SitepingInstance`.\n *\n * Kept structurally identical to `SitepingPublicEvents` from `@siteping/core`\n * so the launcher can bridge between the two without runtime casts. The\n * `satisfies` clause locks that contract at compile time — drift in either\n * side surfaces here.\n */\nexport type PublicWidgetEvents = SitepingPublicEvents;\n\n/** Re-export the listener signature for ergonomics on the widget side. */\nexport type PublicWidgetEventListener<K extends keyof PublicWidgetEvents> = SitepingPublicEventListener<K>;\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_CLOSE, ICON_EDIT, ICON_EYE, ICON_EYE_OFF, ICON_LIST, ICON_SITEPING } from \"./icons.js\";\n\n/** Closed set of radial menu item ids — keeps the label lookup exhaustive. */\ntype RadialItemId = \"chat\" | \"annotate\" | \"toggle-annotations\";\n\ninterface RadialItem {\n id: RadialItemId;\n icon: string;\n iconAlt?: string;\n}\n\nconst ITEM_GAP = 54;\n\n// Stable mapping between radial item ids and their translation keys. The\n// label is fully derived from this map via `t()`, so the constructor and\n// `applyLabels()` share one source of truth for which node gets which string.\nconst ITEM_LABEL_KEYS: Record<RadialItemId, keyof Translations> = {\n chat: \"fab.messages\",\n annotate: \"fab.annotate\",\n \"toggle-annotations\": \"fab.annotations\",\n};\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n const isRight = position === \"bottom-right\";\n\n // Vertical stack above the FAB. Icons:\n // - list → opens the feedback sidebar (panel of feedbacks).\n // - edit → creates a new annotation (the action).\n // - eye → toggles marker visibility on the page (state).\n // The marker-visibility toggle is opt-out via `config.showAnnotationsToggle`:\n // default `true` preserves historical behavior, `false` removes the item from\n // the menu entirely (no DOM, no keyboard slot, no click handler).\n this.items = [\n { id: \"chat\", icon: ICON_LIST },\n { id: \"annotate\", icon: ICON_EDIT },\n ];\n if (config.showAnnotationsToggle !== false) {\n this.items.push({ id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF });\n }\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n label.style.cssText = isRight\n ? \"position:absolute; right:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\"\n : \"position:absolute; left:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n\n // Close radial menu on click outside.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /**\n * Re-read every `t(...)`-derived label and aria-label from the active\n * translation function. Idempotent — call after the locale dictionary has\n * finished loading so the FAB labels swap from the English fallback to the\n * configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the FAB `aria-label`, each radial item's `aria-label`, and each\n * `.sp-radial-label` `textContent`. The single source of truth for which\n * node gets which `t()` string, shared by the constructor and\n * `refreshLabels()` so the two can never drift.\n */\n private applyLabels(): void {\n this.fab.setAttribute(\"aria-label\", this.t(\"fab.aria\"));\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n for (const btn of buttons) {\n const id = btn.dataset.itemId as RadialItemId | undefined;\n if (!id) continue;\n const key = ITEM_LABEL_KEYS[id];\n if (!key) continue;\n const label = this.t(key);\n btn.setAttribute(\"aria-label\", label);\n const labelSpan = btn.querySelector<HTMLSpanElement>(\".sp-radial-label\");\n if (labelSpan) setText(labelSpan, label);\n }\n }\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", this.t(\"fab.badge\").replace(\"{count}\", String(count)));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + ITEM_GAP * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: RadialItemId): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\": {\n // close() above re-focused the FAB, so the annotator resolves its\n // keyboard target via the focus tracker's last page element — but\n // putting keyboard users back on the FAB when the session ends is on us.\n const unsubscribe = this.bus.on(\"annotation:end\", () => {\n unsubscribe();\n this.fab.focus();\n });\n this.bus.emit(\"annotation:start\");\n break;\n }\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n // Replace ONLY the icon SVG, not every child. The button also carries\n // the `<span class=\"sp-radial-label\">` hover label — `replaceChildren`\n // wiped it on the first click, killing the tooltip until reload.\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n const oldSvg = btn?.querySelector(\"svg\");\n if (oldSvg) {\n const newSvg = parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF);\n oldSvg.replaceWith(newSvg);\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick);\n this.root.remove();\n }\n}\n","import { hasOwn } from \"@siteping/core\";\n\nconst STORAGE_KEY = \"siteping_identity\";\n\nexport interface Identity {\n name: string;\n email: string;\n}\n\n/** Type guard — narrows an unknown value to `Identity` only when both fields are non-empty strings. */\nfunction isIdentity(value: unknown): value is Identity {\n if (!hasOwn(value, \"name\") || !hasOwn(value, \"email\")) return false;\n const name = (value as { name: unknown }).name;\n const email = (value as { email: unknown }).email;\n return typeof name === \"string\" && typeof email === \"string\" && name.length > 0 && email.length > 0;\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return isIdentity(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n *\n * Approximate containment uses Sellers' algorithm (1980): a single O(n·m)\n * DP pass over the haystack whose first row is initialized to 0, yielding\n * the minimum edit distance between the needle and ANY substring. This\n * replaces a sliding fixed-length window (O(n·m²)) with identical-or-better\n * scores — a window match is one of the substrings Sellers considers.\n */\n\n/** Below this needle length, approximate substring search over a LONG\n * haystack is statistically meaningless (a 4-char needle \"matches\" almost\n * anything within 1–2 edits somewhere in 500 chars) and was the worst-case\n * cost driver. Exact containment still applies at any length, and short\n * haystacks (≤ SHORT_NEEDLE_HAYSTACK_CAP) keep approximate matching — a\n * near-miss in a short label (\"panier\" vs \"paniers\") is meaningful. */\nexport const MIN_FUZZY_NEEDLE_LENGTH = 8;\n\n/** See MIN_FUZZY_NEEDLE_LENGTH. */\nconst SHORT_NEEDLE_HAYSTACK_CAP = 64;\n\n/** Max haystack length considered for approximate matching. */\nconst HAYSTACK_CAP = 500;\n\n/**\n * Normalize text for comparison: Unicode NFC + collapse whitespace runs to a\n * single space + trim. Absorbs SSR/CSR hydration drift, prettified vs\n * minified markup, and re-indentation (formatting whitespace lives inside\n * `textContent` of nested elements). Applied at comparison time on both\n * sides — already-stored snippets stay valid. Deliberately NOT case-folding:\n * a case change is a real signal (CSS text-transform never affects\n * textContent, so case differences come from actual content edits).\n */\nexport function normalizeText(s: string): string {\n return s.normalize(\"NFC\").replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Whitespace-only collapse — the cheap subset of `normalizeText` for the scan\n * prefilter, which runs on every same-tag candidate. NFC is a table-driven\n * full-Unicode pass and is deliberately skipped there: the prefilter only\n * RANKS, and mixed composition forms cost at worst a slight rank penalty on\n * accented text (full scoring of survivors re-normalizes both sides).\n */\nexport function collapseWhitespace(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are provably in bounds (loop bounds; arrays sized aLen+1) —\n // plain casts instead of ?? fallbacks that could never fire.\n const prevDiag = prev[i - 1] as number;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] as number, curr[i - 1] as number);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] as number; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Sellers 1980 — minimum edit distance between `needle` and any substring of\n * `haystack`. Row 0 of the DP is zero for every haystack position (a match\n * may start anywhere); the answer is the running minimum of the last row.\n * Distance is bounded by needle.length (deleting the whole needle), so the\n * needle-normalized score 1 - dist/needle.length always lands in [0, 1].\n */\nfunction sellersDistance(haystack: string, needle: string): number {\n const n = needle.length;\n let prev = new Int32Array(n + 1);\n let curr = new Int32Array(n + 1);\n for (let i = 0; i <= n; i++) prev[i] = i;\n let best = n;\n\n for (let j = 1; j <= haystack.length; j++) {\n curr[0] = 0;\n const hc = haystack.charCodeAt(j - 1);\n for (let i = 1; i <= n; i++) {\n // Indices provably in bounds — casts, not ?? arms that can never fire.\n const sub = (prev[i - 1] as number) + (needle.charCodeAt(i - 1) === hc ? 0 : 1);\n const del = (prev[i] as number) + 1;\n const ins = (curr[i - 1] as number) + 1;\n curr[i] = Math.min(sub, del, ins);\n }\n const last = curr[n] as number;\n if (last < best) best = last;\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return best;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Returns the best needle-normalized similarity found, or 0 if below `minScore`.\n *\n * Pipeline (cheapest first): exact containment → direct comparison when the\n * needle is longer than the haystack → Sellers approximate substring search.\n * Short needles never enter approximate search over long haystacks (see\n * MIN_FUZZY_NEEDLE_LENGTH).\n *\n * Callers are expected to pass `normalizeText`-processed strings; this\n * function compares verbatim.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const capped = haystack.length > HAYSTACK_CAP ? haystack.slice(0, HAYSTACK_CAP) : haystack;\n\n // Needle longer than haystack — direct comparison (no substring to find)\n if (needle.length > capped.length) {\n const score = similarity(capped, needle);\n return score >= minScore ? score : 0;\n }\n\n if (needle.length < MIN_FUZZY_NEEDLE_LENGTH && capped.length > SHORT_NEEDLE_HAYSTACK_CAP) {\n return 0;\n }\n\n const score = 1 - sellersDistance(capped, needle) / needle.length;\n return score >= minScore ? score : 0;\n}\n\n/**\n * Character-bigram multiset of a string, keyed by packed char-code pairs.\n * Built once per resolution for the stored snippet, then streamed against\n * every scan candidate via `diceAgainst` — no per-candidate copy.\n */\nexport function bigramCounts(s: string): Map<number, number> {\n const counts = new Map<number, number>();\n for (let i = 0; i < s.length - 1; i++) {\n const key = (s.charCodeAt(i) << 16) | s.charCodeAt(i + 1);\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice coefficient between a precomputed bigram multiset and a raw\n * string, in O(|text|). Multiset semantics (bigram occurrences are consumed,\n * not just membership-tested) — repeated-bigram strings like \"aaaa\" would\n * otherwise score against sets they barely overlap.\n *\n * Used exclusively as a RANKING signal for scan prefiltering (top-K keep),\n * never as an eliminating threshold — so an imperfect correlation with edit\n * distance can demote a candidate but never drop a true match outright.\n */\nexport function diceAgainst(needleCounts: Map<number, number>, needleBigramTotal: number, text: string): number {\n const textBigramTotal = text.length - 1;\n if (needleBigramTotal <= 0 || textBigramTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<number, number>();\n for (let i = 0; i < text.length - 1; i++) {\n const key = (text.charCodeAt(i) << 16) | text.charCodeAt(i + 1);\n const available = needleCounts.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needleBigramTotal + textBigramTotal);\n}\n\n/**\n * Word-pair shingle multiset (\"quick brown\", \"brown fox\", …) of a\n * whitespace-normalized string. Character bigrams are order-blind: on pages\n * where many elements share a vocabulary (card grids, list views), every\n * candidate looks alike to them, while word ORDER still discriminates —\n * a true match preserves most word pairs, shared vocabulary in a different\n * order preserves almost none. Scripts without spaces produce no pairs and\n * callers fall back to character bigrams alone.\n */\nexport function wordPairCounts(s: string): Map<string, number> {\n const counts = new Map<string, number>();\n const words = s.split(\" \");\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice over word-pair shingles, multiset semantics, O(|text|).\n * Same ranking-only contract as `diceAgainst`.\n */\nexport function wordPairDiceAgainst(needlePairs: Map<string, number>, needlePairTotal: number, text: string): number {\n if (needlePairTotal <= 0) return 0;\n const words = text.split(\" \");\n const textPairTotal = words.length - 1;\n if (textPairTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<string, number>();\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n const available = needlePairs.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needlePairTotal + textPairTotal);\n}\n","/**\n * Element visibility classification for anchor resolution.\n *\n * Responsive sites render the same component twice (`hidden md:block` mobile +\n * desktop twins); resolution must prefer the rendered copy. Visibility is a\n * scoring TIER, never a hard filter — when every duplicate is hidden (e.g.\n * mobile viewport), the best hidden candidate still resolves rather than\n * orphaning the annotation.\n */\n\nexport type VisibilityClass = \"visible\" | \"soft-hidden\" | \"hidden\" | \"unknown\";\n\n/**\n * Both option-name generations must be passed together: the CSSOM spec ORs\n * the old (checkOpacity/checkVisibilityCSS) and renamed\n * (opacityProperty/visibilityProperty) flags, and Chrome 105–120 /\n * Firefox 106–121 silently ignore the new names.\n * `contentVisibilityAuto` stays OFF — `content-visibility: auto` content is\n * merely offscreen, a perfectly legitimate anchor target.\n */\nconst STRICT_VISIBILITY_OPTIONS: Record<string, boolean> = {\n checkOpacity: true,\n opacityProperty: true,\n checkVisibilityCSS: true,\n visibilityProperty: true,\n};\n\n/**\n * Classify how visible an element currently is.\n *\n * - `\"visible\"` — rendered and painted.\n * - `\"soft-hidden\"` — geometry intact but not painted (visibility:hidden,\n * opacity:0). Anchor rects computed from it stay valid;\n * opacity:0 is common mid fade-in, so this is only a mild\n * penalty, never an exclusion.\n * - `\"hidden\"` — no rendered geometry: display:none chain,\n * content-visibility:hidden (closed <details>), detached.\n * - `\"unknown\"` — the environment performs no layout (jsdom: no\n * checkVisibility, every rect zero/empty). Treated as\n * visible by scorers so layout-less test environments and\n * exotic embedders keep pre-visibility behavior.\n *\n * Fallback chain notes (browsers without checkVisibility — Safari ≤ 17.3):\n * - `getClientRects().length` is the no-box test; `getBoundingClientRect()`\n * zeros are ambiguous (real zero-sized visible elements exist).\n * - NEVER `offsetParent === null` — visible position:fixed elements (sticky\n * headers, FABs: prime feedback targets) report null.\n * - `visibility` is an inherited computed value, so one read on the candidate\n * is sufficient and correctly handles `visibility: visible` re-shows inside\n * hidden ancestors; display:none needs no ancestor walk because the box\n * tree already has no fragments for the whole subtree.\n * - content-visibility:hidden content keeps real geometry, so the fallback\n * misclassifies it as visible — acceptable: every engine old enough to lack\n * checkVisibility also predates content-visibility support.\n * - aria-hidden is deliberately ignored (visually rendered content).\n */\nexport function classifyVisibility(element: Element): VisibilityClass {\n if (!element.isConnected) return \"hidden\";\n\n // Runtime guard stays although lib.dom types it as always-present:\n // jsdom (the test environment) and Safari ≤ 17.3 don't implement it.\n if (typeof element.checkVisibility === \"function\") {\n if (element.checkVisibility(STRICT_VISIBILITY_OPTIONS)) return \"visible\";\n // Base call only rejects display:none chains and content-visibility:hidden;\n // passing it while failing the strict call means visibility/opacity hiding.\n return element.checkVisibility() ? \"soft-hidden\" : \"hidden\";\n }\n\n if (element.getClientRects().length > 0) {\n try {\n const visibility = getComputedStyle(element).visibility;\n return visibility === \"visible\" ? \"visible\" : \"soft-hidden\";\n } catch {\n return \"visible\";\n }\n }\n\n // display:contents generates no box of its own but renders its children.\n const child = element.firstElementChild;\n if (child && child.getClientRects().length > 0) return \"visible\";\n\n // No boxes anywhere — hidden, unless the environment does no layout at all\n // (then every element has zero rects and the signal is meaningless).\n if (element.ownerDocument.documentElement.getClientRects().length === 0) return \"unknown\";\n\n return \"hidden\";\n}\n\n/** Score multiplier for a visibility class — tiering, not filtering. */\nexport function visibilityFactor(cls: VisibilityClass): number {\n switch (cls) {\n case \"hidden\":\n return 0.3;\n case \"soft-hidden\":\n return 0.6;\n default:\n return 1;\n }\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { ANCHOR_KEY_ATTR } from \"./anchor.js\";\nimport { attrHash, scoreFingerprint } from \"./fingerprint.js\";\nimport {\n bigramCounts,\n collapseWhitespace,\n diceAgainst,\n fuzzyIncludes,\n normalizeText,\n similarity,\n wordPairCounts,\n wordPairDiceAgainst,\n} from \"./fuzzy.js\";\nimport { adjacentText, boundedText, neighborText } from \"./text-context.js\";\nimport { classifyVisibility, visibilityFactor } from \"./visibility.js\";\n\nexport type ResolutionStrategy = \"anchorKey\" | \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/**\n * Caller-provided allowance for full tag sweeps across a BATCH of\n * resolutions (marker init, reposition passes). A sweep is the one\n * unbounded-ish cost left in resolution; several drifted or hidden anchors\n * resolved back-to-back must not each pay one synchronously (the Hypothesis\n * issue-#3919 lesson: budget per pass, not per resolution). When the budget\n * is exhausted, resolution proceeds selector-only — the next pass gets a\n * fresh budget and heals the remainder.\n */\nexport interface ScanBudget {\n /** Remaining sweep allowance; decremented each time a sweep actually runs. */\n remaining: number;\n /** Set by the resolver when a sweep was wanted but the budget was empty —\n * callers must NOT cache such degraded results (a selector-only answer may\n * be worse than what the sweep would have found, and a cached wrong\n * element is never re-examined). */\n starved?: boolean;\n}\n\nexport interface ResolveOptions {\n scanBudget?: ScanBudget;\n}\n\n/**\n * Confidence ceiling per strategy — same ladder as v1's cascade, now used as\n * a multiplicative prior in cross-strategy ranking. Multiplicative, not\n * additive: a prior can only amplify verification evidence, never substitute\n * for it, so a stale selector with poor verification cannot outrank a\n * well-verified scan hit.\n */\nconst STRATEGY_PRIORS: Record<ResolutionStrategy, number> = {\n anchorKey: 1.0,\n id: 1.0,\n css: 0.95,\n xpath: 0.9,\n scan: 0.85,\n};\n\n/** Max matches gathered per selector strategy (guards degenerate selectors). */\nconst MAX_PER_STRATEGY = 16;\n\n/** Scan candidates that survive prefiltering and get full multi-signal scoring. */\nconst SCAN_TOP_K = 24;\n\n/** Pathological-DOM guard for the prefilter sweep itself. */\nconst SCAN_HARD_CAP = 10_000;\n\n/** Max candidate text considered for scoring (bounds fuzzy-match cost). */\nconst CANDIDATE_TEXT_CAP = 500;\n\n/**\n * Acceptance for selector strategies gates on the STRONGEST single signal,\n * never on the diluted blend — the blend is a RANKING device. A volatile\n * signal (fingerprints churn with every redesign) must not veto a stable\n * one: v1 resolved `#promo` + fuzzy-passing text regardless of what the\n * surrounding DOM did, and that must survive.\n * - text ≥ 0.5 (v1's effective bar — fuzzyIncludes' own minScore) accepts.\n * - No stored text at all: ALWAYS acceptable — v1 accepted textless selector\n * hits unconditionally, and rejection here silently orphans legacy\n * icon/image anchors whose id still matches (the sweep cannot rescue pool\n * members). Ranking and confidence already penalize structural drift.\n * - Text present but REFUTED: strong structural corroboration required —\n * the i18n case (text translated, fingerprint intact) passes, a weak\n * fingerprint coincidence does not.\n * Scan has no selector evidence, so it keeps v1's 0.4 floor on the blend.\n */\nconst TEXT_FLOOR = 0.5;\nconst STRONG_STRUCT = 0.6;\nconst ACCEPT_SCAN = 0.4;\n\n/** Hostile-stored-data guard: fields are sliced before any normalization\n * (NFC on a multi-megabyte string is itself a freeze) and again after. */\nconst RAW_FIELD_CAP = 2000;\n\n/**\n * Verification at or above this level earns the full strategy prior as\n * confidence; below it, confidence degrades proportionally (and crosses the\n * marker UI's 0.7 \"approximate\" threshold naturally).\n */\nconst STRONG_VERIFY = 0.8;\n\n/**\n * Verification assigned to selector-strategy candidates when the stored\n * anchor carries no verifiable signal at all (no text, no fingerprint, no\n * context — only possible for hand-built or pre-fingerprint data; capture\n * always stores a fingerprint). The selector match is then the only\n * evidence: accept, but rank it below verified alternatives.\n */\nconst NEUTRAL_VERIFICATION = 0.6;\n\n/** Score gap under which two candidates are considered equally plausible. */\nconst AMBIGUITY_EPSILON = 0.05;\n\n/** Stored-anchor signals, normalized once per resolution. */\ninterface AnchorSignals {\n snippet: string;\n snippetBigrams: Map<number, number>;\n snippetBigramTotal: number;\n snippetWordPairs: Map<string, number>;\n snippetWordPairTotal: number;\n prefix: string;\n suffix: string;\n neighbor: string;\n fingerprint: string;\n tag: string;\n}\n\n/** Per-signal verification scores; a signal is absent when undefined. */\ninterface SignalScores {\n blend: number;\n strongest: number;\n text?: number;\n fingerprint?: number;\n context?: number;\n neighbor?: number;\n}\n\ninterface ScoredCandidate {\n element: Element;\n strategy: ResolutionStrategy;\n verification: number;\n strongest: number;\n signals?: SignalScores;\n /** Visibility factor applied to `final` (1 = visible/unknown). */\n visibility: number;\n final: number;\n /** No verifiable signal was stored — verification is a neutral stand-in. */\n unverified?: boolean;\n}\n\nfunction boundedField(value: string | null | undefined, cap: number): string {\n return normalizeText((value ?? \"\").slice(0, RAW_FIELD_CAP)).slice(0, cap);\n}\n\nfunction buildSignals(anchor: AnchorData): AnchorSignals {\n // Capture stores ≤120-char snippets and ≤40-char context — larger values\n // only come from hostile or corrupted storage, and uncapped they turn\n // normalization/edit-distance into a main-thread freeze.\n const snippet = boundedField(anchor.textSnippet, CANDIDATE_TEXT_CAP);\n const snippetWordPairs = wordPairCounts(snippet);\n let snippetWordPairTotal = 0;\n for (const count of snippetWordPairs.values()) snippetWordPairTotal += count;\n return {\n snippet,\n snippetBigrams: bigramCounts(snippet),\n snippetBigramTotal: Math.max(0, snippet.length - 1),\n snippetWordPairs,\n snippetWordPairTotal,\n prefix: boundedField(anchor.textPrefix, 128),\n suffix: boundedField(anchor.textSuffix, 128),\n neighbor: boundedField(anchor.neighborText, 128),\n fingerprint: (anchor.fingerprint ?? \"\").slice(0, 64),\n tag: typeof anchor.elementTag === \"string\" ? anchor.elementTag : \"\",\n };\n}\n\n/**\n * Re-anchor an annotation: gather candidates from EVERY strategy, verify each\n * against all stored signals, rank across strategies, return the best.\n *\n * v1 was a first-match-wins cascade (anchorKey → id → css → xpath → scan)\n * where a wrong-but-text-passing selector hit won outright over a correct\n * element the scan would have found (#175), the first DOM match won even when\n * it was an invisible responsive twin (#171), and elements without text got\n * no verification at all (#172).\n *\n * v2 ranking: final = strategyPrior × verification × visibilityFactor\n * - verification: dynamic-weight blend of text / fingerprint / prefix-suffix /\n * neighbor signals (only signals the stored anchor has contribute).\n * - visibility: tiering, never filtering — hidden duplicates are heavily\n * penalized, but when ONLY hidden candidates exist the best one still\n * resolves (an annotation on a currently-collapsed section survives the\n * breakpoint flipping back).\n * - Confidence keeps the v1 scale: a perfectly verified anchorKey/id/css/\n * xpath match yields exactly 1.0/1.0/0.95/0.9, scan stays capped at 0.85,\n * and weak verification degrades confidence proportionally.\n *\n * The scan sweep is skipped when a selector candidate already scores above\n * anything the scan could produce (its prior caps its final at 0.85) — the\n * happy path costs a handful of querySelector calls, like v1.\n *\n * Returns null if no candidate verifies (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData, options?: ResolveOptions): AnchorResolution | null {\n const signals = buildSignals(anchor);\n const pool = gatherSelectorCandidates(anchor);\n\n const scored: ScoredCandidate[] = [];\n for (const [element, strategy] of pool) {\n const candidate = scoreOne(element, strategy, signals);\n if (candidate) scored.push(candidate);\n }\n\n let bestFinal = 0;\n let strongVisibleMatch = false;\n for (const c of scored) {\n if (c.final > bestFinal) bestFinal = c.final;\n // Identity selectors (id, anchorKey — near-unique by contract, the ones\n // v1 trusted absolutely) with near-exact text on a visible element end\n // the search even when CONTEXT signals (neighbors, prefix/suffix)\n // drifted — but not when the element's own fingerprint contradicts:\n // a wrapper that took over the id contains the same text yet scores a\n // partial fingerprint, and only the sweep can surface the true inner\n // element. Fragile selectors (css/xpath) get no shortcut at all: an\n // element that merely CONTAINS the snippet verbatim plus coincidental\n // structure is exactly the #175 impostor — they suppress the sweep\n // solely through the unbeatable-final bound below.\n if (\n (c.strategy === \"id\" || c.strategy === \"anchorKey\") &&\n c.visibility === 1 &&\n (c.signals?.text ?? 0) >= STRONG_VERIFY &&\n (c.signals?.fingerprint === undefined || c.signals.fingerprint >= STRONG_VERIFY)\n ) {\n strongVisibleMatch = true;\n }\n }\n\n // The sweep only helps when something could beat the pool (scan's final is\n // capped by its prior) AND there is at least one stored signal to verify\n // scan candidates against — with none, every scan candidate is discarded\n // and the sweep is pure cost.\n const verifiable = !!(signals.snippet || signals.fingerprint || signals.prefix || signals.suffix || signals.neighbor);\n const budget = options?.scanBudget;\n if (verifiable && bestFinal < STRATEGY_PRIORS.scan && !strongVisibleMatch) {\n if (budget && budget.remaining <= 0) {\n budget.starved = true;\n } else {\n if (budget) budget.remaining--;\n for (const element of sweepScanCandidates(signals, pool)) {\n const candidate = scoreOne(element, \"scan\", signals);\n if (candidate) scored.push(candidate);\n }\n }\n }\n\n const accepted = scored.filter(isAcceptable);\n if (accepted.length === 0) return null;\n\n accepted.sort((a, b) => b.final - a.final);\n const winner = disambiguate(accepted);\n\n return {\n element: winner.element,\n confidence: confidenceOf(winner),\n strategy: winner.strategy,\n };\n}\n\n/**\n * Collect candidates from all selector strategies, ALL matches per strategy\n * (bounded), in priority order. An element found by several strategies keeps\n * the highest-priority one (first insertion wins).\n */\nfunction gatherSelectorCandidates(anchor: AnchorData): Map<Element, ResolutionStrategy> {\n const pool = new Map<Element, ResolutionStrategy>();\n\n const add = (el: Element | null, strategy: ResolutionStrategy, enforceTag: boolean) => {\n if (!el || pool.has(el)) return;\n if (enforceTag && el.tagName !== anchor.elementTag) return;\n pool.set(el, strategy);\n };\n\n // anchorKey — host-controlled semantic key. Tag NOT enforced: hosts may\n // legitimately refactor the wrapper element while keeping the key stable.\n if (anchor.anchorKey) {\n const escaped = anchor.anchorKey.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const matches = document.querySelectorAll(`[${ANCHOR_KEY_ATTR}=\"${escaped}\"]`);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"anchorKey\", false);\n }\n } catch {\n // Invalid attribute value — skip strategy\n }\n }\n\n // id — duplicate ids are invalid HTML but common in the wild; gather all so\n // a hidden duplicate can lose to the visible one instead of shadowing it.\n // Attribute selector instead of `#…` to avoid needing CSS.escape (absent in\n // some embedders and in jsdom) — matching semantics are identical.\n if (anchor.elementId) {\n const escaped = anchor.elementId.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const matches = document.querySelectorAll(`[id=\"${escaped}\"]`);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"id\", true);\n }\n } catch {\n add(document.getElementById(anchor.elementId), \"id\", true);\n }\n }\n\n // CSS selector\n try {\n const matches = document.querySelectorAll(anchor.cssSelector);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"css\", true);\n }\n } catch {\n // Invalid selector — skip strategy\n }\n\n // XPath — snapshot (not FIRST_ORDERED_NODE) so later duplicates compete too\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n const count = Math.min(result.snapshotLength, MAX_PER_STRATEGY);\n for (let i = 0; i < count; i++) {\n const node = result.snapshotItem(i);\n if (node instanceof Element) add(node, \"xpath\", true);\n }\n } catch {\n // Invalid XPath — skip strategy\n }\n\n return pool;\n}\n\n/**\n * Same-tag sweep, prefiltered. Every same-tag element is considered (v1\n * stopped dead at the 300th in document order — a correct element past the\n * cap was unreachable), but full scoring only runs on the TOP_K best by a\n * cheap O(text-budget) prefilter: bigram-Dice text overlap plus O(1)\n * structural hints (stable-attribute hash, child count). The prefilter only\n * RANKS — it never eliminates on a threshold, so an imperfect cheap score\n * demotes a candidate but cannot drop the true match on its own.\n */\nfunction sweepScanCandidates(signals: AnchorSignals, pool: Map<Element, ResolutionStrategy>): Element[] {\n const tag = signals.tag.toLowerCase();\n if (!tag) return [];\n let candidates: NodeListOf<Element>;\n try {\n candidates = document.querySelectorAll(tag);\n } catch {\n return [];\n }\n\n // Parse only well-formed 3-part fingerprints (mirrors scoreFingerprint).\n // `Number(\"\")` is 0, not NaN — an empty fingerprint would otherwise grant a\n // phantom child-count-0 bonus that biases top-K toward childless decoys.\n const storedFp = signals.fingerprint.split(\":\");\n const storedChildCount = storedFp.length === 3 ? Number(storedFp[0]) : Number.NaN;\n const storedAttrHash = storedFp.length === 3 ? (storedFp[2] ?? \"\") : \"\";\n\n const limit = Math.min(candidates.length, SCAN_HARD_CAP);\n const ranked: { element: Element; cheap: number }[] = [];\n\n for (let i = 0; i < limit; i++) {\n const el = candidates[i];\n if (!el || pool.has(el)) continue; // already scored under a selector strategy\n\n let cheap = 0;\n if (signals.snippetBigramTotal > 0) {\n // collapseWhitespace, not full normalizeText: NFC on every candidate is\n // the prefilter's dominant hidden cost; survivors get re-normalized in\n // full scoring anyway.\n const text = collapseWhitespace(boundedText(el, CANDIDATE_TEXT_CAP));\n const charDice = diceAgainst(signals.snippetBigrams, signals.snippetBigramTotal, text);\n // Character bigrams are order-blind: on shared-vocabulary pages (card\n // grids) every candidate scores alike. Word-pair shingles restore order\n // sensitivity; when the snippet has no pairs (single word, no-space\n // scripts) the whole weight stays on character bigrams. A shared word\n // pair implies shared bigrams, so charDice 0 makes the word pass moot.\n if (signals.snippetWordPairTotal > 0) {\n const wordDice =\n charDice > 0 ? wordPairDiceAgainst(signals.snippetWordPairs, signals.snippetWordPairTotal, text) : 0;\n cheap += 0.6 * (0.5 * charDice + 0.5 * wordDice);\n } else {\n cheap += 0.6 * charDice;\n }\n }\n if (storedAttrHash && attrHash(el) === storedAttrHash) cheap += 0.25;\n if (!Number.isNaN(storedChildCount)) {\n const diff = Math.abs(el.children.length - storedChildCount);\n if (diff === 0) cheap += 0.15;\n else if (diff <= 2) cheap += 0.07;\n }\n\n ranked.push({ element: el, cheap });\n }\n\n // Stable sort: ties keep document order, mirroring v1's document-order bias.\n ranked.sort((a, b) => b.cheap - a.cheap);\n return ranked.slice(0, SCAN_TOP_K).map((r) => r.element);\n}\n\nfunction scoreOne(element: Element, strategy: ResolutionStrategy, signals: AnchorSignals): ScoredCandidate | null {\n const scores = verificationScore(element, signals);\n const visibility = visibilityFactor(classifyVisibility(element));\n if (scores === null) {\n // No verifiable signal stored: the selector match is the only evidence.\n // A scan candidate with nothing to verify against is meaningless, though.\n if (strategy === \"scan\") return null;\n return {\n element,\n strategy,\n verification: NEUTRAL_VERIFICATION,\n strongest: NEUTRAL_VERIFICATION,\n visibility,\n final: STRATEGY_PRIORS[strategy] * NEUTRAL_VERIFICATION * visibility,\n unverified: true,\n };\n }\n\n return {\n element,\n strategy,\n verification: scores.blend,\n strongest: scores.strongest,\n signals: scores,\n visibility,\n final: STRATEGY_PRIORS[strategy] * scores.blend * visibility,\n };\n}\n\n/**\n * Whether a candidate has enough corroboration to be returned at all.\n * Selector strategies accept on the strongest SINGLE signal clearing its\n * floor — a drifted fingerprint must not veto an exact text match (or vice\n * versa: an icon button's intact fingerprint carries it when there is no\n * text). Scan keeps its blend floor: without selector evidence, agreement\n * across signals is the whole case for the match.\n */\nfunction isAcceptable(c: ScoredCandidate): boolean {\n if (c.strategy === \"scan\") return c.verification >= ACCEPT_SCAN;\n if (c.unverified || !c.signals) return true;\n const s = c.signals;\n // No stored text: ranking-only (see constant doc — v1 parity for legacy\n // textless anchors; drift shows up as low confidence, not orphaning).\n if (s.text === undefined) return true;\n if (s.text >= TEXT_FLOOR) return true;\n // Text present but refuted — accept only on strong structural agreement.\n return (\n (s.fingerprint ?? 0) >= STRONG_STRUCT || (s.context ?? 0) >= STRONG_STRUCT || (s.neighbor ?? 0) >= STRONG_STRUCT\n );\n}\n\n/**\n * Multi-signal verification, 0–1. Dynamic weighting: only signals the stored\n * anchor actually has contribute, then the sum is normalized — anchors\n * captured with fewer signals compete on the signals they do have.\n * Returns null when the anchor stores no verifiable signal at all.\n *\n * All text comparisons run on `normalizeText`-processed strings on BOTH\n * sides, so SSR/CSR whitespace drift and re-indented markup no longer\n * penalize otherwise-identical text (#173) — stored snippets are untouched\n * and stay backward compatible.\n */\nfunction verificationScore(candidate: Element, s: AnchorSignals): SignalScores | null {\n let score = 0;\n let totalWeight = 0;\n const out: SignalScores = { blend: 0, strongest: 0 };\n\n // --- Text snippet (weight 40 — most reliable under reordering) ---\n if (s.snippet) {\n totalWeight += 40;\n const candidateText = normalizeText(boundedText(candidate, CANDIDATE_TEXT_CAP));\n out.text = fuzzyIncludes(candidateText, s.snippet, 0.5);\n score += out.text * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (s.fingerprint) {\n totalWeight += 20;\n out.fingerprint = scoreFingerprint(candidate, s.fingerprint);\n score += out.fingerprint * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (s.prefix || s.suffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (s.prefix) {\n const prevText = normalizeText(adjacentText(candidate, \"before\"));\n contextScore += prevText ? similarity(prevText, s.prefix) : 0;\n contextParts++;\n }\n\n if (s.suffix) {\n const nextText = normalizeText(adjacentText(candidate, \"after\"));\n contextScore += nextText ? similarity(nextText, s.suffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n out.context = contextScore / contextParts;\n score += out.context * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (s.neighbor) {\n totalWeight += 20;\n const candidateNeighbor = normalizeText(neighborText(candidate));\n out.neighbor = candidateNeighbor ? similarity(candidateNeighbor, s.neighbor) : 0;\n score += out.neighbor * 20;\n }\n\n if (totalWeight === 0) return null;\n out.blend = score / totalWeight;\n out.strongest = Math.max(out.text ?? 0, out.fingerprint ?? 0, out.context ?? 0, out.neighbor ?? 0);\n return out;\n}\n\n/**\n * Ancestor-decoy tie-break: a wrapper's text contains its child's text, so it\n * scores nearly as well — but anchoring to the wrapper corrupts the\n * percentage-based rect. Among candidates within AMBIGUITY_EPSILON of the\n * best that sit on the best's own descendant chain, prefer the innermost.\n * Unrelated near-ties keep the plain argmax (strategy priors already encode\n * the preference order there).\n */\nfunction disambiguate(sortedAccepted: ScoredCandidate[]): ScoredCandidate {\n const best = sortedAccepted[0] as ScoredCandidate; // non-empty by caller contract\n const contenders = sortedAccepted.filter(\n (c) => best.final - c.final <= AMBIGUITY_EPSILON && (c === best || best.element.contains(c.element)),\n );\n // Innermost = contained by every other contender that contains anything\n let winner = best;\n for (const c of contenders) {\n if (c !== winner && winner.element.contains(c.element)) winner = c;\n }\n return winner;\n}\n\nfunction confidenceOf(c: ScoredCandidate): number {\n if (c.strategy === \"scan\") {\n // v1 semantics: the scan's confidence IS its verification, hard-capped —\n // a scan is never fully certain.\n return Math.min(c.verification, STRATEGY_PRIORS.scan);\n }\n // Nothing was verifiable → the selector is all the evidence there is;\n // v1 semantics: trust it at full prior rather than inventing doubt.\n if (c.unverified) return STRATEGY_PRIORS[c.strategy];\n // Confidence follows the STRONGEST corroborating signal, not the blend:\n // `<h2 id=\"pricing\">Pricing</h2>` moved into a new wrapper still carries an\n // exact text match — the drifted fingerprint/neighbors around it must not\n // dash-flag a perfectly anchored marker. Absence of a signal stays neutral;\n // a present-but-refuted one still drags `strongest` down when it is all\n // there is. Full prior at STRONG_VERIFY keeps v1's exact values.\n return STRATEGY_PRIORS[c.strategy] * Math.min(1, c.strongest / STRONG_VERIFY);\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(\n anchor: AnchorData,\n rect: RectData,\n options?: ResolveOptions,\n): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor, options);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import { type AnchorData, type FeedbackResponse, isClosedStatus, type RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { classifyVisibility } from \"./dom/visibility.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n anchorKey: a.anchorKey ?? null,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): { top: number; left: number } {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n elements: HTMLElement[];\n baseTop: number;\n baseLeft: number;\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\n/** Back-off between full re-resolutions of an anchor that resolved hidden or\n * orphaned, on mutation ticks (resize bypasses it — see hiddenRecheckAt). */\nconst HIDDEN_RECHECK_MS = 3000;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n /** Whether a resize/mutation happened since the last reposition pass —\n * the only triggers that can flip an anchor's visibility (responsive\n * breakpoint, SPA re-render). Pure scroll ticks keep the fast path. */\n private pendingLayoutChange = false;\n /** Resize specifically — the breakpoint-flip event: it bypasses the\n * hidden-anchor re-resolution throttle below. */\n private pendingResize = false;\n /** Per-annotation back-off after a resolution concluded \"hidden\" or\n * \"orphaned\": mutation ticks recur every ~200ms on busy SPAs, and\n * re-resolving an annotation in a collapsed accordion each tick is\n * provably-redundant sweep work. Resize clears the back-off. */\n private hiddenRecheckAt = new Map<string, number>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n /** Last `openCount` broadcast via `markers:changed` (-1 = never emitted). */\n private lastOpenCount = -1;\n\n get count(): number {\n return this.entries.length;\n }\n\n get openCount(): number {\n let count = 0;\n for (const entry of this.entries) {\n // Anything not closed (open, in_progress) still needs attention.\n if (!isClosedStatus(entry.feedback.status)) count++;\n }\n return count;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly liveRegion: HTMLElement | null = null,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition(\"resize\");\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition(\"scroll\");\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant\n // changes. Filtering short-circuits at the first non-widget mutation, so\n // even large batches stop after one DOM walk.\n //\n // The filter is applied unconditionally — earlier versions had a >20-batch\n // fast-path that skipped filtering, but that lets reposition self-trigger\n // when `repositionAll` re-renders the pinned highlight (showHighlight\n // appends N elements to `this.container`); a host page churning lots of\n // DOM (infinite scroll) would then loop at the 200ms debounce interval.\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition(\"mutation\");\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters);\n }\n\n private scheduleReposition(cause: \"scroll\" | \"mutation\" | \"resize\" = \"mutation\"): void {\n // Record the cause even when a tick is already pending — the pending\n // pass must honor the strongest cause seen since it was scheduled.\n if (cause !== \"scroll\") this.pendingLayoutChange = true;\n if (cause === \"resize\") this.pendingResize = true;\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Only resize/mutation ticks re-check cached anchors' visibility: a\n // responsive breakpoint flip can leave the cached element display:none\n // while its twin became the rendered copy (#171) — but re-checking on\n // every scroll tick would turn a legitimately-hidden anchor (collapsed\n // accordion) into a full re-resolution per scroll event.\n const recheckVisibility = this.pendingLayoutChange;\n const resizeTick = this.pendingResize;\n this.pendingLayoutChange = false;\n this.pendingResize = false;\n // A resize is the responsive breakpoint flip — every hidden-anchor\n // back-off is void, the visible twin may exist right now.\n if (resizeTick) this.hiddenRecheckAt.clear();\n const now = Date.now();\n\n // Reposition ticks recur every ~200ms on mutation-heavy pages; several\n // drifted/hidden anchors must not each pay a full tag sweep per tick.\n // Budget-starved annotations simply retry on the next natural tick.\n const scanBudget = { remaining: 2, starved: false };\n\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n const backedOff = (this.hiddenRecheckAt.get(cacheKey) ?? 0) > now;\n const cacheUsable =\n cachedEl?.isConnected && (backedOff || !(recheckVisibility && classifyVisibility(cachedEl) === \"hidden\"));\n\n if (cachedEl && cacheUsable) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else if (backedOff) {\n // A recent full resolution concluded hidden/orphaned and the anchor\n // is gone from the cache — don't burn another sweep this tick.\n resolved = null;\n } else {\n scanBudget.starved = false;\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation), { scanBudget });\n if (scanBudget.starved) {\n // Selector-only answer under an exhausted budget — may be worse\n // than what the sweep would find; never cache it, retry next tick.\n } else {\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n if (!resolved || classifyVisibility(resolved.element) === \"hidden\") {\n this.hiddenRecheckAt.set(cacheKey, now + HIDDEN_RECHECK_MS);\n } else {\n this.hiddenRecheckAt.delete(cacheKey);\n }\n }\n }\n\n if (!resolved) {\n markerEl.style.display = \"none\";\n continue;\n }\n\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n for (const key of this.hiddenRecheckAt.keys()) {\n if (!validKeys.has(key)) this.hiddenRecheckAt.delete(key);\n }\n\n this.applyClusterPositions();\n\n // Re-render the pinned highlight rectangle so it tracks the layout after\n // resize / SPA mutation. Marker dots reposition above; without this,\n // the highlight rect keeps its old pixel position and visibly drifts\n // away from the underlying content.\n if (this.pinnedFeedback) {\n this.showHighlight(this.pinnedFeedback);\n }\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n /**\n * Emit `markers:changed` only when the open count actually moved.\n *\n * Mutations that re-render the same set (panel search keystrokes, filter\n * toggles, \"load more\") all call `render()` without changing the page's\n * open count — emitting unconditionally would rebuild the FAB badge DOM on\n * every keystroke. The `-1` sentinel guarantees the first render still\n * emits, even when the page has zero open feedbacks.\n */\n private emitMarkersChanged(): void {\n const openCount = this.openCount;\n if (openCount === this.lastOpenCount) return;\n this.lastOpenCount = openCount;\n this.bus.emit(\"markers:changed\", openCount);\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n // Announce the number of visible markers to assistive tech (WCAG 4.1.3).\n // Skip the announcement when the host page has not provided a live\n // region (tests, embedded use cases) and when no marker is visible to\n // avoid noisy \"0 markers\" updates on every navigation.\n if (this.liveRegion && this.entries.length > 0) {\n this.liveRegion.textContent = this.t(\"marker.count\").replace(\"{count}\", String(this.entries.length));\n }\n this.emitMarkersChanged();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n this.emitMarkersChanged();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], baseTop: 0, baseLeft: 0 };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n const marker = this.createMarker(index, feedback, pos);\n this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n this.container.appendChild(marker);\n entry.elements.push(marker);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n const allItems: { entry: MarkerEntry; elIdx: number }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n allItems.push({ entry, elIdx: i });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.entry;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.entry;\n const dist = Math.sqrt((a.baseLeft - b.baseLeft) ** 2 + (a.baseTop - b.baseTop) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(b);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: `\n position:absolute;top:-6px;right:-6px;\n min-width:16px;height:16px;padding:0 4px;\n border-radius:9999px;\n background:${this.colors.accent};color:#fff;\n font-size:10px;font-weight:700;\n display:flex;align-items:center;justify-content:center;\n border:1.5px solid #fff;\n pointer-events:none;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n line-height:1;\n `,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = isClosedStatus(feedback.status);\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = this.t(\"marker.approximate\").replace(\"{confidence}\", String(Math.round(confidence * 100)));\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n // Closed feedbacks (resolved, wont_fix) render as muted checkmark markers.\n const isResolved = isClosedStatus(feedback.status);\n\n const marker = el(\"div\", {\n style: `\n position:absolute;\n top:${pos.top}px;\n left:${pos.left}px;\n width:26px;height:26px;\n border-radius:50%;\n background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};\n border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};\n display:flex;align-items:center;justify-content:center;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:11px;font-weight:700;\n color:${isResolved ? \"#94a3b8\" : typeColor};\n cursor:pointer;pointer-events:auto;\n box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};\n transition:top 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.15s ease, box-shadow 0.15s ease;\n user-select:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = this.t(\"marker.aria\")\n .replace(\"{number}\", String(number))\n .replace(\"{type}\", getTypeLabel(feedback.type, this.t))\n .replace(\"{message}\", truncatedMessage);\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n // WCAG 1.4.13 — tooltip must be reachable via keyboard (focus), not only\n // hover. Mirror mouseenter/mouseleave behaviour for focus/blur so a sighted\n // keyboard user gets the same affordance as a mouse user.\n marker.addEventListener(\"focus\", () => {\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"blur\", () => {\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n /**\n * Scroll the annotation into view, pin its highlight, and pulse its marker.\n *\n * Powers the `deepLink` config option and the public\n * `instance.focusFeedback(id)` method. Returns `false` when no entry\n * matches — caller logs that case, the manager stays silent.\n *\n * Scrolling uses the marker element's current document position via\n * `scrollIntoView`, not the original `scrollX/scrollY` captured at\n * annotation time. That keeps the focus correct after layout changes\n * (responsive breakpoints, lazy-loaded content) because the marker has\n * already been re-positioned to track the live anchor.\n */\n focusFeedback(feedbackId: string): boolean {\n const entry = this.entries.find((e) => e.feedback.id === feedbackId);\n if (!entry) return false;\n const markerEl = entry.elements[0];\n if (markerEl) {\n markerEl.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n this.pinHighlight(entry.feedback);\n this.highlight(feedbackId);\n return true;\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: `\n position:absolute;\n top:${rect.top + window.scrollY}px;\n left:${rect.left + window.scrollX}px;\n width:${rect.width}px;height:${rect.height}px;\n border:2px solid ${typeColor};\n background:${typeColor}0c;\n border-radius:8px;\n pointer-events:none;z-index:-1;\n opacity:0;\n box-shadow:0 0 16px ${typeColor}20;\n transition:opacity ${HIGHLIGHT_FADE}ms ease;\n `,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n type FeedbackResponseList,\n flattenAnnotation,\n type SitepingStore,\n} from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const record = await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n urlPattern: payload.urlPattern ?? null,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n screenshotDataUrl: payload.screenshotDataUrl ?? null,\n screenshotRegion: payload.screenshotRegion ?? null,\n diagnostics: payload.diagnostics ?? null,\n });\n\n return toResponse(record);\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n statuses: options?.statuses,\n search: options?.search,\n url: options?.url,\n urlPattern: options?.urlPattern,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, {\n status: resolved ? \"resolved\" : \"open\",\n resolvedAt: resolved ? new Date() : null,\n });\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n urlPattern: record.urlPattern ?? null,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n screenshotUrl: record.screenshotUrl ?? null,\n screenshotRegion: record.screenshotRegion ?? null,\n diagnostics: record.diagnostics ?? null,\n };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n anchorKey: ann.anchorKey ?? null,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = `\n /* ---- Keyframes ---- */\n\n @keyframes sp-fab-in {\n from {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n to {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes sp-fab-glow {\n 0%, 100% { box-shadow: 0 4px 20px var(--sp-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.08); }\n 50% { box-shadow: 0 4px 28px var(--sp-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.1); }\n }\n\n @keyframes sp-marker-in {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 60% {\n transform: scale(1.2);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n }\n }\n\n @keyframes sp-pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 var(--sp-accent-glow);\n }\n 70% {\n box-shadow: 0 0 0 8px transparent;\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n @keyframes sp-flash-bg {\n 0% { background-color: var(--sp-accent-light); }\n 100% { background-color: transparent; }\n }\n\n @keyframes sp-slide-up {\n from {\n transform: translateY(8px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n @keyframes sp-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes sp-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n /* ---- Animation classes ---- */\n\n .sp-anim-fab-in {\n animation: sp-fab-in 0.5s ${SPRING_LINEAR} both;\n }\n\n .sp-anim-marker-in {\n animation: sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;\n }\n\n .sp-anim-pulse {\n animation: sp-pulse-ring 0.7s ease-out;\n }\n\n .sp-anim-flash {\n animation: sp-flash-bg 0.5s ${EASE_OUT_QUART};\n }\n\n .sp-anim-slide-up {\n animation: sp-slide-up 0.3s ${EASE_OUT_EXPO} both;\n }\n\n .sp-anim-fade-in {\n animation: sp-fade-in 0.2s ease-out both;\n }\n\n /* ---- Transition utilities ---- */\n\n .sp-panel {\n transform: translateX(110%);\n transition: transform 0.4s ${EASE_OUT_EXPO};\n }\n\n .sp-panel.sp-panel--open {\n transform: translateX(0);\n }\n\n .sp-radial-item {\n opacity: 0;\n pointer-events: none;\n transform: translate(0, 0) scale(0.8);\n transition:\n transform 0.35s ${SPRING_OVERSHOOT},\n opacity 0.2s ease,\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n }\n\n .sp-radial-item.sp-radial-item--open {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Stagger delay via CSS custom property --sp-i */\n .sp-radial-item {\n transition-delay: calc(var(--sp-i, 0) * 50ms);\n }\n\n /* ---- Card stagger animation ---- */\n\n @keyframes sp-card-in {\n from {\n transform: translateY(12px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n .sp-card {\n animation: sp-card-in 0.35s ${EASE_OUT_EXPO} both;\n animation-delay: calc(var(--sp-card-i, 0) * 40ms);\n }\n\n /* ---- Loading spinner ---- */\n\n @keyframes sp-spin {\n to { transform: rotate(360deg); }\n }\n\n .sp-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--sp-border);\n border-top-color: var(--sp-accent);\n border-radius: 50%;\n animation: sp-spin 0.6s linear infinite;\n }\n\n /* ---- Badge bounce ---- */\n\n @keyframes sp-badge-in {\n 0% { transform: scale(0); }\n 60% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n }\n\n .sp-fab-badge {\n animation: sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n\n`;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return `\n :host {\n all: initial;\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n font-family: var(--sp-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--sp-text);\n /* Match native sub-controls (autofill, scrollbars, etc.) to the resolved theme */\n color-scheme: ${colors.bg === \"#ffffff\" ? \"light\" : \"dark\"};\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n ${cssVariables(colors)}\n\n /* Identity modal — theme-aware backdrop + panel */\n --sp-identity-bg: ${colors.glassBgHeavy};\n --sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ============================\n Focus visible (accessibility)\n ============================ */\n\n :focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: 2px;\n /* Double-ring against any background colour: the bg-coloured halo\n separates the accent ring from busy host-page surfaces. */\n box-shadow: 0 0 0 4px var(--sp-bg);\n }\n\n /* ============================\n FAB (Floating Action Button)\n ============================ */\n\n .sp-fab {\n position: fixed;\n width: 52px;\n height: 52px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-accent-gradient);\n color: #fff;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow:\n 0 4px 20px var(--sp-accent-glow),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.3s ease;\n outline: none;\n }\n\n .sp-fab:focus-visible {\n outline: 2px solid #fff;\n outline-offset: 3px;\n }\n\n .sp-fab:hover {\n transform: translateY(-2px) scale(1.05);\n box-shadow:\n 0 8px 28px var(--sp-accent-glow),\n 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .sp-fab:active {\n transform: translateY(0) scale(0.95);\n transition-duration: 0.1s;\n }\n\n .sp-fab--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-fab--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-fab svg {\n width: 22px;\n height: 22px;\n fill: currentColor;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n /* ---- FAB Badge ---- */\n\n .sp-fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: var(--sp-radius-full);\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid #fff;\n pointer-events: none;\n font-family: var(--sp-font);\n line-height: 1;\n }\n\n /* ============================\n Radial Menu\n ============================ */\n\n .sp-radial {\n position: fixed;\n pointer-events: none;\n width: 52px;\n height: 52px;\n }\n\n .sp-radial--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-radial--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-radial-item {\n position: absolute;\n left: 4px;\n bottom: 4px;\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n color: var(--sp-text);\n border: 1px solid var(--sp-glass-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--sp-shadow-md);\n font-size: 12px;\n font-weight: 600;\n }\n\n .sp-radial-item:hover,\n .sp-radial-item:focus-visible {\n background: rgba(255, 255, 255, 0.95);\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n box-shadow:\n var(--sp-shadow-md),\n 0 0 0 3px var(--sp-accent-light);\n outline: none;\n }\n\n .sp-radial-item svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n stroke: currentColor;\n fill: none;\n }\n\n .sp-radial-label {\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text);\n pointer-events: none;\n opacity: 0;\n padding: 4px 12px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n transform: translateX(4px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n\n .sp-radial-item:hover .sp-radial-label,\n .sp-radial-item:focus-visible .sp-radial-label {\n opacity: 1;\n transform: translateX(0);\n }\n\n /* ============================\n Panel (Side drawer)\n ============================ */\n\n .sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border-left: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n @media (max-width: 480px) {\n .sp-panel {\n width: 100vw;\n border-left: none;\n }\n }\n\n .sp-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: relative;\n z-index: 2;\n }\n\n .sp-panel-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-panel-close {\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n }\n\n .sp-panel-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-panel-close svg {\n width: 16px;\n height: 16px;\n }\n\n /* ============================\n Filters & Search\n ============================ */\n\n .sp-filters {\n padding: 16px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .sp-search-wrap {\n position: relative;\n margin-bottom: 12px;\n }\n\n .sp-search {\n width: 100%;\n height: 40px;\n padding: 0 12px 0 38px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 13px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-search::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-search:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--sp-text-tertiary);\n width: 16px;\n height: 16px;\n transition: color 0.2s ease;\n }\n\n .sp-search:focus ~ .sp-search-icon,\n .sp-search-wrap:focus-within .sp-search-icon {\n color: var(--sp-accent);\n }\n\n /* ============================\n Filter bar (type dropdown + status segmented)\n ============================ */\n\n .sp-filter-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n }\n\n /* ============================\n Type filter dropdown\n ============================ */\n\n .sp-filter-dropdown {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .sp-filter-dropdown-btn {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: var(--sp-glass-bg-heavy);\n\n display: inline-flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px 0 10px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-filter-dropdown-btn:hover {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--sp-chip-color) 14%, transparent);\n }\n\n .sp-filter-dropdown-btn--filtered {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-btn__icon svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-filter-dropdown-btn__label {\n display: inline-flex;\n align-items: baseline;\n gap: 6px;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sp-filter-dropdown-btn__prefix {\n color: var(--sp-text-tertiary);\n font-weight: 500;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .sp-filter-dropdown-btn__value {\n color: var(--sp-chip-color);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sp-filter-dropdown-btn__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-text-tertiary);\n transition: transform 0.18s ease, color 0.18s ease;\n }\n\n .sp-filter-dropdown-btn__chevron svg {\n width: 12px;\n height: 12px;\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron {\n transform: rotate(180deg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-filter-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-filter-menu-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .sp-filter-dropdown-option {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: transparent;\n\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: background 0.12s ease, color 0.12s ease;\n }\n\n .sp-filter-dropdown-option__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n flex-shrink: 0;\n border-radius: 6px;\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option__label {\n flex: 1;\n min-width: 0;\n }\n\n .sp-filter-dropdown-option__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__check svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-filter-dropdown-option--active {\n color: var(--sp-chip-color);\n font-weight: 600;\n }\n\n .sp-filter-dropdown-option--active:hover {\n background: var(--sp-chip-bg);\n }\n\n /* ============================\n Status segmented control\n ============================ */\n\n .sp-segmented {\n display: inline-flex;\n align-items: stretch;\n padding: 2px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n flex-shrink: 0;\n }\n\n .sp-segmented__btn {\n --sp-chip-color: var(--sp-text-tertiary);\n --sp-chip-bg: transparent;\n\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--sp-radius-full);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-segmented__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n transition: color 0.18s ease, transform 0.18s ease;\n }\n\n .sp-segmented__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-segmented__btn:hover {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn:hover .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--active {\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n font-weight: 600;\n box-shadow:\n inset 0 0 0 1px color-mix(in srgb, var(--sp-chip-color) 35%, transparent),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n\n .sp-segmented__btn--active .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: sp-segmented-pulse 2.4s ease-in-out infinite;\n }\n\n @keyframes sp-segmented-pulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(0.85); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sp-filter-dropdown-btn,\n .sp-filter-dropdown-btn__chevron,\n .sp-filter-dropdown-option,\n .sp-segmented__btn,\n .sp-segmented__icon {\n transition: none;\n }\n .sp-filter-dropdown-menu {\n animation: none;\n }\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: none;\n }\n }\n\n /* ============================\n Feedback Cards\n ============================ */\n\n .sp-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n }\n\n .sp-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-list::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-list::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n .sp-card {\n display: flex;\n padding: 14px 16px;\n margin-bottom: 6px;\n cursor: pointer;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xs);\n transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .sp-card:hover {\n background: var(--sp-bg);\n border-color: var(--sp-border);\n box-shadow: var(--sp-shadow-md);\n transform: translateY(-2px);\n }\n\n .sp-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 0.1s;\n }\n\n .sp-card-bar {\n width: 3px;\n border-radius: var(--sp-radius-full);\n margin-right: 14px;\n flex-shrink: 0;\n }\n\n .sp-card-body {\n flex: 1;\n min-width: 0;\n }\n\n .sp-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .sp-card-number {\n font-size: 12px;\n font-weight: 700;\n color: var(--sp-text-tertiary);\n font-variant-numeric: tabular-nums;\n }\n\n .sp-badge {\n padding: 2px 10px;\n border-radius: var(--sp-radius-full);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-card-date {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n margin-left: auto;\n }\n\n .sp-card-message {\n font-size: 13px;\n line-height: 1.5;\n color: var(--sp-text);\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .sp-card-message--expanded {\n -webkit-line-clamp: unset;\n }\n\n .sp-card-expand {\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-accent);\n cursor: pointer;\n background: none;\n border: none;\n padding: 4px 0;\n font-family: var(--sp-font);\n transition: opacity 0.15s ease;\n }\n\n .sp-card-expand:hover {\n opacity: 0.8;\n }\n\n .sp-card-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n }\n\n .sp-btn-resolve,\n .sp-btn-delete {\n padding: 8px 14px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-resolve svg,\n .sp-btn-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-btn-resolve:hover {\n border-color: #22c55e;\n color: #22c55e;\n background: rgba(34, 197, 94, 0.06);\n }\n\n .sp-btn-delete:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-resolve:disabled,\n .sp-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-spinner--sm {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Delete All (header) ---- */\n\n .sp-panel-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-btn-delete-all {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-delete-all svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-btn-delete-all:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-delete-all:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ---- Confirm Dialog ---- */\n\n .sp-confirm-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: ${Z_INDEX_MAX};\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n .sp-confirm-dialog {\n width: 340px;\n padding: 28px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n transform: translateY(8px) scale(0.97);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-confirm-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n margin-bottom: 8px;\n }\n\n .sp-confirm-message {\n font-size: 14px;\n color: var(--sp-text-secondary);\n line-height: 1.5;\n margin-bottom: 20px;\n }\n\n .sp-confirm-actions {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n }\n\n .sp-btn-danger {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: #ef4444;\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);\n }\n\n .sp-btn-danger:hover {\n background: #dc2626;\n box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);\n transform: translateY(-1px);\n }\n\n .sp-btn-danger:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-card--resolved {\n opacity: 0.5;\n }\n\n .sp-card--resolved .sp-card-message {\n text-decoration: line-through;\n text-decoration-color: var(--sp-text-tertiary);\n }\n\n /* ============================\n Loading State\n ============================ */\n\n .sp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n }\n\n /* ============================\n Identity Form\n ============================ */\n\n .sp-identity-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-input {\n width: 100%;\n height: 42px;\n padding: 0 14px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 14px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-input::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-input:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-input-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n margin-bottom: 6px;\n display: block;\n }\n\n /* ============================\n Buttons\n ============================ */\n\n .sp-btn-primary {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-btn-primary:hover {\n box-shadow: 0 4px 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-btn-primary:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-btn-primary:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n .sp-btn-ghost {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .sp-btn-ghost:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Empty State\n ============================ */\n\n .sp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 56px 24px;\n color: var(--sp-text-tertiary);\n text-align: center;\n gap: 8px;\n animation: sp-fade-in 0.3s ease-out both;\n }\n\n .sp-empty-text {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* ============================\n Load More\n ============================ */\n\n .sp-load-more-wrap {\n display: flex;\n justify-content: center;\n padding: 12px 0 4px;\n }\n\n .sp-btn-load-more {\n width: 100%;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-fab,\n .sp-radial-item,\n .sp-filter-dropdown-btn,\n .sp-segmented,\n .sp-segmented__btn,\n .sp-card,\n .sp-panel-close,\n .sp-search,\n .sp-btn-resolve,\n .sp-btn-delete,\n .sp-btn-delete-all,\n .sp-btn-primary,\n .sp-btn-ghost,\n .sp-btn-danger,\n .sp-card-expand,\n .sp-input,\n .sp-confirm-dialog {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-segmented__btn--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-filter-dropdown-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-filter-dropdown-option--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-fab:focus-visible,\n .sp-radial-item:focus-visible,\n .sp-filter-dropdown-btn:focus-visible,\n .sp-segmented__btn:focus-visible,\n .sp-filter-dropdown-option:focus-visible,\n .sp-panel-close:focus-visible,\n .sp-btn-resolve:focus-visible,\n .sp-btn-delete:focus-visible,\n .sp-btn-delete-all:focus-visible,\n .sp-btn-primary:focus-visible,\n .sp-btn-ghost:focus-visible,\n .sp-btn-danger:focus-visible,\n .sp-card-expand:focus-visible,\n .sp-input:focus-visible,\n .sp-search:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-panel {\n border: 2px solid ButtonText !important;\n }\n\n .sp-fab-badge {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-card-bar {\n background: ButtonText !important;\n }\n }\n\n ${ANIMATION_CSS}\n ${STATS_CSS}\n ${SORT_CSS}\n ${BULK_CSS}\n ${EXPORT_CSS}\n ${SHORTCUTS_CSS}\n ${DETAIL_CSS}\n `;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: `\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n max-width: 280px;\n padding: 12px 14px;\n border-radius: 14px;\n background: ${this.colors.glassBgHeavy};\n backdrop-filter: blur(24px);\n -webkit-backdrop-filter: blur(24px);\n border: 1px solid ${this.colors.glassBorder};\n box-shadow: 0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family: \"Inter\", system-ui, -apple-system, sans-serif;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(6px) scale(0.97);\n transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n visibility: hidden;\n -webkit-font-smoothing: antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: `\n position: absolute;\n width: 12px;\n height: 12px;\n background: ${this.colors.glassBgHeavy};\n border: 1px solid ${this.colors.glassBorder};\n transform: rotate(45deg);\n pointer-events: none;\n `,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelHide();\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: `\n padding:3px 10px;border-radius:9999px;\n font-size:11px;font-weight:600;\n color:${typeColor};background:${typeBg};\n letter-spacing:0.02em;\n `,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-right:1px solid ${this.colors.glassBorder};\n border-bottom:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n bottom:-6px;\n left:${arrowLeft}px;\n `;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-left:1px solid ${this.colors.glassBorder};\n border-top:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n top:-6px;\n left:${arrowLeft}px;\n `;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import type {\n DiagnosticsSnapshot,\n FeedbackPayload,\n PageScope,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEventListener,\n SitepingPublicEvents,\n} from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { MOBILE_BREAKPOINT, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { ConsoleBuffer } from \"./diagnostics/console-buffer.js\";\nimport { NetworkBuffer } from \"./diagnostics/network-buffer.js\";\nimport { EventBus, type PublicWidgetEvents, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createFocusTracker } from \"./focus-tracker.js\";\nimport { createT, loadLocale, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport type { Panel as PanelType } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\ninterface NormalisedDiagnostics {\n console: boolean;\n network: boolean;\n maxConsoleEntries: number;\n maxNetworkEntries: number;\n}\n\n/**\n * Resolve `SitepingConfig.captureDiagnostics` into a normalised shape.\n *\n * - `undefined` / `false` → everything off (no monkey-patching).\n * - `true` → console + network on with the defaults (50 / 20).\n * - object → per-channel toggles + optional custom sizes; missing booleans\n * default to `true` so users can pass `{ maxConsoleEntries: 200 }` and\n * still get both channels.\n */\nfunction normaliseDiagnosticsOptions(value: SitepingConfig[\"captureDiagnostics\"]): NormalisedDiagnostics {\n if (value === undefined || value === false) {\n return { console: false, network: false, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n if (value === true) {\n return { console: true, network: true, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n return {\n console: value.console !== false,\n network: value.network !== false,\n maxConsoleEntries: typeof value.maxConsoleEntries === \"number\" ? value.maxConsoleEntries : 50,\n maxNetworkEntries: typeof value.maxNetworkEntries === \"number\" ? value.maxNetworkEntries : 20,\n };\n}\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n focusFeedback: () => false,\n on: () => noop,\n off: noop,\n };\n}\n\n/**\n * Read NODE_ENV so that BOTH detection paths keep working:\n *\n * - The literal `process.env.NODE_ENV` member expression must survive into\n * our own dist — an identity define in tsup.config.ts stops esbuild's\n * browser-platform auto-define from folding it to `\"production\"` and\n * deleting the guard from the shipped bundle (issue #104).\n * - Shipping the literal lets the CONSUMER's bundler (webpack DefinePlugin,\n * Vite, esbuild) inline their real environment, so \"dev-only by default\"\n * works in bundled deployments even when no `process` global exists at\n * runtime. Computed-key dodges (`env[\"NODE_\" + \"ENV\"]`) would defeat that\n * inlining — do not reintroduce them.\n * - No `typeof process` gate: it would return before a consumer-inlined\n * constant is reached. Plain browsers without `process` (script-tag usage)\n * land in the catch instead. Runtime environments with a real `process`\n * (Node/SSR, E2E's `globalThis.process = { env: { NODE_ENV: 'test' } }`)\n * read it live.\n *\n * `scripts/verify-dist-guard.mjs` asserts these invariants against every\n * built bundle after each build.\n */\nfunction readNodeEnv(): string | undefined {\n try {\n return process.env.NODE_ENV;\n } catch {\n // No `process` global (plain browser) or restricted access — no signal\n return undefined;\n }\n}\n\ninterface NormalisedDeepLink {\n enabled: boolean;\n param: string;\n}\n\n/**\n * Resolve `SitepingConfig.deepLink` into a normalised shape.\n *\n * - `undefined` / `false` → disabled, no URL parsing.\n * - `true` → enabled with default param name `siteping`.\n * - object → enabled with optional custom param name. A bare empty object\n * `{}` falls back to the default param so callers never need to repeat it.\n */\nfunction normaliseDeepLinkOptions(value: SitepingConfig[\"deepLink\"]): NormalisedDeepLink {\n if (value === undefined || value === false) return { enabled: false, param: \"siteping\" };\n if (value === true) return { enabled: true, param: \"siteping\" };\n return { enabled: true, param: value.param ?? \"siteping\" };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Guard: no DOM, no widget — SSR frameworks (Next.js, Remix) may run the\n // init on the server. Deliberately NOT bypassed by forceShow: the widget\n // cannot render without a document.\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n config.onSkip?.(\"ssr\");\n return skippedInstance();\n }\n\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses). Uses readNodeEnv()\n // instead of the literal `process.env.NODE_ENV` — avoids both bundler\n // constant-folding (#104) and \"Critical dependency\" import.meta warnings\n // in Next.js webpack builds.\n if (!config.forceShow && readNodeEnv() === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: desktop only (viewport below the threshold = hidden). forceShow\n // bypasses this just like the production guard above; minViewportWidth lets\n // hosts tune (or disable, with 0) the threshold. Non-finite values (NaN from\n // an untyped script-tag consumer, Infinity) would silently break the `<`\n // comparison — fail back to the default instead. See issue #103.\n const minViewportWidth =\n typeof config.minViewportWidth === \"number\" && Number.isFinite(config.minViewportWidth)\n ? config.minViewportWidth\n : MOBILE_BREAKPOINT;\n if (!config.forceShow && window.innerWidth < minViewportWidth) {\n const reason = \"mobile\";\n console.info(\n `[siteping] Widget not loaded: viewport width < ${minViewportWidth}px (mobile not supported). Use forceShow: true or lower minViewportWidth to override.`,\n );\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n const locale = config.locale ?? \"en\";\n // Kick off the locale fetch immediately. English is bundled synchronously\n // and used as the fallback while the chunk is in flight. The launcher\n // awaits `localeReady` before rendering markers and re-localizes the FAB\n // and popup once the dictionary lands — both are mounted synchronously so\n // the widget is interactive immediately, but their labels start in the\n // English fallback until the chunk arrives.\n const localeReady: Promise<unknown> =\n locale === \"en\"\n ? Promise.resolve()\n : loadLocale(locale).catch(() => {\n /* fallback to English — already handled by createT */\n });\n const t = createT(locale);\n\n // Page scope — concrete URL + optional template, used to keep annotations\n // and panel results scoped to the current page. The widget calls this on\n // every initial markers load and on `instance.refresh()`, so SPA hosts can\n // re-fetch when the route changes.\n const scopeAnnotationsByUrl = config.scopeAnnotationsByUrl ?? true;\n const getScope = (): PageScope => {\n try {\n const result = config.getPageScope?.();\n if (result) return result;\n } catch (e) {\n log(\"getPageScope() threw, falling back to pathname:\", e);\n }\n return { url: window.location.pathname, urlPattern: null };\n };\n\n log(\"Initializing widget\", {\n projectName: config.projectName,\n theme: config.theme ?? \"light\",\n locale,\n scopeAnnotationsByUrl,\n });\n\n // Diagnostics — capture console + failed network at submit time when\n // `captureDiagnostics` is set. Buffers are installed eagerly so they\n // cover the entire session, then snapshotted in the annotation handler\n // below. We default to `false` even in dev to avoid surprise side\n // effects; users opt in via the config flag.\n const diagnosticsOpts = normaliseDiagnosticsOptions(config.captureDiagnostics);\n const consoleBuffer = diagnosticsOpts.console ? new ConsoleBuffer(diagnosticsOpts.maxConsoleEntries) : null;\n const networkBuffer = diagnosticsOpts.network ? new NetworkBuffer(diagnosticsOpts.maxNetworkEntries) : null;\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<PublicWidgetEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint).\n // The earlier guard guarantees one of `store` / `endpoint` is set; we\n // capture the chosen branch in a typed local so TypeScript narrows on\n // each side without resorting to a non-null assertion.\n const client: WidgetClient = (() => {\n if (config.store) return new StoreClient(config.store, config.projectName);\n const endpoint = config.endpoint;\n if (typeof endpoint !== \"string\" || endpoint.length === 0) {\n throw new Error(\"[siteping] internal invariant: endpoint must be a non-empty string in HTTP mode\");\n }\n return new ApiClient(endpoint, config.projectName, { apiKey: config.apiKey, headers: config.headers });\n })();\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Bridge internal events to public bus\n bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb));\n bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id));\n bus.on(\"open\", () => publicBus.emit(\"panel:open\"));\n bus.on(\"close\", () => publicBus.emit(\"panel:close\"));\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n const shadowMode = readNodeEnv() === \"test\" ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n (shadow as unknown as DocumentFragment).appendChild(style);\n }\n\n document.body.appendChild(host);\n\n // Track the last page element the user focused. FAB-launched annotation\n // moves focus into the shadow root before the annotator activates, so its\n // own activeElement capture only sees the 0x0 shadow host — the tracker\n // supplies the real keyboard (Enter) target instead. See issue #162.\n const focusTracker = createFocusTracker(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t, liveRegion);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n\n // Keep the FAB unread-count badge in sync with the visible markers. Marker\n // mutations (initial render, addFeedback after submit, panel-driven resolve /\n // delete / bulk-delete via re-render) all emit `markers:changed`, so a single\n // listener covers every path that can change the open count.\n bus.on(\"markers:changed\", (openCount) => fab.updateBadge(openCount));\n\n // Lazy-load Panel on first use (FAB click, instance.open, etc.) to keep the\n // initial bundle small. Panel + sub-modules are ~14 KB gzip on their own.\n // Memoize the import promise so subsequent calls reuse the same instance.\n let panelInstance: PanelType | null = null;\n let panelPromise: Promise<PanelType> | null = null;\n let destroyed = false;\n // Monotonic token guarding the launcher's own marker renders (initial load +\n // doRefresh). The panel guards its own renders with an AbortController; the\n // two direct launcher paths share this counter so the *last-issued* fetch\n // wins, never the last to resolve. Without it, an SPA nav burst (or an\n // initial load racing the first navigation) could render a stale page's\n // markers out of order, since markers.render() is a full clear-and-rebuild.\n let markerGeneration = 0;\n async function loadPanel(): Promise<PanelType | null> {\n if (destroyed) return null;\n if (panelInstance) return panelInstance;\n if (!panelPromise) {\n panelPromise = import(\"./panel.js\").then((mod) => {\n if (destroyed) return null as unknown as PanelType;\n panelInstance = new mod.Panel(shadow, colors, bus, client, config.projectName, markers, t, locale, {\n getScope,\n scopeAnnotationsByUrl,\n });\n return panelInstance;\n });\n }\n return panelPromise;\n }\n\n // Prefetch Panel in idle time so the first FAB click doesn't pay the\n // network/parse cost of the dynamic import. The chunk still ships lazily\n // (saves first-paint gzip), but it's already warming up by the time the\n // user is likely to click. Falls back to setTimeout in browsers without\n // requestIdleCallback (Safari before 17).\n if (typeof window !== \"undefined\") {\n const prefetch = () => {\n if (!destroyed) void loadPanel();\n };\n const ric = (window as { requestIdleCallback?: (cb: () => void) => void }).requestIdleCallback;\n if (typeof ric === \"function\") ric(prefetch);\n else setTimeout(prefetch, 200);\n }\n\n // The FAB emits `panel:toggle` on chat click — we intercept here so the\n // launcher (which holds the lazy loader) can drive the Panel lifecycle.\n // Panel itself also subscribes to `panel:toggle` once loaded; once the\n // dynamic import resolves we manually call `p.open()` because the missed\n // initial emit can't be replayed.\n let pendingOpen = false;\n const unsubToggle = bus.on(\"panel:toggle\", (open) => {\n if (panelInstance) return; // Real Panel already handles subsequent toggles\n if (open) {\n pendingOpen = true;\n loadPanel()\n .then((p) => {\n if (p && pendingOpen) p.open();\n pendingOpen = false;\n })\n .catch((err) => log(\"Failed to lazy-load panel:\", err));\n } else {\n pendingOpen = false;\n }\n });\n\n const annotator = new Annotator(colors, bus, t, config.enableScreenshot ?? false, () =>\n focusTracker.getLastPageFocus(),\n );\n\n let onContextMenu: ((e: MouseEvent) => void) | null = null;\n if (config.enableRightClickComment) {\n onContextMenu = (e: MouseEvent) => {\n // Respect host pages that run their own custom context menus (grids,\n // editors). Element-level handlers fire before this document-level\n // listener, so if they called preventDefault() we yield.\n if (e.defaultPrevented) return;\n // Modifier-key escape hatch: Shift/Ctrl/Alt/Meta → native menu.\n if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return;\n // Exclude SitePing's own UI — right-clicking the FAB, panel, markers,\n // popup, or overlay must not hijack the event. composedPath() reaches\n // into the closed shadow root so all retargeted events are caught.\n const path = e.composedPath();\n if (\n path.some(\n (n) =>\n n === host ||\n (n instanceof Element && (n.hasAttribute(\"data-siteping-ignore\") || n.id === \"siteping-markers\")),\n )\n )\n return;\n // Don't swallow the event while the annotator is already active (e.g.\n // the user right-clicks to paste in the popup textarea). Fall through\n // to the native menu instead of silently consuming the event.\n if (annotator.isBusy) return;\n e.preventDefault();\n void annotator\n .startInstantAnnotation(e.clientX, e.clientY)\n .catch((err) => log(\"right-click annotation failed\", err));\n };\n document.addEventListener(\"contextmenu\", onContextMenu);\n }\n\n // Once the locale dictionary lands, swap the FAB + popup labels from the\n // English fallback to the configured language. `t` already resolves to the\n // loaded dictionary at call time, so the markers list rendered below (which\n // calls `t` lazily) only needs to wait on `localeReady` once.\n if (locale !== \"en\") {\n localeReady.then(() => {\n if (destroyed) return;\n fab.refreshLabels();\n annotator.refreshLabels();\n });\n }\n\n // Handle annotation completion via event bus (not DOM events).\n // Concurrency guard: a second `annotation:complete` while one is still in\n // flight must not start a duplicate submission. The Annotator already\n // serializes its own submissions (no second annotation can be drawn while\n // the popup is open), so this is defence-in-depth — but it must not *silently*\n // drop the event: a dropped event would leave any waiting `runSubmission`\n // listener hung forever. We emit `submission:cancelled` so the waiter\n // unblocks as a benign abort (the popup restores, `onError` is not called).\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) {\n bus.emit(\"submission:cancelled\");\n return;\n }\n submitting = true;\n try {\n const { annotation, type, message, screenshotDataUrl, screenshotRegion } = data;\n\n // Ensure identity — config wins (host-provided), then localStorage,\n // then prompt the user as a last resort. Host-provided identity is\n // not persisted: the host stays the source of truth on every render.\n let identity = config.identity ?? getIdentity();\n if (!identity) {\n identity = await promptIdentity(shadow, t);\n if (!identity) {\n // User cancelled the identity prompt. Emit `submission:cancelled`\n // (not `feedback:error`) so the popup's pending submit handler\n // unblocks and restores the form — cancelling a prompt is a benign\n // user action, so `config.onError` must not fire for it.\n bus.emit(\"submission:cancelled\");\n return;\n }\n saveIdentity(identity);\n }\n\n // crypto.randomUUID() throws in non-secure contexts (plain HTTP)\n const clientId = (() => {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n })();\n\n // Use scope.url as the single source of truth — same identifier the\n // panel filter and marker filter use. If we stored full URLs here while\n // filtering by pathname, freshly-created feedbacks would never match\n // their own scope filter and would vanish from the UI immediately.\n // Default scope.url is `window.location.pathname` (no query string,\n // so token/key/secret query params can't leak by construction). Hosts\n // that need origin or query in the identifier override `getPageScope`.\n const scope = getScope();\n\n // Snapshot the buffers right before submit so the captured slice\n // matches the moment the user clicked \"send\", not some earlier point.\n let diagnostics: DiagnosticsSnapshot | null = null;\n if (consoleBuffer || networkBuffer) {\n diagnostics = {\n console: consoleBuffer?.getEntries() ?? [],\n network: networkBuffer?.getEntries() ?? [],\n };\n }\n\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: scope.url,\n urlPattern: scope.urlPattern,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n screenshotDataUrl: screenshotDataUrl ?? null,\n screenshotRegion: screenshotRegion ?? null,\n diagnostics,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n // Compare against the scope captured before submit (route may have\n // changed during the network round-trip — re-reading scope here\n // would race with SPA navigation).\n if (!scopeAnnotationsByUrl || response.url === scope.url) {\n markers.addFeedback(response, markers.count + 1);\n }\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n // Only refresh the panel if it has been loaded — `refresh()` is a\n // no-op when the panel is closed, so skipping the dynamic import here\n // avoids loading 14 KB of code that would otherwise do nothing.\n if (panelInstance) await panelInstance.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load. We always pass the current page URL\n // when scopeAnnotationsByUrl is enabled so the server narrows results to the\n // current page — preventing annotations from one page accidentally rendering\n // on another (when CSS selectors happen to match unrelated elements).\n const initialScope = getScope();\n const initialOptions = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: initialScope.url } : { limit: PAGE_SIZE };\n const deepLinkOpts = normaliseDeepLinkOptions(config.deepLink);\n // Claim a generation for the initial load so a navigation that fires while\n // this fetch is in flight (doRefresh bumps the counter) supersedes it — the\n // old page's markers must never clobber the page the user navigated to.\n const initialLoadGeneration = ++markerGeneration;\n // Render markers only once both the feedbacks and the locale dictionary are\n // ready. Marker aria-labels are built via `t(...)` at render time — without\n // this `Promise.all`, a fast HTTP response could outrun a slow locale chunk\n // and freeze marker labels in the English fallback for non-English locales.\n Promise.all([client.getFeedbacks(config.projectName, initialOptions), localeReady])\n .then(([{ feedbacks }]) => {\n if (destroyed || markerGeneration !== initialLoadGeneration) return;\n // Defensive client-side filter — backend may not yet support the `url` query.\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === initialScope.url) : feedbacks;\n markers.render(visible);\n // Apply deeplink focus once markers exist. Failures here are\n // non-fatal — a malformed URL or an unknown ID just leaves the page\n // as the user found it, so log and move on.\n if (deepLinkOpts.enabled) {\n try {\n const focusId = new URLSearchParams(window.location.search).get(deepLinkOpts.param);\n if (focusId) {\n const matched = markers.focusFeedback(focusId);\n log(\n `deepLink ?${deepLinkOpts.param}=${focusId} ${matched ? \"focused\" : \"did not match a visible feedback\"}`,\n );\n }\n } catch (e) {\n log(\"deepLink parsing failed:\", e);\n }\n }\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint, config.identity ?? getIdentity(), {\n apiKey: config.apiKey,\n headers: config.headers,\n })\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n // Re-fetch feedbacks for the *current* scope and update the UI. Shared by the\n // public `instance.refresh()` and the SPA navigation watcher below.\n //\n // When the panel is open, its own `refresh()` already runs `loadFeedbacks()`\n // which re-renders markers — a second fetch here would race with it (the\n // loser overwrites the winner's markers, off by a generation). So we delegate\n // when open, and fetch markers ourselves when closed (the panel won't, but\n // SPA hosts still need the new page's markers after a route change).\n //\n // Returns the in-flight promise (rejecting on fetch failure) so callers can\n // react — `instance.refresh()` swallows it (the public API never rejects onto\n // the host), the navigation watcher uses it to re-arm its dedup on failure.\n const doRefresh = (): Promise<void> => {\n // Bump first, before the open/closed split, so switching to panel-driven\n // rendering also invalidates any closed-panel fetch still in flight.\n const generation = ++markerGeneration;\n if (panelInstance?.isCurrentlyOpen) {\n return panelInstance.refresh();\n }\n const scope = getScope();\n const opts = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: scope.url } : { limit: PAGE_SIZE };\n return client.getFeedbacks(config.projectName, opts).then(({ feedbacks }) => {\n // Drop the result if a newer refresh superseded us (out-of-order\n // resolution), the widget was torn down, or the panel opened mid-flight\n // and now owns marker rendering itself.\n if (destroyed || generation !== markerGeneration || panelInstance?.isCurrentlyOpen) return;\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n markers.render(visible);\n });\n };\n\n // SPA route-change watcher. The widget is normally mounted once (singleton)\n // inside a persistent layout — e.g. a Next.js App Router `layout.tsx`, which\n // does NOT remount on client-side navigation. Without this, init runs once and\n // the panel list + markers stay frozen on the page where the widget first\n // mounted. We patch the History API (SPA routers call pushState/replaceState\n // rather than triggering popstate) and listen for popstate/hashchange, then\n // re-fetch only when the scope key actually changes. This re-fetches data\n // only — it deliberately does NOT re-focus/re-scroll (deep-link focus stays\n // initial-load only; see `deepLink`). Opt out with `watchNavigation: false`.\n let teardownNavigation: (() => void) | null = null;\n if (config.watchNavigation !== false && typeof window !== \"undefined\" && typeof history !== \"undefined\") {\n const scopeKey = (s: PageScope): string => `${s.url}\\n${s.urlPattern ?? \"\"}`;\n let lastScopeKey = scopeKey(initialScope);\n const onLocationChange = (): void => {\n if (destroyed) return;\n const key = scopeKey(getScope());\n // Same scope (e.g. query-only or hash-only nav under the default pathname\n // scope) — nothing to re-fetch. Guards against pushState storms too.\n if (key === lastScopeKey) return;\n const prevKey = lastScopeKey;\n lastScopeKey = key;\n log(\"SPA navigation detected — refreshing feedbacks for new scope\");\n doRefresh().catch(() => {\n // The refresh failed (network error). Roll the dedup key back so a\n // later nav *back* to this same scope retries instead of being\n // silently suppressed — unless a newer navigation already moved on.\n if (lastScopeKey === key) lastScopeKey = prevKey;\n });\n };\n\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n // Call through to the original first so `location` is already updated by the\n // time onLocationChange() reads getScope().\n const patchedPushState: typeof history.pushState = function (this: History, ...args) {\n originalPushState.apply(this, args);\n onLocationChange();\n };\n const patchedReplaceState: typeof history.replaceState = function (this: History, ...args) {\n originalReplaceState.apply(this, args);\n onLocationChange();\n };\n history.pushState = patchedPushState;\n history.replaceState = patchedReplaceState;\n window.addEventListener(\"popstate\", onLocationChange);\n window.addEventListener(\"hashchange\", onLocationChange);\n\n teardownNavigation = () => {\n window.removeEventListener(\"popstate\", onLocationChange);\n window.removeEventListener(\"hashchange\", onLocationChange);\n // Restore only if nobody patched on top of us — otherwise we'd clobber\n // another library's History wrapper. If a library did wrap on top, our\n // patch stays in the chain (and keeps its closure alive), but it's inert:\n // `destroyed` is already true above, so onLocationChange() is a no-op.\n if (history.pushState === patchedPushState) history.pushState = originalPushState;\n if (history.replaceState === patchedReplaceState) history.replaceState = originalReplaceState;\n };\n }\n\n instance = {\n destroy: () => {\n log(\"Destroying widget\");\n if (onContextMenu) {\n document.removeEventListener(\"contextmenu\", onContextMenu);\n }\n destroyed = true;\n pendingOpen = false;\n teardownNavigation?.();\n focusTracker.destroy();\n unsubAnnotation();\n unsubToggle();\n fab.destroy();\n panelInstance?.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n // Restore the original console / fetch / XHR so the host page isn't\n // left with patched globals after the widget tears itself down.\n consoleBuffer?.dispose();\n networkBuffer?.dispose();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n instance = null;\n },\n open: () => {\n // Emit synchronously so consumers wired through `onOpen` / `panel:open`\n // see the open event immediately, even before the Panel module has\n // finished loading on the first call.\n bus.emit(\"panel:toggle\", true);\n },\n close: () => {\n if (panelInstance) {\n panelInstance.close();\n } else {\n // Cancel a pending open before the panel has loaded.\n pendingOpen = false;\n }\n },\n focusFeedback: (feedbackId: string) => {\n // Returns false when no entry matches — unknown ID, feedback filtered\n // out by `scopeAnnotationsByUrl`, or markers not yet loaded (the\n // initial getFeedbacks is async, and the widget exposes no public\n // \"markers ready\" event today). Hosts that race against initial load\n // can retry, or trigger focus from a user gesture instead.\n return markers.focusFeedback(feedbackId);\n },\n // Public API must never reject onto the host — swallow the promise.\n refresh: () => {\n void doRefresh().catch(() => {});\n },\n // `PublicWidgetEvents` is a structural alias of `SitepingPublicEvents`, so\n // these on/off forwarders compose without any runtime cast.\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) =>\n publicBus.on(event, listener),\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => {\n publicBus.off(event, listener);\n },\n };\n\n return instance;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n // Move the shadow host to the end of <body> so the identity prompt wins\n // the source-order tiebreak against the feedback popup. Both elements\n // already sit at `Z_INDEX_MAX` (max int32 — no \\\"higher\\\"), and since #114\n // the popup stays visible during submission, so it can be on screen at\n // the moment `promptIdentity` runs. The popup is appended to `document.body`\n // later than the host during init, which made it win when z-indices tied.\n // Re-appending an existing node just moves it; no remount, no listener\n // loss, no visual jitter when the popup isn't open. See issue #126.\n const host = shadowRoot.host;\n if (host.parentNode) host.parentNode.appendChild(host);\n\n const backdrop = document.createElement(\"div\");\n backdrop.style.cssText = `\n position:fixed;inset:0;\n background:var(--sp-identity-overlay);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n display:flex;align-items:center;justify-content:center;\n z-index:${Z_INDEX_MAX};\n opacity:0;transition:opacity 0.25s ease;\n `;\n\n const modal = document.createElement(\"div\");\n modal.style.cssText = `\n width:340px;padding:28px;border-radius:var(--sp-radius-xl);\n background:var(--sp-identity-bg);\n backdrop-filter:blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter:blur(var(--sp-blur-heavy));\n border:1px solid var(--sp-glass-border);\n box-shadow:0 16px 48px var(--sp-shadow), 0 8px 16px var(--sp-shadow);\n font-family:var(--sp-font, \"Inter\",system-ui,-apple-system,sans-serif);\n color:var(--sp-text);\n transform:translateY(12px) scale(0.97);\n transition:transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n -webkit-font-smoothing:antialiased;\n `;\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;justify-content:flex-end;margin-top:20px;\";\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n modal.style.transform = \"translateY(12px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n emailInput.style.borderColor = \"var(--sp-type-bug, #ef4444)\";\n return;\n }\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n modal.style.transform = \"translateY(0) scale(1)\";\n nameInput.focus();\n });\n });\n}\n","import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n FeedbackPayload,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingHeadersOption,\n SitepingInstance,\n SitepingPublicEvents,\n SitepingStore,\n} from \"@siteping/core\";\n\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n"]}
|