Merge pull request #128 from tokens-studio/119-higlight-applied-token-in-the-editing-field

Show token value inside shapes panel (border-radius)
This commit is contained in:
Florian Schrödl 2024-05-23 08:43:51 +02:00 committed by GitHub
commit 2818d097ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 110 additions and 42 deletions

View file

@ -6,6 +6,7 @@
(ns app.main.data.tokens (ns app.main.data.tokens
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.changes-builder :as pcb] [app.common.files.changes-builder :as pcb]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
@ -57,6 +58,9 @@
(->> (map (fn [attr] [attr token-id]) attributes) (->> (map (fn [attr] [attr token-id]) attributes)
(into {}))) (into {})))
(defn unapply-token-id [shape attributes]
(update shape :applied-tokens d/without-keys attributes))
(defn apply-token-id-to-attributes [{:keys [shape token-id attributes]}] (defn apply-token-id-to-attributes [{:keys [shape token-id attributes]}]
(let [token (token-from-attributes token-id attributes)] (let [token (token-from-attributes token-id attributes)]
(toggle-or-apply-token shape token))) (toggle-or-apply-token shape token)))

View file

@ -291,6 +291,16 @@
(on-switch-to-radius-4) (on-switch-to-radius-4)
(on-switch-to-radius-1)))) (on-switch-to-radius-1))))
on-border-radius-token-unapply
(mf/use-fn
(mf/deps ids change-radius border-radius-tokens)
(fn [token]
(let [token-value (some-> token wtc/resolve-token-value)]
(st/emit!
(change-radius (fn [shape]
(-> (dt/unapply-token-id shape (wtc/token-attributes :border-radius))
(ctsr/set-radius-1 token-value))))))))
on-radius-1-change on-radius-1-change
(mf/use-fn (mf/use-fn
(mf/deps ids change-radius border-radius-tokens) (mf/deps ids change-radius border-radius-tokens)
@ -488,6 +498,7 @@
[:span {:class (stl/css :icon)} i/corner-radius] [:span {:class (stl/css :icon)} i/corner-radius]
[:& editable-select [:& editable-select
{:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--")
:on-token-remove on-border-radius-token-unapply
:class (stl/css :token-select) :class (stl/css :token-select)
:type "number" :type "number"
:min 0 :min 0

View file

@ -13,7 +13,6 @@
[app.main.data.workspace :as udw] [app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.transforms :as dwt] [app.main.data.workspace.transforms :as dwt]
[app.main.store :as st])) [app.main.store :as st]))

View file

@ -17,6 +17,7 @@
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[app.util.timers :as timers] [app.util.timers :as timers]
[cuerdas.core :as str]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn on-number-input-key-down [{:keys [event min-val max-val set-value!]}] (defn on-number-input-key-down [{:keys [event min-val max-val set-value!]}]
@ -59,22 +60,28 @@
[:span {:class (stl/css :check-icon)} i/tick]])))]]]) [:span {:class (stl/css :check-icon)} i/tick]])))]]])
(mf/defc editable-select (mf/defc editable-select
[{:keys [value type options class on-change placeholder on-blur input-class] :as params}] [{:keys [value type options class on-change placeholder on-blur input-class on-token-remove] :as params}]
(let [state* (mf/use-state {:id (uuid/next) (let [state* (mf/use-state {:id (uuid/next)
:is-open? false :is-open? false
:current-value value :current-value value
:token-value nil
:current-item nil :current-item nil
:top nil :top nil
:left nil :left nil
:bottom nil}) :bottom nil})
state (deref state*) state (deref state*)
is-open? (:is-open? state) is-open? (:is-open? state)
refocus? (:refocus? state)
current-value (:current-value state) current-value (:current-value state)
element-id (:id state) element-id (:id state)
min-val (get params :min) min-val (get params :min)
max-val (get params :max) max-val (get params :max)
multiple? (= :multiple value)
token (when-not multiple?
(-> (filter :selected? options) (first)))
emit-blur? (mf/use-ref nil) emit-blur? (mf/use-ref nil)
select-wrapper-ref (mf/use-ref) select-wrapper-ref (mf/use-ref)
@ -93,9 +100,15 @@
options) options)
(into {})) (into {}))
set-token-value!
(fn [value]
(swap! state* assoc :token-value value))
set-value set-value
(fn [value] (fn [value]
(swap! state* assoc :current-value value) (swap! state* assoc
:current-value value
:token-value value)
(when on-change (on-change value))) (when on-change (on-change value)))
select-item select-item
@ -109,6 +122,7 @@
{:keys [value] :as item} (get labels-map label)] {:keys [value] :as item} (get labels-map label)]
(swap! state* assoc (swap! state* assoc
:current-value value :current-value value
:token-value nil
:current-item item) :current-item item)
(when on-change (on-change item)) (when on-change (on-change item))
(when on-blur (on-blur))))) (when on-blur (on-blur)))))
@ -119,32 +133,33 @@
value (or (d/parse-double value) value)] value (or (d/parse-double value) value)]
(set-value value))) (set-value value)))
on-node-load
(fn [node]
;; There is a problem when changing the state in this callback that
;; produces the dropdown to close in the same event
(when node
(timers/schedule
#(when-let [bounds (when node (dom/get-bounding-rect node))]
(let [{window-height :height} (dom/get-window-size)
{:keys [left top height]} bounds
bottom (when (< (- window-height top) 300) (- window-height top))
top (when (>= (- window-height top) 300) (+ top height))]
(swap! state*
assoc
:left left
:top top
:bottom bottom))))))
handle-key-down handle-key-down
(mf/use-fn (mf/use-fn
(mf/deps set-value is-open?) (mf/deps set-value is-open? token)
(fn [event] (fn [^js event]
(cond (cond
token (let [backspace? (kbd/backspace? event)
enter? (kbd/enter? event)
value (-> event dom/get-target dom/get-value)
caret-at-beginning? (nil? (.. event -target -selectionStart))
no-text-selected? (str/empty? (.toString (js/document.getSelection)))
delete-token? (and backspace? caret-at-beginning? no-text-selected?)
replace-token-with-value? (and enter? (seq (str/trim value)))]
(cond
delete-token? (do
(dom/prevent-default event)
(on-token-remove token)
;; Re-focus the input value of the newly rendered input element
(swap! state* assoc :refocus? true))
replace-token-with-value? (do
(dom/prevent-default event)
(on-token-remove token)
(handle-change-input event)
(set-token-value! nil))
:else (set-token-value! value)))
is-open? (let [up? (kbd/up-arrow? event) is-open? (let [up? (kbd/up-arrow? event)
down? (kbd/down-arrow? event)] down? (kbd/down-arrow? event)]
(dom/prevent-default event) (dom/prevent-default event))
(js/console.log "up? down?" up? down?))
(= type "number") (on-number-input-key-down {:event event (= type "number") (on-number-input-key-down {:event event
:min-val min-val :min-val min-val
:max-val max-val :max-val max-val
@ -152,13 +167,17 @@
handle-focus handle-focus
(mf/use-fn (mf/use-fn
(mf/deps refocus?)
(fn [] (fn []
(when refocus?
(swap! state* dissoc :refocus?))
(mf/set-ref-val! emit-blur? false))) (mf/set-ref-val! emit-blur? false)))
handle-blur handle-blur
(mf/use-fn (mf/use-fn
(fn [] (fn []
(mf/set-ref-val! emit-blur? true) (mf/set-ref-val! emit-blur? true)
(swap! state* assoc :token-value nil)
(timers/schedule (timers/schedule
200 200
(fn [] (fn []
@ -167,7 +186,7 @@
(mf/use-effect (mf/use-effect
(mf/deps value current-value) (mf/deps value current-value)
#(when (not= (str value) current-value) #(when (not= (str value) current-value)
(reset! state* {:current-value value}))) (swap! state* assoc :current-value value)))
(mf/with-effect [is-open?] (mf/with-effect [is-open?]
(let [wrapper-node (mf/ref-val select-wrapper-ref) (let [wrapper-node (mf/ref-val select-wrapper-ref)
@ -185,23 +204,34 @@
(mf/set-ref-val! emit-blur? (not is-open?))) (mf/set-ref-val! emit-blur? (not is-open?)))
[:div {:class (dm/str class " " (stl/css :editable-select)) [:div {:class (dm/str class " " (stl/css :editable-select))}
:ref on-node-load} (when-let [{:keys [label value]} token]
(if (= type "number") [:div {:title (str label ": " value)
[:> numeric-input* {:value (or current-value "") :class (stl/css :token-pill)}
:className input-class value])
:on-change set-value (cond
:on-focus handle-focus token [:input {:value (or (:token-value state) "")
:on-blur handle-blur :class input-class
:placeholder placeholder}] :on-change handle-change-input
[:input {:value (or current-value "") :on-key-down handle-key-down
:class input-class :on-focus handle-focus
:on-change handle-change-input :on-blur handle-blur
:on-key-down handle-key-down :type type}]
:on-focus handle-focus (= type "number") [:> numeric-input* {:autoFocus refocus?
:on-blur handle-blur :value (or current-value "")
:placeholder placeholder :className input-class
:type type}]) :on-change set-value
:on-focus handle-focus
:on-blur handle-blur
:placeholder placeholder}]
:else [:input {:value (or current-value "")
:class input-class
:on-change handle-change-input
:on-key-down handle-key-down
:on-focus handle-focus
:on-blur handle-blur
:placeholder placeholder
:type type}])
(when (seq options) (when (seq options)
[:span {:class (stl/css :dropdown-button) [:span {:class (stl/css :dropdown-button)

View file

@ -17,6 +17,17 @@
border-radius: $br-8; border-radius: $br-8;
cursor: pointer; cursor: pointer;
background: transparent;
&:hover {
background: transparent;
}
&:focus-within {
.token-pill {
background-color: var(--button-primary-background-color-rest);
color: var(--button-primary-foreground-color-rest);
}
}
.dropdown-button { .dropdown-button {
@include flexCenter; @include flexCenter;
margin-right: -$s-8; margin-right: -$s-8;
@ -38,6 +49,19 @@
margin-bottom: 0; margin-bottom: 0;
} }
.token-pill {
background-color: rgb(94 107 120 / 25%);
border-radius: $br-4;
padding: $s-2 $s-6;
text-overflow: ellipsis;
flex: 0 0 auto;
}
.token-pill + input {
flex: 1 1 auto;
width: 0;
}
.custom-select-dropdown { .custom-select-dropdown {
@extend .dropdown-wrapper; @extend .dropdown-wrapper;
max-height: $s-320; max-height: $s-320;