Improve handling open-status and tokens selection

This commit is contained in:
Andrey Antukh 2025-02-05 11:46:07 +01:00
parent c91b7606a0
commit 81036b9330
3 changed files with 46 additions and 39 deletions

View file

@ -312,7 +312,7 @@
(ptk/reify ::set-token-type-section-open (ptk/reify ::set-token-type-section-open
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc-in state [:workspace-tokens :open-status token-type] open?)))) (assoc-in state [:workspace-local :token-type-open-status token-type] open?))))
;; === Token Context Menu ;; === Token Context Menu

View file

@ -8,6 +8,7 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
@ -44,8 +45,8 @@
[rumext.v2 :as mf] [rumext.v2 :as mf]
[shadow.resource])) [shadow.resource]))
(def lens:token-type-open-status (def ref:token-type-open-status
(l/derived (l/in [:workspace-tokens :open-status]) st/state)) (l/derived #(dm/get-in % [:workspace-local :token-type-open-status]) st/state))
;; Components ------------------------------------------------------------------ ;; Components ------------------------------------------------------------------
@ -65,20 +66,19 @@
:sizing "expand" :sizing "expand"
"add")) "add"))
(defn attribute-actions [token selected-shapes attributes] (def ^:private
xf:map-id
(map :id))
(defn- all-selected? [token selected-shapes attributes]
(let [ids-by-attributes (wtt/shapes-ids-by-applied-attributes token selected-shapes attributes) (let [ids-by-attributes (wtt/shapes-ids-by-applied-attributes token selected-shapes attributes)
shape-ids (into #{} (map :id selected-shapes))] shape-ids (into #{} xf:map-id selected-shapes)]
{:all-selected? (wtt/shapes-applied-all? ids-by-attributes shape-ids attributes) (wtt/shapes-applied-all? ids-by-attributes shape-ids attributes)))
:shape-ids shape-ids
:selected-pred #(seq (% ids-by-attributes))}))
(mf/defc token-group* (mf/defc token-group*
{::mf/private true} {::mf/private true}
[{:keys [type tokens selected-shapes active-theme-tokens]}] [{:keys [type tokens selected-shapes active-theme-tokens is-open]}]
(let [open? (mf/deref (-> (l/key type) (let [{:keys [modal attributes all-attributes title] :as token-type-props}
(l/derived lens:token-type-open-status)))
{:keys [modal attributes all-attributes title] :as token-type-props}
(get wtch/token-properties type) (get wtch/token-properties type)
tokens tokens
@ -98,23 +98,24 @@
on-toggle-open-click on-toggle-open-click
(mf/use-fn (mf/use-fn
(mf/deps open? tokens) (mf/deps is-open type)
#(st/emit! (dt/set-token-type-section-open type (not open?)))) #(st/emit! (dt/set-token-type-section-open type (not is-open))))
on-popover-open-click on-popover-open-click
(mf/use-fn (mf/use-fn
(mf/deps type title modal)
(fn [event] (fn [event]
(mf/deps type title) (dom/stop-propagation event)
(let [{:keys [key fields]} modal] (st/emit! (dt/set-token-type-section-open type true)
(dom/stop-propagation event) ;; FIXME: use dom/get-client-position
(st/emit! (dt/set-token-type-section-open type true)) (modal/show (:key modal)
(modal/show! key {:x (.-clientX ^js event) {:x (.-clientX ^js event)
:y (.-clientY ^js event) :y (.-clientY ^js event)
:position :right :position :right
:fields fields :fields (:fields modal)
:title title :title title
:action "create" :action "create"
:token-type type})))) :token-type type}))))
on-token-pill-click on-token-pill-click
(mf/use-fn (mf/use-fn
@ -131,7 +132,7 @@
[:& cmm/asset-section {:icon (token-section-icon type) [:& cmm/asset-section {:icon (token-section-icon type)
:title title :title title
:assets-count tokens-count :assets-count tokens-count
:open? open?} :open? is-open}
[:& cmm/asset-section-block {:role :title-button} [:& cmm/asset-section-block {:role :title-button}
(when can-edit? (when can-edit?
[:> icon-button* {:on-click on-popover-open-click [:> icon-button* {:on-click on-popover-open-click
@ -139,13 +140,13 @@
:icon "add" :icon "add"
;; TODO: This needs translation ;; TODO: This needs translation
:aria-label (str "Add token: " title)}])] :aria-label (str "Add token: " title)}])]
(when open? (when is-open
[:& cmm/asset-section-block {:role :content} [:& cmm/asset-section-block {:role :content}
[:div {:class (stl/css :token-pills-wrapper)} [:div {:class (stl/css :token-pills-wrapper)}
(for [token tokens] (for [token tokens]
(let [theme-token (get active-theme-tokens (:name token)) (let [theme-token (get active-theme-tokens (:name token))
multiple-selection (< 1 (count selected-shapes)) multiple-selection (< 1 (count selected-shapes))
full-applied (:all-selected? (attribute-actions token selected-shapes (or all-attributes attributes))) full-applied (all-selected? token selected-shapes (or all-attributes attributes))
applied (wtt/shapes-token-applied? token selected-shapes (or all-attributes attributes))] applied (wtt/shapes-token-applied? token selected-shapes (or all-attributes attributes))]
[:> token-pill* [:> token-pill*
@ -270,6 +271,7 @@
[] []
(let [objects (mf/deref refs/workspace-page-objects) (let [objects (mf/deref refs/workspace-page-objects)
selected (mf/deref refs/selected-shapes) selected (mf/deref refs/selected-shapes)
open-status (mf/deref ref:token-type-open-status)
selected-shapes selected-shapes
(mf/with-memo [selected objects] (mf/with-memo [selected objects]
@ -309,6 +311,7 @@
(for [type filled-group] (for [type filled-group]
(let [tokens (get tokens-by-type type)] (let [tokens (get tokens-by-type type)]
[:> token-group* {:key (name type) [:> token-group* {:key (name type)
:is-open (get open-status type false)
:type type :type type
:selected-shapes selected-shapes :selected-shapes selected-shapes
:active-theme-tokens active-theme-tokens :active-theme-tokens active-theme-tokens

View file

@ -1,6 +1,7 @@
(ns app.main.ui.workspace.tokens.token (ns app.main.ui.workspace.tokens.token
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.ui.workspace.tokens.tinycolor :as tinycolor] [app.main.ui.workspace.tokens.tinycolor :as tinycolor]
[clojure.set :as set] [clojure.set :as set]
[cuerdas.core :as str])) [cuerdas.core :as str]))
@ -45,7 +46,7 @@
(defn token-attribute-applied? (defn token-attribute-applied?
"Test if `token` is applied to a `shape` on single `token-attribute`." "Test if `token` is applied to a `shape` on single `token-attribute`."
[token shape token-attribute] [token shape token-attribute]
(when-let [id (get-in shape [:applied-tokens token-attribute])] (when-let [id (dm/get-in shape [:applied-tokens token-attribute])]
(= (token-identifier token) id))) (= (token-identifier token) id)))
(defn token-applied? (defn token-applied?
@ -58,15 +59,18 @@
[token shapes token-attributes] [token shapes token-attributes]
(some #(token-applied? token % token-attributes) shapes)) (some #(token-applied? token % token-attributes) shapes))
(defn shapes-ids-by-applied-attributes [token shapes token-attributes] (defn shapes-ids-by-applied-attributes
(reduce (fn [acc shape] [token shapes token-attributes]
(let [applied-ids-by-attribute (->> (map #(when (token-attribute-applied? token shape %) (let [conj* (fnil conj #{})]
[% #{(:id shape)}]) (reduce (fn [result shape]
token-attributes) (let [shape-id (dm/get-prop shape :id)]
(filter some?) (->> token-attributes
(into {}))] (filter #(token-attribute-applied? token shape %))
(merge-with into acc applied-ids-by-attribute))) (reduce (fn [result attr]
{} shapes)) (update result attr conj* shape-id))
result))))
{}
shapes)))
(defn shapes-applied-all? [ids-by-attributes shape-ids attributes] (defn shapes-applied-all? [ids-by-attributes shape-ids attributes]
(every? #(set/superset? (get ids-by-attributes %) shape-ids) attributes)) (every? #(set/superset? (get ids-by-attributes %) shape-ids) attributes))