Skip to content

Instantly share code, notes, and snippets.

@adz5a
Last active September 21, 2019 14:35
Show Gist options
  • Save adz5a/332e02d00898a2c85451ade9cc95a97b to your computer and use it in GitHub Desktop.
Save adz5a/332e02d00898a2c85451ade9cc95a97b to your computer and use it in GitHub Desktop.
(s/def ::element
(s/cat :type (s/or :htmltag keyword?
:component symbol?)
:props (s/? (s/map-of keyword? any?))
:children (s/* (s/or :text-node string?
:element ::element))))
(s/def ::component
(s/cat :name symbol?
:props-signature (s/spec (s/cat :props any?))
:body any?))
(defn create-element [{:keys [type children props]}]
`(react/createElement
~(case (key type)
:htmltag (-> type val name)
:component (-> type val))
~(when props
(let [process-keys '(fn [[k v]]
(case k
:style [:style (clj->js v)]
[k v]))]
`(cljs-bean.core/object
(into (cljs-bean.core/bean)
(map ~process-keys ~props)))))
~@(when children
(map
(fn [node]
(case (key node)
:text-node (val node)
:element (-> node val create-element)))
children))))
(defmacro jsx [react-tree]
(let [ast (s/conform ::element react-tree)]
(create-element ast)))
(defmacro defcomponent [& args]
(let [{:keys [name props body]} (s/conform ::component args)]
(list 'defn
name
['props]
(list 'let ['props '(cljs-bean.core/bean props)]
body))))
(defcomponent Form [props]
(let [[state setState] (react/useState (-> props :input :default))]
(jsx
[:input
{:placeholder "hello world"
:value state
:onChange #(setState (-> % .-target .-value))}])))
(defn app []
(println "whesh")
(jsx
[:div {:style {:background-color "red"}} "hello"
[:p "world"]
[Form {:input {:default "mdr"}}]]))
(react-dom/render
(jsx
[app])
app-root)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment