diff --git a/.gitignore b/.gitignore index bbde022..ab65fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ draft/ .yarn/*.gz -.calcit-snippets/ \ No newline at end of file +.calcit-snippets/ + +.DS_Store diff --git a/compact.cirru b/compact.cirru index 5df111d..dd016d2 100644 --- a/compact.cirru +++ b/compact.cirru @@ -1,6 +1,6 @@ {} (:about "|Machine-generated snapshot. AI AGENTS: never edit this file directly — changes will be overwritten on recompile. Inspect via `cr query`; modify via `cr edit` / `cr tree`. MANDATORY first step: run `cr docs agents --full`.") (:package |respo) - :configs $ {} (:init-fn |respo.main/main!) (:reload-fn |respo.main/reload!) (:version |0.16.33) + :configs $ {} (:init-fn |respo.main/main!) (:reload-fn |respo.main/reload!) (:version |0.16.39) :modules $ [] |memof/ |calcit-test/ :entries $ {} :files $ {} @@ -58,7 +58,7 @@ :style $ {} :background-color $ if (:done? task) (hsl 200 20 80) (hsl 200 80 70) :on-click $ fn (e d!) - d! $ : toggle (:id task) + d! $ :: :toggle (:id task) =< 8 0 input $ {} :value $ :text task @@ -67,7 +67,7 @@ let task-id $ :id task text $ :value e - d! $ : update task-id text + d! $ %:: Op :update task-id text =< 8 0 input $ {} (:value state) (:class-name widget/style-input) :on-input $ fn (e d!) @@ -76,7 +76,7 @@ div {} (:class-name widget/style-button) :on-click $ fn (e d!) - d! :remove $ :id task + d! $ %:: Op :remove (:id task) <> |Remove =< 8 0 div ({}) (<> state) @@ -117,6 +117,7 @@ respo.comp.inspect :refer $ comp-inspect respo.app.style.widget :as widget respo.css :refer $ defstyle + respo.app.schema :refer $ Op |respo.app.comp.todolist $ %{} :FileEntry :defs $ {} |comp-todolist $ %{} :CodeEntry (:doc |) @@ -139,20 +140,20 @@ :width $ &max 200 + 24 $ text-width (:draft state) 16 |BlinkMacSystemFont :on-input $ fn (e d!) - d! $ :: :states-merge cursor state + d! $ %:: Op :states-merge cursor state {} $ :draft (:value e) :on-focus on-focus =< 8 0 span {} (:class-name widget/style-button) :on-click $ fn (e d!) - d! $ : add (:draft state) + d! $ %:: Op :add (:draft state) d! cursor $ assoc state :draft | span $ {} (:on-click nil) (:inner-text |Add) =< 8 0 span $ {} (:inner-text |Clear) (:class-name widget/style-button) :on-click $ fn (e d!) - d! $ :: :clear + d! $ %:: Op :clear =< 8 0 div ({}) div @@ -174,7 +175,7 @@ :on-click $ if not $ :locked? state fn (e d!) - d! $ : clear + d! $ %:: Op :clear <> |Clear2 =< 8 0 div @@ -211,7 +212,7 @@ defn make-keydown-listener (cursor state) %{} respo.schema/RespoListener (:name :on-keydown) :handler $ fn (event dispatch!) - tag-match event $ + match event $ :keydown info when and @@ -240,23 +241,23 @@ :examples $ [] :schema $ :: :fn {} (:return :unit) - :args $ [] :dynamic :fn + :args $ [] 'respo.schema/RespoEvent :fn |on-keydown $ %{} :CodeEntry (:doc "|Creates a keyboard listener for Ctrl+M shortcut. This function demonstrates how to create component-local listeners that can access component state through closures. Returns a RespoListener that updates the message state when Ctrl+M is pressed.") :code $ quote defn on-keydown (cursor state) %{} respo.schema/RespoListener (:name :on-keydown) :handler $ fn (event dispatch!) - tag-match event $ + match event $ :keydown info when and = |m $ :key info :ctrl info do - dispatch! $ :: :states cursor (assoc state :message "|Message changed by Ctrl+M!") + dispatch! $ %:: Op :states cursor (assoc state :message "|Message changed by Ctrl+M!") js/window.setTimeout fn () $ dispatch! - :: :states cursor $ assoc state :message "|Press Ctrl+M to change message" + %:: Op :states cursor $ assoc state :message "|Press Ctrl+M to change message" , 2000 :examples $ [] quote $ on-keydown cursor state @@ -270,7 +271,7 @@ :examples $ [] :schema $ :: :fn {} (:return :unit) - :args $ [] :dynamic :fn + :args $ [] 'respo.schema/RespoEvent :fn |style-bold! $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-bold! $ {} @@ -305,21 +306,21 @@ defn try-test! (dispatch! acc) let started $ js/Date.now - dispatch! $ :: :clear + dispatch! $ %:: Op :clear loop x 20 - dispatch! :add |empty + dispatch! $ %:: Op :add |empty if (> x 0) recur $ dec x loop x 20 - dispatch! $ : hit-first (js/Math.random) + dispatch! $ %:: Op :hit-first (js/Math.random) if (> x 0) recur $ dec x - dispatch! $ :: :clear + dispatch! $ %:: Op :clear loop x 10 - dispatch! :add "|only 10 items" + dispatch! $ %:: Op :add "|only 10 items" if (> x 0) recur $ dec x let @@ -348,6 +349,7 @@ respo.app.style.widget :as widget memof.once :refer $ memof1-call-by respo.css :refer $ defstyle + respo.app.schema :refer $ Op |respo.app.comp.wrap $ %{} :FileEntry :defs $ {} |comp-wrap $ %{} :CodeEntry (:doc |) @@ -391,7 +393,7 @@ :examples $ [] :schema $ :: :fn {} (:return :unit) - :args $ [] :dynamic (:: :optional :dynamic) + :args $ [] 'respo.app.schema/Op (:: :optional :dynamic) |handle-ssr! $ %{} :CodeEntry (:doc |) :code $ quote defn handle-ssr! (mount-target) @@ -425,6 +427,10 @@ respo.app.updater :refer $ updater |respo.app.schema $ %{} :FileEntry :defs $ {} + |Op $ %{} :CodeEntry (:doc |) (:schema :dynamic) + :code $ quote + defenum Op (:states :list :dynamic) (:states-kv :list :dynamic :dynamic) (:states-merge :list :map :map) (:add :string) (:remove :string) (:clear) (:update :string :string) (:hit-first :dynamic) (:toggle :string) + :examples $ [] |store $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def store $ {} @@ -471,7 +477,7 @@ |updater $ %{} :CodeEntry (:doc |) :code $ quote defn updater (store op op-id) (; println store op) - tag-match op + match op :states cursor s update-states store cursor s (:states-kv cursor k v) (update-states-kv store cursor k v) @@ -509,7 +515,7 @@ :examples $ [] :schema $ :: :fn {} (:return :map) - :args $ [] :map :dynamic :dynamic + :args $ [] :map 'respo.app.schema/Op :string :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.updater $ :require @@ -685,7 +691,7 @@ :examples $ [] :schema $ :: :fn {} (:return :fn) - :args $ [] :dynamic :fn + :args $ [] :tag :fn |patch-instance! $ %{} :CodeEntry (:doc "|Applies collected changes to the DOM and updates event listeners.") :code $ quote defn patch-instance! (changes mount-point deliver-event) @@ -729,7 +735,9 @@ :examples $ [] :schema $ :: :fn {} (:return :unit) - :args $ [] :dynamic :tuple :fn + :args $ [] :dynamic :tuple + :: :fn $ {} (:return :unit) + :args $ [] :tuple |wrap-dispatch $ %{} :CodeEntry (:doc "|Wraps a raw dispatch function to automatically handle different operation types (list, tag, or direct).") :code $ quote defn wrap-dispatch (*dispatch-fn) @@ -816,7 +824,7 @@ :examples $ [] :schema $ :: :fn {} (:return :dynamic) - :args $ [] :dynamic :list :dynamic + :args $ [] :dynamic :list :tag |get-markup-at $ %{} :CodeEntry (:doc "|Retrieves the virtual DOM element at the specified coordinate.") :code $ quote defn get-markup-at (markup coord) @@ -864,7 +872,7 @@ span $ {} (:inner-text content) (:style style) :examples $ [] :schema $ :: :fn - {} (:return :tag) + {} (:return 'respo.schema/Element) :args $ [] :string (:: :optional :dynamic) |>> $ %{} :CodeEntry (:doc "|Navigates to a sub-state cursor. Used for managing nested component states.") :code $ quote @@ -877,7 +885,7 @@ quote $ >> states :task-a :schema $ :: :fn {} (:return :map) - :args $ [] :map :dynamic + :args $ [] :map :tag |a $ %{} :CodeEntry (:doc "|Creates HTML link element (anchor tag).\n\nParameters:\n props - Attribute map, can include standard HTML attributes like href, target, class-name, etc.\n & children - Variable arguments for child elements, typically link display text or other elements\n\nReturns:\n Created link element component\n\nUsed to create hyperlinks, supports all standard HTML link attributes.") :code $ quote defn a (props & children) (create-element :a props & children) @@ -885,15 +893,15 @@ quote $ a {} (:href |https://example.com) (:inner-text "|Visit Example") :schema $ :: :fn - {} (:rest :dynamic) (:return :tag) - :args $ [] (:: :optional :map) + {} (:rest :dynamic) (:return 'respo.schema/Element) + :args $ [] (:: :optional 'respo.schema/DomProps) |blockquote $ %{} :CodeEntry (:doc |) :code $ quote defn blockquote (props & children) (create-element :blockquote props & children) :examples $ [] :schema $ :: :fn - {} (:rest :dynamic) (:return :tag) - :args $ [] (:: :optional :map) + {} (:rest :dynamic) (:return 'respo.schema/Element) + :args $ [] (:: :optional 'respo.schema/DomProps) |body $ %{} :CodeEntry (:doc "|create a body element with properties and children. first argument is a hashmap for properties, rest arguments are children elements.") :code $ quote defn body (props & children) (create-element :body props & children) @@ -904,8 +912,8 @@ {} $ :style {} $ :margin |0 :schema $ :: :fn - {} (:rest :dynamic) (:return :tag) - :args $ [] (:: :optional :map) + {} (:rest :dynamic) (:return 'respo.schema/Element) + :args $ [] (:: :optional 'respo.schema/DomProps) |button $ %{} :CodeEntry (:doc "|Renders a