Add open components, and scroll into view to show main component acction

This commit is contained in:
eva 2021-12-28 12:38:25 +01:00 committed by Alonso Torres
parent c69d7f50a3
commit 6dae420254
6 changed files with 148 additions and 85 deletions

View file

@ -5,6 +5,7 @@
### :boom: Breaking changes ### :boom: Breaking changes
### :sparkles: New features ### :sparkles: New features
- Add actions to go to main component context menu option [Taiga #2053](https://tree.taiga.io/project/penpot/us/2053).
- Add contrast between component select color and shape select color [Taiga #2121](https://tree.taiga.io/project/penpot/issue/2121). - Add contrast between component select color and shape select color [Taiga #2121](https://tree.taiga.io/project/penpot/issue/2121).
- Add animations in interactions [Taiga #2244](https://tree.taiga.io/project/penpot/us/2244). - Add animations in interactions [Taiga #2244](https://tree.taiga.io/project/penpot/us/2244).

View file

@ -44,10 +44,12 @@
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.streams :as ms] [app.main.streams :as ms]
[app.main.worker :as uw] [app.main.worker :as uw]
[app.util.dom :as dom]
[app.util.globals :as ug] [app.util.globals :as ug]
[app.util.http :as http] [app.util.http :as http]
[app.util.i18n :as i18n] [app.util.i18n :as i18n]
[app.util.router :as rt] [app.util.router :as rt]
[app.util.timers :as tm]
[app.util.webapi :as wapi] [app.util.webapi :as wapi]
[beicon.core :as rx] [beicon.core :as rx]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -111,6 +113,10 @@
{:zoom 1 {:zoom 1
:flags #{} :flags #{}
:selected (d/ordered-set) :selected (d/ordered-set)
:selected-assets {:components #{}
:graphics #{}
:colors #{}
:typographies #{}}
:expanded {} :expanded {}
:tooltip nil :tooltip nil
:options-mode :design :options-mode :design
@ -1305,6 +1311,66 @@
qparams {:page-id page-id :layout (name layout)}] qparams {:page-id page-id :layout (name layout)}]
(rx/of (rt/nav :workspace pparams qparams)))))) (rx/of (rt/nav :workspace pparams qparams))))))
(defn check-in-asset
[set element]
(if (contains? set element)
(disj set element)
(conj set element)))
(defn toggle-selected-assets
[asset type]
(ptk/reify ::toggle-selected-assets
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :selected-assets type] #(check-in-asset % asset)))))
(defn select-single-asset
[asset type]
(ptk/reify ::select-single-asset
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-local :selected-assets type] #{asset}))))
(defn select-assets
[assets type]
(ptk/reify ::select-assets
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-local :selected-assets type] (into #{} assets)))))
(defn unselect-all-assets
[]
(ptk/reify ::unselect-all-assets
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-local :selected-assets] {:components #{}
:graphics #{}
:colors #{}
:typographies #{}}))))
(defn go-to-component
[objs]
(ptk/reify ::set-workspace-layout-component
IDeref
(-deref [_] {:layout :assets})
ptk/WatchEvent
(watch [_ state _]
(let [project-id (get-in state [:workspace-project :id])
file-id (get-in state [:workspace-file :id])
page-id (get state :current-page-id)
component-id (get (first objs) :component-id)
pparams {:file-id file-id :project-id project-id}
qparams {:page-id page-id :layout :assets}]
(rx/of (rt/nav :workspace pparams qparams)
(dwl/set-assets-box-open file-id :library true)
(dwl/set-assets-box-open file-id :components true)
(select-single-asset component-id :components))))
ptk/EffectEvent
(effect [_ _ _]
(let [component-id (get (first objs) :component-id)
wrapper-id (str "component-shape-id-" component-id)]
(tm/schedule-on-idle #(dom/scroll-into-view-if-needed! (dom/get-element wrapper-id)))))))
(def go-to-file (def go-to-file
(ptk/reify ::go-to-file (ptk/reify ::go-to-file
ptk/WatchEvent ptk/WatchEvent

View file

@ -155,6 +155,9 @@
(def editors (def editors
(l/derived :editors workspace-local)) (l/derived :editors workspace-local))
(def selected-assets
(l/derived :selected-assets workspace-local))
(def workspace-layout (def workspace-layout
(l/derived :workspace-layout st/state)) (l/derived :workspace-layout st/state))

View file

@ -168,7 +168,7 @@
:accept-label (tr "modals.update-remote-component.accept") :accept-label (tr "modals.update-remote-component.accept")
:accept-style :primary :accept-style :primary
:on-accept confirm-update-remote-component})) :on-accept confirm-update-remote-component}))
do-show-component (st/emitf (dw/go-to-layout :assets)) do-show-component (st/emitf (dw/go-to-component selected-objects))
do-navigate-component-file (st/emitf (dwl/nav-to-component-file do-navigate-component-file (st/emitf (dwl/nav-to-component-file
(:component-file shape))) (:component-file shape)))

View file

@ -273,6 +273,7 @@
:selected (contains? selected-components (:id component)) :selected (contains? selected-components (:id component))
:grid-cell @listing-thumbs? :grid-cell @listing-thumbs?
:enum-item (not @listing-thumbs?)) :enum-item (not @listing-thumbs?))
:id (str "component-shape-id-" (:id component))
:draggable true :draggable true
:on-click #(on-asset-click % (:id component) nil) :on-click #(on-asset-click % (:id component) nil)
:on-context-menu (on-context-menu (:id component)) :on-context-menu (on-context-menu (:id component))
@ -1402,15 +1403,12 @@
reverse-sort? (mf/use-state false) reverse-sort? (mf/use-state false)
listing-thumbs? (mf/use-state true) listing-thumbs? (mf/use-state true)
selected-assets (mf/use-state {:components #{} selected-assets (mf/deref refs/selected-assets)
:graphics #{}
:colors #{}
:typographies #{}})
selected-count (+ (count (:components @selected-assets)) selected-count (+ (count (:components selected-assets))
(count (:graphics @selected-assets)) (count (:graphics selected-assets))
(count (:colors @selected-assets)) (count (:colors selected-assets))
(count (:typographies @selected-assets))) (count (:typographies selected-assets)))
toggle-open (st/emitf (dwl/set-assets-box-open (:id file) :library (not open?))) toggle-open (st/emitf (dwl/set-assets-box-open (:id file) :library (not open?)))
@ -1441,92 +1439,81 @@
(fn [_] (fn [_]
(swap! listing-thumbs? not))) (swap! listing-thumbs? not)))
toggle-selected-asset
(mf/use-callback
(mf/deps @selected-assets)
(fn [asset-type asset-id]
(swap! selected-assets update asset-type
(fn [selected]
(if (contains? selected asset-id)
(disj selected asset-id)
(conj selected asset-id))))))
extend-selected-assets extend-selected-assets
(mf/use-callback (mf/use-callback
(mf/deps @selected-assets) (mf/deps selected-assets)
(fn [asset-type asset-groups asset-id] (fn [asset-type asset-groups asset-id]
(letfn [(flatten-groups (letfn [(flatten-groups
[groups] [groups]
(concat (concat
(get groups "" []) (get groups "" [])
(reduce concat (reduce concat
[] (into []
(->> (filter #(seq (first %)) groups) (->> (filter #(seq (first %)) groups)
(map second) (map second)
(map flatten-groups)))))] (mapcat flatten-groups))))))]
(swap! selected-assets update asset-type (let [selected-assets-type (get selected-assets asset-type)
(fn [selected] count-assets (count selected-assets-type)]
(let [all-assets (flatten-groups asset-groups) (if (<= count-assets 0)
clicked-idx (d/index-of-pred all-assets #(= (:id %) asset-id)) (st/emit! (dw/select-single-asset asset-id asset-type))
selected-idx (->> selected (let [all-assets (flatten-groups asset-groups)
(map (fn [id] clicked-idx (d/index-of-pred all-assets #(= (:id %) asset-id))
(d/index-of-pred all-assets components (get selected-assets asset-type)
#(= (:id %) id)))))
min-idx (apply min (conj selected-idx clicked-idx))
max-idx (apply max (conj selected-idx clicked-idx))]
(->> all-assets first-idx (first (sort (map (fn [asset] (d/index-of-pred all-assets #(= (:id %) asset))) components)))
d/enumerate selected-idx (vector first-idx clicked-idx)
(filter #(<= min-idx (first %) max-idx)) min-idx (apply min (conj selected-idx clicked-idx))
(map #(-> % second :id)) max-idx (apply max (conj selected-idx clicked-idx))
set))))))) values (->> all-assets
d/enumerate
(filter #(<= min-idx (first %) max-idx))
(map #(-> % second :id))
set)]
(st/emit! (dw/select-assets values asset-type))))))))
unselect-all unselect-all
(mf/use-callback (mf/use-callback
(fn [] (fn []
(swap! selected-assets {:components #{} (st/emit! (dw/unselect-all-assets))))
:graphics #{}
:colors #{}
:typographies #{}})))
on-asset-click on-asset-click
(mf/use-callback (mf/use-callback
(mf/deps toggle-selected-asset extend-selected-assets) (mf/deps extend-selected-assets selected-assets)
(fn [asset-type asset-groups event asset-id default-click] (fn [asset-type asset-groups event asset-id default-click]
(cond (cond
(kbd/ctrl? event) (kbd/ctrl? event)
(do (do
(dom/stop-propagation event) (dom/stop-propagation event)
(toggle-selected-asset asset-type asset-id)) (st/emit! (dw/toggle-selected-assets asset-id asset-type)))
(kbd/shift? event) (kbd/shift? event)
(do (do
(dom/stop-propagation event) (dom/stop-propagation event)
(extend-selected-assets asset-type asset-groups asset-id)) (extend-selected-assets asset-type asset-groups asset-id))
:else :else
(when default-click (when default-click
(default-click event))))) (default-click event)))))
on-assets-delete on-assets-delete
(mf/use-callback (mf/use-callback
(mf/deps @selected-assets) (mf/deps selected-assets)
(fn [] (fn []
(let [selected-assets @selected-assets] (st/emit! (dwu/start-undo-transaction))
(st/emit! (dwu/start-undo-transaction)) (apply st/emit! (map #(dwl/delete-component {:id %})
(apply st/emit! (map #(dwl/delete-component {:id %}) (:components selected-assets)))
(:components selected-assets))) (apply st/emit! (map #(dwl/delete-media {:id %})
(apply st/emit! (map #(dwl/delete-media {:id %}) (:graphics selected-assets)))
(:graphics selected-assets))) (apply st/emit! (map #(dwl/delete-color {:id %})
(apply st/emit! (map #(dwl/delete-color {:id %}) (:colors selected-assets)))
(:colors selected-assets))) (apply st/emit! (map #(dwl/delete-typography %)
(apply st/emit! (map #(dwl/delete-typography %) (:typographies selected-assets)))
(:typographies selected-assets))) (when (or (d/not-empty? (:components selected-assets))
(when (or (d/not-empty? (:components selected-assets)) (d/not-empty? (:colors selected-assets))
(d/not-empty? (:colors selected-assets)) (d/not-empty? (:typographies selected-assets)))
(d/not-empty? (:typographies selected-assets))) (st/emit! (dwl/sync-file (:id file) (:id file))))
(st/emit! (dwl/sync-file (:id file) (:id file)))) (st/emit! (dwu/commit-undo-transaction))))]
(st/emit! (dwu/commit-undo-transaction)))))]
[:div.tool-window {:on-context-menu #(dom/prevent-default %) [:div.tool-window {:on-context-menu #(dom/prevent-default %)
:on-click unselect-all} :on-click unselect-all}
@ -1588,7 +1575,7 @@
:open? (open-box? :components) :open? (open-box? :components)
:open-groups (open-groups :components) :open-groups (open-groups :components)
:reverse-sort? @reverse-sort? :reverse-sort? @reverse-sort?
:selected-assets @selected-assets :selected-assets selected-assets
:on-asset-click (partial on-asset-click :components) :on-asset-click (partial on-asset-click :components)
:on-assets-delete on-assets-delete :on-assets-delete on-assets-delete
:on-clear-selection unselect-all}]) :on-clear-selection unselect-all}])
@ -1601,7 +1588,7 @@
:open? (open-box? :graphics) :open? (open-box? :graphics)
:open-groups (open-groups :graphics) :open-groups (open-groups :graphics)
:reverse-sort? @reverse-sort? :reverse-sort? @reverse-sort?
:selected-assets @selected-assets :selected-assets selected-assets
:on-asset-click (partial on-asset-click :graphics) :on-asset-click (partial on-asset-click :graphics)
:on-assets-delete on-assets-delete :on-assets-delete on-assets-delete
:on-clear-selection unselect-all}]) :on-clear-selection unselect-all}])
@ -1612,7 +1599,7 @@
:open? (open-box? :colors) :open? (open-box? :colors)
:open-groups (open-groups :colors) :open-groups (open-groups :colors)
:reverse-sort? @reverse-sort? :reverse-sort? @reverse-sort?
:selected-assets @selected-assets :selected-assets selected-assets
:on-asset-click (partial on-asset-click :colors) :on-asset-click (partial on-asset-click :colors)
:on-assets-delete on-assets-delete :on-assets-delete on-assets-delete
:on-clear-selection unselect-all}]) :on-clear-selection unselect-all}])
@ -1625,7 +1612,7 @@
:open? (open-box? :typographies) :open? (open-box? :typographies)
:open-groups (open-groups :typographies) :open-groups (open-groups :typographies)
:reverse-sort? @reverse-sort? :reverse-sort? @reverse-sort?
:selected-assets @selected-assets :selected-assets selected-assets
:on-asset-click (partial on-asset-click :typographies) :on-asset-click (partial on-asset-click :typographies)
:on-assets-delete on-assets-delete :on-assets-delete on-assets-delete
:on-clear-selection unselect-all}]) :on-clear-selection unselect-all}])

View file

@ -354,6 +354,12 @@
([element scroll-top] ([element scroll-top]
(.scrollIntoView ^js element scroll-top))) (.scrollIntoView ^js element scroll-top)))
(defn scroll-into-view-if-needed!
([element]
(.scrollIntoViewIfNeeded ^js element false))
([element scroll-top]
(.scrollIntoViewIfNeeded ^js element scroll-top)))
(defn is-in-viewport? (defn is-in-viewport?
[element] [element]
(let [rect (.getBoundingClientRect element) (let [rect (.getBoundingClientRect element)