### Run Next.js example
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Start the Next.js example in development mode.
```shell
cd apps/next
pnpm dev
```
--------------------------------
### Run Create React App example
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Start the Create React App example.
```shell
cd apps/cra
pnpm start
```
--------------------------------
### Install with npm
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Install the click-to-react-component package using npm.
```shell
npm install click-to-react-component
```
--------------------------------
### Install with pnpm
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Install the click-to-react-component package using pnpm.
```shell
pnpm add click-to-react-component
```
--------------------------------
### Install dependencies
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Install project dependencies using pnpm.
```shell
pnpm install
```
--------------------------------
### Install with yarn
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Install the click-to-react-component package using yarn.
```shell
yarn add click-to-react-component
```
--------------------------------
### Run the development server with npm or yarn
Source: https://github.com/ericclemmons/click-to-component/blob/main/apps/next/README.md
Start the Next.js development server using either npm run dev or yarn dev. After running, open http://localhost:3000 to view the app.
```bash
npm run dev
# or
yarn dev
```
--------------------------------
### Example: getSourceForInstance usage
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Example usage of getSourceForInstance with getReactInstancesForElement. Shows how to obtain the leaf instance and then the source object. The comment shows the expected result shape.
```js
import { getReactInstancesForElement } from './getReactInstancesForElement.js'
import { getSourceForInstance } from './getSourceForInstance.js'
const [leafInstance] = getReactInstancesForElement(someElement)
const source = getSourceForInstance(leafInstance)
// source === { fileName: '/Users/me/app/src/App.js', lineNumber: 12, columnNumber: 34 }
```
--------------------------------
### getPathToSource usage example
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Shows how to call `getPathToSource` with and without a `pathModifier`. The first call returns the full path; the second strips the `/app/` prefix.
```js
import { getPathToSource } from './getPathToSource.js'
const source = { fileName: '/app/src/Button.tsx', lineNumber: 7, columnNumber: 2 }
getPathToSource(source) // '/app/src/Button.tsx:7:2'
getPathToSource(source, (p) => p.replace('/app/', '')) // 'src/Button.tsx:7:2'
```
--------------------------------
### getPropsForInstance usage example
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Usage example for getPropsForInstance. Imports the function and calls it with a fiber, producing a compact object of scalar props (e.g., { children: 'Submit', disabled: false }). The result is rendered by ContextMenu as {key} elements inside the menu item's .
```javascript
import { getPropsForInstance } from './getPropsForInstance.js'
const props = getPropsForInstance(fiber)
// e.g. { children: 'Submit', disabled: false }
```
--------------------------------
### Docusaurus Babel configuration
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Install the Babel plugin and configure it in babel.config.js to enable JSX source for development.
```shell
npm install @babel/plugin-transform-react-jsx-source
```
```js
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
plugins: [
...(process.env.BABEL_ENV === 'development'
? ['@babel/plugin-transform-react-jsx-source']
: []),
],
};
```
--------------------------------
### getUrl usage example
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Demonstrates `getUrl` with two editor schemes and path styles. The first uses a leading slash, the second does not. The result is meant to be passed to `window.location.assign(url)`; there is no validation of the scheme or path.
```js
import { getUrl } from './getUrl.js'
getUrl({ editor: 'vscode', pathToSource: '/app/src/App.tsx:9:3' })
// 'vscode://file/app/src/App.tsx:9:3'
getUrl({ editor: 'cursor', pathToSource: 'src/App.tsx:9:3' })
// 'cursor://file/src/App.tsx:9:3'
```
--------------------------------
### Usage example for getReactInstanceForElement
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Shows how to call `getReactInstanceForElement` with a DOM element and access fiber properties like `_debugOwner`, `_debugSource`, `tag`, and `memoizedProps` when a fiber is found.
```js
import { getReactInstanceForElement } from './getReactInstanceForElement.js'
const fiber = getReactInstanceForElement(document.querySelector('[data-foo]'))
if (fiber) {
// fiber._debugOwner, fiber._debugSource, fiber.tag, fiber.memoizedProps are available
}
```
--------------------------------
### getReactInstancesForElement usage example
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Shows how to call getReactInstancesForElement with a DOM element, such as a button, to obtain its fiber owner chain.
```js
import { getReactInstancesForElement } from './getReactInstancesForElement.js'
const chain = getReactInstancesForElement(document.querySelector('button'))
```
--------------------------------
### getUrl signature
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Builds an `editor://` deep-link URL from an editor scheme and a `file:line:column` path. If `pathToSource` starts with `/`, it returns `${editor}://file${pathToSource}`; otherwise it inserts a slash after `file`. The leading-slash branch works around microsoft/vscode#197319.
```js
export function getUrl({ editor, pathToSource }) {
// Fix https://github.com/microsoft/vscode/issues/197319
if (pathToSource[0] === '/') {
return `${editor}://file${pathToSource}`
}
return `${editor}://file/${pathToSource}`
}
```
--------------------------------
### getReactInstancesForElement function implementation
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Walks the fiber owner chain starting from the element's own fiber, collecting each _debugOwner until the chain ends. Returns a de-duplicated array in owner-chain order (own fiber first), or an empty array when the element resolves to no fiber.
```js
export function getReactInstancesForElement(
/** @type {HTMLElement} */
element
) {
/** @type {Set} */
const instances = new Set()
let instance = getReactInstanceForElement(element)
while (instance) {
instances.add(instance)
instance = instance._debugOwner
}
return Array.from(instances)
}
```
--------------------------------
### Go to project directory
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Change into the project directory.
```shell
cd click-to-component
```
--------------------------------
### Clone the project
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Clone the click-to-component repository using GitHub CLI.
```shell
gh repo clone ericclemmons/click-to-component
```
--------------------------------
### getReactInstanceForElement implementation
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Resolves the nearest React fiber for a DOM element. Prefers the React DevTools hook, then `_reactRootContainer`, then element own properties starting with `__reactInternalInstance$` or `__reactFiber`. Returns `undefined` when nothing matches.
```js
export function getReactInstanceForElement(element) {
// Prefer React DevTools, which has direct access to `react-dom` for mapping `element` <=> Fiber
if ('__REACT_DEVTOOLS_GLOBAL_HOOK__' in window) {
// @ts-expect-error - TS2339 - Property '__REACT_DEVTOOLS_GLOBAL_HOOK__' does not exist on type 'Window & typeof globalThis'.
const { renderers } = window.__REACT_DEVTOOLS_GLOBAL_HOOK__
for (const renderer of renderers.values()) {
try {
const fiber = renderer.findFiberByHostInstance(element)
if (fiber) {
return fiber
}
} catch (e) {
// If React is mid-render, references to previous nodes may disappear during the click events
// (This is especially true for interactive elements, like menus)
}
}
}
if ('_reactRootContainer' in element) {
// @ts-expect-error - TS2339 - Property '_reactRootContainer' does not exist on type 'HTMLElement'.
return element._reactRootContainer._internalRoot.current.child
}
// eslint-disable-next-line guard-for-in
for (const key in element) {
// Pre-Fiber access React internals
if (key.startsWith('__reactInternalInstance$')) {
return element[key]
}
// Fiber access to React internals
if (key.startsWith('__reactFiber')) {
return element[key]
}
}
}
```
--------------------------------
### Basic usage in Create React App
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
Basic usage in a Create React App, mirroring apps/cra/src/index.js. Renders ClickToComponent inside React.StrictMode alongside the App component.
```jsx
import { ClickToComponent } from 'click-to-react-component';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
```
--------------------------------
### Use ClickToComponent with editor="vscode"
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ContextMenu.md
Used implicitly through ClickToComponent, which mounts ContextMenu inside a FloatingPortal. Hold Alt and right-click an element to see the menu listing parent components with their props and line:column; click an entry to open it in the editor.
```jsx
import { ClickToComponent } from 'click-to-react-component'
function App() {
return (
<>
>
)
}
```
--------------------------------
### CSS custom properties for ClickToComponent.js (click-to-component-style)
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/configuration.md
Default styles injected by ClickToComponent.js (keyed click-to-component-style). The first rule restores pointer-events for descendants of [data-click-to-component]; the second sets cursor and outline on the target element using custom properties. The override example shows how to customize the cursor and outline by setting the custom properties on :root.
```css
[data-click-to-component] * {
pointer-events: auto !important;
}
[data-click-to-component-target] {
cursor: var(--click-to-component-cursor, context-menu) !important;
outline: auto 1px;
outline: var(
--click-to-component-outline,
-webkit-focus-ring-color auto 1px
) !important;
}
```
```css
:root {
--click-to-component-cursor: crosshair;
--click-to-component-outline: 2px solid rebeccapurple;
}
```
--------------------------------
### Click navigation URL construction
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
Builds the editor URL from the resolved source path and the configured editor and pathModifier. This is used during click navigation and when the context menu closes.
```javascript
const path = getPathToSource(source, pathModifier)
const url = getUrl({ editor, pathToSource: path })
```
--------------------------------
### getSourceForElement function source
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Exact source of getSourceForElement and its helper getFirstParentElementWithSource. The function resolves a source for an HTMLElement by getting its React instance and source, falling back to the nearest ancestor with a source. If no parent remains, it throws an Error('No parent found for element'). Note the recursion in the else branch re-passes the original element, not the parent, which may cause repeated inspection of the same parent and eventual throw.
```javascript
export function getSourceForElement(
/**
* @type {HTMLElement}
*/
element
) {
const instance = getReactInstanceForElement(element)
const source = getSourceForInstance(instance)
if (source) return source
const fallbackSource = getFirstParentElementWithSource(element)
return fallbackSource
}
function getFirstParentElementWithSource(element) {
const parentElement = element.parentElement
if (parentElement === null) {
console.warn("Couldn't find a React instance for the element", element)
throw new Error('No parent found for element')
}
const instance = getReactInstanceForElement(parentElement)
const source = getSourceForInstance(instance)
if (source) return source
else return getFirstParentElementWithSource(element)
}
```
--------------------------------
### Compute menu item data for each React instance
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ContextMenu.md
For each React instance of the target that has a source, these values are computed to render a menu item button. The path is used as the submit value (file:line:column string).
```javascript
const name = getDisplayNameForInstance(instance)
const source = getSourceForInstance(instance)
const path = getPathToSource(source, pathModifier)
const props = getPropsForInstance(instance)
```
--------------------------------
### Docusaurus Root component
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Customize the Root component in src/theme/Root.js to include ClickToComponent.
```js
import { ClickToComponent } from 'click-to-react-component';
import React from 'react';
// Default implementation, that you can customize
export default function Root({ children }) {
return (
<>
{children}
>
);
}
```
--------------------------------
### Usage in Create React App
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Add the ClickToComponent component to the root render in a Create React App project. The diff shows adding the import and the component inside React.StrictMode.
```diff
+import { ClickToComponent } from 'click-to-react-component';
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
@@ -8,7 +7,6 @@ import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
+
);
```
--------------------------------
### Import ClickToComponent
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
Import the ClickToComponent component from the click-to-react-component package. This is the primary way to use the component in a React application.
```js
import { ClickToComponent } from 'click-to-react-component'
```
--------------------------------
### onContextMenu handler for Alt+contextmenu
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ContextMenu.md
Document-level contextmenu listener registered via useEffect. Only Alt+contextmenu opens the menu; the anchor is a zero-size rect at e.clientX/e.clientY. The captured HTMLElement becomes the target whose React instances are listed.
```javascript
function onContextMenu(e) {
if (!e.altKey) {
return
}
e.preventDefault()
mergedReferenceRef({ getBoundingClientRect() { /* cursor point rect */ } })
setOpen(true)
if (e.target instanceof HTMLElement) setTarget(e.target)
}
```
--------------------------------
### getSourceForInstance - extract source from fiber
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/source-helpers.md
Exact signature of getSourceForInstance from packages/click-to-react-component/src/getSourceForInstance.js (line 9). Returns undefined if instance._debugSource is falsy; otherwise returns a normalized copy with columnNumber and lineNumber defaulting to 1. Uses @ts-ignore because columnNumber is absent from the published Source type.
```js
/**
* @param {Fiber} instance
*/
export function getSourceForInstance(instance) {
if (!instance._debugSource) {
return
}
const {
// It _does_ exist!
// @ts-ignore Property 'columnNumber' does not exist on type 'Source'.ts(2339)
columnNumber = 1,
fileName,
lineNumber = 1,
} = instance._debugSource
return { columnNumber, fileName, lineNumber }
}
```
--------------------------------
### Set editor to vscode-insiders
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Change the editor prop to 'vscode-insiders' to use Visual Studio Code Insiders.
```diff
-
+
```
--------------------------------
### Usage in Next.js
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Add the ClickToComponent component to the custom App component in a Next.js project. The diff shows adding the import and the component inside the fragment.
```diff
+import { ClickToComponent } from 'click-to-react-component'
import type { AppProps } from 'next/app'
import '../styles/globals.css'
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
+
>
)
```
--------------------------------
### getPropsForInstance implementation
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/react-instance-helpers.md
Exact implementation of getPropsForInstance from packages/click-to-react-component/src/getPropsForInstance.js (line 9). It reads instance.memoizedProps and instance.type.defaultProps (guarded with optional chaining), dropping the 'key' prop and any prop equal to its default, and keeping only scalar primitives (string, number, boolean, symbol) and their wrapper instances. Returns a new object typed as Fiber['pendingProps'].
```javascript
export function getPropsForInstance(instance) {
/**
* @type {Fiber['pendingProps']}
*/
const props = {}
Object.entries(instance.memoizedProps).forEach(([key, value]) => {
const type = typeof value
// Ignore some values, even if they're scalar, because they're not unique enough
if (['key'].includes(key) || value === instance.type.defaultProps?.[key]) {
return
}
// Scalar values
if (
['string', 'number', 'boolean', 'symbol'].includes(type) ||
value instanceof String ||
value instanceof Number ||
value instanceof Boolean ||
value instanceof Symbol
) {
props[key] = value
}
})
return props
}
```
--------------------------------
### ClickToComponent
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
The ClickToComponent component is the main export of the click-to-react-component package. It renders a development-only overlay that watches window-level mouse/keyboard events and navigates the browser to an editor URL pointing at the source of the React component responsible for the hovered element. In production builds, it renders nothing.
```APIDOC
## ClickToComponent
### Description
Renders a development-only overlay that watches window-level mouse/keyboard events and navigates the browser to an editor URL pointing at the source of the React component responsible for the hovered element.
### Import
```js
import { ClickToComponent } from 'click-to-react-component'
```
### Behavior
| Condition | Behavior |
|---|---|
| `process.env.NODE_ENV === 'development'` | Functional component that renders the overlay |
| any other value (e.g. `production`) | No-op returning `null` |
### Production Behavior
In production builds the export renders nothing, and because the package declares `"sideEffects": false`, bundlers can tree-shake the entire implementation.
### Source Files
- Root re-export: `packages/click-to-react-component/src/index.js` (lines 1–4)
- Implementation: `packages/click-to-react-component/src/ClickToComponent.js` (line 25)
```
--------------------------------
### Basic usage in Next.js pages router
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
Basic usage in a Next.js pages router, mirroring apps/next/pages/_app.tsx. Passes the editor from the NEXT_PUBLIC_CTC_EDITOR environment variable.
```tsx
import { ClickToComponent } from 'click-to-react-component'
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
>
)
}
```
--------------------------------
### Integrate pathModifier with editor="vscode-insiders"
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ContextMenu.md
Integrates pathModifier to convert absolute paths to repo-relative ones. The modified string becomes the menu button value and is passed to onClose/navigation, so it must be a filesystem path acceptable to getUrl; the empty string would produce a malformed URL (no validation is performed).
```tsx
import { ClickToComponent } from 'click-to-react-component'
// Relative-ize paths coming from absolute monorepo roots.
const toRepoRelative = (path: string) => path.replace(`${process.cwd()}/`, '')
function App() {
return
}
```
--------------------------------
### ContextMenu component signature (ContextMenu.js line 33)
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ContextMenu.md
Exact source of the ContextMenu component, created with React.forwardRef. The ref is merged with the floating element's reference ref via react-merge-refs inside a useMemo and used to position the menu at the cursor on Alt+contextmenu.
```javascript
// @ts-expect-error
export const ContextMenu = React.forwardRef((props, ref) => {
// @ts-expect-error
const { onClose, pathModifier } = props
```
--------------------------------
### Complete type-declaration file (types.d.ts)
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/types.md
Complete type-declaration file for click-to-react-component. Defines Editor, PathModifier, ClickToComponentProps, Coords, Target, and ContextMenuProps, plus the ClickToComponent function overload. The Editor type includes 'vscode', 'vscode-insiders', 'cursor', and a string union widening for custom editors.
```ts
import * as React from 'react'
export type Editor = 'vscode' | 'vscode-insiders' | 'cursor' | (string & {})
export type PathModifier = (path: string) => string
declare function ClickToComponent(props: ClickToComponentProps): React.ReactElement
export type ClickToComponentProps = {
editor?: Editor
pathModifier?: PathModifier
}
export type Coords = [MouseEvent['pageX'], MouseEvent['pageY']]
export type Target = HTMLElement
export type ContextMenuProps = {
onClose?: () => void
pathModifier?: PathModifier
}
```
--------------------------------
### Usage in Vite
Source: https://github.com/ericclemmons/click-to-component/blob/main/packages/click-to-react-component/README.md
Add the ClickToComponent component to the root render in a Vite project. The diff shows adding the import and the component inside React.StrictMode.
```diff
+import { ClickToComponent } from "click-to-react-component";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root")!).render(
+
);
```
--------------------------------
### Non-trivial usage with explicit editor and pathModifier
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
Non-trivial usage with an explicit editor ("cursor") and a pathModifier that converts absolute paths to workspace-relative before opening the editor.
```tsx
import { ClickToComponent } from 'click-to-react-component'
// Convert absolute paths to workspace-relative before opening the editor.
const stripWorkspacePrefix = (path: string) => path.replace(/^\/workspace\//, '')
function App() {
return (
<>
>
)
}
```
--------------------------------
### ClickToComponent return JSX (htm template)
Source: https://github.com/ericclemmons/click-to-component/blob/main/_autodocs/api-reference/ClickToComponent.md
The JSX structure returned by the component, using the htm template helper. It renders a style element and a FloatingPortal containing a ContextMenu component.
```javascript
return html`
<${FloatingPortal} key="click-to-component-portal">
${html`<${ContextMenu} key="click-to-component-contextmenu"
onClose=${onClose}
pathModifier=${pathModifier}
/>`}
${FloatingPortal}>
`
```