Hakushi.Components (Hakushi v0.1.0)

Copy Markdown View Source

Function components for the canvas.

import Hakushi.Components

<.canvas id="schema" graph={@graph} on_change={&Schema.change/2}>
  <:node type="table" :let={node}>
    <div class="table">
      <h3>{node.data.name}</h3>
      <div :for={column <- node.data.columns} class="relative">
        <.handle id={column.name} kind={:target} side={:left} />
        {column.name}
        <.handle id={column.name} kind={:source} side={:right} />
      </div>
    </div>
  </:node>
</.canvas>

canvas/1 needs the Hakushi hook in the LiveSocket and the Hakushi CSS (see the README).

Summary

Functions

Renders a canvas: an endless sheet that people pan and zoom, with the nodes of graph on it, drawn by the :node slots, and its edges.

Renders an item that people drag onto a canvas, outside it: a palette of the things the canvas makes. Dropped on the canvas, it becomes the node that the canvas's new_node gives for item. Enter or a click puts it in the middle of the canvas, for the keyboard and for a touch screen.

Renders a handle: a point of a node where edges start (:source), end (:target), or both.

Functions

canvas(assigns)

Renders a canvas: an endless sheet that people pan and zoom, with the nodes of graph on it, drawn by the :node slots, and its edges.

People move nodes by dragging them (or with the arrow keys), select them with a click, Shift and a box, connect them by dragging from a handle to a handle (or with C, see the Navigation guide), delete them with Delete, and copy, paste, duplicate, undo and redo with the usual keys. Each change goes to the server, which checks it (rules, then on_change) before anyone sees it, and takes it back in the browser when it refuses it.

Nodes

A :node slot draws the nodes of its type; a :node slot without a type draws the others. The slot gets the Hakushi.Node, and draws it from its data, with the handles where edges start and end (handle/1). A canvas with no :node slot draws each node as a box with its label.

A node is drawn once, and again when it changes: a change of its data (a change :update, or a new graph) draws it again; a change of the LiveView's own assigns does not.

The graph

Without live, the canvas keeps its own copy of graph, which its changes change. Give it a new graph (after the app's own change, say) and it shows what changed. With live, the graph is the room's (see Hakushi.Issho): make the app's changes with Hakushi.Live.change/2 or Hakushi.Issho.change/3.

Attributes

  • id (:string) (required) - the id of the canvas.
  • graph (Hakushi.Graph) (required) - the nodes and edges, a Hakushi.Graph.
  • on_change (:any) - fn change, context -> :ok | {:error, reason} end: the app's own check of each change, and where it saves it. context has the graph before the change and the result after it, the user and the canvas. See the Changes guide. Defaults to nil.

  • new_node (:any) - fn item, {x, y} -> node | nil end: the node for an item dropped on the canvas (canvas_item/1), or for a double click on the sheet (item is nil). A node with no id gets one. Defaults to nil.

  • rules (:list) - the rules of the edges, see Hakushi.Rules. Defaults to [].
  • live (:any) - {issho, topic}: a canvas that everyone in the Issho room topic shares, see Hakushi.Issho. Defaults to nil.
  • user (:map) - the person, on a shared canvas: a map with an :id, and a :name, :color and :avatar. Defaults to nil.
  • background (:atom) - the paper: dots, lines (graph paper), crosses, or none. Defaults to :dots. Must be one of :dots, :lines, :cross, or :none.
  • grid (:integer) - the size of a square of the paper, in pixels at 100%. Defaults to 20.
  • snap (:boolean) - when true, nodes snap to the paper's grid. Defaults to false.
  • wheel (:atom) - what the mouse wheel does: pan (and zoom with ⌘ or Ctrl), or zoom. Defaults to :pan. Must be one of :pan, or :zoom.
  • fit (:boolean) - when true, the canvas opens on all of its nodes. Defaults to true.
  • min_zoom (:float) - the smallest zoom. Defaults to 0.1.
  • max_zoom (:float) - the largest zoom. Defaults to 4.0.
  • minimap (:boolean) - when true, an overview of the canvas in a corner. Defaults to true.
  • controls (:boolean) - when true, buttons to zoom, fit, tidy up, undo and redo, and to download the canvas. Defaults to true.
  • layout (:atom) - the way the tidy up (⇧L, the controls) lays the nodes out: in layers from left to right, or from top to bottom; see Layout and export. Defaults to :right. Must be one of :right, or :down.
  • export (:boolean) - when true, a button of the controls downloads the canvas as an image. Defaults to true.
  • readonly (:boolean) - when true, people pan, zoom and select, and change nothing. Defaults to false.
  • label (:string) - the name of the canvas, for screen readers. Defaults to nil.
  • node_label (:any) - fn node -> text end: the name of a node for screen readers; the default is its data's label or name, or its id. Defaults to &Hakushi.Canvas.label/1.
  • locale (:string) - the locale of the canvas's own words; the default is config :hakushi, locale:, else "en". Defaults to nil.
  • messages (:map) - words that replace the built-in ones, see Hakushi.Messages. Defaults to nil.
  • class (:any) - classes for the canvas element. Defaults to nil.
  • Global attributes are accepted. attributes for the canvas element.

Slots

  • node - draws the nodes of a type (:let gets the Hakushi.Node). Accepts attributes:
    • type (:string) - the type of the nodes it draws; none for every other type.
    • resizable (:boolean) - when true, people resize these nodes by their corners.
    • group (:boolean) - when true, these nodes hold others: a node dropped on one goes in it, see Groups.
  • person - draws a person on a shared canvas (:let gets a map with "id", "name", "color", "avatar").
  • empty - shows on a canvas without nodes.

canvas_item(assigns)

Renders an item that people drag onto a canvas, outside it: a palette of the things the canvas makes. Dropped on the canvas, it becomes the node that the canvas's new_node gives for item. Enter or a click puts it in the middle of the canvas, for the keyboard and for a touch screen.

<.canvas_item for="schema" item="table">New table</.canvas_item>

Attributes

  • for (:string) (required) - the id of the canvas.
  • item (:string) (required) - what it makes, for new_node.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • inner_block (required)

handle(assigns)

Renders a handle: a point of a node where edges start (:source), end (:target), or both.

A handle sits on a side of its nearest positioned ancestor: the node, or an element of it with position: relative, as a row of a table whose edges start at the row.

<div :for={column <- node.data.columns} class="relative">
  {column.name}
  <.handle id={column.name} side={:right} type={column.type} />
</div>

A node may have several handles with one id, on different sides (a row with a handle at each end): an edge meets the one nearest its other end, so the line takes the short way whichever side the other node is on.

type and accepts say what connects to what: a handle connects to a handle that accepts its type (any, when accepts is nil). While a person draws an edge, the handles it may end on show, and no others.

Attributes

  • id (:string) - the id of the handle in its node, the edges' source_handle or target_handle. Defaults to nil.
  • kind (:atom) - where edges start (:source), end (:target), or both. Defaults to :both. Must be one of :source, :target, or :both.
  • side (:atom) - the side it sits on. Defaults to :right. Must be one of :left, :right, :top, or :bottom.
  • type (:string) - what its edges carry, for accepts. Defaults to nil.
  • accepts (:list) - the types it takes; nil for any. Defaults to nil.
  • max (:integer) - the most edges it has; nil for any number. Defaults to nil.
  • label (:string) - its name, for screen readers. Defaults to nil.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.