Skip to content

Commit 6d1dd19

Browse files
authored
feat: add inspector button (#182)
1 parent 0b9d703 commit 6d1dd19

File tree

3 files changed

+71
-72
lines changed

3 files changed

+71
-72
lines changed

src/client/index.js

+64-49
Original file line numberDiff line numberDiff line change
@@ -15,66 +15,81 @@ window.__svelte_devtools_select_element = function (element) {
1515
if (node) send('inspect', { node: serialize(node) });
1616
};
1717

18+
const previous = {
19+
/** @type {HTMLElement | null} */
20+
target: null,
21+
style: {
22+
cursor: '',
23+
background: '',
24+
outline: '',
25+
},
26+
27+
clear() {
28+
if (this.target) {
29+
this.target.style.cursor = this.style.cursor;
30+
this.target.style.background = this.style.background;
31+
this.target.style.outline = this.style.outline;
32+
}
33+
this.target = null;
34+
},
35+
};
36+
37+
const inspect = {
38+
/** @param {MouseEvent} event */
39+
handle({ target }) {
40+
const same = previous.target && previous.target === target;
41+
const html = target instanceof HTMLElement;
42+
if (same || !html) return;
43+
44+
if (previous.target) previous.clear();
45+
previous.target = target;
46+
previous.style = {
47+
cursor: target.style.cursor,
48+
background: target.style.background,
49+
outline: target.style.outline,
50+
};
51+
target.style.cursor = 'pointer';
52+
target.style.background = 'rgba(0, 136, 204, 0.2)';
53+
target.style.outline = '1px dashed rgb(0, 136, 204)';
54+
},
55+
/** @param {MouseEvent} event */
56+
click(event) {
57+
event.preventDefault();
58+
document.removeEventListener('mousemove', inspect.handle, true);
59+
const node = getNode(/** @type {Node} */ (event.target));
60+
if (node) send('bridge::ext/inspect', { node: serialize(node) });
61+
previous.clear();
62+
},
63+
};
64+
1865
window.addEventListener('message', ({ data, source }) => {
1966
// only accept messages from our application or script
2067
if (source !== window || data?.source !== 'svelte-devtools') return;
2168

2269
if (data.type === 'bridge::ext/select') {
2370
const node = getNode(data.payload);
24-
// @ts-expect-error - saved for `inspect()`
71+
// @ts-expect-error - saved for `devtools.inspect()`
2572
if (node) window.$n = node.detail;
2673
} else if (data.type === 'bridge::ext/highlight') {
2774
const node = getNode(data.payload);
2875
return highlight(node);
76+
} else if (data.type === 'bridge::ext/inspect') {
77+
switch (data.payload) {
78+
case 'start': {
79+
document.addEventListener('mousemove', inspect.handle, true);
80+
document.addEventListener('click', inspect.click, {
81+
capture: true,
82+
once: true,
83+
});
84+
break;
85+
}
86+
default: {
87+
document.removeEventListener('mousemove', inspect.handle, true);
88+
document.removeEventListener('click', inspect.click, true);
89+
previous.clear();
90+
}
91+
}
2992
}
30-
31-
// --- TODO: cleanup/implement below ---
32-
33-
// case 'bridge::ext/inspect': {
34-
// console.log(data.payload, data.payload instanceof HTMLElement);
35-
// /** @param {MouseEvent} event */
36-
// const move = ({ target }) => highlight({ type: 'element', detail: target });
37-
// if (data.payload instanceof HTMLElement) {
38-
// const node = getNode(data.payload);
39-
// if (node) window.postMessage({ type: 'inspect', node: serialize(node) });
40-
// } else if (data.payload === 'start') {
41-
// document.addEventListener('mousemove', move, true);
42-
// document.addEventListener(
43-
// 'click',
44-
// ({ target }) => {
45-
// document.removeEventListener('mousemove', move, true);
46-
// const node = getNode(/** @type {Node} */ (target));
47-
// if (node) window.postMessage({ type: 'inspect', node: serialize(node) });
48-
// },
49-
// { capture: true, once: true },
50-
// );
51-
// return;
52-
// }
53-
// document.removeEventListener('mousemove', move, true);
54-
// return highlight(undefined);
55-
// }
56-
57-
// case 'bridge::ext/profiler': {
58-
// return data.payload ? startProfiler() : stopProfiler();
59-
// }
60-
61-
// switch (data.type) {
62-
63-
// case 'startPicker':
64-
// startPicker();
65-
// break;
66-
67-
// case 'stopPicker':
68-
// stopPicker();
69-
// break;
70-
71-
// case 'startProfiler':
72-
// profiler.start();
73-
// break;
74-
75-
// case 'stopProfiler':
76-
// profiler.stop();
77-
// break;
7893
});
7994

8095
/**

src/routes/+layout.svelte

+2-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
import Breadcrumbs from './Breadcrumbs.svelte';
1010
import ConnectMessage from './ConnectMessage.svelte';
11-
// import PickerButton from './PickerButton.svelte';
11+
import Inspector from './Inspector.svelte';
1212
// import ProfileButton from './ProfileButton.svelte';
1313
// import Profiler from './Profiler.svelte';
1414
import SearchBox from './SearchBox.svelte';
@@ -93,10 +93,7 @@
9393
<!-- TODO: reenable profiler -->
9494
<!-- <ProfileButton /> -->
9595

96-
<!-- toggle highlighting page elements -->
97-
<!-- TODO: reenable picker -->
98-
<!-- <PickerButton /> -->
99-
96+
<Inspector />
10097
<VisibilitySelection />
10198

10299
<Divider type="vertical" spacing="0.25rem" />

src/routes/PickerButton.svelte renamed to src/routes/Inspector.svelte

+5-18
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,14 @@
44
import { selected } from '$lib/store';
55
66
let active = false;
7-
let unsub = () => {};
87
98
function click() {
10-
if (active) {
11-
active = false;
12-
background.send('bridge::ext/inspect', 'stop');
13-
return;
14-
}
15-
16-
unsub();
17-
unsub = selected.subscribe((node) => {
18-
if (!active) return;
19-
active = false;
20-
unsub();
9+
active = !active;
10+
background.send('bridge::ext/inspect', active ? 'start' : 'stop');
11+
}
2112
22-
setTimeout(() => {
23-
node?.dom?.scrollIntoView({ block: 'center' });
24-
}, 120);
25-
});
26-
active = true;
27-
background.send('bridge::ext/inspect', 'start');
13+
$: if (active && $selected) {
14+
$selected.dom?.scrollIntoView({ block: 'center' });
2815
}
2916
</script>
3017

0 commit comments

Comments
 (0)