mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 13:46:37 +02:00
💄 Update desing tab phase 2 (#3621)
* 💄 Update constraint component * 💄 Update fill and selected color components * 💄 Update stroke component * 💄 Update text component * 💄 Update frame grid component * 💄 Update export component * 💄 Update shadow and blur components * 💄 Update colorpicker component UI * 💄 Update svg attrs and componets components UI * 💄 Small UI changes * 🐛 Fix shadow functions
This commit is contained in:
parent
95f1a8b9ee
commit
fb36b77bd1
92 changed files with 6014 additions and 2132 deletions
|
@ -5,12 +5,15 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.editable-select
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
|
@ -18,13 +21,21 @@
|
|||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc editable-select
|
||||
[{:keys [value type options class on-change placeholder on-blur] :as params}]
|
||||
(let [state (mf/use-state {:id (uuid/next)
|
||||
:is-open? false
|
||||
:current-value value
|
||||
:top nil
|
||||
:left nil
|
||||
:bottom nil})
|
||||
[{:keys [value type options class on-change placeholder on-blur input-class] :as params}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
state* (mf/use-state {:id (uuid/next)
|
||||
:is-open? false
|
||||
:current-value value
|
||||
:top nil
|
||||
:left nil
|
||||
:bottom nil})
|
||||
state (deref state*)
|
||||
is-open? (:is-open? state)
|
||||
current-value (:current-value state)
|
||||
top-value (:top state)
|
||||
left-value (:left state)
|
||||
bottom-value (:bottom state)
|
||||
element-id (:id state)
|
||||
|
||||
min-val (get params :min)
|
||||
max-val (get params :max)
|
||||
|
@ -35,16 +46,28 @@
|
|||
open-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? true))
|
||||
(swap! state* assoc :is-open? true))
|
||||
|
||||
toggle-dropdown
|
||||
(mf/use-fn
|
||||
(mf/deps state)
|
||||
#(swap! state* update :is-open? not))
|
||||
|
||||
close-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? false))
|
||||
select-item (fn [value]
|
||||
(fn [_]
|
||||
(swap! state assoc :current-value value)
|
||||
(when on-change (on-change value))
|
||||
(when on-blur (on-blur))))
|
||||
(swap! state* assoc :is-open? false))
|
||||
|
||||
select-item
|
||||
(mf/use-fn
|
||||
(mf/deps on-change on-blur)
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(d/read-string))]
|
||||
(swap! state* assoc :current-value value)
|
||||
(when on-change (on-change value))
|
||||
(when on-blur (on-blur)))))
|
||||
|
||||
as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item]))
|
||||
labels-map (into {} (map as-key-value) options)
|
||||
|
@ -52,7 +75,7 @@
|
|||
|
||||
set-value
|
||||
(fn [value]
|
||||
(swap! state assoc :current-value value)
|
||||
(swap! state* assoc :current-value value)
|
||||
(when on-change (on-change value)))
|
||||
|
||||
;; TODO: why this method supposes that all editable select
|
||||
|
@ -75,14 +98,14 @@
|
|||
{:keys [left top height]} bounds
|
||||
bottom (when (< (- window-height top) 300) (- window-height top))
|
||||
top (when (>= (- window-height top) 300) (+ top height))]
|
||||
(swap! state
|
||||
(swap! state*
|
||||
assoc
|
||||
:left left
|
||||
:top top
|
||||
:bottom bottom))))))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps set-value)
|
||||
(fn [event]
|
||||
(when (= type "number")
|
||||
|
@ -113,12 +136,12 @@
|
|||
(set-value new-value)))))))
|
||||
|
||||
handle-focus
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! emit-blur? false)))
|
||||
|
||||
handle-blur
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! emit-blur? true)
|
||||
(timers/schedule
|
||||
|
@ -127,56 +150,101 @@
|
|||
(when (and on-blur (mf/ref-val emit-blur?)) (on-blur))))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps value (:current-value @state))
|
||||
#(when (not= (str value) (:current-value @state))
|
||||
(reset! state {:current-value value})))
|
||||
(mf/deps value current-value)
|
||||
#(when (not= (str value) current-value)
|
||||
(reset! state* {:current-value value})))
|
||||
|
||||
(mf/with-effect [(:is-open? @state)]
|
||||
(mf/with-effect [is-open?]
|
||||
(let [wrapper-node (mf/ref-val font-size-wrapper-ref)
|
||||
node (dom/get-element-by-class "checked-element is-selected" wrapper-node)
|
||||
nodes (dom/get-elements-by-class "checked-element-value" wrapper-node)
|
||||
closest (fn [a b] (first (sort-by #(mth/abs (- % b)) a)))
|
||||
closest-value (str (closest options value))]
|
||||
(when (:is-open? @state)
|
||||
(when is-open?
|
||||
(if (some? node)
|
||||
(dom/scroll-into-view-if-needed! node)
|
||||
(some->> nodes
|
||||
(d/seek #(= closest-value (dom/get-inner-text %)))
|
||||
(dom/scroll-into-view-if-needed!)))))
|
||||
|
||||
(mf/set-ref-val! emit-blur? (not (:is-open? @state))))
|
||||
(mf/set-ref-val! emit-blur? (not is-open?)))
|
||||
|
||||
[:div.editable-select {:class class
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> @state :current-value value->label) "")
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input.input-text {:value (or (some-> @state :current-value value->label) "")
|
||||
:on-change handle-change-input
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder
|
||||
:type type}])
|
||||
[:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
|
||||
|
||||
[:& dropdown {:show (get @state :is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown {:style {:position "fixed"
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:bottom (:bottom @state)
|
||||
:ref font-size-wrapper-ref}}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (str (:id @state) "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (str (:id @state) "-" index)
|
||||
:class (when (= (str value) (-> @state :current-value)) "is-selected")
|
||||
:on-click (select-item value)}
|
||||
[:span.check-icon i/tick]
|
||||
[:span.checked-element-value label]])))]]]))
|
||||
(if new-css-system
|
||||
[:div {:class (dm/str class " " (stl/css :editable-select))
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> current-value value->label) "")
|
||||
:className input-class
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input {:value (or (some-> current-value value->label) "")
|
||||
: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}])
|
||||
|
||||
[:span {:class (stl/css :dropdown-button)
|
||||
:on-click toggle-dropdown}
|
||||
i/arrow-refactor]
|
||||
|
||||
[:& dropdown {:show (or is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)
|
||||
:ref font-size-wrapper-ref}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:li {:class (stl/css :separator)
|
||||
:key (dm/str element-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li
|
||||
{:key (str element-id "-" index)
|
||||
:class (stl/css-case :dropdown-element true
|
||||
:is-selected (= value current-value))
|
||||
:data-value value
|
||||
:on-click select-item}
|
||||
[:span {:class (stl/css :label)} label]
|
||||
[:span {:class (stl/css :check-icon)}
|
||||
i/tick-refactor]])))]]]
|
||||
|
||||
|
||||
[:div.editable-select {:class class
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> current-value value->label) "")
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input.input-text {:value (or (some-> current-value value->label) "")
|
||||
:on-change handle-change-input
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder
|
||||
:type type}])
|
||||
[:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
|
||||
|
||||
[:& dropdown {:show (or is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown {:style {:position "fixed"
|
||||
:top top-value
|
||||
:left left-value
|
||||
:bottom bottom-value}
|
||||
:ref font-size-wrapper-ref}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (str element-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (str element-id "-" index)
|
||||
:class (when (= (str value) current-value) "is-selected")
|
||||
:data-value value
|
||||
:on-click select-item}
|
||||
[:span.check-icon i/tick]
|
||||
[:span.checked-element-value label]])))]]])))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue