Set smooth/instant autoscroll depending on distance

This commit is contained in:
Aitor 2023-07-13 10:21:45 +02:00 committed by Alejandro Alonso
parent 477dc6315e
commit b0ba06eca8
3 changed files with 45 additions and 8 deletions

View file

@ -31,6 +31,7 @@
- Add the ability to use the registration whitelist with OICD [Github #3348](https://github.com/penpot/penpot/issues/3348) - Add the ability to use the registration whitelist with OICD [Github #3348](https://github.com/penpot/penpot/issues/3348)
- Add support for local caching of google fonts (this avoids exposing the final user IP to - Add support for local caching of google fonts (this avoids exposing the final user IP to
goolge and reduces the amount of request sent to google) goolge and reduces the amount of request sent to google)
- Set smooth/instant autoscroll depending on distance [GitHub #3377](https://github.com/penpot/penpot/issues/3377)
### :bug: Bugs fixed ### :bug: Bugs fixed

View file

@ -185,19 +185,25 @@
(mf/with-effect [selected? selected] (mf/with-effect [selected? selected]
(let [single? (= (count selected) 1) (let [single? (= (count selected) 1)
node (mf/ref-val ref) node (mf/ref-val ref)
parent (dom/get-parent (dom/get-parent node)) ;; NOTE: Neither get-parent-at nor get-parent-with-selector
;; work if the component template changes, so we need to
;; seek for an alternate solution. Maybe use-context?
scroll-node (dom/get-parent-with-selector node ".tool-window-content")
parent-node (dom/get-parent-at node 2)
subid subid
(when (and single? selected?) (when (and single? selected?)
(let [scroll-to @scroll-to-middle?] (let [scroll-to @scroll-to-middle?]
(ts/schedule (ts/schedule
100 100
#(if scroll-to #(let [scroll-distance-ratio (dom/get-scroll-distance-ratio node scroll-node)
(dom/scroll-into-view! parent {:block "center" :behavior "smooth" :inline "start"}) scroll-behavior (if (> scroll-distance-ratio 1) "instant" "smooth")]
(do (if scroll-to
(dom/scroll-into-view-if-needed! parent {:block "center" :behavior "smooth" :inline "start"}) (dom/scroll-into-view! parent-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(reset! scroll-to-middle? true))))))] (do
(dom/scroll-into-view-if-needed! parent-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(reset! scroll-to-middle? true)))))))]
#(when (some? subid) #(when (some? subid)
(rx/dispose! subid)))) (rx/dispose! subid))))

View file

@ -158,9 +158,16 @@
(when (some? node) (when (some? node)
(.-parentElement ^js node))) (.-parentElement ^js node)))
(defn get-parent-at
[^js node count]
(when (some? node)
(loop [current node current-count count]
(if (or (nil? current) (= current-count 0))
current
(recur (.-parentElement current) (dec current-count))))))
(defn get-parent-with-selector (defn get-parent-with-selector
[^js node selector] [^js node selector]
(loop [current node] (loop [current node]
(if (or (nil? current) (.matches current selector)) (if (or (nil? current) (.matches current selector))
current current
@ -195,6 +202,22 @@
:scroll-top (.-scrollTop event) :scroll-top (.-scrollTop event)
:scroll-width (.-scrollWidth event)})) :scroll-width (.-scrollWidth event)}))
(defn get-scroll-height-ratio
[^js node]
(when (some? node)
(/ (.-scrollHeight node) (.-clientHeight node))))
(defn get-scroll-distance
[^js node scroll-node]
(when (and (some? node) (some? scroll-node))
(abs (- (.-scrollTop scroll-node) (.-offsetTop node)))))
(defn get-scroll-distance-ratio
[^js node scroll-node]
(let [distance (get-scroll-distance node scroll-node)
height (.-clientHeight scroll-node)]
(/ distance height)))
(def get-target-val (comp get-value get-target)) (def get-target-val (comp get-value get-target))
(def get-target-scroll (comp get-scroll-position get-target)) (def get-target-scroll (comp get-scroll-position get-target))
@ -573,6 +596,13 @@
(when (some? element) (when (some? element)
(.scrollIntoView element options)))) (.scrollIntoView element options))))
;; NOTE: scrollIntoViewIfNeeded is not supported in Firefox
;; because it is not a standard API. BTW it only supports
;; centerIfNeeded as boolean option.
;; @see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
;; @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=17152
;; @see https://github.com/w3c/csswg-drafts/pull/1805
;; @see https://github.com/w3c/csswg-drafts/pull/5677
(defn scroll-into-view-if-needed! (defn scroll-into-view-if-needed!
([^js element] ([^js element]
(scroll-into-view-if-needed! element false)) (scroll-into-view-if-needed! element false))