Liking cljdoc? Tell your friends :D

com.blockether.vis.view

Builders for the two things an extension shows the operator: the typed pause it WAITS on — com.blockether.vis.core/request-human-input! — and the live view it does not, com.blockether.vis.core/with-live-view!.

A request is plain data, and it stays plain data: every builder here returns the very map you could have typed by hand. What it adds is that the two things a hand-typed map gets wrong cannot happen. The node TYPE is the function you called, so :type "plaintxt" is a compile-time unresolved symbol instead of a refused request at run time; and the node is VALIDATED the moment it is built, by the engine's own com.blockether.vis.internal.view.core/normalize-node seam, so a bad :default, an unknown key or a :select with no options throws at the line that built it rather than in front of the human.

(require '[com.blockether.vis.core :as vis]
         '[com.blockether.vis.view :as view])

(vis/request-human-input!
  (view/form {:title "Deploy" :description "Where this build lands."}
             (view/heading "Target")
             (view/paragraph "Staging pages nobody.")
             (view/row (view/select "env" ["staging" "prod"] {:label "Environment"
                                                               :is-required true})
                       (view/slider "canary" {:label "Canary %" :min 0 :max 100 :step 5}))
             (view/password "token" {:label "Deploy token" :is-required true})))

Three node contracts, exactly as the engine sees them: a FIELD holds one answer and is keyed by its name, a GROUP (row / column) only arranges the nodes below it, and a DECORATION (heading / paragraph) is ink — no name, never focusable, never in the answer map.

Every optional key is the one the engine documents, in either spelling (:is-required or "is_required"): builders pass options through untouched instead of keeping a second copy of the vocabulary.

A LIVE VIEW is the same discipline one :kind further: view and the node builders under it declare a picture the human WATCHES while the work runs. It asks nothing and parks no thread; it is patched by node id and ends in a verdict carrying the markdown the model reads.

(vis/with-live-view!
  (view/view {:title "CI"}
             (view/status "now" "Polling GitHub…" {:tone "running"})
             (view/table "jobs" [(view/table-column "job" "Job")
                                 (view/table-column "took" "Took" {:align "right"})]))
  (fn [view-id]
    (vis/patch-live-view!
      view-id
      [{:op "set" :node-id "now" :text "18 jobs" :tone "ok"}
       {:op "append" :node-id "jobs"
        :rows [(view/table-row "build" ["tests / ubuntu" "13m0s"] {:tone "ok"})]}])))

Python extensions get the SAME names on the vis module — vis.select('env', ['staging', 'prod'], label='Environment') — built by the same engine seam across the JSON boundary.

Builders for the two things an extension shows the operator: the typed pause
it WAITS on — `com.blockether.vis.core/request-human-input!` — and the live
view it does not, `com.blockether.vis.core/with-live-view!`.

A request is plain data, and it stays plain data: every builder here returns
the very map you could have typed by hand. What it adds is that the two
things a hand-typed map gets wrong cannot happen. The node TYPE is the
function you called, so `:type "plaintxt"` is a compile-time unresolved
symbol instead of a refused request at run time; and the node is VALIDATED
the moment it is built, by the engine's own [[com.blockether.vis.internal.view.core/normalize-node]]
seam, so a bad `:default`, an unknown key or a `:select` with no options
throws at the line that built it rather than in front of the human.

    (require '[com.blockether.vis.core :as vis]
             '[com.blockether.vis.view :as view])

    (vis/request-human-input!
      (view/form {:title "Deploy" :description "Where this build lands."}
                 (view/heading "Target")
                 (view/paragraph "Staging pages nobody.")
                 (view/row (view/select "env" ["staging" "prod"] {:label "Environment"
                                                                   :is-required true})
                           (view/slider "canary" {:label "Canary %" :min 0 :max 100 :step 5}))
                 (view/password "token" {:label "Deploy token" :is-required true})))

Three node contracts, exactly as the engine sees them: a FIELD holds one
answer and is keyed by its name, a GROUP ([[row]] / [[column]]) only arranges
the nodes below it, and a DECORATION ([[heading]] / [[paragraph]]) is ink —
no name, never focusable, never in the answer map.

Every optional key is the one the engine documents, in either spelling
(`:is-required` or `"is_required"`): builders pass options through
untouched instead of keeping a second copy of the vocabulary.

A LIVE VIEW is the same discipline one `:kind` further: [[view]] and the node
builders under it declare a picture the human WATCHES while the work runs. It
asks nothing and parks no thread; it is patched by node id and ends in a
verdict carrying the markdown the model reads.

    (vis/with-live-view!
      (view/view {:title "CI"}
                 (view/status "now" "Polling GitHub…" {:tone "running"})
                 (view/table "jobs" [(view/table-column "job" "Job")
                                     (view/table-column "took" "Took" {:align "right"})]))
      (fn [view-id]
        (vis/patch-live-view!
          view-id
          [{:op "set" :node-id "now" :text "18 jobs" :tone "ok"}
           {:op "append" :node-id "jobs"
            :rows [(view/table-row "build" ["tests / ubuntu" "13m0s"] {:tone "ok"})]}])))

Python extensions get the SAME names on the `vis` module —
`vis.select('env', ['staging', 'prod'], label='Environment')` — built by
the same engine seam across the JSON boundary.
raw docstring

add-nodeclj

(add-node node)
(add-node node after)

Add a whole node to a RUNNING view — a second table, a per-device log. after names the node it lands behind; without it, it goes last.

Add a whole `node` to a RUNNING view — a second table, a per-device log.
`after` names the node it lands behind; without it, it goes last.
sourceraw docstring

buttonclj

(button id label)
(button id label opts)

Live operator action; accepted presses increment :clicks in shared state.

Live operator action; accepted presses increment :clicks in shared state.
sourceraw docstring

checkboxclj

(checkbox field-name)
(checkbox field-name opts)

One box, answered as a boolean. :is-required means it must end up TICKED, which is how a consent line is expressed.

One box, answered as a boolean. `:is-required` means it must end up TICKED,
which is how a consent line is expressed.
sourceraw docstring

codeclj

(code id text)
(code id text opts)

Literal live code; :language is optional and whitespace is preserved.

Literal live code; :language is optional and whitespace is preserved.
sourceraw docstring

columnclj

(column & nodes)

Stack nodes one under the next — the default arrangement, worth saying explicitly inside a row. Takes a leading id in a live view, exactly like row.

Stack `nodes` one under the next — the default arrangement, worth saying
explicitly inside a [[row]]. Takes a leading id in a live view, exactly like
[[row]].
sourceraw docstring

disclosureclj

(disclosure id label nodes & [opts])

A collapsible live column. :default-expanded applies only to its initial active frame.

A collapsible live column. :default-expanded applies only to its initial active frame.
sourceraw docstring

formclj

(form opts & nodes)

The request map com.blockether.vis.core/request-human-input! takes, built from opts and the nodes that follow it — and refused right here if it is not one.

opts needs at least a :title, and may carry :description, :submit-label, :cancel-label, :is-cancellable, :timeout-ms (0 waits indefinitely) and :channel-ids. At least one node is required, and the answerable ones must have distinct names.

The request map `com.blockether.vis.core/request-human-input!` takes, built
from `opts` and the `nodes` that follow it — and refused right here if it is
not one.

`opts` needs at least a `:title`, and may carry `:description`,
`:submit-label`, `:cancel-label`, `:is-cancellable`, `:timeout-ms` (0 waits
indefinitely) and `:channel-ids`. At least one node is required, and the
answerable ones must have distinct names.
sourceraw docstring

headingclj

(heading text)
(heading id text)
(heading id text opts)

A form title, or live heading addressed by id with :level 1–6.

A form title, or live heading addressed by id with :level 1–6.
sourceraw docstring

(link id links)
(link id links opts)

Labeled pointers the human OPENS: each of links is {:id … :label … :target … :target-kind …} — an attachment, a path or a url.

Labeled pointers the human OPENS: each of `links` is
`{:id … :label … :target … :target-kind …}` — an attachment, a path or a url.
sourceraw docstring

logclj

(log id)
(log id opts)

Append-only lines — the scrollback. :lines seeds it and :window-lines says how many a surface holds hot; the view's record on disk keeps every line either way, so a window is a paint budget, never a loss. Optional :line-tones align with seeded lines (nil is plain); append ops accept one :tone for their lines. Redact before publishing. Terminal controls display literally.

Append-only lines — the scrollback. `:lines` seeds it and `:window-lines` says
how many a surface holds hot; the view's record on disk keeps every line
either way, so a window is a paint budget, never a loss. Optional `:line-tones`
align with seeded lines (nil is plain); append ops accept one `:tone` for their
lines. Redact before publishing. Terminal controls display literally.
sourceraw docstring

multilineclj

(multiline field-name)
(multiline field-name opts)

A multi-line text box, answered as a string with its newlines and its leading whitespace intact. Takes the same opts as plaintext.

A multi-line text box, answered as a string with its newlines and its
leading whitespace intact. Takes the same `opts` as [[plaintext]].
sourceraw docstring

multiselectclj

(multiselect field-name options)
(multiselect field-name options opts)

Choose ANY of options, answered as a vector of the chosen values (empty when nothing is ticked). Same options shape as select.

Choose ANY of `options`, answered as a vector of the chosen values (empty
when nothing is ticked). Same `options` shape as [[select]].
sourceraw docstring

optionclj

(option value)
(option value label)

One entry for a select / multiselect: the value that is answered and, optionally, the label shown instead of it.

An option is not a node, so it is checked by the field that offers it.

One entry for a [[select]] / [[multiselect]]: the `value` that is answered
and, optionally, the `label` shown instead of it.

An option is not a node, so it is checked by the field that offers it.
sourceraw docstring

otpclj

(otp field-name)
(otp field-name opts)

A one-time code in digit boxes, answered as an opaque vis-secret: handle — a code opens the account once, so it is a secret exactly like a password. :min-length / :max-length say how many digits (6 by default, 12 at most).

A one-time code in digit boxes, answered as an opaque `vis-secret:` handle —
a code opens the account once, so it is a secret exactly like a password.
`:min-length` / `:max-length` say how many digits (6 by default, 12 at most).
sourceraw docstring

paragraphclj

(paragraph text)
(paragraph id text)
(paragraph id text opts)

Form prose, or an addressed live paragraph with inline Markdown.

Form prose, or an addressed live paragraph with inline Markdown.
sourceraw docstring

passwordclj

(password field-name)
(password field-name opts)

A typed line whose characters are masked, answered as an opaque vis-secret: HANDLE — never the plaintext. Read it with com.blockether.vis.core/reveal-human-input-secret on the trusted side.

Takes the same opts as plaintext.

A typed line whose characters are masked, answered as an opaque
`vis-secret:` HANDLE — never the plaintext. Read it with
`com.blockether.vis.core/reveal-human-input-secret` on the trusted side.

Takes the same `opts` as [[plaintext]].
sourceraw docstring

plaintextclj

(plaintext field-name)
(plaintext field-name opts)

One typed line, answered as a string.

opts may carry :label, :description, :placeholder, :default, :is-required, :min-length, :max-length and :validate.

One typed line, answered as a string.

`opts` may carry `:label`, `:description`, `:placeholder`, `:default`,
`:is-required`, `:min-length`, `:max-length` and `:validate`.
sourceraw docstring

progressclj

(progress id)
(progress id opts)

How far the work has come: :done of :total, or a :value between 0 and 1. Neither means INDETERMINATE, which is the honest picture while a job queues.

How far the work has come: `:done` of `:total`, or a `:value` between 0 and 1.
Neither means INDETERMINATE, which is the honest picture while a job queues.
sourceraw docstring

remove-nodeclj

(remove-node node-id)

Drop node node-id from a running view, its items with it.

Drop node `node-id` from a running view, its items with it.
sourceraw docstring

rowclj

(row & nodes)

Lay nodes out side by side. A group holds no value and never appears in the answer map; groups nest freely.

A LIVE view arranges its work with the same two builders, and there a group is addressed like every other node, so it opens with its id: (hi/row "reading" (hi/table "hosts" …) (hi/status "why" …))add-node :after names it, remove-node takes it with its children, and no patch ever moves it.

Lay `nodes` out side by side. A group holds no value and never appears in
the answer map; groups nest freely.

A LIVE view arranges its work with the same two builders, and there a group
is addressed like every other node, so it opens with its id:
`(hi/row "reading" (hi/table "hosts" …) (hi/status "why" …))` —
`add-node :after` names it, `remove-node` takes it with its children, and no
patch ever moves it.
sourceraw docstring

selectclj

(select field-name options)
(select field-name options opts)

Choose exactly ONE of options, answered as that option's value.

options is a vector of plain values or option maps. A :default must be one of the values offered.

Choose exactly ONE of `options`, answered as that option's value.

`options` is a vector of plain values or [[option]] maps. A `:default` must
be one of the values offered.
sourceraw docstring

sliderclj

(slider field-name)
(slider field-name opts)

A number on a track, answered as a NUMBER: :min / :max / :step (0 / 100 / 1 when unsaid), :default inside its own track.

The wire type is range; the builder is spelled slider so it never shadows clojure.core/range — and so the Python mirror never shadows the range builtin either.

A number on a track, answered as a NUMBER: `:min` / `:max` / `:step`
(0 / 100 / 1 when unsaid), `:default` inside its own track.

The wire type is `range`; the builder is spelled `slider` so it never
shadows `clojure.core/range` — and so the Python mirror never shadows the
`range` builtin either.
sourceraw docstring

spinnerclj

(spinner id text)
(spinner id text opts)

Live activity indicator; :variant is braille, dots, line or pulse.

Live activity indicator; :variant is braille, dots, line or pulse.
sourceraw docstring

statclj

(stat id stats)
(stat id stats opts)

A strip of counters upserted by id — the score. Each entry of stats is {:id … :label … :value-text … :tone …}.

A strip of counters upserted by id — the score. Each entry of `stats` is
`{:id … :label … :value-text … :tone …}`.
sourceraw docstring

statusclj

(status id text)
(status id text opts)

One line saying what is happening RIGHT NOW — replaced in place, never appended, so the top of the view never scrolls. opts may carry :label, :detail and a :tone.

One line saying what is happening RIGHT NOW — replaced in place, never
appended, so the top of the view never scrolls. `opts` may carry `:label`,
`:detail` and a `:tone`.
sourceraw docstring

stepsclj

(steps id items)
(steps id items opts)

An ORDERED checklist: the shape of a pipeline, in the order it runs. Each of items is {:id … :label … :tone … :detail … :value …} and carries its own tone, because a step is where a run goes wrong.

An ORDERED checklist: the shape of a pipeline, in the order it runs. Each of
`items` is `{:id … :label … :tone … :detail … :value …}` and carries its own
tone, because a step is where a run goes wrong.
sourceraw docstring

tableclj

(table id columns)
(table id columns opts)

Rows upserted and removed by row id, painted in the :order the view DECLARES — columns are table-columns, :rows seeds it and :max-rows bounds it by refusal. :is-selectable true turns rows into controls; :selected-ids is the shared current selection extensions read from state.

Rows upserted and removed by row id, painted in the `:order` the view
DECLARES — `columns` are [[table-column]]s, `:rows` seeds it and `:max-rows`
bounds it by refusal. `:is-selectable true` turns rows into controls;
`:selected-ids` is the shared current selection extensions read from state.
sourceraw docstring

table-columnclj

(table-column id label)
(table-column id label opts)

One column of a table: the id a cell is addressed by and the label over it, optionally :align "right" for numbers.

A column is not a node, so it is checked by the table that declares it.

One column of a [[table]]: the `id` a cell is addressed by and the `label`
over it, optionally `:align` `"right"` for numbers.

A column is not a node, so it is checked by the table that declares it.
sourceraw docstring

table-rowclj

(table-row id cells)
(table-row id cells opts)

One row of a table, keyed by id: cells in column order, optionally :toned or placed below a collapsible :branch label shared by sibling rows. Built rather than typed because it is the one POSITIONAL thing here — a cell means whatever column stands over it.

A row is not a node, so it is checked by the table, or the patch, carrying it.

One row of a [[table]], keyed by `id`: `cells` in column order, optionally
`:tone`d or placed below a collapsible `:branch` label shared by sibling rows.
Built rather than typed because it is the one POSITIONAL thing here — a cell
means whatever column stands over it.

A row is not a node, so it is checked by the table, or the patch, carrying it.
sourceraw docstring

viewclj

(view opts & nodes)

The live view com.blockether.vis.core/open-live-view! mounts, built from opts and the nodes that follow it — and refused right here if it is not one.

opts needs at least a :title, and may carry :description, :source, :channel-ids and :timeout-ms. There is no cancellable flag: a human can stop watching ANY view. At least one node is required, and their ids must be distinct: every patch names the node it speaks to.

The live view `com.blockether.vis.core/open-live-view!` mounts, built from
`opts` and the `nodes` that follow it — and refused right here if it is not
one.

`opts` needs at least a `:title`, and may carry `:description`, `:source`,
`:channel-ids` and `:timeout-ms`. There is no cancellable flag: a human can
stop watching ANY view. At least one node is required, and their ids must be
distinct: every patch names the node it speaks to.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close