0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-09 21:41:23 -05:00

Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-02-12 10:07:32 +01:00
commit dae277adb2
18 changed files with 250 additions and 102 deletions

View file

@ -41,7 +41,9 @@
(let [changes (empty-changes origin)]
(with-meta changes
{::page-id page-id})))
([]
{:redo-changes []
:undo-changes '()})
([origin]
{:redo-changes []
:undo-changes '()
@ -109,13 +111,9 @@
(defn concat-changes
[changes1 changes2]
{:redo-changes (d/concat-vec (:redo-changes changes1)
(:redo-changes changes2))
:undo-changes (concat (:undo-changes changes1)
(:undo-changes changes2))
:origin (:origin changes1)
:undo-group (:undo-group changes1)
:tags (:tags changes1)})
(-> changes1
(update :redo-changes d/concat-vec (:redo-changes changes2))
(update :undo-changes d/concat-vec (:undo-changes changes2))))
; TODO: remove this when not needed
(defn- assert-page-id!

View file

@ -224,8 +224,18 @@
(remove ctl/position-absolute?)
(remove gco/invalid-geometry?))
auto? (or (ctl/auto? parent)
(and (ctl/grid-layout? objects (:parent-id parent))
(ctl/fill? parent)))
auto-width? (or (ctl/auto-width? parent)
(and (ctl/grid-layout? objects (:parent-id parent))
(ctl/fill-width? parent)))
auto-height? (or (ctl/auto-height? parent)
(and (ctl/grid-layout? objects (:parent-id parent))
(ctl/fill-height? parent)))
content-bounds
(when (and (d/not-empty? children) (ctl/auto? parent))
(when (and (d/not-empty? children) auto?)
(cond
(ctl/flex-layout? parent)
(gcfl/layout-content-bounds bounds parent children objects)
@ -238,12 +248,11 @@
auto-width (when content-bounds (gpo/width-points content-bounds))
auto-height (when content-bounds (gpo/height-points content-bounds))]
(cond-> (ctm/empty)
(and (some? auto-width) (ctl/auto-width? parent))
(and (some? auto-width) auto-width?)
(set-parent-auto-width auto-width)
(and (some? auto-height) (ctl/auto-height? parent))
(and (some? auto-height) auto-height?)
(set-parent-auto-height auto-height))))
(defn find-auto-layouts

View file

@ -14,7 +14,7 @@
(def conjv (fnil conj []))
;; Setted in app.common.geom.shapes.common-layout
;; Setted in app.common.geom.shapes.min-size-layout
;; We do it this way because circular dependencies
(def -child-min-width nil)

View file

@ -24,14 +24,16 @@
(ctl/child-min-width child)
(and strict? (ctl/fill-width? child) (ctl/flex-layout? child))
(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
(let [children (->> (cfh/get-immediate-children objects (dm/get-prop child :id))
(remove ctl/position-absolute?))]
(max (ctl/child-min-width child)
(gpo/width-points (fb/layout-content-bounds bounds child children objects))))
(and (ctl/fill-width? child)
(ctl/grid-layout? child))
(let [children
(->> (cfh/get-immediate-children objects (:id child) {:remove-hidden true})
(->> (cfh/get-immediate-children objects (:id child))
(remove ctl/position-absolute?)
(map #(vector @(get bounds (:id %)) %)))
layout-data (gd/calc-layout-data child @(get bounds (:id child)) children bounds objects true)]
(max (ctl/child-min-width child)
@ -52,13 +54,15 @@
(ctl/child-min-height child)
(and strict? (ctl/fill-height? child) (ctl/flex-layout? child))
(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
(let [children (->> (cfh/get-immediate-children objects (dm/get-prop child :id))
(remove ctl/position-absolute?))]
(max (ctl/child-min-height child)
(gpo/height-points (fb/layout-content-bounds bounds child children objects))))
(and (ctl/fill-height? child) (ctl/grid-layout? child))
(let [children
(->> (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})
(->> (cfh/get-immediate-children objects (dm/get-prop child :id))
(remove ctl/position-absolute?)
(map (fn [child] [@(get bounds (:id child)) child])))
layout-data (gd/calc-layout-data child (:points child) children bounds objects true)
auto-bounds (gb/layout-content-bounds bounds child layout-data)]

View file

@ -517,7 +517,6 @@
ids (seq ids)]
(if (empty? ids)
objects
(let [id (first ids)
modifier (dm/get-in modifiers [id :modifiers])]
(recur (d/update-when objects id transform-shape modifier)

View file

@ -68,34 +68,45 @@
:grids :grids-group
:layout :layout-container
:layout-align-content :layout-container
:layout-align-items :layout-container
:layout-flex-dir :layout-container
:layout-gap :layout-container
:layout-gap-type :layout-container
:layout-justify-content :layout-container
:layout-justify-items :layout-container
:layout-wrap-type :layout-container
:layout-padding-type :layout-container
:layout-padding :layout-container
:layout-h-orientation :layout-container
:layout-v-orientation :layout-container
:layout-grid-dir :layout-container
:layout-grid-rows :layout-container
:layout-grid-columns :layout-container
:layout-grid-cells :layout-container})
:layout-align-content :layout-align-content
:layout-align-items :layout-align-items
:layout-flex-dir :layout-flex-dir
:layout-gap :layout-gap
:layout-gap-type :layout-gap
:layout-justify-content :layout-justify-content
:layout-justify-items :layout-justify-items
:layout-wrap-type :layout-wrap-type
:layout-padding-type :layout-padding
:layout-padding :layout-padding
:layout-grid-dir :layout-grid-dir
:layout-grid-rows :layout-grid-rows
:layout-grid-columns :layout-grid-columns
:layout-grid-cells :layout-grid-cells
:layout-item-margin :layout-item-margin
:layout-item-margin-type :layout-item-margin
:layout-item-h-sizing :layout-item-h-sizing
:layout-item-v-sizing :layout-item-v-sizing
:layout-item-max-h :layout-item-max-h
:layout-item-min-h :layout-item-min-h
:layout-item-max-w :layout-item-max-w
:layout-item-min-w :layout-item-min-w
:layout-item-absolute :layout-item-absolute
:layout-item-z-index :layout-item-z-index})
(def swap-keep-attrs
[:layout-item-margin
:layout-item-margin-type
:layout-item-h-sizing
:layout-item-v-sizing
:layout-item-max-h
:layout-item-min-h
:layout-item-max-w
:layout-item-min-w
:layout-item-absolute
:layout-item-z-index])
#{:layout-item-margin
:layout-item-margin-type
:layout-item-h-sizing
:layout-item-v-sizing
:layout-item-max-h
:layout-item-min-h
:layout-item-max-w
:layout-item-min-w
:layout-item-absolute
:layout-item-z-index})
(defn instance-root?
"Check if this shape is the head of a top instance."

View file

@ -428,12 +428,14 @@
comps-nesting-loop?)))
(defn find-valid-parent-and-frame-ids
"Navigate trough the ancestors until find one that is valid"
"Navigate trough the ancestors until find one that is valid. Returns [ parent-id frame-id ]"
[parent-id objects children]
(let [parent (get objects parent-id)]
(if (invalid-structure-for-component? objects parent children)
(find-valid-parent-and-frame-ids (:parent-id parent) objects children)
[parent-id
(if (= :frame (:type parent))
parent-id
(:frame-id parent))])))
(letfn [(get-frame [parent-id]
(if (cfh/frame-shape? objects parent-id) parent-id (get-in objects [parent-id :frame-id])))]
(let [parent (get objects parent-id)
;; We can always move the children to the parent they already have
no-changes?
(->> children (every? #(= parent-id (:parent-id %))))]
(if (or no-changes? (not (invalid-structure-for-component? objects parent children)))
[parent-id (get-frame parent-id)]
(recur (:parent-id parent) objects children)))))

View file

@ -1580,3 +1580,32 @@
(-> shape
(update :layout-grid-cells update-vals do-remap-cells))]
shape))
(defn merge-cells
"Given target cells update with source cells while trying to keep target as
untouched as possible"
[target-cells source-cells omit-touched?]
(if (not omit-touched?)
source-cells
(letfn [(get-data [cells id]
(dissoc (get cells id) :shapes :row :column :row-span :column-span))]
(let [deleted-cells
(into #{}
(filter #(not (contains? source-cells %)))
(keys target-cells))
touched-cells
(into #{}
(filter #(and
(not (contains? deleted-cells %))
(not= (get-data source-cells %)
(get-data target-cells %))))
(keys target-cells))]
(->> touched-cells
(reduce
(fn [cells id]
(-> cells
(d/update-when id d/patch-object (get-data target-cells id))))
source-cells))))))

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M14.667 1H1.333m13.334 14H1.333m7.334-2c1.103 0 2-.896 2-2V4.834c0-1.104-.897-2-2-2H7.333a2 2 0 00-2 2V11a2 2 0 002 2h1.334z"/>
</svg>

After

Width:  |  Height:  |  Size: 254 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 14.667V1.333M1 14.667V1.333m2 7.334c0 1.103.896 2 2 2h6.166c1.104 0 2-.897 2-2V7.333a2 2 0 00-2-2H5a2 2 0 00-2 2v1.334z"/>
</svg>

After

Width:  |  Height:  |  Size: 253 B

View file

@ -53,6 +53,8 @@
(declare update-attrs)
(declare update-grid-main-attrs)
(declare update-grid-copy-attrs)
(declare update-flex-child-main-attrs)
(declare update-flex-child-copy-attrs)
(declare reposition-shape)
(declare make-change)
@ -670,12 +672,21 @@
container
omit-touched?)
(ctl/flex-layout? shape-main)
(update-flex-child-copy-attrs shape-main
shape-inst
library
component
container
omit-touched?)
(ctl/grid-layout? shape-main)
(update-grid-copy-attrs shape-main
shape-inst
library
component
container)
container
omit-touched?)
reset?
(change-touched shape-inst
@ -848,11 +859,19 @@
component-container
{:copy-touched? true}))
(ctl/flex-layout? shape-main)
(update-flex-child-main-attrs shape-main
shape-inst
component-container
container
omit-touched?)
(ctl/grid-layout? shape-main)
(update-grid-main-attrs shape-main
shape-inst
component-container
container)
container
omit-touched?)
clear-remote-synced?
(change-remote-synced shape-inst container nil)
@ -1304,6 +1323,9 @@
touched (get dest-shape :touched #{})]
(loop [attrs (->> (seq (keys ctk/sync-attrs))
;; We don't update the flex-child attrs
(remove ctk/swap-keep-attrs)
;; We don't do automatic update of the `layout-grid-cells` property.
(remove #(= :layout-grid-cells %)))
roperations []
@ -1354,9 +1376,56 @@
(conj roperations roperation)
(conj uoperations uoperation)))))))))
(defn- propagate-attrs
"Helper that puts the origin attributes (attrs) into dest but only if
not touched the group or if omit-touched? flag is true"
[dest origin attrs omit-touched?]
(let [touched (get dest :touched #{})]
(->> attrs
(reduce
(fn [dest attr]
(let [attr-group (get ctk/sync-attrs attr)]
(cond-> dest
(or (not (touched attr-group)) (not omit-touched?))
(assoc attr (get origin attr)))))
dest))))
(defn- update-flex-child-copy-attrs
"Synchronizes the attributes inside the flex-child items (main->copy)"
[changes _shape-main shape-copy main-container main-component copy-container omit-touched?]
(let [do-changes
(fn [cc]
(-> cc
(pcb/with-container copy-container)
(pcb/with-objects (:objects copy-container))
(pcb/update-shapes
(:shapes shape-copy)
(fn [child-copy]
(let [child-main (ctf/get-ref-shape main-container main-component child-copy)]
(-> child-copy
(propagate-attrs child-main ctk/swap-keep-attrs omit-touched?))))
{:ignore-touched true})))]
(pcb/concat-changes changes (do-changes (pcb/empty-changes)))))
(defn- update-flex-child-main-attrs
"Synchronizes the attributes inside the flex-child items (copy->main)"
[changes shape-main shape-copy main-container copy-container omit-touched?]
(let [new-changes
(-> (pcb/empty-changes)
(pcb/with-page main-container)
(pcb/with-objects (:objects main-container))
(pcb/update-shapes
(:shapes shape-main)
(fn [child-main]
(let [child-copy (ctf/get-shape-in-copy copy-container child-main shape-copy)]
(-> child-main
(propagate-attrs child-copy ctk/swap-keep-attrs omit-touched?))))
{:ignore-touched true}))]
(pcb/concat-changes changes new-changes)))
(defn- update-grid-copy-attrs
"Synchronizes the `layout-grid-cells` property from the main shape to the copies"
[changes shape-main shape-copy main-container main-component copy-container]
[changes shape-main shape-copy main-container main-component copy-container omit-touched?]
(let [ids-map
(into {}
(comp
@ -1365,20 +1434,25 @@
(fn [copy-shape]
(let [main-shape (ctf/get-ref-shape main-container main-component copy-shape)]
[(:id main-shape) (:id copy-shape)]))))
(:shapes shape-copy))]
(:shapes shape-copy))
(-> changes
(pcb/with-container copy-container)
(pcb/update-shapes
[(:id shape-copy)]
(fn [shape-copy]
;; Take cells from main and remap the shapes to assign it to the copy
(let [new-cells (-> (ctl/remap-grid-cells shape-main ids-map) :layout-grid-cells)]
(assoc shape-copy :layout-grid-cells new-cells)))))))
new-changes
(-> (pcb/empty-changes)
(pcb/with-container copy-container)
(pcb/with-objects (:objects copy-container))
(pcb/update-shapes
[(:id shape-copy)]
(fn [shape-copy]
;; Take cells from main and remap the shapes to assign it to the copy
(let [copy-cells (:layout-grid-cells shape-copy)
main-cells (-> (ctl/remap-grid-cells shape-main ids-map) :layout-grid-cells)]
(assoc shape-copy :layout-grid-cells (ctl/merge-cells copy-cells main-cells omit-touched?))))
{:ignore-touched true}))]
(pcb/concat-changes changes new-changes)))
(defn- update-grid-main-attrs
"Synchronizes the `layout-grid-cells` property from the copy to the main shape"
[changes shape-main shape-copy main-container copy-container]
[changes shape-main shape-copy main-container copy-container _omit-touched?]
(let [ids-map
(into {}
(comp
@ -1387,16 +1461,20 @@
(fn [main-shape]
(let [copy-shape (ctf/get-shape-in-copy copy-container main-shape shape-copy)]
[(:id copy-shape) (:id main-shape)]))))
(:shapes shape-main))]
(-> changes
(pcb/with-page main-container)
(pcb/with-objects (:objects main-container))
(pcb/update-shapes
[(:id shape-main)]
(fn [shape-main]
;; Take cells from copy and remap the shapes to assign it to the copy
(let [new-cells (-> (ctl/remap-grid-cells shape-copy ids-map) :layout-grid-cells)]
(assoc shape-main :layout-grid-cells new-cells)))))))
(:shapes shape-main))
new-changes
(-> (pcb/empty-changes)
(pcb/with-page main-container)
(pcb/with-objects (:objects main-container))
(pcb/update-shapes
[(:id shape-main)]
(fn [shape-main]
;; Take cells from copy and remap the shapes to assign it to the copy
(let [new-cells (-> (ctl/remap-grid-cells shape-copy ids-map) :layout-grid-cells)]
(assoc shape-main :layout-grid-cells new-cells)))
{:ignore-touched true}))]
(pcb/concat-changes changes new-changes)))
(defn- reposition-shape
[shape origin-root dest-root]

View file

@ -511,7 +511,11 @@
objects (wsh/lookup-page-objects state page-id)
selected (wsh/lookup-selected state {:omit-blocked? true})
ids (if (nil? ids) selected ids)
shapes (mapv #(get objects %) ids)
shapes (into []
(comp (map (d/getf objects))
(remove ctk/in-component-copy-not-head?))
ids)
duplicate-move-started? (get-in state [:workspace-local :duplicate-move-started?] false)
stopper (->> stream
@ -670,6 +674,7 @@
{:keys [layout-grid-cells]}
(->> children
(remove #(ctk/in-component-copy-not-head? (get objects %)))
(keep #(ctl/get-cell-by-shape-id parent %))
(sort-by key-prop key-comp)
(reduce (fn [parent {:keys [id row column row-span column-span]}]

View file

@ -300,6 +300,8 @@
(def ^:icon align-self-row-center-refactor (icon-xref :align-self-row-center-refactor))
(def ^:icon align-self-row-left-refactor (icon-xref :align-self-row-left-refactor))
(def ^:icon align-self-row-right-refactor (icon-xref :align-self-row-right-refactor))
(def ^:icon align-self-column-stretch-refactor (icon-xref :align-self-column-stretch-refactor))
(def ^:icon align-self-row-stretch-refactor (icon-xref :align-self-row-stretch-refactor))
(def ^:icon board-refactor (icon-xref :board-refactor))
(def ^:icon boards-thumbnail-refactor (icon-xref :boards-thumbnail-refactor))
(def ^:icon boolean-difference-refactor (icon-xref :boolean-difference-refactor))

View file

@ -65,7 +65,7 @@
:id (dm/str "align-self-end-" type)}]
[:& radio-button {:value "stretch"
:icon (if is-col? i/align-self-row-strech i/align-self-column-strech)
:icon (if is-col? i/align-self-row-stretch-refactor i/align-self-column-stretch-refactor)
:title "Align self stretch"
:id (dm/str "align-self-stretch-" type)}]]]))

View file

@ -24,6 +24,9 @@
.layout-options {
width: $s-92;
}
.layout-option {
white-space: nowrap;
}
.remove-layout,
.add-layout {
@extend .button-tertiary;

View file

@ -246,7 +246,7 @@
(mf/defc layout-item-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "is-layout-child?" "is-grid-parent?" "is-flex-parent?"]))]}
[{:keys [ids values is-layout-child? is-layout-container? is-grid-parent? is-flex-parent?] :as props}]
[{:keys [ids values is-layout-child? is-layout-container? is-grid-parent? is-flex-parent? is-flex-layout? is-grid-layout?] :as props}]
(let [selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
selection-parents (mf/deref selection-parents-ref)
@ -268,9 +268,15 @@
title
(cond
(and is-layout-container? (not is-layout-child?))
(and is-layout-container? (not is-layout-child?) is-flex-layout?)
"Flex board"
(and is-layout-container? (not is-layout-child?) is-grid-layout?)
"Grid board"
(and is-layout-container? (not is-layout-child?))
"Layout board"
is-flex-parent?
"Flex element"

View file

@ -49,6 +49,8 @@
is-grid-parent? (mf/deref is-grid-parent-ref)
is-layout-container? (ctl/any-layout? shape)
is-flex-layout? (ctl/flex-layout? shape)
is-grid-layout? (ctl/grid-layout? shape)
is-layout-child-absolute? (ctl/item-absolute? shape)
ids (hooks/use-equal-memo ids)
@ -83,6 +85,8 @@
:values layout-item-values
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-flex-layout? is-flex-layout?
:is-grid-layout? is-grid-layout?
:is-layout-child? is-layout-child?
:is-layout-container? is-layout-container?
:shape shape}])

View file

@ -27,7 +27,6 @@
[app.main.store :as st]
[app.main.ui.css-cursors :as cur]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
[app.util.debug :as dbg]
@ -937,34 +936,27 @@
(map (fn [[_ idx]] idx))
(into #{}))
children
(mf/use-memo
(mf/deps objects shape modifiers)
(fn []
(let [ids (cfh/get-children-ids objects (:id shape))
objects (-> objects
(gsh/apply-objects-modifiers (select-keys modifiers ids))
(gsh/update-shapes-geometry (reverse ids)))]
(->> (cfh/get-immediate-children objects (:id shape))
(keep (fn [child]
(when-not (:hidden child)
[(gpo/parent-coords-bounds (:points child) (:points shape)) child])))))))
children (hooks/use-equal-memo children)
bounds (:points shape)
hv #(gpo/start-hv bounds %)
vv #(gpo/start-vv bounds %)
origin (gpo/origin bounds)
all-bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
{:keys [row-tracks column-tracks
column-total-size column-total-gap
row-total-size row-total-gap] :as layout-data}
layout-data
(mf/use-memo
(mf/deps shape children)
#(gsg/calc-layout-data shape bounds children all-bounds objects))
(mf/deps shape modifiers)
(fn []
(let [objects (gsh/apply-objects-modifiers objects modifiers)
ids (cfh/get-children-ids objects (:id shape))
objects (gsh/update-shapes-geometry objects (reverse ids))
children
(->> (cfh/get-immediate-children objects (:id shape) {:remove-hidden true})
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
children-bounds (d/lazy-map ids #(gsh/shape->points (get objects %)))]
(gsg/calc-layout-data shape bounds children children-bounds objects))))
{:keys [row-tracks column-tracks column-total-size column-total-gap row-total-size row-total-gap]} layout-data
width (max (gpo/width-points bounds) (+ column-total-size column-total-gap (ctl/h-padding shape)))
height (max (gpo/height-points bounds) (+ row-total-size row-total-gap (ctl/v-padding shape)))