mirror of
https://github.com/penpot/penpot.git
synced 2025-07-24 11:17:12 +02:00
✨ Fix shadows in frames for dashboard and viewer
This commit is contained in:
parent
e1d6cded62
commit
8e60834292
11 changed files with 215 additions and 258 deletions
|
@ -98,13 +98,6 @@
|
||||||
(defn distance-shapes [shape other]
|
(defn distance-shapes [shape other]
|
||||||
(distance-selrect (:selrect shape) (:selrect other)))
|
(distance-selrect (:selrect shape) (:selrect other)))
|
||||||
|
|
||||||
(defn shape-stroke-margin
|
|
||||||
[shape stroke-width]
|
|
||||||
(if (= (:type shape) :path)
|
|
||||||
;; TODO: Calculate with the stroke offset (not implemented yet
|
|
||||||
(mth/sqrt (* 2 stroke-width stroke-width))
|
|
||||||
(- (mth/sqrt (* 2 stroke-width stroke-width)) stroke-width)))
|
|
||||||
|
|
||||||
(defn close-attrs?
|
(defn close-attrs?
|
||||||
"Compares two shapes attributes to see if they are equal or almost
|
"Compares two shapes attributes to see if they are equal or almost
|
||||||
equal (in case of numeric). Takes into account attributes that are
|
equal (in case of numeric). Takes into account attributes that are
|
||||||
|
|
151
common/src/app/common/geom/shapes/bounds.cljc
Normal file
151
common/src/app/common/geom/shapes/bounds.cljc
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
(ns app.common.geom.shapes.bounds
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.geom.shapes.rect :as gsr]
|
||||||
|
[app.common.math :as mth]
|
||||||
|
[app.common.pages.helpers :as cph]))
|
||||||
|
|
||||||
|
(defn shape-stroke-margin
|
||||||
|
[shape stroke-width]
|
||||||
|
(if (= (:type shape) :path)
|
||||||
|
;; TODO: Calculate with the stroke offset (not implemented yet
|
||||||
|
(mth/sqrt (* 2 stroke-width stroke-width))
|
||||||
|
(- (mth/sqrt (* 2 stroke-width stroke-width)) stroke-width)))
|
||||||
|
|
||||||
|
(defn blur-filters [type value]
|
||||||
|
(->> [value]
|
||||||
|
(remove :hidden)
|
||||||
|
(filter #(= (:type %) type))
|
||||||
|
(map #(hash-map :id (str "filter_" (:id %))
|
||||||
|
:type (:type %)
|
||||||
|
:params %))))
|
||||||
|
|
||||||
|
(defn shadow-filters [type filters]
|
||||||
|
(->> filters
|
||||||
|
(remove :hidden)
|
||||||
|
(filter #(= (:style %) type))
|
||||||
|
(map #(hash-map :id (str "filter_" (:id %))
|
||||||
|
:type (:style %)
|
||||||
|
:params %))))
|
||||||
|
|
||||||
|
(defn shape->filters
|
||||||
|
[shape]
|
||||||
|
(d/concat-vec
|
||||||
|
[{:id "BackgroundImageFix" :type :image-fix}]
|
||||||
|
|
||||||
|
;; Background blur won't work in current SVG specification
|
||||||
|
;; We can revisit this in the future
|
||||||
|
#_(->> shape :blur (blur-filters :background-blur))
|
||||||
|
|
||||||
|
(->> shape :shadow (shadow-filters :drop-shadow))
|
||||||
|
[{:id "shape" :type :blend-filters}]
|
||||||
|
(->> shape :shadow (shadow-filters :inner-shadow))
|
||||||
|
(->> shape :blur (blur-filters :layer-blur))))
|
||||||
|
|
||||||
|
(defn calculate-filter-bounds [{:keys [x y width height]} filter-entry]
|
||||||
|
(let [{:keys [offset-x offset-y blur spread] :or {offset-x 0 offset-y 0 blur 0 spread 0}} (:params filter-entry)
|
||||||
|
filter-x (min x (+ x offset-x (- spread) (- blur) -5))
|
||||||
|
filter-y (min y (+ y offset-y (- spread) (- blur) -5))
|
||||||
|
filter-width (+ width (mth/abs offset-x) (* spread 2) (* blur 2) 10)
|
||||||
|
filter-height (+ height (mth/abs offset-y) (* spread 2) (* blur 2) 10)]
|
||||||
|
(gsr/make-selrect filter-x filter-y filter-width filter-height)))
|
||||||
|
|
||||||
|
(defn get-rect-filter-bounds
|
||||||
|
[selrect filters blur-value]
|
||||||
|
(let [filter-bounds (->> filters
|
||||||
|
(filter #(= :drop-shadow (:type %)))
|
||||||
|
(map (partial calculate-filter-bounds selrect))
|
||||||
|
(concat [selrect])
|
||||||
|
(gsr/join-selrects))
|
||||||
|
delta-blur (* blur-value 2)
|
||||||
|
|
||||||
|
result
|
||||||
|
(-> filter-bounds
|
||||||
|
(update :x - delta-blur)
|
||||||
|
(update :y - delta-blur)
|
||||||
|
(update :x1 - delta-blur)
|
||||||
|
(update :x1 - delta-blur)
|
||||||
|
(update :x2 + delta-blur)
|
||||||
|
(update :y2 + delta-blur)
|
||||||
|
(update :width + (* delta-blur 2))
|
||||||
|
(update :height + (* delta-blur 2)))]
|
||||||
|
|
||||||
|
result))
|
||||||
|
|
||||||
|
(defn get-shape-filter-bounds
|
||||||
|
([shape]
|
||||||
|
(let [svg-root? (and (= :svg-raw (:type shape)) (not= :svg (get-in shape [:content :tag])))]
|
||||||
|
(if svg-root?
|
||||||
|
(:selrect shape)
|
||||||
|
|
||||||
|
(let [filters (shape->filters shape)
|
||||||
|
blur-value (or (-> shape :blur :value) 0)]
|
||||||
|
(get-rect-filter-bounds (-> shape :points gsr/points->selrect) filters blur-value))))))
|
||||||
|
|
||||||
|
(defn calculate-padding
|
||||||
|
([shape]
|
||||||
|
(calculate-padding shape false))
|
||||||
|
|
||||||
|
([shape ignore-margin?]
|
||||||
|
(let [stroke-width (apply max 0 (map #(case (:stroke-alignment % :center)
|
||||||
|
:center (/ (:stroke-width % 0) 2)
|
||||||
|
:outer (:stroke-width % 0)
|
||||||
|
0) (:strokes shape)))
|
||||||
|
|
||||||
|
margin (if ignore-margin?
|
||||||
|
0
|
||||||
|
(apply max 0 (map #(shape-stroke-margin % stroke-width) (:strokes shape))))
|
||||||
|
|
||||||
|
shadow-width (apply max 0 (map #(case (:style % :drop-shadow)
|
||||||
|
:drop-shadow (+ (mth/abs (:offset-x %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
||||||
|
0) (:shadow shape)))
|
||||||
|
|
||||||
|
shadow-height (apply max 0 (map #(case (:style % :drop-shadow)
|
||||||
|
:drop-shadow (+ (mth/abs (:offset-y %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
||||||
|
0) (:shadow shape)))]
|
||||||
|
|
||||||
|
{:horizontal (+ stroke-width margin shadow-width)
|
||||||
|
:vertical (+ stroke-width margin shadow-height)})))
|
||||||
|
|
||||||
|
(defn- add-padding
|
||||||
|
[bounds padding]
|
||||||
|
(-> bounds
|
||||||
|
(update :x - (:horizontal padding))
|
||||||
|
(update :y - (:vertical padding))
|
||||||
|
(update :width + (* 2 (:horizontal padding)))
|
||||||
|
(update :height + (* 2 (:vertical padding)))))
|
||||||
|
|
||||||
|
(defn get-object-bounds
|
||||||
|
[objects shape]
|
||||||
|
|
||||||
|
(let [calculate-base-bounds
|
||||||
|
(fn [shape]
|
||||||
|
(-> (get-shape-filter-bounds shape)
|
||||||
|
(add-padding (calculate-padding shape true))))
|
||||||
|
|
||||||
|
bounds
|
||||||
|
(cph/reduce-objects
|
||||||
|
objects
|
||||||
|
(fn [shape]
|
||||||
|
(and (d/not-empty? (:shapes shape))
|
||||||
|
(or (not (cph/frame-shape? shape))
|
||||||
|
(:show-content shape))
|
||||||
|
|
||||||
|
(or (not (cph/group-shape? shape))
|
||||||
|
(not (:masked-group? shape)))))
|
||||||
|
|
||||||
|
(:id shape)
|
||||||
|
|
||||||
|
(fn [result shape]
|
||||||
|
(conj result (get-object-bounds objects shape)))
|
||||||
|
|
||||||
|
[(calculate-base-bounds shape)])
|
||||||
|
|
||||||
|
|
||||||
|
children-bounds (or (:children-bounds shape) (gsr/join-selrects bounds))
|
||||||
|
|
||||||
|
filters (shape->filters shape)
|
||||||
|
blur-value (or (-> shape :blur :value) 0)]
|
||||||
|
|
||||||
|
(get-rect-filter-bounds children-bounds filters blur-value)))
|
||||||
|
|
|
@ -657,7 +657,10 @@
|
||||||
(reduce-objects objects nil reducer-fn init-val))
|
(reduce-objects objects nil reducer-fn init-val))
|
||||||
|
|
||||||
([objects check-children? reducer-fn init-val]
|
([objects check-children? reducer-fn init-val]
|
||||||
(let [root-children (get-in objects [uuid/zero :shapes])]
|
(reduce-objects objects check-children? uuid/zero reducer-fn init-val))
|
||||||
|
|
||||||
|
([objects check-children? root-id reducer-fn init-val]
|
||||||
|
(let [root-children (get-in objects [root-id :shapes])]
|
||||||
(if (empty? root-children)
|
(if (empty? root-children)
|
||||||
init-val
|
init-val
|
||||||
|
|
||||||
|
|
|
@ -359,7 +359,6 @@
|
||||||
|
|
||||||
(p/let [params {:file-id file-id
|
(p/let [params {:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:render-texts true
|
|
||||||
:render-embed true
|
:render-embed true
|
||||||
:object-id (mapv :id objects)
|
:object-id (mapv :id objects)
|
||||||
:route "objects"}
|
:route "objects"}
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
height: 120px;
|
height: 120px;
|
||||||
border: 1px solid $color-gray-20;
|
border: 1px solid $color-gray-20;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
(:require
|
(:require
|
||||||
["react-dom/server" :as rds]
|
["react-dom/server" :as rds]
|
||||||
[app.common.colors :as clr]
|
[app.common.colors :as clr]
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.geom.shapes.bounds :as gsb]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
|
@ -28,7 +28,6 @@
|
||||||
[app.main.ui.shapes.circle :as circle]
|
[app.main.ui.shapes.circle :as circle]
|
||||||
[app.main.ui.shapes.embed :as embed]
|
[app.main.ui.shapes.embed :as embed]
|
||||||
[app.main.ui.shapes.export :as export]
|
[app.main.ui.shapes.export :as export]
|
||||||
[app.main.ui.shapes.filters :as filters]
|
|
||||||
[app.main.ui.shapes.frame :as frame]
|
[app.main.ui.shapes.frame :as frame]
|
||||||
[app.main.ui.shapes.group :as group]
|
[app.main.ui.shapes.group :as group]
|
||||||
[app.main.ui.shapes.image :as image]
|
[app.main.ui.shapes.image :as image]
|
||||||
|
@ -61,13 +60,11 @@
|
||||||
|
|
||||||
(defn- calculate-dimensions
|
(defn- calculate-dimensions
|
||||||
[objects]
|
[objects]
|
||||||
(let [rect
|
(let [bounds
|
||||||
(->> (cph/get-root-objects objects)
|
(->> (cph/get-root-objects objects)
|
||||||
(map #(if (some? (:children-bounds %))
|
(map (partial gsb/get-object-bounds objects))
|
||||||
(:children-bounds %)
|
(gsh/join-rects))]
|
||||||
(gsh/points->selrect (:points %))))
|
(-> bounds
|
||||||
(gsh/join-selrects))]
|
|
||||||
(-> rect
|
|
||||||
(update :x mth/finite 0)
|
(update :x mth/finite 0)
|
||||||
(update :y mth/finite 0)
|
(update :y mth/finite 0)
|
||||||
(update :width mth/finite 100000)
|
(update :width mth/finite 100000)
|
||||||
|
@ -193,36 +190,12 @@
|
||||||
|
|
||||||
(reduce updt-fn objects mod-ids)))
|
(reduce updt-fn objects mod-ids)))
|
||||||
|
|
||||||
(defn get-object-bounds
|
|
||||||
[objects object-id]
|
|
||||||
(let [object (get objects object-id)
|
|
||||||
padding (filters/calculate-padding object true)
|
|
||||||
bounds (-> (filters/get-filters-bounds object)
|
|
||||||
(update :x - (:horizontal padding))
|
|
||||||
(update :y - (:vertical padding))
|
|
||||||
(update :width + (* 2 (:horizontal padding)))
|
|
||||||
(update :height + (* 2 (:vertical padding))))]
|
|
||||||
|
|
||||||
(cond
|
|
||||||
(and (cph/group-shape? object) (:masked-group? object))
|
|
||||||
(get-object-bounds objects (-> object :shapes first))
|
|
||||||
|
|
||||||
(or (cph/group-shape? object)
|
|
||||||
(and (cph/frame-shape? object) (:show-content object)))
|
|
||||||
(->> (:shapes object)
|
|
||||||
(into [bounds] (map (partial get-object-bounds objects)))
|
|
||||||
(gsh/join-rects))
|
|
||||||
|
|
||||||
:else
|
|
||||||
bounds)))
|
|
||||||
|
|
||||||
(mf/defc page-svg
|
(mf/defc page-svg
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [data thumbnails? render-embed? include-metadata?] :as props
|
[{:keys [data thumbnails? render-embed? include-metadata?] :as props
|
||||||
:or {render-embed? false include-metadata? false}}]
|
:or {render-embed? false include-metadata? false}}]
|
||||||
(let [objects (:objects data)
|
(let [objects (:objects data)
|
||||||
shapes (cph/get-immediate-children objects)
|
shapes (cph/get-immediate-children objects)
|
||||||
|
|
||||||
dim (calculate-dimensions objects)
|
dim (calculate-dimensions objects)
|
||||||
vbox (format-viewbox dim)
|
vbox (format-viewbox dim)
|
||||||
bgcolor (dm/get-in data [:options :background] default-color)
|
bgcolor (dm/get-in data [:options :background] default-color)
|
||||||
|
@ -248,7 +221,6 @@
|
||||||
(when include-metadata?
|
(when include-metadata?
|
||||||
[:& export/export-page {:options (:options data)}])
|
[:& export/export-page {:options (:options data)}])
|
||||||
|
|
||||||
|
|
||||||
(let [shapes (->> shapes
|
(let [shapes (->> shapes
|
||||||
(remove cph/frame-shape?)
|
(remove cph/frame-shape?)
|
||||||
(mapcat #(cph/get-children-with-self objects (:id %))))
|
(mapcat #(cph/get-children-with-self objects (:id %))))
|
||||||
|
@ -262,20 +234,20 @@
|
||||||
|
|
||||||
;; Component that serves for render frame thumbnails, mainly used in
|
;; Component that serves for render frame thumbnails, mainly used in
|
||||||
;; the viewer and handoff
|
;; the viewer and handoff
|
||||||
|
|
||||||
(mf/defc frame-svg
|
(mf/defc frame-svg
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [objects frame zoom show-thumbnails?] :or {zoom 1} :as props}]
|
[{:keys [objects frame zoom show-thumbnails?] :or {zoom 1} :as props}]
|
||||||
(let [frame-id (:id frame)
|
(let [frame-id (:id frame)
|
||||||
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
||||||
|
|
||||||
bounds (or (:children-bounds frame) (gsh/points->rect (:points frame)))
|
bounds (gsb/get-object-bounds objects frame)
|
||||||
|
|
||||||
modifier
|
;; Bounds without shadows/blur will be the bounds of the thumbnail
|
||||||
(mf/with-memo [(:x bounds) (:y bounds)]
|
bounds2 (gsb/get-object-bounds objects (dissoc frame :shadow :blur))
|
||||||
(-> (gpt/point (:x bounds) (:y bounds))
|
|
||||||
(gpt/negate)
|
delta-bounds (gpt/point (:x bounds) (:y bounds))
|
||||||
(gmt/translate-matrix)))
|
|
||||||
|
modifier (gmt/translate-matrix (gpt/negate delta-bounds))
|
||||||
|
|
||||||
children-ids
|
children-ids
|
||||||
(cph/get-children-ids objects frame-id)
|
(cph/get-children-ids objects frame-id)
|
||||||
|
@ -293,19 +265,19 @@
|
||||||
(assoc-in [:modifiers :displacement] modifier)
|
(assoc-in [:modifiers :displacement] modifier)
|
||||||
(gsh/transform-shape)))
|
(gsh/transform-shape)))
|
||||||
|
|
||||||
bounds
|
|
||||||
(if (:show-content frame)
|
|
||||||
(gsh/selection-rect (concat [frame] (->> children-ids (map (d/getf objects)))))
|
|
||||||
(-> frame :points gsh/points->rect))
|
|
||||||
|
|
||||||
frame
|
frame
|
||||||
(cond-> frame
|
(cond-> frame
|
||||||
(and (some? bounds) (nil? (:children-bounds bounds)))
|
(and (some? bounds) (nil? (:children-bounds bounds)))
|
||||||
(assoc :children-bounds bounds))
|
(assoc :children-bounds bounds2))
|
||||||
|
|
||||||
frame-wrapper
|
frame (-> frame
|
||||||
(mf/with-memo [objects]
|
(update-in [:children-bounds :x] - (:x delta-bounds))
|
||||||
(frame-wrapper-factory objects))
|
(update-in [:children-bounds :y] - (:y delta-bounds)))
|
||||||
|
|
||||||
|
shape-wrapper
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps objects)
|
||||||
|
#(shape-wrapper-factory objects))
|
||||||
|
|
||||||
width (* (:width bounds) zoom)
|
width (* (:width bounds) zoom)
|
||||||
height (* (:height bounds) zoom)
|
height (* (:height bounds) zoom)
|
||||||
|
@ -321,13 +293,11 @@
|
||||||
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")
|
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")
|
||||||
:fill "none"}
|
:fill "none"}
|
||||||
|
|
||||||
[:> shape-container {:shape frame}
|
[:& shape-wrapper {:shape frame}]]]))
|
||||||
[:& frame-wrapper {:shape frame :view-box vbox}]]]]))
|
|
||||||
|
|
||||||
|
|
||||||
;; Component for rendering a thumbnail of a single componenent. Mainly
|
;; Component for rendering a thumbnail of a single componenent. Mainly
|
||||||
;; used to render thumbnails on assets panel.
|
;; used to render thumbnails on assets panel.
|
||||||
|
|
||||||
(mf/defc component-svg
|
(mf/defc component-svg
|
||||||
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
||||||
[{:keys [objects group zoom] :or {zoom 1} :as props}]
|
[{:keys [objects group zoom] :or {zoom 1} :as props}]
|
||||||
|
@ -375,7 +345,7 @@
|
||||||
|
|
||||||
(mf/defc object-svg
|
(mf/defc object-svg
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [objects object-id render-texts? render-embed?]
|
[{:keys [objects object-id render-embed?]
|
||||||
:or {render-embed? false}
|
:or {render-embed? false}
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [object (get objects object-id)
|
(let [object (get objects object-id)
|
||||||
|
@ -383,30 +353,21 @@
|
||||||
(:hide-fill-on-export object)
|
(:hide-fill-on-export object)
|
||||||
(assoc :fills []))
|
(assoc :fills []))
|
||||||
|
|
||||||
{:keys [x y width height]} (get-object-bounds objects object-id)
|
|
||||||
vbox (dm/str x " " y " " width " " height)
|
|
||||||
|
|
||||||
frame-wrapper
|
bounds (gsb/get-object-bounds objects object)
|
||||||
(mf/with-memo [objects]
|
vbox (format-viewbox bounds)
|
||||||
(frame-wrapper-factory objects))
|
fonts (ff/shape->fonts object objects)
|
||||||
|
|
||||||
group-wrapper
|
|
||||||
(mf/with-memo [objects]
|
|
||||||
(group-wrapper-factory objects))
|
|
||||||
|
|
||||||
shape-wrapper
|
shape-wrapper
|
||||||
(mf/with-memo [objects]
|
(mf/with-memo [objects]
|
||||||
(shape-wrapper-factory objects))
|
(shape-wrapper-factory objects))]
|
||||||
|
|
||||||
text-shapes (sequence (filter cph/text-shape?) (vals objects))
|
|
||||||
render-texts? (and render-texts? (d/seek (comp nil? :position-data) text-shapes))]
|
|
||||||
|
|
||||||
[:& (mf/provider export/include-metadata-ctx) {:value false}
|
[:& (mf/provider export/include-metadata-ctx) {:value false}
|
||||||
[:& (mf/provider embed/context) {:value render-embed?}
|
[:& (mf/provider embed/context) {:value render-embed?}
|
||||||
[:svg {:id (dm/str "screenshot-" object-id)
|
[:svg {:id (dm/str "screenshot-" object-id)
|
||||||
:view-box vbox
|
:view-box vbox
|
||||||
:width width
|
:width (:width bounds)
|
||||||
:height height
|
:height (:height bounds)
|
||||||
:version "1.1"
|
:version "1.1"
|
||||||
:xmlns "http://www.w3.org/2000/svg"
|
:xmlns "http://www.w3.org/2000/svg"
|
||||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||||
|
@ -415,30 +376,8 @@
|
||||||
:style {:-webkit-print-color-adjust :exact}
|
:style {:-webkit-print-color-adjust :exact}
|
||||||
:fill "none"}
|
:fill "none"}
|
||||||
|
|
||||||
(let [fonts (ff/shape->fonts object objects)]
|
[:& ff/fontfaces-style {:fonts fonts}]
|
||||||
[:& ff/fontfaces-style {:fonts fonts}])
|
[:& shape-wrapper {:shape object}]]]]))
|
||||||
|
|
||||||
(case (:type object)
|
|
||||||
:frame [:> shape-container {:shape object}
|
|
||||||
[:& frame-wrapper {:shape object :view-box vbox}]]
|
|
||||||
:group [:> shape-container {:shape object}
|
|
||||||
[:& group-wrapper {:shape object}]]
|
|
||||||
[:& shape-wrapper {:shape object}])]
|
|
||||||
|
|
||||||
;; Auxiliary SVG for rendering text-shapes
|
|
||||||
(when render-texts?
|
|
||||||
(for [object text-shapes]
|
|
||||||
[:& (mf/provider muc/text-plain-colors-ctx) {:value true}
|
|
||||||
[:svg
|
|
||||||
{:id (dm/str "screenshot-text-" (:id object))
|
|
||||||
:view-box (dm/str "0 0 " (:width object) " " (:height object))
|
|
||||||
:width (:width object)
|
|
||||||
:height (:height object)
|
|
||||||
:version "1.1"
|
|
||||||
:xmlns "http://www.w3.org/2000/svg"
|
|
||||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
|
||||||
:fill "none"}
|
|
||||||
[:& shape-wrapper {:shape (assoc object :x 0 :y 0)}]]]))]]))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; SPRITES (DEBUG)
|
;; SPRITES (DEBUG)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[app.common.data :as d]
|
[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.geom.shapes.bounds :as gsb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.main.ui.context :as muc]
|
[app.main.ui.context :as muc]
|
||||||
[app.main.ui.shapes.attrs :as attrs]
|
[app.main.ui.shapes.attrs :as attrs]
|
||||||
|
@ -45,7 +46,7 @@
|
||||||
:center (/ (:stroke-width shape 0) 2)
|
:center (/ (:stroke-width shape 0) 2)
|
||||||
:outer (:stroke-width shape 0)
|
:outer (:stroke-width shape 0)
|
||||||
0)
|
0)
|
||||||
margin (gsh/shape-stroke-margin shape stroke-width)
|
margin (gsb/shape-stroke-margin shape stroke-width)
|
||||||
bounding-box (-> (gsh/points->selrect (:points shape))
|
bounding-box (-> (gsh/points->selrect (:points shape))
|
||||||
(update :x - (+ stroke-width margin))
|
(update :x - (+ stroke-width margin))
|
||||||
(update :y - (+ stroke-width margin))
|
(update :y - (+ stroke-width margin))
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes.bounds :as gsb]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.util.color :as color]
|
[app.util.color :as color]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -108,34 +107,6 @@
|
||||||
:in2 filter-in
|
:in2 filter-in
|
||||||
:result filter-id}])
|
:result filter-id}])
|
||||||
|
|
||||||
(defn filter-bounds [shape filter-entry]
|
|
||||||
(let [{:keys [x y width height]} (:selrect shape)
|
|
||||||
{:keys [offset-x offset-y blur spread] :or {offset-x 0 offset-y 0 blur 0 spread 0}} (:params filter-entry)
|
|
||||||
filter-x (min x (+ x offset-x (- spread) (- blur) -5))
|
|
||||||
filter-y (min y (+ y offset-y (- spread) (- blur) -5))
|
|
||||||
filter-width (+ width (mth/abs offset-x) (* spread 2) (* blur 2) 10)
|
|
||||||
filter-height (+ height (mth/abs offset-y) (* spread 2) (* blur 2) 10)]
|
|
||||||
{:x1 filter-x
|
|
||||||
:y1 filter-y
|
|
||||||
:x2 (+ filter-x filter-width)
|
|
||||||
:y2 (+ filter-y filter-height)}))
|
|
||||||
|
|
||||||
(defn blur-filters [type value]
|
|
||||||
(->> [value]
|
|
||||||
(remove :hidden)
|
|
||||||
(filter #(= (:type %) type))
|
|
||||||
(map #(hash-map :id (str "filter_" (:id %))
|
|
||||||
:type (:type %)
|
|
||||||
:params %))))
|
|
||||||
|
|
||||||
(defn shadow-filters [type filters]
|
|
||||||
(->> filters
|
|
||||||
(remove :hidden)
|
|
||||||
(filter #(= (:style %) type))
|
|
||||||
(map #(hash-map :id (str "filter_" (:id %))
|
|
||||||
:type (:style %)
|
|
||||||
:params %))))
|
|
||||||
|
|
||||||
(mf/defc filter-entry [{:keys [entry]}]
|
(mf/defc filter-entry [{:keys [entry]}]
|
||||||
(let [props #js {:filter-id (:id entry)
|
(let [props #js {:filter-id (:id entry)
|
||||||
:filter-in (:filter-in entry)
|
:filter-in (:filter-in entry)
|
||||||
|
@ -148,84 +119,6 @@
|
||||||
:image-fix [:> image-fix-filter props]
|
:image-fix [:> image-fix-filter props]
|
||||||
:blend-filters [:> blend-filters props])))
|
:blend-filters [:> blend-filters props])))
|
||||||
|
|
||||||
(defn shape->filters
|
|
||||||
[shape]
|
|
||||||
(d/concat-vec
|
|
||||||
[{:id "BackgroundImageFix" :type :image-fix}]
|
|
||||||
|
|
||||||
;; Background blur won't work in current SVG specification
|
|
||||||
;; We can revisit this in the future
|
|
||||||
#_(->> shape :blur (blur-filters :background-blur))
|
|
||||||
|
|
||||||
(->> shape :shadow (shadow-filters :drop-shadow))
|
|
||||||
[{:id "shape" :type :blend-filters}]
|
|
||||||
(->> shape :shadow (shadow-filters :inner-shadow))
|
|
||||||
(->> shape :blur (blur-filters :layer-blur))))
|
|
||||||
|
|
||||||
(defn get-filters-bounds
|
|
||||||
([shape]
|
|
||||||
(let [filters (shape->filters shape)
|
|
||||||
blur-value (or (-> shape :blur :value) 0)]
|
|
||||||
(get-filters-bounds shape filters blur-value)))
|
|
||||||
|
|
||||||
([shape filters blur-value]
|
|
||||||
|
|
||||||
(let [svg-root? (and (= :svg-raw (:type shape)) (not= :svg (get-in shape [:content :tag])))
|
|
||||||
{:keys [x y width height]} (:selrect shape)]
|
|
||||||
(if svg-root?
|
|
||||||
;; When is a raw-svg but not the root we use the whole svg as bound for the filter. Is the maximum
|
|
||||||
;; we're allowed to display
|
|
||||||
{:x x :y y :width width :height height}
|
|
||||||
|
|
||||||
;; Otherwise we calculate the bound
|
|
||||||
(let [filter-bounds (->> filters
|
|
||||||
(filter #(= :drop-shadow (:type %)))
|
|
||||||
(map (partial filter-bounds shape)))
|
|
||||||
;; We add the selrect so the minimum size will be the selrect
|
|
||||||
filter-bounds (conj filter-bounds (-> shape :points gsh/points->selrect))
|
|
||||||
|
|
||||||
x1 (apply min (map :x1 filter-bounds))
|
|
||||||
y1 (apply min (map :y1 filter-bounds))
|
|
||||||
x2 (apply max (map :x2 filter-bounds))
|
|
||||||
y2 (apply max (map :y2 filter-bounds))
|
|
||||||
|
|
||||||
x1 (- x1 (* blur-value 2))
|
|
||||||
x2 (+ x2 (* blur-value 2))
|
|
||||||
y1 (- y1 (* blur-value 2))
|
|
||||||
y2 (+ y2 (* blur-value 2))]
|
|
||||||
|
|
||||||
;; We should move the frame filter coordinates because they should be
|
|
||||||
;; relative with the frame. By default they come as absolute
|
|
||||||
{:x x1
|
|
||||||
:y y1
|
|
||||||
:width (- x2 x1)
|
|
||||||
:height (- y2 y1)})))))
|
|
||||||
|
|
||||||
(defn calculate-padding
|
|
||||||
([shape]
|
|
||||||
(calculate-padding shape false))
|
|
||||||
|
|
||||||
([shape ignore-margin?]
|
|
||||||
(let [stroke-width (apply max 0 (map #(case (:stroke-alignment % :center)
|
|
||||||
:center (/ (:stroke-width % 0) 2)
|
|
||||||
:outer (:stroke-width % 0)
|
|
||||||
0) (:strokes shape)))
|
|
||||||
|
|
||||||
margin (if ignore-margin?
|
|
||||||
0
|
|
||||||
(apply max 0 (map #(gsh/shape-stroke-margin % stroke-width) (:strokes shape))))
|
|
||||||
|
|
||||||
shadow-width (apply max 0 (map #(case (:style % :drop-shadow)
|
|
||||||
:drop-shadow (+ (mth/abs (:offset-x %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
|
||||||
0) (:shadow shape)))
|
|
||||||
|
|
||||||
shadow-height (apply max 0 (map #(case (:style % :drop-shadow)
|
|
||||||
:drop-shadow (+ (mth/abs (:offset-y %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
|
||||||
0) (:shadow shape)))]
|
|
||||||
|
|
||||||
{:horizontal (+ stroke-width margin shadow-width)
|
|
||||||
:vertical (+ stroke-width margin shadow-height)})))
|
|
||||||
|
|
||||||
(defn change-filter-in
|
(defn change-filter-in
|
||||||
"Adds the previous filter as `filter-in` parameter"
|
"Adds the previous filter as `filter-in` parameter"
|
||||||
[filters]
|
[filters]
|
||||||
|
@ -234,9 +127,9 @@
|
||||||
(mf/defc filters
|
(mf/defc filters
|
||||||
[{:keys [filter-id shape]}]
|
[{:keys [filter-id shape]}]
|
||||||
|
|
||||||
(let [filters (-> shape shape->filters change-filter-in)
|
(let [filters (-> shape gsb/shape->filters change-filter-in)
|
||||||
bounds (get-filters-bounds shape filters (or (-> shape :blur :value) 0))
|
bounds (gsb/get-rect-filter-bounds (:selrect shape) filters (or (-> shape :blur :value) 0))
|
||||||
padding (calculate-padding shape)
|
padding (gsb/calculate-padding shape)
|
||||||
selrect (:selrect shape)
|
selrect (:selrect shape)
|
||||||
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
|
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
|
||||||
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
|
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.main.ui.shapes.filters :as f]
|
[app.common.geom.shapes.bounds :as gsb]
|
||||||
[app.util.svg :as usvg]
|
[app.util.svg :as usvg]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
(d/parse-double (get-in svg-def [:attrs :width]))
|
(d/parse-double (get-in svg-def [:attrs :width]))
|
||||||
(d/parse-double (get-in svg-def [:attrs :height])))
|
(d/parse-double (get-in svg-def [:attrs :height])))
|
||||||
(gsh/transform-rect transform))
|
(gsh/transform-rect transform))
|
||||||
(f/get-filters-bounds shape))))
|
(gsb/get-shape-filter-bounds shape))))
|
||||||
|
|
||||||
(mf/defc svg-defs [{:keys [shape render-id]}]
|
(mf/defc svg-defs [{:keys [shape render-id]}]
|
||||||
(let [svg-defs (:svg-defs shape)
|
(let [svg-defs (:svg-defs shape)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes.bounds :as gsb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcm]
|
||||||
|
@ -23,7 +23,6 @@
|
||||||
[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.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.shapes.filters :as filters]
|
|
||||||
[app.main.ui.share-link]
|
[app.main.ui.share-link]
|
||||||
[app.main.ui.static :as static]
|
[app.main.ui.static :as static]
|
||||||
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
|
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
|
||||||
|
@ -39,16 +38,8 @@
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(defn- calculate-size
|
(defn- calculate-size
|
||||||
[frame zoom bounds]
|
[objects frame zoom]
|
||||||
(let [frame-bounds (filters/get-filters-bounds frame)
|
(let [{:keys [x y width height]} (gsb/get-object-bounds objects frame)]
|
||||||
{:keys [x y width height]} (if (:show-content frame)
|
|
||||||
(gsh/join-rects [bounds frame-bounds])
|
|
||||||
frame-bounds)
|
|
||||||
padding (filters/calculate-padding frame)
|
|
||||||
x (- x (:horizontal padding))
|
|
||||||
y (- y (:vertical padding))
|
|
||||||
width (+ width (* 2 (:horizontal padding)))
|
|
||||||
height (+ height (* 2 (:vertical padding)))]
|
|
||||||
{:base-width width
|
{:base-width width
|
||||||
:base-height height
|
:base-height height
|
||||||
:x x
|
:x x
|
||||||
|
@ -83,10 +74,9 @@
|
||||||
[:div.counter (str/join " / " [(+ index 1) num-frames])]
|
[:div.counter (str/join " / " [(+ index 1) num-frames])]
|
||||||
[:span]]])
|
[:span]]])
|
||||||
|
|
||||||
|
|
||||||
(mf/defc viewer-wrapper
|
(mf/defc viewer-wrapper
|
||||||
[{:keys [wrapper-size scroll orig-frame orig-viewport-ref orig-size page file users current-viewport-ref
|
[{:keys [wrapper-size scroll orig-frame orig-viewport-ref orig-size page file users current-viewport-ref
|
||||||
size frame interactions-mode overlays zoom close-overlay section index children-bounds] :as props}]
|
size frame interactions-mode overlays zoom close-overlay section index] :as props}]
|
||||||
(let [{clist :list} (mf/deref refs/comments-local)
|
(let [{clist :list} (mf/deref refs/comments-local)
|
||||||
show-comments-list (and (= section :comments) (= :show clist))]
|
show-comments-list (and (= section :comments) (= :show clist))]
|
||||||
[:*
|
[:*
|
||||||
|
@ -135,7 +125,7 @@
|
||||||
:interactions-mode interactions-mode}]
|
:interactions-mode interactions-mode}]
|
||||||
|
|
||||||
(for [overlay overlays]
|
(for [overlay overlays]
|
||||||
(let [size-over (calculate-size (:frame overlay) zoom children-bounds)]
|
(let [size-over (calculate-size (:objects page) (:frame overlay) zoom)]
|
||||||
[:*
|
[:*
|
||||||
(when (or (:close-click-outside overlay)
|
(when (or (:close-click-outside overlay)
|
||||||
(:background-overlay overlay))
|
(:background-overlay overlay))
|
||||||
|
@ -204,12 +194,6 @@
|
||||||
frames (:frames page)
|
frames (:frames page)
|
||||||
frame (get frames index)
|
frame (get frames index)
|
||||||
|
|
||||||
children-bounds
|
|
||||||
(mf/use-memo
|
|
||||||
(mf/deps page (:id frame))
|
|
||||||
#(-> (cph/get-children (:objects page) (:id frame))
|
|
||||||
(gsh/selection-rect)))
|
|
||||||
|
|
||||||
fullscreen? (mf/deref refs/viewer-fullscreen?)
|
fullscreen? (mf/deref refs/viewer-fullscreen?)
|
||||||
overlays (:overlays local)
|
overlays (:overlays local)
|
||||||
scroll (mf/use-state nil)
|
scroll (mf/use-state nil)
|
||||||
|
@ -219,13 +203,13 @@
|
||||||
(d/seek #(= (:id %) (:orig-frame-id current-animation)) frames))
|
(d/seek #(= (:id %) (:orig-frame-id current-animation)) frames))
|
||||||
|
|
||||||
size (mf/use-memo
|
size (mf/use-memo
|
||||||
(mf/deps frame zoom children-bounds)
|
(mf/deps frame zoom)
|
||||||
(fn [] (calculate-size frame zoom children-bounds)))
|
(fn [] (calculate-size (:objects page) frame zoom)))
|
||||||
|
|
||||||
orig-size (mf/use-memo
|
orig-size (mf/use-memo
|
||||||
(mf/deps orig-frame zoom)
|
(mf/deps orig-frame zoom)
|
||||||
(fn [] (when orig-frame
|
(fn [] (when orig-frame
|
||||||
(calculate-size orig-frame zoom children-bounds))))
|
(calculate-size (:objects page) orig-frame zoom))))
|
||||||
|
|
||||||
wrapper-size (mf/use-memo
|
wrapper-size (mf/use-memo
|
||||||
(mf/deps size orig-size zoom)
|
(mf/deps size orig-size zoom)
|
||||||
|
@ -318,7 +302,7 @@
|
||||||
wrapper-size)))))
|
wrapper-size)))))
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/use-layout-effect
|
||||||
(mf/deps current-animation children-bounds)
|
(mf/deps current-animation)
|
||||||
(fn []
|
(fn []
|
||||||
;; Overlay animations may be started when needed.
|
;; Overlay animations may be started when needed.
|
||||||
(when current-animation
|
(when current-animation
|
||||||
|
@ -328,7 +312,7 @@
|
||||||
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
||||||
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
||||||
overlays)
|
overlays)
|
||||||
overlay-size (calculate-size (:frame overlay) zoom children-bounds)
|
overlay-size (calculate-size (:objects page) (:frame overlay) zoom)
|
||||||
overlay-position {:x (* (:x (:position overlay)) zoom)
|
overlay-position {:x (* (:x (:position overlay)) zoom)
|
||||||
:y (* (:y (:position overlay)) zoom)}]
|
:y (* (:y (:position overlay)) zoom)}]
|
||||||
(interactions/animate-open-overlay
|
(interactions/animate-open-overlay
|
||||||
|
@ -342,7 +326,7 @@
|
||||||
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
||||||
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
||||||
overlays)
|
overlays)
|
||||||
overlay-size (calculate-size (:frame overlay) zoom children-bounds)
|
overlay-size (calculate-size (:objects page) (:frame overlay) zoom)
|
||||||
overlay-position {:x (* (:x (:position overlay)) zoom)
|
overlay-position {:x (* (:x (:position overlay)) zoom)
|
||||||
:y (* (:y (:position overlay)) zoom)}]
|
:y (* (:y (:position overlay)) zoom)}]
|
||||||
(interactions/animate-close-overlay
|
(interactions/animate-close-overlay
|
||||||
|
@ -427,8 +411,7 @@
|
||||||
:overlays overlays
|
:overlays overlays
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:section section
|
:section section
|
||||||
:index index
|
:index index}]))]]]))
|
||||||
:children-bounds children-bounds}]))]]]))
|
|
||||||
|
|
||||||
;; --- Component: Viewer Page
|
;; --- Component: Viewer Page
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
state))
|
state))
|
||||||
|
|
||||||
(mf/defc object-svg
|
(mf/defc object-svg
|
||||||
[{:keys [page-id file-id object-id render-embed? render-texts?]}]
|
[{:keys [page-id file-id object-id render-embed?]}]
|
||||||
(let [fetch-state (mf/use-fn
|
(let [fetch-state (mf/use-fn
|
||||||
(mf/deps file-id page-id object-id)
|
(mf/deps file-id page-id object-id)
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -131,11 +131,10 @@
|
||||||
[:& render/object-svg
|
[:& render/object-svg
|
||||||
{:objects objects
|
{:objects objects
|
||||||
:object-id object-id
|
:object-id object-id
|
||||||
:render-embed? render-embed?
|
:render-embed? render-embed?}])))
|
||||||
:render-texts? render-texts?}])))
|
|
||||||
|
|
||||||
(mf/defc objects-svg
|
(mf/defc objects-svg
|
||||||
[{:keys [page-id file-id object-ids render-embed? render-texts?]}]
|
[{:keys [page-id file-id object-ids render-embed?]}]
|
||||||
(let [fetch-state (mf/use-fn
|
(let [fetch-state (mf/use-fn
|
||||||
(mf/deps file-id page-id)
|
(mf/deps file-id page-id)
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -157,27 +156,24 @@
|
||||||
{:objects objects
|
{:objects objects
|
||||||
:key (str object-id)
|
:key (str object-id)
|
||||||
:object-id object-id
|
:object-id object-id
|
||||||
:render-embed? render-embed?
|
:render-embed? render-embed?}])))))
|
||||||
:render-texts? render-texts?}])))))
|
|
||||||
|
|
||||||
(s/def ::page-id ::us/uuid)
|
(s/def ::page-id ::us/uuid)
|
||||||
(s/def ::file-id ::us/uuid)
|
(s/def ::file-id ::us/uuid)
|
||||||
(s/def ::object-id
|
(s/def ::object-id
|
||||||
(s/or :single ::us/uuid
|
(s/or :single ::us/uuid
|
||||||
:multiple (s/coll-of ::us/uuid)))
|
:multiple (s/coll-of ::us/uuid)))
|
||||||
(s/def ::render-text ::us/boolean)
|
|
||||||
(s/def ::embed ::us/boolean)
|
(s/def ::embed ::us/boolean)
|
||||||
|
|
||||||
(s/def ::render-objects
|
(s/def ::render-objects
|
||||||
(s/keys :req-un [::file-id ::page-id ::object-id]
|
(s/keys :req-un [::file-id ::page-id ::object-id]
|
||||||
:opt-un [::render-text ::render-embed]))
|
:opt-un [::render-embed]))
|
||||||
|
|
||||||
(defn- render-objects
|
(defn- render-objects
|
||||||
[params]
|
[params]
|
||||||
(let [{:keys [file-id
|
(let [{:keys [file-id
|
||||||
page-id
|
page-id
|
||||||
render-embed
|
render-embed]
|
||||||
render-texts]
|
|
||||||
:as params}
|
:as params}
|
||||||
(us/conform ::render-objects params)
|
(us/conform ::render-objects params)
|
||||||
|
|
||||||
|
@ -190,8 +186,7 @@
|
||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:object-id object-id
|
:object-id object-id
|
||||||
:render-embed? render-embed
|
:render-embed? render-embed}])
|
||||||
:render-texts? render-texts}])
|
|
||||||
|
|
||||||
:multiple
|
:multiple
|
||||||
(mf/html
|
(mf/html
|
||||||
|
@ -199,8 +194,7 @@
|
||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:object-ids (into #{} object-id)
|
:object-ids (into #{} object-id)
|
||||||
:render-embed? render-embed
|
:render-embed? render-embed}]))))
|
||||||
:render-texts? render-texts}]))))
|
|
||||||
|
|
||||||
;; ---- COMPONENTS SPRITE
|
;; ---- COMPONENTS SPRITE
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue