Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (defmacro suggestions-comp
- ([comp-name label]
- `(rum/defc ~comp-name ~(quote <) rum/reactive []
- [:div.suggestion-input-comp
- [:div.suggestions-input.flex
- [:input {:type "text" :placeholder ~label}]
- [:div.showhide-icon.show]]]))
- ([comp-name label atom-name atom-ns url]
- `(let [hidden?# ~(symbol atom-ns (str atom-name "-suggestions-hidden?"))
- suggestions# ~(symbol atom-ns (str atom-name "-suggestions"))
- current-suggs# ~(symbol atom-ns (str atom-name "-suggestions-cur"))
- input-field# ~(symbol atom-ns (str atom-name "-input-field"))
- ajax-post# ~(symbol "ajax.core" "GET")
- swap-chained!# ~(symbol atom-ns (str atom-name "-swap-chained!"))]
- (rum/defcs ~comp-name ~(quote <)
- rum/reactive
- (rum/local "0px" :width)
- (rum/local -1 :active-id)
- {:did-update (fn [~(quote state)]
- (assoc ~(quote state) :width (.-width (.getBoundingClientRect (rum/dom-node ~(quote state))))))}
- {:will-update (fn [~(quote state)]
- (assoc ~(quote state) :width (.-width (.getBoundingClientRect (rum/dom-node ~(quote state))))))}
- {:did-mount (fn [~(quote state)]
- (assoc ~(quote state) :width (.-width (.getBoundingClientRect (rum/dom-node ~(quote state))))))}
- [~(quote state)]
- (let [_# (rum/react ~(symbol "project.app-state.core" "resize-sync"))
- width# (:width ~(quote state))
- active-id# (:active-id ~(quote state))
- current-suggs-derefed# (rum/react current-suggs#)]
- [:div.suggestion-input-comp
- [:div.suggestions-input.flex
- [:input
- {:type "text"
- :placeholder ~label
- :value (let [v# (:value (rum/react input-field#))]
- (cond->> v# (vector? v#) (clojure.string/join " ")))
- :on-change (fn [~(quote ev)]
- (let [input-val# (-> ~(quote ev) .-target .-value)]
- (do (swap! input-field# assoc :value input-val#)
- (if-let [suggs# (get (deref suggestions#) input-val#)]
- (do (reset! hidden?# false)
- (reset! current-suggs# suggs#))
- (ajax-post# ~url {:handler #(do (swap! suggestions# assoc input-val# (vec %))
- (reset! hidden?# false)
- (reset! current-suggs# %))})))))
- :onKeyDown (fn [~(quote ev)]
- (let [code# (.-keyCode ~(quote ev))]
- (case code#
- 40 (swap! active-id# #(mod (inc %) (count @current-suggs#)))
- 38 (swap! active-id# #(mod (dec %) (count @current-suggs#)))
- 13 (do (let [choise-result# (nth @current-suggs# @active-id#)]
- (swap! input-field# #(-> %
- (assoc :value (:sugg choise-result#))
- (assoc :id (:id choise-result#)))))
- (swap-chained!#)
- (reset! active-id# -1)
- (reset! hidden?# true))
- 27 (reset! hidden?# true)
- :do-nothing)))}]
- [(keyword (str "div.showhide-icon." (if @hidden?# "show" "hide")))
- {:on-click #(swap! hidden?# not)}]]
- (when-not (rum/react hidden?#)
- (when current-suggs-derefed#
- [:div.suggestions-list
- {:style {:width (str (- (js/parseInt width#) 14) "px")}}
- (let [act-id# @active-id#]
- (for [[idx# el#] (map-indexed vector current-suggs-derefed#)]
- [(keyword (str "div" (when (= act-id# idx#) ".active")))
- {:on-click (fn [~(quote ev)]
- (do (swap! input-field# #(-> % (assoc :id (:id el#)) (assoc :value (:sugg el#))))
- (swap-chained!#)
- (reset! hidden?# true)))}
- (:sugg el#)]))]))])))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement