react-code-locator 0.2.9 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/esbuild.cjs +16 -16
- package/dist/esbuild.cjs.map +1 -1
- package/dist/esbuild.js +16 -16
- package/dist/esbuild.js.map +1 -1
- package/dist/index.cjs +20 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -20
- package/dist/index.js.map +1 -1
- package/dist/swc.cjs +16 -16
- package/dist/swc.cjs.map +1 -1
- package/dist/swc.js +16 -16
- package/dist/swc.js.map +1 -1
- package/dist/unplugin.cjs +20 -20
- package/dist/unplugin.cjs.map +1 -1
- package/dist/unplugin.js +20 -20
- package/dist/unplugin.js.map +1 -1
- package/dist/webpack.cjs +19 -19
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +19 -19
- package/dist/webpack.js.map +1 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var C=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var $=(t,e)=>{for(var n in e)C(t,n,{get:e[n],enumerable:!0})},
|
|
1
|
+
"use strict";var C=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var $=(t,e)=>{for(var n in e)C(t,n,{get:e[n],enumerable:!0})},j=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of T(e))!_.call(t,o)&&o!==n&&C(t,o,{get:()=>e[o],enumerable:!(r=F(e,o))||r.enumerable});return t};var D=t=>j(C({},"__esModule",{value:!0}),t);var G={};$(G,{enableReactComponentJump:()=>O,locateComponentSource:()=>E});module.exports=D(G);var g="__componentSourceLoc",L="$componentSourceLoc",w="react-code-locator.jsxSourceRegistry";function v(t){return t.replace(/\\/g,"/")}function K(t){return t.replace(/\/+$/,"")}function k(t){return v(t).split("/").filter(Boolean)}function z(t,e){let n=k(t),r=k(e),o=0;for(;o<n.length&&o<r.length&&n[o]===r[o];)o+=1;let s=new Array(Math.max(0,n.length-o)).fill(".."),u=r.slice(o),c=[...s,...u];return c.length>0?c.join("/"):"."}function N(t){return t?K(v(t)):""}function b(t){return t?t.match(/^(.*):\d+:\d+$/)?.[1]??null:null}function J(t,e){if(!t)return!1;let n=N(e),r=v(t);return n?r.startsWith(`${n}/`)||r===n?!0:!z(n,r).startsWith("../"):!r.startsWith("../")&&!r.startsWith("/")&&!/^[A-Za-z]:\//.test(r)}function f(t,e){let n=b(t);return J(n??void 0,e)}function W(t,e){return e==="none"?!0:e==="alt"?t.altKey:e==="meta"?t.metaKey:e==="ctrl"?t.ctrlKey:t.shiftKey}function I(t){return Object.keys(t).find(e=>e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))}function U(t){let e=t;for(;e;){let n=I(e);if(n)return e[n];e=e.parentElement}return null}function h(t){if(!t)return null;if(typeof t=="function"){let r=t[g];return typeof r=="string"?r:null}if(typeof t!="object")return null;let e=t,n=e[g]??e.type?.[g]??e.render?.[g];return typeof n=="string"?n:null}function P(t){if(t&&typeof t=="object"){let n=globalThis[Symbol.for(w)];if(n instanceof WeakMap){let r=n.get(t);if(typeof r=="string")return r}}let e=t?.[L];return typeof e=="string"?e:null}function V(t){let e=t;for(;e;){let n=h(e.type)??h(e.elementType);if(n)return n;e=e.return??null}return null}function X(t){let e=t?._debugSource;return e?.fileName&&typeof e.lineNumber=="number"?`${e.fileName.replace(/\\/g,"/")}:${e.lineNumber}:${e.columnNumber??1}`:null}function M(t,e){if(!e||!t)return t;let n=t.match(/^(.*):(\d+):(\d+)$/);if(!n)return t;let[,r,o,s]=n,u=r.replace(/\\/g,"/"),c=e.replace(/\\/g,"/").replace(/\/$/,"");return u.startsWith(c+"/")?`${u.slice(c.length+1)}:${o}:${s}`:t}function B(t,e){let n=t,r=[],o=[];for(;n;){let l=P(n.pendingProps)??P(n.memoizedProps)??X(n),d=M(l??"",e)||l;if(d){let p=b(d);p&&!r.some(x=>x.source===d)&&r.push({source:d,file:p})}let y=h(n.type)??h(n.elementType),S=M(y??"",e)||y;if(S){let p=b(S);p&&!o.some(x=>x.source===S)&&o.push({source:S,file:p})}n=n.return??null}let s=r[0]?.source??null,u=o.find(l=>f(l.source))?.file,c=null;if(u){let l=r.find(d=>d.file===u);if(l)c=l.source;else{let d=o.find(y=>y.file===u);d&&(c=d.source)}}let a=o.find(l=>!f(l.source))?.source??null,i=r.find(l=>!f(l.source))?.source??null,m=r.find(l=>f(l.source))?.source??null,R=c??m??o.find(l=>f(l.source))?.source??null;return{direct:s??R,screen:R,implementation:a??i??R}}function Y(t){return t==="direct"?"Direct JSX":t==="screen"?"Screen source":"Implementation source"}function A(t){if(typeof document>"u")return null;let e=document.createElement("div"),n=null,r="screen",o=null;e.setAttribute("data-react-code-locator","true"),Object.assign(e.style,{position:"fixed",right:"12px",bottom:"12px",zIndex:"2147483647",padding:"8px 10px",borderRadius:"8px",background:"rgba(17, 24, 39, 0.92)",color:"#fff",fontSize:"12px",lineHeight:"1.4",fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",boxShadow:"0 8px 30px rgba(0, 0, 0, 0.25)",pointerEvents:"auto",cursor:"pointer",maxWidth:"min(70vw, 720px)",wordBreak:"break-all",opacity:"0",transition:"opacity 120ms ease"});let s=(c,a)=>{e.textContent=c,e.style.background=a==="success"?"rgba(6, 95, 70, 0.92)":a==="error"?"rgba(153, 27, 27, 0.94)":"rgba(17, 24, 39, 0.92)",e.style.opacity="1",e.style.pointerEvents="auto",o&&clearTimeout(o),o=setTimeout(()=>{e.style.opacity="0",e.style.pointerEvents="none"},2e3)};e.addEventListener("click",async()=>{if(n)try{await navigator.clipboard.writeText(n),s("[react-code-locator] copied","success")}catch{s("[react-code-locator] copy failed","error")}}),s(`[react-code-locator] enabled (${t}+click, alt+1/2/3 to switch mode)`,"idle");let u=()=>{!e.isConnected&&document.body&&document.body.appendChild(e)};return document.body?u():document.addEventListener("DOMContentLoaded",u,{once:!0}),{setStatus(c,a="idle"){s(c,a)},setCopyValue(c){n=c},setMode(c){r=c,s(`[react-code-locator] ${Y(c)}`,"idle")},remove(){o&&clearTimeout(o),e.remove()}}}function E(t,e="screen",n){let r=t instanceof Element?t:t instanceof Node?t.parentElement:null,o=U(r);if(!o)return null;let s=B(o,n),u=s[e]??s.screen??s.direct??s.implementation;if(u)return{source:u,mode:e};let c=V(o);return c?{source:c,mode:e}:null}function O(t={}){if(process.env.NODE_ENV!=="development")return;let e=A(t.triggerKey??"shift"),n="screen",{triggerKey:r="shift",projectRoot:o,onLocate:s=i=>{console.log(`[react-code-locator] ${i.source}`),e?.setCopyValue(i.source),e?.setStatus(`[react-code-locator] ${i.source}`,"success")},onError:u=i=>{console.error("[react-code-locator]",i);let m=i instanceof Error?i.message:String(i);e?.setCopyValue(null),e?.setStatus(`[react-code-locator] ${m}`,"error")}}=t;console.log("[react-code-locator] enabled",{triggerKey:r});let c=i=>{if(i.altKey){if(i.code==="Digit1"){n="direct",e?.setMode(n),i.preventDefault();return}if(i.code==="Digit2"){n="screen",e?.setMode(n),i.preventDefault();return}i.code==="Digit3"&&(n="implementation",e?.setMode(n),i.preventDefault())}},a=i=>{if(!W(i,r))return;let m=E(i.target,n,o);if(!m){u(new Error("No React component source metadata found for clicked element."));return}i.preventDefault(),i.stopPropagation(),s(m)};return document.addEventListener("click",a,!0),document.addEventListener("keydown",c,!0),()=>{document.removeEventListener("click",a,!0),document.removeEventListener("keydown",c,!0),e?.remove()}}0&&(module.exports={enableReactComponentJump,locateComponentSource});
|
|
2
2
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/constants.ts","../src/sourceMetadata.ts","../src/runtime.ts"],"sourcesContent":["export { enableReactComponentJump, locateComponentSource } from \"./runtime\";\nexport type { LocatorMode, LocatorOptions, LocatorResult, TriggerKey } from \"./runtime\";\n","export const SOURCE_PROP = \"__componentSourceLoc\";\nexport const JSX_SOURCE_PROP = \"$componentSourceLoc\";\nexport const JSX_SOURCE_REGISTRY_SYMBOL = \"react-code-locator.jsxSourceRegistry\";\n","export type SourceLocation = {\n line: number;\n column: number;\n};\n\nfunction normalizeSlashes(value: string) {\n return value.replace(/\\\\/g, \"/\");\n}\n\nfunction trimTrailingSlash(value: string) {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction splitPathSegments(value: string) {\n return normalizeSlashes(value).split(\"/\").filter(Boolean);\n}\n\nfunction computeRelativePath(fromPath: string, toPath: string) {\n const fromSegments = splitPathSegments(fromPath);\n const toSegments = splitPathSegments(toPath);\n\n let sharedIndex = 0;\n while (\n sharedIndex < fromSegments.length &&\n sharedIndex < toSegments.length &&\n fromSegments[sharedIndex] === toSegments[sharedIndex]\n ) {\n sharedIndex += 1;\n }\n\n const upSegments = new Array(Math.max(0, fromSegments.length - sharedIndex)).fill(\"..\");\n const downSegments = toSegments.slice(sharedIndex);\n const relativeSegments = [...upSegments, ...downSegments];\n return relativeSegments.length > 0 ? relativeSegments.join(\"/\") : \".\";\n}\n\nexport function normalizeProjectRoot(projectRoot?: string) {\n if (projectRoot) {\n return trimTrailingSlash(normalizeSlashes(projectRoot));\n }\n return \"\";\n}\n\nexport function toRelativeSource(\n filename: string | undefined,\n loc: SourceLocation | null | undefined,\n projectRoot?: string,\n) {\n if (!filename || !loc) {\n return null;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n const relPath =\n root && normalizedFilename.startsWith(`${root}/`)\n ? normalizedFilename.slice(root.length + 1)\n : root\n ? computeRelativePath(root, normalizedFilename)\n : normalizedFilename;\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nexport function getSourceFile(source: string | null) {\n if (!source) {\n return null;\n }\n\n const match = source.match(/^(.*):\\d+:\\d+$/);\n return match?.[1] ?? null;\n}\n\nexport function isProjectLocalFile(filename: string | undefined, projectRoot?: string) {\n if (!filename) {\n return false;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n\n if (!root) {\n return (\n !normalizedFilename.startsWith(\"../\") &&\n !normalizedFilename.startsWith(\"/\") &&\n !/^[A-Za-z]:\\//.test(normalizedFilename)\n );\n }\n\n if (normalizedFilename.startsWith(`${root}/`) || normalizedFilename === root) {\n return true;\n }\n\n const relativePath = computeRelativePath(root, normalizedFilename);\n return !relativePath.startsWith(\"../\");\n}\n\nexport function isExternalToProjectRoot(filename: string | undefined, projectRoot?: string) {\n return !isProjectLocalFile(filename, projectRoot);\n}\n\nexport function isProjectLocalSource(source: string, projectRoot?: string) {\n const file = getSourceFile(source);\n return isProjectLocalFile(file ?? undefined, projectRoot);\n}\n","import {\n JSX_SOURCE_PROP,\n JSX_SOURCE_REGISTRY_SYMBOL,\n SOURCE_PROP,\n} from \"./constants\";\nimport { getSourceFile, isProjectLocalSource } from \"./sourceMetadata\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\nexport type LocatorMode = \"direct\" | \"screen\" | \"implementation\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\n _debugOwner?: ReactFiber | null;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: LocatorMode;\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n projectRoot?: string;\n};\n\ntype StatusOverlay = {\n setStatus: (message: string, tone?: \"idle\" | \"success\" | \"error\") => void;\n setCopyValue: (value: string | null) => void;\n setMode: (mode: LocatorMode) => void;\n remove: () => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n if (props && typeof props === \"object\") {\n const registry = (globalThis as Record<symbol, unknown>)[\n Symbol.for(JSX_SOURCE_REGISTRY_SYMBOL)\n ];\n if (registry instanceof WeakMap) {\n const intrinsicSource = registry.get(props as object);\n if (typeof intrinsicSource === \"string\") {\n return intrinsicSource;\n }\n }\n }\n\n const source = props?.[JSX_SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveComponentSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDirectDebugSource(fiber: ReactFiber | null) {\n const debugSource = fiber?._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n return null;\n}\n\nfunction normalizeSource(source: string, projectRoot: string | undefined): string {\n if (!projectRoot || !source) return source;\n const match = source.match(/^(.*):(\\d+):(\\d+)$/);\n if (!match) return source;\n const [, file, line, col] = match;\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const normalizedRoot = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n if (normalizedFile.startsWith(normalizedRoot + \"/\")) {\n return `${normalizedFile.slice(normalizedRoot.length + 1)}:${line}:${col}`;\n }\n return source;\n}\n\ntype SourceCandidate = {\n source: string;\n file: string;\n};\n\ntype ResolvedCandidates = {\n direct: string | null;\n screen: string | null;\n implementation: string | null;\n};\n\nfunction resolveSourceCandidates(fiber: ReactFiber | null, projectRoot?: string): ResolvedCandidates {\n let current = fiber;\n const jsxCandidates: SourceCandidate[] = [];\n const componentCandidates: SourceCandidate[] = [];\n\n while (current) {\n const rawJsxSource =\n getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps) ?? getDirectDebugSource(current);\n const jsxSource = normalizeSource(rawJsxSource ?? \"\", projectRoot) || rawJsxSource;\n if (jsxSource) {\n const file = getSourceFile(jsxSource);\n if (file && !jsxCandidates.some((candidate) => candidate.source === jsxSource)) {\n jsxCandidates.push({ source: jsxSource, file });\n }\n }\n\n const rawComponentSource = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n const componentSource = normalizeSource(rawComponentSource ?? \"\", projectRoot) || rawComponentSource;\n if (componentSource) {\n const file = getSourceFile(componentSource);\n if (file && !componentCandidates.some((candidate) => candidate.source === componentSource)) {\n componentCandidates.push({ source: componentSource, file });\n }\n }\n\n current = current.return ?? null;\n }\n\n const direct = jsxCandidates[0]?.source ?? null;\n const nearestProjectLocalComponentFile = componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.file;\n let screen: string | null = null;\n if (nearestProjectLocalComponentFile) {\n const matchingJsxCandidate = jsxCandidates.find((candidate) => candidate.file === nearestProjectLocalComponentFile);\n if (matchingJsxCandidate) {\n screen = matchingJsxCandidate.source;\n } else {\n const matchingComponentCandidate = componentCandidates.find(\n (candidate) => candidate.file === nearestProjectLocalComponentFile,\n );\n if (matchingComponentCandidate) {\n screen = matchingComponentCandidate.source;\n }\n }\n }\n\n const implementationComponentCandidate =\n componentCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n const implementationJsxCandidate =\n jsxCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n\n const projectLocalJsxCandidate = jsxCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n const screenFallback = screen ?? projectLocalJsxCandidate ?? componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n\n return {\n direct: direct ?? screenFallback,\n screen: screenFallback,\n implementation: implementationComponentCandidate ?? implementationJsxCandidate ?? screenFallback,\n };\n}\n\nfunction getModeDescription(mode: LocatorMode) {\n if (mode === \"direct\") {\n return \"Direct JSX\";\n }\n\n if (mode === \"screen\") {\n return \"Screen source\";\n }\n\n return \"Implementation source\";\n}\n\nfunction createStatusOverlay(triggerKey: TriggerKey): StatusOverlay | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const element = document.createElement(\"div\");\n let copyValue: string | null = null;\n let currentMode: LocatorMode = \"screen\";\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n element.setAttribute(\"data-react-code-locator\", \"true\");\n Object.assign(element.style, {\n position: \"fixed\",\n right: \"12px\",\n bottom: \"12px\",\n zIndex: \"2147483647\",\n padding: \"8px 10px\",\n borderRadius: \"8px\",\n background: \"rgba(17, 24, 39, 0.92)\",\n color: \"#fff\",\n fontSize: \"12px\",\n lineHeight: \"1.4\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n boxShadow: \"0 8px 30px rgba(0, 0, 0, 0.25)\",\n pointerEvents: \"auto\",\n cursor: \"pointer\",\n maxWidth: \"min(70vw, 720px)\",\n wordBreak: \"break-all\",\n opacity: \"0\",\n transition: \"opacity 120ms ease\",\n });\n\n const show = (message: string, tone: \"idle\" | \"success\" | \"error\") => {\n element.textContent = message;\n element.style.background =\n tone === \"success\"\n ? \"rgba(6, 95, 70, 0.92)\"\n : tone === \"error\"\n ? \"rgba(153, 27, 27, 0.94)\"\n : \"rgba(17, 24, 39, 0.92)\";\n element.style.opacity = \"1\";\n element.style.pointerEvents = \"auto\";\n\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n\n hideTimer = setTimeout(() => {\n element.style.opacity = \"0\";\n element.style.pointerEvents = \"none\";\n }, 2000);\n };\n\n element.addEventListener(\"click\", async () => {\n if (!copyValue) {\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyValue);\n show(`[react-code-locator] copied`, \"success\");\n } catch {\n show(`[react-code-locator] copy failed`, \"error\");\n }\n });\n\n show(`[react-code-locator] enabled (${triggerKey}+click, alt+1/2/3 to switch mode)`, \"idle\");\n\n const mount = () => {\n if (!element.isConnected && document.body) {\n document.body.appendChild(element);\n }\n };\n\n if (document.body) {\n mount();\n } else {\n document.addEventListener(\"DOMContentLoaded\", mount, { once: true });\n }\n\n return {\n setStatus(message, tone = \"idle\") {\n show(message, tone);\n },\n setCopyValue(value) {\n copyValue = value;\n },\n setMode(mode) {\n currentMode = mode;\n show(`[react-code-locator] ${getModeDescription(mode)}`, \"idle\");\n },\n remove() {\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n element.remove();\n },\n };\n}\n\nexport function locateComponentSource(target: EventTarget | null, mode: LocatorMode = \"screen\", projectRoot?: string): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const candidates = resolveSourceCandidates(fiber, projectRoot);\n const source = candidates[mode] ?? candidates.screen ?? candidates.direct ?? candidates.implementation;\n if (source) {\n return {\n source,\n mode,\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode,\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n if (process.env.NODE_ENV !== \"development\") return;\n const overlay = createStatusOverlay(options.triggerKey ?? \"shift\");\n let currentMode: LocatorMode = \"screen\";\n const {\n triggerKey = \"shift\",\n projectRoot,\n onLocate = (result) => {\n console.log(`[react-code-locator] ${result.source}`);\n overlay?.setCopyValue(result.source);\n overlay?.setStatus(`[react-code-locator] ${result.source}`, \"success\");\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", error);\n const message = error instanceof Error ? error.message : String(error);\n overlay?.setCopyValue(null);\n overlay?.setStatus(`[react-code-locator] ${message}`, \"error\");\n },\n } = options;\n\n console.log(\"[react-code-locator] enabled\", { triggerKey });\n\n const keyHandler = (event: KeyboardEvent) => {\n if (!event.altKey) {\n return;\n }\n\n if (event.code === \"Digit1\") {\n currentMode = \"direct\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit2\") {\n currentMode = \"screen\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit3\") {\n currentMode = \"implementation\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n }\n };\n\n const handler = (event: MouseEvent) => {\n console.log(\"[react-code-locator] click\", {\n triggerKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n target: event.target,\n });\n\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target, currentMode, projectRoot);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n document.addEventListener(\"keydown\", keyHandler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n document.removeEventListener(\"keydown\", keyHandler, true);\n overlay?.remove();\n };\n}\n"],"mappings":"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","names":["client_exports","__export","enableReactComponentJump","locateComponentSource","__toCommonJS","SOURCE_PROP","JSX_SOURCE_PROP","JSX_SOURCE_REGISTRY_SYMBOL","normalizeSlashes","value","trimTrailingSlash","splitPathSegments","computeRelativePath","fromPath","toPath","fromSegments","toSegments","sharedIndex","upSegments","downSegments","relativeSegments","normalizeProjectRoot","projectRoot","getSourceFile","source","isProjectLocalFile","filename","projectRoot","root","normalizeProjectRoot","normalizedFilename","normalizeSlashes","computeRelativePath","isProjectLocalSource","source","projectRoot","file","getSourceFile","isProjectLocalFile","isTriggerPressed","event","triggerKey","getReactFiberKey","element","key","getClosestReactFiber","target","current","fiberKey","getSourceFromType","type","source","SOURCE_PROP","record","getSourceFromProps","props","registry","JSX_SOURCE_REGISTRY_SYMBOL","intrinsicSource","JSX_SOURCE_PROP","resolveComponentSourceFromFiber","fiber","getDirectDebugSource","debugSource","normalizeSource","projectRoot","match","file","line","col","normalizedFile","normalizedRoot","resolveSourceCandidates","jsxCandidates","componentCandidates","rawJsxSource","jsxSource","getSourceFile","candidate","rawComponentSource","componentSource","direct","nearestProjectLocalComponentFile","isProjectLocalSource","screen","matchingJsxCandidate","matchingComponentCandidate","implementationComponentCandidate","implementationJsxCandidate","projectLocalJsxCandidate","screenFallback","getModeDescription","mode","createStatusOverlay","copyValue","currentMode","hideTimer","show","message","tone","mount","value","locateComponentSource","elementTarget","candidates","enableReactComponentJump","options","overlay","onLocate","result","onError","error","keyHandler","handler"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/constants.ts","../src/sourceMetadata.ts","../src/runtime.ts"],"sourcesContent":["export { enableReactComponentJump, locateComponentSource } from \"./runtime\";\nexport type { LocatorMode, LocatorOptions, LocatorResult, TriggerKey } from \"./runtime\";\n","export const SOURCE_PROP = \"__componentSourceLoc\";\nexport const JSX_SOURCE_PROP = \"$componentSourceLoc\";\nexport const JSX_SOURCE_REGISTRY_SYMBOL = \"react-code-locator.jsxSourceRegistry\";\n","export type SourceLocation = {\n line: number;\n column: number;\n};\n\nfunction normalizeSlashes(value: string) {\n return value.replace(/\\\\/g, \"/\");\n}\n\nfunction trimTrailingSlash(value: string) {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction splitPathSegments(value: string) {\n return normalizeSlashes(value).split(\"/\").filter(Boolean);\n}\n\nfunction computeRelativePath(fromPath: string, toPath: string) {\n const fromSegments = splitPathSegments(fromPath);\n const toSegments = splitPathSegments(toPath);\n\n let sharedIndex = 0;\n while (\n sharedIndex < fromSegments.length &&\n sharedIndex < toSegments.length &&\n fromSegments[sharedIndex] === toSegments[sharedIndex]\n ) {\n sharedIndex += 1;\n }\n\n const upSegments = new Array(Math.max(0, fromSegments.length - sharedIndex)).fill(\"..\");\n const downSegments = toSegments.slice(sharedIndex);\n const relativeSegments = [...upSegments, ...downSegments];\n return relativeSegments.length > 0 ? relativeSegments.join(\"/\") : \".\";\n}\n\nexport function normalizeProjectRoot(projectRoot?: string) {\n if (projectRoot) {\n return trimTrailingSlash(normalizeSlashes(projectRoot));\n }\n return \"\";\n}\n\nexport function toRelativeSource(\n filename: string | undefined,\n loc: SourceLocation | null | undefined,\n projectRoot?: string,\n) {\n if (!filename || !loc) {\n return null;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n const relPath =\n root && normalizedFilename.startsWith(`${root}/`)\n ? normalizedFilename.slice(root.length + 1)\n : root\n ? computeRelativePath(root, normalizedFilename)\n : normalizedFilename;\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nexport function getSourceFile(source: string | null) {\n if (!source) {\n return null;\n }\n\n const match = source.match(/^(.*):\\d+:\\d+$/);\n return match?.[1] ?? null;\n}\n\nexport function isProjectLocalFile(filename: string | undefined, projectRoot?: string) {\n if (!filename) {\n return false;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n\n if (!root) {\n return (\n !normalizedFilename.startsWith(\"../\") &&\n !normalizedFilename.startsWith(\"/\") &&\n !/^[A-Za-z]:\\//.test(normalizedFilename)\n );\n }\n\n if (normalizedFilename.startsWith(`${root}/`) || normalizedFilename === root) {\n return true;\n }\n\n const relativePath = computeRelativePath(root, normalizedFilename);\n return !relativePath.startsWith(\"../\");\n}\n\nexport function isExternalToProjectRoot(filename: string | undefined, projectRoot?: string) {\n return !isProjectLocalFile(filename, projectRoot);\n}\n\nexport function isProjectLocalSource(source: string, projectRoot?: string) {\n const file = getSourceFile(source);\n return isProjectLocalFile(file ?? undefined, projectRoot);\n}\n","import {\n JSX_SOURCE_PROP,\n JSX_SOURCE_REGISTRY_SYMBOL,\n SOURCE_PROP,\n} from \"./constants\";\nimport { getSourceFile, isProjectLocalSource } from \"./sourceMetadata\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\nexport type LocatorMode = \"direct\" | \"screen\" | \"implementation\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\n _debugOwner?: ReactFiber | null;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: LocatorMode;\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n projectRoot?: string;\n};\n\ntype StatusOverlay = {\n setStatus: (message: string, tone?: \"idle\" | \"success\" | \"error\") => void;\n setCopyValue: (value: string | null) => void;\n setMode: (mode: LocatorMode) => void;\n remove: () => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n if (props && typeof props === \"object\") {\n const registry = (globalThis as Record<symbol, unknown>)[\n Symbol.for(JSX_SOURCE_REGISTRY_SYMBOL)\n ];\n if (registry instanceof WeakMap) {\n const intrinsicSource = registry.get(props as object);\n if (typeof intrinsicSource === \"string\") {\n return intrinsicSource;\n }\n }\n }\n\n const source = props?.[JSX_SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveComponentSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDirectDebugSource(fiber: ReactFiber | null) {\n const debugSource = fiber?._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n return null;\n}\n\nfunction normalizeSource(source: string, projectRoot: string | undefined): string {\n if (!projectRoot || !source) return source;\n const match = source.match(/^(.*):(\\d+):(\\d+)$/);\n if (!match) return source;\n const [, file, line, col] = match;\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const normalizedRoot = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n if (normalizedFile.startsWith(normalizedRoot + \"/\")) {\n return `${normalizedFile.slice(normalizedRoot.length + 1)}:${line}:${col}`;\n }\n return source;\n}\n\ntype SourceCandidate = {\n source: string;\n file: string;\n};\n\ntype ResolvedCandidates = {\n direct: string | null;\n screen: string | null;\n implementation: string | null;\n};\n\nfunction resolveSourceCandidates(fiber: ReactFiber | null, projectRoot?: string): ResolvedCandidates {\n let current = fiber;\n const jsxCandidates: SourceCandidate[] = [];\n const componentCandidates: SourceCandidate[] = [];\n\n while (current) {\n const rawJsxSource =\n getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps) ?? getDirectDebugSource(current);\n const jsxSource = normalizeSource(rawJsxSource ?? \"\", projectRoot) || rawJsxSource;\n if (jsxSource) {\n const file = getSourceFile(jsxSource);\n if (file && !jsxCandidates.some((candidate) => candidate.source === jsxSource)) {\n jsxCandidates.push({ source: jsxSource, file });\n }\n }\n\n const rawComponentSource = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n const componentSource = normalizeSource(rawComponentSource ?? \"\", projectRoot) || rawComponentSource;\n if (componentSource) {\n const file = getSourceFile(componentSource);\n if (file && !componentCandidates.some((candidate) => candidate.source === componentSource)) {\n componentCandidates.push({ source: componentSource, file });\n }\n }\n\n current = current.return ?? null;\n }\n\n const direct = jsxCandidates[0]?.source ?? null;\n const nearestProjectLocalComponentFile = componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.file;\n let screen: string | null = null;\n if (nearestProjectLocalComponentFile) {\n const matchingJsxCandidate = jsxCandidates.find((candidate) => candidate.file === nearestProjectLocalComponentFile);\n if (matchingJsxCandidate) {\n screen = matchingJsxCandidate.source;\n } else {\n const matchingComponentCandidate = componentCandidates.find(\n (candidate) => candidate.file === nearestProjectLocalComponentFile,\n );\n if (matchingComponentCandidate) {\n screen = matchingComponentCandidate.source;\n }\n }\n }\n\n const implementationComponentCandidate =\n componentCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n const implementationJsxCandidate =\n jsxCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n\n const projectLocalJsxCandidate = jsxCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n const screenFallback = screen ?? projectLocalJsxCandidate ?? componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n\n return {\n direct: direct ?? screenFallback,\n screen: screenFallback,\n implementation: implementationComponentCandidate ?? implementationJsxCandidate ?? screenFallback,\n };\n}\n\nfunction getModeDescription(mode: LocatorMode) {\n if (mode === \"direct\") {\n return \"Direct JSX\";\n }\n\n if (mode === \"screen\") {\n return \"Screen source\";\n }\n\n return \"Implementation source\";\n}\n\nfunction createStatusOverlay(triggerKey: TriggerKey): StatusOverlay | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const element = document.createElement(\"div\");\n let copyValue: string | null = null;\n let currentMode: LocatorMode = \"screen\";\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n element.setAttribute(\"data-react-code-locator\", \"true\");\n Object.assign(element.style, {\n position: \"fixed\",\n right: \"12px\",\n bottom: \"12px\",\n zIndex: \"2147483647\",\n padding: \"8px 10px\",\n borderRadius: \"8px\",\n background: \"rgba(17, 24, 39, 0.92)\",\n color: \"#fff\",\n fontSize: \"12px\",\n lineHeight: \"1.4\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n boxShadow: \"0 8px 30px rgba(0, 0, 0, 0.25)\",\n pointerEvents: \"auto\",\n cursor: \"pointer\",\n maxWidth: \"min(70vw, 720px)\",\n wordBreak: \"break-all\",\n opacity: \"0\",\n transition: \"opacity 120ms ease\",\n });\n\n const show = (message: string, tone: \"idle\" | \"success\" | \"error\") => {\n element.textContent = message;\n element.style.background =\n tone === \"success\"\n ? \"rgba(6, 95, 70, 0.92)\"\n : tone === \"error\"\n ? \"rgba(153, 27, 27, 0.94)\"\n : \"rgba(17, 24, 39, 0.92)\";\n element.style.opacity = \"1\";\n element.style.pointerEvents = \"auto\";\n\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n\n hideTimer = setTimeout(() => {\n element.style.opacity = \"0\";\n element.style.pointerEvents = \"none\";\n }, 2000);\n };\n\n element.addEventListener(\"click\", async () => {\n if (!copyValue) {\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyValue);\n show(`[react-code-locator] copied`, \"success\");\n } catch {\n show(`[react-code-locator] copy failed`, \"error\");\n }\n });\n\n show(`[react-code-locator] enabled (${triggerKey}+click, alt+1/2/3 to switch mode)`, \"idle\");\n\n const mount = () => {\n if (!element.isConnected && document.body) {\n document.body.appendChild(element);\n }\n };\n\n if (document.body) {\n mount();\n } else {\n document.addEventListener(\"DOMContentLoaded\", mount, { once: true });\n }\n\n return {\n setStatus(message, tone = \"idle\") {\n show(message, tone);\n },\n setCopyValue(value) {\n copyValue = value;\n },\n setMode(mode) {\n currentMode = mode;\n show(`[react-code-locator] ${getModeDescription(mode)}`, \"idle\");\n },\n remove() {\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n element.remove();\n },\n };\n}\n\nexport function locateComponentSource(target: EventTarget | null, mode: LocatorMode = \"screen\", projectRoot?: string): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const candidates = resolveSourceCandidates(fiber, projectRoot);\n const source = candidates[mode] ?? candidates.screen ?? candidates.direct ?? candidates.implementation;\n if (source) {\n return {\n source,\n mode,\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode,\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n if (process.env.NODE_ENV !== \"development\") return;\n const overlay = createStatusOverlay(options.triggerKey ?? \"shift\");\n let currentMode: LocatorMode = \"screen\";\n const {\n triggerKey = \"shift\",\n projectRoot,\n onLocate = (result) => {\n console.log(`[react-code-locator] ${result.source}`);\n overlay?.setCopyValue(result.source);\n overlay?.setStatus(`[react-code-locator] ${result.source}`, \"success\");\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", error);\n const message = error instanceof Error ? error.message : String(error);\n overlay?.setCopyValue(null);\n overlay?.setStatus(`[react-code-locator] ${message}`, \"error\");\n },\n } = options;\n\n console.log(\"[react-code-locator] enabled\", { triggerKey });\n\n const keyHandler = (event: KeyboardEvent) => {\n if (!event.altKey) {\n return;\n }\n\n if (event.code === \"Digit1\") {\n currentMode = \"direct\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit2\") {\n currentMode = \"screen\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit3\") {\n currentMode = \"implementation\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n }\n };\n\n const handler = (event: MouseEvent) => {\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target, currentMode, projectRoot);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n document.addEventListener(\"keydown\", keyHandler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n document.removeEventListener(\"keydown\", keyHandler, true);\n overlay?.remove();\n };\n}\n"],"mappings":"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","names":["client_exports","__export","enableReactComponentJump","locateComponentSource","__toCommonJS","SOURCE_PROP","JSX_SOURCE_PROP","JSX_SOURCE_REGISTRY_SYMBOL","normalizeSlashes","value","trimTrailingSlash","splitPathSegments","computeRelativePath","fromPath","toPath","fromSegments","toSegments","sharedIndex","upSegments","downSegments","relativeSegments","normalizeProjectRoot","projectRoot","getSourceFile","source","isProjectLocalFile","filename","projectRoot","root","normalizeProjectRoot","normalizedFilename","normalizeSlashes","computeRelativePath","isProjectLocalSource","source","projectRoot","file","getSourceFile","isProjectLocalFile","isTriggerPressed","event","triggerKey","getReactFiberKey","element","key","getClosestReactFiber","target","current","fiberKey","getSourceFromType","type","source","SOURCE_PROP","record","getSourceFromProps","props","registry","JSX_SOURCE_REGISTRY_SYMBOL","intrinsicSource","JSX_SOURCE_PROP","resolveComponentSourceFromFiber","fiber","getDirectDebugSource","debugSource","normalizeSource","projectRoot","match","file","line","col","normalizedFile","normalizedRoot","resolveSourceCandidates","jsxCandidates","componentCandidates","rawJsxSource","jsxSource","getSourceFile","candidate","rawComponentSource","componentSource","direct","nearestProjectLocalComponentFile","isProjectLocalSource","screen","matchingJsxCandidate","matchingComponentCandidate","implementationComponentCandidate","implementationJsxCandidate","projectLocalJsxCandidate","screenFallback","getModeDescription","mode","createStatusOverlay","copyValue","currentMode","hideTimer","show","message","tone","mount","value","locateComponentSource","elementTarget","candidates","enableReactComponentJump","options","overlay","onLocate","result","onError","error","keyHandler","handler"]}
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var g="__componentSourceLoc",
|
|
1
|
+
var g="__componentSourceLoc",v="$componentSourceLoc",E="react-code-locator.jsxSourceRegistry";function C(t){return t.replace(/\\/g,"/")}function M(t){return t.replace(/\/+$/,"")}function L(t){return C(t).split("/").filter(Boolean)}function O(t,e){let n=L(t),r=L(e),o=0;for(;o<n.length&&o<r.length&&n[o]===r[o];)o+=1;let s=new Array(Math.max(0,n.length-o)).fill(".."),u=r.slice(o),c=[...s,...u];return c.length>0?c.join("/"):"."}function F(t){return t?M(C(t)):""}function b(t){return t?t.match(/^(.*):\d+:\d+$/)?.[1]??null:null}function T(t,e){if(!t)return!1;let n=F(e),r=C(t);return n?r.startsWith(`${n}/`)||r===n?!0:!O(n,r).startsWith("../"):!r.startsWith("../")&&!r.startsWith("/")&&!/^[A-Za-z]:\//.test(r)}function f(t,e){let n=b(t);return T(n??void 0,e)}function _(t,e){return e==="none"?!0:e==="alt"?t.altKey:e==="meta"?t.metaKey:e==="ctrl"?t.ctrlKey:t.shiftKey}function $(t){return Object.keys(t).find(e=>e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))}function j(t){let e=t;for(;e;){let n=$(e);if(n)return e[n];e=e.parentElement}return null}function h(t){if(!t)return null;if(typeof t=="function"){let r=t[g];return typeof r=="string"?r:null}if(typeof t!="object")return null;let e=t,n=e[g]??e.type?.[g]??e.render?.[g];return typeof n=="string"?n:null}function w(t){if(t&&typeof t=="object"){let n=globalThis[Symbol.for(E)];if(n instanceof WeakMap){let r=n.get(t);if(typeof r=="string")return r}}let e=t?.[v];return typeof e=="string"?e:null}function D(t){let e=t;for(;e;){let n=h(e.type)??h(e.elementType);if(n)return n;e=e.return??null}return null}function K(t){let e=t?._debugSource;return e?.fileName&&typeof e.lineNumber=="number"?`${e.fileName.replace(/\\/g,"/")}:${e.lineNumber}:${e.columnNumber??1}`:null}function k(t,e){if(!e||!t)return t;let n=t.match(/^(.*):(\d+):(\d+)$/);if(!n)return t;let[,r,o,s]=n,u=r.replace(/\\/g,"/"),c=e.replace(/\\/g,"/").replace(/\/$/,"");return u.startsWith(c+"/")?`${u.slice(c.length+1)}:${o}:${s}`:t}function z(t,e){let n=t,r=[],o=[];for(;n;){let l=w(n.pendingProps)??w(n.memoizedProps)??K(n),d=k(l??"",e)||l;if(d){let p=b(d);p&&!r.some(x=>x.source===d)&&r.push({source:d,file:p})}let y=h(n.type)??h(n.elementType),S=k(y??"",e)||y;if(S){let p=b(S);p&&!o.some(x=>x.source===S)&&o.push({source:S,file:p})}n=n.return??null}let s=r[0]?.source??null,u=o.find(l=>f(l.source))?.file,c=null;if(u){let l=r.find(d=>d.file===u);if(l)c=l.source;else{let d=o.find(y=>y.file===u);d&&(c=d.source)}}let a=o.find(l=>!f(l.source))?.source??null,i=r.find(l=>!f(l.source))?.source??null,m=r.find(l=>f(l.source))?.source??null,R=c??m??o.find(l=>f(l.source))?.source??null;return{direct:s??R,screen:R,implementation:a??i??R}}function N(t){return t==="direct"?"Direct JSX":t==="screen"?"Screen source":"Implementation source"}function J(t){if(typeof document>"u")return null;let e=document.createElement("div"),n=null,r="screen",o=null;e.setAttribute("data-react-code-locator","true"),Object.assign(e.style,{position:"fixed",right:"12px",bottom:"12px",zIndex:"2147483647",padding:"8px 10px",borderRadius:"8px",background:"rgba(17, 24, 39, 0.92)",color:"#fff",fontSize:"12px",lineHeight:"1.4",fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",boxShadow:"0 8px 30px rgba(0, 0, 0, 0.25)",pointerEvents:"auto",cursor:"pointer",maxWidth:"min(70vw, 720px)",wordBreak:"break-all",opacity:"0",transition:"opacity 120ms ease"});let s=(c,a)=>{e.textContent=c,e.style.background=a==="success"?"rgba(6, 95, 70, 0.92)":a==="error"?"rgba(153, 27, 27, 0.94)":"rgba(17, 24, 39, 0.92)",e.style.opacity="1",e.style.pointerEvents="auto",o&&clearTimeout(o),o=setTimeout(()=>{e.style.opacity="0",e.style.pointerEvents="none"},2e3)};e.addEventListener("click",async()=>{if(n)try{await navigator.clipboard.writeText(n),s("[react-code-locator] copied","success")}catch{s("[react-code-locator] copy failed","error")}}),s(`[react-code-locator] enabled (${t}+click, alt+1/2/3 to switch mode)`,"idle");let u=()=>{!e.isConnected&&document.body&&document.body.appendChild(e)};return document.body?u():document.addEventListener("DOMContentLoaded",u,{once:!0}),{setStatus(c,a="idle"){s(c,a)},setCopyValue(c){n=c},setMode(c){r=c,s(`[react-code-locator] ${N(c)}`,"idle")},remove(){o&&clearTimeout(o),e.remove()}}}function P(t,e="screen",n){let r=t instanceof Element?t:t instanceof Node?t.parentElement:null,o=j(r);if(!o)return null;let s=z(o,n),u=s[e]??s.screen??s.direct??s.implementation;if(u)return{source:u,mode:e};let c=D(o);return c?{source:c,mode:e}:null}function W(t={}){if(process.env.NODE_ENV!=="development")return;let e=J(t.triggerKey??"shift"),n="screen",{triggerKey:r="shift",projectRoot:o,onLocate:s=i=>{console.log(`[react-code-locator] ${i.source}`),e?.setCopyValue(i.source),e?.setStatus(`[react-code-locator] ${i.source}`,"success")},onError:u=i=>{console.error("[react-code-locator]",i);let m=i instanceof Error?i.message:String(i);e?.setCopyValue(null),e?.setStatus(`[react-code-locator] ${m}`,"error")}}=t;console.log("[react-code-locator] enabled",{triggerKey:r});let c=i=>{if(i.altKey){if(i.code==="Digit1"){n="direct",e?.setMode(n),i.preventDefault();return}if(i.code==="Digit2"){n="screen",e?.setMode(n),i.preventDefault();return}i.code==="Digit3"&&(n="implementation",e?.setMode(n),i.preventDefault())}},a=i=>{if(!_(i,r))return;let m=P(i.target,n,o);if(!m){u(new Error("No React component source metadata found for clicked element."));return}i.preventDefault(),i.stopPropagation(),s(m)};return document.addEventListener("click",a,!0),document.addEventListener("keydown",c,!0),()=>{document.removeEventListener("click",a,!0),document.removeEventListener("keydown",c,!0),e?.remove()}}export{W as enableReactComponentJump,P as locateComponentSource};
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/sourceMetadata.ts","../src/runtime.ts"],"sourcesContent":["export const SOURCE_PROP = \"__componentSourceLoc\";\nexport const JSX_SOURCE_PROP = \"$componentSourceLoc\";\nexport const JSX_SOURCE_REGISTRY_SYMBOL = \"react-code-locator.jsxSourceRegistry\";\n","export type SourceLocation = {\n line: number;\n column: number;\n};\n\nfunction normalizeSlashes(value: string) {\n return value.replace(/\\\\/g, \"/\");\n}\n\nfunction trimTrailingSlash(value: string) {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction splitPathSegments(value: string) {\n return normalizeSlashes(value).split(\"/\").filter(Boolean);\n}\n\nfunction computeRelativePath(fromPath: string, toPath: string) {\n const fromSegments = splitPathSegments(fromPath);\n const toSegments = splitPathSegments(toPath);\n\n let sharedIndex = 0;\n while (\n sharedIndex < fromSegments.length &&\n sharedIndex < toSegments.length &&\n fromSegments[sharedIndex] === toSegments[sharedIndex]\n ) {\n sharedIndex += 1;\n }\n\n const upSegments = new Array(Math.max(0, fromSegments.length - sharedIndex)).fill(\"..\");\n const downSegments = toSegments.slice(sharedIndex);\n const relativeSegments = [...upSegments, ...downSegments];\n return relativeSegments.length > 0 ? relativeSegments.join(\"/\") : \".\";\n}\n\nexport function normalizeProjectRoot(projectRoot?: string) {\n if (projectRoot) {\n return trimTrailingSlash(normalizeSlashes(projectRoot));\n }\n return \"\";\n}\n\nexport function toRelativeSource(\n filename: string | undefined,\n loc: SourceLocation | null | undefined,\n projectRoot?: string,\n) {\n if (!filename || !loc) {\n return null;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n const relPath =\n root && normalizedFilename.startsWith(`${root}/`)\n ? normalizedFilename.slice(root.length + 1)\n : root\n ? computeRelativePath(root, normalizedFilename)\n : normalizedFilename;\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nexport function getSourceFile(source: string | null) {\n if (!source) {\n return null;\n }\n\n const match = source.match(/^(.*):\\d+:\\d+$/);\n return match?.[1] ?? null;\n}\n\nexport function isProjectLocalFile(filename: string | undefined, projectRoot?: string) {\n if (!filename) {\n return false;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n\n if (!root) {\n return (\n !normalizedFilename.startsWith(\"../\") &&\n !normalizedFilename.startsWith(\"/\") &&\n !/^[A-Za-z]:\\//.test(normalizedFilename)\n );\n }\n\n if (normalizedFilename.startsWith(`${root}/`) || normalizedFilename === root) {\n return true;\n }\n\n const relativePath = computeRelativePath(root, normalizedFilename);\n return !relativePath.startsWith(\"../\");\n}\n\nexport function isExternalToProjectRoot(filename: string | undefined, projectRoot?: string) {\n return !isProjectLocalFile(filename, projectRoot);\n}\n\nexport function isProjectLocalSource(source: string, projectRoot?: string) {\n const file = getSourceFile(source);\n return isProjectLocalFile(file ?? undefined, projectRoot);\n}\n","import {\n JSX_SOURCE_PROP,\n JSX_SOURCE_REGISTRY_SYMBOL,\n SOURCE_PROP,\n} from \"./constants\";\nimport { getSourceFile, isProjectLocalSource } from \"./sourceMetadata\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\nexport type LocatorMode = \"direct\" | \"screen\" | \"implementation\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\n _debugOwner?: ReactFiber | null;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: LocatorMode;\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n projectRoot?: string;\n};\n\ntype StatusOverlay = {\n setStatus: (message: string, tone?: \"idle\" | \"success\" | \"error\") => void;\n setCopyValue: (value: string | null) => void;\n setMode: (mode: LocatorMode) => void;\n remove: () => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n if (props && typeof props === \"object\") {\n const registry = (globalThis as Record<symbol, unknown>)[\n Symbol.for(JSX_SOURCE_REGISTRY_SYMBOL)\n ];\n if (registry instanceof WeakMap) {\n const intrinsicSource = registry.get(props as object);\n if (typeof intrinsicSource === \"string\") {\n return intrinsicSource;\n }\n }\n }\n\n const source = props?.[JSX_SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveComponentSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDirectDebugSource(fiber: ReactFiber | null) {\n const debugSource = fiber?._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n return null;\n}\n\nfunction normalizeSource(source: string, projectRoot: string | undefined): string {\n if (!projectRoot || !source) return source;\n const match = source.match(/^(.*):(\\d+):(\\d+)$/);\n if (!match) return source;\n const [, file, line, col] = match;\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const normalizedRoot = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n if (normalizedFile.startsWith(normalizedRoot + \"/\")) {\n return `${normalizedFile.slice(normalizedRoot.length + 1)}:${line}:${col}`;\n }\n return source;\n}\n\ntype SourceCandidate = {\n source: string;\n file: string;\n};\n\ntype ResolvedCandidates = {\n direct: string | null;\n screen: string | null;\n implementation: string | null;\n};\n\nfunction resolveSourceCandidates(fiber: ReactFiber | null, projectRoot?: string): ResolvedCandidates {\n let current = fiber;\n const jsxCandidates: SourceCandidate[] = [];\n const componentCandidates: SourceCandidate[] = [];\n\n while (current) {\n const rawJsxSource =\n getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps) ?? getDirectDebugSource(current);\n const jsxSource = normalizeSource(rawJsxSource ?? \"\", projectRoot) || rawJsxSource;\n if (jsxSource) {\n const file = getSourceFile(jsxSource);\n if (file && !jsxCandidates.some((candidate) => candidate.source === jsxSource)) {\n jsxCandidates.push({ source: jsxSource, file });\n }\n }\n\n const rawComponentSource = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n const componentSource = normalizeSource(rawComponentSource ?? \"\", projectRoot) || rawComponentSource;\n if (componentSource) {\n const file = getSourceFile(componentSource);\n if (file && !componentCandidates.some((candidate) => candidate.source === componentSource)) {\n componentCandidates.push({ source: componentSource, file });\n }\n }\n\n current = current.return ?? null;\n }\n\n const direct = jsxCandidates[0]?.source ?? null;\n const nearestProjectLocalComponentFile = componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.file;\n let screen: string | null = null;\n if (nearestProjectLocalComponentFile) {\n const matchingJsxCandidate = jsxCandidates.find((candidate) => candidate.file === nearestProjectLocalComponentFile);\n if (matchingJsxCandidate) {\n screen = matchingJsxCandidate.source;\n } else {\n const matchingComponentCandidate = componentCandidates.find(\n (candidate) => candidate.file === nearestProjectLocalComponentFile,\n );\n if (matchingComponentCandidate) {\n screen = matchingComponentCandidate.source;\n }\n }\n }\n\n const implementationComponentCandidate =\n componentCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n const implementationJsxCandidate =\n jsxCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n\n const projectLocalJsxCandidate = jsxCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n const screenFallback = screen ?? projectLocalJsxCandidate ?? componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n\n return {\n direct: direct ?? screenFallback,\n screen: screenFallback,\n implementation: implementationComponentCandidate ?? implementationJsxCandidate ?? screenFallback,\n };\n}\n\nfunction getModeDescription(mode: LocatorMode) {\n if (mode === \"direct\") {\n return \"Direct JSX\";\n }\n\n if (mode === \"screen\") {\n return \"Screen source\";\n }\n\n return \"Implementation source\";\n}\n\nfunction createStatusOverlay(triggerKey: TriggerKey): StatusOverlay | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const element = document.createElement(\"div\");\n let copyValue: string | null = null;\n let currentMode: LocatorMode = \"screen\";\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n element.setAttribute(\"data-react-code-locator\", \"true\");\n Object.assign(element.style, {\n position: \"fixed\",\n right: \"12px\",\n bottom: \"12px\",\n zIndex: \"2147483647\",\n padding: \"8px 10px\",\n borderRadius: \"8px\",\n background: \"rgba(17, 24, 39, 0.92)\",\n color: \"#fff\",\n fontSize: \"12px\",\n lineHeight: \"1.4\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n boxShadow: \"0 8px 30px rgba(0, 0, 0, 0.25)\",\n pointerEvents: \"auto\",\n cursor: \"pointer\",\n maxWidth: \"min(70vw, 720px)\",\n wordBreak: \"break-all\",\n opacity: \"0\",\n transition: \"opacity 120ms ease\",\n });\n\n const show = (message: string, tone: \"idle\" | \"success\" | \"error\") => {\n element.textContent = message;\n element.style.background =\n tone === \"success\"\n ? \"rgba(6, 95, 70, 0.92)\"\n : tone === \"error\"\n ? \"rgba(153, 27, 27, 0.94)\"\n : \"rgba(17, 24, 39, 0.92)\";\n element.style.opacity = \"1\";\n element.style.pointerEvents = \"auto\";\n\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n\n hideTimer = setTimeout(() => {\n element.style.opacity = \"0\";\n element.style.pointerEvents = \"none\";\n }, 2000);\n };\n\n element.addEventListener(\"click\", async () => {\n if (!copyValue) {\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyValue);\n show(`[react-code-locator] copied`, \"success\");\n } catch {\n show(`[react-code-locator] copy failed`, \"error\");\n }\n });\n\n show(`[react-code-locator] enabled (${triggerKey}+click, alt+1/2/3 to switch mode)`, \"idle\");\n\n const mount = () => {\n if (!element.isConnected && document.body) {\n document.body.appendChild(element);\n }\n };\n\n if (document.body) {\n mount();\n } else {\n document.addEventListener(\"DOMContentLoaded\", mount, { once: true });\n }\n\n return {\n setStatus(message, tone = \"idle\") {\n show(message, tone);\n },\n setCopyValue(value) {\n copyValue = value;\n },\n setMode(mode) {\n currentMode = mode;\n show(`[react-code-locator] ${getModeDescription(mode)}`, \"idle\");\n },\n remove() {\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n element.remove();\n },\n };\n}\n\nexport function locateComponentSource(target: EventTarget | null, mode: LocatorMode = \"screen\", projectRoot?: string): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const candidates = resolveSourceCandidates(fiber, projectRoot);\n const source = candidates[mode] ?? candidates.screen ?? candidates.direct ?? candidates.implementation;\n if (source) {\n return {\n source,\n mode,\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode,\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n if (process.env.NODE_ENV !== \"development\") return;\n const overlay = createStatusOverlay(options.triggerKey ?? \"shift\");\n let currentMode: LocatorMode = \"screen\";\n const {\n triggerKey = \"shift\",\n projectRoot,\n onLocate = (result) => {\n console.log(`[react-code-locator] ${result.source}`);\n overlay?.setCopyValue(result.source);\n overlay?.setStatus(`[react-code-locator] ${result.source}`, \"success\");\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", error);\n const message = error instanceof Error ? error.message : String(error);\n overlay?.setCopyValue(null);\n overlay?.setStatus(`[react-code-locator] ${message}`, \"error\");\n },\n } = options;\n\n console.log(\"[react-code-locator] enabled\", { triggerKey });\n\n const keyHandler = (event: KeyboardEvent) => {\n if (!event.altKey) {\n return;\n }\n\n if (event.code === \"Digit1\") {\n currentMode = \"direct\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit2\") {\n currentMode = \"screen\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit3\") {\n currentMode = \"implementation\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n }\n };\n\n const handler = (event: MouseEvent) => {\n console.log(\"[react-code-locator] click\", {\n triggerKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n target: event.target,\n });\n\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target, currentMode, projectRoot);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n document.addEventListener(\"keydown\", keyHandler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n document.removeEventListener(\"keydown\", keyHandler, true);\n overlay?.remove();\n };\n}\n"],"mappings":"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","names":["SOURCE_PROP","JSX_SOURCE_PROP","JSX_SOURCE_REGISTRY_SYMBOL","normalizeSlashes","value","trimTrailingSlash","splitPathSegments","computeRelativePath","fromPath","toPath","fromSegments","toSegments","sharedIndex","upSegments","downSegments","relativeSegments","normalizeProjectRoot","projectRoot","getSourceFile","source","isProjectLocalFile","filename","projectRoot","root","normalizeProjectRoot","normalizedFilename","normalizeSlashes","computeRelativePath","isProjectLocalSource","source","projectRoot","file","getSourceFile","isProjectLocalFile","isTriggerPressed","event","triggerKey","getReactFiberKey","element","key","getClosestReactFiber","target","current","fiberKey","getSourceFromType","type","source","SOURCE_PROP","record","getSourceFromProps","props","registry","JSX_SOURCE_REGISTRY_SYMBOL","intrinsicSource","JSX_SOURCE_PROP","resolveComponentSourceFromFiber","fiber","getDirectDebugSource","debugSource","normalizeSource","projectRoot","match","file","line","col","normalizedFile","normalizedRoot","resolveSourceCandidates","jsxCandidates","componentCandidates","rawJsxSource","jsxSource","getSourceFile","candidate","rawComponentSource","componentSource","direct","nearestProjectLocalComponentFile","isProjectLocalSource","screen","matchingJsxCandidate","matchingComponentCandidate","implementationComponentCandidate","implementationJsxCandidate","projectLocalJsxCandidate","screenFallback","getModeDescription","mode","createStatusOverlay","copyValue","currentMode","hideTimer","show","message","tone","mount","value","locateComponentSource","elementTarget","candidates","enableReactComponentJump","options","overlay","onLocate","result","onError","error","keyHandler","handler"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/sourceMetadata.ts","../src/runtime.ts"],"sourcesContent":["export const SOURCE_PROP = \"__componentSourceLoc\";\nexport const JSX_SOURCE_PROP = \"$componentSourceLoc\";\nexport const JSX_SOURCE_REGISTRY_SYMBOL = \"react-code-locator.jsxSourceRegistry\";\n","export type SourceLocation = {\n line: number;\n column: number;\n};\n\nfunction normalizeSlashes(value: string) {\n return value.replace(/\\\\/g, \"/\");\n}\n\nfunction trimTrailingSlash(value: string) {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction splitPathSegments(value: string) {\n return normalizeSlashes(value).split(\"/\").filter(Boolean);\n}\n\nfunction computeRelativePath(fromPath: string, toPath: string) {\n const fromSegments = splitPathSegments(fromPath);\n const toSegments = splitPathSegments(toPath);\n\n let sharedIndex = 0;\n while (\n sharedIndex < fromSegments.length &&\n sharedIndex < toSegments.length &&\n fromSegments[sharedIndex] === toSegments[sharedIndex]\n ) {\n sharedIndex += 1;\n }\n\n const upSegments = new Array(Math.max(0, fromSegments.length - sharedIndex)).fill(\"..\");\n const downSegments = toSegments.slice(sharedIndex);\n const relativeSegments = [...upSegments, ...downSegments];\n return relativeSegments.length > 0 ? relativeSegments.join(\"/\") : \".\";\n}\n\nexport function normalizeProjectRoot(projectRoot?: string) {\n if (projectRoot) {\n return trimTrailingSlash(normalizeSlashes(projectRoot));\n }\n return \"\";\n}\n\nexport function toRelativeSource(\n filename: string | undefined,\n loc: SourceLocation | null | undefined,\n projectRoot?: string,\n) {\n if (!filename || !loc) {\n return null;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n const relPath =\n root && normalizedFilename.startsWith(`${root}/`)\n ? normalizedFilename.slice(root.length + 1)\n : root\n ? computeRelativePath(root, normalizedFilename)\n : normalizedFilename;\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nexport function getSourceFile(source: string | null) {\n if (!source) {\n return null;\n }\n\n const match = source.match(/^(.*):\\d+:\\d+$/);\n return match?.[1] ?? null;\n}\n\nexport function isProjectLocalFile(filename: string | undefined, projectRoot?: string) {\n if (!filename) {\n return false;\n }\n\n const root = normalizeProjectRoot(projectRoot);\n const normalizedFilename = normalizeSlashes(filename);\n\n if (!root) {\n return (\n !normalizedFilename.startsWith(\"../\") &&\n !normalizedFilename.startsWith(\"/\") &&\n !/^[A-Za-z]:\\//.test(normalizedFilename)\n );\n }\n\n if (normalizedFilename.startsWith(`${root}/`) || normalizedFilename === root) {\n return true;\n }\n\n const relativePath = computeRelativePath(root, normalizedFilename);\n return !relativePath.startsWith(\"../\");\n}\n\nexport function isExternalToProjectRoot(filename: string | undefined, projectRoot?: string) {\n return !isProjectLocalFile(filename, projectRoot);\n}\n\nexport function isProjectLocalSource(source: string, projectRoot?: string) {\n const file = getSourceFile(source);\n return isProjectLocalFile(file ?? undefined, projectRoot);\n}\n","import {\n JSX_SOURCE_PROP,\n JSX_SOURCE_REGISTRY_SYMBOL,\n SOURCE_PROP,\n} from \"./constants\";\nimport { getSourceFile, isProjectLocalSource } from \"./sourceMetadata\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\nexport type LocatorMode = \"direct\" | \"screen\" | \"implementation\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\n _debugOwner?: ReactFiber | null;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: LocatorMode;\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n projectRoot?: string;\n};\n\ntype StatusOverlay = {\n setStatus: (message: string, tone?: \"idle\" | \"success\" | \"error\") => void;\n setCopyValue: (value: string | null) => void;\n setMode: (mode: LocatorMode) => void;\n remove: () => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n if (props && typeof props === \"object\") {\n const registry = (globalThis as Record<symbol, unknown>)[\n Symbol.for(JSX_SOURCE_REGISTRY_SYMBOL)\n ];\n if (registry instanceof WeakMap) {\n const intrinsicSource = registry.get(props as object);\n if (typeof intrinsicSource === \"string\") {\n return intrinsicSource;\n }\n }\n }\n\n const source = props?.[JSX_SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveComponentSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDirectDebugSource(fiber: ReactFiber | null) {\n const debugSource = fiber?._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n return null;\n}\n\nfunction normalizeSource(source: string, projectRoot: string | undefined): string {\n if (!projectRoot || !source) return source;\n const match = source.match(/^(.*):(\\d+):(\\d+)$/);\n if (!match) return source;\n const [, file, line, col] = match;\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const normalizedRoot = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n if (normalizedFile.startsWith(normalizedRoot + \"/\")) {\n return `${normalizedFile.slice(normalizedRoot.length + 1)}:${line}:${col}`;\n }\n return source;\n}\n\ntype SourceCandidate = {\n source: string;\n file: string;\n};\n\ntype ResolvedCandidates = {\n direct: string | null;\n screen: string | null;\n implementation: string | null;\n};\n\nfunction resolveSourceCandidates(fiber: ReactFiber | null, projectRoot?: string): ResolvedCandidates {\n let current = fiber;\n const jsxCandidates: SourceCandidate[] = [];\n const componentCandidates: SourceCandidate[] = [];\n\n while (current) {\n const rawJsxSource =\n getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps) ?? getDirectDebugSource(current);\n const jsxSource = normalizeSource(rawJsxSource ?? \"\", projectRoot) || rawJsxSource;\n if (jsxSource) {\n const file = getSourceFile(jsxSource);\n if (file && !jsxCandidates.some((candidate) => candidate.source === jsxSource)) {\n jsxCandidates.push({ source: jsxSource, file });\n }\n }\n\n const rawComponentSource = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n const componentSource = normalizeSource(rawComponentSource ?? \"\", projectRoot) || rawComponentSource;\n if (componentSource) {\n const file = getSourceFile(componentSource);\n if (file && !componentCandidates.some((candidate) => candidate.source === componentSource)) {\n componentCandidates.push({ source: componentSource, file });\n }\n }\n\n current = current.return ?? null;\n }\n\n const direct = jsxCandidates[0]?.source ?? null;\n const nearestProjectLocalComponentFile = componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.file;\n let screen: string | null = null;\n if (nearestProjectLocalComponentFile) {\n const matchingJsxCandidate = jsxCandidates.find((candidate) => candidate.file === nearestProjectLocalComponentFile);\n if (matchingJsxCandidate) {\n screen = matchingJsxCandidate.source;\n } else {\n const matchingComponentCandidate = componentCandidates.find(\n (candidate) => candidate.file === nearestProjectLocalComponentFile,\n );\n if (matchingComponentCandidate) {\n screen = matchingComponentCandidate.source;\n }\n }\n }\n\n const implementationComponentCandidate =\n componentCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n const implementationJsxCandidate =\n jsxCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;\n\n const projectLocalJsxCandidate = jsxCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n const screenFallback = screen ?? projectLocalJsxCandidate ?? componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;\n\n return {\n direct: direct ?? screenFallback,\n screen: screenFallback,\n implementation: implementationComponentCandidate ?? implementationJsxCandidate ?? screenFallback,\n };\n}\n\nfunction getModeDescription(mode: LocatorMode) {\n if (mode === \"direct\") {\n return \"Direct JSX\";\n }\n\n if (mode === \"screen\") {\n return \"Screen source\";\n }\n\n return \"Implementation source\";\n}\n\nfunction createStatusOverlay(triggerKey: TriggerKey): StatusOverlay | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const element = document.createElement(\"div\");\n let copyValue: string | null = null;\n let currentMode: LocatorMode = \"screen\";\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n element.setAttribute(\"data-react-code-locator\", \"true\");\n Object.assign(element.style, {\n position: \"fixed\",\n right: \"12px\",\n bottom: \"12px\",\n zIndex: \"2147483647\",\n padding: \"8px 10px\",\n borderRadius: \"8px\",\n background: \"rgba(17, 24, 39, 0.92)\",\n color: \"#fff\",\n fontSize: \"12px\",\n lineHeight: \"1.4\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n boxShadow: \"0 8px 30px rgba(0, 0, 0, 0.25)\",\n pointerEvents: \"auto\",\n cursor: \"pointer\",\n maxWidth: \"min(70vw, 720px)\",\n wordBreak: \"break-all\",\n opacity: \"0\",\n transition: \"opacity 120ms ease\",\n });\n\n const show = (message: string, tone: \"idle\" | \"success\" | \"error\") => {\n element.textContent = message;\n element.style.background =\n tone === \"success\"\n ? \"rgba(6, 95, 70, 0.92)\"\n : tone === \"error\"\n ? \"rgba(153, 27, 27, 0.94)\"\n : \"rgba(17, 24, 39, 0.92)\";\n element.style.opacity = \"1\";\n element.style.pointerEvents = \"auto\";\n\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n\n hideTimer = setTimeout(() => {\n element.style.opacity = \"0\";\n element.style.pointerEvents = \"none\";\n }, 2000);\n };\n\n element.addEventListener(\"click\", async () => {\n if (!copyValue) {\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyValue);\n show(`[react-code-locator] copied`, \"success\");\n } catch {\n show(`[react-code-locator] copy failed`, \"error\");\n }\n });\n\n show(`[react-code-locator] enabled (${triggerKey}+click, alt+1/2/3 to switch mode)`, \"idle\");\n\n const mount = () => {\n if (!element.isConnected && document.body) {\n document.body.appendChild(element);\n }\n };\n\n if (document.body) {\n mount();\n } else {\n document.addEventListener(\"DOMContentLoaded\", mount, { once: true });\n }\n\n return {\n setStatus(message, tone = \"idle\") {\n show(message, tone);\n },\n setCopyValue(value) {\n copyValue = value;\n },\n setMode(mode) {\n currentMode = mode;\n show(`[react-code-locator] ${getModeDescription(mode)}`, \"idle\");\n },\n remove() {\n if (hideTimer) {\n clearTimeout(hideTimer);\n }\n element.remove();\n },\n };\n}\n\nexport function locateComponentSource(target: EventTarget | null, mode: LocatorMode = \"screen\", projectRoot?: string): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const candidates = resolveSourceCandidates(fiber, projectRoot);\n const source = candidates[mode] ?? candidates.screen ?? candidates.direct ?? candidates.implementation;\n if (source) {\n return {\n source,\n mode,\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode,\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n if (process.env.NODE_ENV !== \"development\") return;\n const overlay = createStatusOverlay(options.triggerKey ?? \"shift\");\n let currentMode: LocatorMode = \"screen\";\n const {\n triggerKey = \"shift\",\n projectRoot,\n onLocate = (result) => {\n console.log(`[react-code-locator] ${result.source}`);\n overlay?.setCopyValue(result.source);\n overlay?.setStatus(`[react-code-locator] ${result.source}`, \"success\");\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", error);\n const message = error instanceof Error ? error.message : String(error);\n overlay?.setCopyValue(null);\n overlay?.setStatus(`[react-code-locator] ${message}`, \"error\");\n },\n } = options;\n\n console.log(\"[react-code-locator] enabled\", { triggerKey });\n\n const keyHandler = (event: KeyboardEvent) => {\n if (!event.altKey) {\n return;\n }\n\n if (event.code === \"Digit1\") {\n currentMode = \"direct\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit2\") {\n currentMode = \"screen\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n return;\n }\n\n if (event.code === \"Digit3\") {\n currentMode = \"implementation\";\n overlay?.setMode(currentMode);\n event.preventDefault();\n }\n };\n\n const handler = (event: MouseEvent) => {\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target, currentMode, projectRoot);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n document.addEventListener(\"keydown\", keyHandler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n document.removeEventListener(\"keydown\", keyHandler, true);\n overlay?.remove();\n };\n}\n"],"mappings":"AAAO,IAAMA,EAAc,uBACdC,EAAkB,sBAClBC,EAA6B,uCCG1C,SAASC,EAAiBC,EAAe,CACvC,OAAOA,EAAM,QAAQ,MAAO,GAAG,CACjC,CAEA,SAASC,EAAkBD,EAAe,CACxC,OAAOA,EAAM,QAAQ,OAAQ,EAAE,CACjC,CAEA,SAASE,EAAkBF,EAAe,CACxC,OAAOD,EAAiBC,CAAK,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,CAC1D,CAEA,SAASG,EAAoBC,EAAkBC,EAAgB,CAC7D,IAAMC,EAAeJ,EAAkBE,CAAQ,EACzCG,EAAaL,EAAkBG,CAAM,EAEvCG,EAAc,EAClB,KACEA,EAAcF,EAAa,QAC3BE,EAAcD,EAAW,QACzBD,EAAaE,CAAW,IAAMD,EAAWC,CAAW,GAEpDA,GAAe,EAGjB,IAAMC,EAAa,IAAI,MAAM,KAAK,IAAI,EAAGH,EAAa,OAASE,CAAW,CAAC,EAAE,KAAK,IAAI,EAChFE,EAAeH,EAAW,MAAMC,CAAW,EAC3CG,EAAmB,CAAC,GAAGF,EAAY,GAAGC,CAAY,EACxD,OAAOC,EAAiB,OAAS,EAAIA,EAAiB,KAAK,GAAG,EAAI,GACpE,CAEO,SAASC,EAAqBC,EAAsB,CACzD,OAAIA,EACKZ,EAAkBF,EAAiBc,CAAW,CAAC,EAEjD,EACT,CAsBO,SAASC,EAAcC,EAAuB,CACnD,OAAKA,EAISA,EAAO,MAAM,gBAAgB,IAC5B,CAAC,GAAK,KAJZ,IAKX,CAEO,SAASC,EAAmBC,EAA8BC,EAAsB,CACrF,GAAI,CAACD,EACH,MAAO,GAGT,IAAME,EAAOC,EAAqBF,CAAW,EACvCG,EAAqBC,EAAiBL,CAAQ,EAEpD,OAAKE,EAQDE,EAAmB,WAAW,GAAGF,CAAI,GAAG,GAAKE,IAAuBF,EAC/D,GAIF,CADcI,EAAoBJ,EAAME,CAAkB,EAC5C,WAAW,KAAK,EAXjC,CAACA,EAAmB,WAAW,KAAK,GACpC,CAACA,EAAmB,WAAW,GAAG,GAClC,CAAC,eAAe,KAAKA,CAAkB,CAU7C,CAMO,SAASG,EAAqBC,EAAgBC,EAAsB,CACzE,IAAMC,EAAOC,EAAcH,CAAM,EACjC,OAAOI,EAAmBF,GAAQ,OAAWD,CAAW,CAC1D,CC5DA,SAASI,EAAiBC,EAAmBC,EAAwB,CACnE,OAAIA,IAAe,OACV,GAGLA,IAAe,MACVD,EAAM,OAGXC,IAAe,OACVD,EAAM,QAGXC,IAAe,OACVD,EAAM,QAGRA,EAAM,QACf,CAEA,SAASE,EAAiBC,EAAkB,CAC1C,OAAO,OAAO,KAAKA,CAAO,EAAE,KAAMC,GAAQA,EAAI,WAAW,eAAe,GAAKA,EAAI,WAAW,0BAA0B,CAAC,CACzH,CAEA,SAASC,EAAqBC,EAAwB,CACpD,IAAIC,EAAUD,EAEd,KAAOC,GAAS,CACd,IAAMC,EAAWN,EAAiBK,CAAO,EACzC,GAAIC,EACF,OAAQD,EAA+CC,CAAQ,EAGjED,EAAUA,EAAQ,aACpB,CAEA,OAAO,IACT,CAEA,SAASE,EAAkBC,EAAe,CACxC,GAAI,CAACA,EACH,OAAO,KAGT,GAAI,OAAOA,GAAS,WAAY,CAC9B,IAAMC,EAAUD,EAA4CE,CAAW,EACvE,OAAO,OAAOD,GAAW,SAAWA,EAAS,IAC/C,CAEA,GAAI,OAAOD,GAAS,SAClB,OAAO,KAGT,IAAMG,EAASH,EAMTC,EAASE,EAAOD,CAAW,GAAKC,EAAO,OAAOD,CAAW,GAAKC,EAAO,SAASD,CAAW,EAC/F,OAAO,OAAOD,GAAW,SAAWA,EAAS,IAC/C,CAEA,SAASG,EAAmBC,EAAmD,CAC7E,GAAIA,GAAS,OAAOA,GAAU,SAAU,CACtC,IAAMC,EAAY,WAChB,OAAO,IAAIC,CAA0B,CACvC,EACA,GAAID,aAAoB,QAAS,CAC/B,IAAME,EAAkBF,EAAS,IAAID,CAAe,EACpD,GAAI,OAAOG,GAAoB,SAC7B,OAAOA,CAEX,CACF,CAEA,IAAMP,EAASI,IAAQI,CAAe,EACtC,OAAO,OAAOR,GAAW,SAAWA,EAAS,IAC/C,CAEA,SAASS,EAAgCC,EAA0B,CACjE,IAAId,EAAUc,EAEd,KAAOd,GAAS,CACd,IAAMI,EAASF,EAAkBF,EAAQ,IAAI,GAAKE,EAAkBF,EAAQ,WAAW,EACvF,GAAII,EACF,OAAOA,EAGTJ,EAAUA,EAAQ,QAAU,IAC9B,CAEA,OAAO,IACT,CAEA,SAASe,EAAqBD,EAA0B,CACtD,IAAME,EAAcF,GAAO,aAC3B,OAAIE,GAAa,UAAY,OAAOA,EAAY,YAAe,SACtD,GAAGA,EAAY,SAAS,QAAQ,MAAO,GAAG,CAAC,IAAIA,EAAY,UAAU,IAAIA,EAAY,cAAgB,CAAC,GAGxG,IACT,CAEA,SAASC,EAAgBb,EAAgBc,EAAyC,CAChF,GAAI,CAACA,GAAe,CAACd,EAAQ,OAAOA,EACpC,IAAMe,EAAQf,EAAO,MAAM,oBAAoB,EAC/C,GAAI,CAACe,EAAO,OAAOf,EACnB,GAAM,CAAC,CAAEgB,EAAMC,EAAMC,CAAG,EAAIH,EACtBI,EAAiBH,EAAK,QAAQ,MAAO,GAAG,EACxCI,EAAiBN,EAAY,QAAQ,MAAO,GAAG,EAAE,QAAQ,MAAO,EAAE,EACxE,OAAIK,EAAe,WAAWC,EAAiB,GAAG,EACzC,GAAGD,EAAe,MAAMC,EAAe,OAAS,CAAC,CAAC,IAAIH,CAAI,IAAIC,CAAG,GAEnElB,CACT,CAaA,SAASqB,EAAwBX,EAA0BI,EAA0C,CACnG,IAAIlB,EAAUc,EACRY,EAAmC,CAAC,EACpCC,EAAyC,CAAC,EAEhD,KAAO3B,GAAS,CACd,IAAM4B,EACJrB,EAAmBP,EAAQ,YAAY,GAAKO,EAAmBP,EAAQ,aAAa,GAAKe,EAAqBf,CAAO,EACjH6B,EAAYZ,EAAgBW,GAAgB,GAAIV,CAAW,GAAKU,EACtE,GAAIC,EAAW,CACb,IAAMT,EAAOU,EAAcD,CAAS,EAChCT,GAAQ,CAACM,EAAc,KAAMK,GAAcA,EAAU,SAAWF,CAAS,GAC3EH,EAAc,KAAK,CAAE,OAAQG,EAAW,KAAAT,CAAK,CAAC,CAElD,CAEA,IAAMY,EAAqB9B,EAAkBF,EAAQ,IAAI,GAAKE,EAAkBF,EAAQ,WAAW,EAC7FiC,EAAkBhB,EAAgBe,GAAsB,GAAId,CAAW,GAAKc,EAClF,GAAIC,EAAiB,CACnB,IAAMb,EAAOU,EAAcG,CAAe,EACtCb,GAAQ,CAACO,EAAoB,KAAMI,GAAcA,EAAU,SAAWE,CAAe,GACvFN,EAAoB,KAAK,CAAE,OAAQM,EAAiB,KAAAb,CAAK,CAAC,CAE9D,CAEApB,EAAUA,EAAQ,QAAU,IAC9B,CAEA,IAAMkC,EAASR,EAAc,CAAC,GAAG,QAAU,KACrCS,EAAmCR,EAAoB,KAAMI,GAAcK,EAAqBL,EAAU,MAAM,CAAC,GAAG,KACtHM,EAAwB,KAC5B,GAAIF,EAAkC,CACpC,IAAMG,EAAuBZ,EAAc,KAAMK,GAAcA,EAAU,OAASI,CAAgC,EAClH,GAAIG,EACFD,EAASC,EAAqB,WACzB,CACL,IAAMC,EAA6BZ,EAAoB,KACpDI,GAAcA,EAAU,OAASI,CACpC,EACII,IACFF,EAASE,EAA2B,OAExC,CACF,CAEA,IAAMC,EACJb,EAAoB,KAAMI,GAAc,CAACK,EAAqBL,EAAU,MAAM,CAAC,GAAG,QAAU,KACxFU,EACJf,EAAc,KAAMK,GAAc,CAACK,EAAqBL,EAAU,MAAM,CAAC,GAAG,QAAU,KAElFW,EAA2BhB,EAAc,KAAMK,GAAcK,EAAqBL,EAAU,MAAM,CAAC,GAAG,QAAU,KAChHY,EAAiBN,GAAUK,GAA4Bf,EAAoB,KAAMI,GAAcK,EAAqBL,EAAU,MAAM,CAAC,GAAG,QAAU,KAExJ,MAAO,CACL,OAAQG,GAAUS,EAClB,OAAQA,EACR,eAAgBH,GAAoCC,GAA8BE,CACpF,CACF,CAEA,SAASC,EAAmBC,EAAmB,CAC7C,OAAIA,IAAS,SACJ,aAGLA,IAAS,SACJ,gBAGF,uBACT,CAEA,SAASC,EAAoBpD,EAA8C,CACzE,GAAI,OAAO,SAAa,IACtB,OAAO,KAGT,IAAME,EAAU,SAAS,cAAc,KAAK,EACxCmD,EAA2B,KAC3BC,EAA2B,SAC3BC,EAAkD,KACtDrD,EAAQ,aAAa,0BAA2B,MAAM,EACtD,OAAO,OAAOA,EAAQ,MAAO,CAC3B,SAAU,QACV,MAAO,OACP,OAAQ,OACR,OAAQ,aACR,QAAS,WACT,aAAc,MACd,WAAY,yBACZ,MAAO,OACP,SAAU,OACV,WAAY,MACZ,WAAY,mEACZ,UAAW,iCACX,cAAe,OACf,OAAQ,UACR,SAAU,mBACV,UAAW,YACX,QAAS,IACT,WAAY,oBACd,CAAC,EAED,IAAMsD,EAAO,CAACC,EAAiBC,IAAuC,CACpExD,EAAQ,YAAcuD,EACtBvD,EAAQ,MAAM,WACZwD,IAAS,UACL,wBACAA,IAAS,QACP,0BACA,yBACRxD,EAAQ,MAAM,QAAU,IACxBA,EAAQ,MAAM,cAAgB,OAE1BqD,GACF,aAAaA,CAAS,EAGxBA,EAAY,WAAW,IAAM,CAC3BrD,EAAQ,MAAM,QAAU,IACxBA,EAAQ,MAAM,cAAgB,MAChC,EAAG,GAAI,CACT,EAEAA,EAAQ,iBAAiB,QAAS,SAAY,CAC5C,GAAKmD,EAIL,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,CAAS,EAC7CG,EAAK,8BAA+B,SAAS,CAC/C,MAAQ,CACNA,EAAK,mCAAoC,OAAO,CAClD,CACF,CAAC,EAEDA,EAAK,iCAAiCxD,CAAU,oCAAqC,MAAM,EAE3F,IAAM2D,EAAQ,IAAM,CACd,CAACzD,EAAQ,aAAe,SAAS,MACnC,SAAS,KAAK,YAAYA,CAAO,CAErC,EAEA,OAAI,SAAS,KACXyD,EAAM,EAEN,SAAS,iBAAiB,mBAAoBA,EAAO,CAAE,KAAM,EAAK,CAAC,EAG9D,CACL,UAAUF,EAASC,EAAO,OAAQ,CAChCF,EAAKC,EAASC,CAAI,CACpB,EACA,aAAaE,EAAO,CAClBP,EAAYO,CACd,EACA,QAAQT,EAAM,CACZG,EAAcH,EACdK,EAAK,wBAAwBN,EAAmBC,CAAI,CAAC,GAAI,MAAM,CACjE,EACA,QAAS,CACHI,GACF,aAAaA,CAAS,EAExBrD,EAAQ,OAAO,CACjB,CACF,CACF,CAEO,SAAS2D,EAAsBxD,EAA4B8C,EAAoB,SAAU3B,EAA4C,CAC1I,IAAMsC,EACJzD,aAAkB,QAAUA,EAASA,aAAkB,KAAOA,EAAO,cAAgB,KACjFe,EAAQhB,EAAqB0D,CAAa,EAChD,GAAI,CAAC1C,EACH,OAAO,KAGT,IAAM2C,EAAahC,EAAwBX,EAAOI,CAAW,EACvDd,EAASqD,EAAWZ,CAAI,GAAKY,EAAW,QAAUA,EAAW,QAAUA,EAAW,eACxF,GAAIrD,EACF,MAAO,CACL,OAAAA,EACA,KAAAyC,CACF,EAGF,IAAMZ,EAAkBpB,EAAgCC,CAAK,EAC7D,OAAKmB,EAIE,CACL,OAAQA,EACR,KAAAY,CACF,EANS,IAOX,CAEO,SAASa,EAAyBC,EAA0B,CAAC,EAAG,CACrE,GAAI,QAAQ,IAAI,WAAa,cAAe,OAC5C,IAAMC,EAAUd,EAAoBa,EAAQ,YAAc,OAAO,EAC7DX,EAA2B,SACzB,CACJ,WAAAtD,EAAa,QACb,YAAAwB,EACA,SAAA2C,EAAYC,GAAW,CACrB,QAAQ,IAAI,wBAAwBA,EAAO,MAAM,EAAE,EACnDF,GAAS,aAAaE,EAAO,MAAM,EACnCF,GAAS,UAAU,wBAAwBE,EAAO,MAAM,GAAI,SAAS,CACvE,EACA,QAAAC,EAAWC,GAAU,CACnB,QAAQ,MAAM,uBAAwBA,CAAK,EAC3C,IAAMb,EAAUa,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACrEJ,GAAS,aAAa,IAAI,EAC1BA,GAAS,UAAU,wBAAwBT,CAAO,GAAI,OAAO,CAC/D,CACF,EAAIQ,EAEJ,QAAQ,IAAI,+BAAgC,CAAE,WAAAjE,CAAW,CAAC,EAE1D,IAAMuE,EAAcxE,GAAyB,CAC3C,GAAKA,EAAM,OAIX,IAAIA,EAAM,OAAS,SAAU,CAC3BuD,EAAc,SACdY,GAAS,QAAQZ,CAAW,EAC5BvD,EAAM,eAAe,EACrB,MACF,CAEA,GAAIA,EAAM,OAAS,SAAU,CAC3BuD,EAAc,SACdY,GAAS,QAAQZ,CAAW,EAC5BvD,EAAM,eAAe,EACrB,MACF,CAEIA,EAAM,OAAS,WACjBuD,EAAc,iBACdY,GAAS,QAAQZ,CAAW,EAC5BvD,EAAM,eAAe,GAEzB,EAEMyE,EAAWzE,GAAsB,CACrC,GAAI,CAACD,EAAiBC,EAAOC,CAAU,EACrC,OAGF,IAAMoE,EAASP,EAAsB9D,EAAM,OAAQuD,EAAa9B,CAAW,EAC3E,GAAI,CAAC4C,EAAQ,CACXC,EAAQ,IAAI,MAAM,+DAA+D,CAAC,EAClF,MACF,CAEAtE,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtBoE,EAASC,CAAM,CACjB,EAEA,gBAAS,iBAAiB,QAASI,EAAS,EAAI,EAChD,SAAS,iBAAiB,UAAWD,EAAY,EAAI,EAE9C,IAAM,CACX,SAAS,oBAAoB,QAASC,EAAS,EAAI,EACnD,SAAS,oBAAoB,UAAWD,EAAY,EAAI,EACxDL,GAAS,OAAO,CAClB,CACF","names":["SOURCE_PROP","JSX_SOURCE_PROP","JSX_SOURCE_REGISTRY_SYMBOL","normalizeSlashes","value","trimTrailingSlash","splitPathSegments","computeRelativePath","fromPath","toPath","fromSegments","toSegments","sharedIndex","upSegments","downSegments","relativeSegments","normalizeProjectRoot","projectRoot","getSourceFile","source","isProjectLocalFile","filename","projectRoot","root","normalizeProjectRoot","normalizedFilename","normalizeSlashes","computeRelativePath","isProjectLocalSource","source","projectRoot","file","getSourceFile","isProjectLocalFile","isTriggerPressed","event","triggerKey","getReactFiberKey","element","key","getClosestReactFiber","target","current","fiberKey","getSourceFromType","type","source","SOURCE_PROP","record","getSourceFromProps","props","registry","JSX_SOURCE_REGISTRY_SYMBOL","intrinsicSource","JSX_SOURCE_PROP","resolveComponentSourceFromFiber","fiber","getDirectDebugSource","debugSource","normalizeSource","projectRoot","match","file","line","col","normalizedFile","normalizedRoot","resolveSourceCandidates","jsxCandidates","componentCandidates","rawJsxSource","jsxSource","getSourceFile","candidate","rawComponentSource","componentSource","direct","nearestProjectLocalComponentFile","isProjectLocalSource","screen","matchingJsxCandidate","matchingComponentCandidate","implementationComponentCandidate","implementationJsxCandidate","projectLocalJsxCandidate","screenFallback","getModeDescription","mode","createStatusOverlay","copyValue","currentMode","hideTimer","show","message","tone","mount","value","locateComponentSource","elementTarget","candidates","enableReactComponentJump","options","overlay","onLocate","result","onError","error","keyHandler","handler"]}
|