# `Narabe.Components`
[🔗](https://github.com/hattoriai/narabe/blob/v0.1.0/lib/narabe/components.ex#L1)

Lists, trees and boards that people reorder: `sortable_list/1`,
`tree/1`, `board/1`, and `tree_picker/1` to choose a place in a tree.

    import Narabe.Components

    <.sortable_list id="tasks" items={@streams.tasks} on_move="move">
      <:item :let={task}>{task.title}</:item>
    </.sortable_list>

    <.tree id="pages" items={@pages} on_move="move" rules={[nest: true, max_depth: 6]} filter />

    <.board id="sprint" columns={@columns} cards={@cards} on_move="move_card" move_columns>
      <:column :let={column}>{column.name}</:column>
      <:card :let={card}>{card.title}</:card>
    </.board>

    <.tree_picker field={@form[:folder_id]} items={@folders} />

Items move with a mouse, a finger (a short hold), or the keyboard (Space
lifts, the arrows move, Space drops); several move together when
`multiple`. A drop moves them in the page at once and sends `on_move`
to the LiveView (or to `phx-target`), with the move as `Narabe.Move.parse/2`
reads it:

    %{"v" => 1, "ids" => ["7"], "parent" => nil, "after" => "3", "before" => "9", "index" => 2}

Reply `{:reply, %{ok: true}, socket}` to keep it, or `%{error: "..."}`
to put the items back (`Narabe.Live.reply/1` makes the reply from what
`Narabe.Ecto.move/4` returned). A refused move tells the person why.

The items are structs or maps; the component reads their id from `:id`
and a label for screen readers from `:name`, `:title` or `:label`, or
from the functions `item_id` and `item_label`. A list's items may be a
stream.

The lists need the `Narabe` hook in the LiveSocket and the Narabe CSS
(see the README).

# `board`

A board: columns of cards that people move within a column and across
them, and, with `move_columns`, columns that move too. A kanban, a
sprint, a pipeline.

`columns` are in their order; `cards` are flat, each with its column's
id (`card_column`, `:column_id` by default), in their order. A card's
move says its new column as `parent`; a column's move has `"columns" => true`.

Rules about kinds apply with the column's kind as the parent's
(`column_kind`), so a column may refuse some cards (`accepts`).

## Attributes

* `id` (`:string`) (required) - the element's id, and the list's in its events.
* `label` (`:string`) - the accessible name of the whole. Defaults to `nil`.
* `on_move` (`:string`) - the event of a move; without it, nothing moves. Defaults to `nil`.
* `on_select` (`:string`) - the event of a change of the selected items: `%{"v" => 1, "ids" => [...]}`. Defaults to `nil`.
* `rules` (`:any`) - what may go where: `Narabe.Rules`, its options, or a schema with `use Narabe.Ordered`. Defaults to `nil`.
* `multiple` (`:boolean`) - whether several items are selected and moved together. Defaults to `false`.
* `handle` (`:boolean`) - whether items drag by their handle only (a finger still holds them anywhere). Defaults to `false`.
* `readonly` (`:boolean`) - no moves, only focus and selection. Defaults to `false`.
* `locale` (`:string`) - the language of the words (`Narabe.Messages`). Defaults to `"en"`.
* `messages` (`:map`) - other words, by the keys of `Narabe.Messages.keys/0`. Defaults to `%{}`.
* `item_id` (`:any`) - an item's id: a key or a function. Defaults to `:id`.
* `item_label` (`:any`) - an item's label, for screen readers and the filter: a key or a function. Defaults to `nil`.
* `item_kind` (`:any`) - an item's kind, for the rules: a key or a function. Defaults to `nil`.
* `item_locked` (`:any`) - why an item may not move (a string), or nil: a key or a function. Defaults to `nil`.
* `issho` (`:list`) - the list's room with Issho (`Narabe.Issho`): `[instance: MyApp.Issho, document: "board:7/cards"]`. Defaults to `nil`.
* `user` (`:any`) - the person, with `issho`. Defaults to `nil`.
* `class` (`:any`) - Defaults to `nil`.
* `columns` (`:list`) (required) - the columns, in their order.
* `cards` (`:list`) (required) - the cards, flat, in their order.
* `card_column` (`:any`) - a card's column id: a key or a function. Defaults to `:column_id`.
* `column_id` (`:any`) - Defaults to `:id`.
* `column_label` (`:any`) - Defaults to `nil`.
* `column_kind` (`:any`) - Defaults to `nil`.
* `move_columns` (`:boolean`) - whether the columns move too. Defaults to `false`.
* Global attributes are accepted. Supports all globals plus: `["phx-target"]`.
## Slots

* `column` - a column's header, given the column as `:let`; its label by default.
* `item` - a card's content, given the card as `:let`; its label by default.
* `card` - the same as `item`.
* `actions` - buttons a finger swipes into view (a phone), given the card as `:let`.
* `footer` - the end of each column (an "Add a card" button), given the column as `:let`.

# `sortable_list`

A list that people reorder: tasks, a playlist, a menu's links.

`items` is a list or a stream (`@streams.tasks`). With a stream, insert
and delete as usual; after a move, `Narabe.Live.stream_move/4` puts the
item in its new place for every other viewer.

## Attributes

* `id` (`:string`) (required) - the element's id, and the list's in its events.
* `label` (`:string`) - the accessible name of the whole. Defaults to `nil`.
* `on_move` (`:string`) - the event of a move; without it, nothing moves. Defaults to `nil`.
* `on_select` (`:string`) - the event of a change of the selected items: `%{"v" => 1, "ids" => [...]}`. Defaults to `nil`.
* `rules` (`:any`) - what may go where: `Narabe.Rules`, its options, or a schema with `use Narabe.Ordered`. Defaults to `nil`.
* `multiple` (`:boolean`) - whether several items are selected and moved together. Defaults to `false`.
* `handle` (`:boolean`) - whether items drag by their handle only (a finger still holds them anywhere). Defaults to `false`.
* `readonly` (`:boolean`) - no moves, only focus and selection. Defaults to `false`.
* `locale` (`:string`) - the language of the words (`Narabe.Messages`). Defaults to `"en"`.
* `messages` (`:map`) - other words, by the keys of `Narabe.Messages.keys/0`. Defaults to `%{}`.
* `item_id` (`:any`) - an item's id: a key or a function. Defaults to `:id`.
* `item_label` (`:any`) - an item's label, for screen readers and the filter: a key or a function. Defaults to `nil`.
* `item_kind` (`:any`) - an item's kind, for the rules: a key or a function. Defaults to `nil`.
* `item_locked` (`:any`) - why an item may not move (a string), or nil: a key or a function. Defaults to `nil`.
* `issho` (`:list`) - the list's room with Issho (`Narabe.Issho`): `[instance: MyApp.Issho, document: "board:7/cards"]`. Defaults to `nil`.
* `user` (`:any`) - the person, with `issho`. Defaults to `nil`.
* `class` (`:any`) - Defaults to `nil`.
* `items` (`:any`) (required) - the items, in their order: a list or a stream.
* Global attributes are accepted. Supports all globals plus: `["phx-target"]`.
## Slots

* `item` - an item, given as `:let`; its label by default.
* `actions` - buttons a finger swipes into view (a phone), given the item as `:let`.

# `tree`

A tree that people reorder and nest: pages, folders and files, an
outline.

`items` is flat, as the database has it: each with its parent's id
(`item_parent`, `:parent_id` by default), in their order. The tree shows
each under its parent (`Narabe.Tree.rows/2`); a deep tree is fine.

Rows open and close with a click on their arrow, or Left and Right. With
`on_expand`, an item with children not loaded yet (`item_children`)
sends `%{"v" => 1, "id" => id}` as it opens: add its children to `items`.

With `filter`, a box above the tree shows the items that match, and
their ancestors. With `on_rename`, F2 or a double click on a label
renames the item in place and sends `%{"v" => 1, "id" => id, "name" => name}`.

On a phone, a tree shows as a tree, or one level at a time with
`phone={:drill}`.

## Attributes

* `id` (`:string`) (required) - the element's id, and the list's in its events.
* `label` (`:string`) - the accessible name of the whole. Defaults to `nil`.
* `on_move` (`:string`) - the event of a move; without it, nothing moves. Defaults to `nil`.
* `on_select` (`:string`) - the event of a change of the selected items: `%{"v" => 1, "ids" => [...]}`. Defaults to `nil`.
* `rules` (`:any`) - what may go where: `Narabe.Rules`, its options, or a schema with `use Narabe.Ordered`. Defaults to `nil`.
* `multiple` (`:boolean`) - whether several items are selected and moved together. Defaults to `false`.
* `handle` (`:boolean`) - whether items drag by their handle only (a finger still holds them anywhere). Defaults to `false`.
* `readonly` (`:boolean`) - no moves, only focus and selection. Defaults to `false`.
* `locale` (`:string`) - the language of the words (`Narabe.Messages`). Defaults to `"en"`.
* `messages` (`:map`) - other words, by the keys of `Narabe.Messages.keys/0`. Defaults to `%{}`.
* `item_id` (`:any`) - an item's id: a key or a function. Defaults to `:id`.
* `item_label` (`:any`) - an item's label, for screen readers and the filter: a key or a function. Defaults to `nil`.
* `item_kind` (`:any`) - an item's kind, for the rules: a key or a function. Defaults to `nil`.
* `item_locked` (`:any`) - why an item may not move (a string), or nil: a key or a function. Defaults to `nil`.
* `issho` (`:list`) - the list's room with Issho (`Narabe.Issho`): `[instance: MyApp.Issho, document: "board:7/cards"]`. Defaults to `nil`.
* `user` (`:any`) - the person, with `issho`. Defaults to `nil`.
* `class` (`:any`) - Defaults to `nil`.
* `items` (`:list`) (required) - the items, flat, in their order.
* `item_parent` (`:any`) - an item's parent's id: a key or a function. Defaults to `:parent_id`.
* `item_children` (`:any`) - whether an item has children not loaded yet: a key or a function. Defaults to `nil`.
* `expanded` (`:list`) - the ids of the items open at first. Defaults to `[]`.
* `on_expand` (`:string`) - the event of an item opened whose children are not loaded. Defaults to `nil`.
* `on_rename` (`:string`) - the event of a rename; without it, no renaming. Defaults to `nil`.
* `filter` (`:boolean`) - whether a box filters the items. Defaults to `false`.
* `phone` (`:atom`) - how the tree shows on a phone. Defaults to `:tree`. Must be one of `:tree`, or `:drill`.
* Global attributes are accepted. Supports all globals plus: `["phx-target"]`.
## Slots

* `item` - an item's content, given the item as `:let`; its label by default.
* `actions` - buttons a finger swipes into view (a phone), given the item as `:let`.

# `tree_picker`

A field of a form that chooses an item of a tree: a folder to move
files to, a parent page, a category. It posts the item's id, as a
`<select>` would; `disabled` items are shown and not offered (the item
being moved, and those under it).

    <.tree_picker field={@form[:parent_id]} items={@pages} disabled={[@page.id]} />

On a phone it shows one level at a time unless `phone={:tree}`.

## Attributes

* `id` (`:string`) - Defaults to `nil`.
* `field` (`Phoenix.HTML.FormField`) - the form's field. Defaults to `nil`.
* `name` (`:string`) - Defaults to `nil`.
* `value` (`:any`) - Defaults to `nil`.
* `label` (`:string`) - Defaults to `nil`.
* `items` (`:list`) (required) - the items, flat, in their order.
* `item_id` (`:any`) - Defaults to `:id`.
* `item_label` (`:any`) - Defaults to `nil`.
* `item_kind` (`:any`) - Defaults to `nil`.
* `item_parent` (`:any`) - Defaults to `:parent_id`.
* `item_children` (`:any`) - Defaults to `nil`.
* `disabled` (`:list`) - ids that may not be chosen (and the items under them). Defaults to `[]`.
* `expanded` (`:list`) - the ids open at first; by default, the chosen item's ancestors. Defaults to `nil`.
* `on_expand` (`:string`) - Defaults to `nil`.
* `filter` (`:boolean`) - Defaults to `true`.
* `phone` (`:atom`) - Defaults to `:drill`. Must be one of `:tree`, or `:drill`.
* `rules` (`:any`) - Defaults to `nil`.
* `locale` (`:string`) - Defaults to `"en"`.
* `messages` (`:map`) - Defaults to `%{}`.
* `class` (`:any`) - Defaults to `nil`.
* Global attributes are accepted. Supports all globals plus: `["phx-target"]`.
## Slots

* `item`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
