🎉 Allow complex interactions

This commit is contained in:
Andrés Moya 2021-09-06 15:53:44 +02:00 committed by Andrey Antukh
parent 6c332b949b
commit c7252a950b
16 changed files with 306 additions and 159 deletions

View file

@ -109,7 +109,7 @@
:selected (d/ordered-set)
:expanded {}
:tooltip nil
:options-mode :design
:options-mode :prototype ; OJOOOOOOOOOOOOOOOOOOOOOO============== :design
:draw-interaction-to nil
:left-sidebar? true
:right-sidebar? true
@ -1804,16 +1804,19 @@
shape-id (-> state wsh/lookup-selected first)
shape (get objects shape-id)]
(when-not (= position initial-pos)
(if (and frame shape-id
(not= (:id frame) (:id shape))
(not= (:id frame) (:frame-id shape)))
(rx/of (update-shape shape-id
{:interactions [{:event-type :click
:action-type :navigate
:destination (:id frame)}]}))
(rx/of (update-shape shape-id
{:interactions []}))))))))
(when (and shape (not (= position initial-pos)))
(rx/of (dch/update-shapes [shape-id]
(fn [shape]
(update shape :interactions
(fn [interactions]
(if (and frame
(not= (:id frame) (:id shape))
(not= (:id frame) (:frame-id shape)))
(conj interactions
(assoc spec/default-interaction
:destination (:id frame)))
(vec (remove #(= (:action-type %) :navigate)
interactions)))))))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CANVAS OPTIONS

View file

@ -8,70 +8,148 @@
(:require
[app.common.data :as d]
[app.common.pages :as cp]
[app.common.pages.spec :as spec]
[app.common.uuid :as uuid]
[app.main.data.workspace :as dw]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.alpha :as mf]))
(mf/defc interactions-menu
[{:keys [shape] :as props}]
(let [objects (deref refs/workspace-page-objects)
interaction (first (:interactions shape)) ; TODO: in the
; future we may
; have several
; interactions in
; one shape
(defn- event-type-names
[]
{:click (tr "workspace.options.interaction-on-click")
:hover (tr "workspace.options.interaction-while-hovering")})
(defn- event-type-name
[interaction]
(get (event-type-names) (:event-type interaction) "--"))
(defn- action-type-names
[]
{:navigate (tr "workspace.options.interaction-navigate-to")
:open-overlay (tr "workspace.options.interaction-open-overlay")
:close-overlay (tr "workspace.options.interaction-close-overlay")})
(defn- action-summary
[interaction destination]
(case (:action-type interaction)
:navigate (tr "workspace.options.interaction-navigate-to-dest"
(get destination :name (tr "workspace.options.interaction-none")))
:open-overlay (tr "workspace.options.interaction-open-overlay-dest"
(get destination :name (tr "workspace.options.interaction-none")))
:close-overlay (tr "workspace.options.interaction-close-overlay-dest"
(get destination :name (tr "workspace.options.interaction-self")))
"--"))
(mf/defc interaction-entry
[{:keys [index shape interaction update-interaction remove-interaction]}]
(let [objects (deref refs/workspace-page-objects)
destination (get objects (:destination interaction))
frames (mf/use-memo (mf/deps objects)
#(cp/select-frames objects))
show-frames-dropdown? (mf/use-state false)
extended-open? (mf/use-state false)
on-set-blur #(reset! show-frames-dropdown? false)
on-navigate #(when destination
(st/emit! (dw/select-shapes (d/ordered-set (:id destination)))))
change-event-type
(fn [event]
(let [value (-> event dom/get-target dom/get-value d/read-string)]
(update-interaction index #(assoc % :event-type value))))
on-select-destination
(fn [dest]
(if (nil? dest)
(st/emit! (dw/update-shape (:id shape) {:interactions []}))
(st/emit! (dw/update-shape (:id shape) {:interactions [{:event-type :click
:action-type :navigate
:destination dest}]}))))]
change-action-type
(fn [event]
(let [value (-> event dom/get-target dom/get-value d/read-string)]
(update-interaction index #(assoc % :action-type value))))
(if (not shape)
[:*
[:div.interactions-help-icon i/interaction]
[:div.interactions-help (tr "workspace.options.select-a-shape")]
[:div.interactions-help-icon i/play]
[:div.interactions-help (tr "workspace.options.use-play-button")]]
[:div.element-set {:on-blur on-set-blur}
[:div.element-set-title
[:span (tr "workspace.options.navigate-to")]]
[:div.element-set-content
[:div.row-flex
[:div.custom-select.flex-grow {:on-click #(reset! show-frames-dropdown? true)}
(if destination
[:span (:name destination)]
[:span (tr "workspace.options.select-artboard")])
[:span.dropdown-button i/arrow-down]
[:& dropdown {:show @show-frames-dropdown?
:on-close #(reset! show-frames-dropdown? false)}
[:ul.custom-select-dropdown
[:li.dropdown-separator
{:on-click #(on-select-destination nil)}
(tr "workspace.options.none")]
change-destination
(fn [event]
(let [value (-> event dom/get-target dom/get-value)
value (when (not= value "") (uuid/uuid value))]
(update-interaction index #(assoc % :destination value))))]
[:*
[:div.element-set-options-group
[:div.element-set-actions-button {:on-click #(swap! extended-open? not)}
i/actions]
[:div.interactions-summary
[:div.trigger-name (event-type-name interaction)]
[:div.action-summary (action-summary interaction destination)]]
[:div.elemen-set-actions {:on-click #(remove-interaction index)}
[:div.element-set-actions-button i/minus]]]
(when @extended-open?
[:div.element-set
[:div.element-set-content
[:div.interactions-element
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")]
[:select.input-select
{:default-value (str (:event-type interaction))
:on-change change-event-type}
(for [[value name] (event-type-names)]
[:option {:value (str value)} name])]]
[:div.interactions-element
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")]
[:select.input-select
{:default-value (str (:action-type interaction))
:on-change change-action-type}
(for [[value name] (action-type-names)]
[:option {:value (str value)} name])]]
[:div.interactions-element
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
[:select.input-select
{:default-value (str (:destination interaction))
:on-change change-destination}
[:option {:value ""} (tr "workspace.options.interaction-none")]
(for [frame frames]
(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
[:li {:key (:id frame)
:on-click #(on-select-destination (:id frame))}
(:name frame)]))]]]
[:span.navigate-icon {:style {:visibility (when (not destination) "hidden")}
:on-click on-navigate} i/navigate]]]])))
[:option {:value (str (:id frame))} (:name frame)]))]]]])]))
(mf/defc interactions-menu
[{:keys [shape] :as props}]
(let [interactions (get shape :interactions [])
add-interaction
(fn [_]
(let [new-interactions
(conj interactions (update spec/default-interaction :event-type identity))]
(st/emit! (dw/update-shape (:id shape) {:interactions new-interactions}))))
remove-interaction
(fn [index]
(let [new-interactions
(into (subvec interactions 0 index)
(subvec interactions (inc index)))]
(st/emit! (dw/update-shape (:id shape) {:interactions new-interactions}))))
update-interaction
(fn [index update-fn]
(let [new-interactions (update interactions index update-fn)]
(st/emit! (dw/update-shape (:id shape) {:interactions new-interactions})))) ]
[:div.element-set
(when shape
[:div.element-set-title
[:span (tr "workspace.options.interactions")]
[:div.add-page {:on-click add-interaction}
i/plus]])
[:div.element-set-content
(when (= (count interactions) 0)
[:*
(when shape
[:*
[:div.interactions-help-icon i/plus]
[:div.interactions-help (tr "workspace.options.add-interaction")]])
[:div.interactions-help-icon i/interaction]
[:div.interactions-help (tr "workspace.options.select-a-shape")]
[:div.interactions-help-icon i/play]
[:div.interactions-help (tr "workspace.options.use-play-button")]])]
(for [[index interaction] (d/enumerate interactions)]
[:& interaction-entry {:index index
:shape shape
:interaction interaction
:update-interaction update-interaction
:remove-interaction remove-interaction}])]))