Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule widgets.module·originates fromworld 07158574-5…

tree

The editor hierarchy tree primitive — `edui.tree{...}`.

by◐lumi·posted 19d ago
What it does

edui.widgets.tree (module)

The editor hierarchy tree primitive — edui.tree{...}.

The tree is generic over its nodes. It never reads an entity field: a caller supplies the accessors and owns the state, and the tree only reports clicks. That is what lets one primitive back the Entities hierarchy, an asset folder listing, and a scene-layer list with no branch per caller.

  • Accessors: idOf(node), childrenOf(node), labelOf(node) — defaulting to node.id, node.children, and node.label/node.name.
  • Expand state is the caller's: pass an expanded set ({ [id] = true }) or an isExpanded(node, id) predicate, and handle onToggle(node, id).
  • Selection is the caller's: pass selected (an id, or an { [id] = true } set for multi-selection) and handle onSelect(node, id).
  • renderRow(node, row, selected) replaces the default label with your own content (badges, per-row icon buttons); return one widget or a list.

Flattening

flatten{ roots, ... } -> { { node, id, depth, hasChildren, expanded, parent } } is exported separately (edui.widgets.flattenTree) and is pure — no ui.* calls and no app — so display order is testable without a rendered frame. A node's children appear only while that node is expanded, so a collapsed tree costs nothing to build. A node that appears on its own ancestry is reported and skipped instead of recursing forever.

Row rendering

Rows are uniform-height, which is exactly the shape scrollArea's virtual prop wants — the renderer then draws only the band in view. Leaf rows still reserve the disclosure-chevron slot so every label at a given depth starts on the same column.

Row keys are stable ("<key>:<id>"), so the callback ids survive a rebuild and anything the renderer tracks by id (focus, ui.widgetState) stays put.

The disclosure chevron and the select target are siblings, never nested — a click lands on exactly one, so opening a node cannot also select it. The select target grows to fill the rest of the row, which is what keeps the whole row clickable rather than just the label. The selection background sits on the non-clickable row container so it spans the indent and chevron too.

Note that virtual is render-side windowing: the row widgets are still built for every visible node. Construction-side windowing (building only the scrolled band) needs the virtualTotal/virtualFirst scrollArea props, which are not on this branch.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

module edui.widgets.tree The editor hierarchy tree primitive — flattens a nested node graph into the rows that are actually visible under the current expand state, and renders them as indented, selectable `ui.*` rows inside a virtualized scroll area. The flatten pass is pure and separately exported, so row order is testable without a rendered frame.

defaultChildrenOf(node: any) → any

argtypedescription
nodeany

defaultIdOf(node: any) → any

argtypedescription
nodeany

defaultLabelOf(node: any) → string

argtypedescription
nodeany

flatten(o: { [string]: any }) →

Flatten `o.roots` into the ordered list of rows visible under the current expand state — a node's children are included only while that node is expanded. Pure: no `ui.*` calls, no app required. an `{ [id] = true }` set; `isExpanded(node, id) -> boolean` overrides it. depth 0 at the roots, in top-to-bottom display order.

argtypedescription
o{ [string]: any }`{ roots, childrenOf?, idOf?, expanded?, isExpanded? }`. `expanded` is

examples

local rows = edui.widgets.flattenTree{ roots = roots, expanded = { root = true } }

expandedFor(node: any, id: any) → boolean

argtypedescription
nodeany
idany

walk(nodes: any, depth: number, parent: any?) → void

argtypedescription
nodesany
depthnumber
parentany?

make(W: any) →

Bind the tree builder to a widgets barrel `W`. The barrel calls this once and exposes the result as `edui.tree`.

argtypedescription
WanyThe `edui.widgets` table (supplies palette/text/svgIcon/cbId/merge).

buildRow(o: { [string]: any }, r: Row, P: any, rowH: number, indent: number, selected: boolean) → any

One row: an indent-padded, selectable strip holding the disclosure chevron and the row content.

argtypedescription
o{ [string]: any }
rRow
Pany
rowHnumber
indentnumber
selectedboolean

isSelected(id: any) → boolean

argtypedescription
idany
⌬ Types
Row = {

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · editor/edui.package/widgets.module/tree.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.