mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 16:21:57 -05:00
✨ Add open components, and scroll into view to show main component acction
This commit is contained in:
parent
c69d7f50a3
commit
6dae420254
6 changed files with 148 additions and 85 deletions
|
@ -5,6 +5,7 @@
|
|||
### :boom: Breaking changes
|
||||
### :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 animations in interactions [Taiga #2244](https://tree.taiga.io/project/penpot/us/2244).
|
||||
|
||||
|
|
|
@ -44,10 +44,12 @@
|
|||
[app.main.repo :as rp]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n]
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
|
@ -111,6 +113,10 @@
|
|||
{:zoom 1
|
||||
:flags #{}
|
||||
:selected (d/ordered-set)
|
||||
:selected-assets {:components #{}
|
||||
:graphics #{}
|
||||
:colors #{}
|
||||
:typographies #{}}
|
||||
:expanded {}
|
||||
:tooltip nil
|
||||
:options-mode :design
|
||||
|
@ -1305,6 +1311,66 @@
|
|||
qparams {:page-id page-id :layout (name layout)}]
|
||||
(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
|
||||
(ptk/reify ::go-to-file
|
||||
ptk/WatchEvent
|
||||
|
|
|
@ -155,6 +155,9 @@
|
|||
(def editors
|
||||
(l/derived :editors workspace-local))
|
||||
|
||||
(def selected-assets
|
||||
(l/derived :selected-assets workspace-local))
|
||||
|
||||
(def workspace-layout
|
||||
(l/derived :workspace-layout st/state))
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
:accept-label (tr "modals.update-remote-component.accept")
|
||||
:accept-style :primary
|
||||
: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
|
||||
(:component-file shape)))
|
||||
|
||||
|
|
|
@ -273,6 +273,7 @@
|
|||
:selected (contains? selected-components (:id component))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:id (str "component-shape-id-" (:id component))
|
||||
:draggable true
|
||||
:on-click #(on-asset-click % (:id component) nil)
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
|
@ -1402,15 +1403,12 @@
|
|||
reverse-sort? (mf/use-state false)
|
||||
listing-thumbs? (mf/use-state true)
|
||||
|
||||
selected-assets (mf/use-state {:components #{}
|
||||
:graphics #{}
|
||||
:colors #{}
|
||||
:typographies #{}})
|
||||
selected-assets (mf/deref refs/selected-assets)
|
||||
|
||||
selected-count (+ (count (:components @selected-assets))
|
||||
(count (:graphics @selected-assets))
|
||||
(count (:colors @selected-assets))
|
||||
(count (:typographies @selected-assets)))
|
||||
selected-count (+ (count (:components selected-assets))
|
||||
(count (:graphics selected-assets))
|
||||
(count (:colors selected-assets))
|
||||
(count (:typographies selected-assets)))
|
||||
|
||||
toggle-open (st/emitf (dwl/set-assets-box-open (:id file) :library (not open?)))
|
||||
|
||||
|
@ -1441,92 +1439,81 @@
|
|||
(fn [_]
|
||||
(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
|
||||
(mf/use-callback
|
||||
(mf/deps @selected-assets)
|
||||
(fn [asset-type asset-groups asset-id]
|
||||
(letfn [(flatten-groups
|
||||
[groups]
|
||||
(concat
|
||||
(get groups "" [])
|
||||
(reduce concat
|
||||
[]
|
||||
(->> (filter #(seq (first %)) groups)
|
||||
(map second)
|
||||
(map flatten-groups)))))]
|
||||
(swap! selected-assets update asset-type
|
||||
(fn [selected]
|
||||
(let [all-assets (flatten-groups asset-groups)
|
||||
clicked-idx (d/index-of-pred all-assets #(= (:id %) asset-id))
|
||||
selected-idx (->> selected
|
||||
(map (fn [id]
|
||||
(d/index-of-pred all-assets
|
||||
#(= (:id %) id)))))
|
||||
min-idx (apply min (conj selected-idx clicked-idx))
|
||||
max-idx (apply max (conj selected-idx clicked-idx))]
|
||||
(mf/deps selected-assets)
|
||||
(fn [asset-type asset-groups asset-id]
|
||||
(letfn [(flatten-groups
|
||||
[groups]
|
||||
(concat
|
||||
(get groups "" [])
|
||||
(reduce concat
|
||||
(into []
|
||||
(->> (filter #(seq (first %)) groups)
|
||||
(map second)
|
||||
(mapcat flatten-groups))))))]
|
||||
(let [selected-assets-type (get selected-assets asset-type)
|
||||
count-assets (count selected-assets-type)]
|
||||
(if (<= count-assets 0)
|
||||
(st/emit! (dw/select-single-asset asset-id asset-type))
|
||||
(let [all-assets (flatten-groups asset-groups)
|
||||
clicked-idx (d/index-of-pred all-assets #(= (:id %) asset-id))
|
||||
components (get selected-assets asset-type)
|
||||
|
||||
(->> all-assets
|
||||
d/enumerate
|
||||
(filter #(<= min-idx (first %) max-idx))
|
||||
(map #(-> % second :id))
|
||||
set)))))))
|
||||
first-idx (first (sort (map (fn [asset] (d/index-of-pred all-assets #(= (:id %) asset))) components)))
|
||||
selected-idx (vector first-idx clicked-idx)
|
||||
min-idx (apply min (conj selected-idx clicked-idx))
|
||||
max-idx (apply max (conj selected-idx clicked-idx))
|
||||
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
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(swap! selected-assets {:components #{}
|
||||
:graphics #{}
|
||||
:colors #{}
|
||||
:typographies #{}})))
|
||||
(fn []
|
||||
(st/emit! (dw/unselect-all-assets))))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-callback
|
||||
(mf/deps toggle-selected-asset extend-selected-assets)
|
||||
(fn [asset-type asset-groups event asset-id default-click]
|
||||
(cond
|
||||
(kbd/ctrl? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(toggle-selected-asset asset-type asset-id))
|
||||
(mf/deps extend-selected-assets selected-assets)
|
||||
(fn [asset-type asset-groups event asset-id default-click]
|
||||
(cond
|
||||
(kbd/ctrl? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/toggle-selected-assets asset-id asset-type)))
|
||||
|
||||
(kbd/shift? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(extend-selected-assets asset-type asset-groups asset-id))
|
||||
(kbd/shift? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(extend-selected-assets asset-type asset-groups asset-id))
|
||||
|
||||
:else
|
||||
(when default-click
|
||||
(default-click event)))))
|
||||
:else
|
||||
(when default-click
|
||||
(default-click event)))))
|
||||
|
||||
on-assets-delete
|
||||
(mf/use-callback
|
||||
(mf/deps @selected-assets)
|
||||
(fn []
|
||||
(let [selected-assets @selected-assets]
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit! (map #(dwl/delete-component {:id %})
|
||||
(:components selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-media {:id %})
|
||||
(:graphics selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-color {:id %})
|
||||
(:colors selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-typography %)
|
||||
(:typographies selected-assets)))
|
||||
(when (or (d/not-empty? (:components selected-assets))
|
||||
(d/not-empty? (:colors selected-assets))
|
||||
(d/not-empty? (:typographies selected-assets)))
|
||||
(st/emit! (dwl/sync-file (:id file) (:id file))))
|
||||
(st/emit! (dwu/commit-undo-transaction)))))]
|
||||
(mf/deps selected-assets)
|
||||
(fn []
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit! (map #(dwl/delete-component {:id %})
|
||||
(:components selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-media {:id %})
|
||||
(:graphics selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-color {:id %})
|
||||
(:colors selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-typography %)
|
||||
(:typographies selected-assets)))
|
||||
(when (or (d/not-empty? (:components selected-assets))
|
||||
(d/not-empty? (:colors selected-assets))
|
||||
(d/not-empty? (:typographies selected-assets)))
|
||||
(st/emit! (dwl/sync-file (:id file) (:id file))))
|
||||
(st/emit! (dwu/commit-undo-transaction))))]
|
||||
|
||||
[:div.tool-window {:on-context-menu #(dom/prevent-default %)
|
||||
:on-click unselect-all}
|
||||
|
@ -1588,7 +1575,7 @@
|
|||
:open? (open-box? :components)
|
||||
:open-groups (open-groups :components)
|
||||
:reverse-sort? @reverse-sort?
|
||||
:selected-assets @selected-assets
|
||||
:selected-assets selected-assets
|
||||
:on-asset-click (partial on-asset-click :components)
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection unselect-all}])
|
||||
|
@ -1601,7 +1588,7 @@
|
|||
:open? (open-box? :graphics)
|
||||
:open-groups (open-groups :graphics)
|
||||
:reverse-sort? @reverse-sort?
|
||||
:selected-assets @selected-assets
|
||||
:selected-assets selected-assets
|
||||
:on-asset-click (partial on-asset-click :graphics)
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection unselect-all}])
|
||||
|
@ -1612,7 +1599,7 @@
|
|||
:open? (open-box? :colors)
|
||||
:open-groups (open-groups :colors)
|
||||
:reverse-sort? @reverse-sort?
|
||||
:selected-assets @selected-assets
|
||||
:selected-assets selected-assets
|
||||
:on-asset-click (partial on-asset-click :colors)
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection unselect-all}])
|
||||
|
@ -1625,7 +1612,7 @@
|
|||
:open? (open-box? :typographies)
|
||||
:open-groups (open-groups :typographies)
|
||||
:reverse-sort? @reverse-sort?
|
||||
:selected-assets @selected-assets
|
||||
:selected-assets selected-assets
|
||||
:on-asset-click (partial on-asset-click :typographies)
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection unselect-all}])
|
||||
|
|
|
@ -354,6 +354,12 @@
|
|||
([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?
|
||||
[element]
|
||||
(let [rect (.getBoundingClientRect element)
|
||||
|
|
Loading…
Add table
Reference in a new issue