0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-23 15:26:29 -05:00

♻️ Changed layers component to reuse it in viewer

This commit is contained in:
alonso.torres 2023-12-11 13:06:17 +01:00
parent dfd8ff96b7
commit a0a479b08c
5 changed files with 325 additions and 179 deletions

View file

@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.viewer.inspect.left-sidebar
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@ -15,7 +16,9 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.shape-icon :as si]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.layer-item :refer [layer-item-inner]]
[app.main.ui.workspace.sidebar.layer-name :refer [layer-name]]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
@ -28,43 +31,55 @@
(l/derived st/state)))
(mf/defc layer-item
[{:keys [item selected objects disable-collapse?] :as props}]
(let [id (:id item)
name (:name item)
hidden? (:hidden item)
touched? (-> item :touched seq boolean)
[{:keys [item selected objects disable-collapse? depth component-child? hide-toggle?] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
id (:id item)
name (:name item)
hidden? (:hidden item)
touched? (-> item :touched seq boolean)
selected? (contains? selected id)
item-ref (mf/use-ref nil)
depth (+ depth 1)
file (mf/deref refs/viewer-file)
components-v2 (dm/get-in file [:data :options :components-v2])
main-instance? (if components-v2
(ctk/main-instance? item)
true)
collapsed-iref (mf/use-memo
(mf/deps id)
(make-collapsed-iref id))
file (mf/deref refs/viewer-file)
components-v2 (dm/get-in file [:data :options :components-v2])
main-instance?
(if components-v2
(ctk/main-instance? item)
true)
component-tree? (or component-child? (:component-root item))
collapsed-iref
(mf/use-memo
(mf/deps id)
(make-collapsed-iref id))
expanded? (not (mf/deref collapsed-iref))
absolute? (ctl/item-absolute? item)
toggle-collapse
(fn [event]
(dom/stop-propagation event)
(st/emit! (dv/toggle-collapse id)))
(mf/use-callback
(mf/deps id)
(fn [event]
(dom/stop-propagation event)
(st/emit! (dv/toggle-collapse id))))
select-shape
(fn [event]
(dom/prevent-default event)
(let [id (:id item)]
(cond
(kbd/mod? event)
(st/emit! (dv/toggle-selection id))
(mf/use-callback
(mf/deps id)
(fn [event]
(dom/prevent-default event)
(cond
(kbd/mod? event)
(st/emit! (dv/toggle-selection id))
(kbd/shift? event)
(st/emit! (dv/shift-select-to id))
(kbd/shift? event)
(st/emit! (dv/shift-select-to id))
:else
(st/emit! (dv/select-shape id)))))]
:else
(st/emit! (dv/select-shape id)))))]
(mf/use-effect
(mf/deps selected)
@ -72,55 +87,102 @@
(when (and (= (count selected) 1) selected?)
(dom/scroll-into-view-if-needed! (mf/ref-val item-ref) true))))
[:li {:ref item-ref
:class (dom/classnames
:component (not (nil? (:component-id item)))
:masked (:masked-group item)
:selected selected?)}
(if new-css-system
[:& layer-item-inner
{:ref item-ref
:item item
:depth depth
:read-only? true
:highlighted? false
:selected? selected?
:component-tree? component-tree?
:hidden? hidden?
:filtered? false
:expanded? expanded?
:hide-toggle? hide-toggle?
:on-select-shape select-shape
:on-toggle-collapse toggle-collapse}
[:div.element-list-body {:class (dom/classnames :selected selected?
:icon-layer (= (:type item) :icon))
:on-click select-shape}
[:div.icon
(when absolute?
[:div.absolute i/position-absolute])
[:& si/element-icon {:shape item :main-instance? main-instance?}]]
[:& layer-name {:shape-id id
:shape-name name
:shape-touched? touched?
:hidden? hidden?
:selected? selected?
:type-frame (cfh/frame-shape? item)
:disabled-double-click true}]
(when (and (:shapes item) expanded?)
[:div {:class (stl/css-case
:element-children true
:parent-selected selected?)}
(for [[index id] (reverse (d/enumerate (:shapes item)))]
(when-let [item (get objects id)]
[:& layer-item
{:item item
:selected selected
:index index
:objects objects
:key (dm/str id)
:depth depth
:component-child? component-tree?}]))])]
(when (and (not disable-collapse?) (:shapes item))
[:span.toggle-content
{:on-click toggle-collapse
:class (when expanded? "inverse")}
i/arrow-slide])]
;; OLD
[:li {:ref item-ref
:class (dom/classnames
:component (not (nil? (:component-id item)))
:masked (:masked-group item)
:selected selected?)}
(when (and (:shapes item) expanded?)
[:ul.element-children
(for [[index id] (reverse (d/enumerate (:shapes item)))]
(when-let [item (get objects id)]
[:& layer-item
{:item item
:selected selected
:index index
:objects objects
:key (:id item)}]))])]))
[:div.element-list-body {:class (dom/classnames :selected selected?
:icon-layer (= (:type item) :icon))
:on-click select-shape}
[:div.icon
(when absolute?
[:div.absolute i/position-absolute])
[:& si/element-icon {:shape item :main-instance? main-instance?}]]
[:& layer-name {:shape-id id
:shape-name name
:shape-touched? touched?
:hidden? hidden?
:selected? selected?
:type-frame (cfh/frame-shape? item)
:disabled-double-click true}]
(when (and (not disable-collapse?) (:shapes item))
[:span.toggle-content
{:on-click toggle-collapse
:class (when expanded? "inverse")}
i/arrow-slide])]
(when (and (:shapes item) expanded?)
[:ul.element-children
(for [[index id] (reverse (d/enumerate (:shapes item)))]
(when-let [item (get objects id)]
[:& layer-item
{:item item
:selected selected
:index index
:objects objects
:key (:id item)}]))])])))
(mf/defc left-sidebar
[{:keys [frame page local]}]
(let [selected (:selected local)
(let [new-css-system (mf/use-ctx ctx/new-css-system)
selected (:selected local)
objects (:objects page)]
[:aside.settings-bar.settings-bar-left
[:div.settings-bar-inside
[:ul.element-list
[:& layer-item
{:item frame
:selected selected
:index 0
:objects objects
:disable-collapse? true}]]]]))
(if new-css-system
[:aside {:class (stl/css :settings-bar-left)}
[:div {:class (stl/css :settings-bar-inside)}
[:div {:class (stl/css :element-list)}
[:& layer-item
{:item frame
:selected selected
:index 0
:objects objects
:sortable? false
:filtered? false
:depth -2
:hide-toggle? true}]]]]
[:aside.settings-bar.settings-bar-left
[:div.settings-bar-inside
[:ul.element-list
[:& layer-item
{:item frame
:selected selected
:index 0
:objects objects
:disable-collapse? true}]]]])))

View file

@ -0,0 +1,22 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
@use "common/refactor/common-refactor.scss" as *;
.settings-bar-left {
background-color: $db-primary;
height: 100%;
width: $s-256;
}
.settings-bar-inside {
display: grid;
grid-template-columns: 100%;
grid-template-rows: 100%;
height: calc(100% - $s-2);
overflow-y: auto;
padding-top: $s-8;
}

View file

@ -32,6 +32,129 @@
[okulary.core :as l]
[rumext.v2 :as mf]))
(mf/defc layer-item-inner
{::mf/wrap-props false
::mf/forward-ref true}
[{:keys [item depth parent-size name-ref children
;; Flags
read-only? highlighted? selected? component-tree?
filtered? expanded? dnd-over? dnd-over-top? dnd-over-bot? hide-toggle?
;; Callbacks
on-select-shape on-context-menu on-pointer-enter on-pointer-leave on-zoom-to-selected
on-toggle-collapse on-enable-drag on-disable-drag on-toggle-visibility on-toggle-blocking]}
dref]
(let [id (:id item)
name (:name item)
blocked? (:blocked item)
hidden? (:hidden item)
has-shapes? (-> item :shapes seq boolean)
touched? (-> item :touched seq boolean)
parent-board? (and (cfh/frame-shape? item)
(= uuid/zero (:parent-id item)))
absolute? (ctl/item-absolute? item)
components-v2 (mf/use-ctx ctx/components-v2)
main-instance? (or (not components-v2) (:main-instance item))]
[:*
[:div {:id id
:ref dref
:on-click on-select-shape
:on-context-menu on-context-menu
:class (stl/css-case
:layer-row true
:highlight highlighted?
:component (some? (:component-id item))
:masked (:masked-group item)
:selected selected?
:type-frame (cfh/frame-shape? item)
:type-bool (cfh/bool-shape? item)
:type-comp component-tree?
:hidden hidden?
:dnd-over dnd-over?
:dnd-over-top dnd-over-top?
:dnd-over-bot dnd-over-bot?
:root-board parent-board?)}
[:span {:class (stl/css-case
:tab-indentation true
:filtered filtered?)
:style {"--depth" depth}}]
[:div {:class (stl/css-case
:element-list-body true
:filtered filtered?
:selected selected?
:icon-layer (= (:type item) :icon))
:style {"--depth" depth}
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave
:on-double-click dom/stop-propagation}
(if (< 0 (count (:shapes item)))
[:div {:class (stl/css :button-content)}
(when (and (not hide-toggle?) (not filtered?))
[:button {:class (stl/css-case
:toggle-content true
:inverse expanded?)
:on-click on-toggle-collapse}
i/arrow-refactor])
[:div {:class (stl/css :icon-shape)
:on-double-click on-zoom-to-selected}
(when absolute?
[:div {:class (stl/css :absolute)}])
[:& sic/element-icon-refactor
{:shape item
:main-instance? main-instance?}]]]
[:div {:class (stl/css :button-content)}
(when (not ^boolean filtered?)
[:span {:class (stl/css :toggle-content)}])
[:div {:class (stl/css :icon-shape)
:on-double-click on-zoom-to-selected}
(when ^boolean absolute?
[:div {:class (stl/css :absolute)}])
[:& sic/element-icon-refactor
{:shape item
:main-instance? main-instance?}]]])
[:& layer-name {:ref name-ref
:shape-id id
:shape-name name
:shape-touched? touched?
:disabled-double-click read-only?
:on-start-edit on-disable-drag
:on-stop-edit on-enable-drag
:depth depth
:parent-size parent-size
:selected? selected?
:type-comp component-tree?
:type-frame (cfh/frame-shape? item)
:hidden? hidden?}]
(when (not read-only?)
[:div {:class (stl/css-case
:element-actions true
:is-parent has-shapes?
:selected hidden?
:selected blocked?)}
[:button {:class (stl/css-case
:toggle-element true
:selected hidden?)
:title (if hidden?
(tr "workspace.shape.menu.show")
(tr "workspace.shape.menu.hide"))
:on-click on-toggle-visibility}
(if ^boolean hidden? i/hide-refactor i/shown-refactor)]
[:button {:class (stl/css-case
:block-element true
:selected blocked?)
:title (if (:blocked item)
(tr "workspace.shape.menu.unlock")
(tr "workspace.shape.menu.lock"))
:on-click on-toggle-blocking}
(if ^boolean blocked? i/lock-refactor i/unlock-refactor)]])]]
children]))
(mf/defc layer-item
{::mf/wrap-props false}
[{:keys [index item selected objects sortable? filtered? depth parent-size component-child? highlighted]}]
@ -211,114 +334,44 @@
(let [scroll-to @scroll-to-middle?]
(ts/schedule
100
#(let [scroll-distance-ratio (dom/get-scroll-distance-ratio node scroll-node)
scroll-behavior (if (> scroll-distance-ratio 1) "instant" "smooth")]
(if scroll-to
(dom/scroll-into-view! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(do
(dom/scroll-into-view-if-needed! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(reset! scroll-to-middle? true)))))))]
#(when (and node scroll-node)
(let [scroll-distance-ratio (dom/get-scroll-distance-ratio node scroll-node)
scroll-behavior (if (> scroll-distance-ratio 1) "instant" "smooth")]
(if scroll-to
(dom/scroll-into-view! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(do
(dom/scroll-into-view-if-needed! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
(reset! scroll-to-middle? true))))))))]
#(when (some? subid)
(rx/dispose! subid))))
(if new-css-system
[:*
[:div {:on-context-menu on-context-menu
:ref dref
:on-click select-shape
:id id
:class (stl/css-case
:layer-row true
:highlight highlighted?
:component (some? (:component-id item))
:masked (:masked-group item)
:selected selected?
:type-frame (cfh/frame-shape? item)
:type-bool (cfh/bool-shape? item)
:type-comp component-tree?
:hidden hidden?
:dnd-over (= (:over dprops) :center)
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot)
:root-board parent-board?)}
[:span {:class (stl/css-case
:tab-indentation true
:filtered filtered?)
:style {"--depth" depth}}]
[:div {:class (stl/css-case
:element-list-body true
:filtered filtered?
:selected selected?
:icon-layer (= (:type item) :icon))
:style {"--depth" depth}
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave
:on-double-click dom/stop-propagation}
(if (< 0 (count (:shapes item)))
[:div {:class (stl/css :button-content)}
(when (not filtered?)
[:button {:class (stl/css-case
:toggle-content true
:inverse expanded?)
:on-click toggle-collapse}
i/arrow-refactor])
[:div {:class (stl/css :icon-shape)
:on-double-click zoom-to-selected}
(when absolute?
[:div {:class (stl/css :absolute)}])
[:& sic/element-icon-refactor
{:shape item
:main-instance? main-instance?}]]]
[:div {:class (stl/css :button-content)}
(when (not ^boolean filtered?)
[:span {:class (stl/css :toggle-content)}])
[:div {:class (stl/css :icon-shape)
:on-double-click zoom-to-selected}
(when ^boolean absolute?
[:div {:class (stl/css :absolute)}])
[:& sic/element-icon-refactor
{:shape item
:main-instance? main-instance?}]]])
[:& layer-name {:ref ref
:shape-id id
:shape-name name
:shape-touched? touched?
:disabled-double-click read-only?
:on-start-edit disable-drag
:on-stop-edit enable-drag
:depth depth
:parent-size parent-size
:selected? selected?
:type-comp component-tree?
:type-frame (cfh/frame-shape? item)
:hidden? hidden?}]
[:div {:class (stl/css-case
:element-actions true
:is-parent has-shapes?
:selected hidden?
:selected blocked?)}
[:button {:class (stl/css-case
:toggle-element true
:selected hidden?)
:title (if hidden?
(tr "workspace.shape.menu.show")
(tr "workspace.shape.menu.hide"))
:on-click toggle-visibility}
(if ^boolean hidden? i/hide-refactor i/shown-refactor)]
[:button {:class (stl/css-case
:block-element true
:selected blocked?)
:title (if (:blocked item)
(tr "workspace.shape.menu.unlock")
(tr "workspace.shape.menu.lock"))
:on-click toggle-blocking}
(if ^boolean blocked? i/lock-refactor i/unlock-refactor)]]]]
[:& layer-item-inner
{:ref dref
:item item
:depth depth
:parent-size parent-size
:name-ref ref
:read-only? read-only?
:highlighted? highlighted?
:selected? selected?
:component-tree? component-tree?
:filtered? filtered?
:expanded? expanded?
:dnd-over? (= (:over dprops) :center)
:dnd-over-top? (= (:over dprops) :top)
:dnd-over-bot? (= (:over dprops) :bot)
:on-select-shape select-shape
:on-context-menu on-context-menu
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave
:on-zoom-to-selected zoom-to-selected
:on-toggle-collapse toggle-collapse
:on-enable-drag enable-drag
:on-disable-drag disable-drag
:on-toggle-visibility toggle-visibility
:on-toggle-blocking toggle-blocking}
(when (and (:shapes item) expanded?)
[:div {:class (stl/css-case
@ -326,7 +379,6 @@
:parent-selected selected?
:sticky-children parent-board?)
:data-id (when ^boolean parent-board? id)}
(for [[index id] (reverse (d/enumerate (:shapes item)))]
(when-let [item (get objects id)]
[:& layer-item

View file

@ -12,6 +12,7 @@
align-items: center;
width: 100%;
background-color: var(--layer-row-background-color);
border: 2px solid transparent;
&.highlight,
&:hover {
@ -43,6 +44,16 @@
.parent-selected &:hover {
background-color: var(--layer-row-background-color-hover);
}
&.dnd-over-bot {
border-bottom: $s-2 solid var(--layer-row-foreground-color-hover);
}
&.dnd-over-top {
border-bottom: $s-2 solid var(--layer-row-foreground-color-hover);
}
&.dnd-over {
border: $s-2 solid var(--layer-row-foreground-color-hover);
}
}
.element-children {
@ -164,6 +175,9 @@
.layer-row.hidden & {
opacity: $op-7;
}
.layer-row.selected & {
stroke: var(--layer-row-foreground-color-selected);
}
.layer-row.type-comp & {
stroke: var(--layer-row-component-foreground-color);
}
@ -172,10 +186,6 @@
opacity: $op-10;
stroke: var(--layer-row-foreground-color-hover);
}
.layer-row.selected & {
stroke: var(--layer-row-foreground-color-selected);
}
}
.layer-row.selected & {

View file

@ -47,7 +47,7 @@
highlighted (hooks/use-equal-memo highlighted)
root (get objects uuid/zero)
new-css-system (mf/use-ctx ctx/new-css-system)]
[:ul
[:div
{:class (stl/css new-css-system :element-list)}
[:& hooks/sortable-container {}
(for [[index id] (reverse (d/enumerate (:shapes root)))]