Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Make Rum an optional dependency #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 3 additions & 64 deletions src/org/martinklepsch/derivatives.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -106,68 +106,7 @@
{:get! (partial get! dm)
:release! (partial release! dm)}))

;; RUM specific code ===========================================================

(let [get-k "org.martinklepsch.derivatives/get"
release-k "org.martinklepsch.derivatives/release"]

(defn rum-derivatives
"Given the passed spec add get!/release! derivative functions to
the child context so they can be seen by components using the `deriv`
mixin."
[spec]
#?(:cljs
{:class-properties {:childContextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:child-context (fn [_] (let [{:keys [release! get!]} (derivatives-pool spec)]
{release-k release! get-k get!}))}))

(defn rum-derivatives*
"Like rum-derivatives but get the spec from the arguments passed to the components (`:rum/args`) using `get-spec-fn`"
[get-spec-fn]
#?(:cljs
{:class-properties {:childContextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:init (fn [s _] (assoc s ::spec (get-spec-fn (:rum/args s))))
:child-context (fn [s] (let [{:keys [release! get!]} (derivatives-pool (::spec s))]
{release-k release! get-k get!}))}))

(defn drv
"Rum mixin to retrieve a derivative for `:drv-k` using the functions in the component context
To get the derived-atom use `get-ref` for swappable client/server behavior"
[drv-k]
#?(:cljs
(let [token (rand-int 10000)] ; TODO think of something better here
{:class-properties {:contextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:will-mount (fn [s]
(let [get-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get get-k))]
(assert get-drv! "No get! derivative function found in component context")
(assoc-in s [::derivatives drv-k] (get-drv! drv-k token))))
:will-unmount (fn [s]
(let [release-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get release-k))]
(assert release-drv! "No release! derivative function found in component context")
(release-drv! drv-k token)
(update s ::derivatives dissoc drv-k)))}))))

(def ^:dynamic *derivatives* nil)

(defn get-ref
"Get the derivative identified by `drv-k` from the component state.
When rendering in Clojure this looks for `drv-k` in the dynvar `*derivatives`"
[state drv-k]
(or #?(:cljs (get-in state [::derivatives drv-k])
:clj (get *derivatives* drv-k))
(throw (ex-info (str "No derivative found! Maybe you forgot a (drv " drv-k ") mixin?")
{:key drv-k :derivatives #?(:cljs (keys (::derivatives state))
:clj (keys *derivatives*))}))))

(defn react
"Like `get-ref` wrapped in `rum.core/react`"
[state drv-k]
(rum/react (get-ref state drv-k)))

(comment
(comment
(def base (atom 0))

(def test-subman (subman (reactive-spec base)))
Expand All @@ -180,7 +119,7 @@
:sum #{:token-c}})

(def g (spec->graph (reactive-spec base)))

;; compute all required dependencies
(def req? (apply s/union (into #{} (keys reg)) (map #(dep/transitive-dependencies g %) (keys reg)) ))

Expand All @@ -189,7 +128,7 @@


(sync-subs (reactive-spec base) {:inc (atom 0)} order)

)

(comment
Expand Down
65 changes: 65 additions & 0 deletions src/org/martinklepsch/derivatives/rum.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
(ns org.martinklepsch.derivatives.rum
(:require [org.martinklepsch.derivatives :as drv]
[rum.core :as rum]
#?(:cljs [goog.object :as gobj])))

;; RUM specific code ===========================================================

(let [get-k "org.martinklepsch.derivatives/get"
release-k "org.martinklepsch.derivatives/release"]

(defn rum-derivatives
"Given the passed spec add get!/release! derivative functions to
the child context so they can be seen by components using the `deriv`
mixin."
[spec]
#?(:cljs
{:class-properties {:childContextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:child-context (fn [_] (let [{:keys [release! get!]} (derivatives-pool spec)]
{release-k release! get-k get!}))}))

(defn rum-derivatives*
"Like rum-derivatives but get the spec from the arguments passed to the components (`:rum/args`) using `get-spec-fn`"
[get-spec-fn]
#?(:cljs
{:class-properties {:childContextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:init (fn [s _] (assoc s ::spec (get-spec-fn (:rum/args s))))
:child-context (fn [s] (let [{:keys [release! get!]} (derivatives-pool (::spec s))]
{release-k release! get-k get!}))}))

(defn drv
"Rum mixin to retrieve a derivative for `:drv-k` using the functions in the component context
To get the derived-atom use `get-ref` for swappable client/server behavior"
[drv-k]
#?(:cljs
(let [token (rand-int 10000)] ; TODO think of something better here
{:class-properties {:contextTypes {get-k js/React.PropTypes.func
release-k js/React.PropTypes.func}}
:will-mount (fn [s]
(let [get-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get get-k))]
(assert get-drv! "No get! derivative function found in component context")
(assoc-in s [::derivatives drv-k] (get-drv! drv-k token))))
:will-unmount (fn [s]
(let [release-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get release-k))]
(assert release-drv! "No release! derivative function found in component context")
(release-drv! drv-k token)
(update s ::derivatives dissoc drv-k)))}))))

(def ^:dynamic *derivatives* nil)

(defn get-ref
"Get the derivative identified by `drv-k` from the component state.
When rendering in Clojure this looks for `drv-k` in the dynvar `*derivatives`"
[state drv-k]
(or #?(:cljs (get-in state [::derivatives drv-k])
:clj (get *derivatives* drv-k))
(throw (ex-info (str "No derivative found! Maybe you forgot a (drv " drv-k ") mixin?")
{:key drv-k :derivatives #?(:cljs (keys (::derivatives state))
:clj (keys *derivatives*))}))))

(defn react
"Like `get-ref` wrapped in `rum.core/react`"
[state drv-k]
(rum/react (get-ref state drv-k)))