0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-25 16:25:56 -05:00

Merge pull request #3390 from penpot/hiru-fix-overlay

Fix several bugs related to interaction overlays
This commit is contained in:
Alejandro 2023-07-12 10:57:18 +02:00 committed by GitHub
commit e9ce327eef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 300 additions and 149 deletions

View file

@ -63,7 +63,11 @@
- Fix search bar width on layer tab [Taiga #5445](https://tree.taiga.io/project/penpot/issue/5445)
- Fix border radius values with decimals [Taiga #5283](https://tree.taiga.io/project/penpot/issue/5283)
- Fix shortcuts translations not homogenized [Taiga #5141](https://tree.taiga.io/project/penpot/issue/5141)
- Fix overlay manual position in nested boards [Taiga #5135](https://tree.taiga.io/project/penpot/issue/5135)
- Fix close overlay from a nested board [Taiga #5587](https://tree.taiga.io/project/penpot/issue/5587)
- Fix overlay position when it has shadow or blur [Taiga #4752](https://tree.taiga.io/project/penpot/issue/4752)
- Fix overlay position when there are elements fixed when scrolling [Taiga #4383](https://tree.taiga.io/project/penpot/issue/4383)
### :arrow_up: Deps updates
- Update google fonts catalog (at 2023/07/06) [Taiga #5592](https://tree.taiga.io/project/penpot/issue/5592)

View file

@ -147,6 +147,7 @@
:else
(cph/reduce-objects
objects
(fn [shape]
(and (d/not-empty? (:shapes shape))
(or (not (cph/frame-shape? shape))

View file

@ -495,8 +495,7 @@
"expected compatible interaction map"
(has-overlay-opts interaction))
(let [
;; When the interactive item is inside a nested frame we need to add to the offset the position
(let [;; When the interactive item is inside a nested frame we need to add to the offset the position
;; of the parent-frame otherwise the position won't match
shape-frame (cph/get-frame objects shape)
@ -505,10 +504,10 @@
(cph/root-frame? shape-frame)
(cph/root? shape-frame))
frame-offset
(gpt/add frame-offset (gpt/point shape-frame)))
]
(gpt/add frame-offset (gpt/point shape-frame)))]
(if (nil? dest-frame)
(gpt/point 0 0)
[(gpt/point 0 0) [:top :left]]
(let [overlay-size (gsb/get-object-bounds objects dest-frame)
base-frame-size (:selrect base-frame)
relative-to-shape-size (:selrect relative-to-shape)
@ -526,37 +525,46 @@
overlay-position
{:x (- (:x overlay-position) (:x relative-to-adjusted-to-base-frame))
:y (- (:y overlay-position) (:y relative-to-adjusted-to-base-frame))})]
(case (:overlay-pos-type interaction)
:center
(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(+ (:y base-position) (/ (- (:height relative-to-shape-size) (:height overlay-size)) 2)))
[(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(+ (:y base-position) (/ (- (:height relative-to-shape-size) (:height overlay-size)) 2)))
[:center :center]]
:top-left
(gpt/point (:x base-position) (:y base-position))
[(gpt/point (:x base-position) (:y base-position))
[:top :left]]
:top-right
(gpt/point (+ (:x base-position) (- (:width relative-to-shape-size) (:width overlay-size)))
(:y base-position))
[(gpt/point (+ (:x base-position) (- (:width relative-to-shape-size) (:width overlay-size)))
(:y base-position))
[:top :right]]
:top-center
(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(:y base-position))
[(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(:y base-position))
[:top :center]]
:bottom-left
(gpt/point (:x base-position)
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[(gpt/point (:x base-position)
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[:bottom :left]]
:bottom-right
(gpt/point (+ (:x base-position) (- (:width relative-to-shape-size) (:width overlay-size)))
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[(gpt/point (+ (:x base-position) (- (:width relative-to-shape-size) (:width overlay-size)))
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[:bottom :right]]
:bottom-center
(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[(gpt/point (+ (:x base-position) (/ (- (:width relative-to-shape-size) (:width overlay-size)) 2))
(+ (:y base-position) (- (:height relative-to-shape-size) (:height overlay-size))))
[:bottom :center]]
:manual
(gpt/point (+ (:x base-position) (:x overlay-position))
(+ (:y base-position) (:y overlay-position))))))))
[(gpt/point (+ (:x base-position) (:x overlay-position))
(+ (:y base-position) (:y overlay-position)))
[:top :left]])))))
(defn has-animation?
[interaction]

View file

@ -324,209 +324,275 @@
interaction-rect (ctsi/set-position-relative-to interaction (:id rect))]
(t/testing "Overlay top-left relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 0))
(t/is (= (:y overlay-pos) 0))))
(t/is (= (:y overlay-pos) 0))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 0))))
(t/is (= (:y overlay-pos) 0))
(t/is (= snap-v :top))
(t/is (= snap-h :center))))
(t/testing "Overlay top-right relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 70))
(t/is (= (:y overlay-pos) 0))))
(t/is (= (:y overlay-pos) 0))
(t/is (= snap-v :top))
(t/is (= snap-h :right))))
(t/testing "Overlay bottom-left relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 0))
(t/is (= (:y overlay-pos) 80))))
(t/is (= (:y overlay-pos) 80))
(t/is (= snap-v :bottom))
(t/is (= snap-h :left))))
(t/testing "Overlay bottom-center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 80))))
(t/is (= (:y overlay-pos) 80))
(t/is (= snap-v :bottom))
(t/is (= snap-h :center))))
(t/testing "Overlay bottom-right relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 70))
(t/is (= (:y overlay-pos) 80))))
(t/is (= (:y overlay-pos) 80))
(t/is (= snap-v :bottom))
(t/is (= snap-h :right))))
(t/testing "Overlay center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 40))))
(t/is (= (:y overlay-pos) 40))
(t/is (= snap-v :center))
(t/is (= snap-h :center))))
(t/testing "Overlay manual relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 40))))
(t/is (= (:y overlay-pos) 40))
(t/is (= snap-v :center))
(t/is (= snap-h :center))))
(t/testing "Overlay manual relative to auto"
(let [i2 (-> interaction-auto
(ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62)))
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 17))
(t/is (= (:y overlay-pos) 67))))
(t/is (= (:y overlay-pos) 67))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-left relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 5))
(t/is (= (:y overlay-pos) 5))))
(t/is (= (:y overlay-pos) 5))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 40))
(t/is (= (:y overlay-pos) 5))))
(t/is (= (:y overlay-pos) 5))
(t/is (= snap-v :top))
(t/is (= snap-h :center))))
(t/testing "Overlay top-right relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 75))
(t/is (= (:y overlay-pos) 5))))
(t/is (= (:y overlay-pos) 5))
(t/is (= snap-v :top))
(t/is (= snap-h :right))))
(t/testing "Overlay bottom-left relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 5))
(t/is (= (:y overlay-pos) 85))))
(t/is (= (:y overlay-pos) 85))
(t/is (= snap-v :bottom))
(t/is (= snap-h :left))))
(t/testing "Overlay bottom-center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 40))
(t/is (= (:y overlay-pos) 85))))
(t/is (= (:y overlay-pos) 85))
(t/is (= snap-v :bottom))
(t/is (= snap-h :center))))
(t/testing "Overlay bottom-right relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 75))
(t/is (= (:y overlay-pos) 85))))
(t/is (= (:y overlay-pos) 85))
(t/is (= snap-v :bottom))
(t/is (= snap-h :right))))
(t/testing "Overlay center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 40))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :center))
(t/is (= snap-h :center))))
(t/testing "Overlay manual relative to base-frame"
(let [i2 (-> interaction-base-frame
(ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62)))
overlay-pos (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 17))
(t/is (= (:y overlay-pos) 67))))
(t/is (= (:y overlay-pos) 67))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 15))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :center))))
(t/testing "Overlay top-right relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :right))))
(t/testing "Overlay bottom-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 15))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :left))))
(t/testing "Overlay bottom-center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :center))))
(t/testing "Overlay bottom-right relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :right))))
(t/testing "Overlay center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 30))))
(t/is (= (:y overlay-pos) 30))
(t/is (= snap-v :center))
(t/is (= snap-h :center))))
(t/testing "Overlay manual relative to popup"
(let [i2 (-> interaction-popup
(ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62)))
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 27))
(t/is (= (:y overlay-pos) 77))))
(t/is (= (:y overlay-pos) 77))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 15))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))
(t/testing "Overlay top-center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :center))))
(t/testing "Overlay top-right relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 15))))
(t/is (= (:y overlay-pos) 15))
(t/is (= snap-v :top))
(t/is (= snap-h :right))))
(t/testing "Overlay bottom-left relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-left base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 15))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :left))))
(t/testing "Overlay bottom-center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :center))))
(t/testing "Overlay bottom-right relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-right base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 35))
(t/is (= (:y overlay-pos) 45))))
(t/is (= (:y overlay-pos) 45))
(t/is (= snap-v :bottom))
(t/is (= snap-h :right))))
(t/testing "Overlay center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :center base-frame objects)
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 25))
(t/is (= (:y overlay-pos) 30))))
(t/is (= (:y overlay-pos) 30))
(t/is (= snap-v :center))
(t/is (= snap-h :center))))
(t/testing "Overlay manual relative to rect"
(let [i2 (-> interaction-rect
(ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62)))
overlay-pos (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
[overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)]
(t/is (= (:x overlay-pos) 17))
(t/is (= (:y overlay-pos) 67))))))
(t/is (= (:y overlay-pos) 67))
(t/is (= snap-v :top))
(t/is (= snap-h :left))))))
(t/deftest animation-checks

View file

@ -542,13 +542,14 @@
;; --- Overlays
(defn- open-overlay*
[state frame position close-click-outside background-overlay animation]
[state frame position snap-to close-click-outside background-overlay animation]
(cond-> state
:always
(update :viewer-overlays conj
{:frame frame
:id (:id frame)
:position position
:snap-to snap-to
:close-click-outside close-click-outside
:background-overlay background-overlay
:animation animation})
@ -571,7 +572,7 @@
:animation animation})))
(defn open-overlay
[frame-id position close-click-outside background-overlay animation]
[frame-id position snap-to close-click-outside background-overlay animation]
(dm/assert! (uuid? frame-id))
(dm/assert! (gpt/point? position))
(dm/assert! (or (nil? close-click-outside)
@ -593,6 +594,7 @@
(open-overlay* state
frame
position
snap-to
close-click-outside
background-overlay
animation)
@ -600,7 +602,7 @@
(defn toggle-overlay
[frame-id position close-click-outside background-overlay animation]
[frame-id position snap-to close-click-outside background-overlay animation]
(dm/assert! (uuid? frame-id))
(dm/assert! (gpt/point? position))
(dm/assert! (or (nil? close-click-outside)
@ -623,6 +625,7 @@
(open-overlay* state
frame
position
snap-to
close-click-outside
background-overlay
animation)

View file

@ -142,5 +142,6 @@
[:> frame-container props
[:g.frame-children {:opacity (:opacity shape)}
(for [item childs]
[:& shape-wrapper {:key (dm/str (:id item)) :shape item}])]])))
(when (:id item)
[:& shape-wrapper {:key (dm/str (:id item)) :shape item}]))]])))

