mirror of
https://github.com/penpot/penpot.git
synced 2025-05-18 19:56:11 +02:00
✨ Improved code generation
This commit is contained in:
parent
4b8783c104
commit
600b1a6d8d
18 changed files with 651 additions and 199 deletions
|
@ -464,8 +464,13 @@
|
||||||
column-add-auto (/ free-column-space column-autos)
|
column-add-auto (/ free-column-space column-autos)
|
||||||
row-add-auto (/ free-row-space row-autos)
|
row-add-auto (/ free-row-space row-autos)
|
||||||
|
|
||||||
column-tracks (add-auto-size column-tracks column-add-auto)
|
column-tracks (cond-> column-tracks
|
||||||
row-tracks (add-auto-size row-tracks row-add-auto)
|
(= :stretch (:layout-align-content parent))
|
||||||
|
(add-auto-size column-add-auto))
|
||||||
|
|
||||||
|
row-tracks (cond-> row-tracks
|
||||||
|
(= :stretch (:layout-justify-content parent))
|
||||||
|
(add-auto-size row-add-auto))
|
||||||
|
|
||||||
column-total-size (tracks-total-size column-tracks)
|
column-total-size (tracks-total-size column-tracks)
|
||||||
row-total-size (tracks-total-size row-tracks)
|
row-total-size (tracks-total-size row-tracks)
|
||||||
|
@ -556,8 +561,7 @@
|
||||||
:column-total-size column-total-size
|
:column-total-size column-total-size
|
||||||
:column-total-gap column-total-gap
|
:column-total-gap column-total-gap
|
||||||
:row-total-size row-total-size
|
:row-total-size row-total-size
|
||||||
:row-total-gap row-total-gap
|
:row-total-gap row-total-gap}))
|
||||||
}))
|
|
||||||
|
|
||||||
(defn get-cell-data
|
(defn get-cell-data
|
||||||
[{:keys [origin row-tracks column-tracks shape-cells]} _transformed-parent-bounds [_ child]]
|
[{:keys [origin row-tracks column-tracks shape-cells]} _transformed-parent-bounds [_ child]]
|
||||||
|
|
|
@ -106,9 +106,6 @@ $width-settings-bar: 256px;
|
||||||
.settings-bar {
|
.settings-bar {
|
||||||
transition: width 0.2s;
|
transition: width 0.2s;
|
||||||
width: $width-settings-bar;
|
width: $width-settings-bar;
|
||||||
&.expanded {
|
|
||||||
width: $width-settings-bar * 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.settings-bar-right,
|
&.settings-bar-right,
|
||||||
&.settings-bar-left {
|
&.settings-bar-left {
|
||||||
|
|
|
@ -328,6 +328,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-block {
|
.code-block {
|
||||||
|
position: relative;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
border-top: 1px solid $color-gray-60;
|
border-top: 1px solid $color-gray-60;
|
||||||
|
|
||||||
|
@ -353,17 +354,86 @@
|
||||||
.copy-button {
|
.copy-button {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-select {
|
||||||
|
border: 1px solid $color-gray-40;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.25rem 1.5rem 0.25rem 0.25rem;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.dropdown-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 0.25rem;
|
||||||
|
top: 7px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-40;
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-select-dropdown {
|
||||||
|
background-color: $color-white;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
left: 0;
|
||||||
|
max-height: 30rem;
|
||||||
|
min-width: 7rem;
|
||||||
|
position: absolute;
|
||||||
|
overflow-y: auto;
|
||||||
|
top: 30px;
|
||||||
|
z-index: 12;
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: $color-gray-60;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 0 10px;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0.5rem;
|
||||||
|
|
||||||
|
.checked-element {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: none;
|
||||||
|
margin: 0.25rem;
|
||||||
|
fill: $color-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-selected svg {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-row-display {
|
.code-row-display {
|
||||||
|
line-height: 1;
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
font-size: $fs14;
|
font-size: $fs14;
|
||||||
|
max-height: var(--code-height, 400px);
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
.code-display {
|
.code-display {
|
||||||
|
font-family: monospace;
|
||||||
border-radius: $br4;
|
border-radius: $br4;
|
||||||
padding: 1rem;
|
padding: 0.5rem 1rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: pre-wrap;
|
white-space: pre;
|
||||||
|
min-width: fit-content;
|
||||||
background: $color-gray-60;
|
background: $color-gray-60;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
|
|
||||||
|
@ -378,6 +448,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.resize-area {
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -15px;
|
||||||
|
left: 0;
|
||||||
|
height: 18px;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: ns-resize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.element-options > :first-child {
|
.element-options > :first-child {
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspect .tab-container-content {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-element,
|
.tab-element,
|
||||||
.tab-element-content {
|
.tab-element-content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -48,14 +48,11 @@ $height-palette-max: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-bar.settings-bar-right {
|
.settings-bar.settings-bar-right {
|
||||||
transition: width 0.2s;
|
width: var(--width, $width-settings-bar);
|
||||||
min-width: $width-settings-bar;
|
|
||||||
max-width: $width-settings-bar * 3;
|
|
||||||
width: $width-settings-bar;
|
|
||||||
grid-area: right-sidebar;
|
grid-area: right-sidebar;
|
||||||
|
|
||||||
&.expanded {
|
&.not-expand {
|
||||||
width: $width-settings-bar * 3;
|
max-width: $width-settings-bar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,9 @@
|
||||||
|
|
||||||
(defn ^:export reinit
|
(defn ^:export reinit
|
||||||
[]
|
[]
|
||||||
(mf/unmount (dom/get-element "app"))
|
#_(mf/unmount (dom/get-element "app"))
|
||||||
(mf/unmount (dom/get-element "modal"))
|
#_(mf/unmount (dom/get-element "modal"))
|
||||||
(st/emit! (ev/initialize))
|
#_(st/emit! (ev/initialize))
|
||||||
(init-ui))
|
(init-ui))
|
||||||
|
|
||||||
(defn ^:dev/after-load after-load
|
(defn ^:dev/after-load after-load
|
||||||
|
|
|
@ -2160,20 +2160,6 @@
|
||||||
(let [orphans (set (into [] (keys (wsh/find-orphan-shapes state))))]
|
(let [orphans (set (into [] (keys (wsh/find-orphan-shapes state))))]
|
||||||
(rx/of (relocate-shapes orphans uuid/zero 0 true))))))
|
(rx/of (relocate-shapes orphans uuid/zero 0 true))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Inspect
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
|
|
||||||
(defn set-inspect-expanded
|
|
||||||
[expanded?]
|
|
||||||
(ptk/reify ::set-inspect-expanded
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:workspace-local :inspect-expanded] expanded?))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Sitemap
|
;; Sitemap
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -59,9 +59,9 @@
|
||||||
:layout-gap-type :multiple
|
:layout-gap-type :multiple
|
||||||
:layout-gap {:row-gap 0 :column-gap 0}
|
:layout-gap {:row-gap 0 :column-gap 0}
|
||||||
:layout-align-items :start
|
:layout-align-items :start
|
||||||
:layout-align-content :start
|
|
||||||
:layout-justify-items :start
|
:layout-justify-items :start
|
||||||
:layout-justify-content :start
|
:layout-align-content :stretch
|
||||||
|
:layout-justify-content :stretch
|
||||||
:layout-padding-type :simple
|
:layout-padding-type :simple
|
||||||
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||||
:layout-grid-cells {}
|
:layout-grid-cells {}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
@ -65,11 +66,19 @@
|
||||||
start-size (mf/ref-val start-size-ref)
|
start-size (mf/ref-val start-size-ref)
|
||||||
new-size (-> (+ start-size delta) (max min-val) (min max-val))]
|
new-size (-> (+ start-size delta) (max min-val) (min max-val))]
|
||||||
(reset! size-state new-size)
|
(reset! size-state new-size)
|
||||||
(swap! storage assoc-in [::saved-resize current-file-id key] new-size)))))]
|
(swap! storage assoc-in [::saved-resize current-file-id key] new-size)))))
|
||||||
|
|
||||||
|
set-size
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [new-size]
|
||||||
|
(let [new-size (mth/clamp new-size min-val max-val)]
|
||||||
|
(reset! size-state new-size)
|
||||||
|
(swap! storage assoc-in [::saved-resize current-file-id key] new-size))))]
|
||||||
{:on-pointer-down on-pointer-down
|
{:on-pointer-down on-pointer-down
|
||||||
:on-lost-pointer-capture on-lost-pointer-capture
|
:on-lost-pointer-capture on-lost-pointer-capture
|
||||||
:on-pointer-move on-pointer-move
|
:on-pointer-move on-pointer-move
|
||||||
:parent-ref parent-ref
|
:parent-ref parent-ref
|
||||||
|
:set-size set-size
|
||||||
:size @size-state}))
|
:size @size-state}))
|
||||||
|
|
||||||
(defn use-resize-observer
|
(defn use-resize-observer
|
||||||
|
|
|
@ -48,6 +48,18 @@
|
||||||
|
|
||||||
(mf/ref-val fonts-css-ref)))
|
(mf/ref-val fonts-css-ref)))
|
||||||
|
|
||||||
|
(mf/defc fontfaces-style-html
|
||||||
|
{::mf/wrap-props false
|
||||||
|
::mf/wrap [#(mf/memo' % (mf/check-props ["fonts"]))]}
|
||||||
|
[props]
|
||||||
|
|
||||||
|
(let [fonts (obj/get props "fonts")
|
||||||
|
|
||||||
|
;; Fetch its CSS fontfaces
|
||||||
|
fonts-css (use-fonts-css fonts)]
|
||||||
|
|
||||||
|
[:style fonts-css]))
|
||||||
|
|
||||||
(mf/defc fontfaces-style-render
|
(mf/defc fontfaces-style-render
|
||||||
{::mf/wrap-props false
|
{::mf/wrap-props false
|
||||||
::mf/wrap [#(mf/memo' % (mf/check-props ["fonts"]))]}
|
::mf/wrap [#(mf/memo' % (mf/check-props ["fonts"]))]}
|
||||||
|
@ -63,7 +75,6 @@
|
||||||
(mf/deps fonts-css)
|
(mf/deps fonts-css)
|
||||||
#(fonts/extract-fontface-urls fonts-css))
|
#(fonts/extract-fontface-urls fonts-css))
|
||||||
|
|
||||||
|
|
||||||
;; Calculate the data-uris for these fonts
|
;; Calculate the data-uris for these fonts
|
||||||
fonts-embed (embed/use-data-uris fonts-urls)
|
fonts-embed (embed/use-data-uris fonts-urls)
|
||||||
|
|
||||||
|
|
|
@ -83,19 +83,24 @@
|
||||||
[props ref]
|
[props ref]
|
||||||
(let [shape (obj/get props "shape")
|
(let [shape (obj/get props "shape")
|
||||||
grow-type (obj/get props "grow-type")
|
grow-type (obj/get props "grow-type")
|
||||||
{:keys [id x y width height content]} shape]
|
code? (obj/get props "code?")
|
||||||
|
{:keys [id x y width height content]} shape
|
||||||
|
|
||||||
|
style
|
||||||
|
(when-not code?
|
||||||
|
#js {:position "fixed"
|
||||||
|
:left 0
|
||||||
|
:top 0
|
||||||
|
:background "white"
|
||||||
|
:width (if (#{:auto-width} grow-type) 100000 width)
|
||||||
|
:height (if (#{:auto-height :auto-width} grow-type) 100000 height)})]
|
||||||
|
|
||||||
[:div.text-node-html
|
[:div.text-node-html
|
||||||
{:id (dm/str "html-text-node-" id)
|
{:id (dm/str "html-text-node-" id)
|
||||||
:ref ref
|
:ref ref
|
||||||
:data-x x
|
:data-x x
|
||||||
:data-y y
|
:data-y y
|
||||||
:style {:position "fixed"
|
:style style}
|
||||||
:left 0
|
|
||||||
:top 0
|
|
||||||
:background "white"
|
|
||||||
:width (if (#{:auto-width} grow-type) 100000 width)
|
|
||||||
:height (if (#{:auto-height :auto-width} grow-type) 100000 height)}}
|
|
||||||
;; We use a class here because react has a bug that won't use the appropriate selector for
|
;; We use a class here because react has a bug that won't use the appropriate selector for
|
||||||
;; `background-clip`
|
;; `background-clip`
|
||||||
[:style ".text-node { background-clip: text;
|
[:style ".text-node { background-clip: text;
|
||||||
|
|
|
@ -48,7 +48,8 @@
|
||||||
[_shape data]
|
[_shape data]
|
||||||
(let [line-height (:line-height data 1.2)
|
(let [line-height (:line-height data 1.2)
|
||||||
text-align (:text-align data "start")
|
text-align (:text-align data "start")
|
||||||
base #js {:fontSize (str (:font-size data (:font-size txt/default-text-attrs)) "px")
|
base #js {;; Fix a problem when exporting HTML
|
||||||
|
:fontSize 0 ;;(str (:font-size data (:font-size txt/default-text-attrs)) "px")
|
||||||
:lineHeight (:line-height data (:line-height txt/default-text-attrs))
|
:lineHeight (:line-height data (:line-height txt/default-text-attrs))
|
||||||
:margin 0}]
|
:margin 0}]
|
||||||
(cond-> base
|
(cond-> base
|
||||||
|
|
|
@ -7,41 +7,36 @@
|
||||||
(ns app.main.ui.viewer.inspect.code
|
(ns app.main.ui.viewer.inspect.code
|
||||||
(:require
|
(:require
|
||||||
["js-beautify" :as beautify]
|
["js-beautify" :as beautify]
|
||||||
["react-dom/server" :as rds]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.config :as cfg]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
|
[app.main.fonts :as fonts]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.render :as render]
|
|
||||||
[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.components.select :refer [select]]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
|
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
[app.main.ui.shapes.text.fontfaces :refer [shapes->fonts]]
|
||||||
[app.util.code-gen :as cg]
|
[app.util.code-gen :as cg]
|
||||||
|
[app.util.http :as http]
|
||||||
|
[beicon.core :as rx]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn generate-markup-code [objects shapes]
|
|
||||||
;; Here we can render specific HTML code
|
|
||||||
(->> shapes
|
|
||||||
(map (fn [shape]
|
|
||||||
(dm/str
|
|
||||||
"<!-- Shape: " (:name shape) " -->"
|
|
||||||
(rds/renderToStaticMarkup
|
|
||||||
(mf/element
|
|
||||||
render/object-svg
|
|
||||||
#js {:objects objects
|
|
||||||
:object-id (-> shape :id)})))))
|
|
||||||
(str/join "\n\n")))
|
|
||||||
|
|
||||||
(defn format-code [code type]
|
(defn format-code [code type]
|
||||||
(let [code (-> code
|
(let [code (-> code
|
||||||
(str/replace "<defs></defs>" "")
|
(str/replace "<defs></defs>" "")
|
||||||
(str/replace "><" ">\n<"))]
|
(str/replace "><" ">\n<"))]
|
||||||
(cond-> code
|
(cond-> code
|
||||||
(= type "svg") (beautify/html #js {"indent_size" 2}))))
|
(or (= type "svg") (= type "html")) (beautify/html #js {"indent_size" 2}))))
|
||||||
|
|
||||||
(defn get-flex-elements [page-id shapes from]
|
(defn get-flex-elements [page-id shapes from]
|
||||||
(let [ids (mapv :id shapes)
|
(let [ids (mapv :id shapes)
|
||||||
|
@ -62,46 +57,139 @@
|
||||||
(refs/get-viewer-objects))))]
|
(refs/get-viewer-objects))))]
|
||||||
(mf/deref page-objects-ref)))
|
(mf/deref page-objects-ref)))
|
||||||
|
|
||||||
|
(defn shapes->images
|
||||||
|
[shapes]
|
||||||
|
(->> shapes
|
||||||
|
(keep
|
||||||
|
(fn [shape]
|
||||||
|
(when-let [data (or (:metadata shape) (:fill-image shape))]
|
||||||
|
[(:id shape) (cfg/resolve-file-media data)])))))
|
||||||
|
|
||||||
|
(defn replace-map
|
||||||
|
[value map]
|
||||||
|
(reduce
|
||||||
|
(fn [value [old new]]
|
||||||
|
(str/replace value old new))
|
||||||
|
value map))
|
||||||
|
|
||||||
(mf/defc code
|
(mf/defc code
|
||||||
[{:keys [shapes frame on-expand from]}]
|
[{:keys [shapes frame on-expand from]}]
|
||||||
(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 "html")
|
||||||
|
fontfaces-css* (mf/use-state nil)
|
||||||
|
images-data* (mf/use-state nil)
|
||||||
|
|
||||||
|
style-type (deref style-type*)
|
||||||
|
markup-type (deref markup-type*)
|
||||||
|
fontfaces-css (deref fontfaces-css*)
|
||||||
|
images-data (deref images-data*)
|
||||||
|
|
||||||
shapes (->> shapes
|
shapes (->> shapes
|
||||||
(map #(gsh/translate-to-frame % frame)))
|
(map #(gsh/translate-to-frame % frame)))
|
||||||
|
|
||||||
route (mf/deref refs/route)
|
route (mf/deref refs/route)
|
||||||
page-id (:page-id (:query-params route))
|
page-id (:page-id (:query-params route))
|
||||||
flex-items (get-flex-elements page-id shapes from)
|
flex-items (get-flex-elements page-id shapes from)
|
||||||
objects (get-objects from)
|
objects (get-objects from)
|
||||||
|
|
||||||
|
;; TODO REMOVE THIS
|
||||||
shapes (->> shapes
|
shapes (->> shapes
|
||||||
(map #(assoc % :parent (get objects (:parent-id %))))
|
(map #(assoc % :parent (get objects (:parent-id %))))
|
||||||
(map #(assoc % :flex-items flex-items)))
|
(map #(assoc % :flex-items flex-items)))
|
||||||
style-code (-> (cg/generate-style-code @style-type shapes)
|
|
||||||
(format-code "css"))
|
all-children (->> shapes
|
||||||
|
(map :id)
|
||||||
|
(cph/selected-with-children objects)
|
||||||
|
(ctst/sort-z-index objects)
|
||||||
|
(map (d/getf objects)))
|
||||||
|
|
||||||
|
|
||||||
|
shapes (hooks/use-equal-memo shapes)
|
||||||
|
all-children (hooks/use-equal-memo all-children)
|
||||||
|
|
||||||
|
fonts (-> (shapes->fonts all-children)
|
||||||
|
(hooks/use-equal-memo))
|
||||||
|
|
||||||
|
images-urls (-> (shapes->images all-children)
|
||||||
|
(hooks/use-equal-memo))
|
||||||
|
|
||||||
|
style-code
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps fontfaces-css style-type all-children)
|
||||||
|
(fn []
|
||||||
|
(dm/str
|
||||||
|
fontfaces-css "\n"
|
||||||
|
(-> (cg/generate-style-code objects style-type all-children)
|
||||||
|
(format-code style-type)))))
|
||||||
|
|
||||||
markup-code
|
markup-code
|
||||||
(-> (mf/use-memo (mf/deps shapes) #(generate-markup-code objects shapes))
|
(mf/use-memo
|
||||||
(format-code "svg"))
|
(mf/deps markup-type shapes images-data)
|
||||||
|
(fn []
|
||||||
|
(-> (cg/generate-markup-code objects markup-type (map :id shapes))
|
||||||
|
(format-code markup-type))))
|
||||||
|
|
||||||
on-markup-copied
|
on-markup-copied
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps @markup-type)
|
(mf/deps markup-type)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event
|
(st/emit! (ptk/event ::ev/event
|
||||||
{::ev/name "copy-inspect-code"
|
{::ev/name "copy-inspect-code"
|
||||||
:type @markup-type}))))
|
:type markup-type}))))
|
||||||
|
|
||||||
on-style-copied
|
on-style-copied
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps @style-type)
|
(mf/deps style-type)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event
|
(st/emit! (ptk/event ::ev/event
|
||||||
{::ev/name "copy-inspect-style"
|
{::ev/name "copy-inspect-style"
|
||||||
:type @style-type}))))]
|
:type style-type}))))
|
||||||
|
|
||||||
|
{on-code-pointer-down :on-pointer-down
|
||||||
|
on-code-lost-pointer-capture :on-lost-pointer-capture
|
||||||
|
on-code-pointer-move :on-pointer-move
|
||||||
|
code-size :size}
|
||||||
|
(use-resize-hook :code 400 100 800 :y false :bottom)
|
||||||
|
|
||||||
|
set-style
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [value]
|
||||||
|
(reset! style-type* value)))
|
||||||
|
|
||||||
|
set-markup
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [value]
|
||||||
|
(reset! markup-type* value)))]
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps fonts)
|
||||||
|
#(->> (rx/from fonts)
|
||||||
|
(rx/merge-map fonts/fetch-font-css)
|
||||||
|
(rx/reduce conj [])
|
||||||
|
(rx/subs
|
||||||
|
(fn [result]
|
||||||
|
(let [css (str/join "\n" result)]
|
||||||
|
(reset! fontfaces-css* css))))))
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps images-urls)
|
||||||
|
#(->> (rx/from images-urls)
|
||||||
|
(rx/merge-map
|
||||||
|
(fn [[_ uri]]
|
||||||
|
(->> (http/fetch-data-uri uri true)
|
||||||
|
(rx/catch (fn [_] (rx/of (hash-map uri uri)))))))
|
||||||
|
(rx/reduce conj {})
|
||||||
|
(rx/subs
|
||||||
|
(fn [result]
|
||||||
|
(reset! images-data* result)))))
|
||||||
|
|
||||||
[:div.element-options
|
[:div.element-options
|
||||||
[:div.code-block
|
[:div.code-block
|
||||||
[:div.code-row-lang "CSS"
|
[:div.code-row-lang
|
||||||
|
[:& select {:default-value style-type
|
||||||
|
:class "custom-select"
|
||||||
|
:options [{:label "CSS" :value "css"}]
|
||||||
|
:on-change set-style}]
|
||||||
[:button.expand-button
|
[:button.expand-button
|
||||||
{:on-click on-expand}
|
{:on-click on-expand}
|
||||||
i/full-screen]
|
i/full-screen]
|
||||||
|
@ -109,19 +197,31 @@
|
||||||
[:& copy-button {:data style-code
|
[:& copy-button {:data style-code
|
||||||
:on-copied on-style-copied}]]
|
:on-copied on-style-copied}]]
|
||||||
|
|
||||||
[:div.code-row-display
|
[:div.code-row-display {:style #js {"--code-height" (str (or code-size 400) "px")}}
|
||||||
[:& code-block {:type @style-type
|
[:& code-block {:type style-type
|
||||||
:code style-code}]]]
|
:code style-code}]]
|
||||||
|
|
||||||
|
[:div.resize-area {:on-pointer-down on-code-pointer-down
|
||||||
|
:on-lost-pointer-capture on-code-lost-pointer-capture
|
||||||
|
:on-pointer-move on-code-pointer-move}]]
|
||||||
|
|
||||||
|
|
||||||
[:div.code-block
|
[:div.code-block
|
||||||
[:div.code-row-lang "SVG"
|
[:div.code-row-lang
|
||||||
|
[:& select {:default-value markup-type
|
||||||
|
:class "input-option"
|
||||||
|
:options [{:label "HTML" :value "html"}
|
||||||
|
{:label "SVG" :value "svg"}]
|
||||||
|
:on-change set-markup}]
|
||||||
|
|
||||||
[:button.expand-button
|
[:button.expand-button
|
||||||
{:on-click on-expand}
|
{:on-click on-expand}
|
||||||
i/full-screen]
|
i/full-screen]
|
||||||
|
|
||||||
[:& copy-button {:data markup-code
|
[:& copy-button {:data (replace-map markup-code images-data)
|
||||||
: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}]]]]))
|
||||||
|
|
|
@ -6,9 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.viewer.inspect.right-sidebar
|
(ns app.main.ui.viewer.inspect.right-sidebar
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.workspace :as dw]
|
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
|
||||||
[app.main.ui.components.shape-icon :as si]
|
[app.main.ui.components.shape-icon :as si]
|
||||||
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
|
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
@ -38,10 +36,9 @@
|
||||||
:data local})))))
|
:data local})))))
|
||||||
|
|
||||||
(mf/defc right-sidebar
|
(mf/defc right-sidebar
|
||||||
[{:keys [frame page file selected shapes page-id file-id share-id from]
|
[{:keys [frame page file selected shapes page-id file-id share-id from on-change-section on-expand]
|
||||||
:or {from :inspect}}]
|
:or {from :inspect}}]
|
||||||
(let [expanded (mf/use-state false)
|
(let [section (mf/use-state :info #_:code)
|
||||||
section (mf/use-state :info #_:code)
|
|
||||||
shapes (or shapes
|
shapes (or shapes
|
||||||
(resolve-shapes (:objects page) selected))
|
(resolve-shapes (:objects page) selected))
|
||||||
|
|
||||||
|
@ -49,9 +46,29 @@
|
||||||
page-id (or page-id (:id page))
|
page-id (or page-id (:id page))
|
||||||
file-id (or file-id (:id file))
|
file-id (or file-id (:id file))
|
||||||
|
|
||||||
libraries (get-libraries from)]
|
libraries (get-libraries from)
|
||||||
|
|
||||||
[:aside.settings-bar.settings-bar-right {:class (when @expanded "expanded")}
|
handle-change-tab
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps from on-change-section)
|
||||||
|
(fn [new-section]
|
||||||
|
(reset! section new-section)
|
||||||
|
(when on-change-section
|
||||||
|
(on-change-section new-section))))
|
||||||
|
|
||||||
|
handle-expand
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps on-expand)
|
||||||
|
(fn []
|
||||||
|
(when on-expand (on-expand))))]
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps shapes handle-change-tab)
|
||||||
|
(fn []
|
||||||
|
(when-not (seq shapes)
|
||||||
|
(handle-change-tab :info))))
|
||||||
|
|
||||||
|
[:aside.settings-bar.settings-bar-right
|
||||||
[:div.settings-bar-inside
|
[:div.settings-bar-inside
|
||||||
(if (seq shapes)
|
(if (seq shapes)
|
||||||
[:div.tool-window
|
[:div.tool-window
|
||||||
|
@ -77,12 +94,8 @@
|
||||||
;; inspect.tabs.code.selected.text
|
;; inspect.tabs.code.selected.text
|
||||||
[:span.tool-window-bar-title (:name first-shape)]])]
|
[:span.tool-window-bar-title (:name first-shape)]])]
|
||||||
[:div.tool-window-content.inspect
|
[:div.tool-window-content.inspect
|
||||||
[:& tabs-container {:on-change-tab #(do
|
[:& tabs-container {:on-change-tab handle-change-tab
|
||||||
(reset! expanded false)
|
:selected @section}
|
||||||
(reset! section %)
|
|
||||||
(when (= from :workspace)
|
|
||||||
(st/emit! (dw/set-inspect-expanded false))))
|
|
||||||
:selected @section}
|
|
||||||
[:& tabs-element {:id :info :title (tr "inspect.tabs.info")}
|
[:& tabs-element {:id :info :title (tr "inspect.tabs.info")}
|
||||||
[:& attributes {:page-id page-id
|
[:& attributes {:page-id page-id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
|
@ -95,10 +108,7 @@
|
||||||
[:& tabs-element {:id :code :title (tr "inspect.tabs.code")}
|
[:& tabs-element {:id :code :title (tr "inspect.tabs.code")}
|
||||||
[:& code {:frame frame
|
[:& code {:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:on-expand (fn []
|
:on-expand handle-expand
|
||||||
(when (= from :workspace)
|
|
||||||
(st/emit! (dw/set-inspect-expanded (not @expanded))))
|
|
||||||
(swap! expanded not))
|
|
||||||
:from from}]]]]]
|
:from from}]]]]]
|
||||||
[:div.empty
|
[:div.empty
|
||||||
[:span.tool-window-bar-icon i/code]
|
[:span.tool-window-bar-icon i/code]
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
|
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
|
[app.util.object :as obj]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
;; --- Left Sidebar (Component)
|
;; --- Left Sidebar (Component)
|
||||||
|
@ -134,16 +135,45 @@
|
||||||
is-history? (contains? layout :document-history)
|
is-history? (contains? layout :document-history)
|
||||||
is-inspect? (= section :inspect)
|
is-inspect? (= section :inspect)
|
||||||
|
|
||||||
expanded? (mf/deref refs/inspect-expanded)
|
;;expanded? (mf/deref refs/inspect-expanded)
|
||||||
|
;;prev-expanded? (hooks/use-previous expanded?)
|
||||||
|
|
||||||
|
current-section* (mf/use-state :info)
|
||||||
|
current-section (deref current-section*)
|
||||||
|
|
||||||
can-be-expanded? (and (not is-comments?)
|
can-be-expanded? (and (not is-comments?)
|
||||||
(not is-history?)
|
(not is-history?)
|
||||||
is-inspect?)]
|
is-inspect?
|
||||||
|
(= current-section :code))
|
||||||
|
|
||||||
(mf/with-effect [can-be-expanded?]
|
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move set-size size]}
|
||||||
(when (not can-be-expanded?)
|
(use-resize-hook :code 256 256 768 :x true :right)
|
||||||
(st/emit! (dw/set-inspect-expanded false))))
|
|
||||||
|
|
||||||
[:aside.settings-bar.settings-bar-right {:class (when (and can-be-expanded? expanded?) "expanded")}
|
handle-change-section
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [section]
|
||||||
|
(reset! current-section* section)))
|
||||||
|
|
||||||
|
handle-expand
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps size)
|
||||||
|
(fn []
|
||||||
|
(set-size (if (> size 256) 256 768))))
|
||||||
|
|
||||||
|
props
|
||||||
|
(-> props
|
||||||
|
(obj/clone)
|
||||||
|
(obj/set! "on-change-section" handle-change-section)
|
||||||
|
(obj/set! "on-expand" handle-expand))]
|
||||||
|
|
||||||
|
[:aside.settings-bar.settings-bar-right
|
||||||
|
{:class (when (not can-be-expanded?) "not-expand")
|
||||||
|
:style #js {"--width" (when can-be-expanded? (dm/str size "px"))}}
|
||||||
|
(when can-be-expanded?
|
||||||
|
[:div.resize-area
|
||||||
|
{:on-pointer-down on-pointer-down
|
||||||
|
:on-lost-pointer-capture on-lost-pointer-capture
|
||||||
|
:on-pointer-move on-pointer-move}])
|
||||||
[:div.settings-bar-inside
|
[:div.settings-bar-inside
|
||||||
(cond
|
(cond
|
||||||
(true? is-comments?)
|
(true? is-comments?)
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
(mf/defc options-content
|
(mf/defc options-content
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [selected section shapes shapes-with-children page-id file-id]}]
|
[{:keys [selected section shapes shapes-with-children page-id file-id on-change-section on-expand]}]
|
||||||
(let [drawing (mf/deref refs/workspace-drawing)
|
(let [drawing (mf/deref refs/workspace-drawing)
|
||||||
objects (mf/deref refs/workspace-page-objects)
|
objects (mf/deref refs/workspace-page-objects)
|
||||||
shared-libs (mf/deref refs/workspace-libraries)
|
shared-libs (mf/deref refs/workspace-libraries)
|
||||||
|
@ -83,9 +83,8 @@
|
||||||
|
|
||||||
on-change-tab
|
on-change-tab
|
||||||
(fn [options-mode]
|
(fn [options-mode]
|
||||||
(st/emit! (udw/set-options-mode options-mode)
|
(st/emit! (udw/set-options-mode options-mode))
|
||||||
(udw/set-inspect-expanded false))
|
(if (= options-mode :inspect)
|
||||||
(if (= options-mode :inspect) ;;TODO maybe move this logic to set-options-mode
|
|
||||||
(st/emit! :interrupt (udw/set-workspace-read-only true))
|
(st/emit! :interrupt (udw/set-workspace-read-only true))
|
||||||
(st/emit! :interrupt (udw/set-workspace-read-only false))))]
|
(st/emit! :interrupt (udw/set-workspace-read-only false))))]
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@
|
||||||
[:& tabs-container {:on-change-tab on-change-tab
|
[:& tabs-container {:on-change-tab on-change-tab
|
||||||
:selected section}
|
:selected section}
|
||||||
[:& tabs-element {:id :design
|
[:& tabs-element {:id :design
|
||||||
:title (tr "workspace.options.design")}
|
:title (tr "workspace.options.design")}
|
||||||
[:div.element-options
|
[:div.element-options
|
||||||
[:& align-options]
|
[:& align-options]
|
||||||
[:& bool-options]
|
[:& bool-options]
|
||||||
|
@ -143,13 +142,16 @@
|
||||||
[:& interactions-menu {:shape (first shapes)}]]]
|
[:& interactions-menu {:shape (first shapes)}]]]
|
||||||
|
|
||||||
[:& tabs-element {:id :inspect
|
[:& tabs-element {:id :inspect
|
||||||
:title (tr "workspace.options.inspect")}
|
:title (tr "workspace.options.inspect")}
|
||||||
[:div.element-options
|
|
||||||
[:& hrs/right-sidebar {:page-id page-id
|
[:div.element-options.element-options-inspect
|
||||||
:file-id file-id
|
[:& hrs/right-sidebar {:page-id page-id
|
||||||
:frame shape-parent-frame
|
:file-id file-id
|
||||||
:shapes selected-shapes
|
:frame shape-parent-frame
|
||||||
:from :workspace}]]]]]]))
|
:shapes selected-shapes
|
||||||
|
:on-change-section on-change-section
|
||||||
|
:on-expand on-expand
|
||||||
|
:from :workspace}]]]]]]))
|
||||||
|
|
||||||
;; TODO: this need optimizations, selected-objects and
|
;; TODO: this need optimizations, selected-objects and
|
||||||
;; selected-objects-with-children are derefed always but they only
|
;; selected-objects-with-children are derefed always but they only
|
||||||
|
@ -161,6 +163,8 @@
|
||||||
[props]
|
[props]
|
||||||
(let [section (obj/get props "section")
|
(let [section (obj/get props "section")
|
||||||
selected (obj/get props "selected")
|
selected (obj/get props "selected")
|
||||||
|
on-change-section (obj/get props "on-change-section")
|
||||||
|
on-expand (obj/get props "on-expand")
|
||||||
page-id (mf/use-ctx ctx/current-page-id)
|
page-id (mf/use-ctx ctx/current-page-id)
|
||||||
file-id (mf/use-ctx ctx/current-file-id)
|
file-id (mf/use-ctx ctx/current-file-id)
|
||||||
shapes (mf/deref refs/selected-objects)
|
shapes (mf/deref refs/selected-objects)
|
||||||
|
@ -171,4 +175,6 @@
|
||||||
:shapes-with-children shapes-with-children
|
:shapes-with-children shapes-with-children
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:section section}]))
|
:section section
|
||||||
|
:on-change-section on-change-section
|
||||||
|
:on-expand on-expand}]))
|
||||||
|
|
|
@ -125,6 +125,7 @@
|
||||||
:justify-items
|
:justify-items
|
||||||
(if is-col?
|
(if is-col?
|
||||||
(case val
|
(case val
|
||||||
|
:stretch i/grid-justify-content-column-around
|
||||||
:start i/grid-justify-content-column-start
|
:start i/grid-justify-content-column-start
|
||||||
:end i/grid-justify-content-column-end
|
:end i/grid-justify-content-column-end
|
||||||
:center i/grid-justify-content-column-center
|
:center i/grid-justify-content-column-center
|
||||||
|
@ -133,6 +134,7 @@
|
||||||
:space-evenly i/grid-justify-content-column-between)
|
:space-evenly i/grid-justify-content-column-between)
|
||||||
|
|
||||||
(case val
|
(case val
|
||||||
|
:stretch i/grid-justify-content-column-around
|
||||||
:start i/grid-justify-content-row-start
|
:start i/grid-justify-content-row-start
|
||||||
:end i/grid-justify-content-row-end
|
:end i/grid-justify-content-row-end
|
||||||
:center i/grid-justify-content-row-center
|
:center i/grid-justify-content-row-center
|
||||||
|
@ -407,7 +409,7 @@
|
||||||
[{:keys [is-col? justify-items set-justify] :as props}]
|
[{:keys [is-col? justify-items set-justify] :as props}]
|
||||||
(let [type (if is-col? :column :row)]
|
(let [type (if is-col? :column :row)]
|
||||||
[:div.justify-content-style
|
[:div.justify-content-style
|
||||||
(for [align [:start :center :end :space-around :space-between :space-evenly]]
|
(for [align [:stretch :start :center :end :space-around :space-between]]
|
||||||
[:button.align-start.tooltip
|
[:button.align-start.tooltip
|
||||||
{:class (dom/classnames :active (= justify-items align)
|
{:class (dom/classnames :active (= justify-items align)
|
||||||
:tooltip-bottom-left (not= align :start)
|
:tooltip-bottom-left (not= align :start)
|
||||||
|
@ -748,7 +750,7 @@
|
||||||
align-items-row (:layout-align-items values)
|
align-items-row (:layout-align-items values)
|
||||||
align-items-column (:layout-justify-items values)
|
align-items-column (:layout-justify-items values)
|
||||||
|
|
||||||
set-align-grid
|
set-items-grid
|
||||||
(fn [value type]
|
(fn [value type]
|
||||||
(if (= type :row)
|
(if (= type :row)
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
|
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
|
||||||
|
@ -758,7 +760,7 @@
|
||||||
grid-justify-content-row (:layout-align-content values)
|
grid-justify-content-row (:layout-align-content values)
|
||||||
grid-justify-content-column (:layout-justify-content values)
|
grid-justify-content-column (:layout-justify-content values)
|
||||||
|
|
||||||
set-justify-grid
|
set-content-grid
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps ids)
|
(mf/deps ids)
|
||||||
(fn [value type]
|
(fn [value type]
|
||||||
|
@ -833,25 +835,25 @@
|
||||||
[:& grid-edit-mode {:id (first ids)}]])]]
|
[:& grid-edit-mode {:id (first ids)}]])]]
|
||||||
|
|
||||||
[:div.layout-row
|
[:div.layout-row
|
||||||
[:div.align-items-grid.row-title "Align"]
|
[:div.align-items-grid.row-title "Items"]
|
||||||
[:div.btn-wrapper.align-grid
|
[:div.btn-wrapper.align-grid
|
||||||
[:& align-grid-row {:is-col? false
|
[:& align-grid-row {:is-col? false
|
||||||
:align-items align-items-row
|
:align-items align-items-row
|
||||||
:set-align set-align-grid}]
|
:set-align set-items-grid}]
|
||||||
|
|
||||||
[:& align-grid-row {:is-col? true
|
[:& align-grid-row {:is-col? true
|
||||||
:align-items align-items-column
|
:align-items align-items-column
|
||||||
:set-align set-align-grid}]]]
|
:set-align set-items-grid}]]]
|
||||||
|
|
||||||
[:div.layout-row
|
[:div.layout-row
|
||||||
[:div.jusfiy-content-grid.row-title "Justify"]
|
[:div.jusfiy-content-grid.row-title "Content"]
|
||||||
[:div.btn-wrapper.align-grid
|
[:div.btn-wrapper.align-grid
|
||||||
[:& justify-grid-row {:is-col? true
|
[:& justify-grid-row {:is-col? true
|
||||||
:justify-items grid-justify-content-column
|
:justify-items grid-justify-content-column
|
||||||
:set-justify set-justify-grid}]
|
:set-justify set-content-grid}]
|
||||||
[:& justify-grid-row {:is-col? false
|
[:& justify-grid-row {:is-col? false
|
||||||
:justify-items grid-justify-content-row
|
:justify-items grid-justify-content-row
|
||||||
:set-justify set-justify-grid}]]]
|
:set-justify set-content-grid}]]]
|
||||||
[:& grid-columns-row {:is-col? true
|
[:& grid-columns-row {:is-col? true
|
||||||
:expanded? @grid-columns-open?
|
:expanded? @grid-columns-open?
|
||||||
:toggle toggle-columns-info
|
:toggle toggle-columns-info
|
||||||
|
|
|
@ -6,14 +6,19 @@
|
||||||
|
|
||||||
(ns app.util.code-gen
|
(ns app.util.code-gen
|
||||||
(:require
|
(:require
|
||||||
|
["react-dom/server" :as rds]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[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.formats :as fmt]
|
||||||
|
[app.main.ui.shapes.text.html-text :as text]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn shadow->css [shadow]
|
(defn shadow->css [shadow]
|
||||||
(let [{:keys [style offset-x offset-y blur spread]} shadow
|
(let [{:keys [style offset-x offset-y blur spread]} shadow
|
||||||
|
@ -24,9 +29,14 @@
|
||||||
|
|
||||||
(defn fill-color->background
|
(defn fill-color->background
|
||||||
[fill]
|
[fill]
|
||||||
(uc/color->background {:color (:fill-color fill)
|
(cond
|
||||||
:opacity (:fill-opacity fill)
|
(not= (:fill-opacity fill) 1)
|
||||||
:gradient (:fill-color-gradient fill)}))
|
(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]
|
(defn format-fill-color [_ shape]
|
||||||
(let [fills (:fills shape)
|
(let [fills (:fills shape)
|
||||||
|
@ -41,7 +51,7 @@
|
||||||
[(fill-color->background first-fill)])]
|
[(fill-color->background first-fill)])]
|
||||||
(str/join ", " colors)))
|
(str/join ", " colors)))
|
||||||
|
|
||||||
(defn format-stroke [_ shape]
|
(defn format-stroke [shape]
|
||||||
(let [first-stroke (first (:strokes shape))
|
(let [first-stroke (first (:strokes shape))
|
||||||
width (:stroke-width first-stroke)
|
width (:stroke-width first-stroke)
|
||||||
style (let [style (:stroke-style first-stroke)]
|
style (let [style (:stroke-style first-stroke)]
|
||||||
|
@ -52,16 +62,32 @@
|
||||||
(when-not (= :none (:stroke-style first-stroke))
|
(when-not (= :none (:stroke-style first-stroke))
|
||||||
(str/format "%spx %s %s" width style (uc/color->background color)))))
|
(str/format "%spx %s %s" width style (uc/color->background color)))))
|
||||||
|
|
||||||
(defn format-position [_ shape]
|
(defn format-position [objects]
|
||||||
(let [relative? (cph/frame-shape? shape)
|
(fn [_ shape]
|
||||||
absolute? (or (empty? (:flex-items shape))
|
|
||||||
(and (ctl/any-layout? (:parent shape)) (ctl/layout-absolute? shape)))]
|
|
||||||
(cond
|
(cond
|
||||||
absolute? "absolute"
|
(and (ctl/any-layout-immediate-child? objects shape)
|
||||||
relative? "relative"
|
(not (ctl/layout-absolute? shape))
|
||||||
|
(or (cph/group-shape? shape)
|
||||||
|
(cph/frame-shape? shape)))
|
||||||
|
"relative"
|
||||||
|
|
||||||
;; static is default value in css
|
(and (ctl/any-layout-immediate-child? objects shape)
|
||||||
:else nil)))
|
(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
|
(defn get-size
|
||||||
[type values]
|
[type values]
|
||||||
|
@ -75,14 +101,35 @@
|
||||||
(fmt/format-size :width value values)
|
(fmt/format-size :width value values)
|
||||||
(fmt/format-size :heigth 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
|
(defn styles-data
|
||||||
[shape]
|
[objects shape]
|
||||||
{:position {:props [:type]
|
{:position {:props [:type]
|
||||||
:to-prop {:type "position"}
|
:to-prop {:type "position"}
|
||||||
:format {:type format-position}}
|
:format {:type (format-position objects)}}
|
||||||
:layout {:props (if (or (empty? (:flex-items shape))
|
:layout {:props (if (or (empty? (:flex-items shape))
|
||||||
(ctl/layout-absolute? shape))
|
(ctl/layout-absolute? shape))
|
||||||
[:width :height :x :y :radius :rx :r1]
|
[:x :y :width :height :radius :rx :r1]
|
||||||
[:width :height :radius :rx :r1])
|
[:width :height :radius :rx :r1])
|
||||||
:to-prop {:x "left"
|
:to-prop {:x "left"
|
||||||
:y "top"
|
:y "top"
|
||||||
|
@ -92,30 +139,60 @@
|
||||||
: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 #(get-size :width %)
|
:width #(get-size :width %)
|
||||||
:height #(get-size :height %)}
|
: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]}}
|
:multi {:r1 [:r1 :r2 :r3 :r4]}}
|
||||||
:fill {:props [:fills]
|
:fill {:props [:fills]
|
||||||
:to-prop {:fills (if (> (count (:fills shape)) 1) "background-image" "background-color")}
|
: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}}
|
:format {:fills format-fill-color}}
|
||||||
:stroke {:props [:strokes]
|
:stroke {:props [:strokes]
|
||||||
:to-prop {:strokes "border"}
|
:to-prop {:strokes "border"}
|
||||||
:format {:strokes format-stroke}}
|
: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]
|
:shadow {:props [:shadow]
|
||||||
:to-prop {:shadow :box-shadow}
|
:to-prop {:shadow :box-shadow}
|
||||||
:format {:shadow #(str/join ", " (map shadow->css %1))}}
|
:format {:shadow #(str/join ", " (map shadow->css %1))}}
|
||||||
:blur {:props [:blur]
|
:blur {:props [:blur]
|
||||||
:to-prop {:blur "filter"}
|
:to-prop {:blur "filter"}
|
||||||
:format {:blur #(str/fmt "blur(%spx)" (:value %))}}
|
:format {:blur #(str/fmt "blur(%spx)" (:value %))}}
|
||||||
|
|
||||||
:layout-flex {:props [:layout
|
:layout-flex {:props [:layout
|
||||||
:layout-flex-dir
|
:layout-flex-dir
|
||||||
:layout-align-items
|
:layout-align-items
|
||||||
|
:layout-justify-items
|
||||||
|
:layout-align-content
|
||||||
:layout-justify-content
|
:layout-justify-content
|
||||||
:layout-gap
|
:layout-gap
|
||||||
:layout-padding
|
:layout-padding
|
||||||
:layout-wrap-type]
|
:layout-wrap-type]
|
||||||
|
:gen-props [:flex-shrink]
|
||||||
:to-prop {:layout "display"
|
:to-prop {:layout "display"
|
||||||
:layout-flex-dir "flex-direction"
|
:layout-flex-dir "flex-direction"
|
||||||
:layout-align-items "align-items"
|
:layout-align-items "align-items"
|
||||||
|
:layout-align-content "align-content"
|
||||||
|
:layout-justify-items "justify-items"
|
||||||
:layout-justify-content "justify-content"
|
:layout-justify-content "justify-content"
|
||||||
:layout-wrap-type "flex-wrap"
|
:layout-wrap-type "flex-wrap"
|
||||||
:layout-gap "gap"
|
:layout-gap "gap"
|
||||||
|
@ -123,10 +200,24 @@
|
||||||
:format {:layout d/name
|
:format {:layout d/name
|
||||||
:layout-flex-dir d/name
|
:layout-flex-dir d/name
|
||||||
:layout-align-items d/name
|
:layout-align-items d/name
|
||||||
|
:layout-align-content d/name
|
||||||
|
:layout-justify-items d/name
|
||||||
:layout-justify-content d/name
|
:layout-justify-content d/name
|
||||||
:layout-wrap-type d/name
|
:layout-wrap-type d/name
|
||||||
:layout-gap fmt/format-gap
|
:layout-gap fmt/format-gap
|
||||||
:layout-padding fmt/format-padding}}})
|
: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
|
(def style-text
|
||||||
{:props [:fills
|
{:props [:fills
|
||||||
|
@ -190,9 +281,12 @@
|
||||||
|
|
||||||
(defn generate-css-props
|
(defn generate-css-props
|
||||||
([values properties]
|
([values properties]
|
||||||
(generate-css-props values properties nil))
|
(generate-css-props values properties [] nil))
|
||||||
|
|
||||||
([values properties params]
|
([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]
|
(let [{:keys [to-prop format tab-size multi]
|
||||||
:or {to-prop {} tab-size 0 multi {}}} params
|
:or {to-prop {} tab-size 0 multi {}}} params
|
||||||
|
|
||||||
|
@ -210,7 +304,7 @@
|
||||||
to-prop)
|
to-prop)
|
||||||
|
|
||||||
get-value (fn [prop]
|
get-value (fn [prop]
|
||||||
(if-let [props (prop multi)]
|
(if-let [props (get multi prop)]
|
||||||
(map #(get values %) props)
|
(map #(get values %) props)
|
||||||
(get-specific-value values prop)))
|
(get-specific-value values prop)))
|
||||||
|
|
||||||
|
@ -220,30 +314,35 @@
|
||||||
(or (nil? value) (= value 0))))
|
(or (nil? value) (= value 0))))
|
||||||
|
|
||||||
default-format (fn [value] (dm/str (fmt/format-pixels value)))
|
default-format (fn [value] (dm/str (fmt/format-pixels value)))
|
||||||
format-property (fn [prop]
|
|
||||||
(let [css-prop (or (prop to-prop) (d/name prop))
|
|
||||||
format-fn (or (prop format) default-format)
|
|
||||||
css-val (format-fn (get-value prop) values)]
|
|
||||||
(when css-val
|
|
||||||
(dm/str
|
|
||||||
(str/repeat " " tab-size)
|
|
||||||
(str/fmt "%s: %s;" css-prop css-val)))))]
|
|
||||||
|
|
||||||
(->> properties
|
format-property
|
||||||
(remove #(null? (get-value %)))
|
(fn [prop]
|
||||||
(map format-property)
|
(let [css-prop (or (get to-prop prop) (d/name prop))
|
||||||
(filter (comp not nil?))
|
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")))))
|
(str/join "\n")))))
|
||||||
|
|
||||||
(defn shape->properties [shape]
|
(defn shape->properties [objects shape]
|
||||||
(let [;; This property is added in an earlier step (code.cljs),
|
(let [;; This property is added in an earlier step (code.cljs),
|
||||||
;; it will come with a vector of flex-items if any.
|
;; it will come with a vector of flex-items if any.
|
||||||
;; If there are none it will continue as usual.
|
;; If there are none it will continue as usual.
|
||||||
flex-items (:flex-items shape)
|
flex-items (:flex-items shape)
|
||||||
props (->> (styles-data shape) vals (mapcat :props))
|
props (->> (styles-data objects shape) vals (mapcat :props))
|
||||||
to-prop (->> (styles-data shape) vals (map :to-prop) (reduce merge))
|
to-prop (->> (styles-data objects shape) vals (map :to-prop) (reduce merge))
|
||||||
format (->> (styles-data shape) vals (map :format) (reduce merge))
|
format (->> (styles-data objects shape) vals (map :format) (reduce merge))
|
||||||
multi (->> (styles-data shape) vals (map :multi) (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
|
props (cond-> props
|
||||||
(seq flex-items) (concat (:props layout-flex-item-params))
|
(seq flex-items) (concat (:props layout-flex-item-params))
|
||||||
(= :wrap (:layout-wrap-type shape)) (concat (:props layout-align-content)))
|
(= :wrap (:layout-wrap-type shape)) (concat (:props layout-align-content)))
|
||||||
|
@ -253,10 +352,14 @@
|
||||||
format (cond-> format
|
format (cond-> format
|
||||||
(seq flex-items) (merge (:format layout-flex-item-params))
|
(seq flex-items) (merge (:format layout-flex-item-params))
|
||||||
(= :wrap (:layout-wrap-type shape)) (merge (:format layout-align-content)))]
|
(= :wrap (:layout-wrap-type shape)) (merge (:format layout-align-content)))]
|
||||||
(generate-css-props shape props {:to-prop to-prop
|
(generate-css-props
|
||||||
:format format
|
shape
|
||||||
:multi multi
|
props
|
||||||
:tab-size 2})))
|
gen-props
|
||||||
|
{:to-prop to-prop
|
||||||
|
:format format
|
||||||
|
:multi multi
|
||||||
|
:tab-size 2})))
|
||||||
|
|
||||||
(defn search-text-attrs
|
(defn search-text-attrs
|
||||||
[node attrs]
|
[node attrs]
|
||||||
|
@ -269,36 +372,36 @@
|
||||||
(defn parse-style-text-blocks
|
(defn parse-style-text-blocks
|
||||||
[node attrs]
|
[node attrs]
|
||||||
(letfn
|
(letfn
|
||||||
[(rec-style-text-map [acc node style]
|
[(rec-style-text-map [acc node style]
|
||||||
(let [node-style (merge style (select-keys node attrs))
|
(let [node-style (merge style (select-keys node attrs))
|
||||||
head (or (-> acc first) [{} ""])
|
head (or (-> acc first) [{} ""])
|
||||||
[head-style head-text] head
|
[head-style head-text] head
|
||||||
|
|
||||||
new-acc
|
new-acc
|
||||||
(cond
|
(cond
|
||||||
(:children node)
|
(:children node)
|
||||||
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
|
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
|
||||||
|
|
||||||
(not= head-style node-style)
|
(not= head-style node-style)
|
||||||
(cons [node-style (:text node "")] acc)
|
(cons [node-style (:text node "")] acc)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(cons [node-style (dm/str head-text "" (:text node))] (rest acc)))
|
(cons [node-style (dm/str head-text "" (:text node))] (rest acc)))
|
||||||
|
|
||||||
;; We add an end-of-line when finish a paragraph
|
;; We add an end-of-line when finish a paragraph
|
||||||
new-acc
|
new-acc
|
||||||
(if (= (:type node) "paragraph")
|
(if (= (:type node) "paragraph")
|
||||||
(let [[hs ht] (first new-acc)]
|
(let [[hs ht] (first new-acc)]
|
||||||
(cons [hs (dm/str ht "\n")] (rest new-acc)))
|
(cons [hs (dm/str ht "\n")] (rest new-acc)))
|
||||||
new-acc)]
|
new-acc)]
|
||||||
new-acc))]
|
new-acc))]
|
||||||
|
|
||||||
(-> (rec-style-text-map [] node {})
|
(-> (rec-style-text-map [] node {})
|
||||||
reverse)))
|
reverse)))
|
||||||
|
|
||||||
(defn text->properties [shape]
|
(defn text->properties [objects shape]
|
||||||
(let [flex-items (:flex-items shape)
|
(let [flex-items (:flex-items shape)
|
||||||
text-shape-style (select-keys (styles-data shape) [:layout :shadow :blur])
|
text-shape-style (d/without-keys (styles-data objects shape) [:fill :stroke])
|
||||||
|
|
||||||
shape-props (->> text-shape-style vals (mapcat :props))
|
shape-props (->> text-shape-style vals (mapcat :props))
|
||||||
shape-to-prop (->> text-shape-style vals (map :to-prop) (reduce merge))
|
shape-to-prop (->> text-shape-style vals (map :to-prop) (reduce merge))
|
||||||
|
@ -315,6 +418,7 @@
|
||||||
(:content shape)
|
(:content shape)
|
||||||
(conj (:props style-text) :fill-color-gradient :fill-opacity))
|
(conj (:props style-text) :fill-color-gradient :fill-opacity))
|
||||||
(d/merge txt/default-text-attrs))]
|
(d/merge txt/default-text-attrs))]
|
||||||
|
|
||||||
(str/join
|
(str/join
|
||||||
"\n"
|
"\n"
|
||||||
[(generate-css-props shape
|
[(generate-css-props shape
|
||||||
|
@ -328,21 +432,128 @@
|
||||||
:format (:format style-text)
|
:format (:format style-text)
|
||||||
:tab-size 2})])))
|
:tab-size 2})])))
|
||||||
|
|
||||||
(defn generate-css [shape]
|
(defn selector-name [shape]
|
||||||
(let [name (:name shape)
|
(let [
|
||||||
properties (if (= :text (:type shape))
|
name (-> (:name shape)
|
||||||
(text->properties shape)
|
#_(subs 0 (min 10 (count (:name shape)))))
|
||||||
(shape->properties shape))
|
;; selectors cannot start with numbers
|
||||||
selector (str/css-selector name)
|
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 (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/join "\n" [(str/fmt "/* %s */" name)
|
||||||
(str/fmt ".%s {" selector)
|
(str/fmt ".%s {" selector)
|
||||||
properties
|
properties
|
||||||
"}"])))
|
"}"])))
|
||||||
|
|
||||||
(defn generate-style-code [type shapes]
|
(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
|
(let [generate-style-fn (case type
|
||||||
"css" generate-css)]
|
"css" generate-css)]
|
||||||
(->> shapes
|
(dm/str
|
||||||
(map generate-style-fn)
|
"html, body {
|
||||||
(str/join "\n\n"))))
|
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")))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue