mirror of
https://github.com/penpot/penpot.git
synced 2025-06-04 16:01:38 +02:00
🐛 Fix some issues with grid
This commit is contained in:
parent
7fd02022ac
commit
a0c79fc038
5 changed files with 169 additions and 155 deletions
|
@ -16,6 +16,7 @@
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -265,7 +266,7 @@
|
||||||
(gpt/add orig-pos delta)
|
(gpt/add orig-pos delta)
|
||||||
{:skip-components? true
|
{:skip-components? true
|
||||||
:bottom-frames? true}))
|
:bottom-frames? true}))
|
||||||
frame-ids-map (volatile! {})
|
ids-map (volatile! {})
|
||||||
|
|
||||||
update-new-shape
|
update-new-shape
|
||||||
(fn [new-shape original-shape]
|
(fn [new-shape original-shape]
|
||||||
|
@ -275,8 +276,7 @@
|
||||||
(when (nil? (:parent-id original-shape))
|
(when (nil? (:parent-id original-shape))
|
||||||
(vswap! unames conj new-name))
|
(vswap! unames conj new-name))
|
||||||
|
|
||||||
(when (= (:type original-shape) :frame)
|
(vswap! ids-map assoc (:id original-shape) (:id new-shape))
|
||||||
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
|
|
||||||
|
|
||||||
(cond-> new-shape
|
(cond-> new-shape
|
||||||
:always
|
:always
|
||||||
|
@ -307,24 +307,29 @@
|
||||||
(dissoc :component-root))))
|
(dissoc :component-root))))
|
||||||
|
|
||||||
[new-shape new-shapes _]
|
[new-shape new-shapes _]
|
||||||
(ctst/clone-object component-shape
|
(ctst/clone-object
|
||||||
nil
|
component-shape
|
||||||
(if components-v2 (:objects component-page) (:objects component))
|
nil
|
||||||
update-new-shape
|
(if components-v2 (:objects component-page) (:objects component))
|
||||||
(fn [object _] object)
|
update-new-shape
|
||||||
force-id
|
(fn [object _] object)
|
||||||
keep-ids?)
|
force-id
|
||||||
|
keep-ids?)
|
||||||
|
|
||||||
;; If frame-id points to a shape inside the component, remap it to the
|
;; If frame-id points to a shape inside the component, remap it to the
|
||||||
;; corresponding new frame shape. If not, set it to the destination frame.
|
;; corresponding new frame shape. If not, set it to the destination frame.
|
||||||
;; Also fix empty parent-id.
|
;; Also fix empty parent-id.
|
||||||
remap-frame-id (fn [shape]
|
remap-ids
|
||||||
(as-> shape $
|
(fn [shape]
|
||||||
(update $ :frame-id #(get @frame-ids-map % frame-id))
|
(as-> shape $
|
||||||
(update $ :parent-id #(or % (:frame-id $)))))]
|
(update $ :frame-id #(get @ids-map % frame-id))
|
||||||
|
(update $ :parent-id #(or % (:frame-id $)))
|
||||||
|
(cond-> $
|
||||||
|
(ctl/grid-layout? shape)
|
||||||
|
(ctl/remap-grid-cells @ids-map))))]
|
||||||
|
|
||||||
[(remap-frame-id new-shape)
|
[(remap-ids new-shape)
|
||||||
(map remap-frame-id new-shapes)])))
|
(map remap-ids new-shapes)])))
|
||||||
|
|
||||||
(defn get-top-instance
|
(defn get-top-instance
|
||||||
"The case of having an instance that contains another instances.
|
"The case of having an instance that contains another instances.
|
||||||
|
|
|
@ -1177,3 +1177,15 @@
|
||||||
(for [r (range first-row (inc last-row))
|
(for [r (range first-row (inc last-row))
|
||||||
c (range first-column (inc last-column))]
|
c (range first-column (inc last-column))]
|
||||||
[r c]))))
|
[r c]))))
|
||||||
|
|
||||||
|
(defn remap-grid-cells
|
||||||
|
"Remaps the shapes inside the cells"
|
||||||
|
[shape ids-map]
|
||||||
|
(let [do-remap-cells
|
||||||
|
(fn [cell]
|
||||||
|
(-> cell
|
||||||
|
(update :shapes #(mapv ids-map %))))
|
||||||
|
shape
|
||||||
|
(-> shape
|
||||||
|
(update :layout-grid-cells update-vals do-remap-cells))]
|
||||||
|
shape))
|
||||||
|
|
|
@ -330,17 +330,6 @@
|
||||||
(when selected
|
(when selected
|
||||||
(rx/of (select-shape (:id selected))))))))
|
(rx/of (select-shape (:id selected))))))))
|
||||||
|
|
||||||
(defn remap-grid-cells
|
|
||||||
"Remaps the shapes inside the cells"
|
|
||||||
[shape ids-map]
|
|
||||||
|
|
||||||
(let [do-remap-cells
|
|
||||||
(fn [cell]
|
|
||||||
(-> cell
|
|
||||||
(update :shapes #(mapv ids-map %))))]
|
|
||||||
|
|
||||||
(update shape :layout-grid-cells update-vals do-remap-cells)))
|
|
||||||
|
|
||||||
;; --- Duplicate Shapes
|
;; --- Duplicate Shapes
|
||||||
(declare prepare-duplicate-shape-change)
|
(declare prepare-duplicate-shape-change)
|
||||||
(declare prepare-duplicate-flows)
|
(declare prepare-duplicate-flows)
|
||||||
|
@ -463,8 +452,7 @@
|
||||||
(d/update-when :interactions #(ctsi/remap-interactions % ids-map objects))
|
(d/update-when :interactions #(ctsi/remap-interactions % ids-map objects))
|
||||||
|
|
||||||
(cond-> (ctl/grid-layout? obj)
|
(cond-> (ctl/grid-layout? obj)
|
||||||
(-> (ctl/check-deassigned-cells)
|
(ctl/remap-grid-cells ids-map)))
|
||||||
(remap-grid-cells ids-map))))
|
|
||||||
|
|
||||||
new-obj (cond-> new-obj
|
new-obj (cond-> new-obj
|
||||||
(not duplicating-component?)
|
(not duplicating-component?)
|
||||||
|
@ -474,7 +462,7 @@
|
||||||
changes (-> (pcb/add-object changes new-obj {:ignore-touched (and duplicating-component? child?)})
|
changes (-> (pcb/add-object changes new-obj {:ignore-touched (and duplicating-component? child?)})
|
||||||
(pcb/amend-last-change #(assoc % :old-id (:id obj)))
|
(pcb/amend-last-change #(assoc % :old-id (:id obj)))
|
||||||
(cond-> (ctl/grid-layout? objects (:parent-id obj))
|
(cond-> (ctl/grid-layout? objects (:parent-id obj))
|
||||||
(-> (pcb/update-shapes [(:parent-id obj)] ctl/assign-cells)
|
(-> (pcb/update-shapes [(:parent-id obj)] (fn [shape] (-> shape ctl/assign-cells ctl/check-deassigned-cells)))
|
||||||
(pcb/reorder-grid-children [(:parent-id obj)]))))
|
(pcb/reorder-grid-children [(:parent-id obj)]))))
|
||||||
|
|
||||||
changes (cond-> changes
|
changes (cond-> changes
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def small-size-limit 60)
|
||||||
|
(def medium-size-limit 110)
|
||||||
|
|
||||||
(defn apply-to-point [result next-fn]
|
(defn apply-to-point [result next-fn]
|
||||||
(conj result (next-fn (last result))))
|
(conj result (next-fn (last result))))
|
||||||
|
|
||||||
|
@ -630,6 +633,10 @@
|
||||||
[(:x text-p) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)]
|
[(:x text-p) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)]
|
||||||
[(- (:x text-p) (max 0 (:size track-data))) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)])
|
[(- (:x text-p) (max 0 (:size track-data))) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)])
|
||||||
|
|
||||||
|
trackwidth (* text-width zoom)
|
||||||
|
medium? (and (>= trackwidth small-size-limit) (< trackwidth medium-size-limit))
|
||||||
|
small? (< trackwidth small-size-limit)
|
||||||
|
|
||||||
track-before (get-in layout-data [track-list-prop (dec index)])]
|
track-before (get-in layout-data [track-list-prop (dec index)])]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
|
@ -644,28 +651,29 @@
|
||||||
(dm/str (gmt/transform-in text-p (:transform shape)))
|
(dm/str (gmt/transform-in text-p (:transform shape)))
|
||||||
(dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))}
|
(dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))}
|
||||||
|
|
||||||
(when hovering?
|
(when (and hovering? (not small?))
|
||||||
[:rect {:x (+ text-x (/ 5 zoom))
|
[:rect {:x (+ text-x (/ 18 zoom))
|
||||||
:y text-y
|
:y text-y
|
||||||
:width (- text-width (/ 10 zoom))
|
:width (- text-width (/ 36 zoom))
|
||||||
:height (- text-height (/ 5 zoom))
|
:height (- text-height (/ 5 zoom))
|
||||||
:rx (/ 3 zoom)
|
:rx (/ 3 zoom)
|
||||||
:fill "var(--color-distance)"
|
:fill "var(--color-distance)"
|
||||||
:opacity 0.2}])
|
:opacity 0.2}])
|
||||||
[:foreignObject {:x text-x :y text-y :width text-width :height text-height}
|
(when (not small?)
|
||||||
[:div {:class (css :grid-editor-wrapper)}
|
[:foreignObject {:x text-x :y text-y :width text-width :height text-height}
|
||||||
[:input
|
[:div {:class (css :grid-editor-wrapper)}
|
||||||
{:ref track-input-ref
|
[:input
|
||||||
:style {}
|
{:ref track-input-ref
|
||||||
:class (css :grid-editor-label)
|
:style {}
|
||||||
:type "text"
|
:class (css :grid-editor-label)
|
||||||
:default-value (format-size track-data)
|
:type "text"
|
||||||
:data-default-value (format-size track-data)
|
:default-value (format-size track-data)
|
||||||
:on-key-down handle-keydown-track-input
|
:data-default-value (format-size track-data)
|
||||||
:on-blur handle-blur-track-input}]
|
:on-key-down handle-keydown-track-input
|
||||||
(when hovering?
|
:on-blur handle-blur-track-input}]
|
||||||
[:button {:class (css :grid-editor-button)
|
(when (and hovering? (not medium?) (not small?))
|
||||||
:on-click handle-remove-track} i/trash])]]]
|
[:button {:class (css :grid-editor-button)
|
||||||
|
:on-click handle-remove-track} i/trash])]])]
|
||||||
|
|
||||||
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
|
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
|
||||||
[:& track-marker
|
[:& track-marker
|
||||||
|
@ -782,106 +790,107 @@
|
||||||
(fn []
|
(fn []
|
||||||
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
|
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
|
||||||
|
|
||||||
[:g.grid-editor {:pointer-events (when view-only "none")
|
(when (and (not (:hidden shape)) (not (:blocked shape)))
|
||||||
:on-pointer-down handle-pointer-down}
|
[:g.grid-editor {:pointer-events (when view-only "none")
|
||||||
[:g.cells
|
:on-pointer-down handle-pointer-down}
|
||||||
(for [cell (ctl/get-cells shape {:sort? true})]
|
[:g.cells
|
||||||
[:& grid-cell {:key (dm/str "cell-" (:id cell))
|
(for [cell (ctl/get-cells shape {:sort? true})]
|
||||||
:shape base-shape
|
[:& grid-cell {:key (dm/str "cell-" (:id cell))
|
||||||
:layout-data layout-data
|
:shape base-shape
|
||||||
:cell cell
|
:layout-data layout-data
|
||||||
|
:cell cell
|
||||||
|
:zoom zoom
|
||||||
|
:hover? (contains? hover-cells (:id cell))
|
||||||
|
:selected? (contains? selected-cells (:id cell))}])]
|
||||||
|
(when-not view-only
|
||||||
|
[:*
|
||||||
|
[:& grid-editor-frame {:zoom zoom
|
||||||
|
:bounds bounds}]
|
||||||
|
(let [start-p (-> origin (gpt/add (hv width)))]
|
||||||
|
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
|
||||||
|
[:& plus-btn {:start-p start-p
|
||||||
|
:zoom zoom
|
||||||
|
:type :column
|
||||||
|
:on-click handle-add-column}]])
|
||||||
|
|
||||||
|
(let [start-p (-> origin (gpt/add (vv height)))]
|
||||||
|
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
|
||||||
|
[:& plus-btn {:start-p start-p
|
||||||
|
:zoom zoom
|
||||||
|
:type :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
|
:zoom zoom
|
||||||
:hover? (contains? hover-cells (:id cell))
|
:type :column
|
||||||
:selected? (contains? selected-cells (:id cell))}])]
|
:index idx
|
||||||
(when-not view-only
|
:layout-data layout-data
|
||||||
[:*
|
:snap-pixel? snap-pixel?
|
||||||
[:& grid-editor-frame {:zoom zoom
|
:track-data column-data
|
||||||
:bounds bounds}]
|
:hovering? (contains? hover-columns idx)}])
|
||||||
(let [start-p (-> origin (gpt/add (hv width)))]
|
|
||||||
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
|
|
||||||
[:& plus-btn {:start-p start-p
|
|
||||||
:zoom zoom
|
|
||||||
:type :column
|
|
||||||
:on-click handle-add-column}]])
|
|
||||||
|
|
||||||
(let [start-p (-> origin (gpt/add (vv height)))]
|
;; Last track resize handler
|
||||||
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
|
(when-not (empty? column-tracks)
|
||||||
[:& plus-btn {:start-p start-p
|
(let [last-track (last column-tracks)
|
||||||
:zoom zoom
|
start-p (:start-p last-track)
|
||||||
:type :row
|
end-p (gpt/add start-p (hv (:size last-track)))
|
||||||
:on-click handle-add-row}]])
|
marker-p (-> (gpo/project-point bounds :h end-p)
|
||||||
|
(gpt/subtract (vv (/ 20 zoom))))]
|
||||||
|
[: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)
|
||||||
|
:last? true
|
||||||
|
:shape shape
|
||||||
|
:layout-data layout-data
|
||||||
|
:snap-pixel? snap-pixel?
|
||||||
|
:start-p end-p
|
||||||
|
:type :column
|
||||||
|
:track-before (last column-tracks)
|
||||||
|
:zoom zoom}]]))
|
||||||
|
|
||||||
(for [[idx column-data] (d/enumerate column-tracks)]
|
(for [[idx row-data] (d/enumerate row-tracks)]
|
||||||
[:& track {:key (dm/str "column-track-" idx)
|
[:& track {:index idx
|
||||||
:shape shape
|
:key (dm/str "row-track-" idx)
|
||||||
:zoom zoom
|
:layout-data layout-data
|
||||||
:type :column
|
:shape shape
|
||||||
:index idx
|
:snap-pixel? snap-pixel?
|
||||||
:layout-data layout-data
|
:track-data row-data
|
||||||
:snap-pixel? snap-pixel?
|
:type :row
|
||||||
:track-data column-data
|
:zoom zoom
|
||||||
:hovering? (contains? hover-columns idx)}])
|
:hovering? (contains? hover-rows idx)}])
|
||||||
|
(when-not (empty? row-tracks)
|
||||||
;; Last track resize handler
|
(let [last-track (last row-tracks)
|
||||||
(when-not (empty? column-tracks)
|
start-p (:start-p last-track)
|
||||||
(let [last-track (last column-tracks)
|
end-p (gpt/add start-p (vv (:size last-track)))
|
||||||
start-p (:start-p last-track)
|
marker-p (-> (gpo/project-point bounds :v end-p)
|
||||||
end-p (gpt/add start-p (hv (:size last-track)))
|
(gpt/subtract (hv (/ 20 zoom))))]
|
||||||
marker-p (-> (gpo/project-point bounds :h end-p)
|
[:g.track
|
||||||
(gpt/subtract (vv (/ 20 zoom))))]
|
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
|
||||||
[:g.track
|
[:& track-marker {:center marker-p
|
||||||
[:& track-marker {:center marker-p
|
:index (count row-tracks)
|
||||||
:index (count column-tracks)
|
:shape shape
|
||||||
:shape shape
|
:snap-pixel? snap-pixel?
|
||||||
:snap-pixel? snap-pixel?
|
:track-before (last row-tracks)
|
||||||
:track-before (last column-tracks)
|
:type :row
|
||||||
:type :column
|
:value (dm/str (inc (count row-tracks)))
|
||||||
:value (dm/str (inc (count column-tracks)))
|
:zoom zoom}]]
|
||||||
:zoom zoom}]
|
[:& resize-track-handler
|
||||||
[:& resize-track-handler
|
{:index (count row-tracks)
|
||||||
{:index (count column-tracks)
|
:last? true
|
||||||
:last? true
|
:shape shape
|
||||||
:shape shape
|
:layout-data layout-data
|
||||||
:layout-data layout-data
|
:start-p end-p
|
||||||
:snap-pixel? snap-pixel?
|
:type :row
|
||||||
:start-p end-p
|
:track-before (last row-tracks)
|
||||||
:type :column
|
:snap-pixel? snap-pixel?
|
||||||
:track-before (last column-tracks)
|
:zoom zoom}]]))])])))
|
||||||
: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
|
|
||||||
:hovering? (contains? hover-rows idx)}])
|
|
||||||
(when-not (empty? row-tracks)
|
|
||||||
(let [last-track (last row-tracks)
|
|
||||||
start-p (:start-p last-track)
|
|
||||||
end-p (gpt/add start-p (vv (:size last-track)))
|
|
||||||
marker-p (-> (gpo/project-point bounds :v end-p)
|
|
||||||
(gpt/subtract (hv (/ 20 zoom))))]
|
|
||||||
[: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)
|
|
||||||
:last? true
|
|
||||||
:shape shape
|
|
||||||
:layout-data layout-data
|
|
||||||
:start-p end-p
|
|
||||||
:type :row
|
|
||||||
:track-before (last row-tracks)
|
|
||||||
:snap-pixel? snap-pixel?
|
|
||||||
:zoom zoom}]]))])]))
|
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: calc(10px / var(--zoom));
|
right: calc(20px / var(--zoom));
|
||||||
width: calc(20px / var(--zoom));
|
width: calc(20px / var(--zoom));
|
||||||
height: calc(20px / var(--zoom));
|
height: calc(20px / var(--zoom));
|
||||||
|
|
||||||
|
@ -80,12 +80,12 @@
|
||||||
.grid-cell-outline {
|
.grid-cell-outline {
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
stroke: var(--color-distance);
|
stroke: var(--color-distance);
|
||||||
stroke-linecap: round;
|
stroke-opacity: 0.5;
|
||||||
stroke-width: calc(2 / var(--zoom));
|
stroke-width: calc(1 / var(--zoom));
|
||||||
stroke-dasharray: 0 calc(8 / var(--zoom));
|
|
||||||
|
|
||||||
&.hover,
|
&.hover,
|
||||||
&.selected {
|
&.selected {
|
||||||
stroke-dasharray: initial;
|
stroke-opacity: 1;
|
||||||
|
stroke-width: calc(2 / var(--zoom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue