Make demo a little prettier

This commit is contained in:
Dan Holmsand 2014-01-07 12:45:08 +01:00
parent 16c50fdf1d
commit 062fb33cb3
6 changed files with 121 additions and 77 deletions

View File

@ -23,11 +23,11 @@ var body = ['<body>',
main,
'<script type="text/javascript" src="site/demo.js"></script>',
'<script type="text/javascript">',
'demo.mountdemo();',
'setTimeout(demo.mountdemo, 200);',
'</script>',
'</body>'].join('\n');
var html = ['<html>', head, body, '</html>'].join('\n');
var html = ['<!doctype html>', '<html>', head, body, '</html>'].join('\n');
console.log('Writing site');
fs.writeFileSync("index.html", html);

View File

@ -1,7 +1,6 @@
(ns simpleexample
(:require [cloact.core :as cloact :refer [atom]]
[clojure.string :as string]))
(:require [cloact.core :as cloact :refer [atom]]))
(def timer (atom (js/Date.)))
(def time-color (atom "#f34"))
@ -15,7 +14,7 @@
(defn clock []
(update-time timer)
(let [time-str (-> @timer .toTimeString (string/split " ") first)]
(let [time-str (-> @timer .toTimeString (clojure.string/split " ") first)]
[:div.example-clock
{:style {:color @time-color}}
time-str]))

View File

@ -21,7 +21,7 @@
(dotimes [x 5] (add-todo (str "Some todo " x)))
(defn todo-input-basic [{:keys [title on-save on-stop]}]
(defn todo-input [{:keys [title on-save on-stop]}]
(let [val (atom title)
stop (fn []
(reset! val "")
@ -39,13 +39,13 @@
27 (stop)
nil)})])))
(def todo-input (with-meta todo-input-basic
{:component-did-mount #(.focus (cloact/dom-node %))}))
(def todo-edit (with-meta todo-input
{:component-did-mount #(.focus (cloact/dom-node %))}))
(defn todo-stats [{:keys [filter active done]}]
(defn todo-stats [{:keys [filt active done]}]
(let [props-for (fn [name]
{:class (when (= name @filter) "selected")
:on-click #(reset! filter name)})]
{:class (when (= name @filt) "selected")
:on-click #(reset! filt name)})]
[:div
[:span#todo-count
[:strong active] " " (case active 1 "item" "items") " left"]
@ -69,9 +69,9 @@
[:label {:on-double-click #(reset! editing true)} title]
[:button.destroy {:on-click #(delete id)}]]
(when @editing
[todo-input {:class "edit" :title title
:on-save #(save id %)
:on-stop #(reset! editing false)}])])))
[todo-edit {:class "edit" :title title
:on-save #(save id %)
:on-stop #(reset! editing false)}])])))
(defn todo-app [props]
(let [filt (atom :all)]
@ -83,21 +83,21 @@
[:section#todoapp
[:header#header
[:h1 "todos"]
[todo-input-basic {:id "new-todo"
:placeholder "What needs to be done?"
:on-save add-todo}]]
[todo-input {:id "new-todo"
:placeholder "What needs to be done?"
:on-save add-todo}]]
[:section#main
[:input#toggle-all {:type "checkbox" :checked (zero? active)
:on-change #(complete-all (pos? active))}]
[:label {:for "toggle-all"} "Mark all as complete"]
[:ul#todo-list
(for [{id :id :as todo} (filter (case @filt
:active (complement :done)
:done :done
:all identity) items)]
[todo-item {:key id :todo todo}])]]
(for [todo (filter (case @filt
:active (complement :done)
:done :done
:all identity) items)]
[todo-item {:key (:id todo) :todo todo}])]]
[:footer#footer
[todo-stats {:active active :done done :filter filt}]]
[todo-stats {:active active :done done :filt filt}]]
[:footer#info
[:p "Double-click to edit a todo"]]]))))

View File

@ -1,12 +1,24 @@
.cloact-demo {
background-color: #fff;
margin: 40px -80px;
margin: 40px -100px;
padding: 40px 60px;
}
.test-output-mini {
text-align: right;
}
.cloact-demo h2 {
margin-top: 48px;
color: #555;
}
.demo-text > p {
font-family: georgia, serif;
font-size: 18px;
line-height: 27px;
color: #444;
}
.demo-example {
@ -19,12 +31,21 @@
}
.demo-example, .demo-source {
margin: 0px -20px;
padding: 20px 20px;
margin: 0px -22px;
padding: 22px 22px;
}
.simple-demo, .simple-demo input {
font-size: 17px;
}
.demo-heading {
margin-top: 0;
color: #999;
font-size: 14px;
}
.demo-example-hide {
float: right;
cursor: pointer;
}

View File

@ -31,16 +31,27 @@
[:pre (-> defs src-for-names demoutil/syntaxify)])
(defn demo-component [{:keys [comp defs src]}]
[:div
(when comp
[:div.demo-example
[:h3.demo-heading "Example"]
[comp]])
[:div.demo-source
[:h3.demo-heading "Source"]
(if src
(demoutil/syntaxify src)
(src-for defs))]])
(let [colored (if src
(demoutil/syntaxify src)
(src-for defs))
showing (atom true)]
(fn []
[:div
(when comp
[:div.demo-example
[:a.demo-example-hide {:on-click (fn [e]
(.preventDefault e)
(swap! showing not))}
(if @showing "hide" "show")]
[:h3.demo-heading "Example "]
(when @showing
(if defs
[:div.simple-demo [comp]]
[comp]))])
(when @showing
[:div.demo-source
[:h3.demo-heading "Source"]
colored])])))
(defn simple-component []
[:div
@ -97,23 +108,24 @@
(cloact/render-component [simple-component]
(.-body js/document)))
(defn calc-bmi [{:keys [height weight bmi] :as params}]
(let [h (/ height 100)]
(if (nil? bmi)
(assoc params :bmi (/ weight (* h h)))
(assoc params :weight (* bmi h h)))))
(defn calc-bmi [params to-calc]
(let [{:keys [height weight bmi]} params
h (/ height 100)]
(case to-calc
:bmi (assoc params :bmi (/ weight (* h h)))
:weight (assoc params :weight (* bmi h h)))))
(def bmi-data (atom (calc-bmi {:height 180 :weight 80})))
(def bmi-data (atom (calc-bmi {:height 180 :weight 80} :bmi)))
(defn set-bmi [key val clear]
(swap! bmi-data #(calc-bmi (assoc % key val clear nil))))
(defn set-bmi [key val]
(swap! bmi-data #(calc-bmi (assoc % key val)
(case key :bmi :weight :bmi))))
(defn slider [{:keys [value min max param clear]}]
(defn slider [{:keys [value min max param]}]
[:div
[:input {:type "range" :min min :max max :value value
:style {:width "100%"}
:on-change #(set-bmi param (-> % .-target .-value)
(or clear :bmi))}]])
:on-change #(set-bmi param (-> % .-target .-value))}]])
(defn bmi-component []
(let [{:keys [weight height bmi]} @bmi-data
@ -133,11 +145,11 @@
[:div
"BMI: " (int bmi) " "
[:span {:style {:color color}} diagnose]
[slider {:value bmi :min 10 :max 50 :param :bmi
:clear :weight}]]]))
[slider {:value bmi :min 10 :max 50 :param :bmi}]]]))
(defn intro []
[:div
[:div.demo-text
[:h2 "Introduction to Cloact"]
[:p [:a {:href "https://github.com/holmsand/cloact"} "Cloact"]
@ -157,9 +169,9 @@
[demo-component {:comp simple-parent
:defs [:simple-parent]}]
[:p "Data is passed to child components using a plain old Clojure
[:p "Data is passed to child components using plain old Clojure
maps. For example, here is a component that shows items in a "
[:code "seq"] "." ]
[:code "seq"] ":" ]
[demo-component {:comp lister-user
:defs [:lister :lister-user]}]
@ -172,7 +184,7 @@
large lists."]])
(defn managing-state []
[:div
[:div.demo-text
[:h2 "Managing state in Cloact"]
[:p "The easiest way to manage state in Cloact is to use Cloact's
@ -207,7 +219,7 @@
:defs [:ns :atom-input :shared-state]}]])
(defn essential-api []
[:div
[:div.demo-text
[:h2 "Essential API"]
[:p "Cloact supports most of React's API, but there is really only
@ -221,7 +233,7 @@
[demo-component {:defs [:ns :simple-component :render-simple]}]])
(defn bmi-demo []
[:div
[:div.demo-text
[:h2 "Putting it all together"]
[:p "Here is a slightly less contrived example: a simple BMI
@ -235,18 +247,18 @@
:bmi-component]}]])
(defn test-results []
[:div
[:div.demo-text
[:h2 "Test results"]
[runtests/test-output]])
(defn complete-simple-demo []
[:div
[:div.demo-text
[:h2 "Another demo"]
[demo-component {:comp simpleexample/simple-example
:src (get-source "simpleexample.cljs")}]])
(defn todomvc-demo []
[:div
[:div.demo-text
[:h2 "Todomvc"]
[demo-component {:comp todomvc/todo-app
:src (get-source "todomvc.cljs")}]])

View File

@ -3,7 +3,25 @@
(def builtins #{"def" "defn" "ns" "atom" "let" "if" "when"
"cond" "merge" "assoc" "swap!" "reset!" "for"
"range" "nil?" "int" "or" "->" "%" "fn"})
"range" "nil?" "int" "or" "->" "->>" "%" "fn" "if-not"
"empty?" "case" "str" "pos?" "zero?" "map" "remove"
"empty" "into" "assoc-in" "dissoc" "get-in" "when-not"
"filter" "vals" "count" "complement" "identity" "dotimes"
"update-in" "sorted-map" "inc" "dec" "false" "true" "not"
"="})
(def styles {:comment {:style {:color "gray"
:font-style "italic"}}
:str-litt {:style {:color "green"}}
:keyw {:style {:color "blue"}}
:builtin {:style {:font-weight "bold"
:color "#687868"}}
:def {:style {:color "#55c"
:font-weight "bold"}}})
(def paren-styles [{:style {:color "#272"}}
{:style {:color "#940"}}
{:style {:color "#44a"}}])
(defn tokenize [src]
(let [ws " \\t\\n"
@ -15,18 +33,20 @@
open-p (str "[" open "]")
close-p (str "[" close "]")
iden-p (str "[^" sep "]+")
any-p (str "[" ws "]+" "|.")
meta-p (str "\\^" iden-p)
any-p (str "[" ws "]+" "|\\^[^" sep "]+|.")
patt (re-pattern (str "("
(string/join ")|(" [comment-p str-p open-p
close-p iden-p any-p])
close-p meta-p iden-p any-p])
")"))
keyw-re #"^:"]
(for [[s comment str-litt open close iden any] (re-seq patt src)]
(for [[s comment str-litt open close met iden any] (re-seq patt src)]
(cond
comment [:comment s]
str-litt [:str-litt s]
open [:open s]
close [:close s]
met [:other s]
iden (cond
(re-find keyw-re s) [:keyw s]
(builtins s) [:builtin s]
@ -35,10 +55,9 @@
(defn syntaxify [src]
(let [def-re #"^def|^ns\b"
parcol ["#9a0" "#c80" "#0a8"]
ncol (count parcol)
ncol (count paren-styles)
paren-style (fn [level]
{:style {:color (nth parcol (mod level ncol))}})]
(nth paren-styles (mod level ncol)))]
(loop [tokens (tokenize src)
prev nil
level 0
@ -49,18 +68,11 @@
:close (dec level)
level)
style (case kind
:comment {:style {:color "gray"
:font-style "italic"}}
:str-litt {:style {:color "green"}}
:keyw {:style {:color "blue"}}
:builtin {:style {:font-weight "bold"
:color "#687868"}}
:iden (when (and prev (re-find def-re prev))
{:style {:color "#55c"
:font-weight "bold"}})
:open (paren-style level)
:close (paren-style level')
nil)
:iden (when (and prev (re-find def-re prev))
(:def styles))
:open (paren-style level)
:close (paren-style level')
(styles kind))
remain (rest tokens)]
(if-not (empty? remain)
(recur remain