mirror of
https://github.com/penpot/penpot.git
synced 2025-02-23 15:26:29 -05:00
✨ Information panels
This commit is contained in:
parent
04f620ec00
commit
1e48221d7b
10 changed files with 713 additions and 18 deletions
|
@ -3360,5 +3360,73 @@
|
|||
"ru" : "Кликни чтобы закончить фигуру",
|
||||
"es" : "Pulsar para cerrar la ruta"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"handoff.tabs.info": "Info",
|
||||
"handoff.tabs.code": "Code",
|
||||
|
||||
"handoff.attributes.color.hex": "HEX",
|
||||
"handoff.attributes.color.rgba": "RGBA",
|
||||
"handoff.attributes.color.hsla": "HSLA",
|
||||
|
||||
"handoff.attributes.layout": "Layout",
|
||||
|
||||
"handoff.attributes.layout.width": "Width",
|
||||
"handoff.attributes.layout.height": "Height",
|
||||
"handoff.attributes.layout.left": "Left",
|
||||
"handoff.attributes.layout.top": "Top",
|
||||
"handoff.attributes.layout.rotation": "Rotation",
|
||||
|
||||
"handoff.attributes.fill": "Fill",
|
||||
|
||||
"handoff.attributes.stroke": "Stroke",
|
||||
"handoff.attributes.stroke.width": "Width",
|
||||
|
||||
"handoff.attributes.stroke.style.solid": "Solid",
|
||||
"handoff.attributes.stroke.style.dotted": "Dotted",
|
||||
"handoff.attributes.stroke.style.dashed": "Dashed",
|
||||
"handoff.attributes.stroke.style.mixed": "Mixed",
|
||||
"handoff.attributes.stroke.style.none": "None",
|
||||
|
||||
"handoff.attributes.stroke.alignment.center": "Center",
|
||||
"handoff.attributes.stroke.alignment.inner": "Inner",
|
||||
"handoff.attributes.stroke.alignment.outer": "Outer",
|
||||
|
||||
"handoff.attributes.shadow": "Shadow",
|
||||
|
||||
"handoff.attributes.shadow.shorthand.offset-x": "X",
|
||||
"handoff.attributes.shadow.shorthand.offset-y": "Y",
|
||||
"handoff.attributes.shadow.shorthand.blur": "B",
|
||||
"handoff.attributes.shadow.shorthand.spread": "S",
|
||||
|
||||
"handoff.attributes.shadow.style.inner-shadow": "Inner",
|
||||
"handoff.attributes.shadow.style.drop-shadow": "Drop",
|
||||
|
||||
"handoff.attributes.blur": "Blur",
|
||||
"handoff.attributes.blur.value": "Value",
|
||||
|
||||
"handoff.attributes.image.width": "Width",
|
||||
"handoff.attributes.image.height": "Height",
|
||||
"handoff.attributes.image.download": "Dowload source image",
|
||||
|
||||
"handoff.attributes.typography": "Typography",
|
||||
"handoff.attributes.typography.font-family": "Font Family",
|
||||
"handoff.attributes.typography.font-style": "Font Style",
|
||||
"handoff.attributes.typography.font-size": "Font Size",
|
||||
"handoff.attributes.typography.line-height": "Line Height",
|
||||
"handoff.attributes.typography.letter-spacing": "Letter Spacing",
|
||||
"handoff.attributes.typography.text-decoration": "Text Decoration",
|
||||
"handoff.attributes.typography.text-transform": "Text Transform",
|
||||
|
||||
"handoff.attributes.content": "Content",
|
||||
|
||||
"handoff.attributes.typography.text-decoration.none": "None",
|
||||
"handoff.attributes.typography.text-decoration.underline": "Underline",
|
||||
"handoff.attributes.typography.text-decoration.strikethrough": "Strikethrough",
|
||||
|
||||
"handoff.attributes.typography.text-transform.none": "None",
|
||||
"handoff.attributes.typography.text-transform.uppercase": "Upper Case",
|
||||
"handoff.attributes.typography.text-transform.lowercase": "Lower Case",
|
||||
"handoff.attributes.typography.text-transform.titlecase": "Title Case"
|
||||
}
|
||||
|
|
|
@ -14,3 +14,213 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.attributes-block {
|
||||
user-select: text;
|
||||
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
padding-bottom: 0.5rem;
|
||||
font-size: $fs12;
|
||||
|
||||
.attributes-copy-button {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: $color-gray-20;
|
||||
transition: fill 0.3s;
|
||||
|
||||
&:hover {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-label {
|
||||
color: $color-gray-20;
|
||||
}
|
||||
|
||||
.attributes-value {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
.attributes-block-title {
|
||||
position: relative;
|
||||
color: $color-gray-10;
|
||||
padding: 0.5rem;
|
||||
font-size: $fs14;
|
||||
|
||||
.attributes-copy-button {
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-unit-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 1rem 0.5rem;
|
||||
|
||||
.attributes-label,
|
||||
.attributes-value {
|
||||
width: 50%;
|
||||
}
|
||||
.attributes-copy-button {
|
||||
padding: 1rem 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-color-row {
|
||||
display: flex;
|
||||
padding: 1rem 0;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
|
||||
.attributes-color-display {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.color-bullet {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.attributes-copy-button {
|
||||
padding: 1rem 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
& > * {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
& :last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size: $fs12;
|
||||
margin: 0;
|
||||
background: none;
|
||||
color: $color-gray-20;
|
||||
border: none;
|
||||
border-bottom: 1px solid $color-gray-30;
|
||||
padding: 0 1rem 0.25rem 0.25rem;
|
||||
margin-top: 2px;
|
||||
background-image: url("/images/icons/arrow-down-white.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 95% 48%;
|
||||
background-size: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
option {
|
||||
padding: 1rem;
|
||||
background-color: $color-gray-50;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-content-row {
|
||||
position: relative;
|
||||
margin: 0.5rem;
|
||||
width: calc(100% - 1rem);
|
||||
|
||||
.attributes-content {
|
||||
overflow-y: auto;
|
||||
max-height: 10rem;
|
||||
background: $color-gray-60;
|
||||
border-radius: 4px;
|
||||
padding: 1rem 0.5rem;
|
||||
color: $color-gray-10;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-image-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0.5rem;
|
||||
background: $color-gray-60;
|
||||
border-radius: 4px;
|
||||
|
||||
width: calc(100% - 1rem);
|
||||
min-height: 5rem;
|
||||
img {
|
||||
max-height: 8rem;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-shadow-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin: 0.5rem;
|
||||
padding-right: 2rem;
|
||||
justify-content: space-between;
|
||||
|
||||
& > :first-child {
|
||||
color: $color-gray-10;
|
||||
}
|
||||
|
||||
.attributes-shadow {
|
||||
display: flex;
|
||||
|
||||
.attributes-label {
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-stroke-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin: 0.5rem;
|
||||
padding-right: 2rem;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.download-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
border: 1px solid $color-gray-60;
|
||||
background-color: $color-gray-60;
|
||||
padding: 0.5rem 1rem;
|
||||
color: $color-gray-10;
|
||||
width: calc(100% - 1rem);
|
||||
border-radius: 4px;
|
||||
margin: 0.5rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-primary;
|
||||
color: $color-black;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-block-title,
|
||||
.attributes-unit-row,
|
||||
.attributes-color-row,
|
||||
.attributes-shadow-row,
|
||||
.attributes-stroke-row {
|
||||
&:hover .attributes-copy-button {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])))
|
||||
|
|
|
@ -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}]
|
||||
|
|
248
frontend/src/app/main/ui/viewer/handoff/attrib_panel.cljs
Normal file
248
frontend/src/app/main/ui/viewer/handoff/attrib_panel.cljs
Normal 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}])]))
|
110
frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs
Normal file
110
frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs
Normal 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"]]
|
||||
|
||||
])
|
|
@ -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]]]]]]]))
|
||||
|
||||
|
|
|
@ -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]}]
|
||||
|
|
|
@ -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)))
|
||||
|
|
Loading…
Add table
Reference in a new issue