Skip to content

Instantly share code, notes, and snippets.

@pleasetrythisathome
Last active August 29, 2015 14:17
Show Gist options
  • Save pleasetrythisathome/72ec0a48e4436ea66e2b to your computer and use it in GitHub Desktop.
Save pleasetrythisathome/72ec0a48e4436ea66e2b to your computer and use it in GitHub Desktop.
rum component system
(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