mirror of
https://github.com/penpot/penpot.git
synced 2025-05-13 13:36:37 +02:00
✨ Add code block to layout elements
This commit is contained in:
parent
93bbe1b2f8
commit
2a2b5c7dba
12 changed files with 272 additions and 148 deletions
|
@ -23,12 +23,12 @@
|
||||||
;; ITEMS
|
;; ITEMS
|
||||||
;; :layout-item-margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
;; :layout-item-margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||||
;; :layout-item-margin-type ;; :simple :multiple
|
;; :layout-item-margin-type ;; :simple :multiple
|
||||||
;; :layout-item-h-sizing ;; :fill :fix :auto
|
;; :layout-item-h-sizing ;; :fill :fix :auto
|
||||||
;; :layout-item-v-sizing ;; :fill :fix :auto
|
;; :layout-item-v-sizing ;; :fill :fix :auto
|
||||||
;; :layout-item-max-h ;; num
|
;; :layout-item-max-h ;; num
|
||||||
;; :layout-item-min-h ;; num
|
;; :layout-item-min-h ;; num
|
||||||
;; :layout-item-max-w ;; num
|
;; :layout-item-max-w ;; num
|
||||||
;; :layout-item-min-w
|
;; :layout-item-min-w ;; num
|
||||||
|
|
||||||
(s/def ::layout #{:flex :grid})
|
(s/def ::layout #{:flex :grid})
|
||||||
(s/def ::layout-flex-dir #{:row :reverse-row :column :reverse-column})
|
(s/def ::layout-flex-dir #{:row :reverse-row :column :reverse-column})
|
||||||
|
|
|
@ -104,16 +104,19 @@
|
||||||
(ptk/reify ::toogle-layout-flex
|
(ptk/reify ::toogle-layout-flex
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
selected (wsh/lookup-selected state)
|
selected (wsh/lookup-selected state)
|
||||||
selected-shapes (map (d/getf objects) selected)
|
selected-shapes (map (d/getf objects) selected)
|
||||||
single? (= (count selected-shapes) 1)
|
single? (= (count selected-shapes) 1)
|
||||||
has-flex-layout? (and single? (= :flex (:layout (first selected-shapes))))]
|
has-flex-layout? (and single? (= :flex (:layout (first selected-shapes))))
|
||||||
|
is-frame? (and single? (= :frame (:type (first selected-shapes))))]
|
||||||
|
|
||||||
(if has-flex-layout?
|
(if has-flex-layout?
|
||||||
(rx/of (remove-layout selected))
|
(rx/of (remove-layout selected))
|
||||||
(rx/of (create-layout-from-selection :flex)))))))
|
(if is-frame?
|
||||||
|
(rx/of (create-layout [(first selected)] :flex))
|
||||||
|
(rx/of (create-layout-from-selection :flex))))))))
|
||||||
|
|
||||||
(defn update-layout
|
(defn update-layout
|
||||||
[ids changes]
|
[ids changes]
|
||||||
|
|
|
@ -447,14 +447,14 @@
|
||||||
(some (partial ctl/layout-child? objects))))
|
(some (partial ctl/layout-child? objects))))
|
||||||
workspace-page-objects))
|
workspace-page-objects))
|
||||||
|
|
||||||
(defn get-flex-child-viewer?
|
(defn get-flex-child-viewer
|
||||||
[ids page-id]
|
[ids page-id]
|
||||||
(l/derived
|
(l/derived
|
||||||
(fn [state]
|
(fn [state]
|
||||||
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
||||||
(into []
|
(into []
|
||||||
(comp (filter (partial ctl/layout-child? objects))
|
(comp (map (d/getf objects))
|
||||||
(map (d/getf objects)))
|
(filter (partial ctl/layout-child? objects)))
|
||||||
ids)))
|
ids)))
|
||||||
st/state =))
|
st/state =))
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps code type block-ref)
|
(mf/deps code type block-ref)
|
||||||
(fn []
|
(fn []
|
||||||
(hljs/highlightBlock (mf/ref-val block-ref))))
|
(hljs/highlightElement (mf/ref-val block-ref))))
|
||||||
[:pre.code-display {:class type
|
[:pre.code-display {:class type
|
||||||
:ref block-ref} code]))
|
:ref block-ref} code]))
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.math :as mth]))
|
[app.common.math :as mth]
|
||||||
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
(defn format-percent
|
(defn format-percent
|
||||||
([value]
|
([value]
|
||||||
|
@ -61,3 +62,33 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
{:p1 p1 :p2 p2 :p3 p3})))
|
{:p1 p1 :p2 p2 :p3 p3})))
|
||||||
|
|
||||||
|
(defn format-size [type value shape]
|
||||||
|
(let [sizing (if (= type :width)
|
||||||
|
(:layout-item-h-sizing shape)
|
||||||
|
(:layout-item-v-sizing shape))]
|
||||||
|
(if (= sizing :fill)
|
||||||
|
"100%"
|
||||||
|
(str (format-pixels value)))))
|
||||||
|
|
||||||
|
(defn format-padding
|
||||||
|
[padding-values type]
|
||||||
|
(let [new-padding (if (= :margin type)
|
||||||
|
{:m1 0 :m2 0 :m3 0 :m4 0}
|
||||||
|
{:p1 0 :p2 0 :p3 0 :p4 0})
|
||||||
|
merged-padding (merge new-padding padding-values)
|
||||||
|
short-hand (format-padding-margin-shorthand (vals merged-padding))
|
||||||
|
parsed-values (map #(str/fmt "%spx" %) (vals short-hand))]
|
||||||
|
(str/join " " parsed-values)))
|
||||||
|
|
||||||
|
(defn format-margin
|
||||||
|
[margin-values]
|
||||||
|
(format-padding margin-values :margin))
|
||||||
|
|
||||||
|
(defn format-gap
|
||||||
|
[gap-values]
|
||||||
|
(let [row-gap (:row-gap gap-values)
|
||||||
|
column-gap (:column-gap gap-values)]
|
||||||
|
(if (= row-gap column-gap)
|
||||||
|
(str/fmt "%spx" row-gap)
|
||||||
|
(str/fmt "%spx %spx" row-gap column-gap))))
|
|
@ -23,7 +23,9 @@
|
||||||
:rx "border-radius"
|
:rx "border-radius"
|
||||||
:r1 "border-radius"}
|
:r1 "border-radius"}
|
||||||
:format {:rotation #(str/fmt "rotate(%sdeg)" %)
|
:format {:rotation #(str/fmt "rotate(%sdeg)" %)
|
||||||
:r1 #(apply str/fmt "%spx, %spx, %spx, %spx" %)}
|
:r1 #(apply str/fmt "%spx, %spx, %spx, %spx" %)
|
||||||
|
:width (partial fmt/format-size :width)
|
||||||
|
:height (partial fmt/format-size :height)}
|
||||||
:multi {:r1 [:r1 :r2 :r3 :r4]}})
|
:multi {:r1 [:r1 :r2 :r3 :r4]}})
|
||||||
|
|
||||||
(defn copy-data
|
(defn copy-data
|
||||||
|
@ -35,17 +37,17 @@
|
||||||
(mf/defc layout-block
|
(mf/defc layout-block
|
||||||
[{:keys [shape]}]
|
[{:keys [shape]}]
|
||||||
(let [selrect (:selrect shape)
|
(let [selrect (:selrect shape)
|
||||||
{:keys [width height x y]} selrect]
|
{:keys [x y]} selrect]
|
||||||
[:*
|
[:*
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (tr "handoff.attributes.layout.width")]
|
[:div.attributes-label (tr "handoff.attributes.layout.width")]
|
||||||
[:div.attributes-value (fmt/format-pixels width)]
|
[:div.attributes-value (fmt/format-size :width (:width shape) shape)]
|
||||||
[:& copy-button {:data (copy-data selrect :width)}]]
|
[:& copy-button {:data (copy-data shape :width)}]]
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (tr "handoff.attributes.layout.height")]
|
[:div.attributes-label (tr "handoff.attributes.layout.height")]
|
||||||
[:div.attributes-value (fmt/format-pixels height)]
|
[:div.attributes-value (fmt/format-size :height (:height shape) shape)]
|
||||||
[:& copy-button {:data (copy-data selrect :height)}]]
|
[:& copy-button {:data (copy-data shape :height)}]]
|
||||||
|
|
||||||
(when (not= (:x shape) 0)
|
(when (not= (:x shape) 0)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
|
|
|
@ -13,20 +13,6 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn format-gap
|
|
||||||
[gap-values]
|
|
||||||
(let [row-gap (:row-gap gap-values)
|
|
||||||
column-gap (:column-gap gap-values)]
|
|
||||||
(if (= row-gap column-gap)
|
|
||||||
(str/fmt "%spx" row-gap)
|
|
||||||
(str/fmt "%spx %spx" row-gap column-gap))))
|
|
||||||
|
|
||||||
(defn format-padding
|
|
||||||
[padding-values]
|
|
||||||
(let [short-hand (fm/format-padding-margin-shorthand (vals padding-values))
|
|
||||||
parsed-values (map #(str/fmt "%spx" %) (vals short-hand))]
|
|
||||||
(str/join " " parsed-values)))
|
|
||||||
|
|
||||||
(def properties [:layout
|
(def properties [:layout
|
||||||
:layout-flex-dir
|
:layout-flex-dir
|
||||||
:layout-align-items
|
:layout-align-items
|
||||||
|
@ -49,7 +35,7 @@
|
||||||
:layout-flex-dir "flex-direction"
|
:layout-flex-dir "flex-direction"
|
||||||
:layout-align-items "align-items"
|
:layout-align-items "align-items"
|
||||||
:layout-justify-content "justify-content"
|
:layout-justify-content "justify-content"
|
||||||
:layout-wrap-type "wrap"
|
:layout-wrap-type "flex-wrap"
|
||||||
:layout-gap "gap"
|
:layout-gap "gap"
|
||||||
:layout-padding "padding"}
|
:layout-padding "padding"}
|
||||||
:format {:layout name
|
:format {:layout name
|
||||||
|
@ -57,8 +43,8 @@
|
||||||
:layout-align-items name
|
:layout-align-items name
|
||||||
:layout-justify-content name
|
:layout-justify-content name
|
||||||
:layout-wrap-type name
|
:layout-wrap-type name
|
||||||
:layout-gap format-gap
|
:layout-gap fm/format-gap
|
||||||
:layout-padding format-padding}})
|
:layout-padding fm/format-padding}})
|
||||||
|
|
||||||
(def layout-align-content-params
|
(def layout-align-content-params
|
||||||
{:props [:layout-align-content]
|
{:props [:layout-align-content]
|
||||||
|
@ -109,7 +95,7 @@
|
||||||
[:& copy-button {:data (copy-data shape :layout-justify-content)}]]
|
[:& copy-button {:data (copy-data shape :layout-justify-content)}]]
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label "Wrap"]
|
[:div.attributes-label "Flex wrap"]
|
||||||
[:div.attributes-value (str/capital (d/name (:layout-wrap-type shape)))]
|
[:div.attributes-value (str/capital (d/name (:layout-wrap-type shape)))]
|
||||||
[:& copy-button {:data (copy-data shape :layout-wrap-type)}]]
|
[:& copy-button {:data (copy-data shape :layout-wrap-type)}]]
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.viewer.handoff.code :as cd]
|
||||||
[app.util.code-gen :as cg]
|
[app.util.code-gen :as cg]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -18,41 +18,31 @@
|
||||||
|
|
||||||
(defn format-margin
|
(defn format-margin
|
||||||
[margin-values]
|
[margin-values]
|
||||||
(let [short-hand (fmt/format-padding-margin-shorthand (vals margin-values))
|
(let [short-hand (fmt/format-padding-margin-shorthand (vals margin-values))
|
||||||
parsed-values (map #(str/fmt "%spx" %) (vals short-hand))]
|
parsed-values (map #(str/fmt "%spx" %) (vals short-hand))]
|
||||||
(str/join " " parsed-values)))
|
(str/join " " parsed-values)))
|
||||||
|
|
||||||
(def properties [:layout-item-margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
(def properties [:layout-item-margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||||
:layout-item-h-sizing ;; :fill-width :fix-width :auto-width
|
:layout-item-max-h ;; num
|
||||||
:layout-item-v-sizing ;; :fill-height :fix-height :auto-height
|
:layout-item-min-h ;; num
|
||||||
:layout-item-max-h ;; num
|
:layout-item-max-w ;; num
|
||||||
:layout-item-min-h ;; num
|
:layout-item-min-w ;; num
|
||||||
:layout-item-max-w ;; num
|
:layout-item-align-self]) ;; :start :end :center
|
||||||
:layout-item-min-w ;; num
|
|
||||||
:layout-item-align-self ;; :start :end :center :strech :baseline
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
(def layout-flex-item-params
|
(def layout-flex-item-params
|
||||||
{:props [:layout-item-margin
|
{:props [:layout-item-margin
|
||||||
:layout-item-h-sizing
|
|
||||||
:layout-item-v-sizing
|
|
||||||
:layout-item-max-h
|
:layout-item-max-h
|
||||||
:layout-item-min-h
|
:layout-item-min-h
|
||||||
:layout-item-max-w
|
:layout-item-max-w
|
||||||
:layout-item-min-w
|
:layout-item-min-w
|
||||||
:layout-item-align-self]
|
:layout-item-align-self]
|
||||||
:to-prop {:layout-item-margin "margin"
|
:to-prop {:layout-item-margin "margin"
|
||||||
:layout-item-h-sizing "width"
|
|
||||||
:layout-item-v-sizing "height"
|
|
||||||
:layout-item-align-self "align-self"
|
:layout-item-align-self "align-self"
|
||||||
:layout-item-max-h "max. height"
|
:layout-item-max-h "max-height"
|
||||||
:layout-item-min-h "min. height"
|
:layout-item-min-h "min-height"
|
||||||
:layout-item-max-w "max. width"
|
:layout-item-max-w "max-width"
|
||||||
:layout-item-min-w "min. width"}
|
:layout-item-min-w "min-width"}
|
||||||
:format {:layout-item-margin format-margin
|
:format {:layout-item-margin format-margin
|
||||||
:layout-item-h-sizing name
|
|
||||||
:layout-item-v-sizing name
|
|
||||||
:layout-item-align-self name}})
|
:layout-item-align-self name}})
|
||||||
|
|
||||||
(defn copy-data
|
(defn copy-data
|
||||||
|
@ -69,65 +59,97 @@
|
||||||
(for [[k v] values]
|
(for [[k v] values]
|
||||||
[:span.items {:key (str type "-" k "-" v)} v "px"])]))
|
[:span.items {:key (str type "-" k "-" v)} v "px"])]))
|
||||||
|
|
||||||
|
(defn manage-sizing
|
||||||
|
[value type]
|
||||||
|
(let [ref-value-h {:fill "Width 100%"
|
||||||
|
:fix "Fixed width"
|
||||||
|
:auto "Fit content"}
|
||||||
|
ref-value-v {:fill "Height 100%"
|
||||||
|
:fix "Fixed height"
|
||||||
|
:auto "Fit content"}]
|
||||||
|
(if (= :h type)
|
||||||
|
(ref-value-h value)
|
||||||
|
(ref-value-v value))))
|
||||||
|
|
||||||
(mf/defc layout-element-block
|
(mf/defc layout-element-block
|
||||||
[{:keys [shape]}]
|
[{:keys [shape]}]
|
||||||
[:*
|
(let [old-margin (:layout-item-margin shape)
|
||||||
[:div.attributes-unit-row
|
new-margin {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||||
[:div.attributes-label "Width"]
|
merged-margin (merge new-margin old-margin)
|
||||||
[:div.attributes-value (str/capital (d/name (:layout-item-h-sizing shape)))]
|
shape (assoc shape :layout-item-margin merged-margin)]
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-h-sizing)}]]
|
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
[:*
|
||||||
[:div.attributes-label "Height"]
|
(when (:layout-item-align-self shape)
|
||||||
[:div.attributes-value (str/capital (d/name (:layout-item-v-sizing shape)))]
|
[:div.attributes-unit-row
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-v-sizing)}]]
|
[:div.attributes-label "Align self"]
|
||||||
|
[:div.attributes-value (str/capital (d/name (:layout-item-align-self shape)))]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-align-self)}]])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (:layout-item-margin shape)
|
||||||
[:div.attributes-label "Align self"]
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-value (str/capital (d/name (:layout-item-align-self shape)))]
|
[:div.attributes-label "Margin"]
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-align-self)}]]
|
[:& manage-margin {:margin merged-margin :type "margin"}]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-margin)}]])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (:layout-item-h-sizing shape)
|
||||||
[:div.attributes-label "Margin"]
|
[:div.attributes-unit-row
|
||||||
[:& manage-margin {:margin (:layout-item-margin shape) :type "margin"}]
|
[:div.attributes-label "Horizontal sizing"]
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-margin)}]]
|
[:div.attributes-value (manage-sizing (:layout-item-h-sizing shape) :h)]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-h-sizing)}]])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (:layout-item-v-sizing shape)
|
||||||
[:div.attributes-label "Max. width"]
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-value (fmt/format-pixels (:layout-item-max-w shape))]
|
[:div.attributes-label "Vertical sizing"]
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-max-w)}]]
|
[:div.attributes-value (manage-sizing (:layout-item-v-sizing shape) :v)]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-v-sizing)}]])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (= :fill (:layout-item-h-sizing shape))
|
||||||
[:div.attributes-label "Min. width"]
|
[:*
|
||||||
[:div.attributes-value (fmt/format-pixels (:layout-item-min-w shape))]
|
(when (some? (:layout-item-max-w shape))
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-min-w)}]]
|
[:div.attributes-unit-row
|
||||||
|
[:div.attributes-label "Max. width"]
|
||||||
|
[:div.attributes-value (fmt/format-pixels (:layout-item-max-w shape))]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-max-w)}]])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (some? (:layout-item-min-w shape))
|
||||||
[:div.attributes-label "Max. height"]
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-value (fmt/format-pixels (:layout-item-max-h shape))]
|
[:div.attributes-label "Min. width"]
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-max-h)}]]
|
[:div.attributes-value (fmt/format-pixels (:layout-item-min-w shape))]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-min-w)}]])])
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
(when (= :fill (:layout-item-v-sizing shape))
|
||||||
[:div.attributes-label "Min. height"]
|
[:*
|
||||||
[:div.attributes-value (fmt/format-pixels (:layout-item-min-w shape))]
|
(when (:layout-item-max-h shape)
|
||||||
[:& copy-button {:data (copy-data shape :layout-item-min-h)}]]])
|
[:div.attributes-unit-row
|
||||||
|
[:div.attributes-label "Max. height"]
|
||||||
|
[:div.attributes-value (fmt/format-pixels (:layout-item-max-h shape))]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-max-h)}]])
|
||||||
|
|
||||||
(defn get-flex-elements [page-id shapes]
|
(when (:layout-item-min-h shape)
|
||||||
(let [ids (mapv :id shapes)
|
[:div.attributes-unit-row
|
||||||
ids (hooks/use-equal-memo ids)
|
[:div.attributes-label "Min. height"]
|
||||||
get-layout-children-refs (mf/use-memo (mf/deps ids page-id) #(refs/get-flex-child-viewer? ids page-id))]
|
[:div.attributes-value (fmt/format-pixels (:layout-item-min-h shape))]
|
||||||
|
[:& copy-button {:data (copy-data shape :layout-item-min-h)}]])])]))
|
||||||
(mf/deref get-layout-children-refs)))
|
|
||||||
|
|
||||||
(mf/defc layout-flex-element-panel
|
(mf/defc layout-flex-element-panel
|
||||||
[{:keys [shapes]}]
|
[{:keys [shapes]}]
|
||||||
(let [route (mf/deref refs/route)
|
(let [route (mf/deref refs/route)
|
||||||
page-id (:page-id (:query-params route))
|
page-id (:page-id (:query-params route))
|
||||||
shapes (get-flex-elements page-id shapes)]
|
mod-shapes (cd/get-flex-elements page-id shapes)
|
||||||
(when (and (= (count shapes) 1) (seq shapes))
|
shape (first mod-shapes)
|
||||||
|
has-margin? (some? (:layout-item-margin shape))
|
||||||
|
has-values? (or (some? (:layout-item-max-w shape))
|
||||||
|
(some? (:layout-item-max-h shape))
|
||||||
|
(some? (:layout-item-min-w shape))
|
||||||
|
(some? (:layout-item-min-h shape)))
|
||||||
|
has-align? (some? (:layout-item-align-self shape))
|
||||||
|
has-sizing? (or (some? (:layout-item-h-sizing shape))
|
||||||
|
(some? (:layout-item-w-sizing shape)))
|
||||||
|
must-show (or has-margin? has-values? has-align? has-sizing?)]
|
||||||
|
(when (and (= (count mod-shapes) 1) must-show)
|
||||||
[:div.attributes-block
|
[:div.attributes-block
|
||||||
[:div.attributes-block-title
|
[:div.attributes-block-title
|
||||||
[:div.attributes-block-title-text "Flex element"]
|
[:div.attributes-block-title-text "Flex element"]
|
||||||
[:& copy-button {:data (copy-data (first shapes))}]]
|
[:& copy-button {:data (copy-data shape)}]]
|
||||||
|
|
||||||
[:& layout-element-block {:shape (first shapes)}]])))
|
[:& layout-element-block {:shape shape}]])))
|
||||||
|
|
|
@ -9,9 +9,11 @@
|
||||||
["js-beautify" :as beautify]
|
["js-beautify" :as beautify]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.code-block :refer [code-block]]
|
[app.main.ui.components.code-block :refer [code-block]]
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.code-gen :as cg]
|
[app.util.code-gen :as cg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
@ -40,13 +42,23 @@
|
||||||
(cond-> code
|
(cond-> code
|
||||||
(= type "svg") (beautify/html #js {"indent_size" 2}))))
|
(= type "svg") (beautify/html #js {"indent_size" 2}))))
|
||||||
|
|
||||||
|
(defn get-flex-elements [page-id shapes]
|
||||||
|
(let [ids (mapv :id shapes)
|
||||||
|
ids (hooks/use-equal-memo ids)
|
||||||
|
get-layout-children-refs (mf/use-memo (mf/deps ids page-id) #(refs/get-flex-child-viewer ids page-id))]
|
||||||
|
|
||||||
|
(mf/deref get-layout-children-refs)))
|
||||||
|
|
||||||
(mf/defc code
|
(mf/defc code
|
||||||
[{:keys [shapes frame on-expand]}]
|
[{:keys [shapes frame on-expand]}]
|
||||||
(let [style-type (mf/use-state "css")
|
(let [style-type (mf/use-state "css")
|
||||||
markup-type (mf/use-state "svg")
|
markup-type (mf/use-state "svg")
|
||||||
shapes (->> shapes
|
shapes (->> shapes
|
||||||
(map #(gsh/translate-to-frame % frame)))
|
(map #(gsh/translate-to-frame % frame)))
|
||||||
|
route (mf/deref refs/route)
|
||||||
|
page-id (:page-id (:query-params route))
|
||||||
|
flex-items (get-flex-elements page-id shapes)
|
||||||
|
shapes (map #(assoc % :flex-items flex-items) shapes)
|
||||||
style-code (-> (cg/generate-style-code @style-type shapes)
|
style-code (-> (cg/generate-style-code @style-type shapes)
|
||||||
(format-code "css"))
|
(format-code "css"))
|
||||||
|
|
||||||
|
@ -67,15 +79,14 @@
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event
|
(st/emit! (ptk/event ::ev/event
|
||||||
{::ev/name "copy-handoff-style"
|
{::ev/name "copy-handoff-style"
|
||||||
:type @style-type}))))
|
:type @style-type}))))]
|
||||||
]
|
|
||||||
|
|
||||||
[:div.element-options
|
[:div.element-options
|
||||||
[:div.code-block
|
[:div.code-block
|
||||||
[:div.code-row-lang "CSS"
|
[:div.code-row-lang "CSS"
|
||||||
|
|
||||||
[:button.expand-button
|
[:button.expand-button
|
||||||
{:on-click on-expand }
|
{:on-click on-expand}
|
||||||
i/full-screen]
|
i/full-screen]
|
||||||
|
|
||||||
[:& copy-button {:data style-code
|
[:& copy-button {:data style-code
|
||||||
|
@ -96,6 +107,4 @@
|
||||||
:on-copied on-markup-copied}]]
|
:on-copied on-markup-copied}]]
|
||||||
[:div.code-row-display
|
[:div.code-row-display
|
||||||
[:& code-block {:type @markup-type
|
[:& code-block {:type @markup-type
|
||||||
:code markup-code}]]]
|
:code markup-code}]]]]))
|
||||||
|
|
||||||
]))
|
|
||||||
|
|
|
@ -375,7 +375,9 @@
|
||||||
has-group? (->> shapes (d/seek cph/group-shape?))
|
has-group? (->> shapes (d/seek cph/group-shape?))
|
||||||
is-group? (and single? has-group?)
|
is-group? (and single? has-group?)
|
||||||
ids (->> shapes (map :id))
|
ids (->> shapes (map :id))
|
||||||
add-flex #(st/emit! (dwsl/create-layout-from-selection :flex))
|
add-flex #(st/emit! (if is-frame?
|
||||||
|
(dwsl/create-layout ids :flex)
|
||||||
|
(dwsl/create-layout-from-selection :flex)))
|
||||||
remove-flex #(st/emit! (dwsl/remove-layout ids))]
|
remove-flex #(st/emit! (dwsl/remove-layout ids))]
|
||||||
(cond
|
(cond
|
||||||
(or (not single?) (and is-frame? (not is-flex-container?)) is-group?)
|
(or (not single?) (and is-frame? (not is-flex-container?)) is-group?)
|
||||||
|
|
|
@ -34,7 +34,14 @@
|
||||||
(mf/defc margin-section
|
(mf/defc margin-section
|
||||||
[{:keys [values change-margin-style on-margin-change] :as props}]
|
[{:keys [values change-margin-style on-margin-change] :as props}]
|
||||||
|
|
||||||
(let [margin-type (or (:layout-item-margin-type values) :simple)]
|
(let [margin-type (or (:layout-item-margin-type values) :simple)
|
||||||
|
margins (if (nil? (:layout-item-margin values))
|
||||||
|
{:m1 0 :m2 0 :m3 0 :m4 0}
|
||||||
|
(:layout-item-margin values))
|
||||||
|
rx (if (and (not (= :multiple (:layout-item-margin-type values)))
|
||||||
|
(apply = (vals margins)))
|
||||||
|
(:m1 margins)
|
||||||
|
"--")]
|
||||||
|
|
||||||
[:div.margin-row
|
[:div.margin-row
|
||||||
[:div.margin-icons
|
[:div.margin-icons
|
||||||
|
@ -59,7 +66,7 @@
|
||||||
{:placeholder "--"
|
{:placeholder "--"
|
||||||
:on-click #(dom/select-target %)
|
:on-click #(dom/select-target %)
|
||||||
:on-change (partial on-margin-change :simple)
|
:on-change (partial on-margin-change :simple)
|
||||||
:value (or (-> values :layout-item-margin :m1) 0)}]]]
|
:value rx}]]]
|
||||||
|
|
||||||
(= margin-type :multiple)
|
(= margin-type :multiple)
|
||||||
(for [num [:m1 :m2 :m3 :m4]]
|
(for [num [:m1 :m2 :m3 :m4]]
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
(if (= style :inner-shadow) "inset " "")
|
(if (= style :inner-shadow) "inset " "")
|
||||||
(str/fmt "%spx %spx %spx %spx %s" offset-x offset-y blur spread css-color))))
|
(str/fmt "%spx %spx %spx %spx %s" offset-x offset-y blur spread css-color))))
|
||||||
|
|
||||||
|
(defn format-gap
|
||||||
|
[{row-gap :row-gap column-gap :column-gap}]
|
||||||
|
(if (= row-gap column-gap)
|
||||||
|
(str/fmt "%spx" row-gap)
|
||||||
|
(str/fmt "%spx %spx" row-gap column-gap)))
|
||||||
|
|
||||||
(defn format-fill-color [_ shape]
|
(defn format-fill-color [_ shape]
|
||||||
(let [color {:color (:fill-color shape)
|
(let [color {:color (:fill-color shape)
|
||||||
|
@ -37,27 +42,50 @@
|
||||||
(str/format "%spx %s %s" width style (uc/color->background color)))))
|
(str/format "%spx %s %s" width style (uc/color->background color)))))
|
||||||
|
|
||||||
(def styles-data
|
(def styles-data
|
||||||
{:layout {:props [:width :height :x :y :radius :rx :r1]
|
{:layout {:props [:width :height :x :y :radius :rx :r1]
|
||||||
:to-prop {:x "left"
|
:to-prop {:x "left"
|
||||||
:y "top"
|
:y "top"
|
||||||
:rotation "transform"
|
:rotation "transform"
|
||||||
:rx "border-radius"
|
:rx "border-radius"
|
||||||
:r1 "border-radius"}
|
:r1 "border-radius"}
|
||||||
:format {:rotation #(str/fmt "rotate(%sdeg)" %)
|
:format {:rotation #(str/fmt "rotate(%sdeg)" %)
|
||||||
:r1 #(apply str/fmt "%spx, %spx, %spx, %spx" %)}
|
:r1 #(apply str/fmt "%spx, %spx, %spx, %spx" %)
|
||||||
:multi {:r1 [:r1 :r2 :r3 :r4]}}
|
:width (partial fmt/format-size :width)
|
||||||
:fill {:props [:fill-color :fill-color-gradient]
|
:height (partial fmt/format-size :height)}
|
||||||
:to-prop {:fill-color "background" :fill-color-gradient "background"}
|
:multi {:r1 [:r1 :r2 :r3 :r4]}}
|
||||||
:format {:fill-color format-fill-color :fill-color-gradient format-fill-color}}
|
:fill {:props [:fill-color :fill-color-gradient]
|
||||||
:stroke {:props [:stroke-style]
|
:to-prop {:fill-color "background" :fill-color-gradient "background"}
|
||||||
:to-prop {:stroke-style "border"}
|
:format {:fill-color format-fill-color :fill-color-gradient format-fill-color}}
|
||||||
:format {:stroke-style format-stroke}}
|
:stroke {:props [:stroke-style]
|
||||||
:shadow {:props [:shadow]
|
:to-prop {:stroke-style "border"}
|
||||||
:to-prop {:shadow :box-shadow}
|
:format {:stroke-style format-stroke}}
|
||||||
:format {:shadow #(str/join ", " (map shadow->css %1))}}
|
:shadow {:props [:shadow]
|
||||||
:blur {:props [:blur]
|
:to-prop {:shadow :box-shadow}
|
||||||
:to-prop {:blur "filter"}
|
:format {:shadow #(str/join ", " (map shadow->css %1))}}
|
||||||
:format {:blur #(str/fmt "blur(%spx)" (:value %))}}})
|
:blur {:props [:blur]
|
||||||
|
:to-prop {:blur "filter"}
|
||||||
|
:format {:blur #(str/fmt "blur(%spx)" (:value %))}}
|
||||||
|
:layout-flex {:props [:layout
|
||||||
|
:layout-align-items
|
||||||
|
:layout-flex-dir
|
||||||
|
:layout-justify-content
|
||||||
|
:layout-gap
|
||||||
|
:layout-padding
|
||||||
|
:layout-wrap-type]
|
||||||
|
:to-prop {:layout "display"
|
||||||
|
:layout-flex-dir "flex-direction"
|
||||||
|
:layout-align-items "align-items"
|
||||||
|
:layout-justify-content "justify-content"
|
||||||
|
:layout-wrap-type "flex-wrap"
|
||||||
|
:layout-gap "gap"
|
||||||
|
:layout-padding "padding"}
|
||||||
|
:format {:layout name
|
||||||
|
:layout-flex-dir name
|
||||||
|
:layout-align-items name
|
||||||
|
:layout-justify-content name
|
||||||
|
:layout-wrap-type name
|
||||||
|
:layout-gap format-gap
|
||||||
|
:layout-padding fmt/format-padding}}})
|
||||||
|
|
||||||
(def style-text
|
(def style-text
|
||||||
{:props [:fill-color
|
{:props [:fill-color
|
||||||
|
@ -78,6 +106,26 @@
|
||||||
:text-transform name
|
:text-transform name
|
||||||
:fill-color format-fill-color}})
|
:fill-color format-fill-color}})
|
||||||
|
|
||||||
|
(def layout-flex-item-params
|
||||||
|
{:props [:layout-item-margin
|
||||||
|
:layout-item-max-h
|
||||||
|
:layout-item-min-h
|
||||||
|
:layout-item-max-w
|
||||||
|
:layout-item-min-w
|
||||||
|
:layout-item-align-self]
|
||||||
|
:to-prop {:layout-item-margin "margin"
|
||||||
|
:layout-item-max-h "max-height"
|
||||||
|
:layout-item-min-h "min-height"
|
||||||
|
:layout-item-max-w "max-width"
|
||||||
|
:layout-item-min-w "min-width"
|
||||||
|
:layout-item-align-self "align-self"}
|
||||||
|
:format {:layout-item-margin fmt/format-margin
|
||||||
|
:layout-item-max-h #(str % "px")
|
||||||
|
:layout-item-min-h #(str % "px")
|
||||||
|
:layout-item-max-w #(str % "px")
|
||||||
|
:layout-item-min-w #(str % "px")
|
||||||
|
:layout-item-align-self name}})
|
||||||
|
|
||||||
(defn generate-css-props
|
(defn generate-css-props
|
||||||
([values properties]
|
([values properties]
|
||||||
(generate-css-props values properties nil))
|
(generate-css-props values properties nil))
|
||||||
|
@ -126,10 +174,24 @@
|
||||||
(str/join "\n")))))
|
(str/join "\n")))))
|
||||||
|
|
||||||
(defn shape->properties [shape]
|
(defn shape->properties [shape]
|
||||||
(let [props (->> styles-data vals (mapcat :props))
|
(let [;; This property is added in an earlier step (code.cljs),
|
||||||
to-prop (->> styles-data vals (map :to-prop) (reduce merge))
|
;; it will come with a vector of flex-items if any.
|
||||||
format (->> styles-data vals (map :format) (reduce merge))
|
;; If there are none it will continue as usual.
|
||||||
multi (->> styles-data vals (map :multi) (reduce merge))]
|
flex-items (:flex-items shape)
|
||||||
|
|
||||||
|
props (->> styles-data vals (mapcat :props))
|
||||||
|
to-prop (->> styles-data vals (map :to-prop) (reduce merge))
|
||||||
|
format (->> styles-data vals (map :format) (reduce merge))
|
||||||
|
multi (->> styles-data vals (map :multi) (reduce merge))
|
||||||
|
props (if (seq flex-items)
|
||||||
|
(concat props (:props layout-flex-item-params))
|
||||||
|
props)
|
||||||
|
to-prop (if (seq flex-items)
|
||||||
|
(merge to-prop (:to-prop layout-flex-item-params))
|
||||||
|
to-prop)
|
||||||
|
format (if (seq flex-items)
|
||||||
|
(merge format (:format layout-flex-item-params))
|
||||||
|
format)]
|
||||||
(generate-css-props shape props {:to-prop to-prop
|
(generate-css-props shape props {:to-prop to-prop
|
||||||
:format format
|
:format format
|
||||||
:multi multi
|
:multi multi
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue