Skip to content

Commit

Permalink
Use reagent idiom for react refs
Browse files Browse the repository at this point in the history
  • Loading branch information
kimo-k committed Jan 17, 2024
1 parent e8a9d14 commit f974e64
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 69 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

> Committed but unreleased changes are put here, at the top. Older releases are detailed chronologically below.
## 2.16.2 (2024-01-16)

#### Fixed

- Replace deprecated `r/dom-node` with ref callbacks. (#329, #334) Thanks [RolT](https://github.com/RolT) for PR.

## 2.16.1 (2024-01-16)

#### Fixed

- Cleanup & fixes for the new tree-select component.

## 2.16.0 (2024-01-16)

#### Added
Expand Down
101 changes: 41 additions & 60 deletions src/re_com/dropdown.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -123,78 +123,59 @@
"Render a choice item and set up appropriate mouse events"
[id label on-click internal-model]
(let [mouse-over? (reagent/atom false)
ref (react/createRef)]
!ref (atom nil)
ref! (partial reset! !ref)
show! #(when (= @internal-model id) (show-selected-item @!ref))]
(reagent/create-class
{:component-did-mount
(fn [this]
(let [node (.-current ref)
selected (= @internal-model id)]
(when selected (show-selected-item node))))

:component-did-update
(fn [this]
(let [node (.-current ref)
selected (= @internal-model id)]
(when selected (show-selected-item node))))

:display-name "choice-item"

:reagent-render
(fn
[id label on-click internal-model]
(let [selected (= @internal-model id)
class (if selected
"highlighted"
(when @mouse-over? "mouseover"))]
[:li
{:class (str "active-result group-option " class)
:ref ref
:on-mouse-over (handler-fn (reset! mouse-over? true))
:on-mouse-out (handler-fn (reset! mouse-over? false))
:on-mouse-down (handler-fn
(on-click id)
(.preventDefault event))} ;; Prevent free-text input as well as the normal dropdown from loosing focus
label]))})))
{:component-did-mount show!
:component-did-update show!
:display-name "choice-item"
:reagent-render (fn [id label on-click internal-model]
(let [selected (= @internal-model id)
class (if selected
"highlighted"
(when @mouse-over? "mouseover"))]
[:li
{:class (str "active-result group-option " class)
:ref ref!
:on-mouse-over (handler-fn (reset! mouse-over? true))
:on-mouse-out (handler-fn (reset! mouse-over? false))
:on-mouse-down (handler-fn
(on-click id)
(.preventDefault event))} ;; Prevent free-text input as well as the normal dropdown from losing focus
label]))})))

(defn make-choice-item
[id-fn render-fn callback internal-model opt]
(let [id (id-fn opt)
markup (render-fn opt)]
^{:key (str id)} [choice-item id markup callback internal-model]))

(defn- filter-text-box-base
"Base function (before lifecycle metadata) to render a filter text box"
[ref]
(fn [filter-box? filter-text key-handler drop-showing? set-filter-text filter-placeholder]
[:div.chosen-search {:ref ref}
[:input
{:type "text"
:auto-complete "off"
:style (when-not filter-box? {:position "absolute" ;; When no filter box required, use it but hide it off screen
:width "0px" ;; The rest of these styles make the textbox invisible
:padding "0px"
:border "none"})
:value @filter-text
:placeholder filter-placeholder
:on-change (handler-fn (set-filter-text (-> event .-target .-value)))
:on-key-down (handler-fn (when-not (key-handler event)
(.stopPropagation event)
(.preventDefault event))) ;; When key-handler returns false, preventDefault
:on-blur (handler-fn (reset! drop-showing? false))}]]))

(defn- filter-text-box
"Render a filter text box"
[filter-box? filter-text key-handler drop-showing? set-filter-text filter-placeholder]
(let [ref (react/createRef)
render-fn (filter-text-box-base ref)]
(let [!ref (atom nil)
ref! (partial reset! !ref)
focus! #(.focus (.-firstChild @!ref))]
(reagent/create-class
{:component-did-mount (fn [this]
(let [node (.. ref -current -firstChild)]
(.focus node)))
:component-did-update (fn [this]
(let [node (.. ref -current -firstChild)]
(.focus node)))
:reagent-render render-fn})))
{:component-did-mount focus!
:component-did-update focus!
:reagent-render (fn [filter-box? filter-text key-handler drop-showing? set-filter-text filter-placeholder]
[:div.chosen-search {:ref ref!}
[:input
{:type "text"
:auto-complete "off"
:style (when-not filter-box? {:position "absolute" ;; When no filter box required, use it but hide it off screen
:width "0px" ;; The rest of these styles make the textbox invisible
:padding "0px"
:border "none"})
:value @filter-text
:placeholder filter-placeholder
:on-change (handler-fn (set-filter-text (-> event .-target .-value)))
:on-key-down (handler-fn (when-not (key-handler event)
(.stopPropagation event)
(.preventDefault event))) ;; When key-handler returns false, preventDefault
:on-blur (handler-fn (reset! drop-showing? false))}]])})))

(defn- dropdown-top
"Render the top part of the dropdown, with the clickable area and the up/down arrow"
Expand Down
18 changes: 9 additions & 9 deletions src/re_com/popover.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@
p-height (reagent/atom 0)
pop-offset (reagent/atom 0)
found-optimal (reagent/atom false)
pop-border-ref (react/createRef)
!pop-border (atom nil)
ref! (partial reset! !pop-border)
calc-metrics (fn [pos]
(let [popover-elem (get-element-by-id pop-id)
[orientation arrow-pos] (split-keyword pos "-")
Expand All @@ -320,9 +321,8 @@

:component-did-update
(fn [this]
(let [pop-border-node (.-current pop-border-ref)
clipped? (popover-clipping pop-border-node)
anchor-node (-> pop-border-node .-parentNode .-parentNode .-parentNode)] ;; Get reference to rc-point-wrapper node
(let [clipped? (popover-clipping @!pop-border)
anchor-node (-> @!pop-border .-parentNode .-parentNode .-parentNode)] ;; Get reference to rc-point-wrapper node
(when (and clipped? (not @found-optimal))
(reset! position (calculate-optimal-position (calc-element-midpoint anchor-node)))
(reset! found-optimal true))
Expand Down Expand Up @@ -375,7 +375,7 @@
style)}
(->attr args)
attr
{:ref pop-border-ref})
{:ref ref!})
[popover-arrow orientation @pop-offset arrow-length arrow-width grey-arrow? tooltip-style? popover-color popover-border-color parts]
(when title title)
(into [:div
Expand Down Expand Up @@ -434,12 +434,12 @@
(validate-args-macro popover-content-wrapper-args-desc args)
(let [left-offset (reagent/atom 0)
top-offset (reagent/atom 0)
ref (react/createRef)
!ref (atom nil)
ref! (partial reset! !ref)
position-no-clip-popover (fn position-no-clip-popover
[this]
(when no-clip?
(let [node (.-current ref)
popover-point-node (.-parentNode node) ;; Get reference to rc-popover-point node
(let [popover-point-node (.-parentNode @!ref) ;; Get reference to rc-popover-point node
bounding-rect (.getBoundingClientRect popover-point-node)] ;; The modern magical way of getting offsetLeft and offsetTop. Returns this: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMClientRect
(reset! left-offset (.-left bounding-rect))
(reset! top-offset (.-top bounding-rect)))))]
Expand Down Expand Up @@ -474,7 +474,7 @@
style)}
(->attr args)
attr
{:ref ref})
{:ref ref!})
(when (and (deref-or-value showing-injected?) on-cancel)
[backdrop
:src (at)
Expand Down

0 comments on commit f974e64

Please sign in to comment.