Visualize.Chart.Builder.Library (Visualize v0.2.35)

Copy Markdown View Source

The builder's library: the store's fragments as a tree (spec/14 §18.16).

A Visualize.Chart.Builder.Store is a flat map of name to fragment (§18.3), and a library of any size is unusable as a dropdown. The tree groups by what the name carries:

<category>:<sub-category>:<fragment name>

Frame:axes:dense ticks is dense ticks, under axes, under Frame. Nothing is classified anywhere else — no metadata beside the fragment, nothing derived from the keys it happens to set — so a category exists because some item names it, and inventing one is typing it (D-97).

The parse is total and forgiving, because a store populated before this existed must keep working: two parts is a category and a name, one part is a name under Uncategorised, and an empty sub-category and the literal none are the same absent thing.

This module compiles only when Phoenix.Component is loaded (spec/10 §1.1, D-45, D-85).

Summary

Types

A stored name pulled apart: its category, its sub-category and its own name.

Functions

Entries as the kind tree (spec/14 §19.8): one group per kind, the kinds a library item is usually one of always present, empty or not, and any other kind when an entry has it. Items within a kind sort by name; each carries its group as a second line.

The categories a set of stored names names, in name order.

A category, sub-category and name as the name to store it under (spec/14 §18.16).

Renders the library (spec/10 §15.3).

A stored name as {category, sub_category, name} (spec/14 §18.16).

The sub-categories one category has, in name order, without the unnamed group.

Stored names as the tree the panel draws (spec/14 §18.16).

Types

place()

@type place() :: {String.t(), String.t() | nil, String.t()}

A stored name pulled apart: its category, its sub-category and its own name.

Functions

by_kind(entries)

@spec by_kind([map()]) :: [%{kind: atom(), items: [map()]}]

Entries as the kind tree (spec/14 §19.8): one group per kind, the kinds a library item is usually one of always present, empty or not, and any other kind when an entry has it. Items within a kind sort by name; each carries its group as a second line.

iex> entries = [
...>   %{id: {:style, 1}, name: "Styles::thick", kind: :style},
...>   %{id: {:size, 1}, name: "Frame:size:wide", kind: :size}
...> ]
iex> tree = Visualize.Chart.Builder.Library.by_kind(entries)
iex> Enum.map(tree, &{&1.kind, length(&1.items)})
[composite: 0, theme: 0, style: 1, frame: 0, scale: 0, axis: 0, source: 0, var: 0, mark: 0, label: 0, size: 1]

categories(stored)

@spec categories([String.t() | atom()]) :: [String.t()]

The categories a set of stored names names, in name order.

iex> Visualize.Chart.Builder.Library.categories(["Theme::dark", "Frame::wide"])
["Frame", "Theme"]

name(category, sub_category, name)

@spec name(String.t(), String.t() | nil, String.t()) :: String.t()

A category, sub-category and name as the name to store it under (spec/14 §18.16).

The inverse of parse/1 for every name this builds; nil, "" and "none" are all written as the empty sub-category, so one absent sub-category has one spelling on disk.

iex> Visualize.Chart.Builder.Library.name("Frame", "axes", "dense ticks")
"Frame:axes:dense ticks"

iex> Visualize.Chart.Builder.Library.name("Styles", nil, "thick line")
"Styles::thick line"

iex> Visualize.Chart.Builder.Library.name("Styles", "none", "thick line")
"Styles::thick line"

panel(assigns)

Renders the library (spec/10 §15.3).

An <aside class="vis-builder-library-pane"> holding one section per category, each with one list per sub-category, each item draggable by its stored name. Every top-level header is a button that folds its section (#355): folded, the header stays with the count of what it hides and the items are not rendered.

Attributes

  • entries (:list) (required) - the store's entries, as Store.list/1 returns them.
  • view (:atom) - :group, the default, or :kind (spec/14 §19.8). Defaults to :group.
  • open (:any) - the id last acted on, marked in the tree. Defaults to nil.
  • folded (:any) - the top-level headers folded, by name (spec/14 §18.16, #355). Defaults to MapSet.new([]).
  • target (:any) - the phx-target of the library's events. Defaults to nil.
  • id (:string) (required) - the hook element's id.
  • class (:string) - appended to the library's class. Defaults to nil.

parse(stored)

@spec parse(String.t() | atom()) :: place()

A stored name as {category, sub_category, name} (spec/14 §18.16).

The split takes the first two separators, so a fragment's own name may contain one. An absent sub-category is nil, which both an empty part and the literal none mean.

iex> Visualize.Chart.Builder.Library.parse("Frame:axes:dense ticks")
{"Frame", "axes", "dense ticks"}

iex> Visualize.Chart.Builder.Library.parse("Styles::thick line")
{"Styles", nil, "thick line"}

iex> Visualize.Chart.Builder.Library.parse("Theme:none:dark")
{"Theme", nil, "dark"}

iex> Visualize.Chart.Builder.Library.parse("Frame:dense ticks")
{"Frame", nil, "dense ticks"}

iex> Visualize.Chart.Builder.Library.parse("dark")
{"Uncategorised", nil, "dark"}

iex> Visualize.Chart.Builder.Library.parse("Frame:aspect:2:1 aspect")
{"Frame", "aspect", "2:1 aspect"}

sub_categories(stored, category)

@spec sub_categories([String.t() | atom()], String.t()) :: [String.t()]

The sub-categories one category has, in name order, without the unnamed group.

iex> names = ["Frame:axes:dense", "Frame::wide", "Theme:mood:dark"]
iex> Visualize.Chart.Builder.Library.sub_categories(names, "Frame")
["axes"]

tree(entries)

@spec tree([map()]) :: [map()]

Stored names as the tree the panel draws (spec/14 §18.16).

One entry per category in name order; within it one group per sub-category, the unnamed group first and the rest in name order, because a fragment sitting directly under its category is the general case and the sub-categories refine it.

iex> entries = [
...>   %{id: {:theme, 32}, name: "Theme::dark", kind: :theme},
...>   %{id: {:axis, 2}, name: "Frame:axes:dense", kind: :axis},
...>   %{id: {:size, 1}, name: "Frame::wide", kind: :size}
...> ]
iex> Visualize.Chart.Builder.Library.tree(entries)
[
  %{category: "Frame", groups: [
    %{sub_category: nil, items: [%{id: {:size, 1}, stored: "Frame::wide", name: "wide", kind: :size}]},
    %{sub_category: "axes", items: [%{id: {:axis, 2}, stored: "Frame:axes:dense", name: "dense", kind: :axis}]}
  ]},
  %{category: "Theme", groups: [
    %{sub_category: nil, items: [%{id: {:theme, 32}, stored: "Theme::dark", name: "dark", kind: :theme}]}
  ]}
]