Repository: react
Issue: [Devtools Feature]:let devtool component picker to spport custom renderer which runs on web
Labels: Type: Feature Request,Component: Developer Tools,Component: Reconciler

I develop a custom renderer `egreact`, it's a custom renderer for egret , egret is a game engine depend on canvas.

Thanks for `injectIntoDevTools` that users can view components tree by react devtool easily.But unfortunately, `injectIntoDevTools` does't provide an interface for picking a custom renderer component.

To support it, i read the source code of devtool and tried writing some inject code. Fortunately, it works well!

![https://user-images.githubusercontent.com/48762792/174010546-94a2c99c-b0ea-402e-9d3b-2feb7c1ea104.gif](https://user-images.githubusercontent.com/48762792/174010546-94a2c99c-b0ea-402e-9d3b-2feb7c1ea104.gif)

**Here is what i did mainly:**

**1.intercept `window.listener`**

```tsx
// @link https://github.com/facebook/react/blob/c3d7a7e3d72937443ef75b7e29335c98ad0f1424/packages/react-devtools-shared/src/backend/views/Highlighter/index.js#L41
function registerListenersOnWindow(window) {
    // This plug-in may run in non-DOM environments (e.g. React Native).
    if (window && typeof window.addEventListener === 'function') {
      window.addEventListener('click', onClick, true);
      window.addEventListener('mousedown', onMouseEvent, true);
      window.addEventListener('mouseover', onMouseEvent, true);
      window.addEventListener('mouseup', onMouseEvent, true);
      window.addEventListener('pointerdown', onPointerDown, true);
      window.addEventListener('pointerover', onPointerOver, true);
      window.addEventListener('pointerup', onPointerUp, true);
    }
  }
```

 [my code](https://github.com/xingxinglieo/egreact/blob/a6214979274e29f6252f8aaacb2a86806e688db3/packages/core/src/devtool.ts#L122), intercept `window.listener` to judge is the point  in the canvas, if true, mock an event which target is game engine instance.

```tsx
const proxyHandler: EventHandler = function (e: MouseEvent) {
        const { pageX: x, pageY: y } = e
        const r = getCanvas().getBoundingClientRect()
        r.x += window.scrollX
        r.y += window.scrollY
        // to judge is mouse envent ponit in canvas
        if (x > r.x && x < r.x + r.width && y > r.y && y < r.y + r.height) {
          const scale = caculateScale()
          const target = findTargetByPosition(
            egret.lifecycle.stage,
            (x - r.x) / scale,
            (y - r.y) / scale,
          ) as any
          // mock a new event, change target to egret instance, because e.target is read only
          e = {
            ...e,
            preventDefault: e.preventDefault.bind(e),
            stopPropagation: e.stopPropagation.bind(e),
            target,
          }
}
```

**2.proxy `window.getComputedStyle`** 

```tsx
/**
 * @description proxy window.getComputedStyle，let it can handle game engine instance
 * @link https://github.com/facebook/react/blob/29c2c633159cb2171bb04fe84b9caa09904388e8/packages/react-devtools-shared/src/backend/views/utils.js#L113
 */
export function proxyGetComputedStyle() {
  window.getComputedStyle = function (el, pseudo) {
    if (
      Object.entries(catalogueMap).some(
        ([n, catalogue]) => catalogue.__Class && el instanceof catalogue.__Class,
      )
    ) {
      return emptyCSSStyleSheet
    } else {
      return getComputedStyle.call(this, el, pseudo)
    }
  }
}
```

**3.compliant dom attributes is used in devtool**

```tsx
if (process.env.NODE_ENV !== 'production') {
    // devtool need to get rect of element
    // https://github.com/facebook/react/blob/29c2c633159cb2171bb04fe84b9caa09904388e8/packages/react-devtools-shared/src/backend/views/utils.js#L108
    instance.getBoundingClientRect = () => getBoundingClientRect(instance)

    // https://github.com/facebook/react/blob/327e4a1f96fbb874001b17684fbb073046a84938/packages/react-devtools-shared/src/backend/views/Highlighter/Overlay.js#L193
    instance.nodeType = 1

    // https://github.com/facebook/react/blob/327e4a1f96fbb874001b17684fbb073046a84938/packages/react-devtools-shared/src/backend/views/Highlighter/Overlay.js#L233
    instance.nodeName = instance.__class__

    instance.ownerDocument = document
  }
```

Based on this, I hope the `injectIntoDevTools` can provide the interface like this 

```tsx
interface InjectIntoDevToolsOptions {
			// to judge is the point in the range of custom renderer,
			// if true, return instance
			isInCustomRenderer: (Event) => instance | null 
			// get left/top/width/height of instance
			getBoundingClientRect: (instance) => any 
			// get border/margin/padding/content of instance
			getComputedStyle: (instance) => any
	
}
```