init
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
(ns examples.views
|
||||
"Multiple views example - demonstrates state machine pattern.
|
||||
Mirrors bubbletea's views example."
|
||||
(:require [tui.core :as tui]))
|
||||
|
||||
;; === Model ===
|
||||
(def initial-model
|
||||
{:view :menu ; :menu, :detail, :confirm
|
||||
:cursor 0
|
||||
:items [{:name "Profile" :desc "View and edit your profile settings"}
|
||||
{:name "Settings" :desc "Configure application preferences"}
|
||||
{:name "Help" :desc "Get help and documentation"}
|
||||
{:name "About" :desc "About this application"}]
|
||||
:selected nil})
|
||||
|
||||
;; === Update ===
|
||||
(defn update-model [{:keys [view cursor items] :as model} msg]
|
||||
(case view
|
||||
;; Menu view
|
||||
:menu
|
||||
(cond
|
||||
(or (tui/key= msg "q")
|
||||
(tui/key= msg [:ctrl \c]))
|
||||
[model tui/quit]
|
||||
|
||||
(or (tui/key= msg :up)
|
||||
(tui/key= msg "k"))
|
||||
[(update model :cursor #(max 0 (dec %))) nil]
|
||||
|
||||
(or (tui/key= msg :down)
|
||||
(tui/key= msg "j"))
|
||||
[(update model :cursor #(min (dec (count items)) (inc %))) nil]
|
||||
|
||||
(tui/key= msg :enter)
|
||||
[(assoc model
|
||||
:view :detail
|
||||
:selected (nth items cursor))
|
||||
nil]
|
||||
|
||||
:else
|
||||
[model nil])
|
||||
|
||||
;; Detail view
|
||||
:detail
|
||||
(cond
|
||||
(or (tui/key= msg "q")
|
||||
(tui/key= msg [:ctrl \c]))
|
||||
[(assoc model :view :confirm) nil]
|
||||
|
||||
(or (tui/key= msg :escape)
|
||||
(tui/key= msg "b"))
|
||||
[(assoc model :view :menu :selected nil) nil]
|
||||
|
||||
:else
|
||||
[model nil])
|
||||
|
||||
;; Confirm quit dialog
|
||||
:confirm
|
||||
(cond
|
||||
(tui/key= msg "y")
|
||||
[model tui/quit]
|
||||
|
||||
(or (tui/key= msg "n")
|
||||
(tui/key= msg :escape))
|
||||
[(assoc model :view :detail) nil]
|
||||
|
||||
:else
|
||||
[model nil])))
|
||||
|
||||
;; === Views ===
|
||||
(defn menu-view [{:keys [cursor items]}]
|
||||
[:col {:gap 1}
|
||||
[:box {:border :rounded :padding [0 1] :title "Main Menu"}
|
||||
[:col
|
||||
(for [[idx item] (map-indexed vector items)]
|
||||
(let [is-cursor (= idx cursor)]
|
||||
[:row {:gap 1}
|
||||
[:text {:fg (when is-cursor :cyan)} (if is-cursor ">" " ")]
|
||||
[:text {:bold is-cursor
|
||||
:fg (when is-cursor :cyan)}
|
||||
(:name item)]]))]]
|
||||
[:text {:fg :gray} "j/k: navigate enter: select q: quit"]])
|
||||
|
||||
(defn detail-view [{:keys [selected]}]
|
||||
[:col {:gap 1}
|
||||
[:box {:border :double :padding [1 2]}
|
||||
[:col {:gap 1}
|
||||
[:text {:bold true :fg :cyan} (:name selected)]
|
||||
[:text ""]
|
||||
[:text (:desc selected)]
|
||||
[:text ""]
|
||||
[:text {:fg :gray :italic true}
|
||||
"This is a detailed view of the selected item."]
|
||||
[:text {:fg :gray :italic true}
|
||||
"You could show forms, settings, or other content here."]]]
|
||||
[:text {:fg :gray} "b/esc: back q: quit"]])
|
||||
|
||||
(defn confirm-view [_model]
|
||||
[:col {:gap 1}
|
||||
[:box {:border :rounded :padding [1 2]}
|
||||
[:col
|
||||
[:text {:bold true :fg :yellow} "Quit?"]
|
||||
[:text ""]
|
||||
[:text "Are you sure you want to quit?"]
|
||||
[:text ""]
|
||||
[:row {:gap 2}
|
||||
[:text {:fg :green} "[y] Yes"]
|
||||
[:text {:fg :red} "[n] No"]]]]])
|
||||
|
||||
(defn view [{:keys [view] :as model}]
|
||||
(case view
|
||||
:menu (menu-view model)
|
||||
:detail (detail-view model)
|
||||
:confirm (confirm-view model)))
|
||||
|
||||
;; === Main ===
|
||||
(defn -main [& _args]
|
||||
(println "Starting views demo...")
|
||||
(tui/run {:init initial-model
|
||||
:update update-model
|
||||
:view view})
|
||||
(println "Views demo finished."))
|
||||
Reference in New Issue
Block a user