Recursive tree of a Location's Space hierarchy (floors, rooms, zones,
sections, aisles, shelves) — an adaptation of
PhoenixKitWeb.Components.FolderExplorer.folder_tree_node/1 for
PhoenixKitLocations.Spaces.list_tree/1 nodes. Simplified relative to
that model: no desktop-only fixed-width sidebar and no drag/drop or
connector-line CSS — a single full-width column.
Node shape
Spaces.list_tree/1 returns a plain list of %Space{} structs — each
node carries its children directly under the schema's own :children
association key (Map.put(space, :children, ...)), not wrapped in
a %{space: ..., children: ...} envelope the way FolderExplorer's
%{folder: ..., children: ...} nodes are. Every field on a node is
read straight off the struct: node.kind, node.uuid, node.name,
node.status, node.children — never node.space.kind.
Ownership model
Pure presentation. The consumer owns all state (expanded MapSet,
selected_uuid, renaming_uuid/renaming_text) — every interactive
control fires back via phx-target={@myself}. Pass myself={nil} when
the consumer is a plain LiveView rather than a LiveComponent;
phx-target is then simply omitted, routing the event to the LiveView
itself.
Reorder (▲/▼) and rename are the only actions this component treats as
"immediate" — they fire their event straight away. Everything else
(creating a space, editing its other fields) is left to a form panel
owned by the consumer. delete_space is deliberately not immediate
either — no data-confirm here, since a hard delete cascades to the
whole subtree: the event just asks the consumer to open its own
confirmation modal (with the descendant count), which is the only
place the actual delete is triggered from.
Consumers implement:
toggle_space_node, select_space,
start_rename_space, rename_space_input, rename_space, cancel_rename_space,
move_space_up, move_space_down, open_add_child,
delete_space (opens a confirmation — does not delete by itself),
open_add_root (the "+ Add root space" button in `space_tree/1`)Picker mode
show_actions={false} hides the rename/reorder/add-child/delete
affordances on every node (and the wrapper's "+ Add root space"
button) and leaves only click-to-select + expand/collapse — the shape
PlacePicker (v0.5) needs to reuse this same tree read-only.
Usage
<.space_tree
tree={@tree}
expanded={@expanded}
selected_uuid={@selected_uuid}
myself={nil}
/>
Summary
Functions
Attributes
tree(:list) (required) - Root-level nodes fromSpaces.list_tree/1.expanded(:any) (required) - MapSet of expanded node UUIDs.selected_uuid(:string) - Defaults tonil.renaming_uuid(:string) - Defaults tonil.renaming_text(:string) - Defaults to"".myself(:any) - LiveComponent CID, or nil when the consumer is a plain LiveView. Defaults tonil.on_select(:string) - Defaults to"select_space".on_toggle(:string) - Defaults to"toggle_space_node".on_add_root(:string) - Defaults to"open_add_root".show_actions(:boolean) - false switches every node into picker/read-only mode (select + expand only). Defaults totrue.
Attributes
node(:map) (required) - A%Space{}struct with a nested:childrenlist (see moduledoc).expanded(:any) (required)selected_uuid(:string) - Defaults tonil.renaming_uuid(:string) - Defaults tonil.renaming_text(:string) - Defaults to"".depth(:integer) - Defaults to0.is_first(:boolean) - Hides the move-up button when true. Defaults totrue.is_last(:boolean) - Hides the move-down button when true. Defaults totrue.myself(:any) - Defaults tonil.on_select(:string) - Defaults to"select_space".on_toggle(:string) - Defaults to"toggle_space_node".show_actions(:boolean) - false hides pencil/reorder/add-child/delete — click-to-select + expand only. Defaults totrue.