mirror of
https://github.com/penpot/penpot.git
synced 2026-09-10 14:09:17 +00:00
🔧 Add tokenscript flag and more validations to token values
This commit is contained in:
parent
72a855d4ac
commit
ba87ea1a44
@ -760,6 +760,21 @@
|
|||||||
default
|
default
|
||||||
v))))
|
v))))
|
||||||
|
|
||||||
|
(defn percent?
|
||||||
|
[v]
|
||||||
|
(str/numeric? (str/rtrim v "%")))
|
||||||
|
|
||||||
|
(defn parse-percent
|
||||||
|
([v]
|
||||||
|
(parse-percent v nil))
|
||||||
|
([v default]
|
||||||
|
(if (str/ends-with? v "%")
|
||||||
|
(let [v (impl-parse-double (str/trim v "%"))]
|
||||||
|
(if (or (nil? v) (nan? v))
|
||||||
|
default
|
||||||
|
(/ v 100)))
|
||||||
|
(parse-double v default))))
|
||||||
|
|
||||||
(defn parse-uuid
|
(defn parse-uuid
|
||||||
[v]
|
[v]
|
||||||
(try
|
(try
|
||||||
|
|||||||
@ -31,18 +31,56 @@
|
|||||||
(def schema:token-value-generic
|
(def schema:token-value-generic
|
||||||
[::sm/text {:error/fn token-value-empty-fn}])
|
[::sm/text {:error/fn token-value-empty-fn}])
|
||||||
|
|
||||||
|
(def schema:token-value-numeric
|
||||||
|
[:and
|
||||||
|
[::sm/text {:error/fn token-value-empty-fn}]
|
||||||
|
[:fn {:error/fn #(tr "workspace.tokens.invalid-value" (:value %))}
|
||||||
|
(fn [value]
|
||||||
|
(if (str/numeric? value)
|
||||||
|
(let [n (d/parse-double value)]
|
||||||
|
(some? n))
|
||||||
|
true))]]) ;; Leave references or formulas to be checked by the resolver
|
||||||
|
|
||||||
|
(def schema:token-value-percent
|
||||||
|
[:and
|
||||||
|
[::sm/text {:error/fn token-value-empty-fn}]
|
||||||
|
[:fn {:error/fn #(tr "workspace.tokens.value-with-percent" (:value %))}
|
||||||
|
(fn [value]
|
||||||
|
(if (d/percent? value)
|
||||||
|
(let [v (d/parse-percent value)]
|
||||||
|
(some? v))
|
||||||
|
true))]]) ;; Leave references or formulas to be checked by the resolver
|
||||||
|
|
||||||
(def schema:token-value-composite-ref
|
(def schema:token-value-composite-ref
|
||||||
[::sm/text {:error/fn token-value-empty-fn}])
|
[::sm/text {:error/fn token-value-empty-fn}])
|
||||||
|
|
||||||
|
(def schema:token-value-opacity
|
||||||
|
[:and
|
||||||
|
[::sm/text {:error/fn token-value-empty-fn}]
|
||||||
|
[:fn {:error/fn #(tr "workspace.tokens.opacity-range")}
|
||||||
|
(fn [opacity]
|
||||||
|
(if (str/numeric? opacity)
|
||||||
|
(let [n (d/parse-percent opacity)]
|
||||||
|
(and (some? n) (<= 0 n 1)))
|
||||||
|
true))]]) ;; Leave references or formulas to be checked by the resolver
|
||||||
|
|
||||||
(def schema:token-value-font-family
|
(def schema:token-value-font-family
|
||||||
[:vector ::sm/text])
|
[:or
|
||||||
|
[:vector ::sm/text]
|
||||||
|
cto/schema:token-ref])
|
||||||
|
|
||||||
|
(def schema:token-value-font-weight
|
||||||
|
[:or
|
||||||
|
[:fn {:error/fn #(tr "workspace.tokens.invalid-font-weight-token-value")}
|
||||||
|
cto/valid-font-weight-variant]
|
||||||
|
::sm/text]) ;; Leave references or formulas to be checked by the resolver
|
||||||
|
|
||||||
(def schema:token-value-typography-map
|
(def schema:token-value-typography-map
|
||||||
[:map
|
[:map
|
||||||
[:font-family {:optional true} schema:token-value-font-family]
|
[:font-family {:optional true} schema:token-value-font-family]
|
||||||
[:font-weight {:optional true} schema:token-value-generic]
|
[:font-size {:optional true} schema:token-value-numeric]
|
||||||
[:font-size {:optional true} schema:token-value-generic]
|
[:font-weight {:optional true} schema:token-value-font-weight]
|
||||||
[:line-height {:optional true} schema:token-value-generic]
|
[:line-height {:optional true} schema:token-value-percent]
|
||||||
[:letter-spacing {:optional true} schema:token-value-generic]
|
[:letter-spacing {:optional true} schema:token-value-generic]
|
||||||
[:paragraph-spacing {:optional true} schema:token-value-generic]
|
[:paragraph-spacing {:optional true} schema:token-value-generic]
|
||||||
[:text-decoration {:optional true} schema:token-value-generic]
|
[:text-decoration {:optional true} schema:token-value-generic]
|
||||||
@ -84,7 +122,10 @@
|
|||||||
[token-type]
|
[token-type]
|
||||||
[:multi {:dispatch (constantly token-type)
|
[:multi {:dispatch (constantly token-type)
|
||||||
:title "Token Value"}
|
:title "Token Value"}
|
||||||
|
[:opacity schema:token-value-opacity]
|
||||||
[:font-family schema:token-value-font-family]
|
[:font-family schema:token-value-font-family]
|
||||||
|
[:font-size schema:token-value-numeric]
|
||||||
|
[:font-weight schema:token-value-font-weight]
|
||||||
[:typography schema:token-value-typography]
|
[:typography schema:token-value-typography]
|
||||||
[:shadow schema:token-value-shadow]
|
[:shadow schema:token-value-shadow]
|
||||||
[::m/default schema:token-value-generic]])
|
[::m/default schema:token-value-generic]])
|
||||||
@ -169,7 +210,7 @@
|
|||||||
[tokens-lib set-id]
|
[tokens-lib set-id]
|
||||||
[:and
|
[:and
|
||||||
[:string {:min 1 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
|
[:string {:min 1 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
|
||||||
[:fn {:error/fn #(tr "errors.token-set-already-exists" (:value %))}
|
[:fn {:error/fn #(tr "errors.token-set-already-exists")}
|
||||||
(fn [name]
|
(fn [name]
|
||||||
(or (nil? tokens-lib)
|
(or (nil? tokens-lib)
|
||||||
(let [set (ctob/get-set-by-name tokens-lib name)]
|
(let [set (ctob/get-set-by-name tokens-lib name)]
|
||||||
@ -196,7 +237,7 @@
|
|||||||
[tokens-lib name theme-id]
|
[tokens-lib name theme-id]
|
||||||
[:and
|
[:and
|
||||||
[:string {:min 0 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
|
[:string {:min 0 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
|
||||||
[:fn {:error/fn #(tr "errors.token-theme-already-exists" (:value %))}
|
[:fn {:error/fn #(tr "errors.token-theme-already-exists")}
|
||||||
(fn [group]
|
(fn [group]
|
||||||
(or (nil? tokens-lib)
|
(or (nil? tokens-lib)
|
||||||
(let [theme (ctob/get-theme-by-name tokens-lib group name)]
|
(let [theme (ctob/get-theme-by-name tokens-lib group name)]
|
||||||
|
|||||||
@ -143,6 +143,15 @@
|
|||||||
:gen/gen sg/text}
|
:gen/gen sg/text}
|
||||||
token-name-validation-regex])
|
token-name-validation-regex])
|
||||||
|
|
||||||
|
(def token-ref-validation-regex
|
||||||
|
#"^\{[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*\}$")
|
||||||
|
|
||||||
|
(def schema:token-ref
|
||||||
|
"A token reference is a token name enclosed in {}."
|
||||||
|
[:re {:title "TokenRef"
|
||||||
|
:gen/gen sg/text}
|
||||||
|
token-ref-validation-regex])
|
||||||
|
|
||||||
(def schema:token-type
|
(def schema:token-type
|
||||||
[::sm/one-of {:decode/json (fn [type]
|
[::sm/one-of {:decode/json (fn [type]
|
||||||
(if (string? type)
|
(if (string? type)
|
||||||
|
|||||||
@ -69,6 +69,10 @@
|
|||||||
(and (number-with-unit-symbol? v)
|
(and (number-with-unit-symbol? v)
|
||||||
(= (.-unit v) "rem")))
|
(= (.-unit v) "rem")))
|
||||||
|
|
||||||
|
(defn percent-number-with-unit? [v]
|
||||||
|
(and (number-with-unit-symbol? v)
|
||||||
|
(= (.-unit v) "%")))
|
||||||
|
|
||||||
(defn rem->px [^js v]
|
(defn rem->px [^js v]
|
||||||
(* (.-value v) 16))
|
(* (.-value v) 16))
|
||||||
|
|
||||||
@ -87,10 +91,12 @@
|
|||||||
|
|
||||||
(defn tokenscript-symbols->penpot-unit [^js v]
|
(defn tokenscript-symbols->penpot-unit [^js v]
|
||||||
(cond
|
(cond
|
||||||
|
(nil? v) nil
|
||||||
(structured-token? v) (structured-token->penpot-map v)
|
(structured-token? v) (structured-token->penpot-map v)
|
||||||
(list-symbol? v) (structured-token->penpot-map v)
|
(list-symbol? v) (structured-token->penpot-map v)
|
||||||
(color-symbol? v) (.-value (.to v "hex"))
|
(color-symbol? v) (.-value (.to v "hex"))
|
||||||
(rem-number-with-unit? v) (rem->px v)
|
(rem-number-with-unit? v) (rem->px v)
|
||||||
|
(percent-number-with-unit? v) (/ (.-value v) 100)
|
||||||
:else (.-value v)))
|
:else (.-value v)))
|
||||||
|
|
||||||
;; Processors ------------------------------------------------------------------
|
;; Processors ------------------------------------------------------------------
|
||||||
|
|||||||
@ -8,10 +8,11 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.json :as json]
|
[app.common.json :as json]
|
||||||
[app.common.path-names :as cpn]
|
[app.common.path-names :as cpn]
|
||||||
|
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.tokens.errors :as wte]
|
[app.main.data.workspace.tokens.errors :as wte]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
@ -74,15 +75,18 @@
|
|||||||
(when unknown-tokens
|
(when unknown-tokens
|
||||||
(st/emit! (show-unknown-types-warning unknown-tokens)))
|
(st/emit! (show-unknown-types-warning unknown-tokens)))
|
||||||
(try
|
(try
|
||||||
(->> (ctob/get-all-tokens-map tokens-lib)
|
(let [tokens-tree (ctob/get-all-tokens-map tokens-lib)
|
||||||
(sd/resolve-tokens-with-verbose-errors)
|
resolved-tokens (if (contains? cf/flags :tokenscript)
|
||||||
(rx/map (fn [_]
|
(rx/of (ts/resolve-tokens tokens-tree))
|
||||||
tokens-lib))
|
(sd/resolve-tokens-with-verbose-errors tokens-tree))]
|
||||||
(rx/catch (fn [sd-error]
|
(->> resolved-tokens
|
||||||
(let [reference-errors (extract-reference-errors sd-error)]
|
(rx/map (fn [_]
|
||||||
(if reference-errors
|
tokens-lib))
|
||||||
(rx/of tokens-lib)
|
(rx/catch (fn [sd-error]
|
||||||
(throw (wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error)))))))
|
(let [reference-errors (extract-reference-errors sd-error)]
|
||||||
|
(if reference-errors
|
||||||
|
(rx/of tokens-lib)
|
||||||
|
(throw (wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error))))))))
|
||||||
(catch js/Error e
|
(catch js/Error e
|
||||||
(throw (wte/error-ex-info :error.import/style-dictionary-unknown-error "" e)))))
|
(throw (wte/error-ex-info :error.import/style-dictionary-unknown-error "" e)))))
|
||||||
|
|
||||||
|
|||||||
@ -6,13 +6,16 @@
|
|||||||
|
|
||||||
(ns app.main.data.workspace.tokens.propagation
|
(ns app.main.data.workspace.tokens.propagation
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.time :as ct]
|
[app.common.time :as ct]
|
||||||
[app.common.types.token :as ctt]
|
[app.common.types.token :as ctt]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
[app.main.data.workspace.thumbnails :as dwt]
|
[app.main.data.workspace.thumbnails :as dwt]
|
||||||
[app.main.data.workspace.tokens.application :as dwta]
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
@ -210,10 +213,13 @@
|
|||||||
(ptk/reify ::propagate-workspace-tokens
|
(ptk/reify ::propagate-workspace-tokens
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(when-let [tokens-lib (-> (dsh/lookup-file-data state)
|
(when-let [tokens-tree (-> (dsh/lookup-file-data state)
|
||||||
(get :tokens-lib))]
|
(get :tokens-lib)
|
||||||
(->> (ctob/get-tokens-in-active-sets tokens-lib)
|
(ctob/get-tokens-in-active-sets))]
|
||||||
(sd/resolve-tokens)
|
(->> (if (contains? cf/flags :tokenscript)
|
||||||
|
(rx/of (-> (ts/resolve-tokens tokens-tree)
|
||||||
|
(d/update-vals #(update % :resolved-value ts/tokenscript-symbols->penpot-unit))))
|
||||||
|
(sd/resolve-tokens tokens-tree))
|
||||||
(rx/mapcat (fn [sd-tokens]
|
(rx/mapcat (fn [sd-tokens]
|
||||||
(let [undo-id (js/Symbol)]
|
(let [undo-id (js/Symbol)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
|
|||||||
@ -143,8 +143,7 @@
|
|||||||
(let [token-ids (set tokens-in-path-ids)
|
(let [token-ids (set tokens-in-path-ids)
|
||||||
remaining-tokens (filter (fn [token]
|
remaining-tokens (filter (fn [token]
|
||||||
(not (contains? token-ids (:id token))))
|
(not (contains? token-ids (:id token))))
|
||||||
selected-token-set-tokens)
|
selected-token-set-tokens)]
|
||||||
_ (prn "Remaining tokens:" remaining-tokens)]
|
|
||||||
(seq remaining-tokens))))
|
(seq remaining-tokens))))
|
||||||
|
|
||||||
delete-token
|
delete-token
|
||||||
|
|||||||
@ -13,8 +13,10 @@
|
|||||||
[app.common.types.color :as cl]
|
[app.common.types.color :as cl]
|
||||||
[app.common.types.token :as cto]
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
[app.main.data.tinycolor :as tinycolor]
|
[app.main.data.tinycolor :as tinycolor]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.tokens.format :as dwtf]
|
[app.main.data.workspace.tokens.format :as dwtf]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.ui.ds.controls.input :as ds]
|
[app.main.ui.ds.controls.input :as ds]
|
||||||
@ -70,11 +72,15 @@
|
|||||||
(dissoc (:name prev-token))
|
(dissoc (:name prev-token))
|
||||||
(update (:name token) #(ctob/make-token (merge % prev-token token))))]
|
(update (:name token) #(ctob/make-token (merge % prev-token token))))]
|
||||||
|
|
||||||
(->> tokens
|
(->> (if (contains? cf/flags :tokenscript)
|
||||||
(sd/resolve-tokens-interactive)
|
(rx/of (ts/resolve-tokens tokens))
|
||||||
|
(sd/resolve-tokens-interactive tokens))
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [resolved-tokens]
|
(fn [resolved-tokens]
|
||||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))]
|
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))
|
||||||
|
resolved-value (if (contains? cf/flags :tokenscript)
|
||||||
|
(ts/tokenscript-symbols->penpot-unit resolved-value)
|
||||||
|
resolved-value)]
|
||||||
(if resolved-value
|
(if resolved-value
|
||||||
(rx/of {:value resolved-value})
|
(rx/of {:value resolved-value})
|
||||||
(rx/of {:error (first errors)}))))))))
|
(rx/of {:error (first errors)}))))))))
|
||||||
|
|||||||
@ -10,7 +10,9 @@
|
|||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.types.token :as cto]
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.controls.input :refer [input*]]
|
[app.main.ui.ds.controls.input :refer [input*]]
|
||||||
@ -49,28 +51,30 @@
|
|||||||
;; validate data within the form state.
|
;; validate data within the form state.
|
||||||
|
|
||||||
(defn- resolve-value
|
(defn- resolve-value
|
||||||
[tokens prev-token token-name value]
|
[tokens prev-token _token-name value]
|
||||||
(let [valid-token-name?
|
(let [tmp-value (cto/split-font-family value)
|
||||||
(and (string? token-name)
|
tmp-name "__PENPOT__FONT_FAMILY__PLACEHOLDER__"
|
||||||
(re-matches cto/token-name-validation-regex token-name))
|
|
||||||
|
|
||||||
|
;; Create a temporary font-family token to validate the value
|
||||||
token
|
token
|
||||||
{:value (cto/split-font-family value)
|
{:name tmp-name
|
||||||
:name (if (or (not valid-token-name?) (str/blank? token-name))
|
:type :font-family
|
||||||
"__PENPOT__TOKEN__NAME__PLACEHOLDER__"
|
:value (if (= (:type prev-token) :typography)
|
||||||
token-name)}
|
(assoc (:value prev-token) :font-family tmp-value)
|
||||||
|
tmp-value)}
|
||||||
|
|
||||||
tokens
|
tokens
|
||||||
(-> tokens
|
(update tokens (:name token) #(ctob/make-token (merge % prev-token token)))]
|
||||||
;; Remove previous token when renaming a token
|
|
||||||
(dissoc (:name prev-token))
|
|
||||||
(update (:name token) #(ctob/make-token (merge % prev-token token))))]
|
|
||||||
|
|
||||||
(->> tokens
|
(->> (if (contains? cf/flags :tokenscript)
|
||||||
(sd/resolve-tokens-interactive)
|
(rx/of (ts/resolve-tokens tokens))
|
||||||
|
(sd/resolve-tokens-interactive tokens))
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [resolved-tokens]
|
(fn [resolved-tokens]
|
||||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))]
|
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))
|
||||||
|
resolved-value (if (contains? cf/flags :tokenscript)
|
||||||
|
(ts/tokenscript-symbols->penpot-unit resolved-value)
|
||||||
|
resolved-value)]
|
||||||
(if resolved-value
|
(if resolved-value
|
||||||
(rx/of {:value resolved-value})
|
(rx/of {:value resolved-value})
|
||||||
(rx/of {:error (first errors)}))))))))
|
(rx/of {:error (first errors)}))))))))
|
||||||
@ -176,7 +180,6 @@
|
|||||||
(let [message (tr "workspace.tokens.resolved-value" value)]
|
(let [message (tr "workspace.tokens.resolved-value" value)]
|
||||||
(swap! form update :extra-errors dissoc input-name)
|
(swap! form update :extra-errors dissoc input-name)
|
||||||
(reset! hint* {:message message :type "hint"})))))))]
|
(reset! hint* {:message message :type "hint"})))))))]
|
||||||
|
|
||||||
(fn []
|
(fn []
|
||||||
(rx/dispose! subs))))
|
(rx/dispose! subs))))
|
||||||
|
|
||||||
|
|||||||
@ -175,7 +175,10 @@
|
|||||||
(sd/resolve-tokens-interactive)
|
(sd/resolve-tokens-interactive)
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [resolved-tokens]
|
(fn [resolved-tokens]
|
||||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))]
|
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))
|
||||||
|
resolved-value (if (contains? cf/flags :tokenscript)
|
||||||
|
(ts/tokenscript-symbols->penpot-unit resolved-value)
|
||||||
|
resolved-value)]
|
||||||
(if resolved-value
|
(if resolved-value
|
||||||
(rx/of {:value resolved-value})
|
(rx/of {:value resolved-value})
|
||||||
(rx/of {:error (first errors)}))))))))
|
(rx/of {:error (first errors)}))))))))
|
||||||
|
|||||||
@ -36,9 +36,9 @@
|
|||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn get-value-for-validator
|
(defn get-value-for-validator
|
||||||
[active-tab value value-subfield form-type]
|
[active-tab value value-subfield value-type]
|
||||||
|
|
||||||
(case form-type
|
(case value-type
|
||||||
:indexed
|
:indexed
|
||||||
(if (= active-tab :reference)
|
(if (= active-tab :reference)
|
||||||
(:reference value)
|
(:reference value)
|
||||||
@ -62,7 +62,7 @@
|
|||||||
make-schema
|
make-schema
|
||||||
input-component
|
input-component
|
||||||
initial
|
initial
|
||||||
type
|
value-type
|
||||||
value-subfield
|
value-subfield
|
||||||
input-value-placeholder] :as props}]
|
input-value-placeholder] :as props}]
|
||||||
|
|
||||||
@ -178,13 +178,13 @@
|
|||||||
|
|
||||||
on-submit
|
on-submit
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps validate-token token tokens token-type value-subfield type active-tab on-remap-token on-rename-token is-create)
|
(mf/deps validate-token token tokens token-type value-subfield value-type active-tab on-remap-token on-rename-token is-create)
|
||||||
(fn [form _event]
|
(fn [form _event]
|
||||||
(let [name (get-in @form [:clean-data :name])
|
(let [name (get-in @form [:clean-data :name])
|
||||||
path (str (d/name token-type) "." name)
|
path (str (d/name token-type) "." name)
|
||||||
description (get-in @form [:clean-data :description])
|
description (get-in @form [:clean-data :description])
|
||||||
value (get-in @form [:clean-data :value])
|
value (get-in @form [:clean-data :value])
|
||||||
value-for-validation (get-value-for-validator active-tab value value-subfield type)]
|
value-for-validation (get-value-for-validator active-tab value value-subfield value-type)]
|
||||||
(->> (validate-token {:token-value value-for-validation
|
(->> (validate-token {:token-value value-for-validation
|
||||||
:token-name name
|
:token-name name
|
||||||
:token-description description
|
:token-description description
|
||||||
@ -245,7 +245,7 @@
|
|||||||
:auto-focus true}]]
|
:auto-focus true}]]
|
||||||
|
|
||||||
[:div {:class (stl/css :input-row)}
|
[:div {:class (stl/css :input-row)}
|
||||||
(case type
|
(case value-type
|
||||||
:indexed
|
:indexed
|
||||||
[:> input-component
|
[:> input-component
|
||||||
{:token token
|
{:token token
|
||||||
|
|||||||
@ -365,7 +365,7 @@
|
|||||||
:token-type token-type
|
:token-type token-type
|
||||||
:initial initial
|
:initial initial
|
||||||
:make-schema make-schema
|
:make-schema make-schema
|
||||||
:type :indexed
|
:value-type :indexed
|
||||||
:value-subfield :shadow
|
:value-subfield :shadow
|
||||||
:input-component tabs-wrapper*
|
:input-component tabs-wrapper*
|
||||||
:validator validate-shadow-token})]
|
:validator validate-shadow-token})]
|
||||||
|
|||||||
@ -300,6 +300,6 @@
|
|||||||
:make-schema make-schema
|
:make-schema make-schema
|
||||||
:token token
|
:token token
|
||||||
:validator validate-typography-token
|
:validator validate-typography-token
|
||||||
:type :composite
|
:value-type :composite
|
||||||
:input-component tabs-wrapper*})]
|
:input-component tabs-wrapper*})]
|
||||||
[:> generic/form* props]))
|
[:> generic/form* props]))
|
||||||
|
|||||||
@ -4,7 +4,9 @@
|
|||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.token :as cto]
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.style-dictionary :as sd]
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.tokens.errors :as wte]
|
[app.main.data.workspace.tokens.errors :as wte]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
@ -36,14 +38,20 @@
|
|||||||
|
|
||||||
:always
|
:always
|
||||||
(update (:name token) #(ctob/make-token (merge % prev-token token))))]
|
(update (:name token) #(ctob/make-token (merge % prev-token token))))]
|
||||||
(->> tokens'
|
|
||||||
(sd/resolve-tokens-interactive)
|
(->> (if (contains? cf/flags :tokenscript)
|
||||||
|
(rx/of (ts/resolve-tokens tokens'))
|
||||||
|
(sd/resolve-tokens-interactive tokens'))
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [resolved-tokens]
|
(fn [resolved-tokens]
|
||||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))]
|
(let [resolved-token (cond-> (get resolved-tokens (:name token))
|
||||||
|
(contains? cf/flags :tokenscript)
|
||||||
|
(update :resolved-value ts/tokenscript-symbols->penpot-unit))]
|
||||||
(cond
|
(cond
|
||||||
resolved-value (rx/of resolved-token)
|
(:resolved-value resolved-token)
|
||||||
:else (rx/throw {:errors (or (seq errors)
|
(rx/of resolved-token)
|
||||||
|
|
||||||
|
:else (rx/throw {:errors (or (seq (:errors resolved-token))
|
||||||
[(wte/get-error-code :error/unknown-error)])}))))))))
|
[(wte/get-error-code :error/unknown-error)])}))))))))
|
||||||
|
|
||||||
(defn- validate-token-with [token validators]
|
(defn- validate-token-with [token validators]
|
||||||
|
|||||||
@ -176,9 +176,10 @@
|
|||||||
(mf/defc token-pill*
|
(mf/defc token-pill*
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [on-click token on-context-menu selected-shapes is-selected-inside-layout active-theme-tokens]}]
|
[{:keys [on-click token on-context-menu selected-shapes is-selected-inside-layout active-theme-tokens]}]
|
||||||
(let [{:keys [name value errors type]} token
|
(let [{:keys [name value type]} token
|
||||||
|
|
||||||
resolved-token (get active-theme-tokens (:name token))
|
resolved-token (get active-theme-tokens (:name token))
|
||||||
|
errors (:errors resolved-token)
|
||||||
|
|
||||||
has-selected? (pos? (count selected-shapes))
|
has-selected? (pos? (count selected-shapes))
|
||||||
is-reference? (cfo/is-reference? token)
|
is-reference? (cfo/is-reference? token)
|
||||||
|
|||||||
@ -12,14 +12,12 @@
|
|||||||
[app.common.types.token :as cto]
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.style-dictionary :as sd]
|
|
||||||
[app.main.data.tokenscript :as ts]
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.tokens.application :as dwta]
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.utils :as u]
|
[app.plugins.utils :as u]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[beicon.v2.core :as rx]
|
|
||||||
[clojure.datafy :refer [datafy]]))
|
[clojure.datafy :refer [datafy]]))
|
||||||
|
|
||||||
;; === Token
|
;; === Token
|
||||||
@ -260,20 +258,19 @@
|
|||||||
:decode/options {:key-fn identity}
|
:decode/options {:key-fn identity}
|
||||||
:fn (fn [attrs]
|
:fn (fn [attrs]
|
||||||
(let [tokens-lib (u/locate-tokens-lib file-id)
|
(let [tokens-lib (u/locate-tokens-lib file-id)
|
||||||
tokens-tree (ctob/get-tokens-in-active-sets tokens-lib)
|
token (ctob/make-token attrs)
|
||||||
token (ctob/make-token attrs)]
|
tokens-tree (-> (ctob/get-tokens-in-active-sets tokens-lib)
|
||||||
(->> (assoc tokens-tree (:name token) token)
|
(assoc (:name token) token))
|
||||||
(sd/resolve-tokens-interactive)
|
resolved-tokens (ts/resolve-tokens tokens-tree)
|
||||||
(rx/subs!
|
|
||||||
(fn [resolved-tokens]
|
{:keys [errors resolved-value] :as resolved-token}
|
||||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))]
|
(get resolved-tokens (:name token))]
|
||||||
(if resolved-value
|
|
||||||
(st/emit! (dwtl/create-token id token))
|
(if resolved-value
|
||||||
(u/display-not-valid :addToken (str errors)))))))
|
(do (st/emit! (dwtl/create-token id token))
|
||||||
;; TODO: as the addToken function is synchronous, we must return the newly created
|
(token-proxy plugin-id file-id id (:id token)))
|
||||||
;; token even if the validator will throw it away if the resolution fails.
|
(do (u/display-not-valid :addToken (str errors))
|
||||||
;; This will be solved with the TokenScript resolver, that is syncronous.
|
nil))))}
|
||||||
(token-proxy plugin-id file-id id (:id token))))}
|
|
||||||
|
|
||||||
:duplicate
|
:duplicate
|
||||||
(fn []
|
(fn []
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user