-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomponent-tree.tsx
More file actions
101 lines (90 loc) · 4.39 KB
/
component-tree.tsx
File metadata and controls
101 lines (90 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import {For, useContext, onCleanup, createMemo} from 'solid-js';
import type {ComponentDisposed, InspectComponentSelected} from '../../channel/channel-message-types';
import type {DomRootData, ComponentData} from '../data/component-data-types';
import type {SignalData} from '../data/signal-data-types';
import type {RegistryMirror} from '../registry-mirror/registry-mirror-types';
import {ComponentTreeSelectionContext, selectedComponent, selectedGlobalSignals} from './contexts/tree-selection-context';
import {OptionsContext} from './contexts/options-context';
import {ChannelContext} from './contexts/channel-context';
import {useChannelListener} from './contexts/use-channel-listener';
import {InspectElementsButton} from './inspect-elements-button';
const componentRowElements: Map<string, Element> = new Map();
function ComponentTree(props: {registryMirror: RegistryMirror}) {
const {setTreeSelection} = useContext(ComponentTreeSelectionContext)!;
const selectedComponentId = createMemo(() => selectedComponent()?.id);
useChannelListener('componentDisposed', ({id}: ComponentDisposed) => {
if (id === selectedComponentId()) {
setTreeSelection(undefined);
}
});
useChannelListener('inspectComponentSelected', ({componentId}: InspectComponentSelected) => {
const componentData = props.registryMirror.getComponent(componentId)?.componentData;
if (componentData) {
const componentRowElement = componentRowElements.get(componentId);
componentRowElement?.scrollIntoView({block: 'center'});
setTreeSelection({selectionType: 'component', componentData});
}
});
return <div class="h-full w-full flex flex-col">
<div class="w-full flex-none flex flex-row py-1">
<InspectElementsButton />
<div class="flex-none mx-auto px-8 text-red-700 font-bold">work in progress</div>
</div>
<div class="flex-auto w-full overflow-auto text-xs leading-snug">
<div class="min-w-fit">
<GlobalSignals globalSignals={props.registryMirror.globalSignals} />
<For each={props.registryMirror.domRootsData()}>{domRootData => <DomRootUI {...domRootData} />}</For>
</div>
</div>
</div>
;
}
function DomRootUI(props: DomRootData) {
return <For each={props.getChildren()}>{component => <ComponentUI {...component} />}</For>;
}
function ComponentUI(props: ComponentData) {
const level = props.level() ?? 0;
const indent = 1.5 * (level - 1);
const {setTreeSelection} = useContext(ComponentTreeSelectionContext)!;
const isSelected = createMemo(() => props.id === selectedComponent()?.id);
const exposeIds = useContext(OptionsContext)?.exposeIds;
const channel = useContext(ChannelContext)!;
const onMouseEnter = (cd: ComponentData) => channel.send('highlightComponent', {componentId: cd.id});
const onMouseLeave = () => channel.send('stopHighlightComponent', {});
onCleanup(() => componentRowElements.delete(props.id));
return <>
<div
ref={element => componentRowElements.set(props.id, element)}
onclick={[setTreeSelection, {selectionType: 'component', componentData: props}]}
onmouseenter={[onMouseEnter, props]}
onmouseleave={onMouseLeave}
classList={treeRowClassList(isSelected)}
style={{'padding-left': `${indent}em`}}
>
{componentText(props, exposeIds)}
</div>
<For each={props.getChildren()}>{component => <ComponentUI {...component} />}</For>
</>
;
}
function componentText(componentData: ComponentData, exposeIds?: boolean): string {
const id = exposeIds ? ` [${componentData.id}]` : '';
return componentData.name + id;
}
function GlobalSignals(props: {globalSignals: () => SignalData[]}) {
const {setTreeSelection} = useContext(ComponentTreeSelectionContext)!;
const isSelected = createMemo(() => !!selectedGlobalSignals());
return <div onclick={[setTreeSelection, {selectionType: 'globalSignals', globalSignals: props.globalSignals}]} classList={treeRowClassList(isSelected)}>
Global Signals
</div>
;
}
function treeRowClassList(isSelected: () => boolean) {
return {
'cursor-default': true,
'bg-slate-300': isSelected(),
'hover:bg-slate-100': !isSelected(),
'dark:hover:bg-slate-200': !isSelected()
};
}
export {ComponentTree};