diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 913932a..53fab82 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -10,44 +10,44 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v6 - with: - node-version: 24 - - - name: Enable Corepack - run: | - corepack enable - corepack prepare yarn@4.12.0 --activate - yarn --version - - - uses: calcit-lang/setup-cr@0.0.8 - - - name: "load deps" - run: caps --ci && yarn - - - name: "test js" - run: > - cr --init-fn respo.test.main/main! js - && node test.mjs - - - name: "build js" - run: > - cr js - && yarn vite build --base=./ - - - name: Deploy to server - id: deploy - uses: Pendect/action-rsyncer@v2.0.0 - env: - DEPLOY_KEY: ${{secrets.rsync_private_key}} - with: - flags: '-avzr --progress' - options: '' - ssh_options: '' - src: 'dist/*' - dest: 'rsync-user@tiye.me:/web-assets/repo/${{ github.repository }}' - - - name: Display status from deploy - run: echo "${{ steps.deploy.outputs.status }}" + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v6 + with: + node-version: 24 + + - name: Enable Corepack + run: | + corepack enable + corepack prepare yarn@4.12.0 --activate + yarn --version + + - uses: calcit-lang/setup-cr@0.0.8 + + - name: "load deps" + run: caps --ci && yarn + + - name: "test js" + run: > + cr --init-fn respo.test.main/main! js + && node test.mjs + + - name: "build js" + run: > + cr js + && yarn vite build --base=./ + + - name: Deploy to server + id: deploy + uses: Pendect/action-rsyncer@v2.0.0 + env: + DEPLOY_KEY: ${{secrets.rsync_private_key}} + with: + flags: "-avzr --progress" + options: "" + ssh_options: "" + src: "dist/*" + dest: "rsync-user@tiye.me:/web-assets/repo/${{ github.repository }}" + + - name: Display status from deploy + run: echo "${{ steps.deploy.outputs.status }}" diff --git a/.gitignore b/.gitignore index 6bd40c3..bbde022 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ tmp/ draft/ .yarn/*.gz + +.calcit-snippets/ \ No newline at end of file diff --git a/Agents.md b/Agents.md index 7c5b6f8..88242ce 100644 --- a/Agents.md +++ b/Agents.md @@ -29,6 +29,14 @@ cr docs agents --full - 若代码块是“示意片段”而非可独立运行程序,优先标记为 `cirru.no-check`。 - 若需要在单个代码块里串联多个表达式并共享中间值,使用 `let` 显式绑定;默认不会把前面表达式自动注册为全局定义。 +Respo 特有约束(不要上推到 Calcit 主程序): + +- `defstyle`、`:class-name`、DOM props、样式字符串等约定,只放在 Respo 文档或 Agent 文件中说明,不要要求 Calcit CLI/Rust 主程序内置这些领域知识。 +- 编辑 `defstyle` 时,selector 使用字符串叶子,如 `|&`、`|&:hover`、`|input&`;不要写裸符号 `&`。 +- 样式值只要带空格或特殊字符,优先按字符串处理,并尽量复用 CLI 已输出的序列化形式。例如 `"|4px 10px"`、`"|1px solid "`、`"|calc(100vh - 76px)"`。 +- 遇到这类字符串,不要期待 Calcit 主程序理解它们的前端语义;应通过 Respo 文档里的工作流来规避误写:先 `cr query def` 看当前序列化,再用 `cr edit def --overwrite -f ...` 覆盖。 +- 相关细节统一收敛到 `docs/guide/styles.md`,Agent 文件只保留高频提醒,避免重复扩写。 + CLI 查询速查(面向 Agent): - 列出命名空间: diff --git a/compact.cirru b/compact.cirru index 4a7ee7a..e516cf6 100644 --- a/compact.cirru +++ b/compact.cirru @@ -1,7 +1,7 @@ {} (:about "|file is generated - never edit directly; learn cr edit/tree workflows before changing") (:package |respo) - :configs $ {} (:init-fn |respo.main/main!) (:reload-fn |respo.main/reload!) (:version |0.16.30) - :modules $ [] |memof/ |lilac/ |calcit-test/ + :configs $ {} (:init-fn |respo.main/main!) (:reload-fn |respo.main/reload!) (:version |0.16.33) + :modules $ [] |memof/ |calcit-test/ :entries $ {} :files $ {} |respo.app.comp.container $ %{} :FileEntry @@ -25,15 +25,15 @@ |style-global $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-global $ {} - "\"&" $ {} (:font-family |Avenir,Verdana) - "\"&" $ {} ('contained "\"@media only screen and (max-width: 600px)") + |& $ {} (:font-family |Avenir,Verdana) + |& $ {} ('contained "|@media only screen and (max-width: 600px)") :background-color $ hsl 0 0 90 :examples $ [] - |style-states $ %{} :CodeEntry (:doc |) (:schema nil) + |style-states $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def style-states $ {} (:padding 8) :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.comp.container $ :require respo.core :refer $ defcomp div span <> >> a @@ -42,7 +42,6 @@ respo.app.comp.todolist :refer $ comp-todolist respo.comp.space :refer $ =< respo.comp.inspect :refer $ highlight-defcomp - :examples $ [] |respo.app.comp.task $ %{} :FileEntry :defs $ {} |comp-task $ %{} :CodeEntry (:doc |) @@ -85,17 +84,20 @@ :schema $ :: :fn {} (:return 'respo.schema/Component) :args $ [] :dynamic :dynamic - |effect-log $ %{} :CodeEntry (:doc |) (:schema nil) + |effect-log $ %{} :CodeEntry (:doc |) :code $ quote - defeffect effect-log (task) (action parent at-place?) (; js/console.log "\"Task effect" action at-place?) + defeffect effect-log (task) (action parent at-place?) (; js/console.log "|Task effect" action at-place?) case-default action nil :mount $ let x0 $ js/Math.random - ; println "\"Stored" x0 + ; println |Stored x0 , nil - :update (; println "\"read") nil - :unmount (; println "\"read") nil + :update (; println |read) nil + :unmount (; println |read) nil :examples $ [] + :schema $ :: :fn + {} (:return 'respo.schema/Effect) + :args $ [] :dynamic |style-done $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-done $ {} @@ -104,9 +106,9 @@ |style-task $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-task $ {} - "\"&" $ {} (:display :flex) (:padding "|4px 0px") + |& $ {} (:display :flex) (:padding "|4px 0px") :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.comp.task $ :require respo.core :refer $ defcomp div input span button <> defeffect @@ -115,7 +117,6 @@ respo.comp.inspect :refer $ comp-inspect respo.app.style.widget :as widget respo.css :refer $ defstyle - :examples $ [] |respo.app.comp.todolist $ %{} :FileEntry :defs $ {} |comp-todolist $ %{} :CodeEntry (:doc |) @@ -125,13 +126,14 @@ cursor $ either (:cursor states) ([]) state $ either (:data states) {} (:draft |) (:locked? false) (:message "|Press Ctrl+M to change message") - [] (on-keydown cursor state) (effect-focus) + [] (on-keydown cursor state) (effect-focus |#draft-input) div {} (:class-name style-todo-root) (:data-name |todolist) comp-inspect |States state $ {} (:left |80px) div {} $ :style style-panel input $ {} (:placeholder |Text) + :id |draft-input :value $ :draft state :class-name widget/style-input :style $ {} @@ -194,11 +196,18 @@ :schema $ :: :fn {} (:return 'respo.schema/Component) :args $ [] :dynamic :dynamic - |effect-focus $ %{} :CodeEntry (:doc |) (:schema nil) + |effect-focus $ %{} :CodeEntry (:doc |) :code $ quote - defeffect effect-focus () $ action parent at-place? + defeffect effect-focus (pattern) (action parent at-place?) + when (= action :mount) + if-let + target $ js/document.querySelector pattern + .!select target :examples $ [] - |make-keydown-listener $ %{} :CodeEntry (:doc "|DEPRECATED: Factory function approach for creating listeners. This was an experimental approach that did not work due to Record serialization issues. Use on-keydown function instead.") (:schema nil) + :schema $ :: :fn + {} (:return 'respo.schema/Effect) + :args $ [] :string + |make-keydown-listener $ %{} :CodeEntry (:doc "|DEPRECATED: Factory function approach for creating listeners. This was an experimental approach that did not work due to Record serialization issues. Use on-keydown function instead.") :code $ quote defn make-keydown-listener (cursor state) %{} respo.schema/RespoListener (:name :on-keydown) @@ -215,16 +224,25 @@ fn () $ dispatch! cursor (assoc state :message "|Press Ctrl+M to change message") , 2000 :examples $ [] - |number-order $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return 'respo.schema/RespoListener) + :args $ [] :list :map + |number-order $ %{} :CodeEntry (:doc |) :code $ quote defn number-order (a b) if (&< a b) -1 $ if (&> a b) 1 0 :examples $ [] - |on-focus $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return :number) + :args $ [] :number :number + |on-focus $ %{} :CodeEntry (:doc |) :code $ quote defn on-focus (e dispatch!) (println "|Just focused~") :examples $ [] - |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.") (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic :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) @@ -243,41 +261,47 @@ , 2000 :examples $ [] quote $ on-keydown cursor state - |on-test $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return 'respo.schema/RespoListener) + :args $ [] :list :map + |on-test $ %{} :CodeEntry (:doc |) :code $ quote defn on-test (e dispatch!) (println "|trigger test!") try-test! dispatch! $ [] :examples $ [] + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic :fn |style-bold! $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-bold! $ {} - "\"&" $ {} (:font-weight "\"bold !important") + |& $ {} (:font-weight "|bold !important") :examples $ [] - |style-list $ %{} :CodeEntry (:doc |) (:schema nil) + |style-list $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def style-list $ {} (:color :black) :background-color $ hsl 120 20 98 :examples $ [] - |style-panel $ %{} :CodeEntry (:doc |) (:schema nil) + |style-panel $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def style-panel $ {} (:display :flex) (:margin-bottom 4) :examples $ [] |style-todo-root $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-todo-root $ {} - "\"&" $ {} (:color :black) + |& $ {} (:color :black) :background-color $ hsl 120 20 98 :line-height |24px - "\"font-size" 16 + |font-size 16 :padding 10 :font-family "|\"微软雅黑\", Verdana" :examples $ [] |style-toolbar $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-toolbar $ {} - "\"&" $ {} (:display :flex) (:flex-direction :row) (:justify-content :start) (:padding "\"4px 0") (:white-space :nowrap) + |& $ {} (:display :flex) (:flex-direction :row) (:justify-content :start) (:padding "|4px 0") (:white-space :nowrap) :examples $ [] - |try-test! $ %{} :CodeEntry (:doc |) (:schema nil) + |try-test! $ %{} :CodeEntry (:doc |) :code $ quote defn try-test! (dispatch! acc) let @@ -308,7 +332,10 @@ , 0 println |result: $ sort acc number-order :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :fn (:: :list :number) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.comp.todolist $ :require respo.core :refer $ defcomp div span input <> list-> defeffect >> a @@ -322,7 +349,6 @@ respo.app.style.widget :as widget memof.once :refer $ memof1-call-by respo.css :refer $ defstyle - :examples $ [] |respo.app.comp.wrap $ %{} :FileEntry :defs $ {} |comp-wrap $ %{} :CodeEntry (:doc |) @@ -333,11 +359,10 @@ :schema $ :: :fn {} (:return 'respo.schema/Component) :args $ [] :dynamic - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.comp.wrap $ :require respo.core :refer $ defcomp div - :examples $ [] |respo.app.comp.zero $ %{} :FileEntry :defs $ {} |comp-zero $ %{} :CodeEntry (:doc |) @@ -348,17 +373,16 @@ :schema $ :: :fn {} (:return 'respo.schema/Component) :args $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.comp.zero $ :require respo.core :refer $ defcomp div - :examples $ [] |respo.app.core $ %{} :FileEntry :defs $ {} - |*store $ %{} :CodeEntry (:doc "|Global state storage Atom for the Respo application.\n\nThis is an atom containing all application state data, initialized with the structure defined by schema/store.\nIn Respo applications, all component states are stored in this global store and updated through the dispatch mechanism.") (:schema nil) + |*store $ %{} :CodeEntry (:doc "|Global state storage Atom for the Respo application.\n\nThis is an atom containing all application state data, initialized with the structure defined by schema/store.\nIn Respo applications, all component states are stored in this global store and updated through the dispatch mechanism.") (:schema :ref) :code $ quote (defatom *store schema/store) :examples $ [] - |dispatch! $ %{} :CodeEntry (:doc |) (:schema nil) + |dispatch! $ %{} :CodeEntry (:doc |) :code $ quote defn dispatch! (op ? op-data) if dev? $ js/console.log op op-data @@ -366,21 +390,33 @@ store $ updater @*store op (generate-id!) reset! *store store :examples $ [] - |handle-ssr! $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic (:: :optional :dynamic) + |handle-ssr! $ %{} :CodeEntry (:doc |) :code $ quote defn handle-ssr! (mount-target) realize-ssr! mount-target (comp-container @*store) dispatch! :examples $ [] - |new-fn $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic + |new-fn $ %{} :CodeEntry (:doc |) :code $ quote defn new-fn () $ println |hello :examples $ [] - |render-app! $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] + |render-app! $ %{} :CodeEntry (:doc |) :code $ quote defn render-app! (mount-target) render! mount-target (comp-container @*store) dispatch! :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.core $ :require respo.app.comp.container :refer $ comp-container @@ -388,55 +424,52 @@ respo.schema :refer $ dev? respo.app.schema :as schema respo.app.updater :refer $ updater - :examples $ [] |respo.app.schema $ %{} :FileEntry :defs $ {} - |store $ %{} :CodeEntry (:doc |) (:schema nil) + |store $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def store $ {} :tasks $ [] :states $ {} :cursor $ [] :examples $ [] - |task $ %{} :CodeEntry (:doc |) (:schema nil) + |task $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote def task $ {} (:id nil) (:text |) (:done? false) :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote (ns respo.app.schema) - :examples $ [] |respo.app.style.widget $ %{} :FileEntry :defs $ {} - |button $ %{} :CodeEntry (:doc |) (:schema nil) + |button $ %{} :CodeEntry (:doc |) (:schema :map) :code $ quote - def button $ {} (:display :inline-block) (:padding "\"0 6px 0 6px") (:font-family |Avenir,Verdana) (:cursor :pointer) + def button $ {} (:display :inline-block) (:padding "|0 6px 0 6px") (:font-family |Avenir,Verdana) (:cursor :pointer) :background-color $ hsl 0 80 70.9 :color $ hsl 0 0 100 :height 28 - :line-height "\"28px" - :transition-duration "\"200ms" + :line-height |28px + :transition-duration |200ms :examples $ [] |style-button $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-button $ {} (:& button) - "\"&:hover" $ {} (:transform "\"scale(1.04)") + |&:hover $ {} (:transform "|scale(1.04)") :examples $ [] |style-input $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-input $ {} - "\"&" $ {} (:font-size |16px) (:line-height |24px) (:padding "|0px 8px") (:outline :none) (:min-width |300px) + |& $ {} (:font-size |16px) (:line-height |24px) (:padding "|0px 8px") (:outline :none) (:min-width |300px) :background-color $ hsl 0 0 94 :border :none :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.style.widget $ :require respo.util.format :refer $ hsl respo.css :refer $ defstyle - :examples $ [] |respo.app.updater $ %{} :FileEntry :defs $ {} - |updater $ %{} :CodeEntry (:doc |) (:schema nil) + |updater $ %{} :CodeEntry (:doc |) :code $ quote defn updater (store op op-id) (; println store op) tag-match op @@ -473,19 +506,21 @@ = (:id task) task-id update task :done? not , task - _ $ do (eprintln "\"Unknown op:" op) store + _ $ do (eprintln "|Unknown op:" op) store :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return :map) + :args $ [] :map :dynamic :dynamic + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.app.updater $ :require respo.cursor :refer $ update-states update-states-kv update-states-merge - :examples $ [] |respo.comp.global-keydown $ %{} :FileEntry :defs $ {} |comp-global-keydown $ %{} :CodeEntry (:doc |) :code $ quote - defcomp comp-global-keydown (options on-event) (; "\"dirty solution: proxy window keydown event to a ``, comes with some restrictions. however Respo does not allow effects to modify states.") - [] (effect-listen-keyboard options "\"keydown") + defcomp comp-global-keydown (options on-event) (; "|dirty solution: proxy window keydown event to a ``, comes with some restrictions. however Respo does not allow effects to modify states.") + [] (effect-listen-keyboard options |keydown) span $ {} :on-keydown $ fn (e d!) (on-event e d!) :examples $ [] @@ -494,25 +529,25 @@ :args $ [] :dynamic :dynamic |comp-global-keyup $ %{} :CodeEntry (:doc |) :code $ quote - defcomp comp-global-keyup (options on-event) (; "\"dirty solution: proxy window keydown event to a ``, comes with some restrictions. however Respo does not allow effects to modify states.") - [] (effect-listen-keyboard options "\"keyup") + defcomp comp-global-keyup (options on-event) (; "|dirty solution: proxy window keydown event to a ``, comes with some restrictions. however Respo does not allow effects to modify states.") + [] (effect-listen-keyboard options |keyup) span $ {} :on-keyup $ fn (e d!) (on-event e d!) :examples $ [] :schema $ :: :fn {} (:return 'respo.schema/Component) :args $ [] :dynamic :dynamic - |dirty-field $ %{} :CodeEntry (:doc "|Constant string key for the global keyboard listener.") (:schema nil) - :code $ quote (def dirty-field "\"_global_listener") + |dirty-field $ %{} :CodeEntry (:doc "|Constant string key for the global keyboard listener.") (:schema :string) + :code $ quote (def dirty-field |_global_listener) :examples $ [] - |effect-listen-keyboard $ %{} :CodeEntry (:doc "|Effect for listening to global keyboard events on the window object.") (:schema nil) + |effect-listen-keyboard $ %{} :CodeEntry (:doc "|Effect for listening to global keyboard events on the window object.") :code $ quote defeffect effect-listen-keyboard (options event-name) (action el at?) cond or (= action :mount) (= action :update) let - disabled-commands $ noted "\"copied event does not support `event.preventDefault()`, so we need to pass a set of configs" - either (:disabled-commands options) (#{} "\"p" "\"s") + disabled-commands $ noted "|copied event does not support `event.preventDefault()`, so we need to pass a set of configs" + either (:disabled-commands options) (#{} |p |s) handler $ fn (event) if and @@ -532,11 +567,13 @@ js-delete el dirty-field true nil :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return 'respo.schema/Effect) + :args $ [] :dynamic :string + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.comp.global-keydown $ :require respo.core :refer $ defcomp defeffect <> >> div button textarea span input a list-> - :examples $ [] |respo.comp.inspect $ %{} :FileEntry :defs $ {} |comp-inspect $ %{} :CodeEntry (:doc "|put a label in tag with absolute position, click it to print data.\n\n3 parameters are,\n- `tip` a string of comment,\n- `data` Calcit data to inspect, which will be printed in Console,\n- `style` string of className, or hashmap of styles") @@ -576,21 +613,20 @@ |highlight-defcomp $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle highlight-defcomp $ {} - "\"& *" $ {} - :outline $ str "\"1px dashed " (hsl 200 40 50 0.5) + "|& *" $ {} + :outline $ str "|1px dashed " (hsl 200 40 50 0.5) :examples $ [] |style-data $ %{} :CodeEntry (:doc |) (:schema :string) :code $ quote defstyle style-data $ {} - "\"&" $ {} (:position :absolute) (:background-color "\"hsl(240,100%,0%)") (:color :white) (:opacity 0.2) (:font-size |12px) (:font-family |Avenir,Verdana) (:line-height "\"1.4em") (:padding "|2px 6px") (:border-radius |4px) (:max-width 160) (:max-height 32) (:white-space :normal) (:text-overflow :ellipsis) (:cursor :default) + |& $ {} (:position :absolute) (:background-color "|hsl(240,100%,0%)") (:color :white) (:opacity 0.2) (:font-size |12px) (:font-family |Avenir,Verdana) (:line-height |1.4em) (:padding "|2px 6px") (:border-radius |4px) (:max-width 160) (:max-height 32) (:white-space :normal) (:text-overflow :ellipsis) (:cursor :default) :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.comp.inspect $ :require respo.core :refer $ defcomp pre <> respo.css :refer $ defstyle respo.util.format :refer $ hsl - :examples $ [] |respo.comp.space $ %{} :FileEntry :defs $ {} |=< $ %{} :CodeEntry (:doc "|insert a tiny space, horizontally or verticaly.\n\n- `8 nil` for horizontal width 8px,\n- `nil 8` for vertical height 8px.\n") @@ -619,15 +655,14 @@ defstyle style-space $ {} :& $ {} (:height 1) (:width 1) (:display :inline-block) :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.comp.space $ :require respo.core :refer $ div defcomp respo.css :refer $ defstyle - :examples $ [] |respo.controller.client $ %{} :FileEntry :defs $ {} - |activate-instance! $ %{} :CodeEntry (:doc "|Initializes the application by mounting the root element to the DOM.") (:schema nil) + |activate-instance! $ %{} :CodeEntry (:doc "|Initializes the application by mounting the root element to the DOM.") :code $ quote defn activate-instance! (entire-dom mount-point deliver-event) let @@ -635,7 +670,10 @@ set! (.-innerHTML mount-point) | .!appendChild mount-point $ make-element entire-dom listener-builder ([]) :examples $ [] - |build-listener $ %{} :CodeEntry (:doc "|Creates a DOM event listener that converts events and dispatches them to Respo.") (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] 'respo.schema/Component :dynamic :fn + |build-listener $ %{} :CodeEntry (:doc "|Creates a DOM event listener that converts events and dispatches them to Respo.") :code $ quote defn build-listener (event-name deliver-event) fn (event coord) @@ -643,13 +681,19 @@ simple-event $ event->edn event deliver-event coord event-name simple-event :examples $ [] - |patch-instance! $ %{} :CodeEntry (:doc "|Applies collected changes to the DOM and updates event listeners.") (:schema nil) + :schema $ :: :fn + {} (:return :fn) + :args $ [] :dynamic :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) let listener-builder $ fn (event-name) (build-listener event-name deliver-event) apply-dom-changes changes mount-point listener-builder :examples $ [] + :schema $ :: :fn + {} (:return :unit) + :args $ [] :list :dynamic :fn |send-to-component! $ %{} :CodeEntry (:doc |) :code $ quote defn send-to-component! (event-tuple) (assert-type event-tuple :tuple) @@ -661,7 +705,7 @@ :schema $ :: :fn {} (:return :tag) :args $ [] :tuple - |traverse-and-call $ %{} :CodeEntry (:doc |) (:schema nil) + |traverse-and-call $ %{} :CodeEntry (:doc |) :code $ quote defn traverse-and-call (element event-tuple dispatch!) when (some? element) @@ -681,7 +725,10 @@ child $ get pair 1 traverse-and-call child event-tuple dispatch! :examples $ [] - |wrap-dispatch $ %{} :CodeEntry (:doc "|Wraps a raw dispatch function to automatically handle different operation types (list, tag, or direct).") (:schema nil) + :schema $ :: :fn + {} (:return :unit) + :args $ [] :dynamic :tuple :fn + |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) fn (op ? data) @@ -693,7 +740,10 @@ dispatch! $ :: op data dispatch! op :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return :fn) + :args $ [] :ref + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.controller.client $ :require respo.render.patch :refer $ apply-dom-changes @@ -702,24 +752,26 @@ respo.core :refer $ *dispatch-fn *global-element respo.util.detect :refer $ component? element? respo.controller.resolve :refer $ extract-listeners - :examples $ [] |respo.controller.resolve $ %{} :FileEntry :defs $ {} - |build-deliver-event $ %{} :CodeEntry (:doc "|Creates a function to dispatch events from the DOM to Respo's event handling system.") (:schema nil) + |build-deliver-event $ %{} :CodeEntry (:doc "|Creates a function to dispatch events from the DOM to Respo's event handling system.") :code $ quote defn build-deliver-event (*global-element *dispatch-fn) - fn (coord event-name simple-event) (; echo "\"event coord" coord) + fn (coord event-name simple-event) (; echo "|event coord" coord) let target-element $ find-event-target @*global-element coord event-name target-listener $ if (some? target-element) get (:event target-element) event-name - do (js/console.warn "\"found no element" coord event-name) nil + do (js/console.warn "|found no element" coord event-name) nil dispatch-wrap $ wrap-dispatch *dispatch-fn if (some? target-listener) do (; println "|listener found:" coord event-name) (target-listener simple-event dispatch-wrap) ; println "|found no listener:" coord event-name :examples $ [] - |extract-listeners $ %{} :CodeEntry (:doc |) (:schema nil) + :schema $ :: :fn + {} (:return :fn) + :args $ [] :ref :ref + |extract-listeners $ %{} :CodeEntry (:doc |) :code $ quote defn extract-listeners (component-result) if (list? component-result) @@ -734,11 +786,14 @@ :listeners $ [] :element component-result :examples $ [] - |find-event-target $ %{} :CodeEntry (:doc "|Traverses the virtual DOM to find the element that should handle a specific event.") (:schema nil) + :schema $ :: :fn + {} (:return :map) + :args $ [] :dynamic + |find-event-target $ %{} :CodeEntry (:doc "|Traverses the virtual DOM to find the element that should handle a specific event.") :code $ quote - defn find-event-target (element coord event-name) (; echo "\"looking for" coord event-name) - assert "\"element cannot be nil" $ some? element - assert "\"coord cannot be nil" $ some? coord + defn find-event-target (element coord event-name) (; echo "|looking for" coord event-name) + assert "|element cannot be nil" $ some? element + assert "|coord cannot be nil" $ some? coord let target-element $ loop m $ get-markup-at element coord @@ -757,7 +812,10 @@ , event-name , nil :examples $ [] - |get-markup-at $ %{} :CodeEntry (:doc "|Retrieves the virtual DOM element at the specified coordinate.") (:schema nil) + :schema $ :: :fn + {} (:return :dynamic) + :args $ [] :dynamic :list :dynamic + |get-markup-at $ %{} :CodeEntry (:doc "|Retrieves the virtual DOM element at the specified coordinate.") :code $ quote defn get-markup-at (markup coord) ; println |markup: $ to-lispy-string coord @@ -775,23 +833,25 @@ raise $ str "|child not found:" coord map (:children markup) first :examples $ [] - :ns $ %{} :CodeEntry (:doc |) (:schema :unit) + :schema $ :: :fn + {} (:return :dynamic) + :args $ [] :dynamic :list + :ns $ %{} :NsEntry (:doc |) :code $ quote ns respo.controller.resolve $ :require respo.util.detect :refer $ component? element? listener? respo.controller.client :refer $ wrap-dispatch - :examples $ [] |respo.core $ %{} :FileEntry :defs $ {} - |*changes-logger $ %{} :CodeEntry (:doc "|Atom to hold a logging function for observing changes during rerenders. Function signature: (old-tree new-tree changes).") (:schema nil) + |*changes-logger $ %{} :CodeEntry (:doc "|Atom to hold a logging function for observing changes during rerenders. Function signature: (old-tree new-tree changes).") (:schema :ref) :code $ quote (defatom *changes-logger nil) :examples $ [] quote $ reset! *changes-logger fn (old new changes) (println changes) - |*dispatch-fn $ %{} :CodeEntry (:doc "|internal atom storing the dispatch function. used to handle events and state updates throughout the application.") (:schema nil) + |*dispatch-fn $ %{} :CodeEntry (:doc "|internal atom storing the dispatch function. used to handle events and state updates throughout the application.") (:schema :ref) :code $ quote (defatom *dispatch-fn nil) :examples $ [] - |*global-element $ %{} :CodeEntry (:doc "|internal atom storing the current virtual DOM tree. used by render! to track and update the application state.") (:schema nil) + |*global-element $ %{} :CodeEntry (:doc "|internal atom storing the current virtual DOM tree. used by render! to track and update the application state.") (:schema :ref) :code $ quote (defatom *global-element nil) :examples $ [] |<> $ %{} :CodeEntry (:doc "|create a text node using span element. first argument is the text content. optional second argument is style (hashmap) or class-name (string).") @@ -827,11 +887,14 @@ :schema $ :: :fn {} (:rest :dynamic) (:return :tag) :args $ [] (:: :optional :map) - |blockquote $ %{} :CodeEntry (:doc |) (:schema nil) + |blockquote $ %{} :CodeEntry (:doc |) :code $ quote defn blockquote (props & children) (create-element :blockquote props & children) :examples $ [] - |body $ %{} :CodeEntry (:doc "|create a body element with properties and children. first argument is a hashmap for properties, rest arguments are children elements.") (:schema nil) + :schema $ :: :fn + {} (:rest :dynamic) (:return :tag) + :args $ [] (:: :optional :map) + |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) :examples $ [] @@ -840,6 +903,9 @@ quote $ body {} $ :style {} $ :margin |0 + :schema $ :: :fn + {} (:rest :dynamic) (:return :tag) + :args $ [] (:: :optional :map) |button $ %{} :CodeEntry (:doc "|Renders a