(ns examples.spinner "Spinner example - demonstrates animated loading states. Mirrors bubbletea's spinner example." (:require [tui.core :as tui])) ;; === Spinner Frames === (def spinner-styles {:dots ["⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏"] :line ["|" "/" "-" "\\"] :circle ["◐" "◓" "◑" "◒"] :square ["◰" "◳" "◲" "◱"] :triangle ["◢" "◣" "◤" "◥"] :bounce ["⠁" "⠂" "⠄" "⠂"] :dots2 ["⣾" "⣽" "⣻" "⢿" "⡿" "⣟" "⣯" "⣷"] :arc ["◜" "◠" "◝" "◞" "◡" "◟"] :moon ["🌑" "🌒" "🌓" "🌔" "🌕" "🌖" "🌗" "🌘"]}) ;; === Model === (def initial-model {:frame 0 :style :dots :loading true :message "Loading..." :styles (keys spinner-styles) :style-idx 0}) ;; === Update === (defn update-model [{:keys [styles style-idx] :as model} msg] (cond ;; Quit (or (tui/key= msg "q") (tui/key= msg [:ctrl \c])) [model tui/quit] ;; Tick - advance frame (= (first msg) :tick) (if (:loading model) [(update model :frame inc) (tui/tick 80)] [model nil]) ;; Space - simulate completion (tui/key= msg " ") [(assoc model :loading false :message "Done!") nil] ;; Tab - change spinner style (tui/key= msg :tab) (let [new-idx (mod (inc style-idx) (count styles))] [(assoc model :style-idx new-idx :style (nth styles new-idx)) nil]) ;; r - restart (tui/key= msg "r") [(assoc model :loading true :frame 0 :message "Loading...") (tui/tick 80)] :else [model nil])) ;; === View === (defn spinner-view [{:keys [frame style]}] (let [frames (get spinner-styles style) idx (mod frame (count frames))] (nth frames idx))) (defn view [{:keys [loading message style] :as model}] [:col {:gap 1} [:box {:border :rounded :padding [1 2]} [:col {:gap 1} [:text {:bold true} "Spinner Demo"] [:text ""] [:row {:gap 1} (if loading [:text {:fg :cyan} (spinner-view model)] [:text {:fg :green} "✓"]) [:text message]] [:text ""] [:text {:fg :gray} (str "Style: " (name style))]]] [:col [:text {:fg :gray} "tab: change style space: complete r: restart q: quit"]]]) ;; === Main === (defn -main [& _args] (println "Starting spinner...") (tui/run {:init initial-model :update update-model :view view :init-cmd (tui/tick 80)}) (println "Spinner demo finished."))