View file

@ -50,6 +50,8 @@
(l/derived :viewer-overlays st/state))
(defn- calculate-size
"Calculate the total size we must reserve for the frame, including possible paddings
added because shadows or blur."
[objects frame zoom]
(let [{:keys [x y width height]} (gsb/get-object-bounds objects frame)]
{:base-width width
@ -60,6 +62,23 @@
:height (* height zoom)
:vbox (dm/fmt "% % % %" 0 0 width height)}))
(defn calculate-delta
"Calculate the displacement we need to apply so that the original selrect appears in the
same position as if it had no extra paddings, depending on the side the frame will
be snapped to."
[size selrect [snap-v snap-h] zoom]
(let [delta-x (case snap-h
:left (- (:x1 selrect) (:x size))
:right (- (:x2 selrect) (+ (:x size) (/ (:width size) zoom)))
:center (- (/ (- (:width selrect) (/ (:width size) zoom)) 2)
(- (:x size) (:x1 selrect))))
delta-y (case snap-v
:top (- (:y1 selrect) (:y size))
:bottom (- (:y2 selrect) (+ (:y size) (/ (:height size) zoom)))
:center (- (/ (- (:height selrect) (/ (:height size) zoom)) 2)
(- (:y size) (:y1 selrect))))]
(gpt/point (* delta-x zoom) (* delta-y zoom))))
(defn- calculate-wrapper
[size1 size2 zoom]
(cond
@ -113,6 +132,10 @@
(mf/with-memo [page overlay zoom]
(calculate-size (:objects page) (:frame overlay) zoom))
delta
(mf/with-memo [size overlay-frame overlay zoom]
(calculate-delta size (:selrect overlay-frame) (:snap-to overlay) zoom))
on-click
(mf/use-fn
(mf/deps overlay close-click-outside?)
@ -145,6 +168,7 @@
:base-frame frame
:frame-offset overlay-position
:size size
:delta delta
:page page
:interactions-mode interactions-mode}]]]))

View file

@ -7,6 +7,7 @@
(ns app.main.ui.viewer.inspect.render
"The main container for a frame in inspect mode"
(:require
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph]
[app.main.data.viewer :as dv]
@ -186,7 +187,7 @@
(mf/defc render-frame-svg
[{:keys [page frame local size]}]
(let [objects (mf/with-memo [page frame size]
(prepare-objects frame size (:objects page)))
(prepare-objects frame size (gpt/point 0 0) (:objects page)))
;; Retrieve frame again with correct modifier
frame (get objects (:id frame))

View file

@ -28,9 +28,10 @@
[rumext.v2 :as mf]))
(defn prepare-objects
[frame size objects]
[frame size delta objects]
(let [frame-id (:id frame)
vector (-> (gpt/point (:x size) (:y size))
(gpt/add delta)
(gpt/negate))
update-fn #(d/update-when %1 %2 gsh/transform-shape (ctm/move-modifiers vector))]
(->> (cph/get-children-ids objects frame-id)
@ -46,6 +47,7 @@
base (unchecked-get props "base")
offset (unchecked-get props "offset")
size (unchecked-get props "size")
delta (or (unchecked-get props "delta") (gpt/point 0 0))
vbox (:vbox size)
@ -67,20 +69,26 @@
(map (d/getf (:objects page)))
(concat [frame])
(d/index-by :id)
(prepare-objects frame size)))
(prepare-objects frame size delta)))
wrapper-fixed (mf/with-memo [page frame size]
(shapes/frame-container-factory (calculate-objects fixed-ids)))
objects-fixed (mf/with-memo [fixed-ids page frame size delta]
(calculate-objects fixed-ids))
objects-not-fixed (mf/with-memo [page frame size]
objects-not-fixed (mf/with-memo [not-fixed-ids page frame size delta]
(calculate-objects not-fixed-ids))
all-objects (mf/with-memo [objects-fixed objects-not-fixed]
(merge objects-fixed objects-not-fixed))
wrapper-fixed (mf/with-memo [page frame size]
(shapes/frame-container-factory objects-fixed all-objects))
wrapper-not-fixed (mf/with-memo [objects-not-fixed]
(shapes/frame-container-factory objects-not-fixed))
(shapes/frame-container-factory objects-not-fixed all-objects))
;; Retrieve frames again with correct modifier
frame (get objects-not-fixed (:id frame))
base (get objects-not-fixed (:id base))
frame (get all-objects (:id frame))
base (get all-objects (:id base))
non-delay-interactions (->> (:interactions frame)
(filterv #(not= (:event-type %) :after-delay)))
@ -121,6 +129,7 @@
mode (h/use-equal-memo (unchecked-get props "interactions-mode"))
offset (h/use-equal-memo (unchecked-get props "frame-offset"))
size (h/use-equal-memo (unchecked-get props "size"))
delta (unchecked-get props "delta")
page (unchecked-get props "page")
frame (unchecked-get props "frame")
@ -163,7 +172,8 @@
:frame frame
:base base
:offset offset
:size size}]))
:size size
:delta delta}]))
(mf/defc flows-menu
{::mf/wrap [mf/memo]}

View file

@ -59,19 +59,20 @@
:open-overlay
(let [dest-frame-id (:destination interaction)
viewer-objects (deref (refs/get-viewer-objects))
dest-frame (get viewer-objects dest-frame-id)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(:id shape) ;; manual interactions are allways from "self"
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
(:frame-id shape)
(:id shape))
(:position-relative-to interaction))
relative-to-shape (or (get objects relative-to-id) base-frame)
close-click-outside (:close-click-outside interaction)
background-overlay (:background-overlay interaction)
overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
position (ctsi/calc-overlay-position interaction
[position snap-to] (ctsi/calc-overlay-position interaction
shape
viewer-objects
objects
relative-to-shape
relative-to-base-frame
dest-frame
@ -79,20 +80,23 @@
(when dest-frame-id
(st/emit! (dv/open-overlay dest-frame-id
position
snap-to
close-click-outside
background-overlay
(:animation interaction)))))
:toggle-overlay
(let [frame-id (:destination interaction)
dest-frame (get objects frame-id)
(let [dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(:id shape) ;; manual interactions are allways from "self"
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
(:frame-id shape)
(:id shape))
(:position-relative-to interaction))
relative-to-shape (or (get objects relative-to-id) base-frame)
overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
position (ctsi/calc-overlay-position interaction
[position snap-to] (ctsi/calc-overlay-position interaction
shape
objects
relative-to-shape
@ -102,19 +106,21 @@
close-click-outside (:close-click-outside interaction)
background-overlay (:background-overlay interaction)]
(when frame-id
(st/emit! (dv/toggle-overlay frame-id
(when dest-frame-id
(st/emit! (dv/toggle-overlay dest-frame-id
position
snap-to
close-click-outside
background-overlay
(:animation interaction)))))
:close-overlay
(let [frame-id (or (:destination interaction)
(if (= (:type shape) :frame)
(:id shape)
(:frame-id shape)))]
(st/emit! (dv/close-overlay frame-id (:animation interaction))))
(let [dest-frame-id (or (:destination interaction)
(if (and (= (:type shape) :frame)
(some #(= (:id %) (:id shape)) overlays))
(:id shape)
(:frame-id shape)))]
(st/emit! (dv/close-overlay dest-frame-id (:animation interaction))))
:prev-screen
(st/emit! (rt/nav-back-local))
@ -136,29 +142,49 @@
(st/emit! (dv/close-overlay frame-id)))
:toggle-overlay
(let [frame-id (:destination interaction)
position (:overlay-position interaction)
close-click-outside (:close-click-outside interaction)
background-overlay (:background-overlay interaction)]
(when frame-id
(st/emit! (dv/toggle-overlay frame-id
(let [dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
(:frame-id shape)
(:id shape))
(:position-relative-to interaction))
relative-to-shape (or (get objects relative-to-id) base-frame)
overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
[position snap-to] (ctsi/calc-overlay-position interaction
shape
objects
relative-to-shape
relative-to-base-frame
dest-frame
frame-offset)
close-click-outside (:close-click-outside interaction)
background-overlay (:background-overlay interaction)]
(when dest-frame-id
(st/emit! (dv/toggle-overlay dest-frame-id
position
snap-to
close-click-outside
background-overlay
(:animation interaction)))))
:close-overlay
(let [dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(:id shape) ;; manual interactions are allways from "self"
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
(:frame-id shape)
(:id shape))
(:position-relative-to interaction))
relative-to-shape (or (get objects relative-to-id) base-frame)
close-click-outside (:close-click-outside interaction)
background-overlay (:background-overlay interaction)
overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
position (ctsi/calc-overlay-position interaction
[position snap-to] (ctsi/calc-overlay-position interaction
shape
objects
relative-to-shape
@ -168,6 +194,7 @@
(when dest-frame-id
(st/emit! (dv/open-overlay dest-frame-id
position
snap-to
close-click-outside
background-overlay
(:animation interaction)))))
@ -258,6 +285,7 @@
childs (unchecked-get props "childs")
frame (unchecked-get props "frame")
objects (unchecked-get props "objects")
all-objects (or (unchecked-get props "all-objects") objects)
base-frame (mf/use-ctx base-frame-ctx)
frame-offset (mf/use-ctx frame-offset-ctx)
interactions-show? (mf/deref viewer-interactions-show?)
@ -266,22 +294,25 @@
svg-element? (and (= :svg-raw (:type shape))
(not= :svg (get-in shape [:content :tag])))
;; The objects parameter has the shapes that we must draw. It may be a subset of
;; all-objects in some cases (e.g. if there are fixed elements). But for interactions
;; handling we need access to all objects inside the page.
on-pointer-down
(mf/use-fn (mf/deps shape base-frame frame-offset objects)
#(on-pointer-down % shape base-frame frame-offset objects overlays))
(mf/use-fn (mf/deps shape base-frame frame-offset all-objects)
#(on-pointer-down % shape base-frame frame-offset all-objects overlays))
on-pointer-up
(mf/use-fn (mf/deps shape base-frame frame-offset objects)
#(on-pointer-up % shape base-frame frame-offset objects overlays))
(mf/use-fn (mf/deps shape base-frame frame-offset all-objects)
#(on-pointer-up % shape base-frame frame-offset all-objects overlays))
on-pointer-enter
(mf/use-fn (mf/deps shape base-frame frame-offset objects)
#(on-pointer-enter % shape base-frame frame-offset objects overlays))
(mf/use-fn (mf/deps shape base-frame frame-offset all-objects)
#(on-pointer-enter % shape base-frame frame-offset all-objects overlays))
on-pointer-leave
(mf/use-fn (mf/deps shape base-frame frame-offset objects)
#(on-pointer-leave % shape base-frame frame-offset objects overlays))]
(mf/use-fn (mf/deps shape base-frame frame-offset all-objects)
#(on-pointer-leave % shape base-frame frame-offset all-objects overlays))]
(mf/with-effect []
(let [sems (on-load shape base-frame frame-offset objects overlays)]
@ -350,8 +381,8 @@
(declare shape-container-factory)
(defn frame-container-factory
[objects]
(let [shape-container (shape-container-factory objects)
[objects all-objects]
(let [shape-container (shape-container-factory objects all-objects)
frame-wrapper (frame-wrapper shape-container)]
(mf/fnc frame-container
{::mf/wrap-props false}
@ -361,13 +392,14 @@
props (obj/merge! #js {} props
#js {:shape shape
:childs childs
:objects objects})]
:objects objects
:all-objects all-objects})]
[:> frame-wrapper props]))))
(defn group-container-factory
[objects]
(let [shape-container (shape-container-factory objects)
[objects all-objects]
(let [shape-container (shape-container-factory objects all-objects)
group-wrapper (group-wrapper shape-container)]
(mf/fnc group-container
{::mf/wrap-props false}
@ -380,8 +412,8 @@
[:> group-wrapper props])))))
(defn bool-container-factory
[objects]
(let [shape-container (shape-container-factory objects)
[objects all-objects]
(let [shape-container (shape-container-factory objects all-objects)
bool-wrapper (bool-wrapper shape-container)]
(mf/fnc bool-container
{::mf/wrap-props false}
@ -394,8 +426,8 @@
[:> bool-wrapper props]))))
(defn svg-raw-container-factory
[objects]
(let [shape-container (shape-container-factory objects)
[objects all-objects]
(let [shape-container (shape-container-factory objects all-objects)
svg-raw-wrapper (svg-raw-wrapper shape-container)]
(mf/fnc svg-raw-container
{::mf/wrap-props false}
@ -407,7 +439,7 @@
[:> svg-raw-wrapper props]))))
(defn shape-container-factory
[objects]
[objects all-objects]
(let [path-wrapper (path-wrapper)
text-wrapper (text-wrapper)
rect-wrapper (rect-wrapper)
@ -422,26 +454,27 @@
group-container
(mf/with-memo [objects]
(group-container-factory objects))
(group-container-factory objects all-objects))
frame-container
(mf/with-memo [objects]
(frame-container-factory objects))
(frame-container-factory objects all-objects))
bool-container
(mf/with-memo [objects]
(bool-container-factory objects))
(bool-container-factory objects all-objects))
svg-raw-container
(mf/with-memo [objects]
(svg-raw-container-factory objects))]
(svg-raw-container-factory objects all-objects))]
(when (and shape (not (:hidden shape)))
(let [shape (-> shape
#_(gsh/transform-shape)
(gsh/translate-to-frame frame))
opts #js {:shape shape
:objects objects}]
:objects objects
:all-objects all-objects}]
(case (:type shape)
:frame [:> frame-container opts]
:text [:> text-wrapper opts]