Skip to content

Repository files navigation

Respo: A virtual DOM library in Calcit-js

Inspired by React and Reagent. Previously Respo/respo.cljs.

Project Info

  • Version: 0.16.65
  • Init Function: respo.main/main!
  • Reload Function: respo.main/reload!
  • Core Namespaces: 33 namespaces providing virtual DOM, rendering, components, and utilities
  • Testing: language built-in definition tests, plus a small JS-target smoke suite

Usage

In package.cirru and run caps:

{}
  :dependencies $ {}
    |Respo/respo.calcit |main

Latest

DOM syntax

; ns app.demo $ :require
  respo.core :refer $ div

let
    comp-demo $ fn (dispatch!)
      respo.core/div
        {}
          :class-name "|demo-container"
          :style $ {} (:color :red)
          :on-click $ fn (event dispatch!)
            dispatch! :clicked
        respo.core/div $ {}

More examples adapted from calcit.cirru:

; ns app.demo $ :require
  respo.core :refer $ defcomp a <>

let
    comp-link $ fn (href text)
      respo.core/a
        {} $ :href href
        respo.core/<> text
; ns app.demo $ :require
  respo.core :refer $ list-> div

let
    comp-list $ fn ()
      respo.core/list->
        {}
        {}
          :a $ respo.core/div ({})

Text Node:

; ns app.demo $ :require
  respo.core :refer $ <>

let
    comp-text $ fn (content)
      respo.core/<> content

  ; with styles
  respo.core/<> "|demo" $ {}
    :color :red
    :font-size 14

Component definition:

; ns app.demo $ :require
  respo.core :refer $ div <>

let
    comp-container $ fn (content)
      respo.core/div
        {}
          :class-name |demo-container
          :style $ {} (:color :red)
        respo.core/<> content

App initialization:

; ns app.demo $ :require
  respo.core :refer $ render-with!

; initialize store and update store
let
    *store $ atom $ {} (:point 0) (:states {})
    updater $ fn (store op)
      match op
        (:TODO a b) store
        _ store
    dispatch! $ fn (op)
      reset! *store $ updater @*store op
    mount-point nil
    comp-container $ fn (state) state
  dispatch! $ :: :TODO 1 2

  ; build the tree inside a managed memo frame, then render to the DOM
  defn render-app! ()
    respo.core/render-with! mount-point
      fn () $ comp-container @*store
      , dispatch!

Rerender on store changes:

let
    *store $ atom $ {} (:point 0)
    render-app! $ fn () nil
  add-watch *store :changes $ fn ()
    render-app!

Memoize keyed list components inside the tree built by render-with!:

; ns app.demo $ :require
  respo.core :refer $ list-> memo-comp-by >>

list->
  {} (:class-name |task-list)
  -> tasks .to-list .reverse $ map
    fn (task)
      let
          task-id $ :id task
        [] task-id $ memo-comp-by task-id comp-task (>> states task-id) task

memo-comp-by matches the component function, key, and complete argument list. Each render-with! call records active keys and prunes entries that disappeared from the latest tree. Passing nil as the key bypasses caching. Respo manages this cache internally, so applications do not need memof for component memoization. See Render list: memoization and memof migration for setup, lifecycle, and migration details.

Reset virtual DOM caching during hot code swapping, and rerender:

; ns app.demo $ :require
  respo.core :refer $ clear-cache!

let
    *store $ atom $ {} (:point 0)
    render-app! $ fn () nil
  add-watch *store :changes $ fn ()
    render-app!
  remove-watch *store :changes
  add-watch *store :changes $ fn ()
    render-app!
  respo.core/clear-cache!
  render-app!

Adding effects to component:

; ns app.demo $ :require
  respo.core :refer $ div

let
    effect-a $ fn (text)
      fn (action parent-element at-place?)
        println action
        ; action could be :mount :update :amount
        when (= :mount action) nil
    comp-a $ fn (text)
      []
        effect-a text
        respo.core/div ({})

Define a hooks plugin based on Calcit Record, better use a pure function:

; ns app.demo $ :require
  respo.core :refer $ div <>

let
    plugin-x $ fn (states options)
      %::
        %{} :PluginX
          :render $ fn (self) (nth self 1)
          :show $ fn (self d! ? text) nil
        , :plugin-name
        respo.core/div ({}) (respo.core/<> "|Demo")

License

MIT


Documentation Index (For LLM Tool Integration)

This index helps LLM tools automatically fetch and reference documentation using relative paths and the calcit CLI.

Getting Started

Guides and Concepts (see docs/guide/)

Topic Path Overview
Why Respo docs/guide/why-respo.md Motivation and design philosophy
Virtual DOM docs/guide/virtual-dom.md Understanding virtual DOM concepts
Base Components docs/guide/base-components.md Core component patterns
DOM Elements docs/guide/dom-elements.md HTML element creation and usage
Component States docs/guide/component-states.md Managing component state
DOM Properties docs/guide/dom-properties.md DOM property binding
DOM Events docs/guide/dom-events.md Event handling in Respo
Typed Dispatch docs/guide/type-slots.md Entry-level Op binding and checks
Styles docs/guide/styles.md CSS and styling approach
Render Lists docs/guide/render-list.md Efficient list rendering
Common Primitives docs/guide/common-primitives.md Conditional UI, lifecycle, resources, errors, and batching
Hot Swapping docs/guide/hot-swapping.md Hot code reloading setup
Server Rendering docs/guide/server-rendering.md SSR capabilities
Pros and Cons docs/guide/pros-and-cons.md Framework comparison

API Reference

Core API descriptions are now stored in source doc strings inside calcit.cirru. Use docs/api.md for the overview, or inspect a definition directly with Calcit CLI:

calcit query def respo.core/defcomp
calcit query def respo.core/render!
calcit query def respo.render.html/make-string
API Namespace Purpose
defcomp respo.core/defcomp Define components with macro
defeffect respo.core/defeffect Define lifecycle effects
div respo.core/div Create div elements
create-element respo.core/create-element Dynamically create elements
render! respo.core/render! Sync virtual DOM to real DOM
render-with! respo.core/render-with! Render with managed memo frame
memo-comp-by respo.core/memo-comp-by Memoize keyed components
memo-value-by respo.core/memo-value-by Memoize immutable derived data
show respo.core/show Render a child conditionally
for-keyed respo.core/for-keyed Build ordered keyed child pairs
effect-on-mount respo.core/effect-on-mount Run a mount-only lifecycle callback
effect-on-update respo.core/effect-on-update Run when immutable dependencies change
effect-on-unmount respo.core/effect-on-unmount Run an unmount-only lifecycle callback
effect-watch respo.core/effect-watch Dependency-aware lifecycle effect
error-boundary respo.core/error-boundary Render a synchronous fallback
make-render-scheduler respo.core/make-render-scheduler Coalesce render requests
resource-reducer respo.resource/resource-reducer Reduce immutable async state
resource-idle respo.resource/resource-idle Create initial resource state
load-resource! respo.resource/load-resource! Emit async resource actions
<> respo.core/<> Create text nodes
comp-space respo.comp.space/comp-space Spacing component
comp-inspect respo.comp.inspect/comp-inspect Inspection/debugging component
clear-cache! respo.core/clear-cache! Clear memoization cache
patch-instance! respo.controller.client/patch-instance! Patch DOM instances
activate-instance! respo.controller.client/activate-instance! Activate DOM instances
>> respo.core/>> Create state cursors
purify-element respo.util.format/purify-element Clean element markup
mute-element respo.util.format/mute-element Silence element output
make-string respo.render.html/make-string Serialize to string
find-element-diffs respo.render.diff/find-element-diffs Find DOM differences
apply-dom-changes respo.render.patch/apply-dom-changes Apply DOM patches
realize-ssr! respo.core/realize-ssr! Server-side rendering
list-> respo.core/list-> Create list containers

Legacy page names such as make-html and render-app were removed during the migration to source doc strings.

Agent Workflows

Agent-oriented CLI workflows (query/check-md automation) are maintained in Agents.md.

About

A virtual DOM library in calcit-js

Topics

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages