0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-13 00:01:51 -05:00

Add basic integration of interactions form.

Nothing working only the basic interactions of the
"interactions form".
This commit is contained in:
Andrey Antukh 2016-06-25 17:02:11 +03:00
parent 5e6b3e94da
commit 9e056709df
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95

View file

@ -6,82 +6,542 @@
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.sidebar.options.interactions
(:require [sablono.core :as html :refer-macros [html]]
(:require [sablono.core :refer-macros [html]]
[rum.core :as rum]
[lentes.core :as l]
[uxbox.locales :refer (tr)]
[uxbox.router :as r]
[uxbox.rstore :as rs]
[uxbox.state :as st]
[uxbox.library :as library]
[uxbox.data.shapes :as uds]
[uxbox.data.lightbox :as udl]
[uxbox.ui.icons :as i]
[uxbox.ui.mixins :as mx]
[uxbox.common.i18n :refer (tr)]
[uxbox.common.router :as r]
[uxbox.common.rstore :as rs]
[uxbox.common.ui.mixins :as mx]
[uxbox.main.state :as st]
[uxbox.main.library :as library]
[uxbox.main.data.shapes :as uds]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.ui.workspace.sidebar.sitemap :refer (pages-l)]
[uxbox.main.ui.icons :as i]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.main.ui.colorpicker :as cp]
[uxbox.util.dom :as dom]
[uxbox.util.data :refer (parse-int parse-float read-string)]))
;; --- Helpers
(defn- on-change
([form attr event]
(dom/prevent-default event)
(let [value (dom/event->value event)
value (read-string value)]
(swap! form assoc attr value)))
([form attr keep event]
(let [data (select-keys @form keep)]
(reset! form data)
(on-change form attr event))))
(def show-elements-input?
#{:show :hide :toggle :moveto :moveby
:opacity :size :color :rotate :scrolltoelement})
(def show-animation-input?
#{:show :hide :toggle})
(def show-only-easing-input?
(complement show-animation-input?))
;; --- Interactions List
(defn- interactions-list-render
[own]
(html
[:ul.element-list
[:li
[:div.list-icon i/action]
[:span "Hover"]
[:div.list-actions
[:a {:href "#"} i/pencil]
[:a {:href "#"} i/trash]]]
[:li
[:div.list-icon i/action]
[:span "Mouse in"]
[:div.list-actions
[:a {:href "#"} i/pencil]
[:a {:href "#"} i/trash]]]]))
(def interactions-list
(mx/component
{:render interactions-list-render
:name "interactions-list"
:mixins [mx/static]}))
;; --- Trigger Input
(defn- trigger-input-render
[own form-ref]
(when-not (:trigger @form-ref)
(swap! form-ref assoc :trigger :click))
(html
[:div
[:span "Trigger"]
[:div.row-flex
[:select.input-select {:placeholder "Choose a trigger"
:on-change (partial on-change form-ref :trigger)
:value (pr-str (:trigger @form-ref))}
[:option {:value ":click"} "Click"]
[:option {:value ":doubleclick"} "Double-click"]
[:option {:value ":rightclick"} "Right-click"]
[:option {:value ":hover"} "Hover"]
[:option {:value ":mousein"} "Mouse in"]
[:option {:value ":mousein"} "Mouse out"]
[:option {:value ":mousein"} "Swipe right"]
[:option {:value ":mousein"} "Swipe left"]
[:option {:value ":mousein"} "Swipe dpwn"]
[:option {:value ":mousein"} "Touch and hold"]
[:option {:value ":mousein"} "Hold release"]
[:option {:value ":keypress"} "Key press"]
[:option {:value ":pageisloaded"} "Page is loaded"]
[:option {:value ":windowscroll"} "Window is scrolled to"]]]]))
(def trigger-input
(mx/component
{:render trigger-input-render
:name "trigger-input"
:mixins [mx/static]}))
;; --- URL Input
(defn- url-input-render
[own form-ref]
(html
[:div
[:span "Url"]
[:div.row-flex
[:input.input-text
{:placeholder "http://"
:on-change (partial on-change form-ref :url)
:type "url"}]]]))
(def url-input
(mx/component
{:render url-input-render
:name "url-input"}))
;; --- Elements Input
(defn- collect-shapes
[state page]
(let [shapes-by-id (:shapes-by-id state)
shapes (get-in state [:pages-by-id page :shapes])]
(letfn [(resolve-shape [acc id]
(let [shape (get shapes-by-id id)]
(if (= (:type shape) :group)
(reduce resolve-shape (conj acc shape) (:items shape))
(conj acc shape))))]
(reduce resolve-shape [] shapes))))
(defn- elements-input-render
[own page form-ref]
(let [shapes (collect-shapes @st/state page)]
(html
[:div
[:span "Element"]
[:div.row-flex
[:select.input-select
{:placeholder "Choose an element"
:on-change (partial on-change form-ref :element)
:value (pr-str (:element @form-ref))}
[:option {:value "nil"} "---"]
(for [shape shapes
:let [key (pr-str (:id shape))]]
[:option {:key key :value key} (:name shape)])]]])))
(def elements-input
(mx/component
{:render elements-input-render
:name "elements-input"}))
;; --- Page Input
(defn- pages-input-render
[own form-ref path]
(let [pages @pages-l]
(when (and (not (:page @form-ref))
(pos? (count pages)))
(swap! form-ref assoc :page (:id (first pages))))
(html
[:div
[:span "Page"]
[:div.row-flex
[:select.input-select {:placeholder "Choose a page"
:on-change (partial on-change form-ref :page)
:value (pr-str (:page @form-ref))}
(for [page pages
:let [key (pr-str (:id page))]]
[:option {:key key :value key} (:name page)])]]])))
(def pages-input
(mx/component
{:render pages-input-render
:name "pages-input"}))
;; --- Animation
(defn- animation-input-render
[own form-ref]
(when-not (:action @form-ref)
(swap! form-ref assoc :animation :none))
(html
[:div
[:span "Animation"]
[:div.row-flex
[:select.input-select
{:placeholder "Animation"
:on-change (partial on-change form-ref :animation)
:value (pr-str (:animation @form-ref))}
[:option {:value ":none"} "None"]
[:option {:value ":fade"} "Fade"]
[:option {:value ":slide"} "Slide"]]]]))
(def animation-input
(mx/component
{:render animation-input-render
:name "animation-input"}))
;; --- MoveTo Input
(defn- moveto-input-render
[own form-ref]
(when-not (:moveto-x @form-ref)
(swap! form-ref assoc :moveto-x 0))
(when-not (:moveto-y @form-ref)
(swap! form-ref assoc :moveto-y 0))
(html
[:div
[:span "Move to position (px)"]
[:div.row-flex
[:input.input-text
{:placeholder "X"
:on-change (partial on-change form-ref :moveto-x)
:type "number"
:value (:moveto-x @form-ref)}]
[:input.input-text
{:placeholder "Y"
:on-change (partial on-change form-ref :moveto-y)
:type "number"
:value (:moveto-y @form-ref)}]]]))
(def moveto-input
(mx/component
{:render moveto-input-render
:name "moveto-input"}))
;; --- Opacity Input
(defn- opacity-input-render
[own form-ref]
(when-not (:opacity @form-ref)
(swap! form-ref assoc :opacity 100))
(html
[:div
[:span "Opacity (%)"]
[:div.row-flex
[:input.input-text
{:placeholder "%"
:on-change (partial on-change form-ref :opacity)
:min "0"
:max "100"
:type "number"
:value (:opacity @form-ref)}]]]))
(def opacity-input
(mx/component
{:render opacity-input-render
:name "opacity-input"}))
;; --- Rotate Input
(defn rotate-input-render
[own form-ref]
(html
[:div
[:span "Rotate (dg)"]
[:div.row-flex
[:input.input-text
{:placeholder "px"
:on-change (partial on-change form-ref :rotate)
:type "number"
:value ""}]]]))
(def rotate-input
(mx/component
{:render rotate-input-render
:name "rotate-input"}))
;; --- Resize Input
(defn- resize-input-render
[own form-ref]
(html
[:div
[:span "Resize (px)"]
[:div.row-flex
[:input.input-text
{:placeholder "Width"
:on-change (partial on-change form-ref :resize-width)
:type "number"
:value ""}]
[:input.input-text
{:placeholder "Height"
:on-change (partial on-change form-ref :resize-height)
:type "number"
:value ""}]]]))
(def resize-input
(mx/component
{:render resize-input-render
:name "resize-input"}))
;; --- Color Input
(defn- colorpicker-render
[own {:keys [x y on-change value]}]
(let [left (- x 260)
top (- y 50)]
(html
[:div.colorpicker-tooltip
{:style {:left (str left "px")
:top (str top "px")}}
(cp/colorpicker
:theme :small
:value value
:on-change on-change)])))
(def ^:private colorpicker
(mx/component
{:render colorpicker-render
:name "colorpicker"
:mixins [rum/reactive mx/static]}))
(defmethod lbx/render-lightbox :interactions/colorpicker
[params]
(colorpicker params))
(defn- color-input-render
[own form-ref]
(when-not (:fill-color @form-ref)
(swap! form-ref assoc :fill-color "#000000"))
(when-not (:stroke-color @form-ref)
(swap! form-ref assoc :stroke-color "#000000"))
(letfn [(on-change [attr color]
(swap! form-ref assoc attr color))
(show-picker [attr event]
(let [x (.-clientX event)
y (.-clientY event)
opts {:x x :y y
:on-change (partial on-change attr)
:value (get @form-ref attr)
:transparent? true}]
(udl/open! :interactions/colorpicker opts)))]
(let [stroke-color (:stroke-color @form-ref)
fill-color (:fill-color @form-ref)]
(html
[:div
[:div.row-flex
[:div.column-half
[:span "Fill"]
[:div.color-data
[:span.color-th
{:style {:background-color fill-color}
:on-click (partial show-picker :fill-color)}]
[:div.color-info
[:span fill-color]]]]
[:div.column-half
[:span "Stroke"]
[:div.color-data
[:span.color-th
{:style {:background-color stroke-color}
:on-click (partial show-picker :stroke-color)}]
[:div.color-info
[:span stroke-color]]]]]]))))
(def color-input
(mx/component
{:render color-input-render
:name "color-input"}))
;; --- Easing Input
(defn- easing-input-render
[own form-ref]
(when-not (:easing @form-ref)
(swap! form-ref assoc :easing :none))
(html
[:div
[:span "Easing"]
[:div.row-flex
[:select.input-select
{:placeholder "Easing"
:on-change (partial on-change form-ref :easing)
:value (pr-str (:easing @form-ref))}
[:option {:value ":none"} "None"]
[:option {:value ":linear"} "Linear"]
[:option {:value ":easein"} "Ease in"]
[:option {:value ":easeout"} "Ease out"]
[:option {:value ":easeinout"} "Ease in out"]]]]))
(def easing-input
(mx/component
{:render easing-input-render
:name "easing-input"}))
;; --- Duration Input
(defn- duration-input-render
[own form-ref]
(when-not (:duration @form-ref)
(swap! form-ref assoc :duration 300))
(when-not (:delay @form-ref)
(swap! form-ref assoc :delay 0))
(html
[:div
[:span "Duration | Delay (ms)"]
[:div.row-flex
[:input.input-text
{:placeholder "Duration"
:type "number"
:on-change (partial on-change form-ref :duration)
:value (pr-str (:duration @form-ref))}]
[:input.input-text {:placeholder "Delay"
:type "number"
:on-change (partial on-change form-ref :delay)
:value (pr-str (:delay @form-ref))}]]]))
(def duration-input
(mx/component
{:render duration-input-render
:name "duration-input"}))
;; --- Action Input
(defn- action-input-render
[own page form-ref]
(println "action-input" @form-ref)
(when-not (:action @form-ref)
(swap! form-ref assoc :action :show))
(let [form @form-ref
simple? #{:gotourl :gotopage}
elements? (complement simple?)
animation? #{:show :hide :toggle}
only-easing? (complement animation?)]
(html
[:div
[:span "Action"]
[:div.row-flex
[:select.input-select
{:placeholder "Choose an action"
:on-change (partial on-change form-ref :action [:trigger])
:value (pr-str (:action form))}
[:option {:value ":show"} "Show"]
[:option {:value ":hide"} "Hide"]
[:option {:value ":toggle"} "Toggle"]
[:option {:value ":moveto"} "Move to"]
#_[:option {:value ":moveby"} "Move by"]
[:option {:value ":opacity"} "Opacity"]
[:option {:value ":size"} "Size"]
[:option {:value ":color"} "Color"]
[:option {:value ":rotate"} "Rotate"]
[:option {:value ":gotopage"} "Go to page"]
[:option {:value ":gotourl"} "Go to URL"]
#_[:option {:value ":goback"} "Go back"]
[:option {:value ":scrolltoelement"} "Scroll to element"]]]
(case (:action form)
:gotourl (url-input form-ref)
:gotopage (pages-input form-ref)
:color (color-input form-ref)
:rotate (rotate-input form-ref)
:size (resize-input form-ref)
:moveto (moveto-input form-ref)
:opacity (opacity-input form-ref)
nil)
(when (elements? (:action form))
(elements-input page form-ref))
(when (and (animation? (:action form))
(:element @form-ref))
(animation-input form-ref))
(when (or (not= (:animation form :none) :none)
(and (only-easing? (:action form))
(:element form)))
(mx/concat
(easing-input form-ref)
(duration-input form-ref)))
])))
(def action-input
(mx/component
{:render action-input-render
:name "action-input"}))
;; --- Form
(defn- interactions-form-render
[own shape form-ref]
;; (println "interactions-form" @form-ref)
(html
[:form
(trigger-input form-ref)
(action-input (:page shape) form-ref)
[:div.row-flex
[:input.btn-primary.btn-small.save-btn {:value "Save" :type "submit"}]
[:a.cancel-btn {:href "#"} "Cancel"]]]))
(def interactions-form
(mx/component
{:render interactions-form-render
:name "interactions-form"}))
;; --- Interactions Menu
(defn- interactions-menu-render
[own menu shape]
(let [local (:rum/local own)
form (l/derive (l/key :form) local)
interactions (:interactions shape)]
(html
[:div.element-set {:key (str (:id menu))}
[:div.element-set-title (:name menu)]
[:div.element-set-content
[:span "Trigger"]
[:div.row-flex
[:select#style.input-select {:placeholder "Choose a trigger"
:value ""}
[:option {:value ":click"} "Click"]
[:option {:value ":doubleclick"} "Double-click"]
[:option {:value ":rightclick"} "Right-click"]
[:option {:value ":hover"} "Hover"]
[:option {:value ":mousein"} "Mouse in"]]]
[:span "Action"]
[:div.row-flex
[:select#style.input-select {:placeholder "Choose an action"
:value ""}
[:option {:value ":show"} "Show"]
[:option {:value ":hide"} "Hide"]
[:option {:value ":toggle"} "Toggle"]
[:option {:value ":moveto"} "Move to"]
[:option {:value ":moveby"} "Move by"]]]
[:span "Element"]
[:div.row-flex
[:select#style.input-select {:placeholder "Choose an element"
:value ""}
[:option {:value ":1"} "Box 1"]
[:option {:value ":2"} "Circle 1"]
[:option {:value ":3"} "Circle 2"]
[:option {:value ":4"} "Icon 1"]
[:option {:value ":5"} "Icon 2"]]]
[:span "Page"]
[:div.row-flex
[:select#style.input-select {:placeholder "Choose a page"
:value ""}
[:option {:value ":1"} "page 1"]
[:option {:value ":2"} "page 2"]
[:option {:value ":3"} "page 3"]
[:option {:value ":4"} "page 4"]
[:option {:value ":5"} "page 5"]]]
[:span "Key"]
[:div.row-flex
[:select#style.input-select {:placeholder "Choose a key"
:value ""}
[:option {:value ":1"} "key 1"]
[:option {:value ":2"} "key 2"]
[:option {:value ":3"} "key 3"]
[:option {:value ":4"} "key 4"]
[:option {:value ":5"} "key 5"]]]]
]))
(if (and (not @form)
(not (empty? interactions)))
[:div
(interactions-list interactions)
[:input.btn-primary.btn-small {:value "New interaction" :type "submit"}]]
(interactions-form shape form))]])))
(def interactions-menu
(mx/component
{:render interactions-menu-render
:name "interactions-menu"
:mixed [mx/static]}))
:mixins [mx/static (mx/local)]}))
;; --- Not implemented stuff
;; [:span "Key"]
;; [:div.row-flex
;; [:select.input-select {:placeholder "Choose a key"
;; :value ""}
;; [:option {:value ":1"} "key 1"]
;; [:option {:value ":2"} "key 2"]
;; [:option {:value ":3"} "key 3"]
;; [:option {:value ":4"} "key 4"]
;; [:option {:value ":5"} "key 5"]]]
;; [:span "Scrolled to (px)"]
;; [:div.row-flex
;; [:input.input-text {:placeholder "px"
;; :type "number"
;; :value ""}]]