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

Add margin to spacing token & context menu ()

This commit is contained in:
Florian Schrödl 2025-02-12 14:27:26 +01:00 committed by GitHub
parent 10174aa7bc
commit e776ba1b33
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 122 additions and 77 deletions
common/src/app/common/types
frontend/src/app/main/ui/workspace/tokens

View file

@ -129,6 +129,10 @@
[:p2 {:optional true} token-name-ref]
[:p3 {:optional true} token-name-ref]
[:p4 {:optional true} token-name-ref]
[:m1 {:optional true} token-name-ref]
[:m2 {:optional true} token-name-ref]
[:m3 {:optional true} token-name-ref]
[:m4 {:optional true} token-name-ref]
[:x {:optional true} token-name-ref]
[:y {:optional true} token-name-ref]])

View file

@ -203,6 +203,26 @@
(filter ctsl/any-layout?)
(map :id))))
(defn- shape-ids-with-layout-parent [state page-id shape-ids]
(let [objects (dsh/lookup-page-objects state)]
(->> (dsh/lookup-shapes state page-id shape-ids)
(eduction
(filter #(ctsl/any-layout-immediate-child? objects %))
(map :id)))))
(defn update-layout-item-margin
([value shape-ids attrs] (update-layout-item-margin value shape-ids attrs nil))
([value shape-ids attrs page-id]
(ptk/reify ::update-layout-item-margin
ptk/WatchEvent
(watch [_ state _]
(let [ids-with-layout-parent (shape-ids-with-layout-parent state (or page-id (:current-page-id state)) shape-ids)]
(rx/of
(dwsl/update-layout ids-with-layout-parent
{:layout-item-margin (zipmap attrs (repeat value))}
{:ignore-touched true
:page-id page-id})))))))
(defn update-layout-padding
([value shape-ids attrs] (update-layout-padding value shape-ids attrs nil))
([value shape-ids attrs page-id]
@ -222,7 +242,7 @@
(ptk/reify ::update-layout-spacing
ptk/WatchEvent
(watch [_ state _]
(let [ids-with-layout (shape-ids-with-layout state page-id shape-ids)
(let [ids-with-layout (shape-ids-with-layout state (or page-id (:current-page-id state)) shape-ids)
layout-attributes (attributes->layout-gap attributes value)]
(rx/of
(dwsl/update-layout ids-with-layout

View file

@ -22,6 +22,7 @@
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.timers :as timers]
[clojure.set :as set]
[okulary.core :as l]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
@ -83,85 +84,106 @@
attribute-labels)]
(concat [all-action] single-actions)))
(defn layout-spacing-items [{:keys [token selected-shapes all-attr-labels horizontal-attr-labels vertical-attr-labels on-update-shape]}]
(let [horizontal-attrs (into #{} (keys horizontal-attr-labels))
vertical-attrs (into #{} (keys vertical-attr-labels))
attrs (set/union horizontal-attrs vertical-attrs)
{:keys [all-selected? selected-pred shape-ids]} (attribute-actions token selected-shapes attrs)
horizontal-selected? (and
(not all-selected?)
(every? selected-pred horizontal-attrs))
vertical-selected? (and
(not all-selected?)
(every? selected-pred vertical-attrs))
multi-items [{:title (tr "labels.all")
:selected? all-selected?
:action (fn []
(let [props {:attributes attrs
:token token
:shape-ids shape-ids}]
(if all-selected?
(st/emit! (wtch/unapply-token props))
(st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape))))))}
{:title "Horizontal"
:selected? horizontal-selected?
:action (fn []
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attrs))
horizontal-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attrs))
:else (wtch/apply-token (assoc props
:attributes horizontal-attrs
:on-update-shape on-update-shape)))]
(st/emit! event)))}
{:title "Vertical"
:selected? vertical-selected?
:action (fn []
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attrs))
vertical-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attrs))
:else (wtch/apply-token (assoc props
:attributes vertical-attrs
:on-update-shape on-update-shape)))]
(st/emit! event)))}]
single-items (map (fn [[attr title]]
(let [same-axis-selected? (cond
(get horizontal-attrs attr) horizontal-selected?
(get vertical-attrs attr) vertical-selected?
:else true)
selected? (and
(not all-selected?)
(not same-axis-selected?)
(selected-pred attr))]
{:title title
:selected? selected?
:action #(let [props {:attributes #{attr}
:token token
:shape-ids shape-ids}
event (cond
all-selected? (-> (assoc props :attributes-to-remove attrs)
(wtch/apply-token))
selected? (wtch/unapply-token props)
:else (-> (assoc props :on-update-shape on-update-shape)
(wtch/apply-token)))]
(st/emit! event))}))
all-attr-labels)]
(concat multi-items single-items)))
(defn spacing-attribute-actions [{:keys [token selected-shapes] :as context-data}]
(let [on-update-shape-padding wtch/update-layout-padding
padding-attrs {:p1 "Top"
:p2 "Right"
:p3 "Bottom"
:p4 "Left"}
all-padding-attrs (into #{} (keys padding-attrs))
{:keys [all-selected? selected-pred shape-ids]} (attribute-actions token selected-shapes all-padding-attrs)
horizontal-attributes #{:p2 :p4}
horizontal-padding-selected? (and
(not all-selected?)
(every? selected-pred horizontal-attributes))
vertical-attributes #{:p1 :p3}
vertical-padding-selected? (and
(not all-selected?)
(every? selected-pred vertical-attributes))
padding-items [{:title (tr "labels.all")
:selected? all-selected?
:action (fn []
(let [props {:attributes all-padding-attrs
:token token
:shape-ids shape-ids}]
(if all-selected?
(st/emit! (wtch/unapply-token props))
(st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape-padding))))))}
{:title "Horizontal"
:selected? horizontal-padding-selected?
:action (fn []
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attributes))
horizontal-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attributes))
:else (wtch/apply-token (assoc props
:attributes horizontal-attributes
:on-update-shape on-update-shape-padding)))]
(st/emit! event)))}
{:title "Vertical"
:selected? vertical-padding-selected?
:action (fn []
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes))
vertical-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes))
:else (wtch/apply-token (assoc props
:attributes vertical-attributes
:on-update-shape on-update-shape-padding)))]
(st/emit! event)))}]
single-padding-items (->> padding-attrs
(map (fn [[attr title]]
(let [same-axis-selected? (cond
(get horizontal-attributes attr) horizontal-padding-selected?
(get vertical-attributes attr) vertical-padding-selected?
:else true)
selected? (and
(not all-selected?)
(not same-axis-selected?)
(selected-pred attr))]
{:title title
:selected? selected?
:action #(let [props {:attributes #{attr}
:token token
:shape-ids shape-ids}
event (cond
all-selected? (-> (assoc props :attributes-to-remove all-padding-attrs)
(wtch/apply-token))
selected? (wtch/unapply-token props)
:else (-> (assoc props :on-update-shape on-update-shape-padding)
(wtch/apply-token)))]
(st/emit! event))}))))
(let [padding-items (layout-spacing-items {:token token
:selected-shapes selected-shapes
:all-attr-labels {:p1 "Padding top"
:p2 "Padding right"
:p3 "Padding bottom"
:p4 "Padding left"}
:horizontal-attr-labels {:p2 "Padding right"
:p4 "Padding left"}
:vertical-attr-labels {:p1 "Padding top"
:p3 "Padding bottom"}
:on-update-shape wtch/update-layout-padding})
margin-items (layout-spacing-items {:token token
:selected-shapes selected-shapes
:all-attr-labels {:m1 "Margin top"
:m2 "Margin right"
:m3 "Margin bottom"
:m4 "Margin left"}
:horizontal-attr-labels {:m2 "Margin right"
:m4 "Margin left"}
:vertical-attr-labels {:m1 "Margin top"
:m3 "Margin bottom"}
:on-update-shape wtch/update-layout-item-margin})
gap-items (all-or-sepearate-actions {:attribute-labels {:column-gap "Column Gap"
:row-gap "Row Gap"}
:on-update-shape wtch/update-layout-spacing}
context-data)]
(concat padding-items
single-padding-items
(concat gap-items
[:separator]
gap-items)))
padding-items
[:separator]
margin-items)))
(defn sizing-attribute-actions [context-data]
(concat

View file

@ -3,7 +3,6 @@
[app.common.files.helpers :as cfh]
[app.common.types.token :as ctt]
[app.main.data.helpers :as dsh]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.thumbnails :as dwt]
[app.main.data.workspace.undo :as dwu]
@ -26,8 +25,8 @@
ctt/sizing-keys wtch/update-shape-dimensions
ctt/opacity-keys wtch/update-opacity
#{:x :y} wtch/update-shape-position
#{:p1 :p2 :p3 :p4} (fn [resolved-value shape-ids attrs]
(dwsl/update-layout shape-ids {:layout-padding (zipmap attrs (repeat resolved-value))}))
#{:p1 :p2 :p3 :p4} wtch/update-layout-padding
#{:m1 :m2 :m3 :m4} wtch/update-layout-item-margin
#{:column-gap :row-gap} wtch/update-layout-spacing
#{:width :height} wtch/update-shape-dimensions
#{:layout-item-min-w :layout-item-min-h :layout-item-max-w :layout-item-max-h} wtch/update-layout-sizing-limits