Add code block to layout elements

This commit is contained in:
Eva 2022-11-16 12:54:16 +01:00
parent 93bbe1b2f8
commit 2a2b5c7dba
12 changed files with 272 additions and 148 deletions

View file

@ -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})

View file

@ -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]

View file

@ -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 =))

View file

@ -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]))

View file

@ -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]
@ -60,4 +61,34 @@
{:p1 p1 :p2 p2 :p3 p3} {:p1 p1 :p2 p2 :p3 p3}
: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))))

View file

@ -23,29 +23,31 @@
: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
([shape] ([shape]
(apply copy-data shape properties)) (apply copy-data shape properties))
([shape & properties] ([shape & properties]
(cg/generate-css-props shape properties params))) (cg/generate-css-props shape properties params)))
(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

View file

@ -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)}]]

View file

@ -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)}]])
(when (:layout-item-h-sizing shape)
[:div.attributes-unit-row
[:div.attributes-label "Horizontal sizing"]
[: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 "Margin"] [:div.attributes-unit-row
[:& manage-margin {:margin (:layout-item-margin shape) :type "margin"}] [:div.attributes-label "Vertical sizing"]
[:& copy-button {:data (copy-data shape :layout-item-margin)}]] [:div.attributes-value (manage-sizing (:layout-item-v-sizing shape) :v)]
[:& copy-button {:data (copy-data shape :layout-item-v-sizing)}]])
(when (= :fill (:layout-item-h-sizing shape))
[:*
(when (some? (:layout-item-max-w shape))
[: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. width"] [:div.attributes-unit-row
[:div.attributes-value (fmt/format-pixels (:layout-item-max-w shape))] [:div.attributes-label "Min. width"]
[:& copy-button {:data (copy-data shape :layout-item-max-w)}]] [: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. width"] [:*
[: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-w)}]] [: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)}]])
[:div.attributes-unit-row (when (:layout-item-min-h 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. height"]
[:& copy-button {:data (copy-data shape :layout-item-max-h)}]] [:div.attributes-value (fmt/format-pixels (:layout-item-min-h shape))]
[:& copy-button {:data (copy-data shape :layout-item-min-h)}]])])]))
[:div.attributes-unit-row
[:div.attributes-label "Min. height"]
[:div.attributes-value (fmt/format-pixels (:layout-item-min-w shape))]
[:& copy-button {:data (copy-data shape :layout-item-min-h)}]]])
(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 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}]])))

View file

@ -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}]]]]))
]))

View file

@ -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?)

View file

@ -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]]

View file

@ -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