### Rendering to DOM with Vrac (ClojureScript) Source: https://context7.com/green-coder/vrac/llms.txt Shows how to mount a Vrac application to a DOM element and initialize automatic reactivity updates. It covers basic app setup, rendering the root component, and setting up hot reload support for development. ```clojure ;; Basic app setup (ns my-app.core (:require [vrac.web :as vw :refer [$]] [signaali.reactive :as sr])) (defn app-root [] (let [counter (sr/create-state 0)] ($ :div ($ :h1 "My App") ($ :p "Counter: " counter) ($ :button {:on/click #(swap! counter inc)} "Increment")))) ;; Mount to DOM element (defn ^:export init [] (vw/render (js/document.getElementById "app") ($ app-root))) ;; Hot reload support (defn ^:dev/after-load reload [] (vw/render (js/document.getElementById "app") ($ app-root))) (defn ^:dev/before-load teardown [] (vw/dispose-render-effects)) ;; Start the app (init) ``` -------------------------------- ### Create Reactive Fragment with Conditional Content in ClojureScript Source: https://context7.com/green-coder/vrac/llms.txt Illustrates how to create a reactive fragment that conditionally renders content based on a state variable. The example shows a fragment that displays a message only when a boolean state variable `show` is true. This highlights Vrac's ability to manage dynamic visibility. ```clojure (let [show (sr/create-state true)] (vw/reactive-fragment (fn [] (when @show ($ :div "This content can be toggled"))))) ``` -------------------------------- ### Clojure: Reactive State Management with Signaali Source: https://context7.com/green-coder/vrac/llms.txt Demonstrates creating and managing reactive state using signaali.reactive primitives like create-state, create-signal, and create-memo. It shows how state changes automatically update the DOM and how to handle derived values and side effects. ```clojure (require '[signaali.reactive :as sr]) ;; Create mutable state (like atom but reactive) (let [counter (sr/create-state 0)] ($ :div ($ :p "Count: " counter) ; Displays reactive value ($ :button {:on/click #(swap! counter inc)} "Increment") ($ :button {:on/click #(swap! counter dec)} "Decrement") ($ :button {:on/click #(reset! counter 0)} "Reset"))) ;; DOM updates automatically when counter changes ;; Create read-only signal (let [text-signal (sr/create-signal "Hello")] ($ :div text-signal)) ; Displays "Hello" ;; Derived/computed values (memos) (let [first-name (sr/create-state "John") last-name (sr/create-state "Doe") full-name (sr/create-memo (fn [] (str @first-name " " @last-name)))] ($ :div ($ :input {:value @first-name :on/input #(reset! first-name (.. % -target -value))}) ($ :input {:value @last-name :on/input #(reset! last-name (.. % -target -value))}) ($ :p "Full name: " full-name))) ;; full-name recalculates only when first-name or last-name changes ;; Controlled input with validation (let [text-signal (sr/create-signal "foo")] ($ :input (vw/props-effect (fn [] {:value @text-signal})) {:on/input (fn [event] (let [new-value (.. event -target -value)] ;; Prevent "foobar" from being entered (swap! text-signal (fn [prev] (if (clojure.string/includes? new-value "foobar") prev new-value)))))})) ``` -------------------------------- ### Context for Dependency Injection in Vrac (ClojureScript) Source: https://context7.com/green-coder/vrac/llms.txt Demonstrates how to use Vrac's context API to pass reactive data through the component tree without prop drilling. This is useful for theme switching, configuration, and component customization. It shows defining context, providing it, and consuming it in child components, including nested context updates and a component registry pattern. ```clojure ;; Define and use context (let [theme-context (sr/create-signal {:bg "white" :fg "black"}) is-dark (sr/create-state false)] ;; Parent provides context (vw/with-context theme-context ($ :div ($ :button {:on/click #(if @is-dark (reset! theme-context {:bg "white" :fg "black"}) (reset! theme-context {:bg "black" :fg "white"})) :on/click #(swap! is-dark not)} "Toggle Theme") ;; Child components read context ($ (fn [] (let [theme (vw/get-context)] ($ :div (vw/props-effect (fn [] {:style {:background-color (:bg @theme) :color (:fg @theme)}})) "Themed content"))))))) ;; Nested context with updates (let [root-context (sr/create-signal {:user "Guest" :level 1})] (vw/with-context root-context ($ :div ($ :p "User: " (sr/create-memo (fn [] (:user @(vw/get-context))))) ;; Update context for child scope (vw/with-context-update (fn [parent] (-> @parent (assoc :user "Admin") (update :level inc))) ($ :div ($ :p "User: " (sr/create-memo (fn [] (:user @(vw/get-context))))) ($ :p "Level: " (sr/create-memo (fn [] (:level @(vw/get-context)))))))))) ;; Component registry pattern (defn component-from-context [component-key] (fn [props & children] (let [context (vw/get-context) component-resolver (sr/create-memo (fn [] (get @context component-key)))] (vw/reactive-fragment (fn [] ($ @component-resolver props children)))))) (def button (component-from-context :ui/button)) (let [registry (sr/create-signal {:ui/button (fn [props children] ($ :button props children))})] (vw/with-context registry ($ button {:on/click #(println "Clicked")} "Click Me"))) ``` -------------------------------- ### Effects and Lifecycle Management in Vrac (ClojureScript) Source: https://context7.com/green-coder/vrac/llms.txt Explains how to manage side effects and resource cleanup in Vrac applications using effects. It demonstrates focusing an input element on mount, cleaning up interval timers on unmount, and handling multiple effects within a component. ```clojure ;; Focus input on mount (defn auto-focus-input [] (let [input-ref (sr/create-signal nil)] ($ :<> (vw/use-effects [(sr/create-effect (fn [] (when-some [elem @input-ref] (.focus elem))))]) ($ :input {:ref input-ref :type "text"})))) ;; Cleanup on unmount (defn timer-component [] (let [elapsed (sr/create-state 0)] ($ :<> (vw/use-effects [(sr/create-effect (fn [] (let [interval-id (js/setInterval #(swap! elapsed inc) 1000)] (sr/on-clean-up (fn [] (js/clearInterval interval-id))))))]) ($ :p "Elapsed: " elapsed " seconds"))) ;; Multiple effects (defn logger-component [value] ($ :div (vw/use-effects [(sr/create-effect (fn [] (println "Value changed:" @value))) (sr/create-effect (fn [] (println "Component rendered")))]) "Value: " value) ``` -------------------------------- ### Create Simple Reactive Fragment in ClojureScript Source: https://context7.com/green-coder/vrac/llms.txt Demonstrates the creation of a basic reactive fragment in ClojureScript using Vrac. It manages a counter state and displays it within a reactive region, updating automatically when the counter increments. This showcases the core mechanism of binding state to UI elements. ```clojure (let [counter (sr/create-state 0)] ($ :div ($ :button {:on/click #(swap! counter inc)} "+1") (vw/reactive-fragment (fn [] ($ :p "Count: " @counter)) {:metadata {:name "counter-display"}}))) ``` -------------------------------- ### Vrac Properties and Attributes Source: https://context7.com/green-coder/vrac/llms.txt Vrac allows detailed control over element behavior and appearance through properties and attributes. It distinguishes between HTML attributes (`:a/`), DOM properties (`:p/`), and event handlers (`:on/`). Styles can be set using maps or strings, classes can be managed as vectors, and data attributes are supported. Element references can also be established using signals. ```clojure ;; Attributes vs Properties ($ :input {:a/readonly true ; HTML attribute :type "text"}) ($ :input {:p/readOnly true ; DOM property :type "text"}) ;; Event handlers ($ :button {:on/click (fn [e] (println "Clicked")) :on/dblclick (fn [e] (println "Double-clicked")) :on/keydown (fn [e] (println "Key:" (.-key e)))} "Interactive button") ;; Style as map (converted to string automatically) ($ :div {:style {:background-color "blue" :padding "1em" :border-radius "0.5em"}} "Styled div") ;; Style as string ($ :div {:style "background-color: blue; padding: 1em;"} "Styled div") ;; Classes as vector (automatically joined) ($ :div {:class ["container" "active" "theme-dark"]} "Multiple classes") ;; Classes with conditional inclusion (let [is-active true is-error false] ($ :div {:class ["container" (when is-active "active") (when is-error "error")]} "Conditional classes")) ;; Data attributes ($ :div {:data-testid "main-container" :data-index "42"} "Data attributes") ;; Element references (let [input-ref (sr/create-signal nil)] ($ :input {:ref input-ref :type "text"})) ``` -------------------------------- ### Clojure: Dynamic Properties with props-effect Source: https://context7.com/green-coder/vrac/llms.txt Illustrates how to create dynamic UI attributes that react to state changes using the `props-effect` function. This is useful for implementing features like controlled inputs, conditional styling, and combining static and dynamic properties. ```clojure ;; Controlled checkbox (let [checked-state (sr/create-state false)] ($ :input {:type "checkbox" :on/change #(swap! checked-state not)} (vw/props-effect (fn [] {:checked @checked-state})))) ;; Dynamic styling based on state (let [is-active (sr/create-state false) color (sr/create-state "blue")] ($ :div (vw/props-effect (fn [] {:style {:background-color @color :border (if @is-active "2px solid red" "none")}})) ($ :button {:on/click #(swap! is-active not)} "Toggle Active") ($ :button {:on/click #(reset! color "green")} "Change Color"))) ;; Multiple props-effects combined (let [disabled (sr/create-state false) title (sr/create-state "Click me")] ($ :button (vw/props-effect (fn [] {:disabled @disabled})) (vw/props-effect (fn [] {:title @title})) {:on/click #(println "Clicked")} "Button")) ;; Combining static and dynamic props ($ :div {:class ["base-class" "static-class"]} ; Static (vw/props-effect ; Dynamic (fn [] {:class [(when @is-highlighted "highlight")]})) "Content") ``` -------------------------------- ### List Rendering with for-fragment* in Clojure Source: https://context7.com/green-coder/vrac/llms.txt Efficiently renders collections with automatic DOM reconciliation. Vrac tracks items by key and only updates changed elements. It supports basic list rendering, dynamic lists with add/remove functionality, custom key functions, and rendering without a key function (using identity). Dependencies include the Vrac library (`vw`). ```clojure ;; Basic list rendering (let [items (sr/create-state [{:id 1 :name "Apple"} {:id 2 :name "Banana"} {:id 3 :name "Cherry"}])] ($ :ul (vw/for-fragment* items ; Reactive collection :id ; Key function (fn [{:keys [id name]}] ; Item renderer ($ :li (str id ": " name))))) ;; Dynamic list with add/remove (let [people (sr/create-state [{:id 0 :name "Alice"} {:id 1 :name "Bob"}]) next-id (atom 2) new-name (sr/create-state "")] ($ :div ($ :input (vw/props-effect (fn [] {:value @new-name})) {:on/input #(reset! new-name (.. % -target -value))}) ($ :button {:on/click (fn [] (when-not (clojure.string/blank? @new-name) (swap! people conj {:id @next-id :name @new-name}) (swap! next-id inc) (reset! new-name "")))} "Add Person") ($ :ul (vw/for-fragment* people :id (fn [{:keys [id name]}] ($ :li (str name " ") ($ :button {:on/click #(swap! people (fn [p] (remove #(= (:id %) id) p))} "Remove"))))))) ;; Custom key function (let [messages (sr/create-state [{:timestamp 1234 :text "Hello"} {:timestamp 5678 :text "World"}])] ($ :div (vw/for-fragment* messages :timestamp ; Use timestamp as key (fn [{:keys [text timestamp]}] ($ :div.message ($ :span.time timestamp) ($ :span.text text)))))) ;; Without key function (uses identity) (let [colors (sr/create-state ["red" "green" "blue"])] ($ :div (vw/for-fragment* colors (fn [color] ($ :div {:style {:color color}} color))))) ``` -------------------------------- ### Creating DOM Elements with `$` in Vrac Source: https://context7.com/green-coder/vrac/llms.txt The `$` function in Vrac creates virtual DOM nodes (Vcups) representing elements, fragments, or component invocations. It accepts a node type, properties, and children, supporting basic elements, styled elements with classes and IDs, properties, event handlers, nested structures, fragments, SVG, and MathML. This function is fundamental for building UIs with Vrac. ```clojure (ns my-app.core (:require [vrac.web :as vw :refer [$]] [signaali.reactive :as sr])) ;; Basic elements ($ :div "Hello World") ;; =>
Hello World
;; Elements with CSS classes and IDs ($ :div#main.container.theme-dark "Content") ;; =>
Content
;; Elements with properties ($ :input {:type "text" :value "initial" :placeholder "Enter text..."}) ;; Elements with event handlers ($ :button {:on/click #(js/alert "Clicked!")} "Click me") ;; Nested elements ($ :div.card ($ :h2 "Card Title") ($ :p "Card content goes here") ($ :button {:on/click #(println "Action")} "Action")) ;; Fragments (no wrapper element) ($ :<> ($ :h1 "Title") ($ :p "Paragraph 1") ($ :p "Paragraph 2")) ;; SVG elements (namespace handled automatically) ($ :svg {:width 100 :height 100} ($ :circle {:cx 50 :cy 50 :r 40 :fill "blue"})) ;; MathML elements ($ :math ($ :mrow ($ :mi "x") ($ :mo "=") ($ :mn "5"))) ``` -------------------------------- ### Pattern Matching with case-fragment in Clojure Source: https://context7.com/green-coder/vrac/llms.txt Renders different branches based on discrete values. More efficient than nested if-fragments for multiple cases. It supports single values per case or multiple values grouped together. Dependencies include the Vrac library (`vw`). ```clojure ;; Route-based rendering (let [route (sr/create-state :route/homepage)] ($ :div ($ :nav ($ :button {:on/click #(reset! route :route/homepage)} "Home") ($ :button {:on/click #(reset! route :route/blog)} "Blog") ($ :button {:on/click #(reset! route :route/about)} "About")) (vw/case-fragment (fn [] @route) :route/homepage ($ :div "Welcome to the homepage") :route/blog ($ :div "Blog posts here") :route/about ($ :div "About us") ;; Default case ($ :div "Page not found")))) ;; Multiple values per case (let [status (sr/create-state :pending)] (vw/case-fragment status (:pending :loading :processing) ($ :div.loading "Working...") (:success :completed) ($ :div.success "Done!") (:error :failed) ($ :div.error "Something went wrong") ;; Default ($ :div "Unknown status"))) ``` -------------------------------- ### Clojure: Conditional Rendering with if-fragment Source: https://context7.com/green-coder/vrac/llms.txt Shows how to conditionally render different UI sections based on reactive conditions using `if-fragment`. This function ensures that only the active branch is present in the DOM, optimizing performance. ```clojure ;; Simple if-else (let [is-logged-in (sr/create-state false)] ($ :div (vw/if-fragment is-logged-in ($ :div "Welcome back!") ($ :div "Please log in")) ($ :button {:on/click #(swap! is-logged-in not)} "Toggle Login"))) ;; With reactive function condition (let [counter (sr/create-state 0)] ($ :div ($ :p "Count: " counter) (vw/if-fragment (fn [] (even? @counter)) ($ :div "The value is even.") ($ :div "The value is odd.")) ($ :button {:on/click #(swap! counter inc)} "+1"))) ;; Nested conditionals (let [status (sr/create-state :loading)] (vw/if-fragment (fn [] (= @status :loading)) ($ :div "Loading...") (vw/if-fragment (fn [] (= @status :error)) ($ :div "Error occurred") ($ :div "Content loaded")))) ``` -------------------------------- ### Create Complex Reactive Fragment with Dynamic List in ClojureScript Source: https://context7.com/green-coder/vrac/llms.txt Presents a more complex reactive fragment scenario in ClojureScript, rendering a dynamic list of items. The fragment displays an unordered list where each list item corresponds to an element in a reactive state vector `items`. This demonstrates Vrac's capability for rendering iterable, reactive data structures. ```clojure (let [items (sr/create-state [1 2 3])] (vw/reactive-fragment (fn [] ($ :ul (for [item @items] ($ :li (str "Item " item))))) {:metadata {:name "dynamic-list"}})) ``` -------------------------------- ### Conditional Rendering with cond-fragment in Clojure Source: https://context7.com/green-coder/vrac/llms.txt Evaluates multiple conditions in order, rendering the first matching branch. Similar to Clojure's `cond`. It's useful for sequential condition checking and complex logical conditions. Dependencies include the Vrac library (`vw`). ```clojure ;; Sequential condition checking (let [score (sr/create-state 85)] ($ :div ($ :p "Score: " score) (vw/cond-fragment (>= @score 90) ($ :div.grade "A - Excellent!") (>= @score 80) ($ :div.grade "B - Good job") (>= @score 70) ($ :div.grade "C - Satisfactory") (>= @score 60) ($ :div.grade "D - Needs improvement") :else ($ :div.grade "F - Failed")) ($ :button {:on/click #(swap! score + 5)} "+5") ($ :button {:on/click #(swap! score - 5)} "-5")) ;; Complex conditions (let [user (sr/create-state {:role :guest :premium false})] (vw/cond-fragment (and (= (:role @user) :admin) (:premium @user)) ($ :div "Premium Admin Dashboard") (= (:role @user) :admin) ($ :div "Admin Dashboard") (:premium @user) ($ :div "Premium User Area") :else ($ :div "Guest Access"))) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.