mirror of
https://github.com/penpot/penpot.git
synced 2025-01-21 14:12:36 -05:00
Move callback function to component
This commit is contained in:
parent
28f25da9e8
commit
c98162d0bf
3 changed files with 55 additions and 66 deletions
|
@ -14,6 +14,7 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[malli.core :as m]
|
[malli.core :as m]
|
||||||
[malli.error :as me]
|
[malli.error :as me]
|
||||||
|
[promesa.core :as p]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
;; Schemas ---------------------------------------------------------------------
|
;; Schemas ---------------------------------------------------------------------
|
||||||
|
@ -33,11 +34,6 @@
|
||||||
[:string {:min 1 :max 255}]
|
[:string {:min 1 :max 255}]
|
||||||
non-existing-token-schema])))
|
non-existing-token-schema])))
|
||||||
|
|
||||||
(comment
|
|
||||||
(-> (m/explain (token-name-schema #{"foo"}) nil)
|
|
||||||
(me/humanize))
|
|
||||||
nil)
|
|
||||||
|
|
||||||
;; Helpers ---------------------------------------------------------------------
|
;; Helpers ---------------------------------------------------------------------
|
||||||
|
|
||||||
(defn finalize-name [name]
|
(defn finalize-name [name]
|
||||||
|
@ -46,6 +42,57 @@
|
||||||
(defn finalize-value [name]
|
(defn finalize-value [name]
|
||||||
(str/trim name))
|
(str/trim name))
|
||||||
|
|
||||||
|
;; Component -------------------------------------------------------------------
|
||||||
|
|
||||||
|
(defn use-debonced-resolve-callback
|
||||||
|
[name-ref token tokens callback & {:keys [cached timeout]
|
||||||
|
:or {cached {}
|
||||||
|
timeout 160}}]
|
||||||
|
(let [timeout-id-ref (mf/use-ref nil)
|
||||||
|
cache (mf/use-ref cached)
|
||||||
|
debounced-resolver-callback
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps token callback tokens)
|
||||||
|
(fn [event]
|
||||||
|
(let [input (dom/get-target-val event)
|
||||||
|
timeout-id (js/Symbol)
|
||||||
|
;; Dont execute callback when the timout-id-ref is outdated because this function got called again
|
||||||
|
timeout-outdated-cb? #(not= (mf/ref-val timeout-id-ref) timeout-id)]
|
||||||
|
(mf/set-ref-val! timeout-id-ref timeout-id)
|
||||||
|
(js/setTimeout
|
||||||
|
(fn []
|
||||||
|
(when (not (timeout-outdated-cb?))
|
||||||
|
(if-let [cached (get (mf/ref-val cache) tokens)]
|
||||||
|
(callback cached)
|
||||||
|
(let [token-references (sd/find-token-references input)
|
||||||
|
;; When creating a new token we dont have a token name yet,
|
||||||
|
;; so we use a temporary token name that hopefully doesn't clash with any of the users token names.
|
||||||
|
token-name (if (empty? @name-ref) "__TOKEN_STUDIO_SYSTEM.TEMP" @name-ref)
|
||||||
|
direct-self-reference? (get token-references token-name)
|
||||||
|
empty-input? (empty? (str/trim input))]
|
||||||
|
(cond
|
||||||
|
empty-input? (callback nil)
|
||||||
|
direct-self-reference? (callback :error/token-direct-self-reference)
|
||||||
|
:else
|
||||||
|
(let [token-id (or (:id token) (random-uuid))
|
||||||
|
new-tokens (update tokens token-id merge {:id token-id
|
||||||
|
:value input
|
||||||
|
:name token-name})]
|
||||||
|
(-> (sd/resolve-tokens+ new-tokens)
|
||||||
|
(p/finally
|
||||||
|
(fn [resolved-tokens _err]
|
||||||
|
(when-not (timeout-outdated-cb?)
|
||||||
|
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-id)]
|
||||||
|
(cond
|
||||||
|
resolved-value (do
|
||||||
|
(mf/set-ref-val! cache (assoc (mf/ref-val cache) input resolved-tokens))
|
||||||
|
(callback resolved-token))
|
||||||
|
(= #{:style-dictionary/missing-reference} errors) (callback :error/token-missing-reference)
|
||||||
|
:else (callback :error/unknown-error)))))))))))))
|
||||||
|
|
||||||
|
timeout))))]
|
||||||
|
debounced-resolver-callback))
|
||||||
|
|
||||||
(mf/defc form
|
(mf/defc form
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [token] :as _args}]
|
[{:keys [token] :as _args}]
|
||||||
|
@ -63,7 +110,6 @@
|
||||||
:description ""}
|
:description ""}
|
||||||
token))
|
token))
|
||||||
state @state*
|
state @state*
|
||||||
_ (js/console.log "render")
|
|
||||||
|
|
||||||
form-touched (mf/use-state nil)
|
form-touched (mf/use-state nil)
|
||||||
update-form-touched (mf/use-callback
|
update-form-touched (mf/use-callback
|
||||||
|
@ -90,11 +136,11 @@
|
||||||
set-resolve-value (mf/use-callback
|
set-resolve-value (mf/use-callback
|
||||||
(fn [token-or-err]
|
(fn [token-or-err]
|
||||||
(let [value (cond
|
(let [value (cond
|
||||||
(= token-or-err :error/token-self-reference) :error/token-self-reference
|
(= token-or-err :error/token-direct-self-reference) :error/token-self-reference
|
||||||
(= token-or-err :error/token-missing-reference) :error/token-missing-reference
|
(= token-or-err :error/token-missing-reference) :error/token-missing-reference
|
||||||
(:resolved-value token-or-err) (:resolved-value token-or-err))]
|
(:resolved-value token-or-err) (:resolved-value token-or-err))]
|
||||||
(reset! token-resolve-result value))))
|
(reset! token-resolve-result value))))
|
||||||
on-update-value (sd/use-debonced-resolve-callback name token tokens set-resolve-value)
|
on-update-value (use-debonced-resolve-callback name token tokens set-resolve-value)
|
||||||
value-error? (when (keyword? @token-resolve-result)
|
value-error? (when (keyword? @token-resolve-result)
|
||||||
(= (namespace @token-resolve-result) "error"))
|
(= (namespace @token-resolve-result) "error"))
|
||||||
|
|
||||||
|
@ -136,6 +182,7 @@
|
||||||
(case @token-resolve-result
|
(case @token-resolve-result
|
||||||
:error/token-self-reference "Token has self reference"
|
:error/token-self-reference "Token has self reference"
|
||||||
:error/token-missing-reference "Token has missing reference"
|
:error/token-missing-reference "Token has missing reference"
|
||||||
|
:error/unknown-error ""
|
||||||
nil "Enter token value"
|
nil "Enter token value"
|
||||||
[:p @token-resolve-result])]
|
[:p @token-resolve-result])]
|
||||||
[:& tokens.common/labeled-input {:label "Description"
|
[:& tokens.common/labeled-input {:label "Description"
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
(map second)
|
(map second)
|
||||||
(into #{})))
|
(into #{})))
|
||||||
|
|
||||||
(defn token-self-reference? [token-name value-string]
|
|
||||||
(let [refs (find-token-references value-string)]
|
|
||||||
(get refs token-name)))
|
|
||||||
|
|
||||||
(defn tokens->style-dictionary+
|
(defn tokens->style-dictionary+
|
||||||
"Resolves references and math expressions using StyleDictionary.
|
"Resolves references and math expressions using StyleDictionary.
|
||||||
Returns a promise with the resolved dictionary."
|
Returns a promise with the resolved dictionary."
|
||||||
|
@ -115,55 +111,6 @@
|
||||||
|
|
||||||
;; Hooks -----------------------------------------------------------------------
|
;; Hooks -----------------------------------------------------------------------
|
||||||
|
|
||||||
(def new-token-temp-name
|
|
||||||
"TOKEN_STUDIO_SYSTEM.TEMP")
|
|
||||||
|
|
||||||
(defn use-debonced-resolve-callback
|
|
||||||
[name-ref token tokens callback & {:keys [cached timeout]
|
|
||||||
:or {cached {}
|
|
||||||
timeout 160}}]
|
|
||||||
(let [timeout-id-ref (mf/use-ref nil)
|
|
||||||
cache (mf/use-ref cached)
|
|
||||||
debounced-resolver-callback
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps token callback tokens)
|
|
||||||
(fn [event]
|
|
||||||
(let [input (dom/get-target-val event)
|
|
||||||
timeout-id (js/Symbol)]
|
|
||||||
(mf/set-ref-val! timeout-id-ref timeout-id)
|
|
||||||
(js/setTimeout
|
|
||||||
(fn []
|
|
||||||
(when (= (mf/ref-val timeout-id-ref) timeout-id)
|
|
||||||
(let [cached (-> (mf/ref-val cache)
|
|
||||||
(get tokens))
|
|
||||||
token-name (if (empty? @name-ref) new-token-temp-name @name-ref)]
|
|
||||||
(cond
|
|
||||||
cached (callback cached)
|
|
||||||
(token-self-reference? token-name input) (callback :error/token-self-reference)
|
|
||||||
:else (let [token-id (or (:id token) (random-uuid))
|
|
||||||
new-tokens (update tokens token-id merge {:id token-id
|
|
||||||
:value input
|
|
||||||
:name token-name})]
|
|
||||||
(-> (resolve-tokens+ new-tokens)
|
|
||||||
(p/finally
|
|
||||||
(fn [resolved-tokens _err]
|
|
||||||
(js/console.log "input" input (empty? (str/trim input)))
|
|
||||||
(cond
|
|
||||||
;; Ignore outdated callbacks because the user input changed since it tried to resolve
|
|
||||||
(not= (mf/ref-val timeout-id-ref) timeout-id) nil
|
|
||||||
(empty? (str/trim input)) (callback nil)
|
|
||||||
:else (let [resolved-token (get resolved-tokens token-id)]
|
|
||||||
(js/console.log "resolved-token" resolved-token)
|
|
||||||
(if (:resolved-value resolved-token)
|
|
||||||
(do
|
|
||||||
(mf/set-ref-val! cache (assoc (mf/ref-val cache) input resolved-tokens))
|
|
||||||
(callback resolved-token))
|
|
||||||
(callback :error/token-missing-reference))))))))))))
|
|
||||||
|
|
||||||
|
|
||||||
timeout))))]
|
|
||||||
debounced-resolver-callback))
|
|
||||||
|
|
||||||
(defonce !tokens-cache (atom nil))
|
(defonce !tokens-cache (atom nil))
|
||||||
|
|
||||||
(defn use-resolved-tokens
|
(defn use-resolved-tokens
|
||||||
|
|
|
@ -18,8 +18,3 @@
|
||||||
(t/is (nil? (wtsd/find-token-references "1 + 2")))
|
(t/is (nil? (wtsd/find-token-references "1 + 2")))
|
||||||
;; Edge-case: Ignore unmatched closing parens
|
;; Edge-case: Ignore unmatched closing parens
|
||||||
(t/is (= #{"foo" "bar"} (wtsd/find-token-references "{foo}} + {bar}"))))
|
(t/is (= #{"foo" "bar"} (wtsd/find-token-references "{foo}} + {bar}"))))
|
||||||
|
|
||||||
(t/deftest test-token-self-reference?
|
|
||||||
(t/is (some? (wtsd/token-self-reference? "some.value" "{md} + {some.value}")))
|
|
||||||
(t/is (nil? (wtsd/token-self-reference? "some.value" "some.value")))
|
|
||||||
(t/is (nil? (wtsd/token-self-reference? "sm" "{md} + {lg}"))))
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue