Skip to content

Commit dcbbdbe

Browse files
authored
Add show options to debugger api (#84)
* Refactor devtools settings to use nested show properties for better organization * fix format
1 parent fec87d4 commit dcbbdbe

13 files changed

Lines changed: 216 additions & 88 deletions

File tree

packages/devpage-react/src/components/ui/ControlSection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const ControlSection = ({ title, subtitle }: ControlSectionProps) => {
5757
description: "Toggle Debug Mode",
5858
onClick: () => {
5959
ForesightDevtools.instance.alterDevtoolsSettings({
60-
showDebugger: !ForesightDevtools.instance.devtoolsSettings.showDebugger,
60+
show: { controlPanel: !ForesightDevtools.instance.devtoolsSettings.show.controlPanel },
6161
})
6262
},
6363
isActive: true,

packages/devpage-react/src/contexts/DebugContext.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ const DebugContext = createContext<DebugContextType | undefined>(undefined)
1111

1212
export function DebugProvider({ children }: { children: ReactNode }) {
1313
const [isDebugActive, setIsDebugActive] = useState(
14-
() => ForesightDevtools.instance.devtoolsSettings.showDebugger
14+
() => ForesightDevtools.instance.devtoolsSettings.show.controlPanel
1515
)
1616

1717
const toggleDebug = useCallback(() => {
1818
const newState = !isDebugActive
1919
setIsDebugActive(newState)
2020
ForesightDevtools.instance.alterDevtoolsSettings({
21-
showDebugger: newState,
21+
show: { controlPanel: newState },
2222
})
2323
}, [isDebugActive])
2424

2525
const setDebugMode = useCallback((enabled: boolean) => {
2626
setIsDebugActive(enabled)
2727
ForesightDevtools.instance.alterDevtoolsSettings({
28-
showDebugger: enabled,
28+
show: { controlPanel: enabled },
2929
})
3030
}, [])
3131

packages/docs/src/components/Hero/Hero.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,19 @@ export function Hero() {
4343
})
4444

4545
ForesightDevtools.initialize({
46-
showDebugger:
47-
typeof window !== "undefined" &&
48-
!(window.matchMedia("(pointer: coarse)").matches && navigator.maxTouchPoints > 0),
49-
showNameTags: false,
46+
show: {
47+
controlPanel:
48+
typeof window !== "undefined" &&
49+
!(window.matchMedia("(pointer: coarse)").matches && navigator.maxTouchPoints > 0),
50+
nameTags: false,
51+
},
5052
isControlPanelDefaultMinimized: true,
5153
logging: { callbackCompleted: true, callbackInvoked: true, managerSettingsChanged: true },
5254
})
5355

5456
const turnOffDebugMode = () => {
5557
ForesightDevtools.instance.alterDevtoolsSettings({
56-
showDebugger: false,
58+
show: { controlPanel: false },
5759
})
5860
}
5961

packages/docs/src/hooks/useDebugMode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useState, useEffect } from "react"
44
function useDebugMode() {
55
const [debugMode, setDebugMode] = useState(true)
66
useEffect(() => {
7-
ForesightDevtools.instance.alterDevtoolsSettings({ showDebugger: debugMode })
7+
ForesightDevtools.instance.alterDevtoolsSettings({ show: { controlPanel: debugMode } })
88
}, [debugMode])
99

1010
const toggleDebugMode = () => {

packages/js.foresight-devtools/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@ ForesightManager.initialize({})
3131

3232
// Initialize the development tools (all options are optional)
3333
ForesightDevtools.initialize({
34-
showDebugger: true,
34+
show: {
35+
controlPanel: true, // show the floating control panel
36+
nameTags: true, // show the element name above each registered element
37+
elementOverlays: true, // show the hit-slop boundary around each registered element
38+
mouseTrajectory: true, // show the predicted mouse trajectory line
39+
scrollTrajectory: true, // show the predicted scroll trajectory line
40+
},
3541
isControlPanelDefaultMinimized: false, // optional setting which allows you to minimize the control panel on default
36-
showNameTags: true, // optional setting which shows the name of the element
3742
sortElementList: "visibility", // optional setting for how the elements in the control panel are sorted
3843
logging: {
3944
logLocation: "controlPanel", // Where to log the Foresight Events

packages/js.foresight-devtools/src/lit-entry/control-panel/settings-tab/setting-item/setting-item-checkbox.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { customElement, property } from "lit/decorators.js"
33

44
import "./setting-item"
55
import { ForesightManager, type ForesightManagerSettings } from "js.foresight"
6-
import type { DevtoolsSettings } from "../../../../types/types"
6+
import type { DevtoolsSettings, ShowKey } from "../../../../types/types"
7+
8+
type ShowSettingKey = `show.${ShowKey}`
79
@customElement("setting-item-checkbox")
810
export class SettingItemCheckbox extends LitElement {
911
static styles = [
@@ -56,15 +58,17 @@ export class SettingItemCheckbox extends LitElement {
5658
@property({ type: Boolean }) isChecked: boolean = false
5759
@property({ type: String }) header: string = ""
5860
@property({ type: String }) description: string = ""
59-
@property({ type: String }) setting: keyof ForesightManagerSettings | keyof DevtoolsSettings =
60-
"enableMousePrediction"
61+
@property({ type: String }) setting:
62+
| keyof ForesightManagerSettings
63+
| keyof DevtoolsSettings
64+
| ShowSettingKey = "enableMousePrediction"
6165

6266
private handleCheckboxChange(event: Event): void {
6367
const target = event.target
6468
if (target instanceof HTMLInputElement) {
6569
const targetIsChecked = target.checked
6670

67-
if (this.setting === "showNameTags") {
71+
if (String(this.setting).startsWith("show.")) {
6872
this.dispatchEvent(
6973
new CustomEvent("setting-changed", {
7074
detail: { setting: this.setting, value: targetIsChecked },

packages/js.foresight-devtools/src/lit-entry/control-panel/settings-tab/settings-tab.ts

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import { ForesightManager } from "js.foresight"
88
import { css, html, LitElement } from "lit"
99
import { customElement, state } from "lit/decorators.js"
1010

11-
import type { Corner, DevtoolsSettings } from "../../../types/types"
11+
import {
12+
SHOW_KEYS,
13+
type Corner,
14+
type DevtoolsSettings,
15+
type ShowKey,
16+
type ShowSettings,
17+
} from "../../../types/types"
1218
import {
1319
MAX_POSITION_HISTORY_SIZE,
1420
MAX_SCROLL_MARGIN,
@@ -36,12 +42,12 @@ import { ForesightDevtools } from "../../foresight-devtools"
3642

3743
// A helper type to represent a change in a Devtools setting
3844
type UpdatedDevtoolsSetting = {
39-
[K in keyof DevtoolsSettings]: {
40-
setting: K
41-
newValue: DevtoolsSettings[K]
42-
oldValue: DevtoolsSettings[K]
45+
[K in ShowKey]: {
46+
setting: `show.${K}`
47+
newValue: ShowSettings[K]
48+
oldValue: ShowSettings[K]
4349
}
44-
}[keyof DevtoolsSettings]
50+
}[ShowKey]
4551

4652
@customElement("settings-tab")
4753
export class SettingsTab extends LitElement {
@@ -168,13 +174,20 @@ export class SettingsTab extends LitElement {
168174
const currentDevtoolsSettings = ForesightDevtools.instance.devtoolsSettings
169175
const currentManagerSettings = ForesightManager.instance.getManagerData.globalSettings
170176

171-
// Shallow copy is sufficient for settings objects
172-
this.devtoolsSettings = Object.assign({}, currentDevtoolsSettings)
177+
// Shallow copy is sufficient except for `show`, which we deep-copy so
178+
// the live and initial snapshots can diverge as the user toggles flags.
179+
this.devtoolsSettings = {
180+
...currentDevtoolsSettings,
181+
show: { ...currentDevtoolsSettings.show },
182+
}
173183
this.managerSettings = Object.assign({}, currentManagerSettings)
174184
this.currentCorner = this.getCurrentCorner()
175185

176186
this.initialSettings = {
177-
devtools: Object.assign({}, currentDevtoolsSettings),
187+
devtools: {
188+
...currentDevtoolsSettings,
189+
show: { ...currentDevtoolsSettings.show },
190+
},
178191
manager: Object.assign({}, currentManagerSettings),
179192
}
180193
}
@@ -239,14 +252,12 @@ export class SettingsTab extends LitElement {
239252
private _checkDevtoolsSettingsChanges(
240253
changes: (UpdatedManagerSetting | UpdatedDevtoolsSetting)[]
241254
): void {
242-
const devtoolsKeys: (keyof DevtoolsSettings)[] = ["showNameTags"]
243-
244-
for (const key of devtoolsKeys) {
245-
const oldValue = this.initialSettings.devtools[key]
246-
const newValue = this.devtoolsSettings[key]
255+
for (const key of SHOW_KEYS) {
256+
const oldValue = this.initialSettings.devtools.show[key]
257+
const newValue = this.devtoolsSettings.show[key]
247258
if (oldValue !== newValue) {
248259
changes.push({
249-
setting: key,
260+
setting: `show.${key}`,
250261
oldValue,
251262
newValue,
252263
} as UpdatedDevtoolsSetting)
@@ -257,14 +268,16 @@ export class SettingsTab extends LitElement {
257268
private _handleDevtoolsSettingChange(e: CustomEvent<{ setting: string; value: boolean }>): void {
258269
const { setting, value } = e.detail
259270

260-
if (setting === "showNameTags") {
261-
this.devtoolsSettings = {
262-
...this.devtoolsSettings,
263-
showNameTags: value,
264-
}
265-
ForesightDevtools.instance.alterDevtoolsSettings({ showNameTags: value })
266-
this._updateChangedSettings()
271+
if (!setting.startsWith("show.")) return
272+
const key = setting.slice("show.".length) as ShowKey
273+
if (!SHOW_KEYS.includes(key)) return
274+
275+
this.devtoolsSettings = {
276+
...this.devtoolsSettings,
277+
show: { ...this.devtoolsSettings.show, [key]: value },
267278
}
279+
ForesightDevtools.instance.alterDevtoolsSettings({ show: { [key]: value } })
280+
this._updateChangedSettings()
268281
}
269282

270283
private _handleTouchDeviceStrategyChange = (value: string): void => {
@@ -475,10 +488,31 @@ export class SettingsTab extends LitElement {
475488
<div class="settings-group">
476489
<h4>Developer Tools</h4>
477490
<setting-item-checkbox
478-
.isChecked=${this.devtoolsSettings.showNameTags}
491+
.isChecked=${this.devtoolsSettings.show.nameTags}
479492
header="Show Name Tags"
480493
description="Display name tags over each registered element in the debugger"
481-
setting="showNameTags"
494+
setting="show.nameTags"
495+
@setting-changed=${this._handleDevtoolsSettingChange}
496+
></setting-item-checkbox>
497+
<setting-item-checkbox
498+
.isChecked=${this.devtoolsSettings.show.elementOverlays}
499+
header="Show Element Overlays"
500+
description="Render hit-slop boundary overlays around registered elements. Note: turning this off also hides name tags."
501+
setting="show.elementOverlays"
502+
@setting-changed=${this._handleDevtoolsSettingChange}
503+
></setting-item-checkbox>
504+
<setting-item-checkbox
505+
.isChecked=${this.devtoolsSettings.show.mouseTrajectory}
506+
header="Show Mouse Trajectory"
507+
description="Render the predicted mouse trajectory line"
508+
setting="show.mouseTrajectory"
509+
@setting-changed=${this._handleDevtoolsSettingChange}
510+
></setting-item-checkbox>
511+
<setting-item-checkbox
512+
.isChecked=${this.devtoolsSettings.show.scrollTrajectory}
513+
header="Show Scroll Trajectory"
514+
description="Render the predicted scroll trajectory line"
515+
setting="show.scrollTrajectory"
482516
@setting-changed=${this._handleDevtoolsSettingChange}
483517
></setting-item-checkbox>
484518
<setting-item

packages/js.foresight-devtools/src/lit-entry/debug-overlay/debug-overlay.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { LitElement, css, html } from "lit"
2-
import { customElement, state } from "lit/decorators.js"
2+
import { customElement, property, state } from "lit/decorators.js"
33
import "./element-overlays"
44
import "./mouse-trajectory"
55
import "./scroll-trajectory"
@@ -28,6 +28,11 @@ export class DebugOverlay extends LitElement {
2828
private _strategy: "mouse" | "touch" | "pen" =
2929
ForesightManager.instance.getManagerData.currentDeviceStrategy
3030

31+
@property({ type: Boolean }) showElementOverlays = true
32+
@property({ type: Boolean }) showMouseTrajectory = true
33+
@property({ type: Boolean }) showScrollTrajectory = true
34+
@property({ type: Boolean }) showNameTags = true
35+
3136
connectedCallback(): void {
3237
super.connectedCallback()
3338
this._abortController = new AbortController()
@@ -53,9 +58,12 @@ export class DebugOverlay extends LitElement {
5358
<div id="overlay-container">
5459
${this._strategy === "mouse"
5560
? html`
56-
<mouse-trajectory></mouse-trajectory>
57-
<scroll-trajectory></scroll-trajectory>
58-
<element-overlays></element-overlays>
61+
<mouse-trajectory ?hidden=${!this.showMouseTrajectory}></mouse-trajectory>
62+
<scroll-trajectory ?hidden=${!this.showScrollTrajectory}></scroll-trajectory>
63+
<element-overlays
64+
?hidden=${!this.showElementOverlays}
65+
.showNameTags=${this.showNameTags}
66+
></element-overlays>
5967
`
6068
: ""}
6169
</div>

packages/js.foresight-devtools/src/lit-entry/debug-overlay/element-overlays.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { LitElement, html, css } from "lit"
2-
import { customElement, state, query } from "lit/decorators.js"
1+
import { LitElement, html, css, type PropertyValues } from "lit"
2+
import { customElement, state, query, property } from "lit/decorators.js"
33
import {
44
type ForesightElementData,
55
type ForesightElement,
@@ -14,7 +14,6 @@ import type {
1414
ElementRegisteredEvent,
1515
ElementUnregisteredEvent,
1616
} from "js.foresight"
17-
import { ForesightDevtools } from "../foresight-devtools"
1817
interface ElementOverlay {
1918
expandedOverlay: HTMLElement
2019
nameLabel: HTMLElement
@@ -31,6 +30,8 @@ export class ElementOverlays extends LitElement {
3130
@state() private callbackAnimations: Map<ForesightElement, CallbackAnimation> = new Map()
3231
@query("#overlays-container") private containerElement!: HTMLElement
3332

33+
@property({ type: Boolean }) showNameTags = true
34+
3435
static styles = [
3536
css`
3637
:host {
@@ -43,6 +44,10 @@ export class ElementOverlays extends LitElement {
4344
z-index: 9999;
4445
}
4546
47+
:host([hidden]) {
48+
display: none;
49+
}
50+
4651
.expanded-overlay {
4752
position: absolute;
4853
will-change: transform, box-shadow;
@@ -165,15 +170,12 @@ export class ElementOverlays extends LitElement {
165170
},
166171
{ signal }
167172
)
173+
}
168174

169-
document.addEventListener(
170-
"showNameTagsChanged",
171-
(e: Event) => {
172-
const customEvent = e as CustomEvent<{ showNameTags: boolean }>
173-
this.updateNameTagVisibility(customEvent.detail.showNameTags)
174-
},
175-
{ signal }
176-
)
175+
protected willUpdate(changed: PropertyValues<this>): void {
176+
if (changed.has("showNameTags")) {
177+
this.updateNameTagVisibility(this.showNameTags)
178+
}
177179
}
178180

179181
private createElementOverlays(elementData: ForesightElementData): ElementOverlay {
@@ -198,7 +200,7 @@ export class ElementOverlays extends LitElement {
198200
expandedOverlay.style.height = `${expandedHeight}px`
199201
expandedOverlay.style.transform = `translate3d(${expandedRect.left}px, ${expandedRect.top}px, 0)`
200202

201-
if (!ForesightDevtools.instance.devtoolsSettings.showNameTags) {
203+
if (!this.showNameTags) {
202204
nameLabel.style.display = "none"
203205
} else {
204206
nameLabel.textContent = elementData.name

packages/js.foresight-devtools/src/lit-entry/debug-overlay/mouse-trajectory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export class MouseTrajectory extends LitElement {
2020
display: block;
2121
}
2222
23+
:host([hidden]) {
24+
display: none;
25+
}
26+
2327
.trajectory-line {
2428
display: none;
2529
position: absolute;

0 commit comments

Comments
 (0)