Skip to content

Commit d5cabd5

Browse files
committed
feat(devtools): add copy path to source inspector
1 parent f1844a2 commit d5cabd5

File tree

5 files changed

+60
-0
lines changed

5 files changed

+60
-0
lines changed

.changeset/icy-states-chew.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/devtools': minor
3+
---
4+
5+
Adds copy path feature and config to devtools source inspector

docs/source-inspector.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ export default {
6767

6868
Both `files` and `components` accept arrays of strings (exact match) or RegExp patterns.
6969

70+
## Click Action
71+
72+
By default, clicking an inspected element opens the file in your editor. You can change this to copy the source path to the clipboard instead using the `sourceAction` setting:
73+
74+
```ts
75+
<TanStackDevtools
76+
config={{
77+
sourceAction: 'copy-path',
78+
}}
79+
/>
80+
```
81+
82+
| Value | Behavior |
83+
| --- | --- |
84+
| `"ide-warp"` | Opens the file in your editor at the exact line (default) |
85+
| `"copy-path"` | Copies the `filepath:line:column` string to the clipboard |
86+
87+
This is useful in environments where the Vite dev server cannot reach your editor, or when you want to paste the path elsewhere.
88+
7089
## Editor Configuration
7190

7291
Most popular editors work out of the box via the `launch-editor` package. Supported editors include VS Code, WebStorm, Sublime Text, Atom, and more ([full list](https://github.com/yyx990803/launch-editor?tab=readme-ov-file#supported-editors)).

examples/react/basic/src/setup.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
5555
const router = createRouter({
5656
routeTree,
5757
})
58+
5859
export default function DevtoolsExample() {
5960
return (
6061
<>
6162
<TanStackDevtools
6263
eventBusConfig={{
6364
connectToServerBus: true,
6465
}}
66+
config={{ sourceAction: 'copy-path' }}
6567
plugins={[
6668
{
6769
name: 'TanStack Query',

packages/devtools/src/components/source-inspector.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,32 @@ export const SourceInspector = () => {
3030

3131
const downList = useKeyDownList()
3232

33+
const [disabledAfterClick, setDisabledAfterClick] = createSignal(false)
34+
3335
const isHighlightingKeysHeld = createMemo(() => {
3436
return isHotkeyCombinationPressed(downList(), settings().inspectHotkey)
3537
})
3638

3739
createEffect(() => {
3840
if (!isHighlightingKeysHeld()) {
41+
setDisabledAfterClick(false)
42+
}
43+
})
44+
45+
const isActive = createMemo(
46+
() => isHighlightingKeysHeld() && !disabledAfterClick(),
47+
)
48+
49+
createEffect(() => {
50+
if (isActive()) {
51+
document.body.style.cursor = 'pointer'
52+
} else {
53+
document.body.style.cursor = ''
54+
}
55+
})
56+
57+
createEffect(() => {
58+
if (!isActive()) {
3959
resetHighlight()
4060
return
4161
}
@@ -78,6 +98,12 @@ export const SourceInspector = () => {
7898
window.getSelection()?.removeAllRanges()
7999
e.preventDefault()
80100
e.stopPropagation()
101+
setDisabledAfterClick(true)
102+
103+
if (settings().sourceAction === 'copy-path') {
104+
navigator.clipboard.writeText(highlightState.dataSource).catch(() => {})
105+
return
106+
}
81107

82108
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
83109
const baseUrl = new URL(import.meta.env?.BASE_URL ?? '/', location.origin)

packages/devtools/src/context/devtools-store.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ export type DevtoolsStore = {
7474
*/
7575
theme: TanStackDevtoolsTheme
7676

77+
/**
78+
* The action to perform when clicking a source-inspected element
79+
* - "ide-warp": open the file in the IDE via the Vite middleware
80+
* - "copy-path": copy the file path to the clipboard
81+
* @default "ide-warp"
82+
*/
83+
sourceAction: 'ide-warp' | 'copy-path'
7784
/**
7885
* Whether the trigger should be completely hidden or not (you can still open with the hotkey)
7986
*/
@@ -110,6 +117,7 @@ export const initialState: DevtoolsStore = {
110117
window.matchMedia('(prefers-color-scheme: dark)').matches
111118
? 'dark'
112119
: 'light',
120+
sourceAction: 'ide-warp',
113121
triggerHidden: false,
114122
customTrigger: undefined,
115123
},

0 commit comments

Comments
 (0)