mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 18:48:37 -05:00
Merge pull request #1237 from penpot/complex-interactions3
Complex interactions3
This commit is contained in:
commit
20036bd72b
9 changed files with 274 additions and 72 deletions
|
@ -17,8 +17,8 @@
|
||||||
;; -- Options depending on event type
|
;; -- Options depending on event type
|
||||||
|
|
||||||
(s/def ::event-type #{:click
|
(s/def ::event-type #{:click
|
||||||
:mouse-over
|
|
||||||
:mouse-press
|
:mouse-press
|
||||||
|
:mouse-over
|
||||||
:mouse-enter
|
:mouse-enter
|
||||||
:mouse-leave
|
:mouse-leave
|
||||||
:after-delay})
|
:after-delay})
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
(s/def ::action-type #{:navigate
|
(s/def ::action-type #{:navigate
|
||||||
:open-overlay
|
:open-overlay
|
||||||
|
:toggle-overlay
|
||||||
:close-overlay
|
:close-overlay
|
||||||
:prev-screen
|
:prev-screen
|
||||||
:open-url})
|
:open-url})
|
||||||
|
@ -70,6 +71,13 @@
|
||||||
:opt-un [::close-click-outside
|
:opt-un [::close-click-outside
|
||||||
::background-overlay]))
|
::background-overlay]))
|
||||||
|
|
||||||
|
(defmethod action-opts-spec :toggle-overlay [_]
|
||||||
|
(s/keys :req-un [::destination
|
||||||
|
::overlay-position
|
||||||
|
::overlay-pos-type]
|
||||||
|
:opt-un [::close-click-outside
|
||||||
|
::background-overlay]))
|
||||||
|
|
||||||
(defmethod action-opts-spec :close-overlay [_]
|
(defmethod action-opts-spec :close-overlay [_]
|
||||||
(s/keys :req-un [::destination]))
|
(s/keys :req-un [::destination]))
|
||||||
|
|
||||||
|
@ -103,7 +111,7 @@
|
||||||
|
|
||||||
(def default-delay 100)
|
(def default-delay 100)
|
||||||
|
|
||||||
;; -- Helpers
|
;; -- Helpers for interaction
|
||||||
|
|
||||||
(declare calc-overlay-position)
|
(declare calc-overlay-position)
|
||||||
|
|
||||||
|
@ -137,7 +145,7 @@
|
||||||
:action-type action-type
|
:action-type action-type
|
||||||
:destination (get interaction :destination))
|
:destination (get interaction :destination))
|
||||||
|
|
||||||
:open-overlay
|
(:open-overlay :toggle-overlay)
|
||||||
(let [destination (get interaction :destination)
|
(let [destination (get interaction :destination)
|
||||||
overlay-pos-type (get interaction :overlay-pos-type :center)
|
overlay-pos-type (get interaction :overlay-pos-type :center)
|
||||||
overlay-position (get interaction
|
overlay-position (get interaction
|
||||||
|
@ -174,12 +182,13 @@
|
||||||
(us/verify ::destination destination)
|
(us/verify ::destination destination)
|
||||||
(assert (or (nil? destination)
|
(assert (or (nil? destination)
|
||||||
(some? (get objects destination))))
|
(some? (get objects destination))))
|
||||||
(assert #(:navigate :open-overlay :close-overlay) (:action-type interaction))
|
(assert (#{:navigate :open-overlay :toggle-overlay :close-overlay} (:action-type interaction)))
|
||||||
(cond-> interaction
|
(cond-> interaction
|
||||||
:always
|
:always
|
||||||
(assoc :destination destination)
|
(assoc :destination destination)
|
||||||
|
|
||||||
(= (:action-type interaction) :open-overlay)
|
(or (= (:action-type interaction) :open-overlay)
|
||||||
|
(= (:action-type interaction) :toggle-overlay))
|
||||||
(assoc :overlay-pos-type :center
|
(assoc :overlay-pos-type :center
|
||||||
:overlay-position (calc-overlay-position destination
|
:overlay-position (calc-overlay-position destination
|
||||||
interaction
|
interaction
|
||||||
|
@ -191,7 +200,7 @@
|
||||||
[interaction overlay-pos-type shape objects]
|
[interaction overlay-pos-type shape objects]
|
||||||
(us/verify ::interaction interaction)
|
(us/verify ::interaction interaction)
|
||||||
(us/verify ::overlay-pos-type overlay-pos-type)
|
(us/verify ::overlay-pos-type overlay-pos-type)
|
||||||
(assert #(= :open-overlay (:action-type interaction)))
|
(assert (#{:open-overlay :toggle-overlay} (:action-type interaction)))
|
||||||
(assoc interaction
|
(assoc interaction
|
||||||
:overlay-pos-type overlay-pos-type
|
:overlay-pos-type overlay-pos-type
|
||||||
:overlay-position (calc-overlay-position (:destination interaction)
|
:overlay-position (calc-overlay-position (:destination interaction)
|
||||||
|
@ -204,7 +213,7 @@
|
||||||
[interaction overlay-pos-type shape objects]
|
[interaction overlay-pos-type shape objects]
|
||||||
(us/verify ::interaction interaction)
|
(us/verify ::interaction interaction)
|
||||||
(us/verify ::overlay-pos-type overlay-pos-type)
|
(us/verify ::overlay-pos-type overlay-pos-type)
|
||||||
(assert #(= :open-overlay (:action-type interaction)))
|
(assert (#{:open-overlay :toggle-overlay} (:action-type interaction)))
|
||||||
(let [new-pos-type (if (= (:overlay-pos-type interaction) overlay-pos-type)
|
(let [new-pos-type (if (= (:overlay-pos-type interaction) overlay-pos-type)
|
||||||
:manual
|
:manual
|
||||||
overlay-pos-type)]
|
overlay-pos-type)]
|
||||||
|
@ -220,7 +229,7 @@
|
||||||
[interaction overlay-position]
|
[interaction overlay-position]
|
||||||
(us/verify ::interaction interaction)
|
(us/verify ::interaction interaction)
|
||||||
(us/verify ::overlay-position overlay-position)
|
(us/verify ::overlay-position overlay-position)
|
||||||
(assert #(= :open-overlay (:action-type interaction)))
|
(assert (#{:open-overlay :toggle-overlay} (:action-type interaction)))
|
||||||
(assoc interaction
|
(assoc interaction
|
||||||
:overlay-pos-type :manual
|
:overlay-pos-type :manual
|
||||||
:overlay-position overlay-position))
|
:overlay-position overlay-position))
|
||||||
|
@ -229,14 +238,14 @@
|
||||||
[interaction close-click-outside]
|
[interaction close-click-outside]
|
||||||
(us/verify ::interaction interaction)
|
(us/verify ::interaction interaction)
|
||||||
(us/verify ::us/boolean close-click-outside)
|
(us/verify ::us/boolean close-click-outside)
|
||||||
(assert #(= :open-overlay (:action-type interaction)))
|
(assert (#{:open-overlay :toggle-overlay} (:action-type interaction)))
|
||||||
(assoc interaction :close-click-outside close-click-outside))
|
(assoc interaction :close-click-outside close-click-outside))
|
||||||
|
|
||||||
(defn set-background-overlay
|
(defn set-background-overlay
|
||||||
[interaction background-overlay]
|
[interaction background-overlay]
|
||||||
(us/verify ::interaction interaction)
|
(us/verify ::interaction interaction)
|
||||||
(us/verify ::us/boolean background-overlay)
|
(us/verify ::us/boolean background-overlay)
|
||||||
(assert #(= :open-overlay (:action-type interaction)))
|
(assert (#{:open-overlay :toggle-overlay} (:action-type interaction)))
|
||||||
(assoc interaction :background-overlay background-overlay))
|
(assoc interaction :background-overlay background-overlay))
|
||||||
|
|
||||||
(defn- calc-overlay-position
|
(defn- calc-overlay-position
|
||||||
|
@ -281,3 +290,10 @@
|
||||||
:manual
|
:manual
|
||||||
(:overlay-position interaction)))))
|
(:overlay-position interaction)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; -- Helpers for interactions
|
||||||
|
|
||||||
|
(defn actionable?
|
||||||
|
[interactions]
|
||||||
|
(some #(= (:event-type %) :click) interactions))
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,10 @@
|
||||||
(defn go-to-frame-by-index
|
(defn go-to-frame-by-index
|
||||||
[index]
|
[index]
|
||||||
(ptk/reify ::go-to-frame-by-index
|
(ptk/reify ::go-to-frame-by-index
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:viewer-local :overlays] []))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [route (:route state)
|
||||||
|
@ -304,6 +308,10 @@
|
||||||
[frame-id]
|
[frame-id]
|
||||||
(us/verify ::us/uuid frame-id)
|
(us/verify ::us/uuid frame-id)
|
||||||
(ptk/reify ::go-to-frame
|
(ptk/reify ::go-to-frame
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:viewer-local :overlays] []))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [route (:route state)
|
||||||
|
@ -318,6 +326,10 @@
|
||||||
(defn go-to-section
|
(defn go-to-section
|
||||||
[section]
|
[section]
|
||||||
(ptk/reify ::go-to-section
|
(ptk/reify ::go-to-section
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:viewer-local :overlays] []))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [route (:route state)
|
||||||
|
@ -342,7 +354,7 @@
|
||||||
frames (get-in state [:viewer :pages page-id :frames])
|
frames (get-in state [:viewer :pages page-id :frames])
|
||||||
frame (d/seek #(= (:id %) frame-id) frames)
|
frame (d/seek #(= (:id %) frame-id) frames)
|
||||||
overlays (get-in state [:viewer-local :overlays])]
|
overlays (get-in state [:viewer-local :overlays])]
|
||||||
(if-not (some #(= % frame) overlays)
|
(if-not (some #(= (:frame %) frame) overlays)
|
||||||
(update-in state [:viewer-local :overlays] conj
|
(update-in state [:viewer-local :overlays] conj
|
||||||
{:frame frame
|
{:frame frame
|
||||||
:position position
|
:position position
|
||||||
|
@ -350,6 +362,31 @@
|
||||||
:background-overlay background-overlay})
|
:background-overlay background-overlay})
|
||||||
state)))))
|
state)))))
|
||||||
|
|
||||||
|
(defn toggle-overlay
|
||||||
|
[frame-id position close-click-outside background-overlay]
|
||||||
|
(us/verify ::us/uuid frame-id)
|
||||||
|
(us/verify ::us/point position)
|
||||||
|
(us/verify (s/nilable ::us/boolean) close-click-outside)
|
||||||
|
(us/verify (s/nilable ::us/boolean) background-overlay)
|
||||||
|
(ptk/reify ::toggle-overlay
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [route (:route state)
|
||||||
|
qparams (:query-params route)
|
||||||
|
page-id (:page-id qparams)
|
||||||
|
frames (get-in state [:viewer :pages page-id :frames])
|
||||||
|
frame (d/seek #(= (:id %) frame-id) frames)
|
||||||
|
overlays (get-in state [:viewer-local :overlays])]
|
||||||
|
(if-not (some #(= (:frame %) frame) overlays)
|
||||||
|
(update-in state [:viewer-local :overlays] conj
|
||||||
|
{:frame frame
|
||||||
|
:position position
|
||||||
|
:close-click-outside close-click-outside
|
||||||
|
:background-overlay background-overlay})
|
||||||
|
(update-in state [:viewer-local :overlays]
|
||||||
|
(fn [overlays]
|
||||||
|
(remove #(= (:id (:frame %)) frame-id) overlays))))))))
|
||||||
|
|
||||||
(defn close-overlay
|
(defn close-overlay
|
||||||
[frame-id]
|
[frame-id]
|
||||||
(ptk/reify ::close-overlay
|
(ptk/reify ::close-overlay
|
||||||
|
@ -448,6 +485,10 @@
|
||||||
(defn go-to-page
|
(defn go-to-page
|
||||||
[page-id]
|
[page-id]
|
||||||
(ptk/reify ::go-to-page
|
(ptk/reify ::go-to-page
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:viewer-local :overlays] []))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [route (:route state)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as geom]
|
[app.common.geom.shapes :as geom]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
|
[app.common.types.interactions :as cti]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.shapes.circle :as circle]
|
[app.main.ui.shapes.circle :as circle]
|
||||||
|
@ -27,35 +28,119 @@
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(defn on-mouse-down
|
(defn activate-interaction
|
||||||
[event shape]
|
[interaction shape]
|
||||||
(doseq [interaction (->> (:interactions shape)
|
(case (:action-type interaction)
|
||||||
(filter #(= (:event-type %) :click)))]
|
:navigate
|
||||||
|
(when-let [frame-id (:destination interaction)]
|
||||||
|
(st/emit! (dv/go-to-frame frame-id)))
|
||||||
|
|
||||||
(case (:action-type interaction)
|
:open-overlay
|
||||||
:navigate
|
(let [frame-id (:destination interaction)
|
||||||
(let [frame-id (:destination interaction)]
|
position (:overlay-position interaction)
|
||||||
(dom/stop-propagation event)
|
close-click-outside (:close-click-outside interaction)
|
||||||
(st/emit! (dv/go-to-frame frame-id)))
|
background-overlay (:background-overlay interaction)]
|
||||||
|
(when frame-id
|
||||||
:open-overlay
|
|
||||||
(let [frame-id (:destination interaction)
|
|
||||||
position (:overlay-position interaction)
|
|
||||||
close-click-outside (:close-click-outside interaction)
|
|
||||||
background-overlay (:background-overlay interaction)]
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(st/emit! (dv/open-overlay frame-id
|
(st/emit! (dv/open-overlay frame-id
|
||||||
position
|
position
|
||||||
close-click-outside
|
close-click-outside
|
||||||
background-overlay)))
|
background-overlay))))
|
||||||
|
|
||||||
:close-overlay
|
:toggle-overlay
|
||||||
(let [frame-id (or (:destination interaction)
|
(let [frame-id (:destination interaction)
|
||||||
(:frame-id shape))]
|
position (:overlay-position interaction)
|
||||||
(dom/stop-propagation event)
|
close-click-outside (:close-click-outside interaction)
|
||||||
(st/emit! (dv/close-overlay frame-id)))
|
background-overlay (:background-overlay interaction)]
|
||||||
|
(when frame-id
|
||||||
|
(st/emit! (dv/toggle-overlay frame-id
|
||||||
|
position
|
||||||
|
close-click-outside
|
||||||
|
background-overlay))))
|
||||||
|
|
||||||
nil)))
|
:close-overlay
|
||||||
|
(let [frame-id (or (:destination interaction)
|
||||||
|
(if (= (:type shape) :frame)
|
||||||
|
(:id shape)
|
||||||
|
(:frame-id shape)))]
|
||||||
|
(st/emit! (dv/close-overlay frame-id)))
|
||||||
|
|
||||||
|
nil))
|
||||||
|
|
||||||
|
;; Perform the opposite action of an interaction, if possible
|
||||||
|
(defn deactivate-interaction
|
||||||
|
[interaction shape]
|
||||||
|
(case (:action-type interaction)
|
||||||
|
:open-overlay
|
||||||
|
(let [frame-id (or (:destination interaction)
|
||||||
|
(if (= (:type shape) :frame)
|
||||||
|
(:id shape)
|
||||||
|
(:frame-id shape)))]
|
||||||
|
(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
|
||||||
|
position
|
||||||
|
close-click-outside
|
||||||
|
background-overlay))))
|
||||||
|
|
||||||
|
:close-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/open-overlay frame-id
|
||||||
|
position
|
||||||
|
close-click-outside
|
||||||
|
background-overlay))))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(defn on-mouse-down
|
||||||
|
[event shape]
|
||||||
|
(let [interactions (->> (:interactions shape)
|
||||||
|
(filter #(or (= (:event-type %) :click)
|
||||||
|
(= (:event-type %) :mouse-press))))]
|
||||||
|
(when (seq interactions)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(doseq [interaction interactions]
|
||||||
|
(activate-interaction interaction shape)))))
|
||||||
|
|
||||||
|
(defn on-mouse-up
|
||||||
|
[event shape]
|
||||||
|
(let [interactions (->> (:interactions shape)
|
||||||
|
(filter #(= (:event-type %) :mouse-press)))]
|
||||||
|
(when (seq interactions)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(doseq [interaction interactions]
|
||||||
|
(deactivate-interaction interaction shape)))))
|
||||||
|
|
||||||
|
(defn on-mouse-enter
|
||||||
|
[event shape]
|
||||||
|
(let [interactions (->> (:interactions shape)
|
||||||
|
(filter #(or (= (:event-type %) :mouse-enter)
|
||||||
|
(= (:event-type %) :mouse-over))))]
|
||||||
|
(when (seq interactions)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(doseq [interaction interactions]
|
||||||
|
(activate-interaction interaction shape)))))
|
||||||
|
|
||||||
|
(defn on-mouse-leave
|
||||||
|
[event shape]
|
||||||
|
(let [interactions (->> (:interactions shape)
|
||||||
|
(filter #(= (:event-type %) :mouse-leave)))
|
||||||
|
interactions-inv (->> (:interactions shape)
|
||||||
|
(filter #(= (:event-type %) :mouse-over)))]
|
||||||
|
(when (or (seq interactions) (seq interactions-inv))
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(doseq [interaction interactions]
|
||||||
|
(activate-interaction interaction shape))
|
||||||
|
(doseq [interaction interactions-inv]
|
||||||
|
(deactivate-interaction interaction shape)))))
|
||||||
|
|
||||||
(mf/defc interaction
|
(mf/defc interaction
|
||||||
[{:keys [shape interactions show-interactions?]}]
|
[{:keys [shape interactions show-interactions?]}]
|
||||||
|
@ -85,18 +170,16 @@
|
||||||
|
|
||||||
interactions (:interactions shape)
|
interactions (:interactions shape)
|
||||||
|
|
||||||
on-mouse-down (mf/use-callback
|
|
||||||
(mf/deps shape)
|
|
||||||
(fn [event]
|
|
||||||
(on-mouse-down event shape)))
|
|
||||||
|
|
||||||
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])))]
|
||||||
|
|
||||||
(if-not svg-element?
|
(if-not svg-element?
|
||||||
[:> shape-container {:shape shape
|
[:> shape-container {:shape shape
|
||||||
:cursor (when-not (empty? interactions) "pointer")
|
:cursor (when (cti/actionable? interactions) "pointer")
|
||||||
:on-mouse-down on-mouse-down}
|
:on-mouse-down #(on-mouse-down % shape)
|
||||||
|
:on-mouse-up #(on-mouse-up % shape)
|
||||||
|
:on-mouse-enter #(on-mouse-enter % shape)
|
||||||
|
:on-mouse-leave #(on-mouse-leave % shape)}
|
||||||
|
|
||||||
[:& component {:shape shape
|
[:& component {:shape shape
|
||||||
:frame frame
|
:frame frame
|
||||||
|
|
|
@ -21,7 +21,10 @@
|
||||||
(defn- event-type-names
|
(defn- event-type-names
|
||||||
[]
|
[]
|
||||||
{:click (tr "workspace.options.interaction-on-click")
|
{:click (tr "workspace.options.interaction-on-click")
|
||||||
:mouse-over (tr "workspace.options.interaction-while-hovering")})
|
:mouse-over (tr "workspace.options.interaction-while-hovering")
|
||||||
|
:mouse-press (tr "workspace.options.interaction-while-pressing")
|
||||||
|
:mouse-enter (tr "workspace.options.interaction-mouse-enter")
|
||||||
|
:mouse-leave (tr "workspace.options.interaction-mouse-leave")})
|
||||||
|
|
||||||
(defn- event-type-name
|
(defn- event-type-name
|
||||||
[interaction]
|
[interaction]
|
||||||
|
@ -31,6 +34,7 @@
|
||||||
[]
|
[]
|
||||||
{:navigate (tr "workspace.options.interaction-navigate-to")
|
{:navigate (tr "workspace.options.interaction-navigate-to")
|
||||||
:open-overlay (tr "workspace.options.interaction-open-overlay")
|
:open-overlay (tr "workspace.options.interaction-open-overlay")
|
||||||
|
:toggle-overlay (tr "workspace.options.interaction-toggle-overlay")
|
||||||
:close-overlay (tr "workspace.options.interaction-close-overlay")
|
:close-overlay (tr "workspace.options.interaction-close-overlay")
|
||||||
:prev-screen (tr "workspace.options.interaction-prev-screen")})
|
:prev-screen (tr "workspace.options.interaction-prev-screen")})
|
||||||
|
|
||||||
|
@ -41,6 +45,8 @@
|
||||||
(get destination :name (tr "workspace.options.interaction-none")))
|
(get destination :name (tr "workspace.options.interaction-none")))
|
||||||
:open-overlay (tr "workspace.options.interaction-open-overlay-dest"
|
:open-overlay (tr "workspace.options.interaction-open-overlay-dest"
|
||||||
(get destination :name (tr "workspace.options.interaction-none")))
|
(get destination :name (tr "workspace.options.interaction-none")))
|
||||||
|
:toggle-overlay (tr "workspace.options.interaction-toggle-overlay-dest"
|
||||||
|
(get destination :name (tr "workspace.options.interaction-none")))
|
||||||
:close-overlay (tr "workspace.options.interaction-close-overlay-dest"
|
:close-overlay (tr "workspace.options.interaction-close-overlay-dest"
|
||||||
(get destination :name (tr "workspace.options.interaction-self")))
|
(get destination :name (tr "workspace.options.interaction-self")))
|
||||||
"--"))
|
"--"))
|
||||||
|
@ -131,7 +137,7 @@
|
||||||
:on-change change-action-type}
|
:on-change change-action-type}
|
||||||
(for [[value name] (action-type-names)]
|
(for [[value name] (action-type-names)]
|
||||||
[:option {:value (str value)} name])]]
|
[:option {:value (str value)} name])]]
|
||||||
(when (#{:navigate :open-overlay :close-overlay} action-type)
|
(when (#{:navigate :open-overlay :toggle-overlay :close-overlay} action-type)
|
||||||
[:div.interactions-element
|
[:div.interactions-element
|
||||||
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
|
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
|
||||||
[:select.input-select
|
[:select.input-select
|
||||||
|
@ -142,7 +148,8 @@
|
||||||
(when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
|
(when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
|
||||||
(not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
|
(not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
|
||||||
[:option {:value (str (:id frame))} (:name frame)]))]])
|
[:option {:value (str (:id frame))} (:name frame)]))]])
|
||||||
(when (= action-type :open-overlay)
|
(when (or (= action-type :open-overlay)
|
||||||
|
(= action-type :toggle-overlay))
|
||||||
[:*
|
[:*
|
||||||
[:div.interactions-element
|
[:div.interactions-element
|
||||||
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
|
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
||||||
hover-ids (mf/use-state nil)
|
hover-ids (mf/use-state nil)
|
||||||
hover (mf/use-state nil)
|
hover (mf/use-state nil)
|
||||||
|
hover-disabled? (mf/use-state false)
|
||||||
frame-hover (mf/use-state nil)
|
frame-hover (mf/use-state nil)
|
||||||
active-frames (mf/use-state {})
|
active-frames (mf/use-state {})
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@
|
||||||
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? node-editing?)
|
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? node-editing?)
|
||||||
(hooks/setup-resize layout viewport-ref)
|
(hooks/setup-resize layout viewport-ref)
|
||||||
(hooks/setup-keyboard alt? ctrl? space?)
|
(hooks/setup-keyboard alt? ctrl? space?)
|
||||||
(hooks/setup-hover-shapes page-id move-stream objects transform selected ctrl? hover hover-ids zoom)
|
(hooks/setup-hover-shapes page-id move-stream objects transform selected ctrl? hover hover-ids @hover-disabled? zoom)
|
||||||
(hooks/setup-viewport-modifiers modifiers selected objects render-ref)
|
(hooks/setup-viewport-modifiers modifiers selected objects render-ref)
|
||||||
(hooks/setup-shortcuts node-editing? drawing-path?)
|
(hooks/setup-shortcuts node-editing? drawing-path?)
|
||||||
(hooks/setup-active-frames objects vbox hover active-frames)
|
(hooks/setup-active-frames objects vbox hover active-frames)
|
||||||
|
@ -320,7 +321,8 @@
|
||||||
|
|
||||||
(when show-prototypes?
|
(when show-prototypes?
|
||||||
[:& interactions/interactions
|
[:& interactions/interactions
|
||||||
{:selected selected}])
|
{:selected selected
|
||||||
|
:hover-disabled? hover-disabled?}])
|
||||||
|
|
||||||
(when show-selrect?
|
(when show-selrect?
|
||||||
[:& widgets/selection-rect {:data selrect
|
[:& widgets/selection-rect {:data selrect
|
||||||
|
|
|
@ -89,11 +89,12 @@
|
||||||
(hooks/use-stream ms/keyboard-ctrl #(reset! ctrl? %))
|
(hooks/use-stream ms/keyboard-ctrl #(reset! ctrl? %))
|
||||||
(hooks/use-stream ms/keyboard-space #(reset! space? %)))
|
(hooks/use-stream ms/keyboard-space #(reset! space? %)))
|
||||||
|
|
||||||
(defn setup-hover-shapes [page-id move-stream objects transform selected ctrl? hover hover-ids zoom]
|
(defn setup-hover-shapes [page-id move-stream objects transform selected ctrl? hover hover-ids hover-disabled? zoom]
|
||||||
(let [;; We use ref so we don't recreate the stream on a change
|
(let [;; We use ref so we don't recreate the stream on a change
|
||||||
zoom-ref (mf/use-ref zoom)
|
zoom-ref (mf/use-ref zoom)
|
||||||
transform-ref (mf/use-ref nil)
|
transform-ref (mf/use-ref nil)
|
||||||
selected-ref (mf/use-ref selected)
|
selected-ref (mf/use-ref selected)
|
||||||
|
hover-disabled-ref (mf/use-ref hover-disabled?)
|
||||||
|
|
||||||
query-point
|
query-point
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -101,21 +102,22 @@
|
||||||
(fn [point]
|
(fn [point]
|
||||||
(let [zoom (mf/ref-val zoom-ref)
|
(let [zoom (mf/ref-val zoom-ref)
|
||||||
rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))]
|
rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))]
|
||||||
(uw/ask-buffered!
|
(if (mf/ref-val hover-disabled-ref)
|
||||||
{:cmd :selection/query
|
(rx/of nil)
|
||||||
:page-id page-id
|
(uw/ask-buffered!
|
||||||
:rect rect
|
{:cmd :selection/query
|
||||||
:include-frames? true
|
:page-id page-id
|
||||||
:reverse? true})))) ;; we want the topmost shape to be selected first
|
:rect rect
|
||||||
|
:include-frames? true
|
||||||
|
:reverse? true}))))) ;; we want the topmost shape to be selected first
|
||||||
|
|
||||||
over-shapes-stream
|
over-shapes-stream
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(fn []
|
(fn []
|
||||||
(->> move-stream
|
(->> move-stream
|
||||||
;; When transforming shapes we stop querying the worker
|
;; When transforming shapes we stop querying the worker
|
||||||
(rx/filter #(not (some? (mf/ref-val transform-ref))))
|
(rx/filter #(not (some? (mf/ref-val transform-ref))))
|
||||||
(rx/switch-map query-point))))
|
(rx/switch-map query-point))))]
|
||||||
]
|
|
||||||
|
|
||||||
;; Refresh the refs on a value change
|
;; Refresh the refs on a value change
|
||||||
|
|
||||||
|
@ -131,6 +133,10 @@
|
||||||
(mf/deps selected)
|
(mf/deps selected)
|
||||||
#(mf/set-ref-val! selected-ref selected))
|
#(mf/set-ref-val! selected-ref selected))
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps hover-disabled?)
|
||||||
|
#(mf/set-ref-val! hover-disabled-ref hover-disabled?))
|
||||||
|
|
||||||
(hooks/use-stream
|
(hooks/use-stream
|
||||||
over-shapes-stream
|
over-shapes-stream
|
||||||
(mf/deps page-id objects @ctrl?)
|
(mf/deps page-id objects @ctrl?)
|
||||||
|
|
|
@ -84,27 +84,29 @@
|
||||||
[{:keys [x y stroke action-type arrow-dir zoom] :as props}]
|
[{:keys [x y stroke action-type arrow-dir zoom] :as props}]
|
||||||
(let [icon-pdata (case action-type
|
(let [icon-pdata (case action-type
|
||||||
:navigate (case arrow-dir
|
:navigate (case arrow-dir
|
||||||
:right "M -5 0 l 8 0 l -4 -4 m 4 4 l -4 4"
|
:right "M -6.5 0 l 12 0 l -6 -6 m 6 6 l -6 6"
|
||||||
:left "M 5 0 l -8 0 l 4 -4 m -4 4 l 4 4"
|
:left "M 6.5 0 l -12 0 l 6 -6 m -6 6 l 6 6"
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
:open-overlay "M-4 -4 h6 v6 h-6 z M2 -2 h2.5 v6.5 h-6.5 v-2.5"
|
:open-overlay "M-5 -5 h7 v7 h-7 z M2 -2 h3.5 v7 h-7 v-2.5"
|
||||||
|
|
||||||
:close-overlay "M -4 -4 L 4 4 M -4 4 L 4 -4"
|
:toggle-overlay "M-5 -5 h7 v7 h-7 z M2 -2 h3.5 v7 h-7 v-2.5"
|
||||||
|
|
||||||
|
:close-overlay "M -5 -5 L 5 5 M -5 5 L 5 -5"
|
||||||
|
|
||||||
nil)
|
nil)
|
||||||
inv-zoom (/ 1 zoom)]
|
inv-zoom (/ 1 zoom)]
|
||||||
[:*
|
[:*
|
||||||
[:circle {:cx 0
|
[:circle {:cx 0
|
||||||
:cy 0
|
:cy 0
|
||||||
:r (if (some? action-type) 8 4)
|
:r (if (some? action-type) 11 4)
|
||||||
:fill stroke
|
:fill stroke
|
||||||
:transform (str
|
:transform (str
|
||||||
"scale(" inv-zoom ", " inv-zoom ") "
|
"scale(" inv-zoom ", " inv-zoom ") "
|
||||||
"translate(" (* zoom x) ", " (* zoom y) ")")}]
|
"translate(" (* zoom x) ", " (* zoom y) ")")}]
|
||||||
(when icon-pdata
|
(when icon-pdata
|
||||||
[:path {:fill stroke
|
[:path {:fill stroke
|
||||||
:stroke-width 1
|
:stroke-width 2
|
||||||
:stroke "#FFFFFF"
|
:stroke "#FFFFFF"
|
||||||
:d icon-pdata
|
:d icon-pdata
|
||||||
:transform (str
|
:transform (str
|
||||||
|
@ -126,7 +128,7 @@
|
||||||
(connect-to-point orig-shape
|
(connect-to-point orig-shape
|
||||||
{:x (+ (:x2 (:selrect orig-shape)) 100)
|
{:x (+ (:x2 (:selrect orig-shape)) 100)
|
||||||
:y (+ (- (:y1 (:selrect orig-shape)) 50)
|
:y (+ (- (:y1 (:selrect orig-shape)) 50)
|
||||||
(* level 16))}))
|
(* level 32))}))
|
||||||
|
|
||||||
orig-dx (if (= orig-pos :right) 100 -100)
|
orig-dx (if (= orig-pos :right) 100 -100)
|
||||||
dest-dx (if (= dest-pos :right) 100 -100)
|
dest-dx (if (= dest-pos :right) 100 -100)
|
||||||
|
@ -192,7 +194,7 @@
|
||||||
|
|
||||||
|
|
||||||
(mf/defc overlay-marker
|
(mf/defc overlay-marker
|
||||||
[{:keys [index orig-shape dest-shape position objects] :as props}]
|
[{:keys [index orig-shape dest-shape position objects hover-disabled?] :as props}]
|
||||||
(let [start-move-position
|
(let [start-move-position
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(st/emit! (dw/start-move-overlay-pos index)))]
|
(st/emit! (dw/start-move-overlay-pos index)))]
|
||||||
|
@ -203,7 +205,9 @@
|
||||||
marker-y (+ (:y orig-frame) (:y position))
|
marker-y (+ (:y orig-frame) (:y position))
|
||||||
width (:width dest-shape)
|
width (:width dest-shape)
|
||||||
height (:height dest-shape)]
|
height (:height dest-shape)]
|
||||||
[:g {:on-mouse-down start-move-position}
|
[:g {:on-mouse-down start-move-position
|
||||||
|
:on-mouse-enter #(reset! hover-disabled? true)
|
||||||
|
:on-mouse-leave #(reset! hover-disabled? false)}
|
||||||
[:path {:stroke "#31EFB8"
|
[:path {:stroke "#31EFB8"
|
||||||
:fill "#000000"
|
:fill "#000000"
|
||||||
:fill-opacity 0.3
|
:fill-opacity 0.3
|
||||||
|
@ -223,7 +227,7 @@
|
||||||
]))))
|
]))))
|
||||||
|
|
||||||
(mf/defc interactions
|
(mf/defc interactions
|
||||||
[{:keys [selected] :as props}]
|
[{:keys [selected hover-disabled?] :as props}]
|
||||||
(let [local (mf/deref refs/workspace-local)
|
(let [local (mf/deref refs/workspace-local)
|
||||||
zoom (mf/deref refs/selected-zoom)
|
zoom (mf/deref refs/selected-zoom)
|
||||||
current-transform (:transform local)
|
current-transform (:transform local)
|
||||||
|
@ -286,7 +290,8 @@
|
||||||
:selected? true
|
:selected? true
|
||||||
:action-type (:action-type interaction)
|
:action-type (:action-type interaction)
|
||||||
:zoom zoom}]
|
:zoom zoom}]
|
||||||
(when (= (:action-type interaction) :open-overlay)
|
(when (or (= (:action-type interaction) :open-overlay)
|
||||||
|
(= (:action-type interaction) :toggle-overlay))
|
||||||
(if (and (some? move-overlay-to)
|
(if (and (some? move-overlay-to)
|
||||||
(= move-overlay-index index))
|
(= move-overlay-index index))
|
||||||
[:& overlay-marker {:key (str "pos" (:id shape) "-" index)
|
[:& overlay-marker {:key (str "pos" (:id shape) "-" index)
|
||||||
|
@ -294,13 +299,15 @@
|
||||||
:orig-shape shape
|
:orig-shape shape
|
||||||
:dest-shape dest-shape
|
:dest-shape dest-shape
|
||||||
:position move-overlay-to
|
:position move-overlay-to
|
||||||
:objects objects}]
|
:objects objects
|
||||||
|
:hover-disabled? hover-disabled?}]
|
||||||
[:& overlay-marker {:key (str "pos" (:id shape) "-" index)
|
[:& overlay-marker {:key (str "pos" (:id shape) "-" index)
|
||||||
:index index
|
:index index
|
||||||
:orig-shape shape
|
:orig-shape shape
|
||||||
:dest-shape dest-shape
|
:dest-shape dest-shape
|
||||||
:position (:overlay-position interaction)
|
:position (:overlay-position interaction)
|
||||||
:objects objects}]))])))
|
:objects objects
|
||||||
|
:hover-disabled? hover-disabled?}]))])))
|
||||||
(when (not (#{:move :rotate} current-transform))
|
(when (not (#{:move :rotate} current-transform))
|
||||||
[:& interaction-handle {:key (:id shape)
|
[:& interaction-handle {:key (:id shape)
|
||||||
:index nil
|
:index nil
|
||||||
|
|
|
@ -2425,6 +2425,14 @@ msgstr "Close overlay: %s"
|
||||||
msgid "workspace.options.interaction-destination"
|
msgid "workspace.options.interaction-destination"
|
||||||
msgstr "Destination"
|
msgstr "Destination"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-mouse-enter"
|
||||||
|
msgstr "Mouse enter"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-mouse-leave"
|
||||||
|
msgstr "Mouse leave"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-navigate-to"
|
msgid "workspace.options.interaction-navigate-to"
|
||||||
msgstr "Navigate to"
|
msgstr "Navigate to"
|
||||||
|
@ -2445,10 +2453,18 @@ msgstr "On Click"
|
||||||
msgid "workspace.options.interaction-open-overlay"
|
msgid "workspace.options.interaction-open-overlay"
|
||||||
msgstr "Open overlay"
|
msgstr "Open overlay"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-toggle-overlay"
|
||||||
|
msgstr "Toggle overlay"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-open-overlay-dest"
|
msgid "workspace.options.interaction-open-overlay-dest"
|
||||||
msgstr "Open overlay: %s"
|
msgstr "Open overlay: %s"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-toggle-overlay-dest"
|
||||||
|
msgstr "Toggle overlay: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-pos-manual"
|
msgid "workspace.options.interaction-pos-manual"
|
||||||
msgstr "Manual"
|
msgstr "Manual"
|
||||||
|
@ -2497,6 +2513,10 @@ msgstr "Trigger"
|
||||||
msgid "workspace.options.interaction-while-hovering"
|
msgid "workspace.options.interaction-while-hovering"
|
||||||
msgstr "While Hovering"
|
msgstr "While Hovering"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-while-pressing"
|
||||||
|
msgstr "While Pressing"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interactions"
|
msgid "workspace.options.interactions"
|
||||||
msgstr "Interactions"
|
msgstr "Interactions"
|
||||||
|
|
|
@ -2308,6 +2308,14 @@ msgstr "Close overlay: %s"
|
||||||
msgid "workspace.options.interaction-destination"
|
msgid "workspace.options.interaction-destination"
|
||||||
msgstr "Destino"
|
msgstr "Destino"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-mouse-enter"
|
||||||
|
msgstr "Mouse enter"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-mouse-leave"
|
||||||
|
msgstr "Mouse leave"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-navigate-to"
|
msgid "workspace.options.interaction-navigate-to"
|
||||||
msgstr "Navigate to"
|
msgstr "Navigate to"
|
||||||
|
@ -2328,10 +2336,18 @@ msgstr "On Click"
|
||||||
msgid "workspace.options.interaction-open-overlay"
|
msgid "workspace.options.interaction-open-overlay"
|
||||||
msgstr "Open overlay"
|
msgstr "Open overlay"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-toggle-overlay"
|
||||||
|
msgstr "Toggle overlay"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-open-overlay-dest"
|
msgid "workspace.options.interaction-open-overlay-dest"
|
||||||
msgstr "Open overlay: %s"
|
msgstr "Open overlay: %s"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-toggle-overlay-dest"
|
||||||
|
msgstr "Toggle overlay: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interaction-pos-manual"
|
msgid "workspace.options.interaction-pos-manual"
|
||||||
msgstr "Manual"
|
msgstr "Manual"
|
||||||
|
@ -2380,6 +2396,10 @@ msgstr "Trigger"
|
||||||
msgid "workspace.options.interaction-while-hovering"
|
msgid "workspace.options.interaction-while-hovering"
|
||||||
msgstr "While Hovering"
|
msgstr "While Hovering"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
|
msgid "workspace.options.interaction-while-pressing"
|
||||||
|
msgstr "While Pressing"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
|
||||||
msgid "workspace.options.interactions"
|
msgid "workspace.options.interactions"
|
||||||
msgstr "Interacciones"
|
msgstr "Interacciones"
|
||||||
|
|
Loading…
Add table
Reference in a new issue