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

This commit is contained in:
Andrey Antukh
2026-04-21 22:43:46 +02:00
27 changed files with 206 additions and 174 deletions
+18 -2
View File
@@ -1,6 +1,6 @@
# CHANGELOG
## 2.16.0 (Unreleased)
## 2.17.0 (Unreleased)
### :boom: Breaking changes & Deprecations
@@ -72,7 +72,8 @@
- Fix copy to be more specific [Taiga #13990](https://tree.taiga.io/project/penpot/issue/13990)
- Allow deleting the profile avatar after uploading [Github #9067](https://github.com/penpot/penpot/issues/9067)
## 2.15.0 (Unreleased)
## 2.16.0 (Unreleased)
### :boom: Breaking changes & Deprecations
@@ -96,6 +97,19 @@
- Fix text editor v1 focus [Taiga #13961](https://tree.taiga.io/project/penpot/issue/13961)
## 2.15.0 (Unreleased)
### :sparkles: New features & Enhancements
- Add MCP server integration [Taiga #13112](https://tree.taiga.io/project/penpot/us/13112)
- Add chunked upload API for large media and binary files (removes previous upload size limits) [Github #8909](https://github.com/penpot/penpot/pull/8909)
### :bug: Bugs fixed
- Fix incorrect handling of version restore operation [Github #9041](https://github.com/penpot/penpot/pull/9041)
- Fix removeChild errors from unmount race conditions [Github #8927](https://github.com/penpot/penpot/pull/8927)
## 2.14.3
### :sparkles: New features & Enhancements
@@ -186,6 +200,8 @@
- Optimize sidebar performance for deeply nested shapes [Taiga #13017](https://tree.taiga.io/project/penpot/task/13017)
- Remove tokens path node and bulk remove tokens [Taiga #13007](https://tree.taiga.io/project/penpot/us/13007)
- Replace themes management modal radio buttons for switches [Taiga #9215](https://tree.taiga.io/project/penpot/us/9215)
- [MCP server] Integrations section [Taiga #13112](https://tree.taiga.io/project/penpot/us/13112)
- [Access Tokens] Look & feel refinement [Taiga #13114](https://tree.taiga.io/project/penpot/us/13114)
### :bug: Bugs fixed
+1 -2
View File
@@ -380,7 +380,6 @@
(rx/take 1)
(rx/tap (fn [_] (perf/setup)))))
(->> stream
(rx/filter (ptk/type? ::dps/persistence-notification))
(rx/take 1)
@@ -488,8 +487,8 @@
:selected-before selected-before}]
(rx/of (dwu/append-undo entry stack-undo?)))
(rx/empty))))))
(rx/take-until stoper-s))
(rx/take-until stoper-s))
(rx/of (mcp/notify-other-tabs-disconnect)))))
ptk/EffectEvent
-1
View File
@@ -545,7 +545,6 @@
(ex/print-throwable cause :prefix "Uncaught Rejection")
(ts/asap #(flash :cause cause :type :unhandled))))))))]
(.addEventListener g/window "error" on-unhandled-error)
(.addEventListener g/window "unhandledrejection" on-unhandled-rejection)
(fn []
@@ -24,7 +24,7 @@
[app.main.ui.workspace.color-palette :refer [color-palette*]]
[app.main.ui.workspace.color-palette-ctx-menu :refer [color-palette-ctx-menu*]]
[app.main.ui.workspace.text-palette :refer [text-palette*]]
[app.main.ui.workspace.text-palette-ctx-menu :refer [text-palette-ctx-menu]]
[app.main.ui.workspace.text-palette-ctx-menu :refer [text-palette-ctx-menu*]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.object :as obj]
@@ -203,10 +203,10 @@
:ref container}
(when text-palette?
[:*
[:& text-palette-ctx-menu {:show-menu? show-menu?
:close-menu on-close-menu
:on-select-palette on-select-text-palette-menu
:selected selected-text}]
[:> text-palette-ctx-menu* {:show-menu show-menu?
:close-menu on-close-menu
:on-select-palette on-select-text-palette-menu
:selected selected-text}]
[:> text-palette* {:size size
:selected selected-text
:width vport-width}]])
@@ -16,7 +16,7 @@
[app.render-wasm.api :as wasm.api]
[rumext.v2 :as mf]))
(mf/defc text-edition-outline
(mf/defc text-edition-outline*
[{:keys [shape zoom modifiers]}]
(if (features/active-feature? @st/state "render-wasm/v1")
(let [selrect-transform (mf/deref refs/workspace-selrect)
@@ -258,7 +258,7 @@
(map (resolve-shape-types entries objects))
(mapv select-entry)))
(mf/defc history-entry-details [{:keys [entry]}]
(mf/defc history-entry-details* [{:keys [entry]}]
(let [{entries :items} (mf/deref workspace-undo)
objects (mf/deref refs/workspace-page-objects)]
@@ -319,7 +319,7 @@
deprecated-icon/arrow])]
(when @show-detail?
[:& history-entry-details {:entry entry}])]))
[:> history-entry-details* {:entry entry}])]))
(mf/defc history-toolbox*
[]
@@ -32,7 +32,7 @@
:value 4
:hidden false}))
(mf/defc blur-menu [{:keys [ids type values]}]
(mf/defc blur-menu* [{:keys [ids type values]}]
(let [blur (:blur values)
has-value? (not (nil? blur))
render-wasm? (features/use-feature "render-wasm/v1")
@@ -28,7 +28,7 @@
:parent-id
:frame-id])
(mf/defc constraints-menu
(mf/defc constraints-menu*
[{:keys [ids values] :as props}]
(let [state* (mf/use-state true)
open? (deref state*)
@@ -33,7 +33,7 @@
:separator
18 12 10 8 6 4 3 2])
(mf/defc grid-options
(mf/defc grid-options*
{::mf/wrap [mf/memo]}
[{:keys [shape-id index grid frame-width frame-height default-grid-params]}]
(let [on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
@@ -296,7 +296,7 @@
[:button {:class (stl/css :option-btn)
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])])]))
(mf/defc frame-grid
(mf/defc frame-grid*
[{:keys [shape]}]
(let [state* (mf/use-state true)
open? (deref state*)
@@ -331,12 +331,12 @@
(when (and open? (seq frame-grids))
[:div {:class (stl/css :element-set-content)}
(for [[index grid] (map-indexed vector frame-grids)]
[:& grid-options {:key (str id "-" index)
:shape-id id
:grid grid
:index index
:frame-width (:width shape)
:frame-height (:height shape)
:default-grid-params default-grid-params}])])]))
[:> grid-options* {:key (str id "-" index)
:shape-id id
:grid grid
:index index
:frame-width (:width shape)
:frame-height (:height shape)
:default-grid-params default-grid-params}])])]))
@@ -38,7 +38,7 @@
:stroke-cap-start
:stroke-cap-end])
(mf/defc stroke-menu
(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}]
(let [label (case type
@@ -17,7 +17,8 @@
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc attribute-value [{:keys [attr value on-change on-delete] :as props}]
(mf/defc attribute-value*
[{:keys [attr value on-change on-delete]}]
(let [last-value (mf/use-state value)
handle-change*
@@ -56,13 +57,14 @@
(str (d/name (last attr)))]
(for [[key value] value]
[:div {:class (stl/css :attr-row) :key key}
[:& attribute-value {:key key
:attr (conj attr key)
:value value
:on-change on-change
:on-delete on-delete}]])])]))
[:> attribute-value* {:key key
:attr (conj attr key)
:value value
:on-change on-change
:on-delete on-delete}]])])]))
(mf/defc svg-attrs-menu [{:keys [ids values]}]
(mf/defc svg-attrs-menu*
[{:keys [ids values]}]
(let [state* (mf/use-state true)
open? (deref state*)
attrs (:svg-attrs values)
@@ -103,8 +105,8 @@
(when open?
[:div {:class (stl/css :element-set-content)}
(for [[attr-key attr-value] attrs]
[:& attribute-value {:key attr-key
:attr [attr-key]
:value attr-value
:on-change handle-change
:on-delete handle-delete}])])])))
[:> attribute-value* {:key attr-key
:attr [attr-key]
:value attr-value
:on-change handle-change
:on-delete handle-delete}])])])))
@@ -79,7 +79,6 @@
(mf/defc text-direction-options*
[{:keys [values on-change on-blur]}]
(let [direction (:text-direction values)
handle-change
(mf/use-fn
(mf/deps on-change on-blur direction)
@@ -103,7 +102,6 @@
(mf/defc vertical-align*
[{:keys [values on-change on-blur]}]
(let [vertical-align (or (:vertical-align values) "top")
handle-change
(mf/use-fn
(mf/deps on-change on-blur)
@@ -135,11 +133,26 @@
handle-change
(mf/use-fn
(mf/deps ids on-blur on-change editor-instance)
(mf/deps ids on-blur editor-instance)
(fn [value]
(on-change {:grow-type (keyword value)})
(when (some? on-blur)
(on-blur))))]
(on-blur)
(let [uid (js/Symbol)
grow-type (keyword value)]
(st/emit! (dwu/start-undo-transaction uid))
(when (features/active-feature? @st/state "text-editor/v2")
(let [content (when editor-instance
(content/dom->cljs (dwt/get-editor-root editor-instance)))]
(when (some? content)
(st/emit! (dwt/v2-update-text-shape-content (first ids) content :finalize? true)))))
(st/emit! (dwsh/update-shapes ids #(assoc % :grow-type grow-type)))
(when (features/active-feature? @st/state "render-wasm/v1")
(st/emit! (dwwt/resize-wasm-text-all ids)
(ptk/data-event :layout/update {:ids ids})))
;; We asynchronously commit so every sychronous event is resolved first and inside the transaction
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
(when (some? on-blur) (on-blur))))]
[:div {:class (stl/css :grow-options)}
[:> radio-buttons* {:selected (d/name grow-type)
@@ -410,9 +423,9 @@
(dom/focus! (txu/get-text-editor-content)))))))
common-props
(mf/spread-props {} {:values values
:on-change on-change
:on-blur on-text-blur})]
(mf/props {:values values
:on-change on-change
:on-blur on-text-blur})]
(hooks/use-stream
expand-stream
@@ -9,8 +9,8 @@
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -19,7 +19,7 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[rumext.v2 :as mf]))
(mf/defc options*
@@ -118,8 +118,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -127,15 +127,15 @@
:values shape
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:show-caps true
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:show-caps true
:values stroke-values
:applied-tokens applied-tokens}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:> exports-menu* {:type type
:ids ids
@@ -9,8 +9,8 @@
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -19,8 +19,8 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu*]]
[rumext.v2 :as mf]))
(mf/defc options*
@@ -117,8 +117,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -126,15 +126,15 @@
:values shape
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:& svg-attrs-menu {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:> svg-attrs-menu* {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> exports-menu* {:type type
:ids ids
:shapes shapes
@@ -10,20 +10,20 @@
[app.common.types.component :as ctk]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu* component-variant-main*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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.frame-grid :refer [frame-grid]]
[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.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]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[rumext.v2 :as mf]))
(mf/defc options*
@@ -140,8 +140,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -149,18 +149,18 @@
:values shape
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type shape-type
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type shape-type
:values stroke-values
:applied-tokens applied-tokens}]
[:> color-selection-menu* {:type shape-type
:shapes shapes-with-children
:file-id file-id
:libraries libraries}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:& frame-grid {:shape shape}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:> frame-grid* {:shape shape}]
[:> exports-menu* {:type shape-type
:ids ids
:shapes shapes
@@ -11,9 +11,9 @@
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu*]]
[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]
@@ -22,8 +22,8 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu*]]
[app.main.ui.workspace.sidebar.options.menus.text :as ot]
[app.main.ui.workspace.sidebar.options.shapes.multiple :refer [get-attrs]]
[rumext.v2 :as mf]))
@@ -143,7 +143,7 @@
:values layout-item-values}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
[:> constraints-menu* {:ids constraint-ids :values constraint-values}])
(when-not (empty? fill-ids)
[:> fill/fill-menu*
@@ -153,10 +153,10 @@
:applied-tokens fill-tokens}])
(when-not (empty? stroke-ids)
[:& stroke-menu {:type type
:ids stroke-ids
:values stroke-values
:applied-tokens stroke-tokens}])
[:> stroke-menu* {:type type
:ids stroke-ids
:values stroke-values
:applied-tokens stroke-tokens}])
[:> color-selection-menu*
{:type type
@@ -168,7 +168,7 @@
[:> shadow-menu* {:ids ids :values (get shape :shadow) :type type}])
(when-not (empty? blur-ids)
[:& blur-menu {:type type :ids blur-ids :values blur-values}])
[:> blur-menu* {:type type :ids blur-ids :values blur-values}])
(when-not (empty? text-ids)
[:> ot/text-menu* {:type type
@@ -177,7 +177,7 @@
:applied-tokens text-tokens}])
(when-not (empty? svg-values)
[:& svg-attrs-menu {:ids ids :values svg-values}])
[:> svg-attrs-menu* {:ids ids :values svg-values}])
[:> exports-menu* {:type type
:ids ids
@@ -20,10 +20,10 @@
[app.common.types.token :as tt]
[app.common.weak :as weak]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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*]]
@@ -31,7 +31,7 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.text :as ot]
[rumext.v2 :as mf]))
@@ -478,7 +478,7 @@
:values layout-item-values}])
(when-not (or (empty? constraint-ids) ^boolean is-layout-child?)
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
[:> constraints-menu* {:ids constraint-ids :values constraint-values}])
(when-not (empty? text-ids)
[:> ot/text-menu*
@@ -494,12 +494,12 @@
:applied-tokens fill-tokens}])
(when-not (empty? stroke-ids)
[:& stroke-menu {:type type
:ids stroke-ids
:show-caps show-caps?
:values stroke-values
:disable-stroke-style has-text?
:applied-tokens stroke-tokens}])
[:> stroke-menu* {:type type
:ids stroke-ids
:show-caps show-caps?
:values stroke-values
:disable-stroke-style has-text?
:applied-tokens stroke-tokens}])
(when-not (empty? shapes)
[:> color-selection-menu*
@@ -514,7 +514,7 @@
:values (get shadow-values :shadow)}])
(when-not (empty? blur-ids)
[:& blur-menu {:type type :ids blur-ids :values blur-values}])
[:> blur-menu* {:type type :ids blur-ids :values blur-values}])
(when-not (empty? exports-ids)
[:> exports-menu* {:type type
@@ -9,8 +9,8 @@
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -19,8 +19,8 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu*]]
[rumext.v2 :as mf]))
(mf/defc options*
@@ -117,8 +117,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -126,16 +126,16 @@
:values shape
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:show-caps true
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:show-caps true
:values stroke-values
:applied-tokens applied-tokens}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:& svg-attrs-menu {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:> svg-attrs-menu* {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> exports-menu* {:type type
:ids ids
:shapes shapes
@@ -9,8 +9,8 @@
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -19,8 +19,8 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu*]]
[rumext.v2 :as mf]))
(mf/defc options*
@@ -117,8 +117,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -126,18 +126,18 @@
:values shape
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:& svg-attrs-menu {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> svg-attrs-menu* {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> exports-menu* {:type type
:ids ids
:shapes shapes
@@ -11,8 +11,8 @@
[app.common.types.color :as cc]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -20,8 +20,8 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu*]]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@@ -184,8 +184,8 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu {:ids ids
:values constraint-values}])
[:> constraints-menu* {:ids ids
:values constraint-values}])
[:> fill/fill-menu*
{:ids ids
@@ -193,18 +193,18 @@
:values fill-values
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:values stroke-values
:applied-tokens applied-tokens}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]
[:> blur-menu* {:ids ids
:values (select-keys shape [:blur])}]
[:& svg-attrs-menu {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> svg-attrs-menu* {:ids ids
:values (select-keys shape [:svg-attrs])}]
[:> exports-menu* {:type type
:ids ids
:shapes shapes
@@ -14,9 +14,9 @@
[app.main.features :as features]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu*]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu*]]
[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]
@@ -25,7 +25,7 @@
[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]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu*]]
[app.main.ui.workspace.sidebar.options.menus.text :refer [text-menu*]]
[rumext.v2 :as mf]))
@@ -172,7 +172,7 @@
:shape shape}])
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
[:& constraints-menu
[:> constraints-menu*
{:ids ids
:values (select-keys shape constraint-attrs)}])
@@ -188,11 +188,11 @@
:values fill-values
:applied-tokens applied-tokens}]
[:& stroke-menu {:ids ids
:type type
:values stroke-values
:disable-stroke-style true
:applied-tokens applied-tokens}]
[:> stroke-menu* {:ids ids
:type type
:values stroke-values
:disable-stroke-style true
:applied-tokens applied-tokens}]
(when (= :multiple (:fills fill-values))
[:> color-selection-menu*
@@ -203,7 +203,7 @@
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu
[:> blur-menu*
{:ids ids
:values (select-keys shape [:blur])}]
@@ -14,11 +14,11 @@
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc text-palette-ctx-menu
[{:keys [show-menu? close-menu on-select-palette selected]}]
(mf/defc text-palette-ctx-menu*
[{:keys [show-menu close-menu on-select-palette selected]}]
(let [typographies (mf/deref refs/workspace-file-typography)
libraries (mf/deref refs/libraries)]
[:& dropdown {:show show-menu?
[:& dropdown {:show show-menu
:on-close close-menu}
[:ul {:class (stl/css :text-context-menu)}
(for [[idx cur-library] (map-indexed vector (vals libraries))]
@@ -27,7 +27,7 @@
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(mf/defc image-upload
(mf/defc image-upload*
{::mf/wrap [mf/memo]}
[]
(let [ref (mf/use-ref nil)
@@ -181,7 +181,7 @@
:data-tool "text"}
deprecated-icon/text]]
[:& image-upload]
[:> image-upload*]
[:li
[:button
@@ -30,7 +30,7 @@
[app.main.ui.workspace.shapes :as shapes]
[app.main.ui.workspace.shapes.path.editor :refer [path-editor*]]
[app.main.ui.workspace.shapes.text.editor :as editor-v1]
[app.main.ui.workspace.shapes.text.text-edition-outline :refer [text-edition-outline]]
[app.main.ui.workspace.shapes.text.text-edition-outline :refer [text-edition-outline*]]
[app.main.ui.workspace.shapes.text.v2-editor :as editor-v2]
[app.main.ui.workspace.shapes.text.viewport-texts-html :as stvh]
[app.main.ui.workspace.top-toolbar :refer [top-toolbar*]]
@@ -489,7 +489,7 @@
:on-context-menu on-menu-selected}])
(when show-text-editor?
[:& text-edition-outline
[:> text-edition-outline*
{:shape (get base-objects edition)
:zoom zoom
:modifiers modifiers}])
@@ -28,7 +28,7 @@
[app.main.ui.measurements :as msr]
[app.main.ui.workspace.shapes.path.editor :refer [path-editor*]]
[app.main.ui.workspace.shapes.text.editor :as editor-v1]
[app.main.ui.workspace.shapes.text.text-edition-outline :refer [text-edition-outline]]
[app.main.ui.workspace.shapes.text.text-edition-outline :refer [text-edition-outline*]]
[app.main.ui.workspace.shapes.text.v2-editor :as editor-v2]
[app.main.ui.workspace.shapes.text.v3-editor :as editor-v3]
[app.main.ui.workspace.top-toolbar :refer [top-toolbar*]]
@@ -587,7 +587,7 @@
:on-context-menu on-menu-selected}])
(when show-text-editor?
[:& text-edition-outline
[:> text-edition-outline*
{:shape (get base-objects edition)
:zoom zoom}])
+6 -3
View File
@@ -7591,11 +7591,14 @@ msgid "workspace.plugins.empty-plugins"
msgstr "No plugins installed yet"
#: src/app/main/ui/workspace/plugins.cljs:193
msgid "workspace.plugins.error.manifest"
msgstr "The plugin manifest is incorrect."
msgid "workspace.plugins.error.manifest"
msgstr "The plugin manifest is incorrect."
msgid "plugins.validation.message"
msgstr "Field %s is invalid: %s"
#: src/app/main/data/plugins.cljs:105, src/app/main/ui/workspace/main_menu.cljs:766, src/app/main/ui/workspace/plugins.cljs:84
msgid "workspace.plugins.error.need-editor"
msgid "workspace.plugins.error.need-editor"
msgstr "You need to be an editor to use this plugin"
#: src/app/main/ui/workspace/plugins.cljs:189
@@ -374,7 +374,7 @@ Applying tokens:
- The actual shape properties that the tokens control will reflect the token's resolved value.
Removing tokens:
Simply set the respective property directly - token binding is automatically removed, e.g.
Simply set the respective property directly - token binding is automatically removed, e.g.
shape.fills = [{ fillColor: "#000000", fillOpacity: 1 }]; // Removes fill token
# Visual Inspection of Designs
@@ -386,7 +386,7 @@ For many tasks, it can be critical to visually inspect the design. Remember to u
* When transferring styles from a Penpot design to code, make sure that you strictly adhere to the design.
NEVER make assumptions about missing values and don't get overly creative (e.g. don't pick your own colours and stick to
non-creative defaults such as white/black if you are lacking information).
* When creating new designs,
* When creating new designs,
- ensure a clean internal structure by applying flex and grid layouts when appropriate
- ensure proper semantic naming of elements.