0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-13 16:21:57 -05:00

Change column/row from cell options

This commit is contained in:
alonso.torres 2023-05-10 12:42:43 +02:00
parent f5bb6b05f3
commit 47e927d571
9 changed files with 316 additions and 240 deletions

View file

@ -128,13 +128,13 @@
(let [hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
;;make-is-inside-track
;;(fn [type]
;; (let [[vfn ofn] (if (= type :column) [vv hv] [hv vv])]
;; (fn is-inside-track? [{:keys [start-p size] :as track}]
;; (let [unit-v (vfn 1)
;; end-p (gpt/add start-p (ofn size))]
;; (is-inside-lines? [start-p unit-v] [end-p unit-v] position)))))
make-is-inside-track
(fn [type]
(let [[vfn ofn] (if (= type :column) [vv hv] [hv vv])]
(fn is-inside-track? [{:keys [start-p size] :as track}]
(let [unit-v (vfn 1)
end-p (gpt/add start-p (ofn size))]
(is-inside-lines? [start-p unit-v] [end-p unit-v] position)))))
make-min-distance-track
(fn [type]
@ -149,25 +149,29 @@
[[cur-idx track] (min dist-1 dist-2)]
[selected selected-dist])))))
;;[col-idx column]
;;(->> (d/enumerate column-tracks)
;; (d/seek (comp (make-is-inside-track :column) second)))
;;
;;[row-idx row]
;;(->> (d/enumerate row-tracks)
;; (d/seek (comp (make-is-inside-track :row) second)))
;; Check if it's inside a track
[col-idx column]
(->> (d/enumerate column-tracks)
(reduce (make-min-distance-track :column) [[nil nil] ##Inf])
(first))
(d/seek (comp (make-is-inside-track :column) second)))
[row-idx row]
(->> (d/enumerate row-tracks)
(reduce (make-min-distance-track :row) [[nil nil] ##Inf])
(first))
]
(d/seek (comp (make-is-inside-track :row) second)))
;; If not inside we find the closest start/end line
[col-idx column]
(if (some? column)
[col-idx column]
(->> (d/enumerate column-tracks)
(reduce (make-min-distance-track :column) [[nil nil] ##Inf])
(first)))
[row-idx row]
(if (some? row)
[row-idx row]
(->> (d/enumerate row-tracks)
(reduce (make-min-distance-track :row) [[nil nil] ##Inf])
(first)))]
(when (and (some? column) (some? row))
[(inc row-idx) (inc col-idx)])))

View file

@ -593,8 +593,7 @@
(assoc result id
(merge {:id id
:row (inc row-idx)
:column new-col-num
:track? true}
:column new-col-num}
grid-cell-defaults))))
(:layout-grid-cells parent)))]
(-> parent
@ -617,8 +616,7 @@
(assoc result id
(merge {:id id
:column (inc col-idx)
:row new-row-num
:track? true}
:row new-row-num}
grid-cell-defaults))))
(:layout-grid-cells parent)))]
(-> parent
@ -852,86 +850,98 @@
(first)))
parent)))
(defn create-cells
"Create cells in an area. One cell per row/column "
[parent [column row column-span row-span]]
(->> (for [row (range row (+ row row-span))
column (range column (+ column column-span))]
(merge grid-cell-defaults
{:id (uuid/next)
:row row
:column column
:row-span 1
:column-span 1}))
(reduce #(assoc-in %1 [:layout-grid-cells (:id %2)] %2) parent)))
(defn resize-cell-area
"Increases/decreases the cell size"
[parent row column new-row new-column new-row-span new-column-span]
(let [cells (vec (get-cells parent {:sort? true}))
(if (and (>= new-row 0)
(>= new-column 0)
(>= new-row-span 1)
(>= new-column-span 1))
(let [prev-cell (cell-by-row-column parent row column)
prev-area (sga/make-area prev-cell)
prev-cell (cell-by-row-column parent row column)
prev-area (sga/make-area prev-cell)
target-cell
(-> prev-cell
(assoc
:row new-row
:column new-column
:row-span new-row-span
:column-span new-column-span))
target-cell
(-> prev-cell
(assoc
:row new-row
:column new-column
:row-span new-row-span
:column-span new-column-span))
target-area (sga/make-area target-cell)
target-area (sga/make-area target-cell)]
;; Create columns/rows if necessary
parent
(->> (range (count (:layout-grid-columns parent))
(+ new-column new-column-span -1))
(reduce (fn [parent _] (add-grid-column parent default-track-value)) parent))
(if (sga/contains? prev-area target-area)
;; The new area is smaller than the previous. We need to create cells in the empty space
(let [parent
(-> parent
(assoc-in [:layout-grid-cells (:id target-cell)] target-cell))
parent
(->> (range (count (:layout-grid-rows parent))
(+ new-row new-row-span -1))
(reduce (fn [parent _] (add-grid-row parent default-track-value)) parent))
new-cells
(->> (sga/difference prev-area target-area)
(mapcat (fn [[column row column-span row-span]]
(for [new-col (range column (+ column column-span))
new-row (range row (+ row row-span))]
(merge grid-cell-defaults
{:id (uuid/next)
:row new-row
:column new-col
:row-span 1
:column-span 1})))))
parent (create-cells parent prev-area)
parent
(->> new-cells
(reduce #(assoc-in %1 [:layout-grid-cells (:id %2)] %2) parent))]
cells (vec (get-cells parent {:sort? true}))
remove-cells
(->> cells
(filter #(and (not= (:id target-cell) (:id %))
(sga/contains? target-area (sga/make-area %))))
(into #{}))
parent)
split-cells
(->> cells
(filter #(and (not= (:id target-cell) (:id %))
(not (contains? remove-cells %))
(sga/intersects? target-area (sga/make-area %)))))
;; The new area is bigger we need to remove the cells filled and split the intersections
(let [remove-cells (->> cells
(filter #(and (not= (:id target-cell) (:id %))
(sga/contains? target-area (sga/make-area %))))
(into #{}))
[parent _]
(->> (d/enumerate cells)
(reduce (fn [[parent cells] [index cur-cell]]
(if (contains? remove-cells cur-cell)
(let [[parent cells] (free-cell-push parent cells index)]
[parent (conj cells cur-cell)])
[parent cells]))
[parent cells]))
split-cells (->> cells (filter #(and (not= (:id target-cell) (:id %))
(not (contains? remove-cells %))
(sga/intersects? target-area (sga/make-area %)))))
parent
(-> parent
(assoc-in [:layout-grid-cells (:id target-cell)] target-cell))
[parent _]
(->> (d/enumerate cells)
(reduce (fn [[parent cells] [index cur-cell]]
(if (contains? remove-cells cur-cell)
(let [[parent cells] (free-cell-push parent cells index)]
[parent (conj cells cur-cell)])
[parent cells]))
[parent cells]))
parent
(->> remove-cells
(reduce (fn [parent cell]
(update parent :layout-grid-cells dissoc (:id cell)))
parent))
parent
(-> parent
(assoc-in [:layout-grid-cells (:id target-cell)] target-cell))
parent
(->> split-cells
(reduce (fn [parent cell]
(let [new-areas (sga/difference (sga/make-area cell) target-area)]
(as-> parent $
(update-in $ [:layout-grid-cells (:id cell)] merge (sga/area->cell-props (first new-areas)))
(reduce (fn [parent area]
(let [cell (merge (assoc grid-cell-defaults :id (uuid/next)) (sga/area->cell-props area))]
(assoc-in parent [:layout-grid-cells (:id cell)] cell))) $ new-areas))))
parent))]
parent)
parent
(->> remove-cells
(reduce (fn [parent cell]
(update parent :layout-grid-cells dissoc (:id cell)))
parent))
parent
(->> split-cells
(reduce (fn [parent cell]
(let [new-areas (sga/difference (sga/make-area cell) target-area)]
(as-> parent $
(update-in $ [:layout-grid-cells (:id cell)] merge (sga/area->cell-props (first new-areas)))
(reduce (fn [parent area]
(let [cell (merge (assoc grid-cell-defaults :id (uuid/next)) (sga/area->cell-props area))]
(assoc-in parent [:layout-grid-cells (:id cell)] cell))) $ new-areas))))
parent))]
parent))))
;; Not valid resize: we don't alter the layout
parent))

View file

@ -61,3 +61,4 @@
srect (gsh/make-selrect x y width height)]
(-> local
(update :vbox merge (select-keys srect [:x :y :x1 :x2 :y1 :y2])))))))))))

View file

@ -8,6 +8,7 @@
(:require
[app.common.colors :as clr]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
@ -52,13 +53,13 @@
:layout-padding-type :simple
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}})
(def initial-grid-layout ;; TODO
(def initial-grid-layout
{:layout :grid
:layout-grid-dir :row
:layout-gap-type :multiple
:layout-gap {:row-gap 0 :column-gap 0}
:layout-align-items :start
:layout-align-content :stretch
:layout-align-content :start
:layout-justify-items :start
:layout-justify-content :start
:layout-padding-type :simple
@ -549,3 +550,44 @@
(dwc/update-shapes parent-ids (partial fix-parent-sizing objects (set ids) changes))
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
(defn update-grid-cell
[layout-id cell-id props]
(ptk/reify ::update-grid-cell
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
(dwc/update-shapes
[layout-id]
(fn [shape]
(-> shape
(d/update-in-when [:layout-grid-cells cell-id]
#(d/without-nils (merge % props))))))
(ptk/data-event :layout/update [layout-id])
(dwu/commit-undo-transaction undo-id))))))
(defn update-grid-cell-position
[layout-id cell-id props]
(ptk/reify ::update-grid-cell-position
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
(dwc/update-shapes
[layout-id]
(fn [shape]
(let [prev-data (-> (dm/get-in shape [:layout-grid-cells cell-id])
(select-keys [:row :column :row-span :column-span]))
new-data (merge prev-data props)]
(-> shape
(ctl/resize-cell-area (:row prev-data) (:column prev-data)
(:row new-data) (:column new-data)
(:row-span new-data) (:column-span new-data))
(ctl/assign-cells)))))
(ptk/data-event :layout/update [layout-id])
(dwu/commit-undo-transaction undo-id))))))

View file

@ -151,7 +151,8 @@
(dom/class? node "frame-title")
(let [shape (gsh/transform-shape shape modifiers)
zoom (get-in @st/state [:workspace-local :zoom] 1)
mtx (vwu/title-transform shape zoom false)]
edit-grid? (= (dom/get-data node "edit-grid") "true")
mtx (vwu/title-transform shape zoom edit-grid?)]
(override-transform-att! node "transform" mtx))
(or (= (dom/get-tag-name node) "mask")

View file

@ -8,6 +8,8 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.menus.layout-container :as lyc]
@ -16,7 +18,8 @@
(mf/defc set-self-alignment
[{:keys [is-col? alignment set-alignment] :as props}]
(let [dir-v [:auto :start :center :end :stretch #_:baseline]]
(let [dir-v [:auto :start :center :end :stretch #_:baseline]
alignment (or alignment :auto)]
[:div.align-self-style
(for [align dir-v]
[:button.align-self.tooltip.tooltip-bottom
@ -31,51 +34,69 @@
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [_shape cell] :as props}]
[{:keys [shape cell] :as props}]
(let [position-mode (mf/use-state :auto) ;; TODO this should come from shape
(let [{:keys [mode area-name align-self justify-self column column-span row row-span]} cell
column-end (+ column column-span)
row-end (+ row row-span)
set-position-mode (fn [mode]
(reset! position-mode mode))
cell-mode (or mode :auto)
cell-mode (if (and (= :auto cell-mode)
(or (> (:column-span cell) 1)
(> (:row-span cell) 1)))
:manual
cell-mode)
set-alignment
(mf/use-callback
(mf/deps align-self (:id shape) (:id cell))
(fn [value]
(if (= align-self value)
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:align-self nil}))
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:align-self value})))))
align-self (mf/use-state :auto) ;; TODO this should come from shape
justify-alignment (mf/use-state :auto) ;; TODO this should come from shape
set-alignment (fn [value]
(reset! align-self value)
#_(if (= align-self value)
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil}))
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value}))))
set-justify-self (fn [value]
(reset! justify-alignment value)
#_(if (= align-self value)
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil}))
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value}))))
column-start (:column cell)
column-end (+ (:column cell) (:column-span cell))
row-start (:row cell)
row-end (+ (:row cell) (:row-span cell))
set-justify-self
(mf/use-callback
(mf/deps justify-self (:id shape) (:id cell))
(fn [value]
(if (= justify-self value)
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:justify-self nil}))
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:justify-self value})))))
on-change
(fn [_side _orientation _value]
;; TODO
#_(if (= orientation :column)
(case side
:all ((reset! column-start value)
(reset! column-end value))
:start (reset! column-start value)
:end (reset! column-end value))
(case side
:all ((reset! row-start value)
(reset! row-end value))
:start (reset! row-start value)
:end (reset! row-end value))))
(mf/use-callback
(mf/deps column row (:id shape) (:id cell))
(fn [field type value]
(let [[property value]
(cond
(and (= type :column) (or (= field :all) (= field :start)))
[:column value]
area-name (mf/use-state "header") ;; TODO this should come from shape
(and (= type :column) (= field :end))
[:column-span (max 1 (- value column))]
on-area-name-change (fn [value]
(reset! area-name value))
on-key-press (fn [_event])]
(and (= type :row) (or (= field :all) (= field :start)))
[:row value]
(and (= type :row) (= field :end))
[:row-span (max 1 (- value row))])]
(st/emit! (dwsl/update-grid-cell-position (:id shape) (:id cell) {property value})))))
on-area-name-change
(mf/use-callback
(mf/deps (:id shape) (:id cell))
(fn [event]
(let [value (dom/get-value (dom/get-target event))]
(if (= value "")
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:area-name nil}))
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:area-name value}))))))
set-cell-mode
(mf/use-callback
(mf/deps (:id shape) (:id cell))
(fn [mode]
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) {:mode mode}))))]
[:div.element-set
[:div.element-set-title
@ -86,16 +107,17 @@
[:div.row-title.sizing "Position"]
[:div.position-wrapper
[:button.position-btn
{:on-click #(set-position-mode :auto)
:class (dom/classnames :active (= :auto @position-mode))} "Auto"]
{:on-click #(set-cell-mode :auto)
:class (dom/classnames :active (= :auto cell-mode))} "Auto"]
[:button.position-btn
{:on-click #(set-position-mode :manual)
:class (dom/classnames :active (= :manual @position-mode))} "Manual"]
{:on-click #(set-cell-mode :manual)
:class (dom/classnames :active (= :manual cell-mode))} "Manual"]
[:button.position-btn
{:on-click #(set-position-mode :area)
:class (dom/classnames :active (= :area @position-mode))} "Area"]]]
{:on-click #(set-cell-mode :area)
:class (dom/classnames :active (= :area cell-mode))} "Area"]]]
[:div.manage-grid-columns
(when (= :auto @position-mode)
(when (= :auto cell-mode)
[:div.grid-auto
[:div.grid-columns-auto
[:span.icon i/layout-rows]
@ -103,42 +125,42 @@
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-change :all :column) ;; TODO cambiar este on-change y el value
:value column-start}]]]
:on-change (partial on-change :all :column)
:value column}]]]
[:div.grid-rows-auto
[:span.icon i/layout-columns]
[:div.input-wrapper
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-change :all :row) ;; TODO cambiar este on-change y el value
:value row-start}]]]])
(when (= :area @position-mode)
:on-change (partial on-change :all :row)
:value row}]]]])
(when (= :area cell-mode)
[:div.input-wrapper
[:input.input-text
{:key "grid-area-name"
{:key (dm/str "name-" (:id cell))
:id "grid-area-name"
:type "text"
:aria-label "grid-area-name"
:placeholder "--"
:default-value @area-name
:default-value area-name
:auto-complete "off"
:on-change on-area-name-change
:on-key-press on-key-press}]])
:on-change on-area-name-change}]])
(when (or (= :manual @position-mode) (= :area @position-mode))
(when (or (= :manual cell-mode) (= :area cell-mode))
[:div.grid-manual
[:div.grid-columns-auto
[:span.icon i/layout-rows]
[:div.input-wrapper
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-pointer-down #(dom/select-target %)
:on-change (partial on-change :start :column)
:value column-start}]
:value column}]
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-pointer-down #(dom/select-target %)
:on-change (partial on-change :end :column)
:value column-end}]]]
[:div.grid-rows-auto
@ -146,12 +168,12 @@
[:div.input-wrapper
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-pointer-down #(dom/select-target %)
:on-change (partial on-change :start :row)
:value row-start}]
:value row}]
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-pointer-down #(dom/select-target %)
:on-change (partial on-change :end :row)
:value row-end}]]]])]
@ -159,13 +181,11 @@
[:div.row-title "Align"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? false
:alignment @align-self
:alignment align-self
:set-alignment set-alignment}]]]
[:div.layout-row
[:div.row-title "Justify"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? true
:alignment @justify-alignment
:alignment justify-self
:set-alignment set-justify-self}]]]]]))

View file

@ -204,8 +204,7 @@
(>= zoom 8))
show-text-editor? (and editing-shape (= :text (:type editing-shape)))
;; Debug utility
;; hover-grid? (and (some? @hover-top-frame-id) (ctl/grid-layout? objects @hover-top-frame-id))
hover-grid? (and (some? @hover-top-frame-id) (ctl/grid-layout? objects @hover-top-frame-id))
show-grid-editor? (and editing-shape (ctl/grid-layout? editing-shape))
show-presence? page-id
@ -591,8 +590,7 @@
:zoom zoom}])
(when show-grid-editor?
#_(or show-grid-editor? hover-grid?) ;; Debug utility
(when (or show-grid-editor? hover-grid?)
[:& grid-layout/editor
{:zoom zoom
:objects objects-modified

View file

@ -572,7 +572,6 @@
:on-key-down handle-keydown-track-input
:on-blur handle-blur-track-input}]]]
[:& resize-track-handler
{:index index
:layout-data layout-data
@ -662,85 +661,85 @@
[:& plus-btn {:start-p start-p
:zoom zoom
:type :row
:on-click handle-add-row}])])
:on-click handle-add-row}])
(for [[idx column-data] (d/enumerate column-tracks)]
[:& track {:key (dm/str "column-track-" idx)
:shape shape
:zoom zoom
:type :column
:index idx
:layout-data layout-data
:snap-pixel? snap-pixel?
:track-data column-data}])
(for [[idx column-data] (d/enumerate column-tracks)]
[:& track {:key (dm/str "column-track-" idx)
:shape shape
:zoom zoom
:type :column
:index idx
:layout-data layout-data
:snap-pixel? snap-pixel?
:track-data column-data}])
;; Last track resize handler
(when-not (empty? column-tracks)
(let [last-track (last column-tracks)
start-p (:start-p (last column-tracks))
relative (gpt/to-vec origin start-p)
marker-p (-> origin
(gpt/add (hv (:x relative)))
(gpt/subtract (vv (/ 20 zoom)))
(gpt/add (hv (:size last-track))))]
[:g.track
[:& track-marker {:center marker-p
:index (count column-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last column-tracks)
:type :column
:value (dm/str (inc (count column-tracks)))
:zoom zoom}]
[:& resize-track-handler
{:index (count column-tracks)
:shape shape
:layout-data layout-data
:snap-pixel? snap-pixel?
:start-p (-> start-p (gpt/add (hv (+ layout-gap-col (:size last-track)))))
:type :column
:track-before (last column-tracks)
:zoom zoom}]]))
;; Last track resize handler
(when-not (empty? column-tracks)
(let [last-track (last column-tracks)
start-p (:start-p (last column-tracks))
relative (gpt/to-vec origin start-p)
marker-p (-> origin
(gpt/add (hv (:x relative)))
(gpt/subtract (vv (/ 20 zoom)))
(gpt/add (hv (:size last-track))))]
[:g.track
[:& track-marker {:center marker-p
:index (count column-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last column-tracks)
:type :column
:value (dm/str (inc (count column-tracks)))
:zoom zoom}]
[:& resize-track-handler
{:index (count column-tracks)
:shape shape
:layout-data layout-data
:snap-pixel? snap-pixel?
:start-p (-> start-p (gpt/add (hv (+ layout-gap-col (:size last-track)))))
:type :column
:track-before (last column-tracks)
:zoom zoom}]]))
(for [[idx row-data] (d/enumerate row-tracks)]
[:& track {:index idx
:key (dm/str "row-track-" idx)
:layout-data layout-data
:shape shape
:snap-pixel? snap-pixel?
:track-data row-data
:type :row
:zoom zoom}])
(for [[idx row-data] (d/enumerate row-tracks)]
[:& track {:index idx
:key (dm/str "row-track-" idx)
:layout-data layout-data
:shape shape
:snap-pixel? snap-pixel?
:track-data row-data
:type :row
:zoom zoom}])
(when-not (empty? row-tracks)
(let [last-track (last row-tracks)
start-p (:start-p (last row-tracks))
relative (gpt/to-vec origin start-p)
marker-p
(-> origin
(gpt/add (vv (:y relative)))
(gpt/subtract (hv (/ 20 zoom)))
(gpt/add (vv (:size last-track))))]
[:g.track
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
[:& track-marker {:center marker-p
:index (count row-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last row-tracks)
:type :row
:value (dm/str (inc (count row-tracks)))
:zoom zoom}]]
[:& resize-track-handler
{:index (count row-tracks)
:shape shape
:layout-data layout-data
:start-p (-> start-p
(gpt/add (vv (+ layout-gap-row (:size last-track)))))
:type :row
:track-before (last row-tracks)
:snap-pixel? snap-pixel?
:zoom zoom}]]))
(when-not (empty? row-tracks)
(let [last-track (last row-tracks)
start-p (:start-p (last row-tracks))
relative (gpt/to-vec origin start-p)
marker-p
(-> origin
(gpt/add (vv (:y relative)))
(gpt/subtract (hv (/ 20 zoom)))
(gpt/add (vv (:size last-track))))]
[:g.track
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
[:& track-marker {:center marker-p
:index (count row-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last row-tracks)
:type :row
:value (dm/str (inc (count row-tracks)))
:zoom zoom}]]
[:& resize-track-handler
{:index (count row-tracks)
:shape shape
:layout-data layout-data
:start-p (-> start-p
(gpt/add (vv (+ layout-gap-row (:size last-track)))))
:type :row
:track-before (last row-tracks)
:snap-pixel? snap-pixel?
:zoom zoom}]]))])
(for [[_ cell] (:layout-grid-cells shape)]
[:& grid-cell {:key (dm/str "cell-" (:id cell))

View file

@ -171,6 +171,7 @@
(when (not (:hidden frame))
[:g.frame-title {:id (dm/str "frame-title-" (:id frame))
:data-edit-grid grid-edition?
:transform (vwu/title-transform frame zoom grid-edition?)
:pointer-events (when (:blocked frame) "none")}
(cond