Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions src/core/clickInspector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Config, isDev } from './config.js';
import { isElementNode } from './utils.js';
import type { ElementNode } from './elementNode.js';

let installed = false;

function findDeepestAtPosition(
root: ElementNode,
x: number,
y: number,
): ElementNode {
const precision = Config.rendererOptions?.deviceLogicalPixelRatio || 1;
const px = x / precision;
const py = y / precision;

let current = root;
while (true) {
let best: ElementNode | undefined;
let bestZ = -Infinity;
for (const child of current.children) {
if (!isElementNode(child) || child.alpha === 0) continue;
const cx = (child.lng.absX as number) || 0;
const cy = (child.lng.absY as number) || 0;
const cw = child.width || 0;
const ch = child.height || 0;
if (px < cx || px > cx + cw || py < cy || py > cy + ch) continue;
const z = child.zIndex ?? -1;
if (z >= bestZ) {
bestZ = z;
best = child;
}
}
if (!best) return current;
current = best;
}
}

function handleClick(event: MouseEvent) {
if (!event.altKey) return;
let target = event.target as HTMLElement | null;
while (target && !target.element) {
target = target.parentElement;
}
const hit = target?.element;
if (!hit) return;
let root = hit;
while (root.parent) root = root.parent;
const el = findDeepestAtPosition(root, event.clientX, event.clientY);
event.preventDefault();
event.stopPropagation();
const lng = el.lng as any;

Check warning on line 51 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unexpected any. Specify a different type

Check warning on line 51 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value
const label = el.componentName || el._type;
const loc = el.componentLocation ? ` @ ${el.componentLocation}` : '';
console.log(
`%c[SolidTV Inspector] %c${label}${loc}`,
'color: magenta; font-weight: bold;',
'color: inherit; font-weight: normal;',
{
element: el,
div: lng.div,

Check warning on line 60 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe member access .div on an `any` value

Check warning on line 60 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value
lng,

Check warning on line 61 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value
states: el._states ? Array.from(el._states) : [],
position: { x: lng?.x, y: lng?.y, w: lng?.w, h: lng?.h },

Check warning on line 63 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value

Check warning on line 63 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe member access .y on an `any` value

Check warning on line 63 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value

Check warning on line 63 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe member access .x on an `any` value

Check warning on line 63 in src/core/clickInspector.ts

View workflow job for this annotation

GitHub Actions / build-test

Unsafe assignment of an `any` value
parent: el.parent,
children: el.children,
},
);
(globalThis as any).$el = el;
console.log('Pinned to $el — try $el.parent, $el.setFocus()');
}

export function initClickInspector(): void {
if (installed || !isDev || typeof document === 'undefined') return;
installed = true;
document.addEventListener('click', handleClick, true);
}
4 changes: 3 additions & 1 deletion src/core/dom-renderer/domRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ function updateNodeParent(node: DOMNode | DOMText) {
const parent = node.props.parent;
if (parent instanceof DOMNode) {
elMap.get(parent)!.appendChild(node.div);
} else {
node.div.parentNode?.removeChild(node.div);
}
}

Expand Down Expand Up @@ -1174,7 +1176,7 @@ export class DOMNode extends EventEmitter implements IRendererNode {
if (parent instanceof DOMNode) {
parent.children.delete(this);
}
this.div.parentNode!.removeChild(this.div);
this.div.parentNode?.removeChild(this.div);
}

get parent() {
Expand Down
21 changes: 20 additions & 1 deletion src/core/elementNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
setActiveElement,
FocusNode,
} from './focusManager.js';
import { initClickInspector } from './clickInspector.js';

import {
IRendererNode,
Expand Down Expand Up @@ -279,6 +280,8 @@ declare global {
}
}

initClickInspector();

export type RendererNode = AddColorString<
Partial<
NewOmit<
Expand Down Expand Up @@ -1338,6 +1341,17 @@ export class ElementNode {
_stateChanged() {
isDev && log('State Changed: ', this, this.states);

if (isDev) {
const div = (this.lng as any)?.div as HTMLElement | undefined;
if (div) {
if (this.states.length > 0) {
div.dataset.states = this.states.join(' ');
} else {
delete div.dataset.states;
}
}
}

if (this.forwardStates) {
// apply states to children first
const states = this.states.slice() as States;
Expand Down Expand Up @@ -1622,7 +1636,12 @@ export class ElementNode {

// L3 Inspector adds div to the lng object
const div: HTMLElement | undefined = (node.lng as any)?.div;
if (div) div.element = node;
if (isDev && div) {
div.element = node;
if (node._states && node._states.length > 0) {
div.dataset.states = node._states.join(' ');
}
}

if (node._type === NodeType.Element) {
// only element nodes will have children that need rendering
Expand Down
1 change: 1 addition & 0 deletions src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export function Dynamic<T extends Record<string, any>>(

case 'string': {
const el = createElement(component);
(el as { componentName?: string }).componentName = component;
spread(el, others);
return el;
}
Expand Down
Loading