@visual-agentic-dev/react-devtools 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # @visual-agentic-dev/react-devtools
2
+
3
+ The React runtime SDK for Visual Agentic Dev. This package provides the connection between your React application and the Visual Dev browser extension.
4
+
5
+ ## Integration
6
+
7
+ ### 1. Install
8
+
9
+ ```bash
10
+ npm install @visual-agentic-dev/react-devtools
11
+ # or
12
+ pnpm add @visual-agentic-dev/react-devtools
13
+ # or
14
+ yarn add @visual-agentic-dev/react-devtools
15
+ ```
16
+
17
+ ### 2. Runtime Setup (Required)
18
+
19
+ Wrap your root application with `DevToolsProvider`:
20
+
21
+ ```tsx
22
+ // App.tsx or main.tsx
23
+ import { DevToolsProvider } from '@visual-agentic-dev/react-devtools';
24
+
25
+ export default function App() {
26
+ return (
27
+ <DevToolsProvider enabled={process.env.NODE_ENV === 'development'}>
28
+ <YourApp />
29
+ </DevToolsProvider>
30
+ );
31
+ }
32
+ ```
33
+
34
+ ## React 19 Support & Source Location
35
+
36
+ For **React 16, 17, and 18**, the runtime SDK can usually detect source location (file path, line number) automatically using React's internal fiber information.
37
+
38
+ For **React 19+**, due to internal changes in React Fiber (removal of `_debugSource`), runtime detection may be unreliable or fail completely.
39
+
40
+ **We strongly recommend configuring the build plugin** to ensure 100% accurate source location detection across all React versions and build tools.
41
+
42
+ ### Build Tool Configuration
43
+
44
+ We provide an **Universal Plugin** (unplugin) that supports Vite, Webpack, Rspack, Rollup, and esbuild.
45
+
46
+ #### Vite
47
+
48
+ ```ts
49
+ // vite.config.ts
50
+ import { defineConfig } from 'vite';
51
+ import { vitePlugin as visualDev } from '@visual-agentic-dev/react-devtools/unplugin';
52
+
53
+ export default defineConfig({
54
+ plugins: [
55
+ // ... other plugins
56
+ visualDev(),
57
+ ],
58
+ });
59
+ ```
60
+
61
+ #### Webpack
62
+
63
+ ```js
64
+ // webpack.config.js
65
+ const { webpackPlugin: visualDev } = require('@visual-agentic-dev/react-devtools/unplugin');
66
+
67
+ module.exports = {
68
+ // ...
69
+ plugins: [
70
+ visualDev(),
71
+ ],
72
+ };
73
+ ```
74
+
75
+ #### Rspack
76
+
77
+ ```js
78
+ // rspack.config.js
79
+ const { rspackPlugin: visualDev } = require('@visual-agentic-dev/react-devtools/unplugin');
80
+
81
+ module.exports = {
82
+ // ...
83
+ plugins: [
84
+ visualDev(),
85
+ ],
86
+ };
87
+ ```
88
+
89
+ #### Next.js (Webpack)
90
+
91
+ ```js
92
+ // next.config.js
93
+ const { webpackPlugin: visualDev } = require('@visual-agentic-dev/react-devtools/unplugin');
94
+
95
+ /** @type {import('next').NextConfig} */
96
+ const nextConfig = {
97
+ webpack: (config) => {
98
+ config.plugins.push(visualDev());
99
+ return config;
100
+ },
101
+ };
102
+
103
+ module.exports = nextConfig;
104
+ ```
105
+
106
+ #### Rollup
107
+
108
+ ```js
109
+ // rollup.config.js
110
+ import { rollupPlugin as visualDev } from '@visual-agentic-dev/react-devtools/unplugin';
111
+
112
+ export default {
113
+ // ...
114
+ plugins: [
115
+ visualDev(),
116
+ ],
117
+ };
118
+ ```
119
+
120
+ ## Options
121
+
122
+ The plugin accepts an options object:
123
+
124
+ ```ts
125
+ visualDev({
126
+ // Filter files to transform
127
+ include: [/\.[jt]sx$/], // default
128
+ exclude: [/node_modules/], // default
129
+
130
+ // Customize the data attribute prefix
131
+ // default: 'vdev' -> data-vdev-file, data-vdev-line
132
+ prefix: 'vdev',
133
+ })
134
+ ```
package/dist/index.d.mts CHANGED
@@ -1,9 +1,10 @@
1
1
  import React, { ReactNode } from 'react';
2
2
 
