Skip to content

Commit be27ee9

Browse files
committed
chore: Extend node struct to include structured datas (props, signals,
store, owner...)
1 parent 72edf14 commit be27ee9

File tree

9 files changed

+588
-32
lines changed

9 files changed

+588
-32
lines changed

cmd/rfw/plugins/devtools/devtools.js

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -427,14 +427,28 @@ function selectNode(n) {
427427
if (!detailTitle || !detailKind || !detailKV) return;
428428
detailTitle.textContent = n.name;
429429
detailKind.textContent = n.kind;
430-
detailKV.innerHTML = `
431-
<b>Path</b><div>${n.path || ""}</div>
432-
<b>Props</b><div>${escapeHTML(JSON.stringify(n.props || {}))}</div>
433-
<b>Signals</b><div>${escapeHTML(JSON.stringify(n.signals || {}))}</div>
434-
<b>Render time</b><div>${(n.time || 0).toFixed(2)} ms</div>
435-
<b>Updates</b><div>${n.updates || 0}</div>
436-
<b>Owner</b><div>${n.owner || ""}</div>
437-
`;
430+
const rows = [];
431+
rows.push(renderRow("Path", n.path || ""));
432+
rows.push(renderRow("Render time", `${(n.time || 0).toFixed(2)} ms`));
433+
if (n.owner) rows.push(renderRow("Owner", n.owner));
434+
if (n.hostComponent) rows.push(renderRow("Host component", n.hostComponent));
435+
if (typeof n.updates === "number") rows.push(renderRow("Updates", String(n.updates)));
436+
if (n.props && Object.keys(n.props).length)
437+
rows.push(renderJSONRow("Props", n.props));
438+
if (n.slots && Object.keys(n.slots).length)
439+
rows.push(renderJSONRow("Slots", n.slots));
440+
if (n.signals && Object.keys(n.signals).length)
441+
rows.push(renderJSONRow("Signals", n.signals));
442+
if (n.store) {
443+
const storeLabel = [n.store.module, n.store.name]
444+
.filter(Boolean)
445+
.join("/") || "-";
446+
rows.push(renderRow("Store", storeLabel));
447+
if (n.store.state && Object.keys(n.store.state).length) {
448+
rows.push(renderJSONRow("Store state", n.store.state));
449+
}
450+
}
451+
detailKV.innerHTML = rows.join("") || renderRow("Info", "No metadata available");
438452
}
439453

440454
function escapeHTML(s) {
@@ -447,6 +461,24 @@ function escapeHTML(s) {
447461
);
448462
}
449463

464+
function formatJSON(value) {
465+
try {
466+
return JSON.stringify(value, null, 2);
467+
} catch (err) {
468+
return String(value);
469+
}
470+
}
471+
472+
function renderRow(label, value, isMono = false) {
473+
const content = escapeHTML(value == null ? "" : value);
474+
const cls = isMono ? " class=\"mono\" style=\"white-space:pre-wrap\"" : "";
475+
return `<b>${escapeHTML(label)}</b><div${cls}>${content}</div>`;
476+
}
477+
478+
function renderJSONRow(label, value) {
479+
return renderRow(label, formatJSON(value), true);
480+
}
481+
450482
$("#treeFilter")?.addEventListener("input", (e) => {
451483
const q = e.target.value.trim().toLowerCase();
452484
const nodes = $$(".node", treeContainer);

docs/articles/api/dom.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ Low level DOM helpers used by the framework. Most applications interact with the
3232
| `BindSignalInputs(id, el)` | Binds inputs to local `@signal` directives. |
3333
| `(Element).On(event, handler)` | Attaches an event listener and returns a stop function. |
3434
| `(Element).OnClick(handler)` | Convenience wrapper for click events. |
35+
| `SnapshotComponentSignals(id)` | Copy of signals registered for a component. |
3536

docs/articles/api/state.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ Centralized reactive data stores.
1313
| `Map2(store, key, depA, depB, fn)` | Map two keys into a derived value. |
1414
| `RegisterWatcher(w)` | Run a callback after changes and return a cleanup function. |
1515
| `StoreManager.Snapshot()` | Deep copy of all stores and their current state. |
16+
| `(Store).Module()` | Current module namespace for the store. |
17+
| `(Store).Name()` | Store identifier within its module. |
18+
| `(Store).Snapshot()` | Copy of the store's current key/value state. |
1619
| `StoreManager.UnregisterStore(module, name)` | Remove a store from the manager. |
1720
| `WithHistory(limit)` | Enable mutation history for `Undo`/`Redo` up to `limit` steps. |
1821
| `Undo()` | Revert the last mutation when history is enabled. |

v1/devtools/tree.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,25 @@ import (
66
)
77

88
type node struct {
9-
ID int `json:"id"`
10-
Kind string `json:"kind"`
11-
Name string `json:"name"`
12-
Time float64 `json:"time"`
13-
Path string `json:"path"`
14-
Children []*node `json:"children,omitempty"`
9+
ID int `json:"id"`
10+
Kind string `json:"kind"`
11+
Name string `json:"name"`
12+
Time float64 `json:"time"`
13+
Path string `json:"path"`
14+
Owner string `json:"owner,omitempty"`
15+
Host string `json:"hostComponent,omitempty"`
16+
Updates int `json:"updates,omitempty"`
17+
Props map[string]any `json:"props,omitempty"`
18+
Slots map[string]any `json:"slots,omitempty"`
19+
Signals map[string]any `json:"signals,omitempty"`
20+
Store *storeSnapshot `json:"store,omitempty"`
21+
Children []*node `json:"children,omitempty"`
22+
}
23+
24+
type storeSnapshot struct {
25+
Module string `json:"module"`
26+
Name string `json:"name"`
27+
State map[string]any `json:"state,omitempty"`
1528
}
1629

1730
var (
@@ -21,7 +34,7 @@ var (
2134
nextID int
2235
)
2336

24-
func addComponent(id, kind, name, parentID string) {
37+
func addComponent(id, kind, name, parentID string) *node {
2538
mu.Lock()
2639
defer mu.Unlock()
2740
n := &node{ID: nextID, Kind: kind, Name: name, Path: "/" + name}
@@ -30,11 +43,13 @@ func addComponent(id, kind, name, parentID string) {
3043
if parentID != "" {
3144
if p, ok := nodes[parentID]; ok {
3245
n.Path = p.Path + "/" + name
46+
n.Owner = p.Name
3347
p.Children = append(p.Children, n)
34-
return
48+
return n
3549
}
3650
}
3751
roots = append(roots, n)
52+
return n
3853
}
3954

4055
func removeComponent(id string) {

0 commit comments

Comments
 (0)