mirror of
https://github.com/penpot/penpot.git
synced 2025-07-22 13:47:16 +02:00
✨ Update info panel
This commit is contained in:
parent
c3a8c3826d
commit
a2c59acfa9
27 changed files with 1040 additions and 1144 deletions
|
@ -6,553 +6,21 @@
|
|||
|
||||
(ns app.util.code-gen
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.config :as cfg]
|
||||
[app.main.render :as render]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.shapes.text.html-text :as text]
|
||||
[app.util.color :as uc]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn shadow->css [shadow]
|
||||
(let [{:keys [style offset-x offset-y blur spread]} shadow
|
||||
css-color (uc/color->background (:color shadow))]
|
||||
(dm/str
|
||||
(if (= style :inner-shadow) "inset " "")
|
||||
(str/fmt "%spx %spx %spx %spx %s" offset-x offset-y blur spread css-color))))
|
||||
|
||||
(defn fill-color->background
|
||||
[fill]
|
||||
(cond
|
||||
(not= (:fill-opacity fill) 1)
|
||||
(uc/color->background {:color (:fill-color fill)
|
||||
:opacity (:fill-opacity fill)
|
||||
:gradient (:fill-color-gradient fill)})
|
||||
|
||||
:else
|
||||
(str/upper (:fill-color fill))))
|
||||
|
||||
(defn format-fill-color [_ shape]
|
||||
(let [fills (:fills shape)
|
||||
first-fill (first fills)
|
||||
colors (if (> (count fills) 1)
|
||||
(map (fn [fill]
|
||||
(let [color (fill-color->background fill)]
|
||||
(if (some? (:fill-color-gradient fill))
|
||||
color
|
||||
(str/format "linear-gradient(%s,%s)" color color))))
|
||||
(:fills shape))
|
||||
[(fill-color->background first-fill)])]
|
||||
(str/join ", " colors)))
|
||||
|
||||
(defn format-stroke [shape]
|
||||
(let [first-stroke (first (:strokes shape))
|
||||
width (:stroke-width first-stroke)
|
||||
style (let [style (:stroke-style first-stroke)]
|
||||
(when (keyword? style) (d/name style)))
|
||||
color {:color (:stroke-color first-stroke)
|
||||
:opacity (:stroke-opacity first-stroke)
|
||||
:gradient (:stroke-color-gradient first-stroke)}]
|
||||
(when-not (= :none (:stroke-style first-stroke))
|
||||
(str/format "%spx %s %s" width style (uc/color->background color)))))
|
||||
|
||||
(defn format-position [objects]
|
||||
(fn [_ shape]
|
||||
(cond
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape))
|
||||
(or (cph/group-shape? shape)
|
||||
(cph/frame-shape? shape)))
|
||||
"relative"
|
||||
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
nil
|
||||
|
||||
:else
|
||||
"absolute")))
|
||||
|
||||
(defn mk-grid-coord
|
||||
[objects prop span-prop]
|
||||
|
||||
(fn [_ shape]
|
||||
(when (ctl/grid-layout-immediate-child? objects shape)
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(if (> (get cell span-prop) 1)
|
||||
(dm/str (get cell prop) " / " (+ (get cell prop) (get cell span-prop)))
|
||||
(get cell prop))))))
|
||||
|
||||
(defn get-size
|
||||
[type values]
|
||||
(let [value (cond
|
||||
(number? values) values
|
||||
(string? values) values
|
||||
(type values) (type values)
|
||||
:else (type (:selrect values)))]
|
||||
|
||||
(if (= :width type)
|
||||
(fmt/format-size :width value values)
|
||||
(fmt/format-size :heigth value values))))
|
||||
|
||||
(defn make-format-absolute-pos
|
||||
[objects shape coord]
|
||||
(fn [value]
|
||||
(let [parent-id (dm/get-in objects [(:id shape) :parent-id])
|
||||
parent-value (dm/get-in objects [parent-id :selrect coord])]
|
||||
(when-not (or (cph/root-frame? shape)
|
||||
(ctl/any-layout-immediate-child? objects shape)
|
||||
(ctl/layout-absolute? shape))
|
||||
(fmt/format-pixels (- value parent-value))))))
|
||||
|
||||
(defn format-tracks
|
||||
[tracks]
|
||||
(str/join
|
||||
" "
|
||||
(->> tracks (map (fn [{:keys [type value]}]
|
||||
(case type
|
||||
:flex (dm/str (fmt/format-number value) "fr")
|
||||
:percent (fmt/format-percent (/ value 100))
|
||||
:auto "auto"
|
||||
(fmt/format-pixels value)))))))
|
||||
|
||||
(defn styles-data
|
||||
[objects shape]
|
||||
{:position {:props [:type]
|
||||
:to-prop {:type "position"}
|
||||
:format {:type (format-position objects)}}
|
||||
:layout {:props (if (or (empty? (:flex-items shape))
|
||||
(ctl/layout-absolute? shape))
|
||||
[:x :y :width :height :radius :rx :r1]
|
||||
[:width :height :radius :rx :r1])
|
||||
:to-prop {:x "left"
|
||||
:y "top"
|
||||
:rotation "transform"
|
||||
:rx "border-radius"
|
||||
:r1 "border-radius"}
|
||||
:format {:rotation #(str/fmt "rotate(%sdeg)" %)
|
||||
:r1 #(apply str/fmt "%spx %spx %spx %spx" %)
|
||||
:width #(get-size :width %)
|
||||
:height #(get-size :height %)
|
||||
:x (make-format-absolute-pos objects shape :x)
|
||||
:y (make-format-absolute-pos objects shape :y)}
|
||||
:multi {:r1 [:r1 :r2 :r3 :r4]}}
|
||||
:fill {:props [:fills]
|
||||
:to-prop {:fills (cond
|
||||
(or (cph/path-shape? shape)
|
||||
(cph/mask-shape? shape)
|
||||
(cph/bool-shape? shape)
|
||||
(cph/svg-raw-shape? shape)
|
||||
(some? (:svg-attrs shape)))
|
||||
nil
|
||||
|
||||
(> (count (:fills shape)) 1)
|
||||
"background-image"
|
||||
|
||||
(and (= (count (:fills shape)) 1)
|
||||
(some? (:fill-color-gradient (first (:fills shape)))))
|
||||
"background"
|
||||
|
||||
:else
|
||||
"background-color")}
|
||||
:format {:fills format-fill-color}}
|
||||
:stroke {:props [:strokes]
|
||||
:to-prop {:strokes "border"}
|
||||
:format {:strokes (fn [_ shape]
|
||||
(when-not (or (cph/path-shape? shape)
|
||||
(cph/mask-shape? shape)
|
||||
(cph/bool-shape? shape)
|
||||
(cph/svg-raw-shape? shape)
|
||||
(some? (:svg-attrs shape)))
|
||||
(format-stroke shape)))}}
|
||||
:shadow {:props [:shadow]
|
||||
:to-prop {:shadow :box-shadow}
|
||||
:format {:shadow #(str/join ", " (map shadow->css %1))}}
|
||||
:blur {:props [:blur]
|
||||
:to-prop {:blur "filter"}
|
||||
:format {:blur #(str/fmt "blur(%spx)" (:value %))}}
|
||||
|
||||
:layout-flex {:props [:layout
|
||||
:layout-flex-dir
|
||||
:layout-align-items
|
||||
:layout-justify-items
|
||||
:layout-align-content
|
||||
:layout-justify-content
|
||||
:layout-gap
|
||||
:layout-padding
|
||||
:layout-wrap-type]
|
||||
:gen-props [:flex-shrink]
|
||||
:to-prop {:layout "display"
|
||||
:layout-flex-dir "flex-direction"
|
||||
:layout-align-items "align-items"
|
||||
:layout-align-content "align-content"
|
||||
:layout-justify-items "justify-items"
|
||||
:layout-justify-content "justify-content"
|
||||
:layout-wrap-type "flex-wrap"
|
||||
:layout-gap "gap"
|
||||
:layout-padding "padding"}
|
||||
:format {:layout d/name
|
||||
:layout-flex-dir d/name
|
||||
:layout-align-items d/name
|
||||
:layout-align-content d/name
|
||||
:layout-justify-items d/name
|
||||
:layout-justify-content d/name
|
||||
:layout-wrap-type d/name
|
||||
:layout-gap fmt/format-gap
|
||||
:layout-padding fmt/format-padding
|
||||
:flex-shrink (fn [_ shape] (when (ctl/flex-layout-immediate-child? objects shape) 0))}}
|
||||
|
||||
:layout-grid {:props [:layout-grid-rows
|
||||
:layout-grid-columns]
|
||||
:gen-props [:grid-column
|
||||
:grid-row]
|
||||
:to-prop {:layout-grid-rows "grid-template-rows"
|
||||
:layout-grid-columns "grid-template-columns"}
|
||||
:format {:layout-grid-rows format-tracks
|
||||
:layout-grid-columns format-tracks
|
||||
:grid-column (mk-grid-coord objects :column :column-span)
|
||||
:grid-row (mk-grid-coord objects :row :row-span)}}})
|
||||
|
||||
(def style-text
|
||||
{:props [:fills
|
||||
:font-family
|
||||
:font-style
|
||||
:font-size
|
||||
:font-weight
|
||||
:line-height
|
||||
:letter-spacing
|
||||
:text-decoration
|
||||
:text-transform]
|
||||
:to-prop {:fills "color"}
|
||||
:format {:font-family #(dm/str "'" % "'")
|
||||
:font-style #(dm/str %)
|
||||
:font-size #(dm/str % "px")
|
||||
:font-weight #(dm/str %)
|
||||
:line-height #(dm/str %)
|
||||
:letter-spacing #(dm/str % "px")
|
||||
:text-decoration d/name
|
||||
:text-transform d/name
|
||||
:fills 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 #(dm/str % "px")
|
||||
:layout-item-min-h #(dm/str % "px")
|
||||
:layout-item-max-w #(dm/str % "px")
|
||||
:layout-item-min-w #(dm/str % "px")
|
||||
:layout-item-align-self d/name}})
|
||||
|
||||
(def layout-align-content
|
||||
{:props [:layout-align-content]
|
||||
:to-prop {:layout-align-content "align-content"}
|
||||
:format {:layout-align-content d/name}})
|
||||
|
||||
(defn get-specific-value
|
||||
[values prop]
|
||||
(let [result (if (get values prop)
|
||||
(get values prop)
|
||||
(get (:selrect values) prop))
|
||||
result (if (= :width prop)
|
||||
(get-size :width values)
|
||||
result)
|
||||
result (if (= :height prop)
|
||||
(get-size :height values)
|
||||
result)]
|
||||
|
||||
result))
|
||||
|
||||
(defn generate-css-props
|
||||
([values properties]
|
||||
(generate-css-props values properties [] nil))
|
||||
|
||||
([values properties gen-properties]
|
||||
(generate-css-props values properties gen-properties nil))
|
||||
|
||||
([values properties gen-properties params]
|
||||
(let [{:keys [to-prop format tab-size multi]
|
||||
:or {to-prop {} tab-size 0 multi {}}} params
|
||||
|
||||
;; We allow the :format and :to-prop to be a map for different properties
|
||||
;; or just a value for a single property. This code transform a single
|
||||
;; property to a uniform one
|
||||
properties (if-not (coll? properties) [properties] properties)
|
||||
|
||||
format (if (not (map? format))
|
||||
(into {} (map #(vector % format) properties))
|
||||
format)
|
||||
|
||||
to-prop (if (not (map? to-prop))
|
||||
(into {} (map #(vector % to-prop) properties))
|
||||
to-prop)
|
||||
|
||||
get-value (fn [prop]
|
||||
(if-let [props (get multi prop)]
|
||||
(map #(get values %) props)
|
||||
(get-specific-value values prop)))
|
||||
|
||||
null? (fn [value]
|
||||
(if (coll? value)
|
||||
(every? #(or (nil? %) (= % 0)) value)
|
||||
(or (nil? value) (= value 0))))
|
||||
|
||||
default-format (fn [value] (dm/str (fmt/format-pixels value)))
|
||||
|
||||
format-property
|
||||
(fn [prop]
|
||||
(let [css-prop (or (get to-prop prop) (d/name prop))
|
||||
format-fn (or (get format prop) default-format)
|
||||
css-val (format-fn (get-value prop) values)]
|
||||
(when (and css-val (not= css-val ""))
|
||||
(dm/str
|
||||
(str/repeat " " tab-size)
|
||||
(dm/fmt "%: %;" css-prop css-val)))))]
|
||||
|
||||
(->> (concat
|
||||
(->> properties
|
||||
(remove #(null? (get-value %))))
|
||||
gen-properties)
|
||||
(keep format-property)
|
||||
(str/join "\n")))))
|
||||
|
||||
(defn shape->properties [objects shape]
|
||||
(let [;; This property is added in an earlier step (code.cljs),
|
||||
;; it will come with a vector of flex-items if any.
|
||||
;; If there are none it will continue as usual.
|
||||
flex-items (:flex-items shape)
|
||||
props (->> (styles-data objects shape) vals (mapcat :props))
|
||||
to-prop (->> (styles-data objects shape) vals (map :to-prop) (reduce merge))
|
||||
format (->> (styles-data objects shape) vals (map :format) (reduce merge))
|
||||
multi (->> (styles-data objects shape) vals (map :multi) (reduce merge))
|
||||
gen-props (->> (styles-data objects shape) vals (mapcat :gen-props))
|
||||
|
||||
props (cond-> props
|
||||
(seq flex-items) (concat (:props layout-flex-item-params))
|
||||
(= :wrap (:layout-wrap-type shape)) (concat (:props layout-align-content)))
|
||||
to-prop (cond-> to-prop
|
||||
(seq flex-items) (merge (:to-prop layout-flex-item-params))
|
||||
(= :wrap (:layout-wrap-type shape)) (merge (:to-prop layout-align-content)))
|
||||
format (cond-> format
|
||||
(seq flex-items) (merge (:format layout-flex-item-params))
|
||||
(= :wrap (:layout-wrap-type shape)) (merge (:format layout-align-content)))]
|
||||
(generate-css-props
|
||||
shape
|
||||
props
|
||||
gen-props
|
||||
{:to-prop to-prop
|
||||
:format format
|
||||
:multi multi
|
||||
:tab-size 2})))
|
||||
|
||||
(defn search-text-attrs
|
||||
[node attrs]
|
||||
(->> (txt/node-seq node)
|
||||
(map #(select-keys % attrs))
|
||||
(reduce d/merge)))
|
||||
|
||||
|
||||
;; TODO: used on inspect
|
||||
(defn parse-style-text-blocks
|
||||
[node attrs]
|
||||
(letfn
|
||||
[(rec-style-text-map [acc node style]
|
||||
(let [node-style (merge style (select-keys node attrs))
|
||||
head (or (-> acc first) [{} ""])
|
||||
[head-style head-text] head
|
||||
|
||||
new-acc
|
||||
(cond
|
||||
(:children node)
|
||||
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
|
||||
|
||||
(not= head-style node-style)
|
||||
(cons [node-style (:text node "")] acc)
|
||||
|
||||
:else
|
||||
(cons [node-style (dm/str head-text "" (:text node))] (rest acc)))
|
||||
|
||||
;; We add an end-of-line when finish a paragraph
|
||||
new-acc
|
||||
(if (= (:type node) "paragraph")
|
||||
(let [[hs ht] (first new-acc)]
|
||||
(cons [hs (dm/str ht "\n")] (rest new-acc)))
|
||||
new-acc)]
|
||||
new-acc))]
|
||||
|
||||
(-> (rec-style-text-map [] node {})
|
||||
reverse)))
|
||||
|
||||
(defn text->properties [objects shape]
|
||||
(let [flex-items (:flex-items shape)
|
||||
text-shape-style (d/without-keys (styles-data objects shape) [:fill :stroke])
|
||||
|
||||
shape-props (->> text-shape-style vals (mapcat :props))
|
||||
shape-to-prop (->> text-shape-style vals (map :to-prop) (reduce merge))
|
||||
shape-format (->> text-shape-style vals (map :format) (reduce merge))
|
||||
|
||||
shape-props (cond-> shape-props
|
||||
(seq flex-items) (concat (:props layout-flex-item-params)))
|
||||
shape-to-prop (cond-> shape-to-prop
|
||||
(seq flex-items) (merge (:to-prop layout-flex-item-params)))
|
||||
shape-format (cond-> shape-format
|
||||
(seq flex-items) (merge (:format layout-flex-item-params)))
|
||||
|
||||
text-values (->> (search-text-attrs
|
||||
(:content shape)
|
||||
(conj (:props style-text) :fill-color-gradient :fill-opacity))
|
||||
(d/merge txt/default-text-attrs))]
|
||||
|
||||
(str/join
|
||||
"\n"
|
||||
[(generate-css-props shape
|
||||
shape-props
|
||||
{:to-prop shape-to-prop
|
||||
:format shape-format
|
||||
:tab-size 2})
|
||||
(generate-css-props text-values
|
||||
(:props style-text)
|
||||
{:to-prop (:to-prop style-text)
|
||||
:format (:format style-text)
|
||||
:tab-size 2})])))
|
||||
|
||||
(defn selector-name [shape]
|
||||
(let [name (-> (:name shape)
|
||||
(subs 0 (min 10 (count (:name shape)))))
|
||||
;; selectors cannot start with numbers
|
||||
name (if (re-matches #"^\d.*" name) (dm/str "c-" name) name)
|
||||
id (-> (dm/str (:id shape))
|
||||
#_(subs 24 36))
|
||||
selector (str/css-selector (dm/str name " " id))
|
||||
selector (if (str/starts-with? selector "-") (subs selector 1) selector)]
|
||||
selector))
|
||||
|
||||
(defn generate-css [objects shape]
|
||||
(let [name (:name shape)
|
||||
properties (shape->properties objects shape)
|
||||
selector (selector-name shape)]
|
||||
(str/join "\n" [(str/fmt "/* %s */" name)
|
||||
(str/fmt ".%s {" selector)
|
||||
properties
|
||||
"}"])))
|
||||
|
||||
(defn generate-svg
|
||||
[objects shape-id]
|
||||
(let [shape (get objects shape-id)]
|
||||
(rds/renderToStaticMarkup
|
||||
(mf/element
|
||||
render/object-svg
|
||||
#js {:objects objects
|
||||
:object-id (-> shape :id)}))))
|
||||
|
||||
(defn generate-html
|
||||
([objects shape-id]
|
||||
(generate-html objects shape-id 0))
|
||||
|
||||
([objects shape-id level]
|
||||
(let [shape (get objects shape-id)
|
||||
indent (str/repeat " " level)
|
||||
maybe-reverse (if (ctl/any-layout? shape) reverse identity)]
|
||||
(cond
|
||||
(cph/text-shape? shape)
|
||||
(let [text-shape-html (rds/renderToStaticMarkup (mf/element text/text-shape #js {:shape shape :code? true}))]
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(selector-name shape)
|
||||
text-shape-html
|
||||
indent))
|
||||
|
||||
(cph/image-shape? shape)
|
||||
(let [data (or (:metadata shape) (:fill-image shape))
|
||||
image-url (cfg/resolve-file-media data)]
|
||||
(dm/fmt "%<img src=\"%\" class=\"%\">\n%</img>"
|
||||
indent
|
||||
image-url
|
||||
(selector-name shape)
|
||||
indent))
|
||||
|
||||
(or (cph/path-shape? shape)
|
||||
(cph/mask-shape? shape)
|
||||
(cph/bool-shape? shape)
|
||||
(cph/svg-raw-shape? shape)
|
||||
(some? (:svg-attrs shape)))
|
||||
(let [svg-markup (rds/renderToStaticMarkup (mf/element render/object-svg #js {:objects objects :object-id (:id shape) :render-embed? false}))]
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(selector-name shape)
|
||||
svg-markup
|
||||
indent))
|
||||
|
||||
(empty? (:shapes shape))
|
||||
(dm/fmt "%<div class=\"%\">\n%</div>"
|
||||
indent
|
||||
(selector-name shape)
|
||||
indent)
|
||||
|
||||
:else
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(selector-name shape)
|
||||
(->> (:shapes shape)
|
||||
(maybe-reverse)
|
||||
(map #(generate-html objects % (inc level)))
|
||||
(str/join "\n"))
|
||||
indent)))))
|
||||
|
||||
(defn generate-markup-code [objects type shapes]
|
||||
(let [generate-markup-fn (case type
|
||||
"html" generate-html
|
||||
"svg" generate-svg)]
|
||||
(->> shapes
|
||||
(map #(generate-markup-fn objects % 0))
|
||||
(str/join "\n"))))
|
||||
|
||||
(defn generate-style-code [objects type shapes]
|
||||
(let [generate-style-fn (case type
|
||||
"css" generate-css)]
|
||||
(dm/str
|
||||
"html, body {
|
||||
background-color: #E8E9EA;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
\n"
|
||||
(->> shapes
|
||||
(map (partial generate-style-fn objects))
|
||||
(str/join "\n\n")))))
|
||||
[app.util.code-gen.markup-html :as html]
|
||||
[app.util.code-gen.markup-svg :as svg]
|
||||
[app.util.code-gen.style-css :as css]))
|
||||
|
||||
(defn generate-markup-code
|
||||
[objects type shapes]
|
||||
(let [generate-markup
|
||||
(case type
|
||||
"html" html/generate-markup
|
||||
"svg" svg/generate-markup)]
|
||||
(generate-markup objects shapes)))
|
||||
|
||||
(defn generate-style-code
|
||||
[objects type shapes]
|
||||
(let [generate-style
|
||||
(case type
|
||||
"css" css/generate-style)]
|
||||
(generate-style objects shapes)))
|
||||
|
|
22
frontend/src/app/util/code_gen/common.cljs
Normal file
22
frontend/src/app/util/code_gen/common.cljs
Normal file
|
@ -0,0 +1,22 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.util.code-gen.common
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn shape->selector
|
||||
[shape]
|
||||
(let [name (-> (:name shape)
|
||||
(subs 0 (min 10 (count (:name shape)))))
|
||||
;; selectors cannot start with numbers
|
||||
name (if (re-matches #"^\d.*" name) (dm/str "c-" name) name)
|
||||
id (-> (dm/str (:id shape))
|
||||
#_(subs 24 36))
|
||||
selector (str/css-selector (dm/str name " " id))
|
||||
selector (if (str/starts-with? selector "-") (subs selector 1) selector)]
|
||||
selector))
|
78
frontend/src/app/util/code_gen/markup_html.cljs
Normal file
78
frontend/src/app/util/code_gen/markup_html.cljs
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.util.code-gen.markup-html
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.config :as cfg]
|
||||
[app.main.ui.shapes.text.html-text :as text]
|
||||
[app.util.code-gen.common :as cgc]
|
||||
[app.util.code-gen.markup-svg :refer [generate-svg]]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn generate-html
|
||||
([objects shape]
|
||||
(generate-html objects shape 0))
|
||||
|
||||
([objects shape level]
|
||||
(let [indent (str/repeat " " level)
|
||||
maybe-reverse (if (ctl/any-layout? shape) reverse identity)]
|
||||
|
||||
(cond
|
||||
(cph/text-shape? shape)
|
||||
(let [text-shape-html (rds/renderToStaticMarkup (mf/element text/text-shape #js {:shape shape :code? true}))]
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(cgc/shape->selector shape)
|
||||
text-shape-html
|
||||
indent))
|
||||
|
||||
(cph/image-shape? shape)
|
||||
(let [data (or (:metadata shape) (:fill-image shape))
|
||||
image-url (cfg/resolve-file-media data)]
|
||||
(dm/fmt "%<img src=\"%\" class=\"%\">\n%</img>"
|
||||
indent
|
||||
image-url
|
||||
(cgc/shape->selector shape)
|
||||
indent))
|
||||
|
||||
(or (cph/path-shape? shape)
|
||||
(cph/mask-shape? shape)
|
||||
(cph/bool-shape? shape)
|
||||
(cph/svg-raw-shape? shape)
|
||||
(some? (:svg-attrs shape)))
|
||||
(let [svg-markup (generate-svg objects shape)]
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(cgc/shape->selector shape)
|
||||
svg-markup
|
||||
indent))
|
||||
|
||||
(empty? (:shapes shape))
|
||||
(dm/fmt "%<div class=\"%\">\n%</div>"
|
||||
indent
|
||||
(cgc/shape->selector shape)
|
||||
indent)
|
||||
|
||||
:else
|
||||
(dm/fmt "%<div class=\"%\">\n%\n%</div>"
|
||||
indent
|
||||
(cgc/shape->selector shape)
|
||||
(->> (:shapes shape)
|
||||
(maybe-reverse)
|
||||
(map #(generate-html objects (get objects %) (inc level)))
|
||||
(str/join "\n"))
|
||||
indent)))))
|
||||
|
||||
(defn generate-markup
|
||||
[objects shapes]
|
||||
(->> shapes
|
||||
(map #(generate-html objects %))
|
||||
(str/join "\n")))
|
26
frontend/src/app/util/code_gen/markup_svg.cljs
Normal file
26
frontend/src/app/util/code_gen/markup_svg.cljs
Normal file
|
@ -0,0 +1,26 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.util.code-gen.markup-svg
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.main.render :as render]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn generate-svg
|
||||
[objects shape]
|
||||
(rds/renderToStaticMarkup
|
||||
(mf/element
|
||||
render/object-svg
|
||||
#js {:objects objects
|
||||
:object-id (-> shape :id)})))
|
||||
|
||||
(defn generate-markup
|
||||
[objects shapes]
|
||||
(->> shapes
|
||||
(map #(generate-svg objects %))
|
||||
(str/join "\n")))
|
194
frontend/src/app/util/code_gen/style_css.cljs
Normal file
194
frontend/src/app/util/code_gen/style_css.cljs
Normal file
|
@ -0,0 +1,194 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.util.code-gen.style-css
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.util.code-gen.common :as cgc]
|
||||
[app.util.code-gen.style-css-formats :refer [format-value]]
|
||||
[app.util.code-gen.style-css-values :refer [get-value]]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
;;
|
||||
;; Common styles to display always. Will be attached as a prelude to the generated CSS
|
||||
;;
|
||||
(def prelude "
|
||||
html, body {
|
||||
background-color: #E8E9EA;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
")
|
||||
|
||||
(def shape-css-properties
|
||||
[:position
|
||||
:left
|
||||
:top
|
||||
:width
|
||||
:height
|
||||
:transform
|
||||
:background
|
||||
:background-color
|
||||
:background-image
|
||||
:border
|
||||
:border-radius
|
||||
:box-shadow
|
||||
:filter
|
||||
|
||||
;; Flex/grid related properties
|
||||
:display
|
||||
:align-items
|
||||
:align-content
|
||||
:justify-items
|
||||
:justify-content
|
||||
:gap
|
||||
:padding
|
||||
|
||||
;; Flex related properties
|
||||
:flex-direction
|
||||
:flex-wrap
|
||||
|
||||
;; Grid related properties
|
||||
:grid-template-rows
|
||||
:grid-template-columns
|
||||
|
||||
;; Flex/grid self properties
|
||||
:flex-shrink
|
||||
:margin
|
||||
:max-height
|
||||
:min-height
|
||||
:max-width
|
||||
:min-width
|
||||
:align-self
|
||||
:justify-self
|
||||
|
||||
;; Grid cell properties
|
||||
:grid-column
|
||||
:grid-row
|
||||
])
|
||||
|
||||
(def text-node-css-properties
|
||||
[:font-family
|
||||
:font-style
|
||||
:font-size
|
||||
:font-weight
|
||||
:line-height
|
||||
:letter-spacing
|
||||
:text-decoration
|
||||
:text-transform
|
||||
:color])
|
||||
|
||||
(defn shape->css-property
|
||||
[shape objects property]
|
||||
(when-let [value (get-value property shape objects)]
|
||||
[property value]))
|
||||
|
||||
(defn shape->css-properties
|
||||
"Given a shape extract the CSS properties in the format of list [property value]"
|
||||
[shape objects properties]
|
||||
(->> properties
|
||||
(keep (fn [property]
|
||||
(when-let [value (get-value property shape objects)]
|
||||
[property value])))))
|
||||
|
||||
|
||||
|
||||
(defn format-css-value
|
||||
([[property value] options]
|
||||
(format-css-value property value options))
|
||||
|
||||
([property value options]
|
||||
(when (some? value)
|
||||
(format-value property value options))))
|
||||
|
||||
(defn format-css-property
|
||||
[[property value] options]
|
||||
(when (some? value)
|
||||
(let [formatted-value (format-css-value property value options)]
|
||||
(dm/fmt "%: %;" (d/name property) formatted-value))))
|
||||
|
||||
(defn format-css-properties
|
||||
"Format a list of [property value] into a list of css properties in the format 'property: value;'"
|
||||
[properties options]
|
||||
(->> properties
|
||||
(map #(dm/str " " (format-css-property % options)))
|
||||
(str/join "\n")))
|
||||
|
||||
|
||||
(defn get-shape-properties-css
|
||||
([objects shape properties]
|
||||
(get-shape-properties-css objects shape properties nil))
|
||||
|
||||
([objects shape properties options]
|
||||
(-> shape
|
||||
(shape->css-properties objects properties)
|
||||
(format-css-properties options))))
|
||||
|
||||
(defn get-shape-css-selector
|
||||
([objects shape]
|
||||
(get-shape-css-selector shape objects nil))
|
||||
|
||||
([shape objects options]
|
||||
(let [properties (-> shape
|
||||
(shape->css-properties objects shape-css-properties)
|
||||
(format-css-properties options))
|
||||
selector (cgc/shape->selector shape)]
|
||||
(str/join "\n" [(str/fmt "/* %s */" (:name shape))
|
||||
(str/fmt ".%s {\n%s\n}" selector properties)]))))
|
||||
|
||||
(defn get-css-property
|
||||
([objects shape property]
|
||||
(get-css-property objects shape property nil))
|
||||
|
||||
([objects shape property options]
|
||||
(-> shape
|
||||
(shape->css-property objects property)
|
||||
(format-css-property options))))
|
||||
|
||||
(defn get-css-value
|
||||
([objects shape property]
|
||||
(get-css-value objects shape property nil))
|
||||
|
||||
([objects shape property options]
|
||||
(when-let [prop (shape->css-property shape objects property)]
|
||||
(format-css-value prop options))))
|
||||
|
||||
(defn generate-style
|
||||
([objects shapes]
|
||||
(generate-style objects shapes nil))
|
||||
([objects shapes options]
|
||||
(dm/str
|
||||
prelude
|
||||
(->> shapes
|
||||
(map #(get-shape-css-selector % objects options))
|
||||
(str/join "\n\n")))))
|
||||
|
||||
|
||||
#_(defn extract-text-css
|
||||
[node]
|
||||
(cg/parse-style-text-blocks (:content shape) (keys txt/default-text-attrs)))
|
123
frontend/src/app/util/code_gen/style_css_formats.cljs
Normal file
123
frontend/src/app/util/code_gen/style_css_formats.cljs
Normal file
|
@ -0,0 +1,123 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.util.code-gen.style-css-formats
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.util.color :as uc]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(def css-formatters
|
||||
{:left :position
|
||||
:top :position
|
||||
:width :size
|
||||
:height :size
|
||||
:background :color
|
||||
:background-color :color
|
||||
:background-image :color-array
|
||||
:border :border
|
||||
:border-radius :size-array
|
||||
:box-shadow :shadows
|
||||
:filter :blur
|
||||
:gap :size-array
|
||||
:padding :size-array
|
||||
:grid-template-rows :tracks
|
||||
:grid-template-columns :tracks
|
||||
})
|
||||
|
||||
(defmulti format-value
|
||||
(fn [property _value _options] (css-formatters property)))
|
||||
|
||||
(defmethod format-value :position
|
||||
[_ value _options]
|
||||
(cond
|
||||
(number? value) (fmt/format-pixels value)
|
||||
:else value))
|
||||
|
||||
(defmethod format-value :size
|
||||
[_ value _options]
|
||||
(cond
|
||||
(= value :fill) "100%"
|
||||
(= value :auto) "auto"
|
||||
(number? value) (fmt/format-pixels value)
|
||||
:else value))
|
||||
|
||||
(defn format-color
|
||||
[value _options]
|
||||
(cond
|
||||
(not= (:opacity value) 1)
|
||||
(uc/color->background value)
|
||||
|
||||
:else
|
||||
(str/upper (:color value))))
|
||||
|
||||
(defmethod format-value :color
|
||||
[_ value options]
|
||||
(format-color value options))
|
||||
|
||||
(defmethod format-value :color-array
|
||||
[_ value options]
|
||||
(->> value
|
||||
(map #(format-color % options))
|
||||
(str/join ", ")))
|
||||
|
||||
(defmethod format-value :border
|
||||
[_ {:keys [color style width]} options]
|
||||
(dm/fmt "% % %"
|
||||
(fmt/format-pixels width)
|
||||
(d/name style)
|
||||
(format-color color options)))
|
||||
|
||||
(defmethod format-value :size-array
|
||||
[_ value _options]
|
||||
(cond
|
||||
(and (coll? value) (d/not-empty? value))
|
||||
(->> value
|
||||
(map fmt/format-pixels)
|
||||
(str/join " "))
|
||||
|
||||
(some? value)
|
||||
value))
|
||||
|
||||
(defmethod format-value :keyword
|
||||
[_ value _options]
|
||||
(d/name value))
|
||||
|
||||
(defmethod format-value :tracks
|
||||
[_ value _options]
|
||||
(->> value
|
||||
(map (fn [{:keys [type value]}]
|
||||
(case type
|
||||
:flex (dm/str (fmt/format-number value) "fr")
|
||||
:percent (fmt/format-percent (/ value 100))
|
||||
:auto "auto"
|
||||
(fmt/format-pixels value))))
|
||||
(str/join " ")))
|
||||
|
||||
(defn format-shadow
|
||||
[{:keys [style offset-x offset-y blur spread color]} options]
|
||||
(let [css-color (format-color color options)]
|
||||
(dm/str
|
||||
(if (= style :inner-shadow) "inset " "")
|
||||
(str/fmt "%spx %spx %spx %spx %s" offset-x offset-y blur spread css-color))))
|
||||
|
||||
(defmethod format-value :shadows
|
||||
[_ value options]
|
||||
(->> value
|
||||
(map #(format-shadow % options))
|
||||
(str/join ", " )))
|
||||
|
||||
(defmethod format-value :blur
|
||||
[_ value _options]
|
||||
(dm/fmt "blur(%)" (fmt/format-pixels value)))
|
||||
|
||||
(defmethod format-value :default
|
||||
[_ value _options]
|
||||
(if (keyword? value)
|
||||
(d/name value)
|
||||
value))
|
282
frontend/src/app/util/code_gen/style_css_values.cljs
Normal file
282
frontend/src/app/util/code_gen/style_css_values.cljs
Normal file
|
@ -0,0 +1,282 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
|
||||
(ns app.util.code-gen.style-css-values
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
(defn fill->color
|
||||
[{:keys [fill-color fill-opacity fill-color-gradient]}]
|
||||
{:color fill-color
|
||||
:opacity fill-opacity
|
||||
:gradient fill-color-gradient})
|
||||
|
||||
(defmulti get-value
|
||||
(fn [property _shape _objects] property))
|
||||
|
||||
(defmethod get-value :position
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape))
|
||||
(or (cph/group-shape? shape)
|
||||
(cph/frame-shape? shape)))
|
||||
:relative
|
||||
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
nil
|
||||
|
||||
:else
|
||||
:absolute))
|
||||
|
||||
(defn get-shape-position
|
||||
[shape objects coord]
|
||||
(let [shape-value (-> shape :selrect coord)
|
||||
parent-value (dm/get-in objects [(:parent-id shape) :selrect coord])]
|
||||
(when-not (or (cph/root-frame? shape)
|
||||
(ctl/any-layout-immediate-child? objects shape)
|
||||
(ctl/layout-absolute? shape))
|
||||
(- shape-value parent-value))))
|
||||
|
||||
(defmethod get-value :left
|
||||
[_ shape objects]
|
||||
(get-shape-position shape objects :x))
|
||||
|
||||
(defmethod get-value :top
|
||||
[_ shape objects]
|
||||
(get-shape-position shape objects :y))
|
||||
|
||||
(defn get-shape-size
|
||||
[shape type]
|
||||
(let [sizing (if (= type :width)
|
||||
(:layout-item-h-sizing shape)
|
||||
(:layout-item-v-sizing shape))]
|
||||
(cond
|
||||
(or (= sizing :fill) (= sizing :auto))
|
||||
sizing
|
||||
|
||||
(some? (:selrect shape))
|
||||
(-> shape :selrect type)
|
||||
|
||||
(some? (get shape type))
|
||||
(get shape type))))
|
||||
|
||||
(defmethod get-value :width
|
||||
[_ shape _]
|
||||
(get-shape-size shape :width))
|
||||
|
||||
(defmethod get-value :height
|
||||
[_ shape _]
|
||||
(get-shape-size shape :height))
|
||||
|
||||
(defmethod get-value :transform
|
||||
[_ {:keys [transform] :as shape} _]
|
||||
(when (and (some? transform) (not (gmt/unit? transform)))
|
||||
(dm/str transform)))
|
||||
|
||||
(defn background?
|
||||
[shape]
|
||||
(and (not (cph/path-shape? shape))
|
||||
(not (cph/mask-shape? shape))
|
||||
(not (cph/bool-shape? shape))
|
||||
(not (cph/svg-raw-shape? shape))
|
||||
(nil? (:svg-attrs shape))))
|
||||
|
||||
(defmethod get-value :background
|
||||
[_ {:keys [fills] :as shape} _]
|
||||
(let [single-fill? (= (count fills) 1)
|
||||
ffill (first fills)
|
||||
gradient? (some? (:fill-color-gradient ffill))]
|
||||
(when (and (background? shape) single-fill? gradient?)
|
||||
(fill->color ffill))))
|
||||
|
||||
(defmethod get-value :background-color
|
||||
[_ {:keys [fills] :as shape} _]
|
||||
(let [single-fill? (= (count fills) 1)
|
||||
ffill (first fills)
|
||||
gradient? (some? (:fill-color-gradient ffill))]
|
||||
(when (and (background? shape) single-fill? (not gradient?))
|
||||
(fill->color ffill))))
|
||||
|
||||
(defmethod get-value :background-image
|
||||
[_ {:keys [fills] :as shape} _]
|
||||
(when (and (background? shape) (> (count fills) 1))
|
||||
(->> fills
|
||||
(map fill->color))))
|
||||
|
||||
(defn get-stroke-data
|
||||
[stroke]
|
||||
(let [width (:stroke-width stroke)
|
||||
style (:stroke-style stroke)
|
||||
color {:color (:stroke-color stroke)
|
||||
:opacity (:stroke-opacity stroke)
|
||||
:gradient (:stroke-color-gradient stroke)}]
|
||||
|
||||
(when (and (some? stroke) (not= :none (:stroke-style stroke)))
|
||||
{:color color
|
||||
:style style
|
||||
:width width})))
|
||||
|
||||
(defmethod get-value :border
|
||||
[_ shape _]
|
||||
(get-stroke-data (first (:strokes shape))))
|
||||
|
||||
(defmethod get-value :border-radius
|
||||
[_ {:keys [rx r1 r2 r3 r4]} _]
|
||||
(cond
|
||||
(some? rx)
|
||||
[rx]
|
||||
|
||||
(every? some? [r1 r2 r3 r4])
|
||||
[r1 r2 r3 r4]))
|
||||
|
||||
(defmethod get-value :box-shadow
|
||||
[_ shape _]
|
||||
(:shadow shape))
|
||||
|
||||
(defmethod get-value :filter
|
||||
[_ shape _]
|
||||
(get-in shape [:blur :value]))
|
||||
|
||||
(defmethod get-value :display
|
||||
[_ shape _]
|
||||
(cond
|
||||
(ctl/flex-layout? shape) "flex"
|
||||
(ctl/grid-layout? shape) "grid"))
|
||||
|
||||
(defmethod get-value :flex-direction
|
||||
[_ shape _]
|
||||
(:layout-flex-dir shape))
|
||||
|
||||
(defmethod get-value :align-items
|
||||
[_ shape _]
|
||||
(:layout-align-items shape))
|
||||
|
||||
(defmethod get-value :align-content
|
||||
[_ shape _]
|
||||
(:layout-align-content shape))
|
||||
|
||||
(defmethod get-value :justify-items
|
||||
[_ shape _]
|
||||
(:layout-justify-items shape))
|
||||
|
||||
(defmethod get-value :justify-content
|
||||
[_ shape _]
|
||||
(:layout-justify-content shape))
|
||||
|
||||
(defmethod get-value :flex-wrap
|
||||
[_ shape _]
|
||||
(:layout-wrap-type shape))
|
||||
|
||||
(defmethod get-value :gap
|
||||
[_ shape _]
|
||||
(let [[g1 g2] (ctl/gaps shape)]
|
||||
(when (or (not= g1 0) (not= g2 0))
|
||||
[g1 g2])))
|
||||
|
||||
(defmethod get-value :padding
|
||||
[_ {:keys [layout-padding]} _]
|
||||
(when (some? layout-padding)
|
||||
(let [default-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
{:keys [p1 p2 p3 p4]} (merge default-padding layout-padding)]
|
||||
(when (or (not= p1 0) (not= p2 0) (not= p3 0) (not= p4 0))
|
||||
[p1 p2 p3 p4]))))
|
||||
|
||||
(defmethod get-value :grid-template-rows
|
||||
[_ shape _]
|
||||
(:layout-grid-rows shape))
|
||||
|
||||
(defmethod get-value :grid-template-columns
|
||||
[_ shape _]
|
||||
(:layout-grid-columns shape))
|
||||
|
||||
(defn get-grid-coord
|
||||
[shape objects prop span-prop]
|
||||
(when (ctl/grid-layout-immediate-child? objects shape)
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(if (> (get cell span-prop) 1)
|
||||
(dm/str (get cell prop) " / " (+ (get cell prop) (get cell span-prop)))
|
||||
(get cell prop)))))
|
||||
|
||||
(defmethod get-value :grid-column
|
||||
[_ shape objects]
|
||||
(get-grid-coord shape objects :column :column-span))
|
||||
|
||||
(defmethod get-value :grid-row
|
||||
[_ shape objects]
|
||||
(get-grid-coord shape objects :row :row-span))
|
||||
|
||||
(defmethod get-value :flex-shrink
|
||||
[_ shape objects]
|
||||
(when (and (ctl/flex-layout-immediate-child? objects shape)
|
||||
(not= :fill (:layout-item-h-sizing shape))
|
||||
(not= :fill (:layout-item-v-sizing shape))
|
||||
(not= :auto (:layout-item-h-sizing shape))
|
||||
(not= :auto (:layout-item-v-sizing shape)))
|
||||
0))
|
||||
|
||||
(defmethod get-value :margin
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-margin shape)))
|
||||
|
||||
(defmethod get-value :max-height
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-max-h shape)))
|
||||
|
||||
(defmethod get-value :min-height
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-min-h shape)))
|
||||
|
||||
(defmethod get-value :max-width
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-max-w shape)))
|
||||
|
||||
(defmethod get-value :min-width
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-min-w shape)))
|
||||
|
||||
(defmethod get-value :align-self
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(:layout-item-align-self shape)
|
||||
|
||||
(ctl/grid-layout-immediate-child? objects shape)
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))
|
||||
align-self (:align-self cell)]
|
||||
(when (not= align-self :auto) align-self))))
|
||||
|
||||
(defmethod get-value :justify-self
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/grid-layout-immediate-child? objects shape)
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))
|
||||
justify-self (:justify-self cell)]
|
||||
(when (not= justify-self :auto) justify-self))))
|
||||
|
||||
(defmethod get-value :default
|
||||
[property shape _]
|
||||
(get shape property))
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue