Skip to content

Commit e28f37a

Browse files
authored
Support custom renderers (#345)
2 parents 6170f49 + e364a4e commit e28f37a

32 files changed

+958
-725
lines changed

.changeset/light-friends-film.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solid-devtools/debugger": minor
3+
---
4+
5+
Remove element field from SourceCodeData

.changeset/proud-dogs-end.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@solid-devtools/debugger": minor
3+
"solid-devtools": minor
4+
---
5+
6+
Add setElementInterface funtion to setup to support custom renderers (closes #343)

.changeset/silent-onions-invite.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@solid-devtools/shared": patch
3+
"@solid-devtools/extension": patch
4+
---
5+
6+
Move assert to shared/utils

extension/src/background.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ It has to coordinate the communication between the different scripts based on th
66
77
*/
88

9-
import {error, log} from '@solid-devtools/shared/utils'
9+
import {assert, error, log} from '@solid-devtools/shared/utils'
1010

1111
import {
1212
Place_Name, ConnectionName, type Port,
@@ -37,12 +37,6 @@ chrome.tabs
3737
}
3838
})
3939

40-
function assert(condition: any, message?: string, cause?: any): asserts condition {
41-
if (!condition) {
42-
throw Error(message ?? 'Assertion failed', {cause})
43-
}
44-
}
45-
4640
function get_assert_tab_id(port: Port, place: Place_Name): Tab_Id {
4741
let tab_id = port.sender?.tab?.id
4842
assert(tab_id, `${place} has no port sender tab id.`, port)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"vite-plugin-solid": "^2.11.6",
5252
"vitest": "^2.1.9"
5353
},
54-
"packageManager": "pnpm@10.6.0",
54+
"packageManager": "pnpm@10.7.0",
5555
"engines": {
5656
"node": ">=22",
5757
"pnpm": ">=10.6.0"

packages/debugger/README.md

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pnpm add @solid-devtools/debugger
2727
> **Warning**
2828
> This package changes extremely often, and is not meant to be used directly. Unless you know what you're doing, use the main package instead.
2929
30-
### Module overview
30+
## Module overview
3131

3232
The debugger is split into four submodules:
3333

@@ -48,33 +48,33 @@ The debugger needs to be setup before it can be used. To do that, import the `./
4848
```ts
4949
import '@solid-devtools/debugger/setup'
5050

51-
import { useDebugger } from '@solid-devtools/debugger/bundled' // or from '@solid-devtools/debugger'
51+
import {useDebugger} from '@solid-devtools/debugger/bundled' // or from '@solid-devtools/debugger'
5252
5353
const debug = useDebugger()
5454
```
5555

56-
### Using component locator
56+
## Using component locator
5757

5858
_Debugger feature inspired by [LocatorJS](https://www.locatorjs.com)_
5959

6060
Locator let's you locate components on the page, and go to their source code in your IDE. All you need to do is configure it by calling `setLocatorOptions` with some options.
6161

6262
```ts
63-
import { useDebugger } from '@solid-devtools/debugger' // or 'solid-devtools/setup'
63+
import {useDebugger} from '@solid-devtools/debugger' // or 'solid-devtools/setup'
6464
6565
const debug = useDebugger()
6666
debug.setLocatorOptions()
6767
```
6868

6969
It will not allow you to highlight hovered components on the page and reveal them in the IDE or the Chrome Extension. _(depending of if the extension panel is open or not)_
7070

71-
#### Locator Options
71+
### Locator Options
7272

7373
Not passing any options will enable the locator with <kbd>Alt</kbd> as the trigger key and no `targetIDE` selected.
7474

7575
Currently Locator allows for specifying these props:
7676

77-
##### `targetIDE`
77+
#### `targetIDE`
7878

7979
Choose in which IDE the component source code should be revealed.
8080

@@ -111,7 +111,7 @@ setLocatorOptions({
111111
})
112112
```
113113

114-
##### `key`
114+
#### `key`
115115

116116
Holding which key should enable the locator overlay? It's `"Alt"` by default — <kbd>Alt</kbd> on Windows, and <kbd>Option</kbd> or <kbd>⌥</kbd> on macOS.
117117

@@ -123,14 +123,41 @@ setLocatorOptions({
123123
})
124124
```
125125

126-
#### Using the Locator on the page
126+
### Using the Locator on the page
127127

128128
To activate the Locator module — you have to hold down the <kbd>Alt</kbd>/<kbd>Option</kbd> key and move your mouse around the page to highlight components and their different HTML Elements.
129129

130130
Clicking the component should take you to the component source code, given that you specified the [`targetIDE`](#targetIDE) option.
131131

132132
https://user-images.githubusercontent.com/24491503/174093606-a0d80331-021f-4d43-b0bb-e9a4041e1a26.mp4
133133

134+
## Supporting custom renderers
135+
136+
By default the debugger assumes you are using `"solid-js/web"` as jsx renderer and that the rendered elements are `HTMLElement`s.
137+
138+
If you are using a custom renderer—such as Three.js, Pixi.js, or Lightning.js—you need to provide the debugger with an `ElementInterface` implementation.
139+
140+
```ts
141+
import * as debug from '@solid-devtools/debugger/types'
142+
import {setElementInterface} from '@solid-devtools/debugger/setup' // or 'solid-devtools/setup'
143+
144+
/** ElementInterface implementation for DOM Element */
145+
let element_interface: debug.ElementInterface<Element> = {
146+
isElement: obj => obj instanceof Element,
147+
getElementAt: e => e.target as Element | null,
148+
getName: el => el.localName,
149+
getChildren: el => el.children,
150+
getParent: el => el.parentElement,
151+
getRect: el => el.getBoundingClientRect(),
152+
getLocation: el => {
153+
let attr = debug.getLocationAttr(el)
154+
return attr && debug.parseLocationString(attr) || null
155+
},
156+
}
157+
158+
setElementInterface(element_interface)
159+
```
160+
134161
## Changelog
135162

136163
See [CHANGELOG.md](./CHANGELOG.md).

packages/debugger/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
"@nothing-but/utils": "~0.17.0",
5353
"@solid-devtools/shared": "workspace:^",
5454
"@solid-primitives/bounds": "^0.1.0",
55-
"@solid-primitives/cursor": "^0.1.0",
5655
"@solid-primitives/event-listener": "^2.4.0",
5756
"@solid-primitives/keyboard": "^1.3.0",
5857
"@solid-primitives/platform": "^0.2.0",

packages/debugger/src/inspector/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export function createInspector(props: {
6262
const encoded = encodeValue(
6363
node.getValue(),
6464
selected,
65+
setup.eli,
6566
selected &&
6667
(storeNode => node.addStoreObserver(observeStoreNode(storeNode))),
6768
)
@@ -79,7 +80,7 @@ export function createInspector(props: {
7980
[
8081
storeProperty,
8182
typeof data === 'object'
82-
? encodeValue(data.value, true, undefined, true)
83+
? encodeValue(data.value, true, setup.eli, undefined, true)
8384
: data ?? null,
8485
],
8586
])
@@ -163,6 +164,7 @@ export function createInspector(props: {
163164
onValueUpdate: pushValueUpdate,
164165
onPropStateChange: pushPropState,
165166
observedPropsMap: propsMap,
167+
eli: setup.eli,
166168
})
167169

168170
props.emit(msg('InspectedNodeDetails', result.details))

packages/debugger/src/inspector/index.test.tsx renamed to packages/debugger/src/inspector/inspector.test.tsx

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import * as s from 'solid-js'
44
import * as test from 'vitest'
55
import {getObjectById, getSdtId, ObjectType} from '../main/id.ts'
66
import setup from '../main/setup.ts'
7-
import {type Mapped, NodeType, PropGetterState, type Solid, ValueType} from '../types.ts'
7+
import {dom_element_interface, type Mapped, NodeType, PropGetterState, type Solid, ValueType} from '../types.ts'
88
import {collectOwnerDetails} from './inspector.ts'
99

10+
const eli = dom_element_interface
11+
1012
test.describe('collectOwnerDetails', () => {
1113
test.it('collects focused owner details', () => {
1214
s.createRoot(dispose => {
@@ -42,13 +44,10 @@ test.describe('collectOwnerDetails', () => {
4244
const [innerMemo] = memo.owned as [Solid.Memo, Solid.Computation]
4345

4446
const {details, valueMap} = collectOwnerDetails(memo, {
45-
observedPropsMap: new WeakMap(),
46-
onPropStateChange: () => {
47-
/**/
48-
},
49-
onValueUpdate: () => {
50-
/**/
51-
},
47+
observedPropsMap: new WeakMap(),
48+
onPropStateChange: () => {/**/},
49+
onValueUpdate: () => {/**/},
50+
eli: eli,
5251
})
5352

5453
test.expect(details).toEqual({
@@ -109,13 +108,10 @@ test.describe('collectOwnerDetails', () => {
109108
))
110109

111110
const {details} = collectOwnerDetails(owner, {
112-
observedPropsMap: new WeakMap(),
113-
onPropStateChange: () => {
114-
/**/
115-
},
116-
onValueUpdate: () => {
117-
/**/
118-
},
111+
observedPropsMap: new WeakMap(),
112+
onPropStateChange: () => {/**/},
113+
onValueUpdate: () => {/**/},
114+
eli: eli,
119115
})
120116

121117
dispose()
@@ -169,13 +165,10 @@ test.describe('collectOwnerDetails', () => {
169165
})
170166

171167
const {details} = collectOwnerDetails(owner, {
172-
observedPropsMap: new WeakMap(),
173-
onPropStateChange: () => {
174-
/**/
175-
},
176-
onValueUpdate: () => {
177-
/**/
178-
},
168+
observedPropsMap: new WeakMap(),
169+
onPropStateChange: () => {/**/},
170+
onValueUpdate: () => {/**/},
171+
eli: eli,
179172
})
180173

181174
test.expect(details).toEqual({
@@ -215,11 +208,10 @@ test.describe('collectOwnerDetails', () => {
215208

216209
const onValueUpdate = test.vi.fn()
217210
collectOwnerDetails(owner, {
218-
observedPropsMap: new WeakMap(),
219-
onPropStateChange: () => {
220-
/**/
221-
},
222-
onValueUpdate: onValueUpdate,
211+
observedPropsMap: new WeakMap(),
212+
onPropStateChange: () => {/**/},
213+
onValueUpdate: onValueUpdate,
214+
eli: eli,
223215
})
224216

225217
test.expect(onValueUpdate).not.toBeCalled()
@@ -249,11 +241,10 @@ test.describe('collectOwnerDetails', () => {
249241

250242
const onValueUpdate = test.vi.fn()
251243
collectOwnerDetails(owner, {
252-
observedPropsMap: new WeakMap(),
253-
onPropStateChange: () => {
254-
/**/
255-
},
256-
onValueUpdate: onValueUpdate,
244+
observedPropsMap: new WeakMap(),
245+
onPropStateChange: () => {/**/},
246+
onValueUpdate: onValueUpdate,
247+
eli: eli,
257248
})
258249

259250
test.expect(onValueUpdate).not.toBeCalled()

0 commit comments

Comments
 (0)