diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 52e82b3..4f27158 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -1,5 +1,6 @@ {:lint-as {hyperfiddle.electric/def clojure.core/def hyperfiddle.electric/defn clojure.core/defn hyperfiddle.electric/for clojure.core/for - hyperfiddle.electric/fn clojure.core/fn} + hyperfiddle.electric/fn clojure.core/fn + uix.core/defui clojure.core/defn} :linters {:redundant-expression {:level :off}}} diff --git a/deps.edn b/deps.edn index 2177ced..c568baf 100644 --- a/deps.edn +++ b/deps.edn @@ -15,6 +15,8 @@ ch.qos.logback/logback-classic {:mvn/version "1.2.11"} ring-basic-authentication/ring-basic-authentication {:mvn/version "1.1.1"} reagent/reagent {:mvn/version "1.1.1"} + com.pitch/uix.core {:mvn/version "1.0.1"} + com.pitch/uix.dom {:mvn/version "1.0.1"} markdown-clj/markdown-clj {:mvn/version "1.11.4"} nextjournal/clojure-mode {:git/url "https://github.com/nextjournal/clojure-mode" :sha "ac038ebf6e5da09dd2b8a31609e9ff4a65e36852"}} diff --git a/src/user/demo_uix_interop.cljc b/src/user/demo_uix_interop.cljc new file mode 100644 index 0000000..b297dcc --- /dev/null +++ b/src/user/demo_uix_interop.cljc @@ -0,0 +1,53 @@ +(ns user.demo-uix-interop + #?(:cljs (:require-macros [user.demo-uix-interop :refer [with-uix]])) + (:require [hyperfiddle.electric :as e] + [hyperfiddle.electric-dom2 :as dom] + [uix.core :refer [defui $ strict-mode]] + #?(:cljs [uix.dom :as ud]) + #?(:cljs ["recharts" :refer [ScatterChart Scatter LineChart Line + XAxis YAxis CartesianGrid]]))) + +(defmacro with-uix [app args] + `(dom/div ; React will hijack this element and empty it. + (let [root# (ud/create-root dom/node)] + (ud/render-root ($ strict-mode ($ ~app ~args)) root#) + (e/on-unmount #(.unmount root#))))) + +;; Reagent World + +(defui TinyLineChart [{:keys [data]}] + #?(:cljs + ($ LineChart {:width 400 :height 200 :data (clj->js data)} + ($ CartesianGrid {:strokeDasharray "3 3"}) + ($ XAxis {:dataKey "name"}) + ($ YAxis) + ($ Line {:type "monotone", :dataKey "pv", :stroke "#8884d8"}) + ($ Line {:type "monotone", :dataKey "uv", :stroke "#82ca9d"})))) + +(defui MousePosition [{:keys [x y]}] + #?(:cljs + ($ ScatterChart {:width 300 :height 300 + :margin {:top 20, :right 20, :bottom 20, :left 20}} + ($ CartesianGrid {:strokeDasharray "3 3"}) + ($ XAxis {:type "number", :dataKey "x", :unit "px", :domain #js[0 2000]}) + ($ YAxis {:type "number", :dataKey "y", :unit "px", :domain #js[0 2000]}) + ($ Scatter {:name "Mouse position", + :data (clj->js [{:x x, :y y}]), :fill "#8884d8"})))) + +;; Electric Clojure + +(e/defn UixInterop [] + (e/client + (let [[x y] (dom/on! js/document "mousemove" + (fn [e] [(.-clientX e) (.-clientY e)]))] + (with-uix MousePosition {:x x :y y}) ; reactive + ;; Adapted from https://recharts.org/en-US/examples/TinyLineChart + (with-uix TinyLineChart + {:data + [{:name "Page A" :uv 4000 :amt 2400 :pv 2400} + {:name "Page B" :uv 3000 :amt 2210 :pv 1398} + {:name "Page C" :uv 2000 :amt 2290 :pv (+ 6000 (* -5 y))} ; reactive + {:name "Page D" :uv 2780 :amt 2000 :pv 3908} + {:name "Page E" :uv 1890 :amt 2181 :pv 4800} + {:name "Page F" :uv 2390 :amt 2500 :pv 3800} + {:name "Page G" :uv 3490 :amt 2100 :pv 4300}]})))) diff --git a/src/user_main.cljc b/src/user_main.cljc index ab15863..680ccd9 100644 --- a/src/user_main.cljc +++ b/src/user_main.cljc @@ -42,6 +42,7 @@ wip.demo-custom-types wip.tracing user.demo-reagent-interop ; yarn + user.demo-uix-interop ;yarn wip.demo-stage-ui4 ; yarn wip.js-interop)) @@ -61,6 +62,7 @@ `user.demo-webview/Webview user.demo-webview/Webview `user.demo-todos-simple/TodoList user.demo-todos-simple/TodoList `user.demo-reagent-interop/ReagentInterop user.demo-reagent-interop/ReagentInterop + `user.demo-uix-interop/UixInterop user.demo-uix-interop/UixInterop ;; `wip.demo-stage-ui4/CrudForm wip.demo-stage-ui4/CrudForm `user.demo-svg/SVG user.demo-svg/SVG ; -- `wip.tracing/TracingDemo wip.tracing/TracingDemo @@ -165,7 +167,9 @@ {::id `user.demo-todos-simple/TodoList ::lead "minimal todo list. it's multiplayer, try two tabs"} {::id `user.demo-reagent-interop/ReagentInterop - ::lead "Reagent (React.js) embedded inside Electric. The reactive mouse coordinates cross from Electric to Reagent via props."} + ::lead "Reagent (React.js wrapper) embedded inside Electric. The reactive mouse coordinates cross from Electric to Reagent via props."} + {::id `user.demo-uix-interop/UixInterop + ::lead "Uix (modern React.js wrapper) embedded inside Electric. The reactive mouse coordinates cross from Electric to Reagent via props."} {::id `user.demo-svg/SVG ::lead "SVG support. Note the animation is reactive and driven by javascript cosine."}