Skip to content

Commit 48850c4

Browse files
committed
WIP
1 parent e92e9c0 commit 48850c4

File tree

6 files changed

+87
-29
lines changed

6 files changed

+87
-29
lines changed

src/browser_panel/page/stimulus_observer.js

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
1-
// ;[
2-
// {
3-
// controllers: [
4-
// {
5-
// identifier: "my-controller",
6-
// selector: "[data-controller~='my-controller']",
7-
// values: [{ name: "auto-start", value: "true" }],
8-
// class: "my-controller",
9-
// },
10-
// ],
11-
// targets: [{ name: "item", selector: "[data-my-controller-target='item']" }],
12-
// },
13-
// ]
14-
15-
import { ensureUUIDOnElement, getUUIDFromElement, stringifyHTMLElementTag, getElementPath } from "$utils/utils.js"
1+
import { ensureUUIDOnElement, getUUIDFromElement, stringifyHTMLElementTag, capitalizeFirstChar } from "$utils/utils.js"
162

173
export default class StimulusObserver {
184
constructor(delegate) {
@@ -110,7 +96,20 @@ export default class StimulusObserver {
11096
if (!controller) return []
11197

11298
const keys = Object.keys(Object.getOwnPropertyDescriptors(Object.getPrototypeOf(controller)))
113-
return keys.filter((key) => key.endsWith("Target") && !key.startsWith("has"))
99+
const targetKeys = keys.filter((key) => key.endsWith("Target") && !key.startsWith("has"))
100+
return targetKeys.map((targetKey) => {
101+
const targets = controller[`has${capitalizeFirstChar(targetKey)}`] ? controller[`${targetKey}s`] : []
102+
return {
103+
name: targetKey,
104+
elements: Array.from(targets).map((target) => {
105+
return {
106+
id: target.id,
107+
uuid: ensureUUIDOnElement(target),
108+
serializedTag: stringifyHTMLElementTag(target),
109+
}
110+
}),
111+
}
112+
})
114113
}
115114

116115
getStimulusData() {

src/browser_panel/panel/App.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
}
1919
initializeDevToolOptions()
2020
21-
let currentTab = $state("turbo-tab")
21+
let currentTab = $state("stimulus-tab")
2222
2323
const addEventListeners = () => {
2424
window.addEventListener("resize", handleResize)
@@ -78,11 +78,11 @@
7878
</wa-option>
7979
</wa-select>
8080
</nav>
81-
<div id="turbo-tab" class="tab-content active">
81+
<div id="turbo-tab" class="tab-content">
8282
<TurboTab />
8383
</div>
8484

85-
<div id="stimulus-tab" class="tab-content">
85+
<div id="stimulus-tab" class="tab-content active">
8686
<StimulusTab />
8787
</div>
8888

src/browser_panel/panel/tabs/StimulusTab.svelte

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import { flip } from "svelte/animate"
44
55
import ValueTreeItem from "$src/components/Stimulus/ValueTreeItem.svelte"
6+
import TargetTreeItem from "$src/components/Stimulus/TargetTreeItem.svelte"
67
import InspectButton from "$components/InspectButton.svelte"
78
import HTMLRenderer from "$src/browser_panel/HTMLRenderer.svelte"
9+
import ScrollIntoViewButton from "$components/ScrollIntoViewButton.svelte"
810
import { getStimulusData } from "../../State.svelte.js"
9-
import { flattenNodes, handleKeyboardNavigation, debounce } from "$utils/utils.js"
11+
import { flattenNodes, handleKeyboardNavigation, selectorByUUID } from "$utils/utils.js"
1012
import { addHighlightOverlay, hideHighlightOverlay } from "../../messaging.js"
1113
import { getDevtoolInstance } from "$lib/devtool.js"
1214
import { horizontalPanes } from "../../theme.svelte.js"
@@ -153,7 +155,7 @@
153155
tabindex="0"
154156
onclick={() => setSelectedController(instance)}
155157
onkeyup={handleInstancesKeyboardNavigation}
156-
onmouseenter={() => addHighlightOverlay(`[data-hotwire-dev-tools-uuid="${instance.uuid}"]`)}
158+
onmouseenter={() => addHighlightOverlay(selectorByUUID(instance.uuid))}
157159
onmouseleave={() => hideHighlightOverlay()}
158160
>
159161
<div class="d-table-row">
@@ -163,7 +165,7 @@
163165

164166
<div class="stimulus-instance-second-column">
165167
<div class="me-3 overflow-x-auto scrollbar-none">
166-
<InspectButton class="btn-hoverable me-2" selector={`[data-hotwire-dev-tools-uuid="${instance.uuid}"]`}></InspectButton>
168+
<InspectButton class="btn-hoverable me-2" selector={selectorByUUID(instance.uuid)}></InspectButton>
167169
<HTMLRenderer htmlString={instance.serializedTag} />
168170
</div>
169171
</div>
@@ -191,6 +193,10 @@
191193
{@const dataAttribute = `data-${selected.identifier}-${valueObject.key}`}
192194
<ValueTreeItem {valueObject} {selected} {dataAttribute} />
193195
{/each}
196+
<div class="pane-section-heading">Targets</div>
197+
{#each selected.controller.targets.sort((a, b) => a.elements?.length < b.elements?.length) as target (selected.uuid + target.name)}
198+
<TargetTreeItem {target} {selected} />
199+
{/each}
194200
</div>
195201
</div>
196202
{:else}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script>
2+
import CopyButton from "$components/CopyButton.svelte"
3+
import HTMLRenderer from "$src/browser_panel/HTMLRenderer.svelte"
4+
import ScrollIntoViewButton from "$components/ScrollIntoViewButton.svelte"
5+
import InspectButton from "$components/InspectButton.svelte"
6+
import { capitalizeFirstChar, selectorByUUID } from "$utils/utils.js"
7+
8+
let { target, selected } = $props()
9+
</script>
10+
11+
<div class="d-flex gap-2 mb-2">
12+
<wa-tree>
13+
<wa-tree-item>
14+
<span class="code-key">{target.name}</span>
15+
{#if target.elements.length === 0}
16+
<span class="text-muted">(no targets)</span>
17+
{:else}
18+
{#each target.elements as element}
19+
<wa-tree-item>
20+
<div>
21+
<HTMLRenderer htmlString={element.serializedTag} />
22+
<ScrollIntoViewButton selector={selectorByUUID(element.uuid)}></ScrollIntoViewButton>
23+
<InspectButton selector={selectorByUUID(element.uuid)}></InspectButton>
24+
</div>
25+
</wa-tree-item>
26+
{/each}
27+
{/if}
28+
<wa-button id={`rich-tooltip-${target.name}`} variant="neutral" appearance="plain" size="small" class="small-icon-button">
29+
<wa-icon name="info" label="Info"></wa-icon>
30+
</wa-button>
31+
</wa-tree-item>
32+
</wa-tree>
33+
34+
<wa-tooltip for={`rich-tooltip-${target.name}`} trigger="click" style="--max-width: 100%;">
35+
<div>
36+
<div class="d-flex justify-content-between align-items-center">
37+
<span>{`data-${selected.identifier}-${target.name}`}</span>
38+
<CopyButton value={`data-${selected.identifier}-${target.name}`} />
39+
</div>
40+
</div>
41+
</wa-tooltip>
42+
</div>

src/components/Stimulus/ValueTreeItem.svelte

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import NestedValue from "./NestedValue.svelte"
44
import CopyButton from "$components/CopyButton.svelte"
55
import { updateDataAttribute } from "../../browser_panel/messaging"
6+
import { capitalizeFirstChar, selectorByUUID } from "$utils/utils.js"
67
78
let { valueObject, selected, dataAttribute } = $props()
89
@@ -62,7 +63,7 @@
6263
6364
const serializedValue = serializeValue(updatedValue, valueObject.type)
6465
65-
updateDataAttribute(`[data-hotwire-dev-tools-uuid="${selected.uuid}"]`, dataAttribute, serializedValue)
66+
updateDataAttribute(selectorByUUID(selected.uuid), dataAttribute, serializedValue)
6667
6768
editingStates[path.join(".")] = false
6869
}
@@ -98,13 +99,12 @@
9899
/>
99100
</div>
100101
{/if}
102+
<wa-button id={`rich-tooltip-${valueObject.key}`} variant="neutral" appearance="plain" size="small" class="small-icon-button">
103+
<wa-icon name="info" label="Info"></wa-icon>
104+
</wa-button>
101105
</wa-tree-item>
102106
</wa-tree>
103107

104-
<wa-button id={`rich-tooltip-${valueObject.key}`} variant="neutral" appearance="plain" size="small" class="small-icon-button" class:d-none={Object.values(editingStates).some(Boolean)}>
105-
<wa-icon name="info" label="Info"></wa-icon>
106-
</wa-button>
107-
108108
<wa-tooltip for={`rich-tooltip-${valueObject.key}`} trigger="click" style="--max-width: 100%;">
109109
<div>
110110
<div class="flex-center">Type: {valueObject.type}</div>
@@ -117,8 +117,8 @@
117117
<CopyButton value={`this.${valueObject.name}Value`} />
118118
</div>
119119
<div class="d-flex justify-content-between align-items-center">
120-
<span>{`this.has${valueObject.name[0].toUpperCase() + valueObject.name.slice(1)}Value`}</span>
121-
<CopyButton value={`this.has${valueObject.name[0].toUpperCase() + valueObject.name.slice(1)}Value`} />
120+
<span>{`this.has${capitalizeFirstChar(valueObject)}Value`}</span>
121+
<CopyButton value={`this.has${capitalizeFirstChar(valueObject)}Value`} />
122122
</div>
123123
</div>
124124
</wa-tooltip>

src/utils/utils.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,14 @@ export const safeStringifyEventDetail = (detail) => {
170170
export const flattenNodes = (tree) => {
171171
return tree.flatMap((node) => [node, ...flattenNodes(node.children || [])])
172172
}
173+
174+
export const capitalizeFirstChar = (str) => {
175+
if (typeof str !== "string" || str === undefined || str.length === 0) {
176+
return str
177+
}
178+
return str.charAt(0).toUpperCase() + str.slice(1)
179+
}
180+
181+
export const selectorByUUID = (uuid) => {
182+
return `[data-hotwire-dev-tools-uuid="${uuid}"]`
183+
}

0 commit comments

Comments
 (0)