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

This commit is contained in:
Andrey Antukh 2026-01-08 13:48:21 +01:00
commit 722fcc1f82
14 changed files with 94 additions and 38 deletions

View File

@ -38,6 +38,11 @@
- Fix wrong board size presets in Android [Taiga #12339](https://tree.taiga.io/project/penpot/issue/12339) - Fix wrong board size presets in Android [Taiga #12339](https://tree.taiga.io/project/penpot/issue/12339)
- Fix problem with grid layout components and auto sizing [Github #7797](https://github.com/penpot/penpot/issues/7797) - Fix problem with grid layout components and auto sizing [Github #7797](https://github.com/penpot/penpot/issues/7797)
- Fix some alignments on inspect tab [Taiga #12915](https://tree.taiga.io/project/penpot/issue/12915) - Fix some alignments on inspect tab [Taiga #12915](https://tree.taiga.io/project/penpot/issue/12915)
- Fix color assets from shared libraries not appearing as assets in Selected colors panel [Taiga #12957](https://tree.taiga.io/project/penpot/issue/12957)
- Fix CSS generated box-shadow property [Taiga #12997](https://tree.taiga.io/project/penpot/issue/12997)
- Fix inner shadow selector on shadow token [Taiga #12951](https://tree.taiga.io/project/penpot/issue/12951)
- Fix missing text color token from selected shapes in selected colors list [Taiga #12956](https://tree.taiga.io/project/penpot/issue/12956)
- Fix dropdown option width in Guides columns dropdown [Taiga #12959](https://tree.taiga.io/project/penpot/issue/12959)
## 2.12.1 ## 2.12.1

View File

@ -41,7 +41,10 @@ services:
- 6062:6062 - 6062:6062
- 6063:6063 - 6063:6063
- 6064:6064 - 6064:6064
- 9000:9000
- 9001:9001
- 9090:9090 - 9090:9090
- 9091:9091
environment: environment:
- EXTERNAL_UID=${CURRENT_USER_ID} - EXTERNAL_UID=${CURRENT_USER_ID}

View File

@ -667,6 +667,9 @@
} }
// UI ELEMENTS // UI ELEMENTS
// FIXME: This is used multiple times accross the app. We should design this in
// the DS and create a proper component for it.
.asset-element { .asset-element {
@include bodySmallTypography; @include bodySmallTypography;
display: flex; display: flex;

View File

@ -236,7 +236,7 @@
Uses `font-size-value` to calculate the relative line-height value. Uses `font-size-value` to calculate the relative line-height value.
Returns an error for an invalid font-size value." Returns an error for an invalid font-size value."
[line-height-value font-size-value font-size-errors] [line-height-value font-size-value font-size-errors]
(let [missing-references (seq (some cto/find-token-value-references line-height-value)) (let [missing-references (seq (cto/find-token-value-references line-height-value))
error error
(cond (cond
missing-references missing-references

View File

@ -1122,7 +1122,7 @@
ref-id (:stroke-color-ref-id stroke) ref-id (:stroke-color-ref-id stroke)
colors (-> libraries colors (-> libraries
(get ref-id) (get ref-file)
(get :data) (get :data)
(ctl/get-colors)) (ctl/get-colors))
shared? (contains? colors ref-id) shared? (contains? colors ref-id)
@ -1167,7 +1167,7 @@
ref-file (get color :ref-file) ref-file (get color :ref-file)
ref-id (get color :ref-id) ref-id (get color :ref-id)
colors (-> libraries colors (-> libraries
(get ref-id) (get ref-file)
(get :data) (get :data)
(ctl/get-colors)) (ctl/get-colors))
shared? (contains? colors ref-id) shared? (contains? colors ref-id)
@ -1180,19 +1180,20 @@
:index (:index shadow)})) :index (:index shadow)}))
(defn- text->color-att (defn- text->color-att
[fill file-id libraries] [fill file-id libraries & {:keys [has-token-applied token-name]}]
(let [ref-file (:fill-color-ref-file fill) (let [ref-file (:fill-color-ref-file fill)
ref-id (:fill-color-ref-id fill) ref-id (:fill-color-ref-id fill)
colors (-> libraries colors (-> libraries
(get ref-id) (get ref-file)
(get :data) (get :data)
(ctl/get-colors)) (ctl/get-colors))
shared? (contains? colors ref-id) shared? (contains? colors ref-id)
attrs (cond-> (types.fills/fill->color fill) base-attrs (cond-> (types.fills/fill->color fill)
(not (or shared? (= ref-file file-id))) (not (or shared? (= ref-file file-id)))
(dissoc :ref-file :ref-id))] (dissoc :ref-file :ref-id))
attrs (cond-> base-attrs
has-token-applied (assoc :has-token-applied true)
token-name (assoc :token-name token-name))]
{:attrs attrs {:attrs attrs
:prop :content :prop :content
:shape-id (:shape-id fill) :shape-id (:shape-id fill)
@ -1200,13 +1201,18 @@
(defn- extract-text-colors (defn- extract-text-colors
[text file-id libraries] [text file-id libraries]
(let [treat-node (let [applied-fill-token (get-in text [:applied-tokens :fill])
treat-node
(fn [node shape-id] (fn [node shape-id]
(map-indexed #(assoc %2 :shape-id shape-id :index %1) node))] (map-indexed (fn [idx fill]
(let [args (cond-> []
(and (= idx 0) applied-fill-token)
(conj :has-token-applied true :token-name applied-fill-token))]
(apply text->color-att (assoc fill :shape-id shape-id :index idx) file-id libraries args)))
node))]
(->> (txt/node-seq txt/is-text-node? (:content text)) (->> (txt/node-seq txt/is-text-node? (:content text))
(map :fills) (map :fills)
(mapcat #(treat-node % (:id text))) (mapcat #(treat-node % (:id text))))))
(map #(text->color-att % file-id libraries)))))
(defn- fill->color-att (defn- fill->color-att
"Given a fill map enriched with :shape-id, :index, and optionally "Given a fill map enriched with :shape-id, :index, and optionally
@ -1232,7 +1238,7 @@
ref-id (:fill-color-ref-id fill) ref-id (:fill-color-ref-id fill)
colors (-> libraries colors (-> libraries
(get ref-id) (get ref-file)
(get :data) (get :data)
(ctl/get-colors)) (ctl/get-colors))
shared? (contains? colors ref-id) shared? (contains? colors ref-id)

View File

@ -4,22 +4,29 @@
// //
// Copyright (c) KALEIDOS INC // Copyright (c) KALEIDOS INC
@use "refactor/common-refactor.scss" as deprecated; // FIXME: we need this import for .asset-element
@use "refactor/basic-rules.scss" as deprecated;
@use "ds/_borders.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_utils.scss" as *;
@use "ds/spacing.scss" as *;
.editable-select { .editable-select {
@extend .asset-element; @extend .asset-element;
margin: 0; margin: 0;
padding: 0; padding: 0;
border: deprecated.$s-1 solid var(--input-border-color); border: $b-1 solid var(--input-border-color);
position: relative; position: relative;
display: flex; display: flex;
height: deprecated.$s-32; height: $sz-32;
width: 100%; width: 100%;
padding: deprecated.$s-8; padding: var(--sp-s);
border-radius: deprecated.$br-8; border-radius: $br-8;
cursor: pointer; cursor: pointer;
.dropdown-button { .dropdown-button {
@include deprecated.flexCenter; display: flex;
place-content: center;
svg { svg {
@extend .button-icon-small; @extend .button-icon-small;
transform: rotate(90deg); transform: rotate(90deg);
@ -29,10 +36,11 @@
.custom-select-dropdown { .custom-select-dropdown {
@extend .dropdown-wrapper; @extend .dropdown-wrapper;
max-height: deprecated.$s-320; width: fit-content;
max-height: px2rem(320); // TODO: when this gets addressed in the DS, use a token
.separator { .separator {
margin: 0; margin: 0;
height: deprecated.$s-12; height: $sz-12;
} }
.dropdown-element { .dropdown-element {
@extend .dropdown-element-base; @extend .dropdown-element-base;
@ -43,7 +51,8 @@
} }
.check-icon { .check-icon {
@include deprecated.flexCenter; display: flex;
place-content: center;
svg { svg {
@extend .button-icon-small; @extend .button-icon-small;
visibility: hidden; visibility: hidden;

View File

@ -54,7 +54,7 @@
modifiers (dm/get-in modifiers [shape-id :modifiers]) modifiers (dm/get-in modifiers [shape-id :modifiers])
shape (gsh/transform-shape shape modifiers) shape (gsh/transform-shape shape modifiers)
props (mf/spread-props props {:shape shape :file-id file-id :page-id page-id})] props (mf/spread-props props {:shape shape :file-id file-id :page-id page-id :libraries libraries})]
(case shape-type (case shape-type
:frame [:> frame/options* props] :frame [:> frame/options* props]

View File

@ -349,6 +349,7 @@
(let [form (mf/use-ctx fc/context) (let [form (mf/use-ctx fc/context)
input-name name input-name name
error error
(get-in @form [:errors :value value-subfield index input-name]) (get-in @form [:errors :value value-subfield index input-name])

View File

@ -35,8 +35,8 @@
on-change on-change
(mf/use-fn (mf/use-fn
(mf/deps input-name) (mf/deps input-name)
(fn [type] (fn [id]
(let [is-inner? (= type "inner")] (let [is-inner? (= id "inner")]
(swap! form assoc-in [:data :value indexed-type index input-name] is-inner?)))) (swap! form assoc-in [:data :value indexed-type index input-name] is-inner?))))
props (mf/spread-props props {:default-selected (if value "inner" "drop") props (mf/spread-props props {:default-selected (if value "inner" "drop")

View File

@ -76,7 +76,7 @@
[token index prop value-subfield] [token index prop value-subfield]
(let [value (get-in token [:value value-subfield index prop])] (let [value (get-in token [:value value-subfield index prop])]
(d/without-nils (d/without-nils
{:type (if (= prop :color) :color :number) {:type (if (= prop :color) :color :dimensions)
:value value}))) :value value})))
(mf/defc shadow-formset* (mf/defc shadow-formset*
@ -114,7 +114,7 @@
:token inset-token :token inset-token
:tokens tokens :tokens tokens
:index index :index index
:value-subfield value-subfield :indexed-type value-subfield
:name :inset}] :name :inset}]
(when show-button (when show-button
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
@ -269,13 +269,25 @@
[:value [:value
[:map [:map
[:shadow {:optinal true} [:shadow {:optional true}
[:vector [:vector
[:map [:map
[:offset-x {:optional true} [:maybe :string]] [:offset-x {:optional true} [:maybe :string]]
[:offset-y {:optional true} [:maybe :string]] [:offset-y {:optional true} [:maybe :string]]
[:blur {:optional true} [:maybe :string]] [:blur {:optional true}
[:spread {:optional true} [:maybe :string]] [:and
[:maybe :string]
[:fn {:error/fn #(tr "workspace.tokens.shadow-token-blur-value-error")}
(fn [blur]
(let [n (d/parse-double blur)]
(or (nil? n) (not (< n 0)))))]]]
[:spread {:optional true}
[:and
[:maybe :string]
[:fn {:error/fn #(tr "workspace.tokens.shadow-token-spread-value-error")}
(fn [spread]
(let [n (d/parse-double spread)]
(or (nil? n) (not (< n 0)))))]]]
[:color {:optional true} [:maybe :string]] [:color {:optional true} [:maybe :string]]
[:color-result {:optional true} ::sm/any] [:color-result {:optional true} ::sm/any]
[:inset {:optional true} [:maybe :boolean]]]]] [:inset {:optional true} [:maybe :boolean]]]]]

View File

@ -199,7 +199,7 @@
:string-or-size-array (format-string-or-size-array value) :string-or-size-array (format-string-or-size-array value)
:keyword (format-keyword value) :keyword (format-keyword value)
:tracks (format-tracks value) :tracks (format-tracks value)
:shadow (format-shadow value options) :shadows (format-shadow value options)
:blur (format-blur value) :blur (format-blur value)
:matrix (format-matrix value) :matrix (format-matrix value)
(if (keyword? value) (d/name value) value)))) (if (keyword? value) (d/name value) value))))

View File

@ -47,17 +47,18 @@
[acc {:keys [schema in value type] :as problem}] [acc {:keys [schema in value type] :as problem}]
(let [props (m/properties schema) (let [props (m/properties schema)
tprops (m/type-properties schema) tprops (m/type-properties schema)
field (or (first in) field (or (:error/field props)
(:error/field props)) in)
field (if (vector? field) field (if (vector? field)
field field
[field])] [field])]
(if (contains? acc field) (if (and (= 1 (count field))
(contains? acc (first field)))
acc acc
(cond (cond
(nil? field) (or (nil? field)
(empty? field))
acc acc
(or (= type :malli.core/missing-key) (or (= type :malli.core/missing-key)

View File

@ -8068,6 +8068,14 @@ msgstr "Name"
msgid "workspace.tokens.token-name-duplication-validation-error" msgid "workspace.tokens.token-name-duplication-validation-error"
msgstr "A token already exists at the path: %s" msgstr "A token already exists at the path: %s"
#: src/app/main/ui/workspace/tokens/management/forms/shadow.cljs
msgid "workspace.tokens.shadow-token-blur-value-error"
msgstr "Blur value cannot be negative"
#: src/app/main/ui/workspace/tokens/management/forms/shadow.cljs
msgid "workspace.tokens.shadow-token-spread-value-error"
msgstr "Spread value cannot be negative"
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68 #: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
msgid "workspace.tokens.token-name-length-validation-error" msgid "workspace.tokens.token-name-length-validation-error"
msgstr "Name should be at least 1 character" msgstr "Name should be at least 1 character"

View File

@ -7944,6 +7944,14 @@ msgstr "Nombre"
msgid "workspace.tokens.token-name-duplication-validation-error" msgid "workspace.tokens.token-name-duplication-validation-error"
msgstr "Ya existe un token en la ruta: %s" msgstr "Ya existe un token en la ruta: %s"
#: src/app/main/ui/workspace/tokens/management/forms/shadow.cljs
msgid "workspace.tokens.shadow-token-blur-value-error"
msgstr "El valor de blur no puede ser negativo"
#: src/app/main/ui/workspace/tokens/management/forms/shadow.cljs
msgid "workspace.tokens.shadow-token-spread-value-error"
msgstr "El valor de spread no puede ser negativo"
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68 #: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
msgid "workspace.tokens.token-name-length-validation-error" msgid "workspace.tokens.token-name-length-validation-error"
msgstr "El nombre debería ser de al menos 1 caracter" msgstr "El nombre debería ser de al menos 1 caracter"