# `Masu.Components`
[🔗](https://github.com/hattoriai/masu/blob/v0.7.0/lib/masu/components.ex#L1)

The grid component.

    import Masu.Components

    <.data_grid id="users" rows={@users} label="Users">
      <:col field={:name} />
      <:col field={:email} />
      <:col field={:inserted_at} type={:datetime} label="Joined" />
    </.data_grid>

`data_grid/1` goes in a LiveView. It needs the `Masu` hook in the
LiveSocket and the Masu CSS (see the README). The rows come from a
list (`rows`), or from an Ecto query or schema and a repo (`source` and
`repo`), which then sorts, filters and counts in the database; see the
[Sources](sources.md) guide.

# `data_grid`

Renders a data grid.

The browser draws only the rows on the screen, and asks the grid for
the others as the person scrolls. A click on a column's header sorts by
it (with Shift, by it too); the edge of a header resizes its column,
and a double click there fits the column to its content. The arrow keys
move between the cells, Shift with them selects a range, and ⌘C (Ctrl+C)
copies the range as text that a spreadsheet pastes.

## Columns

Each `:col` is a column (see `Masu.Column`):

  * `field` - the key of the row's value (a map key or a struct field);
  * `value` - a function of the row that computes the value instead;
    it needs a `key`, and does not sort or filter with an Ecto source;
  * `key` - the name of the column in `Masu.Test` and in filters; the
    field as a string unless given;
  * `label` - the header; the field in words unless given;
  * `type` - `:text` (the default), `:enum`, `:integer`, `:number`,
    `:decimal`, `:date`, `:datetime`, `:time` or `:boolean`;
  * `width` and `min_width` - in pixels;
  * `grow` - `true` takes the room the columns leave in a wider grid, from
    its width up (a title, a description); a number is its share of it,
    `grow={2}` twice that of `grow`;
  * `align` - `:start`, `:center` or `:end` (numbers are at the end);
  * `sortable`, `filterable` and `searchable` - `false` to turn off,
    `searchable` is on for text and enums;
  * `editable` - in a grid that edits: `false` for a read-only column, or
    a function of the row that says whether its cell edits;
  * `values` - the values of an `:enum` column, which its editor offers;
  * `decimals` - the digits after the point of a `:decimal` or `:number`
    column, whatever the value has;
  * `filters` - the `Masu.Filter` operators the column offers, of its
    type: those the app runs, in a controlled grid (`on_query`).
  * `editor` - an editor of your own for its cells: a function component
    of a form field (a Koyomi picker, a Kotoba editor, any HEEx), or the
    name of an editor of the browser's; see the Editors of your own
    guide.

A `:col` with content renders each cell, with the row as `:let`:

    <:col :let={user} field={:name}>
      <.link navigate={~p"/users/#{user}"}>{user.name}</.link>
    </:col>

## Writes and actions

A grid with a `changeset` edits its cells, and with `struct` and
`deletable` adds and deletes rows, its own way; `on_update`,
`on_create`, `on_delete` and `on_restore` write them your way, each a
function of a `Masu.Write`; see the [Editing](editing.md) guide.
`history` keeps who changed each cell, when, and from what, and brings
a value back; see `Masu.History` and the [History](history.md) guide.
`:action` acts on the rows selected, and `:row_action` on a row; see
`Masu.Action` and the [Actions](actions.md) guide. `on_row_activate`
opens a row (a panel beside the grid, its page) on a click on it or
Enter. `scope` is in every write and every action.

## Menus

`cell_menu` gives each cell a menu (a right click, or the context-menu
key or Shift+F10 on the active cell): copy, filter by the cell's value,
sort. `:header_action` and `:cell_action` add items of your own to the
header menus and to the menu of the cells; see `Masu.Action` and the
[Menus of your own](menus.md) guide.

## Attributes

* `id` (`:string`) (required) - the id of the grid.
* `rows` (`:list`) - the rows: maps or structs, or lists of values (see `columns`), up to about 10,000; past that, an Ecto `source` (see the Sources guide). Defaults to `nil`.
* `columns` (`:list`) - for a grid with no `:col` slots: its columns, each a key, or a keyword list or map of a `:col`'s attributes; without a `field`, a column reads the row at its place (rows as lists), and without a `type`, it takes the type of its values (`:auto`); see the Columns guide. Defaults to `nil`.
* `source` (`:any`) - an Ecto query or schema (with `repo`), or `{module, opts}` of a `Masu.Source`. Defaults to `nil`.
* `repo` (`:atom`) - the repo of an Ecto source. Defaults to `nil`.
* `repo_opts` (`:list`) - options for each call to the repo. Defaults to `[]`.
* `read` (`:any`) - an Ecto source's read of a block of rows, your own: a function of the query (with the grid's filters, search and order) and `%{offset:, limit:, order:, after:}`, which gives the rows; see the Sources guide. Defaults to `nil`.
* `changeset` (`:any`) - a function of a row and params that gives a changeset: the person edits the cells, which the grid saves its own way (`Masu.Write.save/1`), see the Editing guide. Defaults to `nil`.
* `struct` (`:any`) - with `changeset`: the struct of a new row (or a function that gives it), which the changeset casts and the repo inserts; the person adds rows. Defaults to `nil`.
* `create_with` (`:any`) - fields every new row gets, as a map or keyword list (`%{account_id: @current_scope.account.id}`): put on `struct` before the changeset and again after it, so params cannot change them; the person neither sets nor edits a cell of these fields. Defaults to `nil`.
* `on_update` (`:any`) - a function of a `Masu.Write` of edited cells, which saves them and gives the write back with their results; the person edits the cells, see `Masu.Write`. Defaults to `nil`.
* `on_create` (`:any`) - a function of a `Masu.Write` of new rows, as `on_update`; the person adds rows. Defaults to `nil`.
* `on_delete` (`:any`) - a function of a `Masu.Write` of rows to delete, as `on_update`; the person deletes rows. Defaults to `nil`.
* `on_restore` (`:any`) - a function of a `Masu.Write` of deleted rows to bring back (an undo), as `on_update`; a grid that deletes its own way brings them back its own way. Defaults to `nil`.
* `deletable` (`:any`) - `true` to delete rows (the grid's own way: with the repo of an Ecto source, or from a list; or with `on_delete`), `false` never, or a function of a row that says whether it deletes. Defaults to `nil`.
* `row_editable` (`:any`) - a function of a row: `false` makes every cell of the row read-only. Defaults to `nil`.
* `history` (`:atom`) - a `Masu.History` store: the grid records who changed each cell, when, from what to what, and a person sees a cell's history and brings a value back; `user` says who. Defaults to `nil`.
* `scope` (`:any`) - what your app knows of the person (`@current_scope`): every `Masu.Write` and every action's context has it. Defaults to `nil`.
* `live` (`:any`) - `{pubsub, topic}`: shows the rows that change on the topic as they change, see `Masu.Live`. Defaults to `nil`.
* `presence` (`:any`) - removed in 0.4: a grid's people are those of an Issho room, `issho`; see the Upgrading guide. Defaults to `nil`.
* `issho` (`:any`) - the grid's people, in an Issho room: `[instance: MyApp.Issho, document: "notebook:42/tasks"]`, with the keys of every component (`Issho.Join`): the grid's `document` (its name, the same wherever it is: its page, a document; its room is the part before the first `"/"`), `can`, `people` (`false` hides the avatars above the grid, on a page that lists its people itself), `follow` (`false` for a grid that takes no part in following), `claims` and `on_behalf_of`; and Masu's own `actor` (the person as the room knows them; `user` unless given). Agents in the room are among them; see the Collaboration guide. Defaults to `nil`.
* `people` (`:any`) - removed in 0.5: `issho`'s `:people`. Defaults to `nil`.
* `follow` (`:any`) - removed in 0.5: `issho`'s `:follow`. Defaults to `nil`.
* `user` (`:map`) - with `presence` or `issho`: this person, `%{id: ..., name: ..., color: ..., avatar: ...}`. Defaults to `nil`.
* `url` (`:boolean`) - when `true`, the person's view (order, filters, search, columns) goes into the URL's params, under the grid's id, and a link opens it; see `Masu.View`. Defaults to `false`.
* `views` (`:atom`) - a `Masu.Views` store: the grid keeps each person's last view, and a views menu saves named views; needs `user`. Defaults to `nil`.
* `views_key` (`:string`) - with `views`: the name of the grid in the store; its id unless given. Defaults to `nil`.
* `views_scope` (`:any`) - with `views`: whose views these are, such as the account's id; the store keeps each scope's views apart, so a view shared in one is not offered in another. Defaults to `nil`.
* `columns_menu` (`:boolean`) - when `true`, a columns menu to show, hide, pin and move columns. Defaults to `false`.
* `share_view` (`:boolean`) - with `issho`: whether the person's order, filters and search go to the others, who see them when they follow the person. Defaults to `true`.
* `selectable` (`:boolean`) - rows with a box to select them, and every row of the query at once; see `Masu.Live.selected/1`. Defaults to `false`.
* `on_select` (`:any`) - a function called with `%{count: n, all: boolean}` when the selection changes. Defaults to `nil`.
* `on_row_activate` (`:any`) - a function called with `%{id: id, row: row, grid: id, scope: scope}` when the person opens a row: a click on it, or Enter on its active cell, where the cell does not edit. It gives `{:patch, path}` or `{:navigate, path}` for the grid to follow, or anything else; see the Actions guide. Defaults to `nil`.
* `export` (`:any`) - an Export menu: `true` for CSV and XLSX, or a list of `:csv` and `:xlsx`; `false` (the default) has none, and the server exports nothing; see `Masu.Export`. Defaults to `false`.
* `cell_menu` (`:any`) - a menu on each cell (a right click, or the context-menu key or Shift+F10 on the active cell): `true` for its built-in items, or a list of `:copy`, `:filter` and `:sort`; `false` (the default) has only the `:cell_action` items, if any; see `Masu.Action`. Defaults to `false`.
* `group_by` (`:any`) - the keys of the columns the rows start grouped by, the first the outermost; see `Masu.Group`. Defaults to `[]`.
* `tree` (`:any`) - rows in a tree: the field of a row that holds its parent's id (or a function of the row); see `Masu.Tree`. Defaults to `nil`.
* `expanded` (`:any`) - the rows that start open: with `tree`, the ids of the rows; with groups, `:all` for every group at every level, or the keys of the columns whose groups start open (`[:status]`); see `Masu.Group`. Defaults to `[]`.
* `count` (`:atom`) - how the grid counts its rows: `:exact` with the query, `:deferred` after the first rows (in a task), `:none` only when the person goes to the end; see the Export, selection and large tables guide. Defaults to `:exact`. Must be one of `:exact`, `:deferred`, or `:none`.
* `count_limit` (`:integer`) - the most rows an Ecto source counts: past it, the grid says it has at least that many ("10,000+"), and counts them all when the person goes to the end; see the Export, selection and large tables guide. Defaults to `nil`.
* `paging` (`:atom`) - `:pages` shows a page of rows at a time, with a pager below the grid, and the page in the view. Defaults to `:scroll`. Must be one of `:scroll`, or `:pages`.
* `page_size` (`:integer`) - with `paging={:pages}`: the rows of a page, read from the source at once (at most `max_block`). Defaults to `50`.
* `block_size` (`:integer`) - the rows the grid reads from its source at once as the person scrolls (at most `max_block`). Defaults to `100`.
* `max_block` (`:integer`) - the most rows of one read from the source: higher for a source where a read is costly and rows are small; see the Export, selection and large tables guide. Defaults to `500`.
* `load` (`:atom`) - how the grid reads its source: `:inline` (the default) in the event, `:async` in a task, for a slow source: the LiveView answers meanwhile, the grid says it runs, with Stop; see the Sources guide. Defaults to `:inline`. Must be one of `:inline`, or `:async`.
* `timeout` (`:integer`) - with `load={:async}`: the milliseconds a read may take, then it stops and the grid says so. Defaults to `nil`.
* `on_query` (`:any`) - a controlled grid: the LiveView runs the query. The grid shows `rows` as they are, and calls this function with `%{query: %Masu.Query{}, page: n, offset: n, limit: n}` when the person sorts, filters, searches or goes to a page; see the Sources guide. Defaults to `nil`.
* `total` (`:integer`) - with `on_query`: how many rows the LiveView's query has (its rows are a page of them). Defaults to `nil`.
* `loading` (`:boolean`) - with `on_query`: the LiveView runs its query; the grid says so, and keeps its rows until the new ones come. Defaults to `false`.
* `multi_sort` (`:boolean`) - `false` sorts by one column at a time: Shift adds none. Defaults to `true`.
* `filter_bar` (`:boolean`) - the filter bar: the chips of the filters and Add filter above the grid, and on each header a menu of its sorts and filter; `false` for the leaner header, a funnel on each header that filters; see the Filters guide. Defaults to `true`.
* `header_filters` (`:boolean`) - whether a header's menu has its column's filter; `false` with the filter bar: the filters are the bar's alone, and a header's menu has its sorts; see the Filters guide. Defaults to `true`.
* `row_id` (`:any`) - a function that gives a row's id; the `id` of the row unless given, or its place in the query for a row without one in a grid that needs no ids. `:position`: the place in the query, always, for a read-only grid of rows with no id; see the Sources guide. Defaults to `nil`.
* `sort` (`:list`) - the first order: keys, `{key, :asc | :desc}` or `Masu.Sort` structs. Defaults to `[]`.
* `filters` (`:list`) - the first filters: `{key, op, value}` or `Masu.Filter` structs. Defaults to `[]`.
* `searchable` (`:boolean`) - when `true`, a search box above the grid. Defaults to `false`.
* `label` (`:string`) - the name of the grid for a screen reader. Defaults to `nil`.
* `label_id` (`:string`) - the id of an element that names the grid. Defaults to `nil`.
* `density` (`:atom`) - the room around a cell's text: rows of 28, 36 or 48 pixels and their padding, unless `row_height` is given. Defaults to `:normal`. Must be one of `:compact`, `:normal`, or `:comfortable`.
* `row_height` (`:integer`) - the height of a row, in pixels; of the `density` unless given. Defaults to `nil`.
* `height` (`:string`) - the height of the whole grid, as CSS (`100%` fills its container); the rows take what its toolbar leaves; `"auto"`: the height of its rows, up to `max_height` (a grid in a document). Defaults to `"32rem"`.
* `max_height` (`:string`) - with `height="auto"`: the most the rows take, as CSS; past it, they scroll. Defaults to `"32rem"`.
* `wheel` (`:atom`) - `:page` for a grid in a page that scrolls (a document): the wheel scrolls the page until the person is in the grid (a click, the keyboard), and the grid then. Defaults to `:grid`. Must be one of `:grid`, or `:page`.
* `view` (`:map`) - the view the grid opens with: a view's params (`Masu.View`), such as a saved view's (`Masu.Views`); a link's view (`url`) wins over it, and it over the person's last view. Defaults to `nil`.
* `locale` (`:string`) - the locale that formats numbers and dates; the browser's unless given. Defaults to `nil`.
* `messages` (`:map`) - words that replace the built-in ones, by key (`search`, `empty`, `rows`...): `Masu.Messages` has every key, for a grid in another language. Defaults to `%{}`.
* `class` (`:any`) - classes for the grid element. Defaults to `nil`.
* Global attributes are accepted. attributes for the grid element.
## Slots

* `col` - a column; without any, the columns are `columns`, or the source's. Accepts attributes:

  * `field` (`:any`)
  * `value` (`:any`)
  * `key` (`:string`)
  * `label` (`:string`)
  * `type` (`:atom`)
  * `width` (`:integer`)
  * `min_width` (`:integer`)
  * `grow` (`:any`)
  * `align` (`:atom`)
  * `sortable` (`:boolean`)
  * `filterable` (`:boolean`)
  * `searchable` (`:boolean`)
  * `editable` (`:any`)
  * `values` (`:list`)
  * `decimals` (`:integer`)
  * `raw` (`:boolean`)
  * `hidden` (`:boolean`)
  * `pinned` (`:atom`)
  * `aggregate` (`:any`)
  * `filters` (`:list`)
  * `editor` (`:any`)
* `header_action` - an item of each column's header menu: a function, an event to the LiveView, a JS command, or a panel of its content; see `Masu.Action`. Accepts attributes:

  * `label` (`:string`) (required)
  * `on_action` (`:any`)
  * `event` (`:string`)
  * `js` (`:any`)
  * `columns` (`:list`)
  * `types` (`:list`)
  * `show` (`:any`)
* `cell_action` - an item of the menu of a cell, as `:header_action`; see `Masu.Action`. Accepts attributes:

  * `label` (`:string`) (required)
  * `on_action` (`:any`)
  * `event` (`:string`)
  * `js` (`:any`)
  * `columns` (`:list`)
  * `types` (`:list`)
  * `show` (`:any`)
* `action` - an action on the rows selected, a button of the bar above the grid while rows are selected; needs `selectable`; see `Masu.Action`. Accepts attributes:

  * `label` (`:string`) (required)
  * `on_action` (`:any`)
  * `event` (`:string`)
  * `confirm` (`:string`)
  * `danger` (`:boolean`)
  * `keep_selection` (`:boolean`)
* `row_action` - an action on a row, in the menu at the end of each row and in the menu of its cells: a function, an event, or a link (`navigate`, `patch`); see `Masu.Action`. Accepts attributes:

  * `label` (`:string`) (required)
  * `on_action` (`:any`)
  * `event` (`:string`)
  * `navigate` (`:any`)
  * `patch` (`:any`)
  * `show` (`:any`)
  * `disabled` (`:any`)
  * `confirm` (`:string`)
  * `danger` (`:boolean`)
* `empty` - what the grid shows when it has no rows.
* `detail` - what a row shows when it opens, under it: any HEEx, another `data_grid` too; it gets the row.
* `person` - draws a person who has the grid open (`:let`), see the Collaboration guide; initials in their color unless given.

---

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