93 lines
4.5 KiB
Clojure
93 lines
4.5 KiB
Clojure
(ns com.fulcrologic.rad.rendering.semantic-ui.components
|
|
(:require
|
|
#?@(:cljs
|
|
[[com.fulcrologic.fulcro.dom :as dom :refer [div label input]]
|
|
[com.fulcrologic.semantic-ui.modules.dropdown.ui-dropdown :refer [ui-dropdown]]]
|
|
:clj
|
|
[[com.fulcrologic.fulcro.dom-server :as dom :refer [div label input]]])
|
|
[com.fulcrologic.fulcro.components :as comp :refer [defsc]]
|
|
[com.fulcrologic.fulcro.algorithms.transit :as ftransit]
|
|
[taoensso.timbre :as log]))
|
|
|
|
(defn sui-format->user-format
|
|
"Converts transit encoded value(s), used by Semantic UI, into CLJS datastructure."
|
|
[{:keys [multiple]} value]
|
|
(if multiple
|
|
(into [] (map ftransit/transit-str->clj value))
|
|
(ftransit/transit-str->clj value)))
|
|
|
|
(defn user-format->sui-format [{:keys [multiple]} value]
|
|
"Converts CLJS datastructure into transit encoded string(s), usable by Semantic UI."
|
|
(if multiple
|
|
(if value
|
|
(to-array (map ftransit/transit-clj->str value))
|
|
#js [])
|
|
(if (or value (boolean? value))
|
|
(ftransit/transit-clj->str value)
|
|
"")))
|
|
|
|
(defn wrapped-onChange
|
|
"Wraps userOnChange fn with try/catch and sui-form->user-format conversion."
|
|
[props userOnChange]
|
|
(fn [_ v]
|
|
#?(:cljs
|
|
(try
|
|
(if (and (.-value v) (seq (.-value v)))
|
|
(let [value (sui-format->user-format props (.-value v))]
|
|
(when (and value userOnChange) (userOnChange value)))
|
|
(userOnChange nil))
|
|
(catch :default e
|
|
(log/error e "Unable to read dropdown value " (when v (.-value v))))))))
|
|
|
|
(defsc WrappedDropdown [this {:keys [onChange value multiple] :as props}]
|
|
{:initLocalState (fn [this]
|
|
#?(:cljs
|
|
(let [xform-options (memoize (fn [options]
|
|
(clj->js (mapv (fn [{:keys [text value]}]
|
|
#js {:text text :value (some-> value (ftransit/transit-clj->str))})
|
|
options))))
|
|
xform-value (fn [multiple? value]
|
|
(user-format->sui-format {:multiple multiple?} value))]
|
|
{:get-options (fn [props] (xform-options (:options props)))
|
|
:format-value (fn [props value] (xform-value (:multiple props) value))})))}
|
|
#?(:cljs
|
|
(let [{:keys [get-options format-value]} (comp/get-state this)
|
|
userOnChange onChange
|
|
options (get-options props)
|
|
value (format-value props value)
|
|
props (merge
|
|
{:search true
|
|
:selection true
|
|
:closeOnBlur true
|
|
:openOnFocus true
|
|
:selectOnBlur true
|
|
:selectOnNavigation true
|
|
:multiple (boolean multiple)}
|
|
props
|
|
{:value value
|
|
:options options
|
|
:onChange (fn [e v]
|
|
(try
|
|
(let [string-value (.-value v)
|
|
value (if multiple
|
|
(mapv #(when (seq %) (ftransit/transit-str->clj %)) string-value)
|
|
(when (seq string-value) (ftransit/transit-str->clj string-value)))]
|
|
(when userOnChange
|
|
(userOnChange value)))
|
|
(catch :default e
|
|
(log/error "Unable to read dropdown value " e (when v (.-value v))))))})]
|
|
(ui-dropdown props))
|
|
:clj
|
|
(dom/div :.ui.selection.dropdown
|
|
(dom/input {:type "hidden"})
|
|
(dom/i :.dropdown.icon)
|
|
(dom/div :.default.text "")
|
|
(dom/div :.menu))))
|
|
|
|
(def ui-wrapped-dropdown
|
|
"Draw a SUI dropdown with the given props. The arguments are identical to sui/ui-dropdown, but options and onChange
|
|
are auto-wrapped so that clojure data (e.g. keywords) can be used for the option :value fields. It also defaults
|
|
a number of things (:search, :closeOnBlue, openOnFocus, selectOnBlue, and :selectOnNavigation) to true, but you can"
|
|
(comp/factory WrappedDropdown))
|
|
|