(ns reagent.impl.util (:require [cljsjs.react] [cljsjs.create-react-class] [reagent.debug :refer-macros [dbg log warn]] [reagent.interop :refer-macros [$ $!]] [clojure.string :as string])) (defonce react (cond (exists? js/React) js/React (exists? js/require) (or (js/require "react") (throw (js/Error. "require('react') failed"))) :else (throw (js/Error. "js/React is missing")))) (defonce create-class (cond (exists? js/createReactClass) js/createReactClass (exists? js/require) (or (js/require "create-react-class") (throw (js/Error. "require('create-react-class') failed"))) :else (throw (js/Error. "js/createReactClass is missing")))) (def is-client (and (exists? js/window) (-> js/window ($ :document) nil? not))) (def ^:dynamic ^boolean *non-reactive* false) ;;; Props accessors ;; Misc utilities (defn memoize-1 [f] (let [mem (atom {})] (fn [arg] (let [v (get @mem arg)] (if-not (nil? v) v (let [ret (f arg)] (swap! mem assoc arg ret) ret)))))) (def dont-camel-case #{"aria" "data"}) (defn capitalize [s] (if (< (count s) 2) (string/upper-case s) (str (string/upper-case (subs s 0 1)) (subs s 1)))) (defn dash-to-camel [dashed] (if (string? dashed) dashed (let [name-str (name dashed) [start & parts] (string/split name-str #"-")] (if (dont-camel-case start) name-str (apply str start (map capitalize parts)))))) (defn fun-name [f] (let [n (or (and (fn? f) (or ($ f :displayName) ($ f :name))) (and (implements? INamed f) (name f)) (let [m (meta f)] (if (map? m) (:name m))))] (-> n str (clojure.string/replace "$" ".")))) (deftype PartialFn [pfn f args] Fn IFn (-invoke [_] (pfn)) (-invoke [_ a] (pfn a)) (-invoke [_ a b] (pfn a b)) (-invoke [_ a b c] (pfn a b c)) (-invoke [_ a b c d] (pfn a b c d)) (-invoke [_ a b c d e] (pfn a b c d e)) (-invoke [_ a b c d e f] (pfn a b c d e f)) (-invoke [_ a b c d e f g] (pfn a b c d e f g)) (-invoke [_ a b c d e f g h] (pfn a b c d e f g h)) (-invoke [_ a b c d e f g h i] (pfn a b c d e f g h i)) (-invoke [_ a b c d e f g h i j] (pfn a b c d e f g h i j)) (-invoke [_ a b c d e f g h i j k] (pfn a b c d e f g h i j k)) (-invoke [_ a b c d e f g h i j k l] (pfn a b c d e f g h i j k l)) (-invoke [_ a b c d e f g h i j k l m] (pfn a b c d e f g h i j k l m)) (-invoke [_ a b c d e f g h i j k l m n] (pfn a b c d e f g h i j k l m n)) (-invoke [_ a b c d e f g h i j k l m n o] (pfn a b c d e f g h i j k l m n o)) (-invoke [_ a b c d e f g h i j k l m n o p] (pfn a b c d e f g h i j k l m n o p)) (-invoke [_ a b c d e f g h i j k l m n o p q] (pfn a b c d e f g h i j k l m n o p q)) (-invoke [_ a b c d e f g h i j k l m n o p q r] (pfn a b c d e f g h i j k l m n o p q r)) (-invoke [_ a b c d e f g h i j k l m n o p q r s] (pfn a b c d e f g h i j k l m n o p q r s)) (-invoke [_ a b c d e f g h i j k l m n o p q r s t] (pfn a b c d e f g h i j k l m n o p q r s t)) (-invoke [_ a b c d e f g h i j k l m n o p q r s t rest] (apply pfn a b c d e f g h i j k l m n o p q r s t rest)) IEquiv (-equiv [_ other] (and (= f (.-f other)) (= args (.-args other)))) IHash (-hash [_] (hash [f args]))) (defn make-partial-fn [f args] (->PartialFn (apply partial f args) f args)) (defn- merge-class [p1 p2] (let [class (when-let [c1 (:class p1)] (when-let [c2 (:class p2)] (str c1 " " c2)))] (if (nil? class) p2 (assoc p2 :class class)))) (defn- merge-style [p1 p2] (let [style (when-let [s1 (:style p1)] (when-let [s2 (:style p2)] (merge s1 s2)))] (if (nil? style) p2 (assoc p2 :style style)))) (defn merge-props [p1 p2] (if (nil? p1) p2 (do (assert (map? p1) (str "Property must be a map, not " (pr-str p1))) (merge-style p1 (merge-class p1 (merge p1 p2)))))) (def ^:dynamic *always-update* false) (defn force-update [comp deep] (if deep (binding [*always-update* true] ($ comp forceUpdate)) ($ comp forceUpdate)))