mirror of
https://github.com/penpot/penpot.git
synced 2025-02-23 15:26:29 -05:00
✨ Add validation to token opacity (#5802)
This commit is contained in:
parent
8b7a102927
commit
6692f8dce2
5 changed files with 92 additions and 9 deletions
|
@ -35,6 +35,11 @@
|
|||
{:error/code :error.style-dictionary/invalid-token-value
|
||||
:error/fn #(str "Invalid token value: " %)}
|
||||
|
||||
:error.style-dictionary/invalid-token-value-opacity
|
||||
{:error/code :error.style-dictionary/invalid-token-value-opacity
|
||||
:error/fn #(str/join "\n" [(str "Invalid token value: " % ".") "Opacity must be between 0 and 100% or 0 and 1 (e.g. 50% or 0.5)"])}
|
||||
|
||||
|
||||
:error/unknown
|
||||
{:error/code :error/unknown
|
||||
:error/message "Unknown error"}})
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.main.ui.workspace.tokens.token-types :as wtty]
|
||||
[app.main.ui.workspace.tokens.update :as wtu]
|
||||
[app.main.ui.workspace.tokens.warnings :as wtw]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.functions :as uf]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -198,18 +199,21 @@
|
|||
|
||||
(mf/defc token-value-or-errors
|
||||
[{:keys [result-or-errors]}]
|
||||
(let [{:keys [errors]} result-or-errors
|
||||
(let [{:keys [errors warnings resolved-value]} result-or-errors
|
||||
empty-message? (or (nil? result-or-errors)
|
||||
(wte/has-error-code? :error/empty-input errors))
|
||||
|
||||
message (cond
|
||||
empty-message? (tr "workspace.token.resolved-value" "-")
|
||||
warnings (wtw/humanize-warnings warnings)
|
||||
errors (->> (wte/humanize-errors errors)
|
||||
(str/join "\n"))
|
||||
:else (tr "workspace.token.resolved-value" result-or-errors))]
|
||||
:else (tr "workspace.token.resolved-value" (or resolved-value result-or-errors)))]
|
||||
[:> text* {:as "p"
|
||||
:typography "body-small"
|
||||
:class (stl/css-case :resolved-value true
|
||||
:resolved-value-placeholder empty-message?
|
||||
:resolved-value-warning (seq warnings)
|
||||
:resolved-value-error (seq errors))}
|
||||
message]))
|
||||
|
||||
|
@ -227,6 +231,7 @@
|
|||
token-path (mf/use-memo
|
||||
(mf/deps (:name token))
|
||||
#(wtt/token-name->path (:name token)))
|
||||
|
||||
selected-set-tokens-tree (mf/use-memo
|
||||
(mf/deps token-path selected-set-tokens)
|
||||
(fn []
|
||||
|
@ -294,14 +299,20 @@
|
|||
color-ramp-open? (deref color-ramp-open*)
|
||||
value-input-ref (mf/use-ref nil)
|
||||
value-ref (mf/use-var (:value token))
|
||||
token-resolve-result* (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value]))
|
||||
|
||||
token-resolve-result* (mf/use-state (get resolved-tokens (wtt/token-identifier token)))
|
||||
token-resolve-result (deref token-resolve-result*)
|
||||
set-resolve-value
|
||||
(mf/use-fn
|
||||
(fn [token-or-err]
|
||||
(let [error? (:errors token-or-err)
|
||||
v (if error?
|
||||
warnings? (:warnings token-or-err)
|
||||
v (cond
|
||||
error?
|
||||
token-or-err
|
||||
warnings?
|
||||
(:warnings {:warnings token-or-err})
|
||||
:else
|
||||
(:resolved-value token-or-err))]
|
||||
(when color? (reset! color (if error? nil v)))
|
||||
(reset! token-resolve-result* v))))
|
||||
|
@ -333,6 +344,7 @@
|
|||
(on-display-colorpicker open?))))
|
||||
|
||||
value-error? (seq (:errors token-resolve-result))
|
||||
|
||||
valid-value-field? (and
|
||||
(not value-error?)
|
||||
(valid-value? token-resolve-result))
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
margin-bottom: 0;
|
||||
padding: $s-4 $s-6;
|
||||
color: var(--input-hint-color);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.resolved-value-placeholder {
|
||||
|
@ -63,6 +64,10 @@
|
|||
--input-hint-color: var(--status-color-error-500);
|
||||
}
|
||||
|
||||
.resolved-value-warning {
|
||||
--input-hint-color: var(--status-color-warning-500);
|
||||
}
|
||||
|
||||
.form-modal-title {
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.main.ui.workspace.tokens.errors :as wte]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.main.ui.workspace.tokens.warnings :as wtw]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.core :as p]
|
||||
|
@ -59,6 +60,31 @@
|
|||
:references references}
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]})))
|
||||
|
||||
(defn parse-sd-token-opacity-value
|
||||
"Parses `value` of a dimensions `sd-token` into a map like `{:value 1 :unit \"px\"}`.
|
||||
If the `value` is not parseable and/or has missing references returns a map with `:errors`.
|
||||
If the `value` is parseable but is out of range returns a map with `warnings`."
|
||||
[value has-references?]
|
||||
|
||||
(let [parsed-value (wtt/parse-token-value value)
|
||||
out-of-scope (< 100 (:value parsed-value))
|
||||
references (seq (ctob/find-token-value-references value))]
|
||||
(cond
|
||||
(and parsed-value (not out-of-scope))
|
||||
parsed-value
|
||||
|
||||
references
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)]
|
||||
:references references}
|
||||
|
||||
(and (not has-references?) out-of-scope)
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-opacity value)]}
|
||||
|
||||
(and has-references? out-of-scope)
|
||||
(assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value value)])
|
||||
|
||||
:else {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]})))
|
||||
|
||||
(defn process-sd-tokens
|
||||
"Converts a StyleDictionary dictionary with resolved tokens (aka `sd-tokens`) back to clojure.
|
||||
The `get-origin-token` argument should be a function that takes an
|
||||
|
@ -95,14 +121,22 @@
|
|||
(fn [acc ^js sd-token]
|
||||
(let [origin-token (get-origin-token sd-token)
|
||||
value (.-value sd-token)
|
||||
has-references? (str/includes? (:value origin-token) "{")
|
||||
parsed-token-value (case (:type origin-token)
|
||||
:color (parse-sd-token-color-value value)
|
||||
:opacity (parse-sd-token-opacity-value value has-references?)
|
||||
(parse-sd-token-dimensions-value value))
|
||||
output-token (if (:errors parsed-token-value)
|
||||
(merge origin-token parsed-token-value)
|
||||
(assoc origin-token
|
||||
:resolved-value (:value parsed-token-value)
|
||||
:unit (:unit parsed-token-value)))]
|
||||
output-token (cond (:errors parsed-token-value)
|
||||
(merge origin-token parsed-token-value)
|
||||
(:warnings parsed-token-value)
|
||||
(assoc origin-token
|
||||
:resolved-value (:value parsed-token-value)
|
||||
:warnings (:warnings parsed-token-value)
|
||||
:unit (:unit parsed-token-value))
|
||||
:else
|
||||
(assoc origin-token
|
||||
:resolved-value (:value parsed-token-value)
|
||||
:unit (:unit parsed-token-value)))]
|
||||
(assoc acc (:name output-token) output-token)))
|
||||
{} sd-tokens))
|
||||
|
||||
|
|
27
frontend/src/app/main/ui/workspace/tokens/warnings.cljs
Normal file
27
frontend/src/app/main/ui/workspace/tokens/warnings.cljs
Normal file
|
@ -0,0 +1,27 @@
|
|||
(ns app.main.ui.workspace.tokens.warnings
|
||||
(:require
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(def warning-codes
|
||||
{:warning.style-dictionary/invalid-referenced-token-value
|
||||
{:warning/code :warning.style-dictionary/invalid-referenced-token-value
|
||||
:warning/fn (fn [value] (str/join "\n" [(str "Resolved value " value ".") "Opacity must be between 0 and 100% or 0 and 1 (e.g. 50% or 0.5)"]))}
|
||||
|
||||
:warning/unknown
|
||||
{:warning/code :warning/unknown
|
||||
:warning/message "Unknown warning"}})
|
||||
|
||||
(defn get-warning-code [warning-key]
|
||||
(get warning-codes warning-key (:warning/unknown warning-codes)))
|
||||
|
||||
(defn warning-with-value [warning-key warning-value]
|
||||
(-> (get-warning-code warning-key)
|
||||
(assoc :warning/value warning-value)))
|
||||
|
||||
(defn humanize-warnings [warnings]
|
||||
(->> warnings
|
||||
(map (fn [warn]
|
||||
(cond
|
||||
(:warning/fn warn) ((:warning/fn warn) (:warning/value warn))
|
||||
(:warning/message warn) (:warning/message warn)
|
||||
:else warn)))))
|
Loading…
Add table
Reference in a new issue