mirror of
https://github.com/penpot/penpot.git
synced 2025-02-08 16:18:11 -05:00
🎉 Show assets as a list
This commit is contained in:
parent
112e656f40
commit
e8da04d4ab
7 changed files with 150 additions and 57 deletions
|
@ -65,6 +65,7 @@
|
|||
(d/export helpers/parse-path-name)
|
||||
(d/export helpers/merge-path-item)
|
||||
(d/export helpers/compact-path)
|
||||
(d/export helpers/compact-name)
|
||||
|
||||
;; Process changes
|
||||
(d/export changes/process-changes)
|
||||
|
|
|
@ -460,13 +460,19 @@
|
|||
(d/enumerate (:shapes parent)))]
|
||||
parent-idx))
|
||||
|
||||
(defn split-path
|
||||
[path]
|
||||
"Decompose a string in the form 'one / two / three' into
|
||||
an array of strings, normalizing spaces."
|
||||
(->> (str/split path "/")
|
||||
(map str/trim)
|
||||
(remove str/empty?)))
|
||||
|
||||
(defn parse-path-name
|
||||
"Parse a string in the form 'group / subgroup / name'.
|
||||
Retrieve the path and the name in separated values, normalizing spaces."
|
||||
[path-name]
|
||||
(let [path-name-split (->> (str/split path-name "/")
|
||||
(map str/trim)
|
||||
(remove str/empty?))
|
||||
(let [path-name-split (split-path path-name)
|
||||
path (str/join " / " (butlast path-name-split))
|
||||
name (last path-name-split)]
|
||||
[path name]))
|
||||
|
@ -479,14 +485,13 @@
|
|||
name))
|
||||
|
||||
(defn compact-path
|
||||
"Separate last component of the path, and truncate the others if too long:
|
||||
"Separate last item of the path, and truncate the others if too long:
|
||||
'one' -> ['' 'one' false]
|
||||
'one / two / three' -> ['one / two' 'three' false]
|
||||
'one / two / three / four' -> ['one / two / ...' 'four' true]
|
||||
'one-item-but-very-long / two' -> ['...' 'two' true] "
|
||||
[path max-length]
|
||||
(let [path-split (->> (str/split path "/")
|
||||
(map str/trim))
|
||||
(let [path-split (split-path path)
|
||||
last-item (last path-split)]
|
||||
(loop [other-items (seq (butlast path-split))
|
||||
other-path ""]
|
||||
|
@ -500,3 +505,9 @@
|
|||
(merge-path-item other-path item))))
|
||||
[other-path last-item false]))))
|
||||
|
||||
(defn compact-name
|
||||
"Append the first item of the path and the name."
|
||||
[path name]
|
||||
(let [path-split (split-path path)]
|
||||
(merge-path-item (first path-split) name)))
|
||||
|
||||
|
|
Before Width: | Height: | Size: 446 B After Width: | Height: | Size: 446 B |
|
@ -305,6 +305,56 @@
|
|||
border: 2px solid $color-primary;
|
||||
}
|
||||
|
||||
.asset-title + .asset-enum {
|
||||
margin-top: $small;
|
||||
}
|
||||
|
||||
.asset-enum {
|
||||
.enum-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $small;
|
||||
cursor: pointer;
|
||||
|
||||
& > svg,
|
||||
& > img {
|
||||
background-color: $color-canvas;
|
||||
border-radius: 4px;
|
||||
border: 2px solid transparent;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: $small;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
width: calc(100% - 24px - #{$small});
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
|
||||
&.editing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.editable-label-input {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.editable-label-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.enum-item:hover,
|
||||
.enum-item.selected,
|
||||
{
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: see if this is useful, or is better to leave only
|
||||
one scroll bar in the whole sidebar
|
||||
(also see .asset-section) */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
(mf/defc editable-label
|
||||
[{:keys [value on-change on-cancel editing? disable-dbl-click? class-name] :as props}]
|
||||
(let [display-value (get props :display-value value)
|
||||
tooltip (get props :tooltip)
|
||||
input (mf/use-ref nil)
|
||||
state (mf/use-state (:editing false))
|
||||
is-editing (:editing @state)
|
||||
|
@ -54,4 +55,5 @@
|
|||
:on-blur cancel-editing}]
|
||||
[:span.editable-label-close {:on-click cancel-editing} i/close]]
|
||||
[:span.editable-label {:class class-name
|
||||
:title tooltip
|
||||
:on-double-click on-dbl-click} display-value])))
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
(def libraries (icon-xref :libraries))
|
||||
(def library (icon-xref :library))
|
||||
(def line (icon-xref :line))
|
||||
(def listing-list (icon-xref :listing-list))
|
||||
(def listing-enum (icon-xref :listing-enum))
|
||||
(def listing-thumbs (icon-xref :listing-thumbs))
|
||||
(def line-height (icon-xref :line-height))
|
||||
(def loader (icon-xref :loader))
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
;; ---- Components box ----
|
||||
|
||||
(mf/defc components-box
|
||||
[{:keys [file-id local? components open?] :as props}]
|
||||
[{:keys [file-id local? components listing-thumbs? open?] :as props}]
|
||||
(let [state (mf/use-state {:menu-open false
|
||||
:renaming nil
|
||||
:top nil
|
||||
|
@ -301,24 +301,34 @@
|
|||
[:span {:title (when truncated path)}
|
||||
last-path]]))
|
||||
(when group-open?
|
||||
[:div.asset-grid.big
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid @listing-thumbs?
|
||||
:big @listing-thumbs?
|
||||
:asset-enum (not @listing-thumbs?))}
|
||||
(for [component components]
|
||||
(let [renaming? (= (:renaming @state)(:id component))]
|
||||
[:div.grid-cell {:key (:id component)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected (:id component)))
|
||||
:draggable true
|
||||
:on-click (on-select (:id component))
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start (partial on-drag-start component)}
|
||||
[:div {:key (:id component)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected (:id component))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:draggable true
|
||||
:on-click (on-select (:id component))
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start (partial on-drag-start component)}
|
||||
[:& exports/component-svg {:group (get-in component [:objects (:id component)])
|
||||
:objects (:objects component)}]
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name true
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cp/merge-path-item (:path component) (:name component))
|
||||
:display-value (:name component)
|
||||
:tooltip (cp/merge-path-item (:path component) (:name component))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name component)
|
||||
(cp/compact-name (:path component)
|
||||
(:name component)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
|
@ -341,7 +351,7 @@
|
|||
;; ---- Graphics box ----
|
||||
|
||||
(mf/defc graphics-box
|
||||
[{:keys [file-id local? objects open?] :as props}]
|
||||
[{:keys [file-id local? objects listing-thumbs? open?] :as props}]
|
||||
(let [input-ref (mf/use-ref nil)
|
||||
state (mf/use-state {:menu-open false
|
||||
:renaming nil
|
||||
|
@ -504,26 +514,34 @@
|
|||
[:span {:title (when truncated path)}
|
||||
last-path]]))
|
||||
(when group-open?
|
||||
[:div.asset-grid
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid @listing-thumbs?
|
||||
:asset-enum (not @listing-thumbs?))}
|
||||
(for [object objects]
|
||||
[:div.grid-cell {:key (:id object)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected (:id object)))
|
||||
:draggable true
|
||||
:on-click (on-select (:id object))
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
:on-drag-start (partial on-drag-start object)}
|
||||
[:div {:key (:id object)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected (:id object))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:draggable true
|
||||
:on-click (on-select (:id object))
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
:on-drag-start (partial on-drag-start object)}
|
||||
[:img {:src (cfg/resolve-file-media object true)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
|
||||
#_[:div.cell-name (:name object)]
|
||||
(let [renaming? (= (:renaming @state) (:id object))]
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name true
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cp/merge-path-item (:path object) (:name object))
|
||||
:display-value (:name object)
|
||||
:tooltip (cp/merge-path-item (:path object) (:name object))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name object)
|
||||
(cp/compact-name (:path object)
|
||||
(:name object)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
|
@ -861,43 +879,49 @@
|
|||
(sort-by #(str/lower (:name %)) comp-fn))))
|
||||
|
||||
(mf/defc file-library
|
||||
[{:keys [file local? default-open? filters locale] :as props}]
|
||||
(let [open-file (mf/deref (open-file-ref (:id file)))
|
||||
open? (-> open-file
|
||||
:library
|
||||
(d/nilv default-open?))
|
||||
open-box? (fn [box]
|
||||
(-> open-file
|
||||
box
|
||||
(d/nilv true)))
|
||||
shared? (:is-shared file)
|
||||
router (mf/deref refs/router)
|
||||
[{:keys [file local? default-open? filters locale] :as props}]
|
||||
(let [open-file (mf/deref (open-file-ref (:id file)))
|
||||
open? (-> open-file
|
||||
:library
|
||||
(d/nilv default-open?))
|
||||
open-box? (fn [box]
|
||||
(-> open-file
|
||||
box
|
||||
(d/nilv true)))
|
||||
shared? (:is-shared file)
|
||||
router (mf/deref refs/router)
|
||||
|
||||
reverse-sort? (mf/use-state false)
|
||||
reverse-sort? (mf/use-state false)
|
||||
listing-thumbs? (mf/use-state true)
|
||||
|
||||
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?)))
|
||||
|
||||
url (rt/resolve router :workspace
|
||||
{:project-id (:project-id file)
|
||||
:file-id (:id file)}
|
||||
{:page-id (get-in file [:data :pages 0])})
|
||||
url (rt/resolve router :workspace
|
||||
{:project-id (:project-id file)
|
||||
:file-id (:id file)}
|
||||
{:page-id (get-in file [:data :pages 0])})
|
||||
|
||||
colors-ref (mf/use-memo (mf/deps (:id file)) #(file-colors-ref (:id file)))
|
||||
colors (apply-filters (mf/deref colors-ref) filters @reverse-sort?)
|
||||
colors-ref (mf/use-memo (mf/deps (:id file)) #(file-colors-ref (:id file)))
|
||||
colors (apply-filters (mf/deref colors-ref) filters @reverse-sort?)
|
||||
|
||||
typography-ref (mf/use-memo (mf/deps (:id file)) #(file-typography-ref (:id file)))
|
||||
typographies (apply-filters (mf/deref typography-ref) filters @reverse-sort?)
|
||||
typography-ref (mf/use-memo (mf/deps (:id file)) #(file-typography-ref (:id file)))
|
||||
typographies (apply-filters (mf/deref typography-ref) filters @reverse-sort?)
|
||||
|
||||
media-ref (mf/use-memo (mf/deps (:id file)) #(file-media-ref (:id file)))
|
||||
media (apply-filters (mf/deref media-ref) filters @reverse-sort?)
|
||||
media-ref (mf/use-memo (mf/deps (:id file)) #(file-media-ref (:id file)))
|
||||
media (apply-filters (mf/deref media-ref) filters @reverse-sort?)
|
||||
|
||||
components-ref (mf/use-memo (mf/deps (:id file)) #(file-components-ref (:id file)))
|
||||
components (apply-filters (mf/deref components-ref) filters @reverse-sort?)
|
||||
components-ref (mf/use-memo (mf/deps (:id file)) #(file-components-ref (:id file)))
|
||||
components (apply-filters (mf/deref components-ref) filters @reverse-sort?)
|
||||
|
||||
toggle-sort
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(swap! reverse-sort? not)))]
|
||||
(swap! reverse-sort? not)))
|
||||
|
||||
toggle-listing
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(swap! listing-thumbs? not)))]
|
||||
|
||||
[:div.tool-window
|
||||
[:div.tool-window-bar.library-bar
|
||||
|
@ -942,16 +966,21 @@
|
|||
(if @reverse-sort?
|
||||
i/sort-descending
|
||||
i/sort-ascending)]
|
||||
[:div.listing-option-btn i/listing-thumbs]]
|
||||
[:div.listing-option-btn {:on-click toggle-listing}
|
||||
(if @listing-thumbs?
|
||||
i/listing-thumbs
|
||||
i/listing-thumbs)]]
|
||||
(when show-components?
|
||||
[:& components-box {:file-id (:id file)
|
||||
:local? local?
|
||||
:components components
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (open-box? :components)}])
|
||||
(when show-graphics?
|
||||
[:& graphics-box {:file-id (:id file)
|
||||
:local? local?
|
||||
:objects media
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (open-box? :graphics)}])
|
||||
(when show-colors?
|
||||
[:& colors-box {:file-id (:id file)
|
||||
|
|
Loading…
Add table
Reference in a new issue