From 976b34910c61a6bf01cb964f87e0294b2bf70db9 Mon Sep 17 00:00:00 2001 From: Eric Webb Date: Tue, 26 Apr 2016 20:12:01 -0700 Subject: [PATCH] Add Rum support --- re-natal.coffee | 12 ++++++++++ resources/cljs-rum/core.cljs | 30 ++++++++++++++++++++++++ resources/cljs-rum/main_dev.cljs | 15 ++++++++++++ resources/cljs-rum/main_prod.cljs | 4 ++++ resources/cljs-rum/sablono_compiler.clj | 5 ++++ resources/cljs-rum/support.cljs | 31 +++++++++++++++++++++++++ 6 files changed, 97 insertions(+) create mode 100644 resources/cljs-rum/core.cljs create mode 100644 resources/cljs-rum/main_dev.cljs create mode 100644 resources/cljs-rum/main_prod.cljs create mode 100644 resources/cljs-rum/sablono_compiler.clj create mode 100644 resources/cljs-rum/support.cljs diff --git a/re-natal.coffee b/re-natal.coffee index 251ca19..810f6bb 100644 --- a/re-natal.coffee +++ b/re-natal.coffee @@ -71,6 +71,18 @@ interfaceConf = shims: ["cljsjs.react", "cljsjs.react.dom"] sampleCommandNs: '(in-ns \'$PROJECT_NAME_HYPHENATED$.state)' sampleCommand: '(swap! app-state assoc :app/msg "Hello Native World!")' + 'rum': + cljsDir: "cljs-rum" + sources: + ios: ["core.cljs"] + android: ["core.cljs"] + common: [] + other: [["sablono_compiler.clj","sablono/compiler.clj"],["support.cljs","re_natal/support.cljs"]] + deps: ['[rum "0.8.3" :exclusions [cljsjs/react cljsjs/react-dom sablono]]' + '[natal-shell "0.1.6"]'] + shims: ["cljsjs.react", "cljsjs.react.dom", "sablono.core"] + sampleCommandNs: '(in-ns \'$PROJECT_NAME_HYPHENATED$.ios.core)' + sampleCommand: '(swap! app-state assoc :greeting "Hello Clojure in iOS and Android with Rum!")' interfaceNames = Object.keys interfaceConf defaultInterface = 'reagent' defaultEnvRoots = diff --git a/resources/cljs-rum/core.cljs b/resources/cljs-rum/core.cljs new file mode 100644 index 0000000..153e8bc --- /dev/null +++ b/resources/cljs-rum/core.cljs @@ -0,0 +1,30 @@ +(ns $PROJECT_NAME_HYPHENATED$.$PLATFORM$.core + (:require-macros [natal-shell.components :refer [view text image touchable-highlight]] + [natal-shell.alert :refer [alert]] + [rum.core :refer [defc]]) + (:require [re-natal.support :as support] + [rum.core :as rum])) + +(set! js/window.React (js/require "react-native")) + +(def app-registry (.-AppRegistry js/React)) +(def logo-img (js/require "./images/cljs.png")) + +(defonce app-state (atom {:greeting "Hello Clojure in iOS and Android!"})) + +(defc AppRoot < rum/cursored-watch [state] + (view {:style {:flexDirection "column" :margin 40 :alignItems "center"}} + (text {:style {:fontSize 30 :fontWeight "100" :marginBottom 20 :textAlign "center"}} (:greeting @state)) + (image {:source logo-img + :style {:width 80 :height 80 :marginBottom 30}}) + (touchable-highlight {:style {:backgroundColor "#999" :padding 10 :borderRadius 5} + :onPress #(alert "HELLO!")} + (text {:style {:color "white" :textAlign "center" :fontWeight "bold"}} "press me")))) + +(defonce root-component-factory (support/make-root-component-factory)) + +(defn mount-app [] (support/mount (AppRoot app-state))) + +(defn init [] + (mount-app) + (.registerComponent app-registry "$PROJECT_NAME$" (fn [] root-component-factory))) \ No newline at end of file diff --git a/resources/cljs-rum/main_dev.cljs b/resources/cljs-rum/main_dev.cljs new file mode 100644 index 0000000..6fae51c --- /dev/null +++ b/resources/cljs-rum/main_dev.cljs @@ -0,0 +1,15 @@ +(ns ^:figwheel-no-load env.$PLATFORM$.main + (:require [$PROJECT_NAME_HYPHENATED$.$PLATFORM$.core :as core] + [figwheel.client :as figwheel :include-macros true])) + +(enable-console-print!) + +(figwheel/watch-and-reload + :websocket-url "ws://localhost:3449/figwheel-ws" + :heads-up-display false + ;; TODO make this Rum something + :jsload-callback #(#'core/mount-app)) + +(core/init) + +(def root-el (core/root-component-factory)) diff --git a/resources/cljs-rum/main_prod.cljs b/resources/cljs-rum/main_prod.cljs new file mode 100644 index 0000000..859a0cf --- /dev/null +++ b/resources/cljs-rum/main_prod.cljs @@ -0,0 +1,4 @@ +(ns env.$PLATFORM$.main + (:require [$PROJECT_NAME_HYPHENATED$.$PLATFORM$.core :as core])) + +(core/init) \ No newline at end of file diff --git a/resources/cljs-rum/sablono_compiler.clj b/resources/cljs-rum/sablono_compiler.clj new file mode 100644 index 0000000..e658efe --- /dev/null +++ b/resources/cljs-rum/sablono_compiler.clj @@ -0,0 +1,5 @@ +(ns sablono.compiler) + +(defn compile-html + [& content] + (first content)) \ No newline at end of file diff --git a/resources/cljs-rum/support.cljs b/resources/cljs-rum/support.cljs new file mode 100644 index 0000000..d98bd31 --- /dev/null +++ b/resources/cljs-rum/support.cljs @@ -0,0 +1,31 @@ +(ns re-natal.support + "Helpers and adapters to be able to mount/remount Rum components in a React Native application.") + +(def React (js/require "react-native")) +(def create-class (.-createClass React)) +(def create-factory (.-createFactory React)) + +(defonce root-component (atom nil)) +(defonce mounted-element (atom nil)) + +(defn make-root-component-factory + "Returns a React Native component factory fn for the root componenet singleton" + [] + (create-factory + (create-class + #js {:getInitialState (fn [] + (this-as this + (if-not @root-component + (reset! root-component this) + (throw (js/Error. "ASSERTION FAILED: re-natal.support root component mounted more than once."))))) + :render (fn [] @mounted-element)}))) + +(defn mount + "A modified version of rum.core/mount to work with React Native and re-natal. + + Since React Native's root component is a singleton, mount doesn't apply in the context of a DOM element (like in React), + but applies globally to the app. This function mounts/replaces the current " + [element] + (reset! mounted-element element) + (when @root-component + (.forceUpdate @root-component))) \ No newline at end of file