0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-23 23:35:58 -05:00

Improve efficiency of grouping and sorting token types

This commit is contained in:
Andrey Antukh 2025-02-04 20:29:39 +01:00
parent e4bf2bd9ad
commit 831b0baddd
3 changed files with 59 additions and 38 deletions

View file

@ -35,6 +35,7 @@
[app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.token-pill :refer [token-pill*]]
[app.main.ui.workspace.tokens.token-types :as wtty]
[app.util.array :as array]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.webapi :as wapi]
@ -74,10 +75,12 @@
(mf/defc token-group*
{::mf/private true}
[{:keys [type tokens selected-shapes token-type-props active-theme-tokens]}]
[{:keys [type tokens selected-shapes active-theme-tokens]}]
(let [open? (mf/deref (-> (l/key type)
(l/derived lens:token-type-open-status)))
{:keys [modal attributes all-attributes title]} token-type-props
{:keys [modal attributes all-attributes title] :as token-type-props}
(get wtty/token-types type)
tokens
(mf/with-memo [tokens]
@ -150,7 +153,6 @@
[:> token-pill*
{:key (:name token)
:token-type-props token-type-props
:token (d/nilv theme-token token)
:selected-shapes selected-shapes
:active-theme-tokens active-theme-tokens
@ -163,19 +165,23 @@
:on-context-menu on-context-menu}]))]])]]))
(defn- get-sorted-token-groups
"Separate token-types into groups of `:empty` or `:filled` depending if tokens exist for that type.
Sort each group alphabetically (by their `:token-key`)."
[tokens]
(let [tokens-by-type (ctob/group-by-type tokens)
{:keys [empty filled]} (->> wtty/token-types
(map (fn [[token-key token-type-props]]
{:token-key token-key
:token-type-props token-type-props
:tokens (get tokens-by-type token-key [])}))
(group-by (fn [{:keys [tokens]}]
(if (empty? tokens) :empty :filled))))]
{:empty (sort-by :token-key empty)
:filled (sort-by :token-key filled)}))
"Separate token-types into groups of `empty` or `filled` depending if
tokens exist for that type. Sort each group alphabetically (by
their type)."
[tokens-by-type]
(loop [empty #js []
filled #js []
types (-> wtty/token-types keys seq)]
(if-let [type (first types)]
(if (not-empty (get tokens-by-type type))
(recur empty
(array/conj! filled type)
(rest types))
(recur (array/conj! empty type)
filled
(rest types)))
[(seq (array/sort! empty))
(seq (array/sort! filled))])))
(mf/defc themes-header
[_props]
@ -283,31 +289,39 @@
selected-token-set-name
(mf/deref refs/workspace-selected-token-set-name)
token-groups
tokens-by-type
(mf/with-memo [tokens selected-token-set-tokens]
(-> (select-keys tokens (keys selected-token-set-tokens))
(get-sorted-token-groups)))]
(let [tokens (reduce-kv (fn [tokens k _]
(if (contains? selected-token-set-tokens k)
tokens
(dissoc tokens k)))
tokens
tokens)]
(ctob/group-by-type tokens)))
[empty-group filled-group]
(mf/with-memo [tokens-by-type]
(get-sorted-token-groups tokens-by-type))]
[:*
[:& token-context-menu]
[:& title-bar {:all-clickable true
:title (tr "workspace.token.tokens-section-title" selected-token-set-name)}]
(for [{:keys [token-key token-type-props tokens]} (:filled token-groups)]
[:> token-group* {:key token-key
:type token-key
(for [type filled-group]
(let [tokens (get tokens-by-type type)]
[:> token-group* {:key (name type)
:type type
:selected-shapes selected-shapes
:active-theme-tokens active-theme-tokens
:tokens tokens
:token-type-props token-type-props}])
:tokens tokens}]))
(for [{:keys [token-key token-type-props tokens]} (:empty token-groups)]
[:> token-group* {:key token-key
:type token-key
(for [type empty-group]
[:> token-group* {:key (name type)
:type type
:selected-shapes selected-shapes
:active-theme-tokens active-theme-tokens
:tokens tokens
:token-type-props token-type-props}])]))
:tokens []}])]))
(mf/defc import-export-button
{::mf/wrap-props false}

View file

@ -9,6 +9,7 @@
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.main.ui.ds.foundations.utilities.token.token-status :refer [token-status-icon*]]
[app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.token-types :as wtty]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[cuerdas.core :as str]
@ -95,9 +96,9 @@
(defn- generate-tooltip
"Generates a tooltip for a given token"
[is-viewer shape token-type-props token half-applied no-valid-value ref-not-in-active-set]
[is-viewer shape token half-applied no-valid-value ref-not-in-active-set]
(let [{:keys [name value resolved-value type]} token
{:keys [title]} token-type-props
{:keys [title] :as token-type-props} (get wtty/token-types (:type token))
applied-tokens (:applied-tokens shape)
app-token-vals (set (vals applied-tokens))
app-token-keys (keys applied-tokens)
@ -142,7 +143,7 @@
(contains? active-tokens match)))
(mf/defc token-pill*
[{:keys [on-click token full-applied on-context-menu half-applied selected-shapes token-type-props active-theme-tokens]}]
[{:keys [on-click token full-applied on-context-menu half-applied selected-shapes active-theme-tokens]}]
(let [{:keys [name value errors]} token
is-reference? (wtt/is-reference? token)
@ -203,8 +204,7 @@
(mf/deps selected-shapes is-viewer)
(fn [event]
(let [node (dom/get-current-target event)
title (generate-tooltip is-viewer (first selected-shapes)
token-type-props token
title (generate-tooltip is-viewer (first selected-shapes) token
half-applied no-valid-value ref-not-in-active-set)]
(dom/set-attribute! node "title" title))))]

View file

@ -6,9 +6,10 @@
(ns app.util.array
"A collection of helpers for work with javascript arrays."
(:refer-clojure :exclude [conj! conj filter map reduce find])
(:refer-clojure :exclude [conj! conj filter map reduce find sort])
(:require
[cljs.core :as c]))
[cljs.core :as c]
[goog.array :as garray]))
(defn conj
"A conj like function for js arrays."
@ -67,3 +68,9 @@
(defn find
[f v]
(.find ^js/Array v f))
(defn sort!
[a]
(garray/sort a compare)
a)