Liking cljdoc? Tell your friends :D

co.multiply.tropical.cookie

State the browser owns and the server renders, kept in a cookie: whether a section is open, a sidebar folded, a pane's width. It changes in the browser without a round trip, survives page loads, is right in the first frame, and neither a later patch nor an island mounting again undoes what the user did.

defcookie declares a state, with its default and what a value must be. The var is its identity, so it lives wherever the code that uses it does: next to one island, or in a namespace several share. Any island anywhere in the page takes it up with use-cookie, which returns a handle for value and for the helpers in co.multiply.tropical.ui:

(defcookie group-open
  "Whether a sidebar group is open, per group."
  {:default true :valid? boolean?})

(defisland sidebar-group
  {:key :id}
  [group]
  (let [open (use-cookie group-open (:id group))]
    [:section
     [:button (ui/aria-expanded {:data-on:click (ui/toggle open)} open) (:name group)]
     [:ul (ui/shown open) ...]]))

How it holds:

  • The browser keeps each state in a Datastar signal under _cookie. An island that uses a state declares its signal on its root, only if missing (island/declare-signal), so the first island in the page to use it declares it, and any later declaration, a remount or a patch carrying the server's stale copy changes nothing. Islands using one state follow one signal.
  • The element the app mounts in carries ui/page-attrs (ring/mount adds it): a handler that writes each change of a _cookie signal into the cookie, merged with what the cookie holds, so tabs don't undo one another's changes. It keeps only values other than their state's default, drops states no longer declared, and drops the oldest values past max-cookie-chars.
  • The server reads the cookie of the request that created the session (co.multiply.tropical.ring binds it), so its value is the state as the session began. The cookie is the client's to write: a value that isn't valid for its state reads as the default.

The server sets a state from an action, as it would any signal: its handler returns patch's signals, which the islands using the state follow and the body's handler keeps. For the page an action opens, such as a new item's with a choice made before the item existed, it passes them to action/navigate's :signals: the cookie has them before the page loads.

A state's values are booleans, numbers or strings, since every request carries the cookie. Text, or a value of any size, that the server needn't render in the first frame is co.multiply.tropical.storage's. A state is used either with an item, as one per item, or without, never both.

State the browser owns and the server renders, kept in a cookie: whether a
section is open, a sidebar folded, a pane's width. It changes in the browser
without a round trip, survives page loads, is right in the first frame, and
neither a later patch nor an island mounting again undoes what the user did.

`defcookie` declares a state, with its default and what a value must be. The
var is its identity, so it lives wherever the code that uses it does: next to
one island, or in a namespace several share. Any island anywhere in the page
takes it up with `use-cookie`, which returns a handle for `value` and for the
helpers in `co.multiply.tropical.ui`:

    (defcookie group-open
      "Whether a sidebar group is open, per group."
      {:default true :valid? boolean?})

    (defisland sidebar-group
      {:key :id}
      [group]
      (let [open (use-cookie group-open (:id group))]
        [:section
         [:button (ui/aria-expanded {:data-on:click (ui/toggle open)} open) (:name group)]
         [:ul (ui/shown open) ...]]))

How it holds:

- The browser keeps each state in a Datastar signal under `_cookie`. An
  island that uses a state declares its signal on its root, only if missing
  (`island/declare-signal`), so the first island in the page to use it
  declares it, and any later declaration, a remount or a patch carrying the
  server's stale copy changes nothing. Islands using one state follow one
  signal.
- The element the app mounts in carries `ui/page-attrs` (`ring/mount` adds
  it): a handler that writes each change of a `_cookie` signal into the
  cookie, merged with what the cookie holds, so tabs don't undo one
  another's changes. It keeps only values other than
  their state's default, drops states no longer declared, and drops the
  oldest values past `max-cookie-chars`.
- The server reads the cookie of the request that created the session
  (`co.multiply.tropical.ring` binds it), so its value is the state as the
  session began. The cookie is the client's to write: a value that isn't
  valid for its state reads as the default.

The server sets a state from an action, as it would any signal: its handler
returns `patch`'s signals, which the islands using the state follow and the
body's handler keeps. For the page an action opens, such as a new item's
with a choice made before the item existed, it passes them to
`action/navigate`'s `:signals`: the cookie has them before the page loads.

A state's values are booleans, numbers or strings, since every request
carries the cookie. Text, or a value of any size, that the server needn't
render in the first frame is `co.multiply.tropical.storage`'s. A state is
used either with an item, as one per item, or without, never both.
raw docstring

The cookie the browser keeps its state in.

The cookie the browser keeps its state in.
sourceraw docstring

defcookiecljmacro

(defcookie state-name & decl)

Defines a state kept in the cookie: (defcookie name doc? {:default v, :valid? pred}). :default is a boolean, a number or a string, what the state is until the user changes it. :valid? decides what the cookie may hold for it, and defaults to some?.

Defines a state kept in the cookie: `(defcookie name doc? {:default v, :valid? pred})`.
`:default` is a boolean, a number or a string, what the state is until the
user changes it. `:valid?` decides what the cookie may hold for it, and
defaults to `some?`.
sourceraw docstring

The most the cookie holds, encoded. A browser keeps about 4 KB per cookie, and every request carries it.

The most the cookie holds, encoded. A browser keeps about 4 KB per cookie,
and every request carries it.
sourceraw docstring

patchclj

(patch entries)

The signals that set cookie states, for an action's handler to return, merged with its own. Each of entries is [state item value], or [state value] for a state used without an item:

(fn [_] (cookie/patch (for [g groups] [group-open (:id g) false])))

Patched in, they change the islands in the page that use those states, and the body's handler (ui/page-attrs) writes them into the cookie, so a page loaded later starts with them, one showing an item this page doesn't too. For the page an action opens, pass them to action/navigate's :signals, and the cookie has them before that page loads.

A value that isn't a boolean, a number or a string, or isn't valid for its state, throws, as does a state used the other way, with an item or without.

The signals that set cookie states, for an action's handler to return,
merged with its own. Each of `entries` is `[state item value]`, or
`[state value]` for a state used without an item:

    (fn [_] (cookie/patch (for [g groups] [group-open (:id g) false])))

Patched in, they change the islands in the page that use those states, and
the body's handler (`ui/page-attrs`) writes them into the cookie, so a page
loaded later starts with them, one showing an item this page doesn't too.
For the page an action opens, pass them to `action/navigate`'s `:signals`,
and the cookie has them before that page loads.

A value that isn't a boolean, a number or a string, or isn't valid for its
state, throws, as does a state used the other way, with an item or without.
sourceraw docstring

(use-cookie state)
(use-cookie state item)

Takes up state in this island, or the one for item, such as a group's id: declares its signal on the island's root, unless the browser has it, and returns a handle for value and the helpers in co.multiply.tropical.ui. A hook: call it during the render.

Takes up `state` in this island, or the one for `item`, such as a group's id:
declares its signal on the island's root, unless the browser has it, and
returns a handle for `value` and the helpers in `co.multiply.tropical.ui`. A
hook: call it during the render.
sourceraw docstring

valueclj

(value handle)

The value of handle's state as the session began: what to render for the first paint. The browser's may have moved on since.

The value of `handle`'s state as the session began: what to render for the
first paint. The browser's may have moved on since.
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