diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs index 4a26f0f39..0a4aeef63 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs @@ -99,12 +99,30 @@ selection-parents (mf/deref selection-parents-ref) tokens (mf/deref refs/workspace-tokens) - border-radius-tokens (mf/use-memo (mf/deps tokens) #(wtc/tokens-name-map-for-type :border-radius tokens)) - border-radius-options (mf/use-memo (mf/deps shape border-radius-tokens) - #(map (fn [[_k {:keys [name] :as item}]] - (cond-> (assoc item :label name) - (wtc/token-applied? item shape (wtc/token-attributes :border-radius)) (assoc :selected? true))) - border-radius-tokens)) + tokens-by-type (mf/use-memo (mf/deps tokens) #(wtc/group-tokens-by-type tokens)) + + border-radius-tokens (:border-radius tokens-by-type) + border-radius-options (mf/use-memo + (mf/deps shape border-radius-tokens) + #(wtc/tokens-name-map->select-options + {:shape shape + :tokens border-radius-tokens + :attributes (wtc/token-attributes :border-radius)})) + sizing-tokens (:sizing tokens-by-type) + width-options (mf/use-memo + (mf/deps shape sizing-tokens) + #(wtc/tokens-name-map->select-options + {:shape shape + :tokens sizing-tokens + :attributes (wtc/token-attributes :sizing) + :selected-attributes #{:width}})) + height-options (mf/use-memo + (mf/deps shape sizing-tokens) + #(wtc/tokens-name-map->select-options + {:shape shape + :tokens sizing-tokens + :attributes (wtc/token-attributes :sizing) + :selected-attributes #{:height}})) flex-child? (->> selection-parents (some ctl/flex-layout?)) absolute? (ctl/item-absolute? shape) @@ -219,8 +237,17 @@ (mf/use-fn (mf/deps ids) (fn [value attr] - (st/emit! (udw/trigger-bounding-box-cloaking ids) - (udw/update-dimensions ids attr value)))) + (let [token-value (wtc/maybe-resolve-token-value value)] + (st/emit! (udw/trigger-bounding-box-cloaking ids) + (dch/update-shapes ids + (if token-value + #(assoc-in % [:applied-tokens attr] (:id value)) + #(d/dissoc-in % [:applied-tokens attr])) + {:reg-objects? true + :attrs [:applied-tokens]}) + (udw/update-dimensions ids attr (or token-value value)))))) + + on-proportion-lock-change (mf/use-fn @@ -293,9 +320,9 @@ on-border-radius-token-unapply (mf/use-fn - (mf/deps ids change-radius border-radius-tokens) + (mf/deps ids change-radius) (fn [token] - (let [token-value (some-> token wtc/resolve-token-value)] + (let [token-value (wtc/maybe-resolve-token-value token)] (st/emit! (change-radius (fn [shape] (-> (dt/unapply-token-id shape (wtc/token-attributes :border-radius)) @@ -303,13 +330,12 @@ on-radius-1-change (mf/use-fn - (mf/deps ids change-radius border-radius-tokens) + (mf/deps ids change-radius) (fn [value] - (let [token (when (map? value) value) - token-value (some-> token wtc/resolve-token-value)] + (let [token-value (wtc/maybe-resolve-token-value value)] (st/emit! (change-radius (fn [shape] - (-> (dt/maybe-apply-token-to-shape {:token token + (-> (dt/maybe-apply-token-to-shape {:token (when token-value value) :shape shape :attributes (wtc/token-attributes :border-radius)}) (ctsr/set-radius-1 (or token-value value))))))))) @@ -422,24 +448,36 @@ :disabled disabled-width-sizing?) :title (tr "workspace.options.width")} [:span {:class (stl/css :icon-text)} "W"] - [:> numeric-input* {:min 0.01 - :no-validate true - :placeholder (if (= :multiple (:width values)) (tr "settings.multiple") "--") - :on-change on-width-change - :disabled disabled-width-sizing? - :className (stl/css :numeric-input) - :value (:width values)}]] + [:& editable-select + {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") + :no-validate true + :min 0.01 + :class (stl/css :token-select) + :disabled disabled-width-sizing? + :input-class (stl/css :numeric-input) + :on-change on-width-change + :on-token-remove #(on-width-change (wtc/maybe-resolve-token-value %)) + :options width-options + :position :left + :type "number" + :value (:width values)}]] [:div {:class (stl/css-case :height true :disabled disabled-height-sizing?) :title (tr "workspace.options.height")} [:span {:class (stl/css :icon-text)} "H"] - [:> numeric-input* {:min 0.01 - :no-validate true - :placeholder (if (= :multiple (:height values)) (tr "settings.multiple") "--") - :on-change on-height-change - :disabled disabled-height-sizing? - :className (stl/css :numeric-input) - :value (:height values)}]] + [:& editable-select + {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") + :no-validate true + :min 0.01 + :class (stl/css :token-select) + :disabled disabled-height-sizing? + :input-class (stl/css :numeric-input) + :on-change on-height-change + :on-token-remove #(on-height-change (wtc/maybe-resolve-token-value %)) + :options height-options + :position :right + :type "number" + :value (:height values)}]] [:button {:class (stl/css-case :lock-size-btn true :selected (true? proportion-lock) @@ -498,13 +536,14 @@ [:span {:class (stl/css :icon)} i/corner-radius] [:& editable-select {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") - :on-token-remove on-border-radius-token-unapply - :class (stl/css :token-select) - :type "number" :min 0 + :class (stl/css :token-select) :input-class (stl/css :numeric-input) :on-change on-radius-1-change + :on-token-remove on-border-radius-token-unapply :options border-radius-options + :position :right + :type "number" :value (:rx values)}]] @radius-multi? diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss index 810c79f37..10bbf5056 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss @@ -109,6 +109,7 @@ .size { @include flexRow; + position: relative; } .height, @@ -182,6 +183,7 @@ .radius-1 { @extend .input-element; width: $s-108; + position: relative; } .radius-4 { diff --git a/frontend/src/app/main/ui/workspace/tokens/core.cljs b/frontend/src/app/main/ui/workspace/tokens/core.cljs index 9f0405a62..0b972f61d 100644 --- a/frontend/src/app/main/ui/workspace/tokens/core.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/core.cljs @@ -37,6 +37,9 @@ int-or-double (throw (ex-info (str "Implement token value resolve for " value) token)))) +(defn maybe-resolve-token-value [{:keys [value] :as token}] + (when value (resolve-token-value token))) + (defn group-tokens-by-type "Groups tokens by their `:type` property." [tokens] @@ -60,6 +63,12 @@ (get token-type []) (tokens-name-map))) +(defn tokens-name-map->select-options [{:keys [shape tokens attributes selected-attributes]}] + (->> (tokens-name-map tokens) + (map (fn [[_k {:keys [name] :as item}]] + (cond-> (assoc item :label name) + (token-applied? item shape (or selected-attributes attributes)) (assoc :selected? true)))))) + ;; Update functions ------------------------------------------------------------ (defn on-apply-token [{:keys [token token-type-props selected-shapes] :as _props}] diff --git a/frontend/src/app/main/ui/workspace/tokens/editable_select.cljs b/frontend/src/app/main/ui/workspace/tokens/editable_select.cljs index afbd5a2ee..6c487cbd3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/editable_select.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/editable_select.cljs @@ -38,11 +38,13 @@ :else new-value)] (set-value! new-value))))) -(mf/defc dropdown-select [{:keys [on-close element-id element-ref options on-select]}] +(mf/defc dropdown-select [{:keys [position on-close element-id element-ref options on-select]}] [:& dropdown {:show true :on-close on-close} - [:div {:class (stl/css :custom-select-dropdown) - :ref element-ref} + [:> :div {:class (stl/css-case :custom-select-dropdown true + :custom-select-dropdown-right (= position :right) + :custom-select-dropdown-left (= position :left)) + :ref element-ref} [:ul {:class (stl/css :custom-select-dropdown-list)} (for [[index item] (d/enumerate options)] (cond @@ -60,7 +62,7 @@ [:span {:class (stl/css :check-icon)} i/tick]])))]]]) (mf/defc editable-select - [{:keys [value type options class on-change placeholder on-blur input-class on-token-remove] :as params}] + [{:keys [value type options class on-change placeholder on-blur input-class on-token-remove position] :as params}] (let [state* (mf/use-state {:id (uuid/next) :is-open? false :current-value value @@ -133,6 +135,12 @@ value (or (d/parse-double value) value)] (set-value value))) + handle-token-change-input + (fn [event] + (let [value (-> event dom/get-target dom/get-value) + value (or (d/parse-double value) value)] + (set-token-value! value))) + handle-key-down (mf/use-fn (mf/deps set-value is-open? token) @@ -141,7 +149,7 @@ 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)) + caret-at-beginning? (zero? (.. 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)))] @@ -212,11 +220,10 @@ (cond token [:input {:value (or (:token-value state) "") :class input-class - :on-change handle-change-input + :on-change handle-token-change-input :on-key-down handle-key-down :on-focus handle-focus - :on-blur handle-blur - :type type}] + :on-blur handle-blur}] (= type "number") [:> numeric-input* {:autoFocus refocus? :value (or current-value "") :className input-class @@ -239,7 +246,8 @@ i/arrow]) (when (and is-open? (seq options)) - [:& dropdown-select {:on-close close-dropdown + [:& dropdown-select {:position position + :on-close close-dropdown :element-id element-id :element-ref select-wrapper-ref :options options diff --git a/frontend/src/app/main/ui/workspace/tokens/editable_select.scss b/frontend/src/app/main/ui/workspace/tokens/editable_select.scss index 7bb4e7f4e..3f0eb03f9 100644 --- a/frontend/src/app/main/ui/workspace/tokens/editable_select.scss +++ b/frontend/src/app/main/ui/workspace/tokens/editable_select.scss @@ -9,7 +9,6 @@ .editable-select { @extend .asset-element; margin: 0; - position: relative; display: flex; height: calc($s-32 - 2px); // Fixes border being clipped by the input field width: 100%; @@ -62,13 +61,21 @@ width: 0; } + .custom-select-dropdown-left { + left: 0; + right: unset; + } + + .custom-select-dropdown-right { + right: 0; + left: unset; + } + .custom-select-dropdown { @extend .dropdown-wrapper; max-height: $s-320; width: auto; margin-top: $s-4; - right: 0; - left: unset; .separator { margin: 0;