0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-27 00:49:28 -05:00

🎉 Add delay interactions trigger

This commit is contained in:
Andrés Moya 2021-09-24 10:07:10 +02:00 committed by Alonso Torres
parent edefb588b6
commit ed380c86eb
7 changed files with 139 additions and 26 deletions

View file

@ -109,16 +109,18 @@
:action-type :navigate :action-type :navigate
:destination nil}) :destination nil})
(def default-delay 100) (def default-delay 600)
;; -- Helpers for interaction ;; -- Helpers for interaction
(declare calc-overlay-position) (declare calc-overlay-position)
(defn set-event-type (defn set-event-type
[interaction event-type] [interaction event-type shape]
(us/verify ::interaction interaction) (us/verify ::interaction interaction)
(us/verify ::event-type event-type) (us/verify ::event-type event-type)
(assert (or (not= event-type :after-delay)
(= (:type shape) :frame)))
(if (= (:event-type interaction) event-type) (if (= (:event-type interaction) event-type)
interaction interaction
(case event-type (case event-type
@ -176,6 +178,13 @@
:action-type action-type :action-type action-type
:url (get interaction :url ""))))) :url (get interaction :url "")))))
(defn set-delay
[interaction delay]
(us/verify ::interaction interaction)
(us/verify ::delay delay)
(assert (= (:event-type interaction) :after-delay))
(assoc interaction :delay delay))
(defn set-destination (defn set-destination
[interaction destination shape objects] [interaction destination shape objects]
(us/verify ::interaction interaction) (us/verify ::interaction interaction)

View file

@ -185,6 +185,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: $x-small; padding: $x-small;
width: 100%;
.input-text { .input-text {
background-color: $color-gray-50; background-color: $color-gray-50;
@ -219,6 +220,10 @@
color: $color-gray-60; color: $color-gray-60;
background: $color-white; background: $color-white;
font-size: $fs12; font-size: $fs12;
&:disabled {
color: $color-gray-20;
}
} }
} }
@ -253,7 +258,7 @@
width: 64px; width: 64px;
&.wide { &.wide {
width: 110px; min-width: 75px;
} }
} }
@ -441,6 +446,10 @@
color: $color-gray-60; color: $color-gray-60;
background: $color-white; background: $color-white;
font-size: $fs12; font-size: $fs12;
&:disabled {
color: $color-gray-20;
}
} }
} }

View file

@ -26,6 +26,7 @@
[app.main.ui.shapes.text :as text] [app.main.ui.shapes.text :as text]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.object :as obj] [app.util.object :as obj]
[app.util.timers :as tm]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(defn activate-interaction (defn activate-interaction
@ -142,6 +143,19 @@
(doseq [interaction interactions-inv] (doseq [interaction interactions-inv]
(deactivate-interaction interaction shape))))) (deactivate-interaction interaction shape)))))
(defn on-load
[shape]
(let [interactions (->> (:interactions shape)
(filter #(= (:event-type %) :after-delay)))]
(loop [interactions (seq interactions)
sems []]
(if-let [interaction (first interactions)]
(let [sem (tm/schedule (:delay interaction)
#(activate-interaction interaction shape))]
(recur (next interactions)
(conj sems sem)))
sems))))
(mf/defc interaction (mf/defc interaction
[{:keys [shape interactions show-interactions?]}] [{:keys [shape interactions show-interactions?]}]
(let [{:keys [x y width height]} (:selrect shape) (let [{:keys [x y width height]} (:selrect shape)
@ -173,6 +187,11 @@
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])))]
(mf/use-effect
(fn []
(let [sems (on-load shape)]
#(run! tm/dispose! sems))))
(if-not svg-element? (if-not svg-element?
[:> shape-container {:shape shape [:> shape-container {:shape shape
:cursor (when (cti/actionable? interactions) "pointer") :cursor (when (cti/actionable? interactions) "pointer")

View file

@ -13,6 +13,7 @@
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input]]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -21,10 +22,12 @@
(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") ; TODO: need more UX research
:mouse-press (tr "workspace.options.interaction-while-pressing") ;; :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-enter (tr "workspace.options.interaction-mouse-enter")
:mouse-leave (tr "workspace.options.interaction-mouse-leave")}) :mouse-leave (tr "workspace.options.interaction-mouse-leave")
:after-delay (tr "workspace.options.interaction-after-delay")})
(defn- event-type-name (defn- event-type-name
[interaction] [interaction]
@ -69,6 +72,7 @@
frames (mf/use-memo (mf/deps objects) frames (mf/use-memo (mf/deps objects)
#(cp/select-frames objects)) #(cp/select-frames objects))
event-type (:event-type interaction)
action-type (:action-type interaction) action-type (:action-type interaction)
overlay-pos-type (:overlay-pos-type interaction) overlay-pos-type (:overlay-pos-type interaction)
close-click-outside? (:close-click-outside interaction false) close-click-outside? (:close-click-outside interaction false)
@ -76,16 +80,25 @@
extended-open? (mf/use-state false) extended-open? (mf/use-state false)
ext-delay-ref (mf/use-ref nil)
select-text
(fn [ref] (fn [_] (dom/select-text! (mf/ref-val ref))))
change-event-type change-event-type
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/get-value d/read-string)] (let [value (-> event dom/get-target dom/get-value d/read-string)]
(update-interaction index #(cti/set-event-type % value)))) (update-interaction index #(cti/set-event-type % value shape))))
change-action-type change-action-type
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/get-value d/read-string)] (let [value (-> event dom/get-target dom/get-value d/read-string)]
(update-interaction index #(cti/set-action-type % value shape objects)))) (update-interaction index #(cti/set-action-type % value shape objects))))
change-delay
(fn [value]
(update-interaction index #(cti/set-delay % value)))
change-destination change-destination
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/get-value) (let [value (-> event dom/get-target dom/get-value)
@ -114,6 +127,8 @@
[:* [:*
[:div.element-set-options-group {:class (dom/classnames [:div.element-set-options-group {:class (dom/classnames
:open @extended-open?)} :open @extended-open?)}
; Summary
[:div.element-set-actions-button {:on-click #(swap! extended-open? not)} [:div.element-set-actions-button {:on-click #(swap! extended-open? not)}
i/actions] i/actions]
[:div.interactions-summary {:on-click #(swap! extended-open? not)} [:div.interactions-summary {:on-click #(swap! extended-open? not)}
@ -121,15 +136,34 @@
[:div.action-summary (action-summary interaction destination)]] [:div.action-summary (action-summary interaction destination)]]
[:div.elemen-set-actions {:on-click #(remove-interaction index)} [:div.elemen-set-actions {:on-click #(remove-interaction index)}
[:div.element-set-actions-button i/minus]] [:div.element-set-actions-button i/minus]]
(when @extended-open? (when @extended-open?
[:div.element-set-content [:div.element-set-content
; Trigger select
[:div.interactions-element.separator [:div.interactions-element.separator
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")] [:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")]
[:select.input-select [:select.input-select
{:value (str (:event-type interaction)) {:value (str (:event-type interaction))
:on-change change-event-type} :on-change change-event-type}
(for [[value name] (event-type-names)] (for [[value name] (event-type-names)]
[:option {:value (str value)} name])]] [:option {:value (str value)
:disabled (and (= value :after-delay)
(not= (:type shape) :frame))}
name])]]
; Delay
(when (= event-type :after-delay)
[:div.interactions-element
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-delay")]
[:div.input-element
[:> numeric-input {:ref ext-delay-ref
:on-click (select-text ext-delay-ref)
:on-change change-delay
:value (:delay interaction)}]
[:span.after (tr "workspace.options.interaction-ms")]]])
; Action select
[:div.interactions-element.separator [:div.interactions-element.separator
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")] [:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")]
[:select.input-select [:select.input-select
@ -137,6 +171,8 @@
: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])]]
; Destination
(when (#{:navigate :open-overlay :toggle-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")]
@ -148,9 +184,11 @@
(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 (or (= action-type :open-overlay) (when (or (= action-type :open-overlay)
(= action-type :toggle-overlay)) (= action-type :toggle-overlay))
[:* [:*
; Overlay position (select)
[: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")]
[:select.input-select [:select.input-select
@ -158,6 +196,8 @@
:on-change change-overlay-pos-type} :on-change change-overlay-pos-type}
(for [[value name] (overlay-pos-type-names)] (for [[value name] (overlay-pos-type-names)]
[:option {:value (str value)} name])]] [:option {:value (str value)} name])]]
; Overlay position (buttons)
[:div.interactions-element.interactions-pos-buttons [:div.interactions-element.interactions-pos-buttons
[:div.element-set-actions-button [:div.element-set-actions-button
{:class (dom/classnames :active (= overlay-pos-type :center)) {:class (dom/classnames :active (= overlay-pos-type :center))
@ -187,6 +227,8 @@
{:class (dom/classnames :active (= overlay-pos-type :bottom-center)) {:class (dom/classnames :active (= overlay-pos-type :bottom-center))
:on-click #(toggle-overlay-pos-type :bottom-center)} :on-click #(toggle-overlay-pos-type :bottom-center)}
i/position-bottom-center]] i/position-bottom-center]]
; Overlay click outside
[:div.interactions-element [:div.interactions-element
[:div.input-checkbox [:div.input-checkbox
[:input {:type "checkbox" [:input {:type "checkbox"
@ -195,6 +237,8 @@
:on-change change-close-click-outside}] :on-change change-close-click-outside}]
[:label {:for (str "close-" index)} [:label {:for (str "close-" index)}
(tr "workspace.options.interaction-close-outside")]]] (tr "workspace.options.interaction-close-outside")]]]
; Overlay background
[:div.interactions-element [:div.interactions-element
[:div.input-checkbox [:div.input-checkbox
[:input {:type "checkbox" [:input {:type "checkbox"

View file

@ -128,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 32))})) (/ (* level 32) zoom))}))
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)

View file

@ -2405,6 +2405,10 @@ msgstr "Click the + button to add interactions."
msgid "workspace.options.interaction-action" msgid "workspace.options.interaction-action"
msgstr "Action" msgstr "Action"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-after-delay"
msgstr "After delay"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-background" msgid "workspace.options.interaction-background"
msgstr "Add background overlay" msgstr "Add background overlay"
@ -2425,6 +2429,10 @@ 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-delay"
msgstr "Delay"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-mouse-enter" msgid "workspace.options.interaction-mouse-enter"
msgstr "Mouse enter" msgstr "Mouse enter"
@ -2433,6 +2441,10 @@ msgstr "Mouse enter"
msgid "workspace.options.interaction-mouse-leave" msgid "workspace.options.interaction-mouse-leave"
msgstr "Mouse leave" msgstr "Mouse leave"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-ms"
msgstr "ms"
#: 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"
@ -2443,7 +2455,7 @@ msgstr "Navigate to: %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-none" msgid "workspace.options.interaction-none"
msgstr "none" msgstr "(not set)"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-on-click" msgid "workspace.options.interaction-on-click"
@ -2453,6 +2465,10 @@ 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-prev-screen"
msgstr "Previous screen"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-toggle-overlay" msgid "workspace.options.interaction-toggle-overlay"
msgstr "Toggle overlay" msgstr "Toggle overlay"

View file

@ -2288,6 +2288,10 @@ msgstr "Pulsa el botón + para añadir interacciones."
msgid "workspace.options.interaction-action" msgid "workspace.options.interaction-action"
msgstr "Acción" msgstr "Acción"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-after-delay"
msgstr "Tiempo"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-background" msgid "workspace.options.interaction-background"
msgstr "Añadir sombreado de fondo" msgstr "Añadir sombreado de fondo"
@ -2298,55 +2302,67 @@ msgstr "Cerrar al pulsar fuera"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-close-overlay" msgid "workspace.options.interaction-close-overlay"
msgstr "Close overlay" msgstr "Cerrar superposición"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-close-overlay-dest" msgid "workspace.options.interaction-close-overlay-dest"
msgstr "Close overlay: %s" msgstr "Cerrar superposición: %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-destination" msgid "workspace.options.interaction-destination"
msgstr "Destino" msgstr "Destino"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-delay"
msgstr "Tiempo"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-mouse-enter" msgid "workspace.options.interaction-mouse-enter"
msgstr "Mouse enter" msgstr "Pasar encima"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-mouse-leave" msgid "workspace.options.interaction-mouse-leave"
msgstr "Mouse leave" msgstr "Retirar encima"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-ms"
msgstr "ms"
#: 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 "Navegar a"
#: 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-dest" msgid "workspace.options.interaction-navigate-to-dest"
msgstr "Navigate to: %s" msgstr "Navegar a: %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-none" msgid "workspace.options.interaction-none"
msgstr "none" msgstr "(sin definir)"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-on-click" msgid "workspace.options.interaction-on-click"
msgstr "On Click" msgstr "En click"
#: 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" msgid "workspace.options.interaction-open-overlay"
msgstr "Open overlay" msgstr "Superposición"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-prev-screen"
msgstr "Pantalla anterior"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-toggle-overlay" msgid "workspace.options.interaction-toggle-overlay"
msgstr "Toggle overlay" msgstr "Alternar superpos."
#: 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 "Superposición: %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-toggle-overlay-dest" msgid "workspace.options.interaction-toggle-overlay-dest"
msgstr "Toggle overlay: %s" msgstr "Alternar superpos.: %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"
@ -2386,19 +2402,19 @@ msgstr "Posición"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-self" msgid "workspace.options.interaction-self"
msgstr "self" msgstr "mismo"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-trigger" msgid "workspace.options.interaction-trigger"
msgstr "Trigger" msgstr "Disparador"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-while-hovering" msgid "workspace.options.interaction-while-hovering"
msgstr "While Hovering" msgstr "Mientras pasa encima"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-while-pressing" msgid "workspace.options.interaction-while-pressing"
msgstr "While Pressing" msgstr "Mientras pulsa"
#: 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"