3
- interface SourceLocation {
3
+ interface SourceLocation$1 {
4
4
  fileName: string;
5
5
  lineNumber: number;
6
6
  columnNumber: number;
7
+ componentName?: string;
7
8
  }
8
9
  interface ElementInfo {
9
10
  tagName: string;
@@ -16,7 +17,7 @@ interface VDevMessage {
16
17
  payload?: unknown;
17
18
  }
18
19
  interface ElementSelectedPayload {
19
- source: SourceLocation;
20
+ source: SourceLocation$1;
20
21
  elementInfo: ElementInfo;
21
22
  }
22
23
 
@@ -24,7 +25,7 @@ interface DevToolsContextValue {
24
25
  isInspecting: boolean;
25
26
  setInspecting: (v: boolean) => void;
26
27
  selectedElement: HTMLElement | null;
27
- selectedSource: SourceLocation | null;
28
+ selectedSource: SourceLocation$1 | null;
28
29
  clearSelection: () => void;
29
30
  }
30
31
  declare const useDevTools: () => DevToolsContextValue;
@@ -56,20 +57,29 @@ interface Props {
56
57
  declare const SelectionBox: React.FC<Props>;
57
58
 
58
59
  /**
59
- * Parse the data-vdev-source attribute value into a SourceLocation object
60
- * (Legacy support for projects using the babel/vite plugin)
60
+ * Source Location Detection Utilities
61
+ * Reference implementation based on:
62
+ * https://github.com/benjitaylor/agentation/blob/main/package/src/utils/source-location.ts
61
63
  */
62
- declare function parseSourceAttr(attrValue: string | null): SourceLocation | null;
64
+ interface SourceLocation {
65
+ fileName: string;
66
+ lineNumber: number;
67
+ columnNumber: number;
68
+ componentName?: string;
69
+ }
63
70
  /**
64
- * Find the closest element with source information
65
- * First tries React Fiber (runtime), then falls back to data attributes
71
+ * Parse the data-vdev-source attribute value (Legacy/Fallback)
66
72
  */
67
- declare function findSourceElement(target: HTMLElement, prefix?: string): HTMLElement | null;
73
+ declare function parseSourceAttr(attrValue: string | null): SourceLocation | null;
68
74
  /**
69
- * Get source location from an element
70
- * Prioritizes React Fiber _debugSource, falls back to data attributes
75
+ * Main function to get source location from an element
76
+ * Combines Fiber inspection and data attribute fallbacks
71
77
  */
72
78
  declare function getSourceFromElement(element: HTMLElement, prefix?: string): SourceLocation | null;
79
+ /**
80
+ * Find the closest element with source information
81
+ */
82
+ declare function findSourceElement(target: HTMLElement, prefix?: string): HTMLElement | null;
73
83
 
74
84
  /**
75
85
  * Send a message to the Chrome extension via window.postMessage
@@ -84,4 +94,4 @@ declare function notifyReady(): void;
84
94
  */
85
95
  declare function createMessageHandler(handler: (message: VDevMessage) => void): (event: MessageEvent) => void;
86
96
 
87
- export { DevToolsProvider, type ElementInfo, type ElementSelectedPayload, Highlighter, SelectionBox, type SourceLocation, type VDevMessage, createMessageHandler, findSourceElement, getSourceFromElement, notifyReady, parseSourceAttr, sendToExtension, useDevTools };
97
+ export { DevToolsProvider, type ElementInfo, type ElementSelectedPayload, Highlighter, SelectionBox, type SourceLocation$1 as SourceLocation, type VDevMessage, createMessageHandler, findSourceElement, getSourceFromElement, notifyReady, parseSourceAttr, sendToExtension, useDevTools };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import React, { ReactNode } from 'react';
2
2
 
3
- interface SourceLocation {
3
+ interface SourceLocation$1 {
4
4
  fileName: string;
5
5
  lineNumber: number;
6
6
  columnNumber: number;
7
+ componentName?: string;
7
8
  }
8
9
  interface ElementInfo {
9
10
  tagName: string;
@@ -16,7 +17,7 @@ interface VDevMessage {
16
17
  payload?: unknown;
17
18
  }
18
19
  interface ElementSelectedPayload {
19
- source: SourceLocation;
20
+ source: SourceLocation$1;
20
21
  elementInfo: ElementInfo;
21
22
  }
22
23
 
@@ -24,7 +25,7 @@ interface DevToolsContextValue {
24
25
  isInspecting: boolean;
25
26
  setInspecting: (v: boolean) => void;
26
27
  selectedElement: HTMLElement | null;
27
- selectedSource: SourceLocation | null;
28
+ selectedSource: SourceLocation$1 | null;
28
29
  clearSelection: () => void;
29
30
  }
30
31
  declare const useDevTools: () => DevToolsContextValue;
@@ -56,20 +57,29 @@ interface Props {
56
57
  declare const SelectionBox: React.FC<Props>;
57
58
 
58
59
  /**
59
- * Parse the data-vdev-source attribute value into a SourceLocation object
60
- * (Legacy support for projects using the babel/vite plugin)
60
+ * Source Location Detection Utilities
61
+ * Reference implementation based on:
62
+ * https://github.com/benjitaylor/agentation/blob/main/package/src/utils/source-location.ts
61
63
  */
62
- declare function parseSourceAttr(attrValue: string | null): SourceLocation | null;
64
+ interface SourceLocation {
65
+ fileName: string;
66
+ lineNumber: number;
67
+ columnNumber: number;
68
+ componentName?: string;
69
+ }
63
70
  /**
64
- * Find the closest element with source information
65
- * First tries React Fiber (runtime), then falls back to data attributes
71
+ * Parse the data-vdev-source attribute value (Legacy/Fallback)
66
72
  */
67
- declare function findSourceElement(target: HTMLElement, prefix?: string): HTMLElement | null;
73
+ declare function parseSourceAttr(attrValue: string | null): SourceLocation | null;
68
74
  /**
69
- * Get source location from an element
70
- * Prioritizes React Fiber _debugSource, falls back to data attributes
75
+ * Main function to get source location from an element
76
+ * Combines Fiber inspection and data attribute fallbacks
71
77
  */
72
78
  declare function getSourceFromElement(element: HTMLElement, prefix?: string): SourceLocation | null;
79
+ /**
80
+ * Find the closest element with source information
81
+ */
82
+ declare function findSourceElement(target: HTMLElement, prefix?: string): HTMLElement | null;
73
83
 
74
84
  /**
75
85
  * Send a message to the Chrome extension via window.postMessage
@@ -84,4 +94,4 @@ declare function notifyReady(): void;
84
94
  */
85
95
  declare function createMessageHandler(handler: (message: VDevMessage) => void): (event: MessageEvent) => void;
86
96
 
87
- export { DevToolsProvider, type ElementInfo, type ElementSelectedPayload, Highlighter, SelectionBox, type SourceLocation, type VDevMessage, createMessageHandler, findSourceElement, getSourceFromElement, notifyReady, parseSourceAttr, sendToExtension, useDevTools };
97
+ export { DevToolsProvider, type ElementInfo, type ElementSelectedPayload, Highlighter, SelectionBox, type SourceLocation$1 as SourceLocation, type VDevMessage, createMessageHandler, findSourceElement, getSourceFromElement, notifyReady, parseSourceAttr, sendToExtension, useDevTools };
package/dist/index.js CHANGED
@@ -83,74 +83,153 @@ var Highlighter = ({
83
83
  var import_react2 = require("react");
84
84
 
85
85
  // src/utils/sourceLocator.ts
86
- function getReactFiber(element) {
87
- const key = Object.keys(element).find(
88
- (k) => k.startsWith("__reactFiber$") || k.startsWith("__reactInternalInstance$")
89
- );
90
- return key ? element[key] : null;
86
+ function getFiberFromElement(element) {
87
+ if (!element || typeof element !== "object") {
88
+ return null;
89
+ }
90
+ const keys = Object.keys(element);
91
+ const fiberKey = keys.find((key) => key.startsWith("__reactFiber$"));
92
+ if (fiberKey) {
93
+ return element[fiberKey];
94
+ }
95
+ const instanceKey = keys.find((key) => key.startsWith("__reactInternalInstance$"));
96
+ if (instanceKey) {
97
+ return element[instanceKey];
98
+ }
99
+ const possibleFiberKey = keys.find((key) => {
100
+ if (!key.startsWith("__react")) return false;
101
+ if (key.startsWith("__reactContainer") || key.startsWith("__reactProps") || key.startsWith("__reactEvents")) return false;
102
+ const value = element[key];
103
+ return value && typeof value === "object" && ("_debugSource" in value || "tag" in value || "return" in value);
104
+ });
105
+ if (possibleFiberKey) {
106
+ return element[possibleFiberKey];
107
+ }
108
+ return null;
91
109
  }
92
- function findFiberWithSource(fiber) {
110
+ function getComponentName(fiber) {
111
+ if (!fiber.type) return null;
112
+ if (typeof fiber.type === "string") return null;
113
+ if (typeof fiber.type === "object" || typeof fiber.type === "function") {
114
+ return fiber.type.displayName || fiber.type.name || null;
115
+ }
116
+ return null;
117
+ }
118
+ function findDebugSource(fiber, maxDepth = 50) {
93
119
  let current = fiber;
94
- while (current) {
120
+ let depth = 0;
121
+ while (current && depth < maxDepth) {
95
122
  if (current._debugSource) {
96
- return current;
123
+ return {
124
+ source: current._debugSource,
125
+ componentName: getComponentName(current)
126
+ };
127
+ }
128
+ if (current._debugOwner?._debugSource) {
129
+ return {
130
+ source: current._debugOwner._debugSource,
131
+ componentName: getComponentName(current._debugOwner)
132
+ };
97
133
  }
98
134
  current = current.return;
135
+ depth++;
99
136
  }
100
137
  return null;
101
138
  }
102
- function getSourceFromFiber(element) {
103
- const fiber = getReactFiber(element);
104
- if (!fiber) return null;
105
- const fiberWithSource = findFiberWithSource(fiber);
106
- if (fiberWithSource?._debugSource) {
107
- const { fileName, lineNumber, columnNumber } = fiberWithSource._debugSource;
108
- return {
109
- fileName,
110
- lineNumber,
111
- columnNumber: columnNumber || 1
112
- };
139
+ function findDebugSourceReact19(fiber) {
140
+ let current = fiber;
141
+ let depth = 0;
142
+ const maxDepth = 50;
143
+ while (current && depth < maxDepth) {
144
+ const anyFiber = current;
145
+ const possibleSourceKeys = ["_debugSource", "__source", "_source", "debugSource", "_debugInfo"];
146
+ for (const key of possibleSourceKeys) {
147
+ const source = anyFiber[key];
148
+ if (source) {
149
+ if (typeof source === "object" && typeof source.fileName === "string") {
150
+ return {
151
+ source,
152
+ componentName: getComponentName(current)
153
+ };
154
+ }
155
+ if (Array.isArray(source)) {
156
+ for (const info of source) {
157
+ if (info && typeof info.fileName === "string") {
158
+ return {
159
+ source: info,
160
+ componentName: getComponentName(current)
161
+ };
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ const props = current.memoizedProps || current.pendingProps;
168
+ if (props && typeof props === "object") {
169
+ if (props.__source && typeof props.__source === "object" && props.__source.fileName) {
170
+ return {
171
+ source: props.__source,
172
+ componentName: getComponentName(current)
173
+ };
174
+ }
175
+ }
176
+ current = current.return;
177
+ depth++;
113
178
  }
114
179
  return null;
115
180
  }
116
181
  function parseSourceAttr(attrValue) {
117
182
  if (!attrValue) return null;
118
183
  try {
119
- const parsed = JSON.parse(attrValue);
120
- if (typeof parsed.fileName === "string" && typeof parsed.lineNumber === "number" && typeof parsed.columnNumber === "number") {
121
- return parsed;
184
+ if (attrValue.startsWith("{")) {
185
+ const parsed = JSON.parse(attrValue);
186
+ if (parsed.fileName && typeof parsed.lineNumber === "number") {
187
+ return parsed;
188
+ }
122
189
  }
123
190
  } catch {
124
191
  }
125
192
  return null;
126
193
  }
194
+ function getSourceFromElement(element, prefix = "vdev") {
195
+ const fiber = getFiberFromElement(element);
196
+ if (fiber) {
197
+ let result = findDebugSource(fiber);
198
+ if (!result) {
199
+ result = findDebugSourceReact19(fiber);
200
+ }
201
+ if (result) {
202
+ return {
203
+ fileName: result.source.fileName,
204
+ lineNumber: result.source.lineNumber,
205
+ columnNumber: result.source.columnNumber || 1,
206
+ componentName: result.componentName || void 0
207
+ };
208
+ }
209
+ }
210
+ const file = element.getAttribute(`data-${prefix}-file`);
211
+ const line = element.getAttribute(`data-${prefix}-line`);
212
+ const col = element.getAttribute(`data-${prefix}-col`);
213
+ if (file && line) {
214
+ return {
215
+ fileName: file,
216
+ lineNumber: parseInt(line, 10),
217
+ columnNumber: col ? parseInt(col, 10) : 1,
218
+ componentName: element.tagName.toLowerCase()
219
+ // Simple fallback
220
+ };
221
+ }
222
+ return null;
223
+ }
127
224
  function findSourceElement(target, prefix = "vdev") {
128
225
  let current = target;
129
226
  while (current && current !== document.body) {
130
- if (getSourceFromFiber(current)) {
227
+ if (getSourceFromElement(current, prefix)) {
131
228
  return current;
132
229
  }
133
230
  current = current.parentElement;
134
231
  }
135
- return target.closest(`[data-${prefix}-file], [data-${prefix}-source]`);
136
- }
137
- function getSourceFromElement(element, prefix = "vdev") {
138
- const fiberSource = getSourceFromFiber(element);
139
- if (fiberSource) {
140
- return fiberSource;
141
- }
142
- const fileName = element.getAttribute(`data-${prefix}-file`);
143
- const lineStr = element.getAttribute(`data-${prefix}-line`);
144
- const colStr = element.getAttribute(`data-${prefix}-col`);
145
- if (fileName && lineStr) {
146
- return {
147
- fileName,
148
- lineNumber: parseInt(lineStr, 10),
149
- columnNumber: colStr ? parseInt(colStr, 10) : 1
150
- };
151
- }
152
- const attrValue = element.getAttribute(`data-${prefix}-source`);
153
- return parseSourceAttr(attrValue);
232
+ return null;
154
233
  }
155
234
 
156
235
  // src/overlay/SelectionBox.tsx
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/DevToolsProvider.tsx","../src/overlay/Highlighter.tsx","../src/overlay/SelectionBox.tsx","../src/utils/sourceLocator.ts","../src/utils/messaging.ts"],"sourcesContent":["// Components\nexport { DevToolsProvider, useDevTools } from './components';\n\n// Overlay (advanced usage)\nexport { Highlighter, SelectionBox } from './overlay';\n\n// Utilities\nexport {\n parseSourceAttr,\n findSourceElement,\n getSourceFromElement\n} from './utils/sourceLocator';\n\nexport {\n sendToExtension,\n notifyReady,\n createMessageHandler\n} from './utils/messaging';\n\n// Types\nexport type {\n SourceLocation,\n ElementInfo,\n VDevMessage,\n ElementSelectedPayload\n} from './types';\n","import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode\n} from 'react';\nimport { Highlighter } from '../overlay/Highlighter';\nimport { SelectionBox } from '../overlay/SelectionBox';\nimport { getSourceFromElement, findSourceElement } from '../utils/sourceLocator';\nimport { sendToExtension, createMessageHandler, notifyReady } from '../utils/messaging';\nimport type { SourceLocation, VDevMessage } from '../types';\n\ninterface DevToolsContextValue {\n isInspecting: boolean;\n setInspecting: (v: boolean) => void;\n selectedElement: HTMLElement | null;\n selectedSource: SourceLocation | null;\n clearSelection: () => void;\n}\n\nconst DevToolsContext = createContext<DevToolsContextValue | null>(null);\n\nexport const useDevTools = () => {\n const context = useContext(DevToolsContext);\n if (!context) {\n throw new Error('useDevTools must be used within a DevToolsProvider');\n }\n return context;\n};\n\ninterface DevToolsProviderProps {\n children: ReactNode;\n /** Only enable in development mode (default: true) */\n enabled?: boolean;\n /** Attribute prefix (default: 'vdev') */\n prefix?: string;\n}\n\nexport const DevToolsProvider: React.FC<DevToolsProviderProps> = ({\n children,\n enabled = true,\n prefix = 'vdev'\n}) => {\n const [isInspecting, setInspecting] = useState(false);\n const [hoveredElement, setHoveredElement] = useState<HTMLElement | null>(null);\n const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(null);\n const [selectedSource, setSelectedSource] = useState<SourceLocation | null>(null);\n\n const clearSelection = useCallback(() => {\n setSelectedElement(null);\n setSelectedSource(null);\n }, []);\n\n // Listen to messages from extension\n useEffect(() => {\n if (!enabled) return;\n\n const handler = createMessageHandler((message: VDevMessage) => {\n console.log('[DevTools] Received message:', message);\n if (message.type === 'VDEV_START_INSPECT') {\n console.log('[DevTools] Starting inspection');\n setInspecting(true);\n clearSelection();\n } else if (message.type === 'VDEV_STOP_INSPECT') {\n console.log('[DevTools] Stopping inspection');\n setInspecting(false);\n setHoveredElement(null);\n } else if (message.type === 'VDEV_TOGGLE_INSPECT') {\n console.log('[DevTools] Toggling inspection');\n setInspecting(prev => {\n const newState = !prev;\n if (newState) {\n // Starting inspection, clear selection\n clearSelection();\n } else {\n // Stopping inspection, clear hovered\n setHoveredElement(null);\n }\n // Notify extension of state change\n sendToExtension({\n type: 'VDEV_INSPECT_STATE_CHANGED',\n payload: { isInspecting: newState }\n });\n return newState;\n });\n } else if (message.type === 'VDEV_CLEAR_SELECTION') {\n clearSelection();\n }\n });\n\n window.addEventListener('message', handler);\n\n // Notify extension that SDK is ready\n notifyReady();\n console.log('[DevTools] SDK Ready, listening for messages');\n\n return () => window.removeEventListener('message', handler);\n }, [enabled, clearSelection]);\n\n // Handle mouse events in inspect mode\n useEffect(() => {\n if (!isInspecting || !enabled) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore our own overlay elements\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n // console.log('[DevTools] Mouse move', target, sourceElement);\n\n if (sourceElement && sourceElement !== hoveredElement) {\n console.log('[DevTools] Hovered element found:', sourceElement);\n setHoveredElement(sourceElement);\n }\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n\n // Ignore clicks on overlay\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n\n if (sourceElement) {\n const source = getSourceFromElement(sourceElement, prefix);\n setSelectedElement(sourceElement);\n setSelectedSource(source);\n setInspecting(false);\n setHoveredElement(null);\n\n // Notify extension of selection\n sendToExtension({\n type: 'VDEV_ELEMENT_SELECTED',\n payload: {\n source,\n elementInfo: {\n tagName: sourceElement.tagName.toLowerCase(),\n className: sourceElement.className,\n textContent: sourceElement.textContent?.slice(0, 100) || '',\n },\n },\n });\n }\n };\n\n // Use capture to intercept before normal handlers\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n\n // Add cursor style\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n };\n }, [isInspecting, enabled, hoveredElement, prefix]);\n\n // Don't render anything if disabled\n if (!enabled) {\n return <>{children}</>;\n }\n\n return (\n <DevToolsContext.Provider\n value={{\n isInspecting,\n setInspecting,\n selectedElement,\n selectedSource,\n clearSelection\n }}\n >\n {children}\n\n {/* Hover highlighter */}\n {isInspecting && hoveredElement && (\n <Highlighter element={hoveredElement} />\n )}\n\n {/* Selection box */}\n {selectedElement && (\n <SelectionBox element={selectedElement} prefix={prefix} />\n )}\n </DevToolsContext.Provider>\n );\n};\n","import React, { useEffect, useState } from 'react';\n\ninterface Props {\n element: HTMLElement;\n color?: string;\n}\n\n/**\n * Highlighter overlay component - shows a blue overlay on hovered elements\n */\nexport const Highlighter: React.FC<Props> = ({\n element,\n color = 'rgba(66, 153, 225, 0.3)'\n}) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n backgroundColor: color,\n border: '2px solid #4299e1',\n pointerEvents: 'none',\n zIndex: 999999,\n transition: 'all 0.1s ease',\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"highlighter\"\n />\n );\n};\n","import React, { useEffect, useState } from 'react';\nimport type { SourceLocation } from '../types';\nimport { getSourceFromElement } from '../utils/sourceLocator';\n\ninterface Props {\n element: HTMLElement;\n prefix?: string;\n}\n\n/**\n * SelectionBox component - shows a persistent selection box with source info label\n */\nexport const SelectionBox: React.FC<Props> = ({ element, prefix = 'vdev' }) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n const [source, setSource] = useState<SourceLocation | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n // Get source info\n setSource(getSourceFromElement(element, prefix));\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element, prefix]);\n\n if (!rect) return null;\n\n // Format file path for display (show only basename)\n const fileName = source?.fileName.split('/').pop() || 'unknown';\n const lineInfo = source ? `${fileName}:${source.lineNumber}` : '';\n\n return (\n <>\n {/* Selection border */}\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n border: '2px solid #6366f1',\n backgroundColor: 'rgba(99, 102, 241, 0.1)',\n pointerEvents: 'none',\n zIndex: 999999,\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"selection\"\n />\n\n {/* Label showing file:line */}\n {lineInfo && (\n <div\n style={{\n position: 'fixed',\n top: Math.max(0, rect.top - 24),\n left: rect.left,\n backgroundColor: '#6366f1',\n color: 'white',\n fontSize: '11px',\n fontFamily: 'monospace',\n padding: '2px 6px',\n borderRadius: '3px',\n pointerEvents: 'none',\n zIndex: 999999,\n whiteSpace: 'nowrap',\n }}\n data-vdev-overlay=\"label\"\n >\n {lineInfo}\n </div>\n )}\n </>\n );\n};\n","import type { SourceLocation } from '../types';\n\n/**\n * Get React Fiber node from DOM element\n * React attaches fiber information to DOM elements with internal keys\n */\nfunction getReactFiber(element: HTMLElement): any {\n const key = Object.keys(element).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (element as any)[key] : null;\n}\n\n/**\n * Walk up the fiber tree to find a fiber with _debugSource\n */\nfunction findFiberWithSource(fiber: any): any {\n let current = fiber;\n while (current) {\n if (current._debugSource) {\n return current;\n }\n current = current.return;\n }\n return null;\n}\n\n/**\n * Get source from React Fiber's _debugSource (runtime detection)\n * This is the preferred method as it doesn't require any build plugin\n */\nexport function getSourceFromFiber(element: HTMLElement): SourceLocation | null {\n const fiber = getReactFiber(element);\n if (!fiber) return null;\n\n const fiberWithSource = findFiberWithSource(fiber);\n if (fiberWithSource?._debugSource) {\n const { fileName, lineNumber, columnNumber } = fiberWithSource._debugSource;\n return {\n fileName,\n lineNumber,\n columnNumber: columnNumber || 1\n };\n }\n return null;\n}\n\n/**\n * Parse the data-vdev-source attribute value into a SourceLocation object\n * (Legacy support for projects using the babel/vite plugin)\n */\nexport function parseSourceAttr(attrValue: string | null): SourceLocation | null {\n if (!attrValue) return null;\n\n try {\n const parsed = JSON.parse(attrValue);\n if (\n typeof parsed.fileName === 'string' &&\n typeof parsed.lineNumber === 'number' &&\n typeof parsed.columnNumber === 'number'\n ) {\n return parsed as SourceLocation;\n }\n } catch {\n // Ignore parse errors\n }\n\n return null;\n}\n\n/**\n * Find the closest element with source information\n * First tries React Fiber (runtime), then falls back to data attributes\n */\nexport function findSourceElement(target: HTMLElement, prefix = 'vdev'): HTMLElement | null {\n // First, try to find source from React Fiber (runtime)\n let current: HTMLElement | null = target;\n while (current && current !== document.body) {\n if (getSourceFromFiber(current)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Fallback: check for data attributes (legacy plugin support)\n return target.closest(`[data-${prefix}-file], [data-${prefix}-source]`) as HTMLElement | null;\n}\n\n/**\n * Get source location from an element\n * Prioritizes React Fiber _debugSource, falls back to data attributes\n */\nexport function getSourceFromElement(element: HTMLElement, prefix = 'vdev'): SourceLocation | null {\n // 1. Try React Fiber _debugSource first (runtime, no plugin needed)\n const fiberSource = getSourceFromFiber(element);\n if (fiberSource) {\n return fiberSource;\n }\n\n // 2. Try new data attribute format (plugin-based)\n const fileName = element.getAttribute(`data-${prefix}-file`);\n const lineStr = element.getAttribute(`data-${prefix}-line`);\n const colStr = element.getAttribute(`data-${prefix}-col`);\n\n if (fileName && lineStr) {\n return {\n fileName,\n lineNumber: parseInt(lineStr, 10),\n columnNumber: colStr ? parseInt(colStr, 10) : 1\n };\n }\n\n // 3. Fallback to legacy format (JSON in single attribute)\n const attrValue = element.getAttribute(`data-${prefix}-source`);\n return parseSourceAttr(attrValue);\n}\n\n","import type { VDevMessage } from '../types';\n\nconst MESSAGE_SOURCE = 'vdev-react-sdk';\n\n/**\n * Send a message to the Chrome extension via window.postMessage\n */\nexport function sendToExtension(message: VDevMessage): void {\n window.postMessage(\n { ...message, source: MESSAGE_SOURCE },\n '*'\n );\n}\n\n/**\n * Notify extension that SDK is ready\n */\nexport function notifyReady(): void {\n sendToExtension({ type: 'VDEV_SDK_READY' });\n}\n\n/**\n * Create a message handler that only processes messages from the extension\n */\nexport function createMessageHandler(\n handler: (message: VDevMessage) => void\n): (event: MessageEvent) => void {\n return (event: MessageEvent) => {\n // Only process messages from the same window\n if (event.source !== window) return;\n\n // Only process messages from extension (not from SDK itself)\n if (event.data?.source === MESSAGE_SOURCE) return;\n\n // Process VDEV messages\n if (event.data?.type?.startsWith('VDEV_')) {\n handler(event.data as VDevMessage);\n }\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/DevToolsProvider.tsx","../src/overlay/Highlighter.tsx","../src/overlay/SelectionBox.tsx","../src/utils/sourceLocator.ts","../src/utils/messaging.ts"],"sourcesContent":["// Components\nexport { DevToolsProvider, useDevTools } from './components';\n\n// Overlay (advanced usage)\nexport { Highlighter, SelectionBox } from './overlay';\n\n// Utilities\nexport {\n parseSourceAttr,\n findSourceElement,\n getSourceFromElement\n} from './utils/sourceLocator';\n\nexport {\n sendToExtension,\n notifyReady,\n createMessageHandler\n} from './utils/messaging';\n\n// Types\nexport type {\n SourceLocation,\n ElementInfo,\n VDevMessage,\n ElementSelectedPayload\n} from './types';\n","import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode\n} from 'react';\nimport { Highlighter } from '../overlay/Highlighter';\nimport { SelectionBox } from '../overlay/SelectionBox';\nimport { getSourceFromElement, findSourceElement } from '../utils/sourceLocator';\nimport { sendToExtension, createMessageHandler, notifyReady } from '../utils/messaging';\nimport type { SourceLocation, VDevMessage } from '../types';\n\ninterface DevToolsContextValue {\n isInspecting: boolean;\n setInspecting: (v: boolean) => void;\n selectedElement: HTMLElement | null;\n selectedSource: SourceLocation | null;\n clearSelection: () => void;\n}\n\nconst DevToolsContext = createContext<DevToolsContextValue | null>(null);\n\nexport const useDevTools = () => {\n const context = useContext(DevToolsContext);\n if (!context) {\n throw new Error('useDevTools must be used within a DevToolsProvider');\n }\n return context;\n};\n\ninterface DevToolsProviderProps {\n children: ReactNode;\n /** Only enable in development mode (default: true) */\n enabled?: boolean;\n /** Attribute prefix (default: 'vdev') */\n prefix?: string;\n}\n\nexport const DevToolsProvider: React.FC<DevToolsProviderProps> = ({\n children,\n enabled = true,\n prefix = 'vdev'\n}) => {\n const [isInspecting, setInspecting] = useState(false);\n const [hoveredElement, setHoveredElement] = useState<HTMLElement | null>(null);\n const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(null);\n const [selectedSource, setSelectedSource] = useState<SourceLocation | null>(null);\n\n const clearSelection = useCallback(() => {\n setSelectedElement(null);\n setSelectedSource(null);\n }, []);\n\n // Listen to messages from extension\n useEffect(() => {\n if (!enabled) return;\n\n const handler = createMessageHandler((message: VDevMessage) => {\n console.log('[DevTools] Received message:', message);\n if (message.type === 'VDEV_START_INSPECT') {\n console.log('[DevTools] Starting inspection');\n setInspecting(true);\n clearSelection();\n } else if (message.type === 'VDEV_STOP_INSPECT') {\n console.log('[DevTools] Stopping inspection');\n setInspecting(false);\n setHoveredElement(null);\n } else if (message.type === 'VDEV_TOGGLE_INSPECT') {\n console.log('[DevTools] Toggling inspection');\n setInspecting(prev => {\n const newState = !prev;\n if (newState) {\n // Starting inspection, clear selection\n clearSelection();\n } else {\n // Stopping inspection, clear hovered\n setHoveredElement(null);\n }\n // Notify extension of state change\n sendToExtension({\n type: 'VDEV_INSPECT_STATE_CHANGED',\n payload: { isInspecting: newState }\n });\n return newState;\n });\n } else if (message.type === 'VDEV_CLEAR_SELECTION') {\n clearSelection();\n }\n });\n\n window.addEventListener('message', handler);\n\n // Notify extension that SDK is ready\n notifyReady();\n console.log('[DevTools] SDK Ready, listening for messages');\n\n return () => window.removeEventListener('message', handler);\n }, [enabled, clearSelection]);\n\n // Handle mouse events in inspect mode\n useEffect(() => {\n if (!isInspecting || !enabled) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore our own overlay elements\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n // console.log('[DevTools] Mouse move', target, sourceElement);\n\n if (sourceElement && sourceElement !== hoveredElement) {\n console.log('[DevTools] Hovered element found:', sourceElement);\n setHoveredElement(sourceElement);\n }\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n\n // Ignore clicks on overlay\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n\n if (sourceElement) {\n const source = getSourceFromElement(sourceElement, prefix);\n setSelectedElement(sourceElement);\n setSelectedSource(source);\n setInspecting(false);\n setHoveredElement(null);\n\n // Notify extension of selection\n sendToExtension({\n type: 'VDEV_ELEMENT_SELECTED',\n payload: {\n source,\n elementInfo: {\n tagName: sourceElement.tagName.toLowerCase(),\n className: sourceElement.className,\n textContent: sourceElement.textContent?.slice(0, 100) || '',\n },\n },\n });\n }\n };\n\n // Use capture to intercept before normal handlers\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n\n // Add cursor style\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n };\n }, [isInspecting, enabled, hoveredElement, prefix]);\n\n // Don't render anything if disabled\n if (!enabled) {\n return <>{children}</>;\n }\n\n return (\n <DevToolsContext.Provider\n value={{\n isInspecting,\n setInspecting,\n selectedElement,\n selectedSource,\n clearSelection\n }}\n >\n {children}\n\n {/* Hover highlighter */}\n {isInspecting && hoveredElement && (\n <Highlighter element={hoveredElement} />\n )}\n\n {/* Selection box */}\n {selectedElement && (\n <SelectionBox element={selectedElement} prefix={prefix} />\n )}\n </DevToolsContext.Provider>\n );\n};\n","import React, { useEffect, useState } from 'react';\n\ninterface Props {\n element: HTMLElement;\n color?: string;\n}\n\n/**\n * Highlighter overlay component - shows a blue overlay on hovered elements\n */\nexport const Highlighter: React.FC<Props> = ({\n element,\n color = 'rgba(66, 153, 225, 0.3)'\n}) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n backgroundColor: color,\n border: '2px solid #4299e1',\n pointerEvents: 'none',\n zIndex: 999999,\n transition: 'all 0.1s ease',\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"highlighter\"\n />\n );\n};\n","import React, { useEffect, useState } from 'react';\nimport type { SourceLocation } from '../types';\nimport { getSourceFromElement } from '../utils/sourceLocator';\n\ninterface Props {\n element: HTMLElement;\n prefix?: string;\n}\n\n/**\n * SelectionBox component - shows a persistent selection box with source info label\n */\nexport const SelectionBox: React.FC<Props> = ({ element, prefix = 'vdev' }) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n const [source, setSource] = useState<SourceLocation | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n // Get source info\n setSource(getSourceFromElement(element, prefix));\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element, prefix]);\n\n if (!rect) return null;\n\n // Format file path for display (show only basename)\n const fileName = source?.fileName.split('/').pop() || 'unknown';\n const lineInfo = source ? `${fileName}:${source.lineNumber}` : '';\n\n return (\n <>\n {/* Selection border */}\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n border: '2px solid #6366f1',\n backgroundColor: 'rgba(99, 102, 241, 0.1)',\n pointerEvents: 'none',\n zIndex: 999999,\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"selection\"\n />\n\n {/* Label showing file:line */}\n {lineInfo && (\n <div\n style={{\n position: 'fixed',\n top: Math.max(0, rect.top - 24),\n left: rect.left,\n backgroundColor: '#6366f1',\n color: 'white',\n fontSize: '11px',\n fontFamily: 'monospace',\n padding: '2px 6px',\n borderRadius: '3px',\n pointerEvents: 'none',\n zIndex: 999999,\n whiteSpace: 'nowrap',\n }}\n data-vdev-overlay=\"label\"\n >\n {lineInfo}\n </div>\n )}\n </>\n );\n};\n","/**\n * Source Location Detection Utilities\n * Reference implementation based on:\n * https://github.com/benjitaylor/agentation/blob/main/package/src/utils/source-location.ts\n */\n\nexport interface SourceLocation {\n fileName: string;\n lineNumber: number;\n columnNumber: number;\n componentName?: string;\n}\n\n/**\n * React Fiber node structure (partial)\n */\ninterface ReactFiber {\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber?: number;\n };\n _debugOwner?: ReactFiber;\n _debugInfo?: any; // React 19 specific\n type?: {\n displayName?: string;\n name?: string;\n } | string | any;\n tag?: number;\n return?: ReactFiber | null;\n memoizedProps?: Record<string, any>;\n pendingProps?: Record<string, any>;\n}\n\n/**\n * Gets the React fiber node associated with a DOM element\n */\nfunction getFiberFromElement(element: HTMLElement): ReactFiber | null {\n if (!element || typeof element !== \"object\") {\n return null;\n }\n\n const keys = Object.keys(element);\n\n // React 18+ uses __reactFiber$ prefix\n const fiberKey = keys.find((key) => key.startsWith(\"__reactFiber$\"));\n if (fiberKey) {\n return (element as any)[fiberKey];\n }\n\n // React 16-17 uses __reactInternalInstance$ prefix\n const instanceKey = keys.find((key) => key.startsWith(\"__reactInternalInstance$\"));\n if (instanceKey) {\n return (element as any)[instanceKey];\n }\n\n // React 19 may use different patterns - check for any fiber-like object\n // that contains _debugSource, or looks like a fiber\n const possibleFiberKey = keys.find((key) => {\n if (!key.startsWith(\"__react\")) return false;\n // Avoid known non-fiber keys\n if (key.startsWith(\"__reactContainer\") || key.startsWith(\"__reactProps\") || key.startsWith(\"__reactEvents\")) return false;\n\n const value = (element as any)[key];\n return value && typeof value === \"object\" &&\n (\"_debugSource\" in value || \"tag\" in value || \"return\" in value);\n });\n\n if (possibleFiberKey) {\n return (element as any)[possibleFiberKey];\n }\n\n return null;\n}\n\n/**\n * Gets the display name of a React component from its fiber\n */\nfunction getComponentName(fiber: ReactFiber): string | null {\n if (!fiber.type) return null;\n if (typeof fiber.type === \"string\") return null;\n\n if (typeof fiber.type === \"object\" || typeof fiber.type === \"function\") {\n return fiber.type.displayName || fiber.type.name || null;\n }\n return null;\n}\n\n/**\n * Walks up the fiber tree to find the nearest component with _debugSource\n * (Standard React 16-18)\n */\nfunction findDebugSource(fiber: ReactFiber, maxDepth = 50): { source: NonNullable<ReactFiber[\"_debugSource\"]>; componentName: string | null } | null {\n let current: ReactFiber | null | undefined = fiber;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n if (current._debugSource) {\n return {\n source: current._debugSource,\n componentName: getComponentName(current),\n };\n }\n\n if (current._debugOwner?._debugSource) {\n return {\n source: current._debugOwner._debugSource,\n componentName: getComponentName(current._debugOwner),\n };\n }\n\n current = current.return;\n depth++;\n }\n\n return null;\n}\n\n/**\n * Attempts to find source location using React 19's potentially different structure\n * or alternative build tool injections\n */\nfunction findDebugSourceReact19(fiber: ReactFiber): { source: NonNullable<ReactFiber[\"_debugSource\"]>; componentName: string | null } | null {\n let current: ReactFiber | null | undefined = fiber;\n let depth = 0;\n const maxDepth = 50;\n\n while (current && depth < maxDepth) {\n const anyFiber = current as any;\n\n // 1. Check for valid keys on the fiber itself\n const possibleSourceKeys = [\"_debugSource\", \"__source\", \"_source\", \"debugSource\", \"_debugInfo\"];\n for (const key of possibleSourceKeys) {\n const source = anyFiber[key];\n if (source) {\n // Handle standard object with fileName\n if (typeof source === \"object\" && typeof source.fileName === 'string') {\n return {\n source: source,\n componentName: getComponentName(current),\n };\n }\n // Handle React 19 _debugInfo array\n if (Array.isArray(source)) {\n for (const info of source) {\n if (info && typeof info.fileName === 'string') {\n return {\n source: info,\n componentName: getComponentName(current)\n };\n }\n }\n }\n }\n }\n\n // 2. Check memoizedProps/pendingProps for injected __source\n const props = current.memoizedProps || current.pendingProps;\n if (props && typeof props === 'object') {\n if (props.__source && typeof props.__source === 'object' && props.__source.fileName) {\n return {\n source: props.__source as any,\n componentName: getComponentName(current)\n };\n }\n }\n\n current = current.return;\n depth++;\n }\n\n return null;\n}\n\n/**\n * Parse the data-vdev-source attribute value (Legacy/Fallback)\n */\nexport function parseSourceAttr(attrValue: string | null): SourceLocation | null {\n if (!attrValue) return null;\n try {\n // Try parsing JSON first\n if (attrValue.startsWith('{')) {\n const parsed = JSON.parse(attrValue);\n if (parsed.fileName && typeof parsed.lineNumber === 'number') {\n return parsed as SourceLocation;\n }\n }\n } catch { }\n return null;\n}\n\n/**\n * Main function to get source location from an element\n * Combines Fiber inspection and data attribute fallbacks\n */\nexport function getSourceFromElement(element: HTMLElement, prefix = 'vdev'): SourceLocation | null {\n // 1. Try React Fiber (Runtime)\n const fiber = getFiberFromElement(element);\n if (fiber) {\n // Try standard strategy\n let result = findDebugSource(fiber);\n\n // Try React 19 strategy if standard failed\n if (!result) {\n result = findDebugSourceReact19(fiber);\n }\n\n if (result) {\n return {\n fileName: result.source.fileName,\n lineNumber: result.source.lineNumber,\n columnNumber: result.source.columnNumber || 1,\n componentName: result.componentName || undefined\n };\n }\n }\n\n // 2. Fallback: Data attributes (Build-time plugin)\n // Check for explicit individual attributes from vite-plugin\n const file = element.getAttribute(`data-${prefix}-file`);\n const line = element.getAttribute(`data-${prefix}-line`);\n const col = element.getAttribute(`data-${prefix}-col`);\n\n if (file && line) {\n return {\n fileName: file,\n lineNumber: parseInt(line, 10),\n columnNumber: col ? parseInt(col, 10) : 1,\n componentName: element.tagName.toLowerCase() // Simple fallback\n };\n }\n\n return null;\n}\n\n/**\n * Find the closest element with source information\n */\nexport function findSourceElement(target: HTMLElement, prefix = 'vdev'): HTMLElement | null {\n let current: HTMLElement | null = target;\n\n // Check up to Body\n while (current && current !== document.body) {\n // Check if this element has source info via Fiber OR Attributes\n if (getSourceFromElement(current, prefix)) {\n return current;\n }\n current = current.parentElement;\n }\n\n return null;\n}\n","import type { VDevMessage } from '../types';\n\nconst MESSAGE_SOURCE = 'vdev-react-sdk';\n\n/**\n * Send a message to the Chrome extension via window.postMessage\n */\nexport function sendToExtension(message: VDevMessage): void {\n window.postMessage(\n { ...message, source: MESSAGE_SOURCE },\n '*'\n );\n}\n\n/**\n * Notify extension that SDK is ready\n */\nexport function notifyReady(): void {\n sendToExtension({ type: 'VDEV_SDK_READY' });\n}\n\n/**\n * Create a message handler that only processes messages from the extension\n */\nexport function createMessageHandler(\n handler: (message: VDevMessage) => void\n): (event: MessageEvent) => void {\n return (event: MessageEvent) => {\n // Only process messages from the same window\n if (event.source !== window) return;\n\n // Only process messages from extension (not from SDK itself)\n if (event.data?.source === MESSAGE_SOURCE) return;\n\n // Process VDEV messages\n if (event.data?.type?.startsWith('VDEV_')) {\n handler(event.data as VDevMessage);\n }\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_jsx_runtime"]}