Information panels

This commit is contained in:
alonso.torres 2020-10-22 18:08:40 +02:00 committed by Hirunatan
parent 04f620ec00
commit 1e48221d7b
10 changed files with 713 additions and 18 deletions

View file

@ -93,12 +93,13 @@
(update [_ state]
(let [objects (:objects page)
frames (extract-frames objects)]
(assoc state :viewer-data {:project project
:objects objects
:file file
:page page
:frames frames
:share-token share-token})))))
(-> state
(assoc :viewer-data {:project project
:objects objects
:file file
:page page
:frames frames
:share-token share-token}))))))
(def create-share-link
(ptk/reify ::create-share-link

View file

@ -36,7 +36,7 @@
(let [color (if (string? color) {:color color :opacity 1} color)
{:keys [name color opacity gradient]} color
color-str (or name color (gradient-type->string (:type gradient)))]
(when (= size :big)
(when (or (not size) (= size :big))
[:span.color-text {:on-click #(when on-click (on-click %))
:on-double-click #(when on-double-click (on-double-click %))
:title name } color-str])))

View file

@ -43,6 +43,12 @@
frames (:frames data [])
objects (:objects data)
frame (get frames index)]
(mf/use-effect
(mf/deps index)
(fn []
(st/emit! (dv/select-shape (:id frame)))))
[:section.viewer-preview
(cond
(empty? frames)
@ -60,7 +66,7 @@
[:& render-frame-svg {:frame-id (:id frame)
:zoom (:zoom local)
:objects objects}]]
[:& attributes-sidebar]])]))
[:& attributes-sidebar {:frame frame}]])]))
(mf/defc handoff-content
[{:keys [data local index] :as props}]

View file

@ -0,0 +1,248 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.main.ui.viewer.handoff.attrib-panel
(:require
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.config :as cfg]
[app.util.i18n :refer [locale t]]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.main.ui.icons :as i]
[app.util.color :as uc]
[app.util.text :as ut]
[app.main.fonts :as fonts]
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]))
(mf/defc color-row [{:keys [color]}]
(let [locale (mf/deref locale)]
[:div.attributes-color-row
[:& color-bullet {:color color}]
[:*
[:& color-name {:color color}]
(when-not (:gradient color) [:div (str (* 100 (:opacity color)) "%")])]
[:select
[:option (t locale "handoff.attributes.color.hex")]
[:option (t locale "handoff.attributes.color.rgba")]
[:option (t locale "handoff.attributes.color.hsla")]]
[:button.attributes-copy-button i/copy]]))
(mf/defc layout-panel
[{:keys [shape locale]}]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.layout")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
[:div.attributes-value (mth/precision (:width shape) 2) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
[:div.attributes-value (mth/precision (:height shape) 2) "px"]
[:button.attributes-copy-button i/copy]]
(when (not= (:x shape) 0)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
[:div.attributes-value (mth/precision (:x shape) 2) "px"]
[:button.attributes-copy-button i/copy]])
(when (not= (:y shape) 0)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.top")]
[:div.attributes-value (mth/precision (:y shape) 2) "px"]
[:button.attributes-copy-button i/copy]])
(when (not= (:rotation shape) 0)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.rotation")]
[:div.attributes-value (mth/precision (:rotation shape) 2) "deg"]
[:button.attributes-copy-button i/copy]])])
(mf/defc fill-panel
[{:keys [shape locale]}]
(let [{:keys [fill-color fill-opacity fill-color-gradient fill-ref-id fill-ref-file-id]} shape]
(when (or fill-color fill-color-gradient)
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.fill")]
[:button.attributes-copy-button i/copy]]
(let [color {:color fill-color
:opacity fill-opacity
:gradient fill-color-gradient
:id fill-ref-id
:file-id fill-ref-file-id}]
[:& color-row {:color color}])])))
(mf/defc stroke-panel
[{:keys [shape locale]}]
(when (and (:stroke-style shape) (not= (:stroke-style shape) :none))
(let [{:keys [stroke-style stroke-alignment stroke-width
stroke-color stroke-opacity stroke-color-gradient
stroke-color-ref-id stroke-color-file-id]} shape
color {:color stroke-color
:opacity stroke-opacity
:gradient stroke-color-gradient
:id stroke-color-ref-id
:file-id stroke-color-file-id}]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.stroke")]
[:button.attributes-copy-button i/copy]]
[:& color-row {:color color}]
[:div.attributes-stroke-row
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
[:div.attributes-value (str stroke-width) "px"]
[:div.attributes-value (->> stroke-style name (str "handoff.attributes.stroke.style.") (t locale))]
[:div.attributes-label (->> stroke-alignment name (str "handoff.attributes.stroke.alignment.") (t locale))]
[:button.attributes-copy-button i/copy]]])))
(mf/defc shadow-panel [{:keys [shape locale]}]
(when (seq (:shadow shape))
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.shadow")]
[:button.attributes-copy-button i/copy]]
(for [shadow (:shadow shape)]
(do
(prn "???" (:spread shadow))
[:*
[:div.attributes-shadow-row
[:div.attributes-label (->> shadow :style name (str "handoff.attributes.shadow.style.") (t locale))]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-x")]
[:div.attributes-value (str (:offset-x shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-y")]
[:div.attributes-value (str (:offset-y shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.blur")]
[:div.attributes-value (str (:blur shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.spread")]
[:div.attributes-value (str (:spread shadow))]]
[:button.attributes-copy-button i/copy]]
[:& color-row {:color (:color shadow)}]]))]))
(mf/defc blur-panel [{:keys [shape locale]}]
(when (:blur shape)
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.blur")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.blur.value")]
[:div.attributes-value (-> shape :blur :value) "px"]
[:button.attributes-copy-button i/copy]]]))
(mf/defc image-panel [{:keys [shape locale]}]
[:div.attributes-block
[:div.attributes-image-row
[:div.attributes-image
[:img {:src (cfg/resolve-media-path (-> shape :metadata :path))}]]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.image.width")]
[:div.attributes-value (-> shape :metadata :width) "px"]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.image.height")]
[:div.attributes-value (-> shape :metadata :height) "px"]]
(let [filename (last (str/split (-> shape :metadata :path) "/"))]
[:a.download-button {:target "_blank"
:download filename
:href (cfg/resolve-media-path (-> shape :metadata :path))}
(t locale "handoff.attributes.image.download")])])
(mf/defc typography-panel [{:keys [shape locale]}]
(let [font (ut/search-text-attrs (:content shape)
(keys ut/default-text-attrs))
font (merge ut/default-text-attrs font)]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.typography")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-family")]
[:div.attributes-value (-> font :font-id fonts/get-font-data :name)]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-style")]
[:div.attributes-value (str (:font-style font))]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-size")]
[:div.attributes-value (str (:font-size font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.line-height")]
[:div.attributes-value (str (:line-height font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.letter-spacing")]
[:div.attributes-value (str (:letter-spacing font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-decoration")]
[:div.attributes-value (->> font :text-decoration (str "handoff.attributes.typography.text-decoration.") (t locale))]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-transform")]
[:div.attributes-value (->> font :text-transform (str "handoff.attributes.typography.text-transform.") (t locale))]
[:button.attributes-copy-button i/copy]]]))
(mf/defc content-panel [{:keys [shape locale]}]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.content")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-content-row
[:pre.attributes-content (ut/content->text (:content shape))]
[:button.attributes-copy-button i/copy]]])
(mf/defc attrib-panel [{:keys [shape frame options]}]
(let [locale (mf/deref locale)]
[:div.element-options
(for [option options]
[:>
(case option
:layout layout-panel
:fill fill-panel
:stroke stroke-panel
:shadow shadow-panel
:blur blur-panel
:image image-panel
:typography typography-panel
:content content-panel
)
{:shape (gsh/translate-to-frame shape frame)
:frame frame
:locale locale}])]))

View file

@ -0,0 +1,110 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.main.ui.viewer.handoff.attributes.layout
(:require
[rumext.alpha :as mf]
[app.main.ui.icons :as i]
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]))
(mf/defc layout-panel [{:keys [shapes]}]
(prn "???" shapes)
[:*
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text "Layout"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label "Width"]
[:div.attributes-value "100px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label "Height"]
[:div.attributes-value "100px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label "Top"]
[:div.attributes-value "100px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label "Left"]
[:div.attributes-value "100px"]
[:button.attributes-copy-button i/copy]]]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text "Fill"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-shadow-row
[:div.attributes-label "Drop"]
[:div.attributes-shadow
[:div.attributes-label "X"]
[:div.attributes-value "4"]]
[:div.attributes-shadow
[:div.attributes-label "Y"]
[:div.attributes-value "4"]]
[:div.attributes-shadow
[:div.attributes-label "B"]
[:div.attributes-value "0"]]
[:div.attributes-shadow
[:div.attributes-label "B"]
[:div.attributes-value "0"]]
[:button.attributes-copy-button i/copy]]
[:div.attributes-color-row
[:& color-bullet {:color {:color "#000000" :opacity 0.5}}]
[:*
[:div "#000000"]
[:div "100%"]]
[:select
[:option "Hex"]
[:option "RGBA"]
[:option "HSLA"]]
[:button.attributes-copy-button i/copy]]
[:div.attributes-stroke-row
[:div.attributes-label "Width"]
[:div.attributes-value "1px"]
[:div.attributes-value "Solid"]
[:div.attributes-label "Center"]
[:button.attributes-copy-button i/copy]]]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text "Content"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-content-row
[:div.attributes-content
"Hi, how are you"]
[:button.attributes-copy-button i/copy]]]
[:div.attributes-block
[:div.attributes-image-row
[:div.attributes-image
#_[:img {:src "https://www.publico.es/tremending/wp-content/uploads/2019/05/Cxagv.jpg"}]
#_[:img {:src "https://i.blogs.es/3861b2/grumpy-cat/1366_2000.png"}]
[:img {:src "https://abs.twimg.com/favicons/twitter.ico"}]
]]
[:button.download-button "Dowload source image"]]
])

View file

@ -10,16 +10,48 @@
(ns app.main.ui.viewer.handoff.attributes-sidebar
(:require
[rumext.alpha :as mf]
[okulary.core :as l]
[app.main.store :as st]
[app.main.ui.icons :as i]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]))
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.viewer.handoff.attrib-panel :refer [attrib-panel]]))
(mf/defc info-panel []
[:div.element-options])
(defn make-selected-shapes-iref
[]
(let [selected->shapes
(fn [state]
(let [selected (get-in state [:viewer-local :selected])
objects (get-in state [:viewer-data :page :objects])
resolve-shape #(get objects %)]
(mapv resolve-shape selected)))]
#(l/derived selected->shapes st/state)))
(mf/defc info-panel [{:keys [frame]}]
(let [selected-ref (mf/use-memo (make-selected-shapes-iref))
shapes (mf/deref selected-ref)]
(if (> (count shapes) 1)
;; Multiple selection
nil
;; Single shape
(when-let [shape (first shapes)]
(let [options
(case (:type shape)
:frame [:layout :fill]
:group [:layout]
:rect [:layout :fill :stroke :shadow :blur]
:circle [:layout :fill :stroke :shadow :blur]
:path [:layout :fill :stroke :shadow :blur]
:curve [:layout :fill :stroke :shadow :blur]
:image [:image :layout :shadow :blur]
:text [:layout :fill :typography :content :shadow :blur])]
[:& attrib-panel {:frame frame
:shape shape
:options options}])))))
(mf/defc code-panel []
[:div.element-options])
(mf/defc attributes-sidebar []
(mf/defc attributes-sidebar [{:keys [frame]}]
(let [section (mf/use-state :info #_:code)]
[:aside.settings-bar.settings-bar-right
[:div.settings-bar-inside
@ -31,8 +63,7 @@
[:& tab-container {:on-change-tab #(reset! section %)
:selected @section}
[:& tab-element {:id :info :title "Info"}
[:& info-panel]]
[:& info-panel {:frame frame}]]
[:& tab-element {:id :code :title "Code"}
[:& code-panel]]]]]]]))

View file

@ -46,7 +46,7 @@
(let [hover (get-in state [:viewer-local :hover])
objects (get-in state [:viewer-data :page :objects])
resolve-shape #(get objects %)]
(map resolve-shape hover)))]
(mapv resolve-shape hover)))]
#(l/derived hover->shapes st/state)))
(mf/defc selection-feedback [{:keys [frame]}]

View file

@ -1,4 +1,6 @@
(ns app.util.text)
(ns app.util.text
(:require
[cuerdas.core :as str]))
(defonce default-text-attrs
{:font-id "sourcesanspro"
@ -11,7 +13,9 @@
:letter-spacing "0"
:text-transform "none"
:text-align "left"
:text-decoration "none"})
:text-decoration "none"
:fill-color "#000000"
:fill-opacity 1})
(def typography-fields
[:font-id
@ -38,3 +42,20 @@
[map-fn node]
(cond-> (map-fn node)
(:children node) (update :children (fn [children] (mapv #(map-node map-fn %) children)))))
(defn content->text
[node]
(str
(if (:children node)
(str/join (if (= "paragraph-set" (:type node)) "\n" "") (map content->text (:children node)))
(:text node ""))))
(defn search-text-attrs
[node attrs]
(let [rec-fn
(fn rec-fn [current node]
(let [current (reduce rec-fn current (:children node []))]
(merge current
(select-keys node attrs))))]
(rec-fn {} node)))