Last active
August 29, 2015 14:17
-
-
Save pleasetrythisathome/72ec0a48e4436ea66e2b to your computer and use it in GitHub Desktop.
rum component system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defprotocol IRender | |
(renderer [_]) | |
(render-fn [_ views])) | |
(defprotocol IRumView | |
(display-name [_]) | |
(state? [_]) | |
(mixins [_])) | |
(defn rum-ctor [view] | |
;;(assert (every? #(satisfies? % view) [IRumView IRender]) "view must satisfy IRumView and IRender") | |
(let [render-ctor (if (state? view) | |
rum/render-state->mixin | |
rum/render->mixin) | |
views (->> (for [[k v] view | |
:when (satisfies? IRender v)] | |
[k (rum-ctor v)]) | |
(into {})) | |
render-mixin (render-ctor (render-fn view views)) | |
class (rum/build-class (cons render-mixin | |
(or (mixins view) [])) | |
(or (display-name view) "")) | |
ctor (fn [& args] | |
(let [state (rum/args->state args)] | |
(rum/element class state nil)))] | |
(with-meta ctor {:rum/class class}))) | |
(defrecord RumRoot [target] | |
component/Lifecycle | |
(start [this] | |
(let [view (->> (vals this) | |
(filter #(satisfies? IRumView %)) | |
first)] | |
(assert view "rum root requires a dependency that satisfies IRumView") | |
(rum/mount ((rum-ctor view)) (gdom/getElement target))) | |
this) | |
(stop [this] | |
(js/React.unmountComponentAtNode target) | |
this)) | |
(def new-rum-root | |
(validated-ctr | |
{:map->cmp map->RumRoot | |
:opts {:target s/Str}})) | |
(defrecord Clicker [config] | |
IRumView | |
(display-name [_] "clicker") | |
(state? [_] true) | |
(mixins [_] [(rum/local 0 :count)]) | |
IRender | |
(renderer [_] rum-ctor) | |
(render-fn [_ views] | |
(fn [state] | |
(html | |
[:button | |
{:on-click #(swap! (:count state) + (:click-step config))} | |
(str "Count " @(:count state))])))) | |
(defrecord AppView [header clicker] | |
IRumView | |
(display-name [_] "app-view") | |
(state? [_] false) | |
(mixins [_] []) | |
IRender | |
(renderer [_] rum-ctor) | |
(render-fn [_ {:keys [clicker]}] | |
(fn [] | |
(html | |
[:div | |
header | |
(clicker)])))) | |
(def system | |
(component/system-map | |
:config {:data "this is some data in a system" | |
:click-step 5} | |
:clicker (-> (map->Clicker {}) | |
(component/using [:config])) | |
:app (-> (map->AppView {:header "Hello Rum Components!"}) | |
(component/using [:clicker :config])) | |
:rum-root (-> (new-rum-root | |
:target "root") | |
(component/using [:app])))) | |
(component/start system) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment