├── Procfile ├── .gitignore ├── README.md ├── src ├── clj │ └── cljs_react_material_ui_example │ │ ├── util.clj │ │ ├── website.clj │ │ ├── core.clj │ │ └── system.clj └── cljs │ └── cljs_react_material_ui_example │ ├── util.cljs │ ├── parser.cljs │ ├── state.cljs │ └── core.cljs ├── env ├── prod │ └── clj │ │ └── cljs_react_material_ui_example │ │ └── prod_server.clj └── dev │ └── clj │ └── cljs_react_material_ui_example │ ├── dev_server.clj │ └── figwheel.clj ├── resources └── public │ ├── html │ └── index.html │ └── css │ └── style.css ├── project.clj ├── LICENSE └── cljs-react-material-ui-example.iml /Procfile: -------------------------------------------------------------------------------- 1 | web: java $JVM_OPTS -cp target/cljs-react-material-ui-example.jar clojure.main -m cljs-react-material-ui-example.prod-server -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /cljs-react-material-ui-example.iml 10 | /.nrepl-port 11 | .hgignore 12 | .hg/ 13 | /resources/public/js 14 | .idea 15 | /figwheel_server.log 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Material-UI Om.Next example app 2 | 3 | http://cljs-react-material-ui-example.herokuapp.com/ 4 | 5 | This is example app, which uses my library [cljs-react-material-ui](https://github.com/madvas/cljs-react-material-ui) to get [Material-UI](http://www.material-ui.com/) working in Clojurescript. 6 | 7 | `lein run` 8 | 9 | Head on to http://localhost:8081/ to see the running application. 10 | 11 | -------------------------------------------------------------------------------- /src/clj/cljs_react_material_ui_example/util.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.util 2 | (:require [clojure.pprint :refer [pprint]])) 3 | 4 | (defn p [& args] 5 | "Like print, but returns last arg. For debugging purposes" 6 | (doseq [a args] 7 | (let [f (if (map? a) pprint print)] 8 | (f a))) 9 | (println) 10 | (flush) 11 | (last args)) 12 | 13 | (defn str->int [s] 14 | (if (number? s) 15 | s 16 | (Integer/parseInt (re-find #"\A-?\d+" s)))) -------------------------------------------------------------------------------- /env/prod/clj/cljs_react_material_ui_example/prod_server.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.prod-server 2 | (:require [cljs-react-material-ui-example.core :as app]) 3 | (:gen-class)) 4 | 5 | (def config 6 | {:web-port (or (System/getenv "PORT") 8082)}) 7 | 8 | (defn -main [& args] 9 | (println "Starting on port " (:web-port config)) 10 | (app/dev-start config) 11 | (println (str "Started server on port " (:web-port config))) 12 | (.addShutdownHook (Runtime/getRuntime) 13 | (Thread. #(do (app/stop) 14 | (println "Server stopped"))))) -------------------------------------------------------------------------------- /env/dev/clj/cljs_react_material_ui_example/dev_server.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.dev-server 2 | (:require [cljs-react-material-ui-example.core :as cljs-react-material-ui-example] 3 | [cljs-react-material-ui-example.figwheel :as f])) 4 | 5 | 6 | (def config 7 | {:web-port 8999}) 8 | 9 | (cljs-react-material-ui-example/dev-start config) 10 | (println (str "Started server on port " (:web-port config))) 11 | (.addShutdownHook (Runtime/getRuntime) 12 | (Thread. #(do (cljs-react-material-ui-example/stop) 13 | (println "Server stopped")))) 14 | (f/start-fig!) -------------------------------------------------------------------------------- /src/clj/cljs_react_material_ui_example/website.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.website 2 | (:require [com.stuartsierra.component :as c] 3 | [bidi.bidi :as b] 4 | [clojure.java.io :as io] 5 | [yada.yada :refer [yada]] 6 | [yada.resources.classpath-resource :as yr])) 7 | 8 | (defrecord Website [] 9 | c/Lifecycle 10 | (start [component] 11 | component) 12 | (stop [component] 13 | component) 14 | 15 | b/RouteProvider 16 | (routes [component] 17 | ["/" [["" (yada (io/resource "public/html/index.html"))] 18 | ["" (yada (yr/new-classpath-resource "public/"))]]])) 19 | 20 | (defn new-website [] 21 | (-> (map->Website {}))) -------------------------------------------------------------------------------- /src/clj/cljs_react_material_ui_example/core.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.core 2 | (:require [com.stuartsierra.component :as component] 3 | [cljs-react-material-ui-example.system :as system])) 4 | 5 | (def servlet-system (atom nil)) 6 | 7 | ;; ============================================================================= 8 | ;; Development 9 | 10 | (defn dev-start [config] 11 | (let [sys (system/dev-system config) 12 | sys' (component/start sys)] 13 | (reset! servlet-system sys') 14 | (println "System started") 15 | sys')) 16 | 17 | (defn stop [] 18 | (swap! servlet-system component/stop) 19 | (println "System stopped")) 20 | 21 | (defn dev-restart [config] 22 | (stop) 23 | (dev-start config)) 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /resources/public/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Material UI Om.Next Example App 7 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /env/dev/clj/cljs_react_material_ui_example/figwheel.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.figwheel 2 | (:require [figwheel-sidecar.repl-api :as ra] 3 | [cljs.build.api :as b])) 4 | 5 | 6 | (def opts 7 | {:main 'cljs-react-material-ui-example.core 8 | :asset-path "/js" 9 | :output-to "resources/public/js/app.js" 10 | :output-dir "resources/public/js" 11 | :parallel-build true 12 | :compiler-stats true 13 | :verbose true}) 14 | 15 | (comment 16 | (b/build "src/cljs" opts)) 17 | 18 | (defn build [] 19 | (b/build "src/cljs" opts)) 20 | 21 | 22 | (defn start-fig! [] 23 | (ra/start-figwheel! 24 | {:figwheel-options {:server-port 5309} 25 | :build-ids ["dev"] 26 | :all-builds [{:id "dev" 27 | :figwheel true 28 | :source-paths ["src/cljs"] 29 | :compiler opts}]})) 30 | 31 | (ra/cljs-repl) 32 | -------------------------------------------------------------------------------- /src/cljs/cljs_react_material_ui_example/util.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.util 2 | (:require [cognitect.transit :as t] 3 | [cljs.pprint :refer [pprint]] 4 | [goog.events.KeyCodes :as kc])) 5 | 6 | 7 | (defn p [& args] 8 | "Like print, but returns last arg. For debugging purposes" 9 | (doseq [a args] 10 | (let [f (if (map? a) pprint print)] 11 | (f a))) 12 | (println) 13 | (flush) 14 | (last args)) 15 | 16 | (defn pcoll [items] 17 | (doall (map p items))) 18 | 19 | (defn prevent-default [e] 20 | (doto e (.preventDefault) (.stopPropagation))) 21 | 22 | (defn target-val [e] 23 | (.. e -target -value)) 24 | 25 | (defn on-key-down [key-fns] 26 | (fn [e] 27 | (let [f (condp == (aget e "keyCode") 28 | kc/ESC (:key/esc key-fns) 29 | kc/ENTER (:key/enter key-fns) 30 | #(do %))] 31 | (f e)))) 32 | 33 | (defn event-data [e] 34 | (aget (.-event_ e) "data")) 35 | 36 | (defn apply-if [pred f x & args] 37 | (if-not (pred x) 38 | (apply f x args) 39 | x)) 40 | 41 | (defn find-by-key [k v coll] 42 | (first (filter #(= v (get % k)) coll))) -------------------------------------------------------------------------------- /src/cljs/cljs_react_material_ui_example/parser.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.parser 2 | (:require [om.next :as om] 3 | [cljs-react-material-ui-example.state :refer [init-state]])) 4 | 5 | ;; ============================================================================= 6 | ;; Reads 7 | 8 | (defmulti read om/dispatch) 9 | 10 | (defmethod read :default 11 | [{:keys [state query]} k _] 12 | #_(println "Default read " k query) 13 | (let [st @state] 14 | {:remote false 15 | :value (om/db->tree query (k st) st)})) 16 | 17 | (defmethod read :person/new 18 | [{:keys [state]} k _] 19 | {:value (k @state)}) 20 | 21 | (defmulti mutate om/dispatch) 22 | 23 | (defmethod mutate :default 24 | [_ k _] 25 | (println "Default mutate " k) 26 | {:remote false}) 27 | 28 | (defmethod mutate 'person-new/change 29 | [{:keys [state]} _ {:keys [value path]}] 30 | {:action (fn [] 31 | (swap! state assoc-in (cons :person/new path) value))}) 32 | 33 | 34 | (defmethod mutate 'person-new/add 35 | [{:keys [state]} _] 36 | {:action (fn [] 37 | (let [id (rand-int 9999) 38 | person-new (-> (:person/new @state) 39 | (assoc :db/id id))] 40 | (swap! state assoc-in [:person/by-id id] person-new) 41 | (swap! state update :person/list conj [:person/by-id id]) 42 | (swap! state assoc :person/new (:person/new init-state))))}) 43 | -------------------------------------------------------------------------------- /src/clj/cljs_react_material_ui_example/system.clj: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.system 2 | (:require [com.stuartsierra.component :as c] 3 | cljs-react-material-ui-example.website 4 | [modular.maker :as mm] 5 | [modular.bidi :refer [new-router new-web-resources]] 6 | [modular.aleph :refer [new-webserver]] 7 | [cljs-react-material-ui-example.util :as u])) 8 | 9 | (defn http-listener-components [system config] 10 | (assoc system :http-listener (new-webserver :port (u/str->int (:web-port config))))) 11 | 12 | (defn modular-bidi-router-components [system config] 13 | (assoc system :bidi-request-handler (mm/make new-router config))) 14 | 15 | (defn website-components [system config] 16 | (assoc system :website 17 | (-> (mm/make cljs-react-material-ui-example.website/new-website config) 18 | (c/using [])))) 19 | 20 | (defn new-dependency-map [] 21 | {:http-listener {:request-handler :bidi-request-handler} 22 | :bidi-request-handler {:website :website}}) 23 | 24 | (defn new-system-map 25 | [config] 26 | (apply c/system-map 27 | (apply concat 28 | (-> {} 29 | (http-listener-components config) 30 | (modular-bidi-router-components config) 31 | (website-components config))))) 32 | 33 | (defn dev-system 34 | ([] (dev-system {})) 35 | ([config] 36 | (-> (new-system-map config) 37 | (c/system-using (new-dependency-map))))) 38 | -------------------------------------------------------------------------------- /src/cljs/cljs_react_material_ui_example/state.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.state) 2 | 3 | (defonce init-state 4 | {:person/list [[:person/by-id 1] 5 | [:person/by-id 2]] 6 | :person/by-id {1 {:db/id 1 7 | :person/name "John" 8 | :person/date #inst "2016-04-08T22:00:00.000-00:00" 9 | :person/status [:status/by-id 1] 10 | :person/happiness [:happiness/by-id 3]} 11 | 2 {:db/id 2 12 | :person/name "Susan" 13 | :person/date #inst "2016-04-08T22:00:00.000-00:00" 14 | :person/status [:status/by-id 4] 15 | :person/happiness [:happiness/by-id 2]}} 16 | :person/new {:person/name "" 17 | :person/date nil 18 | :person/status nil 19 | :person/happiness [:happiness/by-id 2]} 20 | :status/list [[:status/by-id 1] [:status/by-id 2] [:status/by-id 3] [:status/by-id 4] 21 | [:status/by-id 5]] 22 | :status/by-id {1 {:db/id 1 :status/name "Employed"} 23 | 2 {:db/id 2 :status/name "Unemployed"} 24 | 3 {:db/id 3 :status/name "Freelancer"} 25 | 4 {:db/id 4 :status/name "Entrepreneur"} 26 | 5 {:db/id 5 :status/name "Parental leave"}} 27 | :happiness/list [[:happiness/by-id 1] [:happiness/by-id 2] [:happiness/by-id 3]] 28 | :happiness/by-id {1 {:db/id 1 :happiness/name "Sad"} 29 | 2 {:db/id 2 :happiness/name "Normal"} 30 | 3 {:db/id 3 :happiness/name "Superb"}}}) -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject cljs-react-material-ui-example "0.1.0-SNAPSHOT" 2 | :description "Example app for library cljs-react-material-ui" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.8.0"] 7 | [org.clojure/clojurescript "1.9.908"] 8 | [org.omcljs/om "1.0.0-alpha37"] 9 | [com.stuartsierra/component "0.3.1"] 10 | [com.cemerick/piggieback "0.2.1"] 11 | [cljsjs/react "15.6.1-1"] 12 | [cljsjs/react-dom "15.6.1-1"] 13 | [figwheel-sidecar "0.5.0-2" :scope "test"] 14 | [com.cemerick/piggieback "0.2.1"] 15 | [org.clojure/tools.nrepl "0.2.10"] 16 | [aleph "0.4.1-beta5"] 17 | [bidi "2.0.4"] 18 | [yada "1.1.5"] 19 | [juxt.modular/bidi "0.9.5"] 20 | [juxt.modular/maker "0.5.0"] 21 | [juxt.modular/wire-up "0.5.0"] 22 | [juxt.modular/aleph "0.1.4"] 23 | [com.andrewmcveigh/cljs-time "0.4.0"] 24 | [cljs-react-material-ui "0.2.50"] 25 | [cljsjs/material-ui-chip-input "0.17.2-0"] 26 | [prismatic/schema "1.1.1"] 27 | [print-foo-cljs "2.0.0"]] 28 | 29 | :plugins [[lein-cljsbuild "1.1.3"]] 30 | :min-lein-version "2.0.0" 31 | :uberjar-name "cljs-react-material-ui-example.jar" 32 | :clean-targets ^{:protect false} ["resources/public/js"] 33 | :source-paths ["src/clj" "src/cljs"] 34 | 35 | :cljsbuild {:builds {:app {:source-paths ["src/cljs"] 36 | :figwheel true 37 | :compiler {:main cljs-react-material-ui-example.core 38 | :output-to "resources/public/js/app.js" 39 | :output-dir "resources/public/js" 40 | :asset-path "/js" 41 | :optimizations :none 42 | :pretty-print true 43 | :externs ["src/js/externs.js"] 44 | :closure-defines {goog.DEBUG false} 45 | :parallel-build true 46 | :verbose true}}}} 47 | 48 | :profiles {:dev {:source-paths ["env/dev/clj"] 49 | :main cljs-react-material-ui-example.dev-server 50 | :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]} 51 | :plugins [[lein-figwheel "0.5.1"]]} 52 | :uberjar {:source-paths ["env/prod/clj"] 53 | :main cljs-react-material-ui-example.prod-server 54 | :hooks [leiningen.cljsbuild] 55 | :aot :all 56 | :omit-source true 57 | :cljsbuild {:builds {:app 58 | {:compiler {:optimizations :advanced 59 | :closure-defines {:goog.DEBUG false} 60 | :pretty-print false}}}}}}) -------------------------------------------------------------------------------- /resources/public/css/style.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | html, 6 | body, 7 | div, 8 | span, 9 | applet, 10 | object, 11 | iframe, 12 | h1, 13 | h2, 14 | h3, 15 | h4, 16 | h5, 17 | h6, 18 | p, 19 | blockquote, 20 | pre, 21 | a, 22 | abbr, 23 | acronym, 24 | address, 25 | big, 26 | cite, 27 | code, 28 | del, 29 | dfn, 30 | em, 31 | img, 32 | ins, 33 | kbd, 34 | q, 35 | s, 36 | samp, 37 | small, 38 | strike, 39 | strong, 40 | sub, 41 | sup, 42 | tt, 43 | var, 44 | b, 45 | u, 46 | i, 47 | center, 48 | dl, 49 | dt, 50 | dd, 51 | ol, 52 | ul, 53 | li, 54 | fieldset, 55 | form, 56 | label, 57 | legend, 58 | table, 59 | caption, 60 | tbody, 61 | tfoot, 62 | thead, 63 | tr, 64 | th, 65 | td, 66 | article, 67 | aside, 68 | canvas, 69 | details, 70 | embed, 71 | figure, 72 | figcaption, 73 | footer, 74 | header, 75 | hgroup, 76 | menu, 77 | nav, 78 | output, 79 | ruby, 80 | section, 81 | summary, 82 | time, 83 | mark, 84 | audio, 85 | video { 86 | margin: 0; 87 | padding: 0; 88 | border: 0; 89 | font-size: 100%; 90 | font: inherit; 91 | } 92 | /* HTML5 display-role reset for older browsers */ 93 | article, 94 | aside, 95 | details, 96 | figcaption, 97 | figure, 98 | footer, 99 | header, 100 | hgroup, 101 | menu, 102 | nav, 103 | section { 104 | display: block; 105 | } 106 | ol, 107 | ul { 108 | list-style: none; 109 | } 110 | blockquote, 111 | q { 112 | quotes: none; 113 | } 114 | blockquote:before, 115 | blockquote:after, 116 | q:before, 117 | q:after { 118 | content: ''; 119 | content: none; 120 | } 121 | table { 122 | border-collapse: collapse; 123 | border-spacing: 0; 124 | } 125 | button::-moz-focus-inner, 126 | input::-moz-focus-inner { 127 | border: 0; 128 | padding: 0; 129 | } 130 | 131 | .pad-top-20 { 132 | padding-top: 20px; 133 | } 134 | .pad-lef-20 { 135 | padding-left: 20px; 136 | } 137 | .pad-rig-20 { 138 | padding-right: 20px; 139 | } 140 | .pad-bot-20 { 141 | padding-bottom: 20px; 142 | } 143 | .pad-top-15 { 144 | padding-top: 15px; 145 | } 146 | .pad-lef-15 { 147 | padding-left: 15px; 148 | } 149 | .pad-rig-15 { 150 | padding-right: 15px; 151 | } 152 | .pad-bot-15 { 153 | padding-bottom: 15px; 154 | } 155 | .pad-top-10 { 156 | padding-top: 10px; 157 | } 158 | .pad-lef-10 { 159 | padding-left: 10px; 160 | } 161 | .pad-rig-10 { 162 | padding-right: 10px; 163 | } 164 | .pad-bot-10 { 165 | padding-bottom: 10px; 166 | } 167 | .pad-top-5 { 168 | padding-top: 5px; 169 | } 170 | .pad-lef-5 { 171 | padding-left: 5px; 172 | } 173 | .pad-rig-5 { 174 | padding-right: 5px; 175 | } 176 | .pad-bot-5 { 177 | padding-bottom: 5px; 178 | } 179 | .pad-top-0 { 180 | padding-top: 0; 181 | } 182 | .pad-lef-0 { 183 | padding-left: 0; 184 | } 185 | .pad-rig-0 { 186 | padding-right: 0; 187 | } 188 | .pad-bot-0 { 189 | padding-bottom: 0; 190 | } 191 | .pad-ver-0 { 192 | padding-top: 0; 193 | padding-bottom: 0; 194 | } 195 | .pad-ver-5 { 196 | padding-top: 5px; 197 | padding-bottom: 5px; 198 | } 199 | .pad-ver-10 { 200 | padding-top: 10px; 201 | padding-bottom: 10px; 202 | } 203 | .pad-ver-15 { 204 | padding-top: 15px; 205 | padding-bottom: 15px; 206 | } 207 | .pad-ver-20 { 208 | padding-top: 20px; 209 | padding-bottom: 20px; 210 | } 211 | .pad-hor-0 { 212 | padding-left: 0; 213 | padding-right: 0; 214 | } 215 | .pad-hor-5 { 216 | padding-left: 5px; 217 | padding-right: 5px; 218 | } 219 | .pad-hor-10 { 220 | padding-left: 10px; 221 | padding-right: 10px; 222 | } 223 | .pad-hor-15 { 224 | padding-left: 15px; 225 | padding-right: 15px; 226 | } 227 | .pad-hor-20 { 228 | padding-left: 20px; 229 | padding-right: 20px; 230 | } 231 | .pad-0 { 232 | padding: 0px !important; 233 | } 234 | .pad-5 { 235 | padding: 5px; 236 | } 237 | .pad-10 { 238 | padding: 10px; 239 | } 240 | .pad-15 { 241 | padding: 15px; 242 | } 243 | .pad-20 { 244 | padding: 20px; 245 | } 246 | .pad-top-30 { 247 | padding-top: 30px; 248 | } 249 | .pad-top-40 { 250 | padding-top: 40px; 251 | } 252 | .mar-top-30 { 253 | margin-top: 30px; 254 | } 255 | .mar-top-40 { 256 | margin-top: 40px; 257 | } 258 | .mar-top-20 { 259 | margin-top: 20px; 260 | } 261 | .mar-lef-20 { 262 | margin-left: 20px; 263 | } 264 | .mar-rig-20 { 265 | margin-right: 20px; 266 | } 267 | .mar-bot-20 { 268 | margin-bottom: 20px; 269 | } 270 | .mar-top-15 { 271 | margin-top: 15px; 272 | } 273 | .mar-lef-15 { 274 | margin-left: 15px; 275 | } 276 | .mar-rig-15 { 277 | margin-right: 15px; 278 | } 279 | .mar-bot-15 { 280 | margin-bottom: 15px; 281 | } 282 | .mar-top-10 { 283 | margin-top: 10px; 284 | } 285 | .mar-lef-10 { 286 | margin-left: 10px; 287 | } 288 | .mar-rig-10 { 289 | margin-right: 10px; 290 | } 291 | .mar-bot-10 { 292 | margin-bottom: 10px; 293 | } 294 | .mar-top-5 { 295 | margin-top: 5px; 296 | } 297 | .mar-lef-5 { 298 | margin-left: 5px; 299 | } 300 | .mar-rig-5 { 301 | margin-right: 5px; 302 | } 303 | .mar-bot-5 { 304 | margin-bottom: 5px; 305 | } 306 | .mar-top-0 { 307 | margin-top: 0; 308 | } 309 | .mar-lef-0 { 310 | margin-left: 0; 311 | } 312 | .mar-rig-0 { 313 | margin-right: 0; 314 | } 315 | .mar-bot-0 { 316 | margin-bottom: 0; 317 | } 318 | .mar-ver-0 { 319 | margin-top: 0; 320 | margin-bottom: 0; 321 | } 322 | .mar-ver-5 { 323 | margin-top: 5px; 324 | margin-bottom: 5px; 325 | } 326 | .mar-ver-10 { 327 | margin-top: 10px; 328 | margin-bottom: 10px; 329 | } 330 | .mar-ver-15 { 331 | margin-top: 15px; 332 | margin-bottom: 15px; 333 | } 334 | .mar-ver-20 { 335 | margin-top: 20px; 336 | margin-bottom: 20px; 337 | } 338 | .mar-hor-0 { 339 | margin-left: 0; 340 | margin-right: 0; 341 | } 342 | .mar-hor-5 { 343 | margin-left: 5px; 344 | margin-right: 5px; 345 | } 346 | .mar-hor-10 { 347 | margin-left: 10px; 348 | margin-right: 10px; 349 | } 350 | .mar-hor-15 { 351 | margin-left: 15px; 352 | margin-right: 15px; 353 | } 354 | .mar-hor-20 { 355 | margin-left: 20px; 356 | margin-right: 20px; 357 | } 358 | .mar-0 { 359 | margin: 0px !important; 360 | } 361 | .mar-5 { 362 | margin: 5px; 363 | } 364 | .mar-10 { 365 | margin: 10px; 366 | } 367 | .mar-15 { 368 | margin: 15px; 369 | } 370 | .mar-20 { 371 | margin: 20px; 372 | } 373 | 374 | .w-100 { 375 | width: 100% !important; 376 | } 377 | 378 | .h-100 { 379 | height: 100%; 380 | } 381 | 382 | #app { 383 | background-color: #f5f5f5; 384 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 4 | 5 | 1. DEFINITIONS 6 | 7 | "Contribution" means: 8 | 9 | a) in the case of the initial Contributor, the initial code and 10 | documentation distributed under this Agreement, and 11 | 12 | b) in the case of each subsequent Contributor: 13 | 14 | i) changes to the Program, and 15 | 16 | ii) additions to the Program; 17 | 18 | where such changes and/or additions to the Program originate from and are 19 | distributed by that particular Contributor. A Contribution 'originates' from 20 | a Contributor if it was added to the Program by such Contributor itself or 21 | anyone acting on such Contributor's behalf. Contributions do not include 22 | additions to the Program which: (i) are separate modules of software 23 | distributed in conjunction with the Program under their own license 24 | agreement, and (ii) are not derivative works of the Program. 25 | 26 | "Contributor" means any person or entity that distributes the Program. 27 | 28 | "Licensed Patents" mean patent claims licensable by a Contributor which are 29 | necessarily infringed by the use or sale of its Contribution alone or when 30 | combined with the Program. 31 | 32 | "Program" means the Contributions distributed in accordance with this 33 | Agreement. 34 | 35 | "Recipient" means anyone who receives the Program under this Agreement, 36 | including all Contributors. 37 | 38 | 2. GRANT OF RIGHTS 39 | 40 | a) Subject to the terms of this Agreement, each Contributor hereby grants 41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 42 | reproduce, prepare derivative works of, publicly display, publicly perform, 43 | distribute and sublicense the Contribution of such Contributor, if any, and 44 | such derivative works, in source code and object code form. 45 | 46 | b) Subject to the terms of this Agreement, each Contributor hereby grants 47 | Recipient a non-exclusive, worldwide, royalty-free patent license under 48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 49 | transfer the Contribution of such Contributor, if any, in source code and 50 | object code form. This patent license shall apply to the combination of the 51 | Contribution and the Program if, at the time the Contribution is added by the 52 | Contributor, such addition of the Contribution causes such combination to be 53 | covered by the Licensed Patents. The patent license shall not apply to any 54 | other combinations which include the Contribution. No hardware per se is 55 | licensed hereunder. 56 | 57 | c) Recipient understands that although each Contributor grants the licenses 58 | to its Contributions set forth herein, no assurances are provided by any 59 | Contributor that the Program does not infringe the patent or other 60 | intellectual property rights of any other entity. Each Contributor disclaims 61 | any liability to Recipient for claims brought by any other entity based on 62 | infringement of intellectual property rights or otherwise. As a condition to 63 | exercising the rights and licenses granted hereunder, each Recipient hereby 64 | assumes sole responsibility to secure any other intellectual property rights 65 | needed, if any. For example, if a third party patent license is required to 66 | allow Recipient to distribute the Program, it is Recipient's responsibility 67 | to acquire that license before distributing the Program. 68 | 69 | d) Each Contributor represents that to its knowledge it has sufficient 70 | copyright rights in its Contribution, if any, to grant the copyright license 71 | set forth in this Agreement. 72 | 73 | 3. REQUIREMENTS 74 | 75 | A Contributor may choose to distribute the Program in object code form under 76 | its own license agreement, provided that: 77 | 78 | a) it complies with the terms and conditions of this Agreement; and 79 | 80 | b) its license agreement: 81 | 82 | i) effectively disclaims on behalf of all Contributors all warranties and 83 | conditions, express and implied, including warranties or conditions of title 84 | and non-infringement, and implied warranties or conditions of merchantability 85 | and fitness for a particular purpose; 86 | 87 | ii) effectively excludes on behalf of all Contributors all liability for 88 | damages, including direct, indirect, special, incidental and consequential 89 | damages, such as lost profits; 90 | 91 | iii) states that any provisions which differ from this Agreement are offered 92 | by that Contributor alone and not by any other party; and 93 | 94 | iv) states that source code for the Program is available from such 95 | Contributor, and informs licensees how to obtain it in a reasonable manner on 96 | or through a medium customarily used for software exchange. 97 | 98 | When the Program is made available in source code form: 99 | 100 | a) it must be made available under this Agreement; and 101 | 102 | b) a copy of this Agreement must be included with each copy of the Program. 103 | 104 | Contributors may not remove or alter any copyright notices contained within 105 | the Program. 106 | 107 | Each Contributor must identify itself as the originator of its Contribution, 108 | if any, in a manner that reasonably allows subsequent Recipients to identify 109 | the originator of the Contribution. 110 | 111 | 4. COMMERCIAL DISTRIBUTION 112 | 113 | Commercial distributors of software may accept certain responsibilities with 114 | respect to end users, business partners and the like. While this license is 115 | intended to facilitate the commercial use of the Program, the Contributor who 116 | includes the Program in a commercial product offering should do so in a 117 | manner which does not create potential liability for other Contributors. 118 | Therefore, if a Contributor includes the Program in a commercial product 119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend 120 | and indemnify every other Contributor ("Indemnified Contributor") against any 121 | losses, damages and costs (collectively "Losses") arising from claims, 122 | lawsuits and other legal actions brought by a third party against the 123 | Indemnified Contributor to the extent caused by the acts or omissions of such 124 | Commercial Contributor in connection with its distribution of the Program in 125 | a commercial product offering. The obligations in this section do not apply 126 | to any claims or Losses relating to any actual or alleged intellectual 127 | property infringement. In order to qualify, an Indemnified Contributor must: 128 | a) promptly notify the Commercial Contributor in writing of such claim, and 129 | b) allow the Commercial Contributor tocontrol, and cooperate with the 130 | Commercial Contributor in, the defense and any related settlement 131 | negotiations. The Indemnified Contributor may participate in any such claim 132 | at its own expense. 133 | 134 | For example, a Contributor might include the Program in a commercial product 135 | offering, Product X. That Contributor is then a Commercial Contributor. If 136 | that Commercial Contributor then makes performance claims, or offers 137 | warranties related to Product X, those performance claims and warranties are 138 | such Commercial Contributor's responsibility alone. Under this section, the 139 | Commercial Contributor would have to defend claims against the other 140 | Contributors related to those performance claims and warranties, and if a 141 | court requires any other Contributor to pay any damages as a result, the 142 | Commercial Contributor must pay those damages. 143 | 144 | 5. NO WARRANTY 145 | 146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON 147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the 151 | appropriateness of using and distributing the Program and assumes all risks 152 | associated with its exercise of rights under this Agreement , including but 153 | not limited to the risks and costs of program errors, compliance with 154 | applicable laws, damage to or loss of data, programs or equipment, and 155 | unavailability or interruption of operations. 156 | 157 | 6. DISCLAIMER OF LIABILITY 158 | 159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 166 | OF SUCH DAMAGES. 167 | 168 | 7. GENERAL 169 | 170 | If any provision of this Agreement is invalid or unenforceable under 171 | applicable law, it shall not affect the validity or enforceability of the 172 | remainder of the terms of this Agreement, and without further action by the 173 | parties hereto, such provision shall be reformed to the minimum extent 174 | necessary to make such provision valid and enforceable. 175 | 176 | If Recipient institutes patent litigation against any entity (including a 177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 178 | (excluding combinations of the Program with other software or hardware) 179 | infringes such Recipient's patent(s), then such Recipient's rights granted 180 | under Section 2(b) shall terminate as of the date such litigation is filed. 181 | 182 | All Recipient's rights under this Agreement shall terminate if it fails to 183 | comply with any of the material terms or conditions of this Agreement and 184 | does not cure such failure in a reasonable period of time after becoming 185 | aware of such noncompliance. If all Recipient's rights under this Agreement 186 | terminate, Recipient agrees to cease use and distribution of the Program as 187 | soon as reasonably practicable. However, Recipient's obligations under this 188 | Agreement and any licenses granted by Recipient relating to the Program shall 189 | continue and survive. 190 | 191 | Everyone is permitted to copy and distribute copies of this Agreement, but in 192 | order to avoid inconsistency the Agreement is copyrighted and may only be 193 | modified in the following manner. The Agreement Steward reserves the right to 194 | publish new versions (including revisions) of this Agreement from time to 195 | time. No one other than the Agreement Steward has the right to modify this 196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 197 | Eclipse Foundation may assign the responsibility to serve as the Agreement 198 | Steward to a suitable separate entity. Each new version of the Agreement will 199 | be given a distinguishing version number. The Program (including 200 | Contributions) may always be distributed subject to the version of the 201 | Agreement under which it was received. In addition, after a new version of 202 | the Agreement is published, Contributor may elect to distribute the Program 203 | (including its Contributions) under the new version. Except as expressly 204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 205 | licenses to the intellectual property of any Contributor under this 206 | Agreement, whether expressly, by implication, estoppel or otherwise. All 207 | rights in the Program not expressly granted under this Agreement are 208 | reserved. 209 | 210 | This Agreement is governed by the laws of the State of New York and the 211 | intellectual property laws of the United States of America. No party to this 212 | Agreement will bring a legal action under this Agreement more than one year 213 | after the cause of action arose. Each party waives its rights to a jury trial 214 | in any resulting litigation. 215 | -------------------------------------------------------------------------------- /cljs-react-material-ui-example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/cljs/cljs_react_material_ui_example/core.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs-react-material-ui-example.core 2 | (:require 3 | [cljsjs.material-ui] 4 | [cljs-react-material-ui.core :as ui] 5 | [cljs-react-material-ui.icons :as ic] 6 | [goog.dom :as gdom] 7 | [om.next :as om :refer-macros [defui]] 8 | [cljs-react-material-ui-example.parser :as p] 9 | [cljs-react-material-ui-example.util :as u] 10 | [cljs-react-material-ui.chip-input.core :refer [chip-input]] 11 | [om.dom :as dom] 12 | [cljs-time.format :as tf] 13 | [cljs-time.coerce :refer [from-date]] 14 | [cljs-react-material-ui-example.state :refer [init-state]] 15 | ;[schema.core :as s :include-macros true] 16 | [print.foo :as pf :include-macros true])) 17 | 18 | (enable-console-print!) 19 | 20 | (defn get-step-content [step-index] 21 | (case step-index 22 | 0 "Select campaign settings..." 23 | 1 "What is an ad group anyways?" 24 | 2 "This is the bit I really care about!" 25 | "You're a long way from home sonny jim!")) 26 | 27 | (defui MyStepper 28 | Object 29 | (componentWillMount [this] 30 | (om/set-state! this {:finished? false :step-index 0})) 31 | (render [this] 32 | (let [{:keys [finished? step-index]} (om/get-state this)] 33 | (dom/div 34 | #js {:className "row center-xs mar-top-20"} 35 | (ui/paper 36 | {:class-name "col-xs-12 col-md-8 col-lg-6 pad-10"} 37 | (ui/stepper 38 | {:active-step step-index} 39 | (ui/step 40 | (ui/step-label "Select campaign settings")) 41 | (ui/step 42 | (ui/step-label "Create an ad group")) 43 | (ui/step 44 | (ui/step-label "Create an ad"))) 45 | (if finished? 46 | (dom/div 47 | nil 48 | (ui/floating-action-button 49 | {:secondary true 50 | :on-click #(om/set-state! this {:finished? false :step-index 0})} 51 | (ic/content-clear))) 52 | (dom/div 53 | nil 54 | (dom/p #js {:className "mar-bot-20"} (get-step-content step-index)) 55 | (dom/div 56 | nil 57 | (ui/flat-button 58 | {:label "Back" 59 | :disabled (= step-index 0) 60 | :on-click #(om/set-state! this {:step-index (- step-index 1)})}) 61 | (ui/raised-button 62 | {:label (if (= step-index 2) "Finish" "Next") 63 | :primary true 64 | :on-click #(om/set-state! this {:step-index (+ step-index 1) 65 | :finished? (>= step-index 2)})}))))))))) 66 | 67 | (def my-stepper (om/factory MyStepper {})) 68 | 69 | (defui Person 70 | static om/Ident 71 | (ident [this {:keys [db/id]}] 72 | [:person/by-id id]) 73 | 74 | static om/IQuery 75 | (query [this] 76 | [:db/id :person/name :person/date {:person/status [:status/name]} {:person/happiness [:db/id :happiness/name]}]) 77 | 78 | Object 79 | (render [this] 80 | (let [{:keys [person/name person/date person/status person/happiness]} (om/props this)] 81 | (ui/table-row 82 | (ui/table-row-column name) 83 | (ui/table-row-column (tf/unparse (:date tf/formatters) (from-date date))) 84 | (ui/table-row-column (:status/name status)) 85 | (ui/table-row-column (:happiness/name happiness)))))) 86 | 87 | (def person (om/factory Person {})) 88 | 89 | (defn my-table [people] 90 | (ui/table 91 | {:height "250px"} 92 | (ui/table-header 93 | {:display-select-all false 94 | :adjust-for-checkbox false} 95 | (ui/table-row 96 | (ui/table-header-column "Name") 97 | (ui/table-header-column "Date") 98 | (ui/table-header-column "Status") 99 | (ui/table-header-column "Happiness"))) 100 | (ui/table-body 101 | (map person people)))) 102 | 103 | 104 | (defn radio-btn-group [c happiness-list val] 105 | (let [[sad normal superb] happiness-list] 106 | (ui/radio-button-group 107 | {:name "happiness" 108 | :value-selected (str val) 109 | :on-change #(om/transact! c `[(person-new/change {:value ~(js/parseInt %2) 110 | :path [:person/happiness 1]}) 111 | :person/new]) 112 | :class-name "row between-xs mar-ver-15"} 113 | (ui/radio-button 114 | {:value (str (:db/id sad)) 115 | :label (:happiness/name sad) 116 | :class-name "col-xs-4" 117 | :checked-icon (ic/social-sentiment-dissatisfied) 118 | :unchecked-icon (ic/social-sentiment-dissatisfied)}) 119 | (ui/radio-button 120 | {:value (str (:db/id normal)) 121 | :label (:happiness/name normal) 122 | :class-name "col-xs-4"}) 123 | (ui/radio-button 124 | {:value (str (:db/id superb)) 125 | :label (:happiness/name superb) 126 | :class-name "col-xs-4" 127 | :checked-icon (ic/action-favorite) 128 | :unchecked-icon (ic/action-favorite-border)})))) 129 | 130 | #_(s/defschema ValidPerson 131 | {:person/name s/Str 132 | :person/date s/Inst 133 | :person/status [(s/one s/Keyword "status/by-id") s/Int] 134 | :person/happiness [(s/one s/Keyword "happiness/by-id") s/Int]}) 135 | 136 | (defn handle-chip-delete [this idx] 137 | (om/update-state! this (fn [state] 138 | (update state :chip-data (partial remove #(= (key %) idx)))))) 139 | 140 | (defui MyChips 141 | Object 142 | (componentWillMount [this] 143 | (om/set-state! this {:chip-data {0 "Clojure" 144 | 1 "Clojurescript" 145 | 2 "Om.Next" 146 | 3 "MaterialUI"}})) 147 | (render [this] 148 | (let [chip-data (:chip-data (om/get-state this))] 149 | (ui/paper 150 | {:class-name "col-xs-12 col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3 pad-10 mar-top-20 row"} 151 | (for [chip (into [] chip-data)] 152 | (ui/chip {:key (key chip) 153 | :style {:margin-right 5} 154 | :on-request-delete #(handle-chip-delete this (key chip))} 155 | (val chip))))))) 156 | 157 | (def my-chips (om/factory MyChips)) 158 | 159 | (defui AppRoot 160 | static om/IQuery 161 | (query [this] 162 | [{:person/list (om/get-query Person)} 163 | {:status/list [:db/id :status/name]} 164 | {:happiness/list [:db/id :happiness/name]} 165 | {:person/new (om/get-query Person)}]) 166 | Object 167 | (render [this] 168 | (let [props (om/props this) 169 | state (om/get-state this) 170 | person-list (:person/list props) 171 | status-list (:status/list props) 172 | happiness-list (:happiness/list props) 173 | person-new (:person/new props) 174 | close-help #(om/update-state! this assoc :open-help? false) 175 | {:keys [drawer-open?]} (om/get-state this)] 176 | (ui/mui-theme-provider 177 | {:mui-theme (ui/get-mui-theme)} 178 | (dom/div 179 | #js {:className "h-100"} 180 | (ui/app-bar 181 | {:title "Material UI Om.Next App" 182 | :icon-element-right 183 | (ui/flat-button 184 | {:label "Github" 185 | :href "https://github.com/madvas/cljs-react-material-ui-example" 186 | :secondary true 187 | :target :_blank}) 188 | :on-left-icon-button-touch-tap 189 | #(om/set-state! this {:drawer-open? true})}) 190 | (ui/drawer 191 | {:docked false 192 | :open drawer-open? 193 | :on-request-change #(om/set-state! this {:drawer-open? %})} 194 | (ui/menu-item {:on-click #(println "Menu Item Clicked")} "Menu Item") 195 | (ui/menu-item "Menu Item 2")) 196 | 197 | (dom/div 198 | #js {:className "row around-xs mar-top-20"} 199 | (ui/paper 200 | {:class-name "col-xs-11 col-md-6 col-lg-4"} 201 | (ui/text-field 202 | {:floating-label-text "Name" 203 | :class-name "w-100" 204 | :value (:person/name person-new) 205 | :on-change #(om/transact! this `[(person-new/change {:value ~(u/target-val %) 206 | :path [:person/name]}) 207 | :person/new])}) 208 | (ui/date-picker 209 | {:hint-text "Select Date" 210 | :mode :landscape 211 | :class-name "w-100" 212 | :value (:person/date person-new) 213 | :on-change #(om/transact! this `[(person-new/change {:value ~%2 214 | :path [:person/date]}) 215 | :person/new])}) 216 | (ui/auto-complete 217 | {:dataSource (map :status/name status-list) 218 | :hint-text "Type status" 219 | :full-width true 220 | :open-on-focus true 221 | :search-text (or (:status/name 222 | (u/find-by-key :db/id (second (:person/status person-new)) status-list)) 223 | "") 224 | 225 | :filter (aget js/MaterialUI "AutoComplete" "caseInsensitiveFilter") 226 | :on-new-request (fn [chosen] 227 | (let [status-id (:db/id (u/find-by-key :status/name chosen status-list))] 228 | (om/transact! this `[(person-new/change {:value [:status/by-id ~status-id] 229 | :path [:person/status]}) 230 | :person/new])))}) 231 | 232 | (radio-btn-group this happiness-list (get-in person-new [:person/happiness 1])) 233 | (dom/div 234 | #js {:className "row pad-10 reverse"} 235 | (ui/raised-button 236 | {:label "Add" 237 | :primary true 238 | :label-position :before 239 | :icon (ic/content-add-circle) 240 | ;:disabled (boolean (s/check ValidPerson person-new)) 241 | :on-click #(om/transact! this `[(person-new/add) 242 | :person/new :person/list])}) 243 | (ui/raised-button 244 | {:label "Help" 245 | :class-name "mar-rig-10" 246 | :secondary true 247 | :label-position :before 248 | :icon (ic/action-help) 249 | :on-click #(om/update-state! this assoc :open-help? true)}))) 250 | 251 | (ui/paper 252 | {:class-name "col-xs-11 col-md-11 col-lg-7"} 253 | (ui/mui-theme-provider 254 | {:mui-theme (ui/get-mui-theme 255 | {:table-header-column 256 | {:text-color (ui/color :deep-orange500)}})} 257 | (my-table person-list)))) 258 | 259 | (ui/mui-theme-provider 260 | {:mui-theme (ui/get-mui-theme 261 | {:palette {:primary1-color (ui/color :amber600) 262 | :shadow-color (ui/color :deep-orange900) 263 | :text-color (ui/color :indigo900)} 264 | :stepper {:inactive-icon-color (ui/color :deep-orange900) 265 | :connector-line-color (ui/color :light-blue600) 266 | :text-color (ui/color :teal900) 267 | :disabled-text-color (ui/color :teal200)}})} 268 | (my-stepper)) 269 | (my-chips) 270 | (ui/paper 271 | {:class-name "col-xs-12 col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3 pad-10 mar-top-20 row"} 272 | (chip-input 273 | {:full-width true 274 | :default-value ["write" "here"]})) 275 | (ui/dialog 276 | {:title "Help" 277 | :key "dialog" 278 | :modal false 279 | :open (boolean (:open-help? state)) 280 | :actions [(ui/raised-button 281 | {:label "Back" 282 | :key "back" 283 | :on-click close-help}) 284 | (ui/raised-button 285 | {:label "Thanks" 286 | :key "thanks" 287 | :on-click close-help})] 288 | :on-request-close close-help}) 289 | ))))) 290 | 291 | (def reconciler 292 | (om/reconciler 293 | {:state (atom init-state) 294 | :normalize true 295 | :parser (om/parser {:read p/read :mutate p/mutate})})) 296 | 297 | (om/add-root! reconciler AppRoot (gdom/getElement "app")) 298 | 299 | --------------------------------------------------------------------------------