mirror of
https://github.com/penpot/penpot.git
synced 2025-03-20 11:41:47 -05:00
Merge remote-tracking branch 'origin/staging'
This commit is contained in:
commit
c638ab459f
33 changed files with 329 additions and 244 deletions
CHANGES.mdversion.txt
backend
common/src/app/common
exporter/src/app
frontend
resources/styles/main/partials
src/app
17
CHANGES.md
17
CHANGES.md
|
@ -1,5 +1,17 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 1.15.4-beta
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
- Fix overlay remains open on frame change [Taiga #4066](https://tree.taiga.io/project/penpot/issue/4066)
|
||||
- Fix toggle overlay position [Taiga #4091](https://tree.taiga.io/project/penpot/issue/4091)
|
||||
- Fix overlay closed on clicked outside [Taiga #4027](https://tree.taiga.io/project/penpot/issue/4027)
|
||||
- Fix animate multiple overlays [Taiga #3993](https://tree.taiga.io/project/penpot/issue/3993)
|
||||
- Fix problem with snap to grids [#2221](https://github.com/penpot/penpot/issues/2221)
|
||||
- Fix issue when scaling to value 0 [#2252](https://github.com/penpot/penpot/issues/2252)
|
||||
- Fix problem when moving shapes inside nested frames [Taiga #4113](https://tree.taiga.io/project/penpot/issue/4113)
|
||||
|
||||
## 1.15.3-beta
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
@ -9,6 +21,11 @@
|
|||
- Fix problem when hovering over nested frames [Taiga #4018](https://tree.taiga.io/project/penpot/issue/4018)
|
||||
- Fix problem editing rotated texts [Taiga #4026](https://tree.taiga.io/project/penpot/issue/4026)
|
||||
- Fix problem with texts for non existing fonts [Taiga #4087](https://tree.taiga.io/project/penpot/issue/4087)
|
||||
- Fix undo after moving layers will wrongly order the layers [Taiga #3344](https://tree.taiga.io/project/penpot/issue/3344)
|
||||
- Fix grouping typographies by drag & drop does not work (again) [#2203](https://github.com/penpot/penpot/issues/2203)
|
||||
- Fix when ungrouping, the items previously grouped should ALWAYS remain selected [Taiga #4064](https://tree.taiga.io/project/penpot/issue/4064)
|
||||
- Change shortcut for "Clear undo" [#2219](https://github.com/penpot/penpot/issues/2219)
|
||||
|
||||
|
||||
## 1.15.2-beta
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
;; Pretty Print specs
|
||||
pretty-spec/pretty-spec {:mvn/version "0.1.4"}
|
||||
software.amazon.awssdk/s3 {:mvn/version "2.17.209"}}
|
||||
software.amazon.awssdk/s3 {:mvn/version "2.17.272"}}
|
||||
|
||||
:paths ["src" "resources" "target/classes"]
|
||||
:aliases
|
||||
|
|
|
@ -515,7 +515,7 @@
|
|||
[_ {:keys [executor session] :as cfg}]
|
||||
(let [cfg (update cfg :provider d/without-nils)]
|
||||
["" {:middleware [[(:middleware session)]
|
||||
[hmw/with-promise-async executor]
|
||||
[hmw/with-dispatch executor]
|
||||
[hmw/with-config cfg]
|
||||
[provider-lookup]
|
||||
]}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.logging :as l]
|
||||
[app.common.transit :as t]
|
||||
[app.http.errors :as errors]
|
||||
[app.http.middleware :as middleware]
|
||||
[app.http.middleware :as mw]
|
||||
[app.metrics :as mtx]
|
||||
[app.worker :as wrk]
|
||||
[clojure.spec.alpha :as s]
|
||||
|
@ -144,12 +144,12 @@
|
|||
(defmethod ig/init-key ::router
|
||||
[_ {:keys [ws session metrics assets feedback] :as cfg}]
|
||||
(rr/router
|
||||
[["" {:middleware [[middleware/server-timing]
|
||||
[middleware/format-response]
|
||||
[middleware/params]
|
||||
[middleware/parse-request]
|
||||
[middleware/errors errors/handle]
|
||||
[middleware/restrict-methods]]}
|
||||
[["" {:middleware [[mw/server-timing]
|
||||
[mw/format-response]
|
||||
[mw/params]
|
||||
[mw/parse-request]
|
||||
[mw/errors errors/handle]
|
||||
[mw/restrict-methods]]}
|
||||
|
||||
["/metrics" {:handler (:handler metrics)}]
|
||||
["/assets" {:middleware [(:middleware session)]}
|
||||
|
@ -167,7 +167,7 @@
|
|||
:handler ws
|
||||
:allowed-methods #{:get}}]
|
||||
|
||||
["/api" {:middleware [[middleware/cors]
|
||||
["/api" {:middleware [[mw/cors]
|
||||
[(:middleware session)]]}
|
||||
["/audit/events" {:handler (:audit-handler cfg)
|
||||
:allowed-methods #{:post}}]
|
||||
|
@ -176,4 +176,3 @@
|
|||
(:doc-routes cfg)
|
||||
(:oidc-routes cfg)
|
||||
(:rpc-routes cfg)]]]))
|
||||
|
||||
|
|
|
@ -379,17 +379,20 @@
|
|||
|
||||
(defmethod ig/init-key ::routes
|
||||
[_ {:keys [session pool executor] :as cfg}]
|
||||
["/dbg" {:middleware [[(:middleware session)]
|
||||
[with-authorization pool]
|
||||
[mw/with-promise-async executor]
|
||||
[mw/with-config cfg]]}
|
||||
["" {:handler index-handler}]
|
||||
["/health" {:handler health-handler}]
|
||||
["/changelog" {:handler changelog-handler}]
|
||||
;; ["/error-by-id/:id" {:handler error-handler}]
|
||||
["/error/:id" {:handler error-handler}]
|
||||
["/error" {:handler error-list-handler}]
|
||||
["/file/export" {:handler export-handler}]
|
||||
["/file/import" {:handler import-handler}]
|
||||
["/file/data" {:handler file-data-handler}]
|
||||
["/file/changes" {:handler file-changes-handler}]])
|
||||
[["/readyz" {:middleware [[mw/with-dispatch executor]
|
||||
[mw/with-config cfg]]
|
||||
:handler health-handler}]
|
||||
["/dbg" {:middleware [[(:middleware session)]
|
||||
[with-authorization pool]
|
||||
[mw/with-dispatch executor]
|
||||
[mw/with-config cfg]]}
|
||||
["" {:handler index-handler}]
|
||||
["/health" {:handler health-handler}]
|
||||
["/changelog" {:handler changelog-handler}]
|
||||
;; ["/error-by-id/:id" {:handler error-handler}]
|
||||
["/error/:id" {:handler error-handler}]
|
||||
["/error" {:handler error-list-handler}]
|
||||
["/file/export" {:handler export-handler}]
|
||||
["/file/import" {:handler import-handler}]
|
||||
["/file/data" {:handler file-data-handler}]
|
||||
["/file/changes" {:handler file-changes-handler}]]])
|
||||
|
|
|
@ -195,8 +195,9 @@
|
|||
{:name ::restrict-methods
|
||||
:compile compile-restrict-methods})
|
||||
|
||||
(def with-promise-async
|
||||
{:compile
|
||||
(def with-dispatch
|
||||
{:name ::with-dispatch
|
||||
:compile
|
||||
(fn [& _]
|
||||
(fn [handler executor]
|
||||
(fn [request respond raise]
|
||||
|
@ -206,7 +207,8 @@
|
|||
(p/catch raise)))))})
|
||||
|
||||
(def with-config
|
||||
{:compile
|
||||
{:name ::with-config
|
||||
:compile
|
||||
(fn [& _]
|
||||
(fn [handler config]
|
||||
(fn
|
||||
|
|
|
@ -230,13 +230,12 @@
|
|||
(handler request respond raise)
|
||||
|
||||
:else
|
||||
(let [request (-> request
|
||||
(assoc :profile-id (:profile-id session))
|
||||
(assoc :session-id (:id session)))
|
||||
respond (cond-> respond
|
||||
(renew-session? session)
|
||||
(wrap-respond session))]
|
||||
|
||||
(let [request (-> request
|
||||
(assoc :profile-id (:profile-id session))
|
||||
(assoc :session-id (:id session)))
|
||||
respond (cond-> respond
|
||||
(renew-session? session)
|
||||
(wrap-respond session))]
|
||||
(handler request respond raise))))))
|
||||
|
||||
(catch Throwable cause
|
||||
|
|
|
@ -317,9 +317,14 @@
|
|||
(unit)
|
||||
(scale value))))
|
||||
|
||||
(defn no-zeros
|
||||
"Remove zero values from either coordinate"
|
||||
[point]
|
||||
(-> point
|
||||
(update :x #(if (mth/almost-zero? %) 0.001 %))
|
||||
(update :y #(if (mth/almost-zero? %) 0.001 %))))
|
||||
|
||||
;; --- Debug
|
||||
|
||||
(defmethod pp/simple-dispatch Point [obj] (pr obj))
|
||||
|
||||
|
||||
|
|
|
@ -243,13 +243,20 @@
|
|||
|
||||
mk-undo-change
|
||||
(fn [change-set shape]
|
||||
(let [idx (or (cph/get-position-on-parent objects (:id shape)) 0)
|
||||
;; Different index if the movement was from top to bottom or the other way
|
||||
;; Similar that on frontend/src/app/main/ui/workspace/sidebar/layers.cljs
|
||||
;; with the 'side' property of the on-drop
|
||||
idx (if (< index idx)
|
||||
(inc idx)
|
||||
idx)]
|
||||
(d/preconj
|
||||
change-set
|
||||
{:type :mov-objects
|
||||
:page-id (::page-id (meta changes))
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [(:id shape)]
|
||||
:index (cph/get-position-on-parent objects (:id shape))}))]
|
||||
:index idx})))]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj set-parent-change)
|
||||
|
|
|
@ -287,6 +287,26 @@
|
|||
(d/seek #(and position (gsh/has-point? (get objects %) position))))]
|
||||
(or top-frame uuid/zero)))
|
||||
|
||||
(defn all-frames-by-position
|
||||
[objects position]
|
||||
(->> (get-frames-ids objects)
|
||||
(sort-z-index objects)
|
||||
(filterv #(and position (gsh/has-point? (get objects %) position)))))
|
||||
|
||||
(defn top-nested-frame
|
||||
"Search for the top nested frame for positioning shapes when moving or creating.
|
||||
Looks for all the frames in a position and then goes in depth between the top-most and its
|
||||
children to find the target."
|
||||
[objects position]
|
||||
(let [frame-ids (all-frames-by-position objects position)
|
||||
frame-set (set frame-ids)]
|
||||
(loop [current-id (first frame-ids)]
|
||||
(let [current-shape (get objects current-id)
|
||||
child-frame-id (d/seek #(contains? frame-set %) (-> (:shapes current-shape) reverse))]
|
||||
(if (nil? child-frame-id)
|
||||
(or current-id uuid/zero)
|
||||
(recur child-frame-id))))))
|
||||
|
||||
(defn frame-by-position
|
||||
[objects position]
|
||||
(let [frame-id (frame-id-by-position objects position)]
|
||||
|
|
|
@ -124,6 +124,16 @@
|
|||
(let [token (.get ^js cookies cookie-name)]
|
||||
(handler (cond-> exchange token (assoc :request/auth-token token))))))
|
||||
|
||||
(defn- wrap-health
|
||||
"Add /healthz entry point intercept."
|
||||
[handler]
|
||||
(fn [{:keys [:request/path] :as exchange}]
|
||||
(if (= path "/readyz")
|
||||
(assoc exchange
|
||||
:response/status 200
|
||||
:response/body "OK")
|
||||
(handler exchange))))
|
||||
|
||||
(defn- create-adapter
|
||||
[handler]
|
||||
(fn [req res]
|
||||
|
@ -149,6 +159,7 @@
|
|||
(defn init
|
||||
[]
|
||||
(let [handler (-> handlers/handler
|
||||
(wrap-health)
|
||||
(wrap-auth "auth-token")
|
||||
(wrap-response-format)
|
||||
(wrap-params)
|
||||
|
|
|
@ -171,6 +171,20 @@
|
|||
}
|
||||
|
||||
.viewport-container {
|
||||
clip-path: inset(0 0 0 0);
|
||||
grid-column: 1 / 1;
|
||||
grid-row: 1 / 1;
|
||||
|
||||
.not-fixed {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
|
||||
.frame-children g {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,6 +274,11 @@
|
|||
|
||||
(def select-prev-frame
|
||||
(ptk/reify ::select-prev-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(dissoc :viewer-animations)
|
||||
(assoc :viewer-overlays [])))
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [route (:route state)
|
||||
|
@ -287,6 +292,11 @@
|
|||
|
||||
(def select-next-frame
|
||||
(ptk/reify ::select-next-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(dissoc :viewer-animations)
|
||||
(assoc :viewer-overlays [])))
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [route (:route state)
|
||||
|
@ -371,7 +381,7 @@
|
|||
(ptk/reify ::complete-animation
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(dissoc state :viewer-animation))))
|
||||
(dissoc state :viewer-animations))))
|
||||
|
||||
;; --- Navigation inside page
|
||||
|
||||
|
@ -412,7 +422,7 @@
|
|||
(assoc :viewer-overlays [])
|
||||
|
||||
(some? animation)
|
||||
(assoc :viewer-animation
|
||||
(assoc-in [:viewer-animations (:id frame)]
|
||||
{:kind :go-to-frame
|
||||
:orig-frame-id (:id frame)
|
||||
:animation animation}))))
|
||||
|
@ -465,13 +475,14 @@
|
|||
:id (:id frame)
|
||||
:position position
|
||||
:close-click-outside close-click-outside
|
||||
:background-overlay background-overlay})
|
||||
:background-overlay background-overlay
|
||||
:animation animation})
|
||||
|
||||
(some? animation)
|
||||
(assoc :viewer-animation
|
||||
{:kind :open-overlay
|
||||
:overlay-id (:id frame)
|
||||
:animation animation})))
|
||||
(assoc-in [:viewer-animations (:id frame)]
|
||||
{:kind :open-overlay
|
||||
:overlay-id (:id frame)
|
||||
:animation animation})))
|
||||
|
||||
(defn- close-overlay*
|
||||
[state frame-id animation]
|
||||
|
@ -479,10 +490,10 @@
|
|||
(update state :viewer-overlays
|
||||
(fn [overlays]
|
||||
(d/removev #(= (:id (:frame %)) frame-id) overlays)))
|
||||
(assoc state :viewer-animation
|
||||
{:kind :close-overlay
|
||||
:overlay-id frame-id
|
||||
:animation animation})))
|
||||
(assoc-in state [:viewer-animations frame-id]
|
||||
{:kind :close-overlay
|
||||
:overlay-id frame-id
|
||||
:animation animation})))
|
||||
|
||||
(defn open-overlay
|
||||
[frame-id position close-click-outside background-overlay animation]
|
||||
|
|
|
@ -1344,7 +1344,7 @@
|
|||
[frame-id frame-id delta])
|
||||
|
||||
(empty? page-selected)
|
||||
(let [frame-id (cph/frame-id-by-position page-objects mouse-pos)
|
||||
(let [frame-id (cph/top-nested-frame page-objects mouse-pos)
|
||||
delta (gpt/subtract mouse-pos orig-pos)]
|
||||
[frame-id frame-id delta])
|
||||
|
||||
|
@ -1456,7 +1456,7 @@
|
|||
height 16
|
||||
page-id (:current-page-id state)
|
||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||
(cph/frame-id-by-position @ms/mouse-position))
|
||||
(cph/top-nested-frame @ms/mouse-position))
|
||||
shape (cp/setup-rect-selrect
|
||||
{:id id
|
||||
:type :text
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
focus (:workspace-focus-selected state)
|
||||
zoom (get-in state [:workspace-local :zoom] 1)
|
||||
|
||||
fid (cph/frame-id-by-position objects initial)
|
||||
fid (cph/top-nested-frame objects initial)
|
||||
|
||||
shape (get-in state [:workspace-drawing :object])
|
||||
shape (-> shape
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (get-in content [0 :params] nil)
|
||||
frame-id (cph/frame-id-by-position objects position)]
|
||||
frame-id (cph/top-nested-frame objects position)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
|
||||
|
||||
|
|
|
@ -154,18 +154,24 @@
|
|||
is-group? #(or (= :bool (:type %)) (= :group (:type %)))
|
||||
lookup #(get objects %)
|
||||
prepare #(prepare-remove-group it page-id % objects)
|
||||
selected (wsh/lookup-selected state)
|
||||
children (into (d/ordered-set)
|
||||
(mapcat #(->> %
|
||||
lookup
|
||||
:shapes) selected))
|
||||
|
||||
changes-list (sequence
|
||||
(comp (map lookup)
|
||||
(filter is-group?)
|
||||
(map prepare))
|
||||
(wsh/lookup-selected state))
|
||||
(comp (map lookup)
|
||||
(filter is-group?)
|
||||
(map prepare))
|
||||
selected)
|
||||
|
||||
changes {:redo-changes (vec (mapcat :redo-changes changes-list))
|
||||
:undo-changes (vec (mapcat :undo-changes changes-list))
|
||||
:origin it}]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dws/select-shapes children))))))
|
||||
|
||||
(def mask-group
|
||||
(ptk/reify ::mask-group
|
||||
|
|
|
@ -87,6 +87,15 @@
|
|||
(update [_ state]
|
||||
(assoc-in state [:workspace-global :assets-files-open file-id :groups box path] open?))))
|
||||
|
||||
(defn extract-path-if-missing
|
||||
[item]
|
||||
(let [[path name] (cph/parse-path-name (:name item))]
|
||||
(if (and
|
||||
(= (:name item) name)
|
||||
(contains? item :path))
|
||||
item
|
||||
(assoc item :path path :name name))))
|
||||
|
||||
(defn default-color-name [color]
|
||||
(or (:color color)
|
||||
(case (get-in color [:gradient :type])
|
||||
|
@ -235,8 +244,7 @@
|
|||
(defn- do-update-tipography
|
||||
[it state typography file-id]
|
||||
(let [data (get state :workspace-data)
|
||||
[path name] (cph/parse-path-name (:name typography))
|
||||
typography (assoc typography :path path :name name)
|
||||
typography (extract-path-if-missing typography)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-typography typography))]
|
||||
|
|
|
@ -146,7 +146,7 @@
|
|||
objects (:objects page)
|
||||
unames (volatile! (un/retrieve-used-names objects))
|
||||
|
||||
frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta))
|
||||
frame-id (cph/top-nested-frame objects (gpt/add orig-pos delta))
|
||||
|
||||
update-new-shape
|
||||
(fn [new-shape original-shape]
|
||||
|
|
|
@ -258,7 +258,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (get-in content [0 :params] nil)
|
||||
frame-id (cph/frame-id-by-position objects position)]
|
||||
frame-id (cph/top-nested-frame objects position)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
;; Calculate the frame over which we're drawing
|
||||
(let [position @ms/mouse-position
|
||||
frame-id (:frame-id attrs (cph/frame-id-by-position objects position))
|
||||
frame-id (:frame-id attrs (cph/top-nested-frame objects position))
|
||||
shape (when-not (empty? selected)
|
||||
(cph/get-base-shape objects selected))]
|
||||
|
||||
|
@ -252,7 +252,6 @@
|
|||
(ptk/reify ::create-and-add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(prn ">>>create-")
|
||||
(let [{:keys [width height]} data
|
||||
|
||||
[vbc-x vbc-y] (viewport-center state)
|
||||
|
@ -260,7 +259,7 @@
|
|||
y (:y data (- vbc-y (/ height 2)))
|
||||
page-id (:current-page-id state)
|
||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||
(cph/frame-id-by-position {:x frame-x :y frame-y}))
|
||||
(cph/top-nested-frame {:x frame-x :y frame-y}))
|
||||
shape (-> (cp/make-minimal-shape type)
|
||||
(merge data)
|
||||
(merge {:x x :y y})
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
:subsections [:edit]
|
||||
:fn #(st/emit! dwc/redo)}
|
||||
|
||||
:clear-undo {:tooltip (ds/meta "Q")
|
||||
:command (ds/c-mod "q")
|
||||
:clear-undo {:tooltip (ds/alt "Z")
|
||||
:command "alt+z"
|
||||
:subsections [:edit]
|
||||
:fn #(st/emit! dwu/reinitialize-undo)}
|
||||
|
||||
|
|
|
@ -437,7 +437,7 @@
|
|||
(try
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (cph/frame-id-by-position objects position)
|
||||
frame-id (cph/top-nested-frame objects position)
|
||||
selected (wsh/lookup-selected state)
|
||||
|
||||
[vb-x vb-y vb-width vb-height] (svg-dimensions svg-data)
|
||||
|
|
|
@ -463,7 +463,8 @@
|
|||
(gpt/multiply handler-mult))
|
||||
|
||||
;; Resize vector
|
||||
scalev (gpt/divide (gpt/add shapev deltav) shapev)
|
||||
scalev (-> (gpt/divide (gpt/add shapev deltav) shapev)
|
||||
(gpt/no-zeros))
|
||||
|
||||
scalev (if lock?
|
||||
(let [v (cond
|
||||
|
@ -863,7 +864,7 @@
|
|||
(let [position @ms/mouse-position
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (cph/frame-id-by-position objects position)
|
||||
frame-id (cph/top-nested-frame objects position)
|
||||
|
||||
moving-shapes
|
||||
(->> ids
|
||||
|
@ -877,15 +878,17 @@
|
|||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/update-shapes moving-frames (fn [shape]
|
||||
;; Hide in viwer must be enabled just when a board is moved inside another artboard an nested to it, we have to avoid situations like:
|
||||
;; - Moving inside the same frame
|
||||
;; - Moving outside the frame
|
||||
(cond-> shape
|
||||
(and (not= frame-id (:id shape))
|
||||
(not= frame-id (:frame-id shape))
|
||||
(not= frame-id uuid/zero))
|
||||
(assoc :hide-in-viewer true))))
|
||||
(pcb/update-shapes
|
||||
moving-frames
|
||||
(fn [shape]
|
||||
;; Hide in viwer must be enabled just when a board is moved inside another artboard an nested to it, we have to avoid situations like:
|
||||
;; - Moving inside the same frame
|
||||
;; - Moving outside the frame
|
||||
(cond-> shape
|
||||
(and (not= frame-id (:id shape))
|
||||
(not= frame-id (:frame-id shape))
|
||||
(not= frame-id uuid/zero))
|
||||
(assoc :hide-in-viewer true))))
|
||||
(pcb/change-parent frame-id moving-shapes))]
|
||||
|
||||
(when-not (empty? changes)
|
||||
|
|
|
@ -42,21 +42,13 @@
|
|||
(if masked-group?
|
||||
["g" (-> (obj/create)
|
||||
(obj/set! "mask" (mask-url render-id mask)))]
|
||||
[mf/Fragment nil])
|
||||
|
||||
;; This factory is generic, it's used for viewer, workspace and handoff.
|
||||
;; These props are generated in viewer wrappers only, in the rest of the
|
||||
;; cases these props will be nil, not affecting the code.
|
||||
delta (unchecked-get props "delta")
|
||||
fixed? (unchecked-get props "fixed?")]
|
||||
[mf/Fragment nil])]
|
||||
|
||||
[:> clip-wrapper clip-props
|
||||
[:> mask-wrapper mask-props
|
||||
(when masked-group?
|
||||
[:> render-mask #js {:mask mask
|
||||
:objects objects
|
||||
:delta delta
|
||||
:fixed? fixed?}])
|
||||
:objects objects}])
|
||||
|
||||
(for [item childs]
|
||||
[:& shape-wrapper {:shape item
|
||||
|
|
|
@ -50,13 +50,7 @@
|
|||
render-id (mf/use-ctx muc/render-id)
|
||||
svg-text? (and (= :text (:type mask)) (some? (:position-data mask)))
|
||||
|
||||
;; This factory is generic, it's used for viewer, workspace and handoff.
|
||||
;; These props are generated in viewer wrappers only, in the rest of the
|
||||
;; cases these props will be nil, not affecting the code.
|
||||
fixed? (unchecked-get props "fixed?")
|
||||
delta (unchecked-get props "delta")
|
||||
mask-bb (-> (gsh/transform-shape mask)
|
||||
(cond-> fixed? (gsh/move delta))
|
||||
(:points))
|
||||
|
||||
mask-bb-rect (gsh/points->rect mask-bb)]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.geom.shapes.bounds :as gsb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.viewer :as dv]
|
||||
[app.main.data.viewer.shortcuts :as sc]
|
||||
|
@ -41,8 +42,8 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(def current-animation-ref
|
||||
(l/derived :viewer-animation st/state))
|
||||
(def current-animations-ref
|
||||
(l/derived :viewer-animations st/state))
|
||||
|
||||
(def current-overlays-ref
|
||||
(l/derived :viewer-overlays st/state))
|
||||
|
@ -101,7 +102,7 @@
|
|||
:page page}])]))
|
||||
|
||||
(mf/defc viewer-overlay
|
||||
[{:keys [overlay page frame zoom wrapper-size close-overlay interactions-mode]}]
|
||||
[{:keys [overlay page frame zoom wrapper-size interactions-mode]}]
|
||||
(let [close-click-outside? (:close-click-outside overlay)
|
||||
background-overlay? (:background-overlay overlay)
|
||||
overlay-frame (:frame overlay)
|
||||
|
@ -113,10 +114,12 @@
|
|||
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps overlay close-overlay close-click-outside?)
|
||||
(mf/deps overlay close-click-outside?)
|
||||
(fn [_]
|
||||
(when close-click-outside?
|
||||
(close-overlay (:frame overlay)))))]
|
||||
(if-let [animation (:animation overlay)]
|
||||
(st/emit! (dv/close-overlay (:id overlay) (ctsi/invert-direction animation)))
|
||||
(st/emit! (dv/close-overlay (:id overlay)))))))]
|
||||
|
||||
[:*
|
||||
(when (or close-click-outside? background-overlay?)
|
||||
|
@ -147,7 +150,7 @@
|
|||
|
||||
(mf/defc viewer-wrapper
|
||||
[{:keys [wrapper-size orig-frame orig-viewport-ref orig-size page file users current-viewport-ref
|
||||
size frame interactions-mode overlays zoom close-overlay section index] :as props}]
|
||||
size frame interactions-mode overlays zoom section index] :as props}]
|
||||
[:*
|
||||
[:& viewer-pagination-and-sidebar
|
||||
{:section section
|
||||
|
@ -197,10 +200,7 @@
|
|||
:frame frame
|
||||
:zoom zoom
|
||||
:wrapper-size wrapper-size
|
||||
:close-overlay close-overlay
|
||||
:interactions-mode interactions-mode}])
|
||||
|
||||
]]
|
||||
:interactions-mode interactions-mode}])]]
|
||||
|
||||
|
||||
(when (= section :comments)
|
||||
|
@ -234,7 +234,7 @@
|
|||
current-viewport-ref (mf/use-ref nil)
|
||||
viewer-section-ref (mf/use-ref nil)
|
||||
|
||||
current-animation (mf/deref current-animation-ref)
|
||||
current-animations (mf/deref current-animations-ref)
|
||||
|
||||
page-id (or page-id (-> file :data :pages first))
|
||||
|
||||
|
@ -255,11 +255,15 @@
|
|||
|
||||
fullscreen? (mf/deref header/fullscreen-ref)
|
||||
overlays (mf/deref current-overlays-ref)
|
||||
scroll (mf/use-state nil)
|
||||
|
||||
orig-frame
|
||||
(when (:orig-frame-id current-animation)
|
||||
(d/seek #(= (:id %) (:orig-frame-id current-animation)) frames))
|
||||
(mf/with-memo [current-animations]
|
||||
;; We assume there can only be one animation with origin (this is used only in
|
||||
;; navigation animations, and we cannot navigate to two different destinations
|
||||
;; at the same time).
|
||||
(let [animation-with-origin (d/seek :orig-frame-id (vals current-animations))]
|
||||
(when animation-with-origin
|
||||
(d/seek #(= (:id %) (:orig-frame-id animation-with-origin)) frames))))
|
||||
|
||||
size
|
||||
(mf/with-memo [frame zoom]
|
||||
|
@ -304,11 +308,6 @@
|
|||
size (dom/get-client-size viewer-section)]
|
||||
(st/emit! (dv/set-viewport-size {:size size})))))
|
||||
|
||||
on-scroll
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(reset! scroll (dom/get-target-scroll event))))
|
||||
|
||||
on-wheel
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
|
@ -349,12 +348,10 @@
|
|||
(mf/with-effect []
|
||||
(dom/set-html-theme-color clr/gray-50 "dark")
|
||||
(let [key1 (events/listen js/window "click" on-click)
|
||||
key2 (events/listen (mf/ref-val viewer-section-ref) "scroll" on-scroll #js {"passive" true})
|
||||
key3 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
|
||||
key2 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
|
||||
(fn []
|
||||
(events/unlistenByKey key1)
|
||||
(events/unlistenByKey key2)
|
||||
(events/unlistenByKey key3))))
|
||||
(events/unlistenByKey key2))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
|
@ -384,59 +381,59 @@
|
|||
(wapi/exit-fullscreen))))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps index)
|
||||
(mf/deps index current-animations)
|
||||
(fn []
|
||||
;; Navigate animation needs to be started after navigation
|
||||
;; is complete, and we have the next page index.
|
||||
(when (and current-animation
|
||||
(= (:kind current-animation) :go-to-frame))
|
||||
(let [orig-viewport (mf/ref-val orig-viewport-ref)
|
||||
current-viewport (mf/ref-val current-viewport-ref)]
|
||||
(interactions/animate-go-to-frame
|
||||
(:animation current-animation)
|
||||
current-viewport
|
||||
orig-viewport
|
||||
size
|
||||
orig-size
|
||||
wrapper-size)))))
|
||||
(let [nav-animation (d/seek #(= (:kind %) :go-to-frame) (vals current-animations))]
|
||||
(when nav-animation
|
||||
(let [orig-viewport (mf/ref-val orig-viewport-ref)
|
||||
current-viewport (mf/ref-val current-viewport-ref)]
|
||||
(interactions/animate-go-to-frame
|
||||
(:animation nav-animation)
|
||||
current-viewport
|
||||
orig-viewport
|
||||
size
|
||||
orig-size
|
||||
wrapper-size))))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps current-animation)
|
||||
(mf/deps current-animations)
|
||||
(fn []
|
||||
;; Overlay animations may be started when needed.
|
||||
(when current-animation
|
||||
(case (:kind current-animation)
|
||||
|
||||
:open-overlay
|
||||
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
||||
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
||||
overlays)
|
||||
overlay-size (calculate-size (:objects page) (:frame overlay) zoom)
|
||||
(when current-animations
|
||||
(doseq [[overlay-frame-id animation-vals] current-animations]
|
||||
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id animation-vals))))
|
||||
overlay (d/seek #(= (:id (:frame %)) overlay-frame-id)
|
||||
overlays)
|
||||
overlay-size (calculate-size (:objects page) (:frame overlay) zoom)
|
||||
overlay-position {:x (* (:x (:position overlay)) zoom)
|
||||
:y (* (:y (:position overlay)) zoom)}]
|
||||
(interactions/animate-open-overlay
|
||||
(:animation current-animation)
|
||||
overlay-viewport
|
||||
wrapper-size
|
||||
overlay-size
|
||||
overlay-position))
|
||||
:y (* (:y (:position overlay)) zoom)}
|
||||
orig-frame (when (:orig-frame-id animation-vals)
|
||||
(d/seek #(= (:id %) (:orig-frame-id animation-vals)) frames))
|
||||
size (calculate-size (:objects page) frame zoom)
|
||||
orig-size (when orig-frame
|
||||
(calculate-size (:objects page) orig-frame zoom))
|
||||
wrapper-size (calculate-wrapper size orig-size zoom)]
|
||||
(case (:kind animation-vals)
|
||||
:open-overlay
|
||||
(interactions/animate-open-overlay
|
||||
(:animation animation-vals)
|
||||
overlay-viewport
|
||||
wrapper-size
|
||||
overlay-size
|
||||
overlay-position)
|
||||
|
||||
:close-overlay
|
||||
(let [overlay-viewport (dom/get-element (str "overlay-" (str (:overlay-id current-animation))))
|
||||
overlay (d/seek #(= (:id (:frame %)) (:overlay-id current-animation))
|
||||
overlays)
|
||||
overlay-size (calculate-size (:objects page) (:frame overlay) zoom)
|
||||
overlay-position {:x (* (:x (:position overlay)) zoom)
|
||||
:y (* (:y (:position overlay)) zoom)}]
|
||||
(interactions/animate-close-overlay
|
||||
(:animation current-animation)
|
||||
overlay-viewport
|
||||
wrapper-size
|
||||
overlay-size
|
||||
overlay-position
|
||||
(:id (:frame overlay))))
|
||||
:close-overlay
|
||||
(interactions/animate-close-overlay
|
||||
(:animation animation-vals)
|
||||
overlay-viewport
|
||||
wrapper-size
|
||||
overlay-size
|
||||
overlay-position
|
||||
(:id (:frame overlay)))
|
||||
|
||||
nil))))
|
||||
nil))))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps text-shapes)
|
||||
|
@ -494,24 +491,24 @@
|
|||
:index index
|
||||
:viewer-pagination viewer-pagination}]
|
||||
|
||||
[:& (mf/provider ctx/current-scroll) {:value @scroll}
|
||||
[:& (mf/provider ctx/current-zoom) {:value zoom}
|
||||
[:& viewer-wrapper
|
||||
{:wrapper-size wrapper-size
|
||||
:orig-frame orig-frame
|
||||
:orig-viewport-ref orig-viewport-ref
|
||||
:orig-size orig-size
|
||||
:page page
|
||||
:file file
|
||||
:users users
|
||||
:current-viewport-ref current-viewport-ref
|
||||
:size size
|
||||
:frame frame
|
||||
:interactions-mode interactions-mode
|
||||
:overlays overlays
|
||||
:zoom zoom
|
||||
:section section
|
||||
:index index}]]]))]]]))
|
||||
|
||||
[:& (mf/provider ctx/current-zoom) {:value zoom}
|
||||
[:& viewer-wrapper
|
||||
{:wrapper-size wrapper-size
|
||||
:orig-frame orig-frame
|
||||
:orig-viewport-ref orig-viewport-ref
|
||||
:orig-size orig-size
|
||||
:page page
|
||||
:file file
|
||||
:users users
|
||||
:current-viewport-ref current-viewport-ref
|
||||
:size size
|
||||
:frame frame
|
||||
:interactions-mode interactions-mode
|
||||
:overlays overlays
|
||||
:zoom zoom
|
||||
:section section
|
||||
:index index}]]))]]]))
|
||||
|
||||
;; --- Component: Viewer Page
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
(mf/defc render-frame-svg
|
||||
[{:keys [page frame local size]}]
|
||||
(let [objects (mf/with-memo [page frame size]
|
||||
(prepare-objects page frame size))
|
||||
(prepare-objects frame size (:objects page)))
|
||||
|
||||
;; Retrieve frame again with correct modifier
|
||||
frame (get objects (:id frame))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.viewer :as dv]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -27,8 +28,8 @@
|
|||
[rumext.alpha :as mf]))
|
||||
|
||||
(defn prepare-objects
|
||||
[page frame size]
|
||||
(let [objects (:objects page)
|
||||
[frame size objects]
|
||||
(let [
|
||||
frame-id (:id frame)
|
||||
modifier (-> (gpt/point (:x size) (:y size))
|
||||
(gpt/negate)
|
||||
|
@ -52,26 +53,60 @@
|
|||
|
||||
vbox (:vbox size)
|
||||
|
||||
objects (mf/with-memo [page frame size]
|
||||
(prepare-objects page frame size))
|
||||
fixed-ids (filter :fixed-scroll (vals (:objects page)))
|
||||
|
||||
wrapper (mf/with-memo [objects]
|
||||
(shapes/frame-container-factory objects))
|
||||
;; we have con consider the children if the fixed element is a group
|
||||
fixed-children-ids (into #{} (mapcat #(cph/get-children-ids (:objects page) (:id %)) fixed-ids))
|
||||
|
||||
parent-children-ids (->> fixed-ids
|
||||
(mapcat #(cons (:id %) (cph/get-parent-ids (:objects page) (:id %))))
|
||||
(remove #(= % uuid/zero)))
|
||||
|
||||
fixed-ids (concat fixed-children-ids parent-children-ids)
|
||||
|
||||
not-fixed-ids (->> (remove (set fixed-ids) (keys (:objects page)))
|
||||
(remove #(= % uuid/zero)))
|
||||
|
||||
calculate-objects (fn [ids] (->> ids
|
||||
(map (d/getf (:objects page)))
|
||||
(concat [frame])
|
||||
(d/index-by :id)
|
||||
(prepare-objects frame size)))
|
||||
|
||||
wrapper-fixed (mf/with-memo [page frame size]
|
||||
(shapes/frame-container-factory (calculate-objects fixed-ids)))
|
||||
|
||||
objects-not-fixed (mf/with-memo [page frame size]
|
||||
(calculate-objects not-fixed-ids))
|
||||
|
||||
wrapper-not-fixed (mf/with-memo [objects-not-fixed]
|
||||
(shapes/frame-container-factory objects-not-fixed))
|
||||
|
||||
;; Retrieve frames again with correct modifier
|
||||
frame (get objects (:id frame))
|
||||
base (get objects (:id base))]
|
||||
frame (get objects-not-fixed (:id frame))
|
||||
base (get objects-not-fixed (:id base))]
|
||||
|
||||
[:& (mf/provider shapes/base-frame-ctx) {:value base}
|
||||
[:& (mf/provider shapes/frame-offset-ctx) {:value offset}
|
||||
[:svg {:view-box vbox
|
||||
:width (:width size)
|
||||
:height (:height size)
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:fill "none"}
|
||||
[:& wrapper {:shape frame :view-box vbox}]]]]))
|
||||
;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg
|
||||
[:svg.not-fixed {:view-box vbox
|
||||
:width (:width size)
|
||||
:height (:height size)
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:fill "none"}
|
||||
[:& wrapper-not-fixed {:shape frame :view-box vbox}]]
|
||||
[:svg.fixed {:view-box vbox
|
||||
:width (:width size)
|
||||
:height (:height size)
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:fill "none"
|
||||
:style {:width (:width size)
|
||||
:height (:height size)}}
|
||||
[:& wrapper-fixed {:shape (dissoc frame :fills) :view-box vbox}]]]]))
|
||||
|
||||
(mf/defc viewport
|
||||
{::mf/wrap [mf/memo]
|
||||
|
|
|
@ -7,14 +7,12 @@
|
|||
(ns app.main.ui.viewer.shapes
|
||||
"The main container for a frame in viewer mode"
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.main.data.viewer :as dv]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.shapes.bool :as bool]
|
||||
[app.main.ui.shapes.circle :as circle]
|
||||
[app.main.ui.shapes.frame :as frame]
|
||||
|
@ -69,7 +67,11 @@
|
|||
|
||||
:toggle-overlay
|
||||
(let [frame-id (:destination interaction)
|
||||
position (:overlay-position interaction)
|
||||
dest-frame (get objects frame-id)
|
||||
position (ctsi/calc-overlay-position interaction
|
||||
base-frame
|
||||
dest-frame
|
||||
frame-offset)
|
||||
close-click-outside (:close-click-outside interaction)
|
||||
background-overlay (:background-overlay interaction)]
|
||||
(when frame-id
|
||||
|
@ -219,8 +221,6 @@
|
|||
childs (unchecked-get props "childs")
|
||||
frame (unchecked-get props "frame")
|
||||
objects (unchecked-get props "objects")
|
||||
fixed? (unchecked-get props "fixed?")
|
||||
delta (unchecked-get props "delta")
|
||||
base-frame (mf/use-ctx base-frame-ctx)
|
||||
frame-offset (mf/use-ctx frame-offset-ctx)
|
||||
|
||||
|
@ -265,9 +265,7 @@
|
|||
:frame frame
|
||||
:childs childs
|
||||
:is-child-selected? true
|
||||
:objects objects
|
||||
:fixed? fixed?
|
||||
:delta delta}]
|
||||
:objects objects}]
|
||||
|
||||
[:& interaction {:shape shape
|
||||
:interactions interactions
|
||||
|
@ -389,20 +387,6 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
frame (unchecked-get props "frame")
|
||||
|
||||
;; TODO: this watch of scroll position is killing
|
||||
;; performance of the viewer.
|
||||
scroll (mf/use-ctx ctx/current-scroll)
|
||||
zoom (mf/use-ctx ctx/current-zoom)
|
||||
|
||||
fixed? (mf/with-memo [shape objects]
|
||||
(->> (cph/get-parent-ids objects (:id shape))
|
||||
(map (d/getf objects))
|
||||
(concat [shape])
|
||||
(some :fixed-scroll)))
|
||||
|
||||
delta {:x (/ (:scroll-left scroll) zoom)
|
||||
:y (/ (:scroll-top scroll) zoom)}
|
||||
|
||||
group-container
|
||||
(mf/with-memo [objects]
|
||||
(group-container-factory objects))
|
||||
|
@ -422,8 +406,7 @@
|
|||
]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(let [shape (-> (gsh/transform-shape shape)
|
||||
(gsh/translate-to-frame frame)
|
||||
(cond-> fixed? (gsh/move delta)))
|
||||
(gsh/translate-to-frame frame))
|
||||
|
||||
opts #js {:shape shape
|
||||
:objects objects}]
|
||||
|
@ -434,6 +417,6 @@
|
|||
:path [:> path-wrapper opts]
|
||||
:image [:> image-wrapper opts]
|
||||
:circle [:> circle-wrapper opts]
|
||||
:group [:> group-container {:shape shape :frame frame :objects objects :fixed? fixed? :delta delta}]
|
||||
:group [:> group-container {:shape shape :frame frame :objects objects}]
|
||||
:bool [:> bool-container {:shape shape :frame frame :objects objects}]
|
||||
:svg-raw [:> svg-raw-container {:shape shape :frame frame :objects objects}])))))))
|
||||
|
|
|
@ -891,18 +891,8 @@
|
|||
multi-assets? (or (seq (:components selected-assets))
|
||||
(seq (:colors selected-assets))
|
||||
(seq (:typographies selected-assets)))
|
||||
|
||||
extract-path-if-missing
|
||||
(fn [graphic]
|
||||
(let [[path name] (cph/parse-path-name (:name graphic))]
|
||||
(if (and
|
||||
(= (:name graphic) name)
|
||||
(contains? graphic :path))
|
||||
graphic
|
||||
(assoc graphic :path path :name name))))
|
||||
|
||||
objects (->> objects
|
||||
(map extract-path-if-missing))
|
||||
(map dwl/extract-path-if-missing))
|
||||
|
||||
|
||||
groups (group-assets objects reverse-sort?)
|
||||
|
@ -1633,18 +1623,8 @@
|
|||
|
||||
local-data (mf/deref typography-data)
|
||||
menu-state (mf/use-state auto-pos-menu-state)
|
||||
|
||||
extract-path-if-missing
|
||||
(fn [typography]
|
||||
(let [[path name] (cph/parse-path-name (:name typography))]
|
||||
(if (and
|
||||
(= (:name typography) name)
|
||||
(contains? typography :path))
|
||||
typography
|
||||
(assoc typography :path path :name name))))
|
||||
|
||||
typographies (->> typographies
|
||||
(map extract-path-if-missing))
|
||||
(map dwl/extract-path-if-missing))
|
||||
|
||||
groups (group-assets typographies reverse-sort?)
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
(defn get-grids-snap-points
|
||||
[frame coord]
|
||||
(if (not (cph/rotated-frame? frame))
|
||||
(if (cph/rotated-frame? frame)
|
||||
[]
|
||||
(let [grid->snap (fn [[grid-type position]]
|
||||
{:type :layout
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.15.3-beta
|
||||
1.15.4-beta
|
||||
|
|
Loading…
Add table
Reference in a new issue