mirror of
https://github.com/penpot/penpot.git
synced 2025-05-21 09:36:13 +02:00
⚡ Add performance oriented refactor for color palette components
This commit is contained in:
parent
6d666c4926
commit
068dd5f4bc
6 changed files with 93 additions and 71 deletions
|
@ -115,6 +115,9 @@
|
||||||
(sm/register! ::recent-color schema:recent-color)
|
(sm/register! ::recent-color schema:recent-color)
|
||||||
(sm/register! ::color-attrs schema:color-attrs)
|
(sm/register! ::color-attrs schema:color-attrs)
|
||||||
|
|
||||||
|
(def valid-color?
|
||||||
|
(sm/lazy-validator schema:color))
|
||||||
|
|
||||||
(def check-color!
|
(def check-color!
|
||||||
(sm/check-fn schema:color :hint "expected valid color struct"))
|
(sm/check-fn schema:color :hint "expected valid color struct"))
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,8 @@
|
||||||
(rx/of (dwsh/update-shapes shape-ids transform-attrs)))))))
|
(rx/of (dwsh/update-shapes shape-ids transform-attrs)))))))
|
||||||
|
|
||||||
(defn change-fill
|
(defn change-fill
|
||||||
([ids color position] (change-fill ids color position nil))
|
([ids color position]
|
||||||
|
(change-fill ids color position nil))
|
||||||
([ids color position options]
|
([ids color position options]
|
||||||
(ptk/reify ::change-fill
|
(ptk/reify ::change-fill
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
|
|
|
@ -8,19 +8,21 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.types.color :as ctc]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.workspace.colors :as mdc]
|
[app.main.data.workspace.colors :as mdc]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.color-bullet :as cb]
|
[app.main.ui.components.color-bullet :as cb]
|
||||||
[app.main.ui.hooks :as h]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
[okulary.core :as l]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -48,10 +50,8 @@
|
||||||
[:& cb/color-name {:color color :size size :origin :palette}]]))
|
[:& cb/color-name {:color color :size size :origin :palette}]]))
|
||||||
|
|
||||||
(mf/defc palette*
|
(mf/defc palette*
|
||||||
[{:keys [current-colors size width selected]}]
|
[{:keys [colors size width selected]}]
|
||||||
(let [;; We had to do this due to a bug that leave some bugged colors
|
(let [state (mf/use-state #(do {:show-menu false}))
|
||||||
current-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) current-colors))
|
|
||||||
state (mf/use-state {:show-menu false})
|
|
||||||
offset-step (cond
|
offset-step (cond
|
||||||
(<= size 64) 40
|
(<= size 64) 40
|
||||||
(<= size 80) 72
|
(<= size 80) 72
|
||||||
|
@ -61,12 +61,12 @@
|
||||||
:else 132)
|
:else 132)
|
||||||
width (- width buttons-size)
|
width (- width buttons-size)
|
||||||
visible (int (/ width offset-step))
|
visible (int (/ width offset-step))
|
||||||
show-arrows? (> (count current-colors) visible)
|
show-arrows? (> (count colors) visible)
|
||||||
visible (if show-arrows?
|
visible (if show-arrows?
|
||||||
(int (/ (- width 48) offset-step))
|
(int (/ (- width 48) offset-step))
|
||||||
visible)
|
visible)
|
||||||
offset (:offset @state 0)
|
offset (:offset @state 0)
|
||||||
max-offset (- (count current-colors)
|
max-offset (- (count colors)
|
||||||
visible)
|
visible)
|
||||||
container (mf/use-ref nil)
|
container (mf/use-ref nil)
|
||||||
bullet-size (cond
|
bullet-size (cond
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
:else 64)
|
:else 64)
|
||||||
|
|
||||||
on-left-arrow-click
|
on-left-arrow-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps max-offset visible)
|
(mf/deps max-offset visible)
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(swap! state update :offset
|
(swap! state update :offset
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
offset)))))
|
offset)))))
|
||||||
|
|
||||||
on-right-arrow-click
|
on-right-arrow-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps max-offset visible)
|
(mf/deps max-offset visible)
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(swap! state update :offset
|
(swap! state update :offset
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
offset)))))
|
offset)))))
|
||||||
|
|
||||||
on-scroll
|
on-scroll
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps max-offset)
|
(mf/deps max-offset)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [event (dom/event->native-event event)
|
(let [event (dom/event->native-event event)
|
||||||
|
@ -109,12 +109,12 @@
|
||||||
(on-right-arrow-click event)
|
(on-right-arrow-click event)
|
||||||
(on-left-arrow-click event)))))]
|
(on-left-arrow-click event)))))]
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/with-layout-effect []
|
||||||
#(let [dom (mf/ref-val container)
|
(let [dom (mf/ref-val container)
|
||||||
width (obj/get dom "clientWidth")]
|
width (obj/get dom "clientWidth")]
|
||||||
(swap! state assoc :width width)))
|
(swap! state assoc :width width)))
|
||||||
|
|
||||||
(mf/with-effect [width current-colors]
|
(mf/with-effect [width colors]
|
||||||
(when (not= 0 (:offset @state))
|
(when (not= 0 (:offset @state))
|
||||||
(swap! state assoc :offset 0)))
|
(swap! state assoc :offset 0)))
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@
|
||||||
[:div {:class (stl/css :color-palette-content)
|
[:div {:class (stl/css :color-palette-content)
|
||||||
:ref container
|
:ref container
|
||||||
:on-wheel on-scroll}
|
:on-wheel on-scroll}
|
||||||
(if (empty? current-colors)
|
(if (empty? colors)
|
||||||
[:div {:class (stl/css :color-palette-empty)
|
[:div {:class (stl/css :color-palette-empty)
|
||||||
:style {:position "absolute"
|
:style {:position "absolute"
|
||||||
:left "50%"
|
:left "50%"
|
||||||
|
@ -140,44 +140,61 @@
|
||||||
:style {:position "relative"
|
:style {:position "relative"
|
||||||
:max-width (str width "px")
|
:max-width (str width "px")
|
||||||
:right (str (* offset-step offset) "px")}}
|
:right (str (* offset-step offset) "px")}}
|
||||||
(for [[idx item] (map-indexed vector current-colors)]
|
(for [[idx item] (map-indexed vector colors)]
|
||||||
[:> palette-item* {:color item :key idx :size size :selected selected}])])]
|
[:> palette-item* {:color item :key idx :size size :selected selected}])])]
|
||||||
|
|
||||||
(when show-arrows?
|
(when show-arrows?
|
||||||
[:button {:class (stl/css :right-arrow)
|
[:button {:class (stl/css :right-arrow)
|
||||||
:disabled (= offset max-offset)
|
:disabled (= offset max-offset)
|
||||||
:on-click on-right-arrow-click} i/arrow])]))
|
:on-click on-right-arrow-click} i/arrow])]))
|
||||||
|
|
||||||
(defn library->colors [shared-libs selected]
|
(mf/defc recent-colors-palette*
|
||||||
(map #(merge % {:file-id selected})
|
{::mf/private true}
|
||||||
(-> shared-libs
|
[props]
|
||||||
(get-in [selected :data :colors])
|
(let [colors (mf/deref refs/recent-colors)
|
||||||
(vals))))
|
|
||||||
|
|
||||||
(mf/defc color-palette
|
colors (mf/with-memo [colors]
|
||||||
|
(->> (reverse colors)
|
||||||
|
(filter ctc/valid-color?)
|
||||||
|
(vec)))
|
||||||
|
|
||||||
|
props (mf/spread-props props {:colors colors})]
|
||||||
|
[:> palette* props]))
|
||||||
|
|
||||||
|
(defn- make-library-colors-ref
|
||||||
|
[file-id]
|
||||||
|
(l/derived (fn [libraries]
|
||||||
|
(dm/get-in libraries [file-id :data :colors]))
|
||||||
|
refs/libraries))
|
||||||
|
|
||||||
|
(mf/defc file-color-palette*
|
||||||
|
{::mf/private true}
|
||||||
|
[{:keys [file-id] :as props}]
|
||||||
|
(let [colors-ref (mf/with-memo [file-id]
|
||||||
|
(make-library-colors-ref file-id))
|
||||||
|
colors (mf/deref colors-ref)
|
||||||
|
colors (mf/with-memo [colors file-id]
|
||||||
|
(->> (vals colors)
|
||||||
|
(filter ctc/valid-color?)
|
||||||
|
(map #(assoc % :file-id file-id))
|
||||||
|
(sort-by :name)
|
||||||
|
(vec)))
|
||||||
|
props (mf/spread-props props {:colors colors})]
|
||||||
|
|
||||||
|
[:> palette* props]))
|
||||||
|
|
||||||
|
(mf/defc color-palette*
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [size width selected] :as props}]
|
[{:keys [selected] :as props}]
|
||||||
(let [recent-colors (mf/deref refs/recent-colors)
|
(let [file-id (mf/use-ctx ctx/current-file-id)]
|
||||||
file-colors (mf/deref refs/workspace-file-colors)
|
(cond
|
||||||
shared-libs (mf/deref refs/libraries)
|
(= selected :recent)
|
||||||
colors (mf/use-state [])]
|
[:> recent-colors-palette* props]
|
||||||
|
|
||||||
(mf/with-effect [selected shared-libs]
|
(= selected :file)
|
||||||
(let [colors' (cond
|
(let [props (mf/spread-props props {:file-id file-id})]
|
||||||
(= selected :recent) (reverse recent-colors)
|
[:> file-color-palette* props])
|
||||||
(= selected :file) (->> (vals file-colors) (sort-by :name))
|
|
||||||
:else (->> (library->colors shared-libs selected) (sort-by :name)))]
|
|
||||||
(reset! colors (into [] colors'))))
|
|
||||||
|
|
||||||
(mf/with-effect [recent-colors selected]
|
:else
|
||||||
(when (= selected :recent)
|
(let [props (mf/spread-props props {:file-id selected})]
|
||||||
(reset! colors (reverse recent-colors))))
|
[:> file-color-palette* props]))))
|
||||||
|
|
||||||
(mf/with-effect [file-colors selected]
|
|
||||||
(when (= selected :file)
|
|
||||||
(reset! colors (into [] (->> (vals file-colors)
|
|
||||||
(sort-by :name))))))
|
|
||||||
|
|
||||||
[:> palette* {:current-colors @colors
|
|
||||||
:size size
|
|
||||||
:width width
|
|
||||||
:selected selected}]))
|
|
||||||
|
|
|
@ -74,6 +74,8 @@
|
||||||
|
|
||||||
.color-palette-content {
|
.color-palette-content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-palette-inside {
|
.color-palette-inside {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
[app.main.ui.hooks :as h]
|
[app.main.ui.hooks :as h]
|
||||||
[app.main.ui.hooks.resize :as r]
|
[app.main.ui.hooks.resize :as r]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.workspace.color-palette :refer [color-palette]]
|
[app.main.ui.workspace.color-palette :refer [color-palette*]]
|
||||||
[app.main.ui.workspace.color-palette-ctx-menu :refer [color-palette-ctx-menu]]
|
[app.main.ui.workspace.color-palette-ctx-menu :refer [color-palette-ctx-menu]]
|
||||||
[app.main.ui.workspace.text-palette :refer [text-palette]]
|
[app.main.ui.workspace.text-palette :refer [text-palette]]
|
||||||
[app.main.ui.workspace.text-palette-ctx-menu :refer [text-palette-ctx-menu]]
|
[app.main.ui.workspace.text-palette-ctx-menu :refer [text-palette-ctx-menu]]
|
||||||
|
@ -195,11 +195,12 @@
|
||||||
:selected selected-text
|
:selected selected-text
|
||||||
:width vport-width}]])
|
:width vport-width}]])
|
||||||
(when color-palette?
|
(when color-palette?
|
||||||
[:* [:& color-palette-ctx-menu {:show-menu? show-menu?
|
[:*
|
||||||
|
[:& color-palette-ctx-menu {:show-menu? show-menu?
|
||||||
:close-menu on-close-menu
|
:close-menu on-close-menu
|
||||||
:on-select-palette on-select-palette
|
:on-select-palette on-select-palette
|
||||||
:selected @selected}]
|
:selected @selected}]
|
||||||
[:& color-palette {:size size
|
[:> color-palette* {:size size
|
||||||
:selected @selected
|
:selected @selected
|
||||||
:width vport-width}]])]]
|
:width vport-width}]])]]
|
||||||
[:div {:class (stl/css :handler)
|
[:div {:class (stl/css :handler)
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
[app.main.ui.components.color-input :refer [color-input*]]
|
[app.main.ui.components.color-input :refer [color-input*]]
|
||||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||||
[app.main.ui.components.reorder-handler :refer [reorder-handler]]
|
[app.main.ui.components.reorder-handler :refer [reorder-handler]]
|
||||||
[app.main.ui.context :as ctx]
|
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.hooks :as h]
|
[app.main.ui.hooks :as h]
|
||||||
|
@ -49,8 +48,7 @@
|
||||||
[{:keys [index color disable-gradient disable-opacity disable-image disable-picker on-change
|
[{:keys [index color disable-gradient disable-opacity disable-image disable-picker on-change
|
||||||
on-reorder on-detach on-open on-close on-remove
|
on-reorder on-detach on-open on-close on-remove
|
||||||
disable-drag on-focus on-blur select-only select-on-focus]}]
|
disable-drag on-focus on-blur select-only select-on-focus]}]
|
||||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
(let [shared-libs (mf/deref refs/libraries)
|
||||||
shared-libs (mf/deref refs/libraries)
|
|
||||||
hover-detach (mf/use-state false)
|
hover-detach (mf/use-state false)
|
||||||
on-change (h/use-ref-callback on-change)
|
on-change (h/use-ref-callback on-change)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue