Add proper props checking to several workspace sidebar components (#10159)

*  Add memo to sidebar components

*  Add memo to layout-container component

*  Add memo to layout-item component

*  Add memo to constraits component

*  Add memo to stroke-menu component

*  Add memo to shadows-menu component

*  Add memo to blur-menu component

*  Add memo to frame-grid-menu component

*  Add memo to grid-cell/options component

*  Add memo to svg-attrs component

*  Add check props to text-menu component

* 🐛 Fix CI
This commit is contained in:
Eva Marco 2026-06-17 14:39:03 +02:00 committed by GitHub
parent 585d6944fc
commit bdc9b092c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 458 additions and 224 deletions

View File

@ -157,8 +157,9 @@
(cond
(and edit-grid? (d/not-empty? selected-cells))
[:& grid-cell/options
{:shape (get objects edition)
[:> grid-cell/options*
{:shape-id (-> (get objects edition)
:id)
:cells selected-cells}]
edit-grid?

View File

@ -192,32 +192,26 @@
(conj {:key :background-blur
:value (:background-blur values)})))
(defn- check-props
"A blur-menu specific memoize check function that only checks if
specific values are changed on provided props. This allows pass the
whole shape as values without adding additional rerenders when other
shape properties changes."
[n-props o-props]
(and (identical? (unchecked-get n-props "ids")
(unchecked-get o-props "ids"))
(let [o-vals (unchecked-get o-props "values")
n-vals (unchecked-get n-props "values")
o-blur-values (get o-vals :blur)
n-blur-values (get n-vals :blur)
o-background-blur-values (get o-vals :background-blur)
n-background-blur-values (get n-vals :background-blur)]
(and (identical? o-blur-values n-blur-values)
(identical? o-background-blur-values n-background-blur-values)))))
(defn- check-blur-menu-props
[old-props new-props]
(let [old-values (unchecked-get old-props "values")
new-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (unchecked-get old-props "type")
(unchecked-get new-props "type"))
(identical? (get old-values :blur)
(get new-values :blur))
(identical? (get old-values :background-blur)
(get new-values :background-blur)))))
(mf/defc blur-menu*
{::mf/wrap [#(mf/memo' % check-props)]}
{::mf/wrap [#(mf/memo' % check-blur-menu-props)]}
[{:keys [ids type values]}]
(let [render-wasm? (features/use-feature "render-wasm/v1")
bg-blur? (and render-wasm?
(contains? cf/flags :background-blur))
blur-values (get-blurs values)
mixed-state (and (or (= :group type)

View File

@ -28,7 +28,33 @@
:parent-id
:frame-id])
(defn- check-constraints-menu-props
[old-props new-props]
(let [old-values (unchecked-get old-props "values")
new-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (get old-values :constraints-h)
(get new-values :constraints-h))
(identical? (get old-values :constraints-v)
(get new-values :constraints-v))
(identical? (get old-values :fixed-scroll)
(get new-values :fixed-scroll))
(identical? (get old-values :parent-id)
(get new-values :parent-id))
(identical? (get old-values :frame-id)
(get new-values :frame-id))
(identical? (get old-values :x)
(get new-values :x))
(identical? (get old-values :y)
(get new-values :y))
(identical? (get old-values :width)
(get new-values :width))
(identical? (get old-values :height)
(get new-values :height)))))
(mf/defc constraints-menu*
{::mf/wrap [#(mf/memo' % check-constraints-menu-props)]}
[{:keys [ids values] :as props}]
(let [state* (mf/use-state true)
open? (deref state*)

View File

@ -296,16 +296,26 @@
[:button {:class (stl/css :option-btn)
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])])]))
(defn- check-frame-grid-props
[old-props new-props]
(and (identical? (unchecked-get old-props "grids")
(unchecked-get new-props "grids"))
(identical? (unchecked-get old-props "id")
(unchecked-get new-props "id"))
(identical? (unchecked-get old-props "frameWidth")
(unchecked-get new-props "frameWidth"))
(identical? (unchecked-get old-props "frameHeight")
(unchecked-get new-props "frameHeight"))))
(mf/defc frame-grid*
[{:keys [shape]}]
{::mf/wrap [#(mf/memo' % check-frame-grid-props)]}
[{:keys [grids id frame-width frame-height]}]
(let [state* (mf/use-state true)
open? (deref state*)
frame-grids (:grids shape)
has-frame-grids? (or (= :multiple frame-grids) (some? (seq frame-grids)))
has-frame-grids? (or (= :multiple grids) (some? (seq grids)))
toggle-content (mf/use-fn #(swap! state* not))
id (:id shape)
default-grids (mf/deref lens:default-grids)
default-grid-params (mf/with-memo [default-grids]
(merge ctg/default-grid-params default-grids))
@ -328,15 +338,15 @@
:on-click handle-create-grid
:icon i/add}]]]
(when (and open? (seq frame-grids))
(when (and open? (seq grids))
[:div {:class (stl/css :element-set-content)}
(for [[index grid] (map-indexed vector frame-grids)]
(for [[index grid] (map-indexed vector grids)]
[:> grid-options* {:key (str id "-" index)
:shape-id id
:grid grid
:index index
:frame-width (:width shape)
:frame-height (:height shape)
:frame-width frame-width
:frame-height frame-height
:default-grid-params default-grid-params}])])]))

View File

@ -81,9 +81,19 @@
:id (dm/str "align-self-stretch-" type)}]]]))
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [shape cell cells] :as props}]
(defn- check-options-props
[old-props new-props]
(and (identical? (unchecked-get old-props "shapeId")
(unchecked-get new-props "shapeId"))
(identical? (unchecked-get old-props "cell")
(unchecked-get new-props "cell"))
(identical? (unchecked-get old-props "cells")
(unchecked-get new-props "cells"))))
;;TODO: Review this component only recieve cells prop ib this file app.main.ui.workspace.sidebar.options
(mf/defc options*
{::mf/wrap [#(mf/memo' % check-options-props)]}
[{:keys [shape-id cell cells] :as props}]
(let [state* (mf/use-state {:open true})
open? (:open @state*)
@ -115,23 +125,23 @@
set-alignment
(mf/use-callback
(mf/deps align-self (:id shape) cell-ids)
(mf/deps align-self shape-id cell-ids)
(fn [value]
(if (= align-self value)
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:align-self nil}))
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:align-self value})))))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:align-self nil}))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:align-self value})))))
set-justify-self
(mf/use-callback
(mf/deps justify-self (:id shape) cell-ids)
(mf/deps justify-self shape-id cell-ids)
(fn [value]
(if (= justify-self value)
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:justify-self nil}))
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:justify-self value})))))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:justify-self nil}))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:justify-self value})))))
on-grid-coordinates
(mf/use-callback
(mf/deps column row (:id shape) (:id cell))
(mf/deps column row shape-id (:id cell))
(fn [field type value]
(when-not multiple?
(let [value (mth/round value)
@ -151,30 +161,30 @@
(and (= type :row) (= field :end))
[:row-span (max 1 (- value row))])]
(st/emit! (dwsl/update-grid-cell-position (:id shape) (:id cell) {property value}))))))
(st/emit! (dwsl/update-grid-cell-position shape-id (:id cell) {property value}))))))
on-area-name-change
(mf/use-callback
(mf/deps (:id shape) cell-ids)
(mf/deps shape-id cell-ids)
(fn [event]
(let [value (dom/get-value (dom/get-target event))]
(if (= value "")
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:area-name nil}))
(st/emit! (dwsl/update-grid-cells (:id shape) cell-ids {:area-name value}))))))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:area-name nil}))
(st/emit! (dwsl/update-grid-cells shape-id cell-ids {:area-name value}))))))
set-cell-mode
(mf/use-callback
(mf/deps (:id shape) cell-ids)
(mf/deps shape-id cell-ids)
(fn [mode]
(let [mode (-> mode keyword)]
(st/emit! (dwsl/change-cells-mode (:id shape) cell-ids mode)))))
(st/emit! (dwsl/change-cells-mode shape-id cell-ids mode)))))
toggle-edit-mode
(mf/use-fn
(mf/deps (:id shape))
(mf/deps shape-id)
(fn []
(st/emit! (dw/start-edition-mode (:id shape))
(dwge/clear-selection (:id shape)))))]
(st/emit! (dw/start-edition-mode shape-id)
(dwge/clear-selection shape-id))))]
[:div {:class (stl/css :grid-cell-menu)}

View File

@ -1070,8 +1070,39 @@
[_]
(st/emit! (dom/open-new-window cf/grid-help-uri)))
(mf/defc layout-container-menu
{::mf/memo #{:ids :values :multiple :shapes :applied-tokens}}
(defn- check-layout-container-menu-props
[old-props new-props]
(let [o-values (unchecked-get old-props "values")
n-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (unchecked-get old-props "appliedTokens")
(unchecked-get new-props "appliedTokens"))
(identical? (unchecked-get old-props "multiple")
(unchecked-get new-props "multiple"))
(identical? (get o-values :layout-gap)
(get n-values :layout-gap))
(identical? (get o-values :layout-gap-type)
(get n-values :layout-gap-type))
(identical? (get o-values :layout-padding)
(get n-values :layout-padding))
(identical? (get o-values :layout-padding-type)
(get n-values :layout-padding-type))
(identical? (get o-values :layout-wrap-type)
(get n-values :layout-wrap-type))
(identical? (get o-values :layout-align-items)
(get n-values :layout-align-items))
(identical? (get o-values :layout-flex-dir)
(get n-values :layout-flex-dir))
(identical? (get o-values :layout-justify-content)
(get n-values :layout-justify-content))
(identical? (get o-values :layout-align-content)
(get n-values :layout-align-content))
(identical? (get o-values :layout)
(get n-values :layout)))))
(mf/defc layout-container-menu*
{::mf/wrap [#(mf/memo' % check-layout-container-menu-props)]}
[{:keys [ids values multiple applied-tokens]}]
(let [;; Display
layout-type (:layout values)

View File

@ -512,7 +512,6 @@
:title "Align self end"
:id "align-self-end"}]])
(def ^:private schema:layout-item-props-schema
[:map
[:layout-item-margin
@ -721,16 +720,60 @@
:value (get values :layout-item-max-h)
:nillable true}]])])]))
(mf/defc layout-item-menu
{::mf/memo #{:ids :values :type :is-layout-child? :is-grid-parent :is-flex-parent? :is-grid-layout? :is-flex-layout? :applied-tokens}
::mf/props :obj}
(defn- check-layout-item-menu-props
[old-props new-props]
(let [old-values (unchecked-get old-props "values")
new-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (unchecked-get old-props "type")
(unchecked-get new-props "type"))
(identical? (unchecked-get old-props "isLayoutChild")
(unchecked-get new-props "isLayoutChild"))
(identical? (unchecked-get old-props "isLayoutContainer")
(unchecked-get new-props "isLayoutContainer"))
(identical? (unchecked-get old-props "isGridParent")
(unchecked-get new-props "isGridParent"))
(identical? (unchecked-get old-props "isFlexParent")
(unchecked-get new-props "isFlexParent"))
(identical? (unchecked-get old-props "isGridLayout")
(unchecked-get new-props "isGridLayout"))
(identical? (unchecked-get old-props "isFlexLayout")
(unchecked-get new-props "isFlexLayout"))
(identical? (unchecked-get old-props "appliedTokens")
(unchecked-get new-props "appliedTokens"))
(identical? (get old-values :layout-item-margin)
(get new-values :layout-item-margin))
(identical? (get old-values :layout-item-margin-type)
(get new-values :layout-item-margin-type))
(identical? (get old-values :layout-item-h-sizing)
(get new-values :layout-item-h-sizing))
(identical? (get old-values :layout-item-v-sizing)
(get new-values :layout-item-v-sizing))
(identical? (get old-values :layout-item-max-h)
(get new-values :layout-item-max-h))
(identical? (get old-values :layout-item-min-h)
(get new-values :layout-item-min-h))
(identical? (get old-values :layout-item-max-w)
(get new-values :layout-item-max-w))
(identical? (get old-values :layout-item-min-w)
(get new-values :layout-item-min-w))
(identical? (get old-values :layout-item-align-self)
(get new-values :layout-item-align-self))
(identical? (get old-values :layout-item-absolute)
(get new-values :layout-item-absolute))
(identical? (get old-values :layout-item-z-index)
(get new-values :layout-item-z-index)))))
(mf/defc layout-item-menu*
{::mf/wrap [#(mf/memo' % check-layout-item-menu-props)]}
[{:keys [ids values
^boolean is-layout-child?
^boolean is-layout-container?
^boolean is-grid-parent?
^boolean is-flex-parent?
^boolean is-flex-layout?
^boolean is-grid-layout?
^boolean is-layout-child
^boolean is-layout-container
^boolean is-grid-parent
^boolean is-flex-parent
^boolean is-flex-layout
^boolean is-grid-layout
applied-tokens]}]
(let [selection-parents* (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
@ -743,16 +786,16 @@
is-col? (every? ctl/col? selection-parents)
^boolean
is-layout-child? (and is-layout-child? (not is-absolute?))
is-layout-child? (and is-layout-child (not is-absolute?))
state* (mf/use-state true)
open? (deref state*)
toggle-content (mf/use-fn #(swap! state* not))
has-content? (or is-layout-child?
is-flex-parent?
is-grid-parent?
is-layout-container?)
is-flex-parent
is-grid-parent
is-layout-container)
;; Align self
align-self (:layout-item-align-self values)
@ -761,24 +804,24 @@
title
(cond
(and is-layout-container?
is-flex-layout?
(and is-layout-container
is-flex-layout
(not is-layout-child?))
"Flex board"
(and is-layout-container?
is-grid-layout?
(and is-layout-container
is-grid-layout
(not is-layout-child?))
"Grid board"
(and is-layout-container?
(and is-layout-container
(not is-layout-child?))
"Layout board"
is-flex-parent?
is-flex-parent
"Flex element"
is-grid-parent?
is-grid-parent
"Grid element"
:else
@ -882,19 +925,19 @@
[:div {:class (stl/css-case
:behaviour-menu true
:wrap (and ^boolean is-layout-child?
^boolean is-layout-container?))}
^boolean is-layout-container))}
[:& element-behaviour-horizontal
{:is-auto is-layout-container?
{:is-auto is-layout-container
:has-fill is-layout-child?
:value (:layout-item-h-sizing values)
:on-change on-behaviour-h-change}]
[:& element-behaviour-vertical
{:is-auto is-layout-container?
{:is-auto is-layout-container
:has-fill is-layout-child?
:value (:layout-item-v-sizing values)
:on-change on-behaviour-v-change}]]]
(when (and is-layout-child? is-flex-parent?)
(when (and is-layout-child? is-flex-parent)
[:div {:class (stl/css :align-row)}
[:& align-self-row {:is-col is-col?
:value align-self

View File

@ -130,7 +130,47 @@
acc))))
acc)))))
(defn- check-measures-menu-props
[old-props new-props]
(let [o-values (unchecked-get old-props "values")
n-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (unchecked-get old-props "type")
(unchecked-get new-props "type"))
(identical? (unchecked-get old-props "appliedTokens")
(unchecked-get new-props "appliedTokens"))
(identical? (get o-values :x)
(get n-values :x))
(identical? (get o-values :y)
(get n-values :y))
(identical? (get o-values :rotation)
(get n-values :rotation))
(identical? (get o-values :hide-in-viewer)
(get n-values :hide-in-viewer))
(identical? (get o-values :width)
(get n-values :width))
(identical? (get o-values :width)
(get n-values :width))
(identical? (get o-values :height)
(get n-values :height))
(identical? (get o-values :points)
(get n-values :points))
(identical? (get o-values :selrect)
(get n-values :selrect))
(identical? (get o-values :r1)
(get n-values :r1))
(identical? (get o-values :r2)
(get n-values :r2))
(identical? (get o-values :r3)
(get n-values :r3))
(identical? (get o-values :r4)
(get n-values :r4))
(identical? (get o-values :proportion-lock)
(get n-values :proportion-lock)))))
(mf/defc measures-menu*
{::mf/wrap [#(mf/memo' % check-measures-menu-props)]}
[{:keys [ids values applied-tokens type shapes]}]
(let [token-numeric-inputs
(features/use-feature "tokens/numeric-input")

View File

@ -48,7 +48,17 @@
(map-indexed (fn [index shadow]
(assoc shadow ::index index))))
(defn- check-shadow-menu-props
[old-props new-props]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (unchecked-get old-props "type")
(unchecked-get new-props "type"))
(identical? (unchecked-get old-props "values")
(unchecked-get new-props "values"))))
(mf/defc shadow-menu*
{::mf/wrap [#(mf/memo' % check-shadow-menu-props)]}
[{:keys [ids type values] :as props}]
(let [shadows (mf/with-memo [values]
(if (= :multiple values)

View File

@ -20,7 +20,6 @@
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.hooks :as h]
[app.main.ui.workspace.sidebar.options.rows.stroke-row :refer [stroke-row*]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@ -40,9 +39,31 @@
:stroke-cap-start
:stroke-cap-end])
(defn- stroke-menu-check-props
"A stroke-menu specific memoize check function that only checks if
specific values are changed on provided props. This allows pass the
whole shape as values without adding additional rerenders when other
shape properties changes."
[n-props o-props]
(and (identical? (unchecked-get n-props "ids")
(unchecked-get o-props "ids"))
(identical? (unchecked-get n-props "type")
(unchecked-get o-props "type"))
(identical? (unchecked-get n-props "appliedTokens")
(unchecked-get o-props "appliedTokens"))
(identical? (unchecked-get n-props "showCaps")
(unchecked-get o-props "showCaps"))
(identical? (unchecked-get n-props "disableStrokeStyle")
(unchecked-get o-props "disableStrokeStyle"))
(let [o-vals (unchecked-get o-props "values")
n-vals (unchecked-get n-props "values")
o-strokes (get o-vals :strokes)
n-strokes (get n-vals :strokes)]
(identical? o-strokes n-strokes))))
(mf/defc stroke-menu*
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps" "applied-tokens"]))]}
[{:keys [ids type values show-caps disable-stroke-style applied-tokens shapes objects] :as props}]
{::mf/wrap [#(mf/memo' % stroke-menu-check-props)]}
[{:keys [ids type values show-caps disable-stroke-style applied-tokens]}]
(let [label (case type
:multiple (tr "workspace.options.selection-stroke")
:group (tr "workspace.options.group-stroke")
@ -127,30 +148,6 @@
(st/emit! (udw/trigger-bounding-box-cloaking ids))
(st/emit! (dc/change-stroke-attrs ids {:stroke-gap value} index))))
open-caps-select
(fn [caps-state]
(fn [event]
(let [window-size (dom/get-window-size)
target (dom/get-current-target event)
rect (dom/get-bounding-rect target)
top (if (< (+ (:bottom rect) 320) (:height window-size))
(+ (:bottom rect) 5)
(- (:height window-size) 325))
left (if (< (+ (:left rect) 200) (:width window-size))
(:left rect)
(- (:width window-size) 205))]
(swap! caps-state assoc :open? true
:left left
:top top))))
close-caps-select
(fn [caps-state]
(fn [_]
(swap! caps-state assoc :open? false)))
on-stroke-cap-start-change
(fn [index value]
(st/emit! (udw/trigger-bounding-box-cloaking ids))
@ -231,32 +228,28 @@
[:> h/sortable-container* {}
(for [[index value] (d/enumerate (:strokes values []))]
[:> stroke-row* {:key (dm/str "stroke-" index "-" (hash applied-tokens))
:index index
:stroke value
:title (tr "workspace.options.stroke-color")
:index index
:shapes shapes
:objects objects
:show-caps show-caps
:on-color-change on-color-change
:on-reorder handle-reorder
:on-color-detach on-color-detach
:on-remove on-remove
:on-stroke-width-change on-stroke-width-change
:on-stroke-dash-change on-stroke-dash-change
:on-stroke-gap-change on-stroke-gap-change
:on-stroke-style-change on-stroke-style-change
:on-stroke-alignment-change on-stroke-alignment-change
:open-caps-select open-caps-select
:close-caps-select close-caps-select
:on-stroke-cap-start-change on-stroke-cap-start-change
:on-stroke-cap-end-change on-stroke-cap-end-change
:on-stroke-cap-switch on-stroke-cap-switch
:applied-tokens (when (= 0 index) applied-tokens)
:on-detach-token on-detach-token
:on-remove on-remove
:on-toggle-visibility on-toggle-visibility
:on-reorder handle-reorder
:disable-drag disable-drag
:on-focus on-focus
:select-on-focus (not @disable-drag)
:on-blur on-blur
:ids ids
:disable-stroke-style disable-stroke-style}])])])]))
:applied-tokens (when (= 0 index) applied-tokens)
:on-detach-token on-detach-token
:disable-stroke-style disable-stroke-style
:select-on-focus (not @disable-drag)
:ids ids}])])])]))

View File

@ -63,7 +63,17 @@
:on-change on-change
:on-delete on-delete}]])])]))
(defn- check-svg-attrs-menu-props
[old-props new-props]
(let [old-values (unchecked-get old-props "values")
new-values (unchecked-get new-props "values")]
(and (identical? (unchecked-get old-props "ids")
(unchecked-get new-props "ids"))
(identical? (get old-values :svg-attrs)
(get new-values :svg-attrs)))))
(mf/defc svg-attrs-menu*
{::mf/wrap [#(mf/memo' % check-svg-attrs-menu-props)]}
[{:keys [ids values]}]
(let [state* (mf/use-state true)
open? (deref state*)

View File

@ -245,12 +245,52 @@
(d/seek #(= (:id %) (uuid/uuid id)))))
(defn- check-props [n-props o-props]
(and (identical? (unchecked-get n-props "ids")
(unchecked-get o-props "ids"))
(identical? (unchecked-get n-props "appliedTokens")
(unchecked-get o-props "appliedTokens"))
(identical? (unchecked-get n-props "values")
(unchecked-get o-props "values"))))
(let [o-values (unchecked-get o-props "values")
n-values (unchecked-get n-props "values")]
(and (identical? (unchecked-get n-props "ids")
(unchecked-get o-props "ids"))
(identical? (unchecked-get n-props "type")
(unchecked-get o-props "type"))
(identical? (unchecked-get n-props "appliedTokens")
(unchecked-get o-props "appliedTokens"))
(identical? (unchecked-get n-props "fileId")
(unchecked-get o-props "fileId"))
(identical? (unchecked-get n-props "typographies")
(unchecked-get o-props "typographies"))
(identical? (get o-values :fills)
(get n-values :fills))
(identical? (get o-values :font-family)
(get n-values :font-family))
(identical? (get o-values :font-id)
(get n-values :font-id))
(identical? (get o-values :font-size)
(get n-values :font-size))
(identical? (get o-values :font-style)
(get n-values :font-style))
(identical? (get o-values :font-variant-id)
(get n-values :font-variant-id))
(identical? (get o-values :font-weight)
(get n-values :font-weight))
(identical? (get o-values :grow-type)
(get n-values :grow-type))
(identical? (get o-values :letter-spacing)
(get n-values :letter-spacing))
(identical? (get o-values :line-height)
(get n-values :line-height))
(identical? (get o-values :text-align)
(get n-values :text-align))
(identical? (get o-values :text-decoration)
(get n-values :text-decoration))
(identical? (get o-values :text-direction)
(get n-values :text-direction))
(identical? (get o-values :text-transform)
(get n-values :text-transform))
(identical? (get o-values :typography-ref-file)
(get n-values :typography-ref-file))
(identical? (get o-values :typography-ref-id)
(get n-values :typography-ref-id))
(identical? (get o-values :vertical-align)
(get n-values :vertical-align)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Main component
@ -258,12 +298,9 @@
(mf/defc text-menu*
{::mf/wrap [#(mf/memo' % check-props)]}
[{:keys [ids type values applied-tokens]}]
[{:keys [ids type values applied-tokens libraries file-id typographies]}]
(let [file-id (mf/use-ctx ctx/current-file-id)
typographies (mf/deref refs/workspace-file-typography)
libraries (mf/deref refs/files)
;; --- UI state
(let [;; --- UI state
menu-state* (mf/use-state {:main-menu true
:more-options false})
menu-state (deref menu-state*)

View File

@ -15,8 +15,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -94,7 +94,7 @@
:values measure-values
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids [(:id shape)]
:values layout-container-values
@ -102,18 +102,19 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu
[:> layout-item-menu*
{:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-layout-child true
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])

View File

@ -15,8 +15,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -93,7 +93,7 @@
:values measure-values
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids [(:id shape)]
:values layout-container-values
@ -101,20 +101,21 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu {:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-layout-container? false
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])
[:> layout-item-menu* {:ids ids
:type type
:values layout-item-values
:is-layout-child true
:is-layout-container false
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:> constraints-menu* {:ids ids

View File

@ -19,8 +19,8 @@
[app.main.ui.workspace.sidebar.options.menus.frame-grid :refer [frame-grid*]]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [select-measure-keys measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -113,7 +113,7 @@
(when is-variant?
[:> component-variant-main* {:shapes shapes}])
[:& layout-container-menu
[:> layout-container-menu*
{:type shape-type
:ids ids
:applied-tokens applied-tokens
@ -121,22 +121,23 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when (or is-layout-child? is-layout-container?)
[:& layout-item-menu
[:> layout-item-menu*
{:ids ids
:type shape-type
: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-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?
:applied-tokens applied-tokens
:is-layout-container? is-layout-container?
:is-layout-container is-layout-container?
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
@ -159,8 +160,11 @@
:libraries libraries}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur :background-blur])}]
[:> frame-grid* {:shape shape}]
:values (select-keys shape [:blur])}]
[:> frame-grid* {:grids (:grids shape)
:id (:id shape)
:frame-width (:width shape)
:frame-height (:height shape)}]
[:> exports-menu* {:type shape-type
:ids ids
:shapes shapes

View File

@ -18,8 +18,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-menu*]]
@ -37,6 +37,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
typographies
(mf/deref refs/workspace-file-typography)
applied-tokens
(get shape :applied-tokens)
@ -119,7 +122,7 @@
:values measure-values
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids [(:id shape)]
:values layout-container-values
@ -127,18 +130,19 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu
[:> layout-item-menu*
{:type type
:ids layout-item-ids
:is-layout-child? true
:is-layout-container? false
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-layout-child true
:is-layout-container false
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:values layout-item-values}])
@ -174,7 +178,10 @@
[:> ot/text-menu* {:type type
:ids text-ids
:values text-values
:applied-tokens text-tokens}])
:applied-tokens text-tokens
:libraries libraries
:file-id file-id
:typographies typographies}])
(when-not (empty? svg-values)
[:> svg-attrs-menu* {:ids ids :values svg-values}])

View File

@ -27,8 +27,8 @@
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-attrs exports-menu*]]
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [select-measure-keys measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-attrs shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -339,6 +339,9 @@
(mf/with-memo [shapes]
(into #{} d/xf:map-id shapes))
typographies
(mf/deref refs/workspace-file-typography)
is-layout-child-ref
(mf/with-memo [shape-ids]
(refs/is-layout-child? shape-ids))
@ -468,7 +471,7 @@
(when (some? components)
[:> component-menu* {:shapes components}])
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids layout-container-ids
:values layout-container-values
@ -476,13 +479,13 @@
:multiple true}]
(when (or is-layout-child? has-flex-layout-container?)
[:& layout-item-menu
[:> layout-item-menu*
{:type type
:ids layout-item-ids
:is-layout-child? all-layout-child?
:is-layout-container? all-flex-layout-container?
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-layout-child all-layout-child?
:is-layout-container all-flex-layout-container?
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens layout-item-tokens
:values layout-item-values}])
@ -494,7 +497,10 @@
{:type type
:ids text-ids
:values text-values
:applied-tokens text-tokens}])
:applied-tokens text-tokens
:libraries libraries
:file-id file-id
:typographies typographies}])
(when-not (empty? fill-ids)
[:> fill/fill-menu* {:type type

View File

@ -15,8 +15,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -93,7 +93,7 @@
:values measure-values
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids [(:id shape)]
:values layout-container-values
@ -101,20 +101,21 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu {:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-layout-container? false
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])
[:> layout-item-menu* {:ids ids
:type type
:values layout-item-values
:is-layout-child true
:is-layout-container false
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:> constraints-menu* {:ids ids

View File

@ -15,8 +15,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -93,7 +93,7 @@
:applied-tokens applied-tokens
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids ids
:values layout-container-values
@ -101,19 +101,20 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when ^boolean is-layout-child?
[:& layout-item-menu
[:> layout-item-menu*
{:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-flex-parent? is-flex-parent?
:is-layout-child true
:is-flex-parent is-flex-parent?
:applied-tokens applied-tokens
:is-grid-parent? is-grid-parent?
:is-grid-parent is-grid-parent?
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)

View File

@ -16,8 +16,8 @@
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-menu* exports-attrs]]
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -160,7 +160,7 @@
:values measure-values
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids [(:id shape)]
:values layout-container-values
@ -168,18 +168,19 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu
[:> layout-item-menu*
{:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-layout-child true
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])

View File

@ -21,8 +21,8 @@
[app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu*]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu*]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu*]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu*]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
@ -36,6 +36,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
typographies
(mf/deref refs/workspace-file-typography)
applied-tokens
(get shape :applied-tokens)
@ -154,7 +157,7 @@
:applied-tokens applied-tokens
:shapes shapes}]
[:& layout-container-menu
[:> layout-container-menu*
{:type type
:ids ids
:values layout-container-values
@ -162,18 +165,19 @@
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
[:& grid-cell/options
{:shape (first parents)
[:> grid-cell/options*
{:shape-id (-> (first parents)
:id)
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
(when is-layout-child?
[:& layout-item-menu
[:& layout-item-menu*
{:ids ids
:type type
:values layout-item-values
:is-layout-child? true
:is-flex-parent? is-flex-parent?
:is-grid-parent? is-grid-parent?
:is-layout-child true
:is-flex-parent is-flex-parent?
:is-grid-parent is-grid-parent?
:applied-tokens applied-tokens
:shape shape}])
@ -186,7 +190,10 @@
{:ids ids
:type type
:applied-tokens applied-tokens
:values text-values}]
:values text-values
:libraries libraries
:file-id file-id
:typographies typographies}]
[:> fill/fill-menu*
{:ids ids