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 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 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 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 ### :arrow_up: Deps updates
- Update google fonts catalog (at 2023/07/06) [Taiga #5592](https://tree.taiga.io/project/penpot/issue/5592) - 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 :else
(cph/reduce-objects (cph/reduce-objects
objects objects
(fn [shape] (fn [shape]
(and (d/not-empty? (:shapes shape)) (and (d/not-empty? (:shapes shape))
(or (not (cph/frame-shape? shape)) (or (not (cph/frame-shape? shape))

View file

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

View file

@ -324,209 +324,275 @@
interaction-rect (ctsi/set-position-relative-to interaction (:id rect))] interaction-rect (ctsi/set-position-relative-to interaction (:id rect))]
(t/testing "Overlay top-left relative to auto" (t/testing "Overlay top-left relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-left base-frame objects) (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 (= (: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" (t/testing "Overlay top-center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-center base-frame objects) (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 (= (: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" (t/testing "Overlay top-right relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-right base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-left relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-left base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-center base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-right relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-right base-frame objects) (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 (= (: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" (t/testing "Overlay center relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects) (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 (= (: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" (t/testing "Overlay manual relative to auto"
(let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects) (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 (= (: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" (t/testing "Overlay manual relative to auto"
(let [i2 (-> interaction-auto (let [i2 (-> interaction-auto
(ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62))) (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 (= (: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" (t/testing "Overlay top-left relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-left base-frame objects) (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 (= (: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" (t/testing "Overlay top-center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-center base-frame objects) (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 (= (: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" (t/testing "Overlay top-right relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-right base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-left relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-left base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-center base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-right relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-right base-frame objects) (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 (= (: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" (t/testing "Overlay center relative to base-frame"
(let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :center base-frame objects) (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 (= (: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" (t/testing "Overlay manual relative to base-frame"
(let [i2 (-> interaction-base-frame (let [i2 (-> interaction-base-frame
(ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62))) (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 (= (: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" (t/testing "Overlay top-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects) (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 (= (: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" (t/testing "Overlay top-center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-center base-frame objects) (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 (= (: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" (t/testing "Overlay top-right relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-right base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-left base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-center base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-right relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-right base-frame objects) (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 (= (: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" (t/testing "Overlay center relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :center base-frame objects) (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 (= (: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" (t/testing "Overlay manual relative to popup"
(let [i2 (-> interaction-popup (let [i2 (-> interaction-popup
(ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62))) (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 (= (: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" (t/testing "Overlay top-left relative to popup"
(let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects) (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 (= (: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" (t/testing "Overlay top-center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-center base-frame objects) (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 (= (: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" (t/testing "Overlay top-right relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-right base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-left relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-left base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-center base-frame objects) (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 (= (: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" (t/testing "Overlay bottom-right relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-right base-frame objects) (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 (= (: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" (t/testing "Overlay center relative to rect"
(let [i2 (ctsi/set-overlay-pos-type interaction-rect :center base-frame objects) (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 (= (: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" (t/testing "Overlay manual relative to rect"
(let [i2 (-> interaction-rect (let [i2 (-> interaction-rect
(ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-pos-type :manual base-frame objects)
(ctsi/set-overlay-position (gpt/point 12 62))) (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 (= (: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 (t/deftest animation-checks

View file

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

View file

@ -142,5 +142,6 @@
[:> frame-container props [:> frame-container props
[:g.frame-children {:opacity (:opacity shape)} [:g.frame-children {:opacity (:opacity shape)}
(for [item childs] (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)) (l/derived :viewer-overlays st/state))
(defn- calculate-size (defn- calculate-size
"Calculate the total size we must reserve for the frame, including possible paddings
added because shadows or blur."
[objects frame zoom] [objects frame zoom]
(let [{:keys [x y width height]} (gsb/get-object-bounds objects frame)] (let [{:keys [x y width height]} (gsb/get-object-bounds objects frame)]
{:base-width width {:base-width width
@ -60,6 +62,23 @@
:height (* height zoom) :height (* height zoom)
:vbox (dm/fmt "% % % %" 0 0 width height)})) :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 (defn- calculate-wrapper
[size1 size2 zoom] [size1 size2 zoom]
(cond (cond
@ -113,6 +132,10 @@
(mf/with-memo [page overlay zoom] (mf/with-memo [page overlay zoom]
(calculate-size (:objects page) (:frame 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 on-click
(mf/use-fn (mf/use-fn
(mf/deps overlay close-click-outside?) (mf/deps overlay close-click-outside?)
@ -145,6 +168,7 @@
:base-frame frame :base-frame frame
:frame-offset overlay-position :frame-offset overlay-position
:size size :size size
:delta delta
:page page :page page
:interactions-mode interactions-mode}]]])) :interactions-mode interactions-mode}]]]))

View file

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

View file

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

View file

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