You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Namespace-by-namespace listing of all public functions and macros.
Naming convention: Sections below abbreviate org.replikativ.spindel.*
to spindel.* for brevity. The real require is always the full
org.replikativ.spindel.… form — see any file in src/ or examples/
for canonical require lines.
spindel.core
Convenience re-export namespace. All functions below are also available from their originating namespaces.
Macros
Macro
Description
(spin & body)
Create a cached reactive spin with CPS transformation
Create a reactive signal with deterministic ID. The 2-arity form takes an explicit execution-context (e.g. (signal runtime [])) and is what top-level defs in the examples use.
(batch & body)
Batch signal updates into a single propagation
(gen-aseq & body)
Generate a lazy async sequence using yield
(for [bindings body])
Async sequence comprehension with spindel effects
Effects
Function
Description
(await spin-or-deferred)
Suspend until value available, track dependency
(track signal-ref)
Read signal with dual perspective (new/old/deltas)
(interval new) / (interval old new) / (interval old new deltas)
Create interval
(interval? x)
Type check
(as-interval x)
Coerce to interval
(as-interval-with-old prev current)
Coerce with previous baseline
(changed? iv)
True if old != new
(static? iv)
True if no old and no deltas
(derive-interval prev-output new deltas)
Create derived interval
(merge-intervals acc new)
Merge intervals (associative)
Protocol: PInterval
(get-old this) ;; baseline value
(get-new this) ;; current value
(get-deltas this) ;; delta sequence
(has-deltas? this) ;; true if pending
(commit this) ;; end interval (new→old, clear deltas)
spindel.incremental.combinators
Incremental operations on intervals.
All combinators return a typed-interval map {:algebra A :old :new :deltas} —
see Incremental Collections for the algebra contract.
Macro
Description
(ifilter pred source)
Incremental filter (sequence algebra)
(imap f source)
Incremental map (sequence algebra)
(ireduce rf init source)
Incremental reduce (scalar algebra)
(ifor-each key-fn transform source)
Keyed per-item transformation (sequence algebra)
(islice window source)
Windowed view for virtual scroll (sequence algebra). window is a map {:start n :end n}.
(izip f s1 s2 …)
Combine intervals into a scalar (typed combinator)
(iflat-map f source)
Flat-map producing a sequence interval (typed combinator)
spindel.dom.elements
vnode constructors. The el/* macros (el/div, el/span, el/h1, …)
are generated for every HTML tag.
Macro / Fn
Description
(el/<tag> attrs? & children)
One macro per HTML tag — emits a vnode at a deterministic addr derived from source location.
(el/text s)
Text vnode (auto-wrapped when a string appears as a child).
(el/fragment & children)
Inline fragment vnode (children spliced into parent).
Common vnode attrs: :class, :style, :id, any :data-*, event
handlers as :on-click / :on-input / …, and:
:key — stable identity within an ifor-each fragment.
:ref — (fn [el-or-nil] …) called on mount with the live DOM
element and on unmount with nil. Not re-fired on reconcile (the
element identity survives). See examples/block_editor_demo and
examples/README.md for the canonical usage pattern.
spindel.dom.foreach
Typed-sequence to DOM bridge. Emits a single :seq-diff child delta
carrying a SequenceAlgebra record.
Macro / Fn
Description
(ifor-each key-fn source render-fn)
(macro) Render an interval of items as a keyed fragment under the surrounding parent. Source can be a signal, an interval, or any value implementing PInterval.
(for-each* …)
(fn) Underlying functional form used by the macro.
Wrapping rule: the ifor-each fragment must be the sole child
of its parent element. apply-seq-diff!
(dom/discharge.cljc:418-497) walks (range size-after) and passes
those indices straight into insert-child! / move-child! /
remove-child!, which interpret them as positions in
parent.childNodes. With sibling DOM nodes preceding the fragment
the indices skew by the sibling count and the diff corrupts on
update. The workaround until the discharge takes an :offset is
structural: wrap the ifor-each in its own <div> / <ul> and put
headings, footers, separators one level up.
spindel.dom.foreign
Macro / Fn
Description
(foreign-node attrs)
(macro) Escape hatch for third-party JS that owns its subtree (TipTap, ProseMirror, video, …). Accepts :on-mount, :on-unmount callbacks. Spindel manages the container, the third-party lib manages everything inside.
(foreign-node* loc attrs)
(fn) Underlying form.
spindel.dom.discharge
PDischarge protocol — implemented by browser/make-dom-discharge
for real DOM and by examples.shared.logging-discharge for diagnostic
op logging. Users typically don't implement this protocol — they wrap
the browser discharge for logging or build a server-side string
implementation.
Function
Description
(make-mock-discharge)
Returns {:discharge :log} — a mock implementation for unit tests.
apply-seq-diff!
Internal: consumes a SequenceAlgebra :seq-diff and applies grow → permutation → shrink → change → freeze to DOM children.
spindel.dom.render
Function
Description
(render-spin! container spin discharge)
Mount a spin's vnode output into container and wire reactive re-render on signal changes. Returns {:stop! fn :state atom}.
(render-once! container vnode discharge)
One-shot non-reactive render.
(create-render-effect container discharge)
Lower-level: returns a function that takes a vnode and discharges to container, with :applied-vnodes cross-cycle deduplication.
Hash-partitioned fan-out (Rama-style). The source is routed to one of N
partitions (N must be a power of two) using a partition-fn that extracts a
routing key. Each partition has its own buffer; consumers tap individual
partitions for parallel downstream processing.
Function
Description
(partitioned n source partition-fn & opts)
Create with N partitions
(tap-partition p idx) / (tap-partition p idx buffer)
Subscribe to one partition
(tap-all p)
Subscribe to every partition; returns a vector of taps
(partition-post! p idx item)
Post directly to a partition (e.g. for chained pipelines)
Publish-only: own the topic, publish the signal's changes (a thin sync-signal! :owner? true).
(subscribe-signal! peer topic & opts)
Subscribe a remote signal into a local holder atom (or supplied :atom); :on-update for changes.
(sync-signal! peer topic signal & opts)
Bidirectional convergent sync — every peer calls it; exactly one is :owner? (the relay hub). Opts: :merge-fn:apply-delta-fn:delta-fn:clear-delta-fn:state-fn:sync?.
Live wiring (konserve-sync + signal_sync glue). Fully .cljc; the konserve-sync transport defaults resolve via requiring-resolve on the JVM, and cljs callers inject :subscribe-fn.