mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
⚡ Improve handling open-status and tokens selection
This commit is contained in:
parent
c91b7606a0
commit
81036b9330
3 changed files with 46 additions and 39 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue