mirror of
https://github.com/penpot/penpot.git
synced 2025-05-24 18:06:12 +02:00
👾 changes libraries types, reworked color palette
This commit is contained in:
parent
decd3e3443
commit
5cd8e85034
14 changed files with 193 additions and 128 deletions
3
frontend/resources/images/icons/tick.svg
Normal file
3
frontend/resources/images/icons/tick.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="500" height="500" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.99941 1.62266C8.01413 1.36698 7.74905 1.14313 7.49807 1.21294C7.35967 1.27903 7.02149 1.60601 7.02149 1.60601C7.02149 1.60601 3.82775 4.79865 2.80464 5.76808C2.68664 5.81588 2.6167 5.68421 2.54114 5.62249C1.48872 4.57167 1.68802 4.66986 0.628214 3.62654C0.403393 3.46589 0.0441303 3.61642 0.00630665 3.8924C-0.0278168 4.07137 0.0811424 4.23539 0.212762 4.34466C1.2602 5.45375 1.12484 5.34669 2.1814 6.44725C2.31167 6.56977 2.42611 6.71875 2.58163 6.80902C2.77403 6.89051 2.99255 6.79154 3.11096 6.63235C4.317 5.44398 6.72612 3.05828 7.90933 1.84723C7.96218 1.78479 8.00392 1.70675 7.99941 1.62266Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 731 B |
|
@ -52,18 +52,24 @@
|
|||
left: 280px;
|
||||
width: calc(100% - 280px);
|
||||
}
|
||||
|
||||
& .context-menu-items {
|
||||
bottom: 1.5rem;
|
||||
top: initial;
|
||||
min-width: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
.color-palette-actions {
|
||||
align-self: stretch;
|
||||
border: 1px solid #1F1F1F;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
margin-right: .5rem;
|
||||
|
||||
border: 1px solid #1F1F1F;
|
||||
align-self: stretch;
|
||||
padding: 0.5rem;
|
||||
justify-content: center;
|
||||
margin-right: .5rem;
|
||||
padding: 0.5rem;
|
||||
|
||||
.color-palette-buttons {
|
||||
align-items: center;
|
||||
|
@ -115,6 +121,7 @@
|
|||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 4.8rem;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
border-radius: $br-small;
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||
left: -$size-4;
|
||||
max-height: 30rem;
|
||||
min-width: 7rem;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: $size-3;
|
||||
}
|
||||
|
@ -27,9 +29,25 @@
|
|||
display: block;
|
||||
font-size: $fs12;
|
||||
padding: $size-2 $size-4;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
color: $color-black;
|
||||
background: $color-primary-lighter;
|
||||
background-color: $color-primary-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
.context-menu.is-selectable {
|
||||
& .context-menu-action {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
& .context-menu-item.is-selected .context-menu-action {
|
||||
background-image: url(/images/icons/tick.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5% 48%;
|
||||
background-size: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
.settings-bar-inside {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: 100%;
|
||||
|
||||
&[data-layout*='layers'] {
|
||||
grid-template-rows: 30% 70%;
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
grid-template-columns: repeat(2, 50%);
|
||||
padding: 0.5rem;
|
||||
align-items: center;
|
||||
|
||||
& .context-menu-items {
|
||||
left: initial;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.libraries-window-bar-title {
|
||||
|
|
|
@ -266,4 +266,4 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :selected-items library-id] #(into [item] %) )))))
|
||||
(update-in [:library-items :palettes library-id] #(into [item] %) )))))
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
(update [_ state]
|
||||
(let [{:keys [id] :as item} (assoc item :type :icon)]
|
||||
(-> state
|
||||
(update-in [:library :selected-items library-id] #(into [item] %)))))))
|
||||
(update-in [:library-items :icons library-id] #(into [item] %)))))))
|
||||
|
||||
;; ;; --- Icon Persisted
|
||||
;;
|
||||
|
|
|
@ -395,5 +395,5 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :selected-items library-id] #(into [item] %))))))
|
||||
(update-in [:library-items :images library-id] #(into [item] %))))))
|
||||
|
||||
|
|
|
@ -56,15 +56,15 @@
|
|||
:images :images
|
||||
:palettes :colors)]
|
||||
(->> (rp/query! method {:library-id library-id})
|
||||
(rx/map (partial retrieve-library-data-result library-id)))))))
|
||||
(rx/map (partial retrieve-library-data-result type library-id)))))))
|
||||
|
||||
(defn retrieve-library-data-result
|
||||
[library-id data]
|
||||
[type library-id data]
|
||||
(ptk/reify ::retrieve-library-data-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:library :selected-items library-id] data)))))
|
||||
(assoc-in [:library-items type library-id] data)))))
|
||||
|
||||
|
||||
;; Create library
|
||||
|
@ -178,7 +178,7 @@
|
|||
(let [update-fn (fn [items]
|
||||
(filterv #(not= item-id (:id %)) items))]
|
||||
(-> state
|
||||
(update-in [:library :selected-items library-id] update-fn))))))
|
||||
(update-in [:library-items type library-id] update-fn))))))
|
||||
|
||||
;; Batch delete
|
||||
|
||||
|
@ -207,4 +207,4 @@
|
|||
update-fn (fn [items]
|
||||
(filterv #(not (item-ids-set (:id %))) items))]
|
||||
(-> state
|
||||
(update-in [:library :selected-items library-id] update-fn))))))
|
||||
(update-in [:library-items type library-id] update-fn))))))
|
||||
|
|
|
@ -270,9 +270,7 @@
|
|||
|
||||
(declare initialize-alignment)
|
||||
|
||||
#_(def default-layout #{:sitemap :layers :element-options :rules})
|
||||
(def default-layout #{:libraries :rules :colorpalette})
|
||||
|
||||
(def default-layout #{:sitemap :layers :element-options :rules})
|
||||
|
||||
(def workspace-default
|
||||
{:zoom 1
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
[rumext.alpha :as mf]
|
||||
[goog.object :as gobj]
|
||||
[uxbox.main.ui.components.dropdown :refer [dropdown-container]]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.data :refer [classnames]]))
|
||||
|
||||
(mf/defc context-menu
|
||||
{::mf/wrap-props false}
|
||||
|
@ -13,12 +14,17 @@
|
|||
(assert (vector? (gobj/get props "options")) "missing `options` prop")
|
||||
|
||||
(let [open? (gobj/get props "show")
|
||||
options (gobj/get props "options")]
|
||||
options (gobj/get props "options")
|
||||
is-selectable (gobj/get props "selectable")
|
||||
selected (gobj/get props "selected")]
|
||||
(println "selected" selected)
|
||||
(when open?
|
||||
[:> dropdown-container props
|
||||
[:div.context-menu {:class (when open? "is-open")}
|
||||
[:div.context-menu {:class (classnames :is-open open?
|
||||
:is-selectable is-selectable)}
|
||||
[:ul.context-menu-items
|
||||
(for [[action-name action-handler] options]
|
||||
[:li.context-menu-item {:key action-name}
|
||||
[:li.context-menu-item {:class (classnames :is-selected (and selected (= action-name selected)))
|
||||
:key action-name}
|
||||
[:a.context-menu-action {:on-click action-handler}
|
||||
action-name]])]]])))
|
||||
|
|
|
@ -305,8 +305,8 @@
|
|||
(-> (comp (l/key :library) (l/key section) (l/key team-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
(defn selected-items-ref [library-id]
|
||||
(-> (comp (l/key :library) (l/key :selected-items) (l/key library-id))
|
||||
(defn selected-items-ref [section library-id]
|
||||
(-> (comp (l/key :library-items) (l/key section) (l/key library-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
(def last-deleted-library-ref
|
||||
|
@ -317,7 +317,7 @@
|
|||
[{:keys [team-id library-id section]}]
|
||||
(let [state (mf/use-state {:selected #{}})
|
||||
libraries (mf/deref (libraries-ref section team-id))
|
||||
items (mf/deref (selected-items-ref library-id))
|
||||
items (mf/deref (selected-items-ref section library-id))
|
||||
last-deleted-library (mf/deref last-deleted-library-ref)
|
||||
selected-library (first (filter #(= (:id %) library-id) libraries))]
|
||||
|
||||
|
|
|
@ -13,16 +13,26 @@
|
|||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.colors :as udc]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.data.library :as dlib]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.util.color :refer [hex->rgb]]
|
||||
[uxbox.util.data :refer [read-string seek]]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
||||
|
||||
;; --- Refs
|
||||
|
||||
(def collections-iref
|
||||
(-> (l/key :colors-collections)
|
||||
(def project-ref
|
||||
(-> (l/key :workspace-project)
|
||||
(l/derive st/state)))
|
||||
|
||||
(def libraries-ref
|
||||
(-> (comp (l/key :library) (l/key :palettes))
|
||||
(l/derive st/state)))
|
||||
|
||||
(defn selected-items-ref [library-id]
|
||||
(-> (comp (l/key :library-items) (l/key :palettes) (l/key library-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
;; --- Components
|
||||
|
@ -30,8 +40,6 @@
|
|||
(mf/defc palette-item
|
||||
[{:keys [color] :as props}]
|
||||
(let [rgb-vec (hex->rgb color)
|
||||
rgb-color (apply str "" (interpose ", " rgb-vec))
|
||||
|
||||
select-color
|
||||
(fn [event]
|
||||
(if (kbd/shift? event)
|
||||
|
@ -41,46 +49,38 @@
|
|||
[:div.color-cell {:key (str color)
|
||||
:on-click select-color}
|
||||
[:span.color {:style {:background color}}]
|
||||
[:span.color-text color]
|
||||
#_[:span.color-text rgb-color]]))
|
||||
[:span.color-text color]]))
|
||||
|
||||
(mf/defc palette
|
||||
[{:keys [colls left-sidebar?] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
colls (->> colls
|
||||
(filter :id)
|
||||
(sort-by :name))
|
||||
[{:keys [libraries left-sidebar?] :as props}]
|
||||
|
||||
coll (or (:selected @local)
|
||||
(first colls))
|
||||
(when (and libraries (-> libraries count (> 0)))
|
||||
(let [state (mf/use-state {:show-menu false
|
||||
:selected-library (-> libraries first :id)})]
|
||||
(mf/use-effect (mf/deps (:selected-library @state))
|
||||
#(st/emit! (dlib/retrieve-library-data :palettes (:selected-library @state))))
|
||||
|
||||
(let [items (-> (:selected-library @state) selected-items-ref mf/deref)
|
||||
doc-width (.. js/document -documentElement -clientWidth)
|
||||
width (:width @local (* doc-width 0.84))
|
||||
offset (:offset @local 0)
|
||||
width (:width @state (* doc-width 0.84))
|
||||
offset (:offset @state 0)
|
||||
visible (/ width 86)
|
||||
invisible (- (count (:colors coll)) visible)
|
||||
invisible (- (count items) visible)
|
||||
close #(st/emit! (udw/toggle-layout-flag :colorpalette))
|
||||
|
||||
container (mf/use-ref nil)
|
||||
container-child (mf/use-ref nil)
|
||||
|
||||
select-coll
|
||||
(fn [event]
|
||||
(let [id (read-string (dom/event->value event))
|
||||
selected (seek #(= id (:id %)) colls)]
|
||||
(swap! local assoc :selected selected :position 0)))
|
||||
|
||||
on-left-arrow-click
|
||||
(fn [event]
|
||||
(when (> offset 0)
|
||||
(let [element (mf/ref-val container-child)]
|
||||
(swap! local update :offset dec))))
|
||||
(swap! state update :offset dec))))
|
||||
|
||||
on-right-arrow-click
|
||||
(fn [event]
|
||||
(when (< offset invisible)
|
||||
(let [element (mf/ref-val container-child)]
|
||||
(swap! local update :offset inc))))
|
||||
(swap! state update :offset inc))))
|
||||
|
||||
on-scroll
|
||||
(fn [event]
|
||||
|
@ -92,42 +92,42 @@
|
|||
(fn []
|
||||
(let [dom (mf/ref-val container)
|
||||
width (.-clientWidth dom)]
|
||||
(when (not= (:width @local) width)
|
||||
(swap! local assoc :width width))))]
|
||||
(when (not= (:width @state) width)
|
||||
(swap! state assoc :width width))))
|
||||
|
||||
handle-click
|
||||
(fn [library]
|
||||
(swap! state assoc :selected-library (:id library)))]
|
||||
|
||||
(mf/use-effect nil after-render)
|
||||
|
||||
[:div.color-palette {:class (when left-sidebar? "left-sidebar-open")}
|
||||
[:& context-menu {:selectable true
|
||||
:selected (->> libraries (filter #(= (:id %) (:selected-library @state))) first :name)
|
||||
:show (:show-menu @state)
|
||||
:on-close #(swap! state assoc :show-menu false)
|
||||
:options (mapv #(vector (:name %) (partial handle-click %)) libraries)} ]
|
||||
[:div.color-palette-actions
|
||||
[:div.color-palette-actions-button i/actions]
|
||||
#_[:select.input-select {:on-change select-coll
|
||||
:default-value (pr-str (:id coll))}
|
||||
(for [item colls]
|
||||
[:option {:key (:id item) :value (pr-str (:id item))}
|
||||
(:name item)])]
|
||||
|
||||
#_[:div.color-palette-buttons
|
||||
[:div.btn-palette.edit.current i/pencil]
|
||||
[:div.btn-palette.create i/close]]]
|
||||
{:on-click #(swap! state assoc :show-menu true)}
|
||||
[:div.color-palette-actions-button i/actions]]
|
||||
|
||||
[:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide]
|
||||
|
||||
[:div.color-palette-content {:ref container :on-wheel on-scroll}
|
||||
[:div.color-palette-inside {:ref container-child
|
||||
:style {:position "relative"
|
||||
:width (str (* 86 (count (:colors coll))) "px")
|
||||
:width (str (* 86 (count items)) "px")
|
||||
:right (str (* 86 offset) "px")}}
|
||||
#_(for [color (:colors coll)]
|
||||
[:& palette-item {:color color :key color}])
|
||||
(for [color (range 0 20)]
|
||||
[:& palette-item {:color "#FFFF00" :key color}])]]
|
||||
(for [item items]
|
||||
[:& palette-item {:color (:content item) :key (:id item)}])]]
|
||||
|
||||
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]
|
||||
#_[:span.close-palette {:on-click close} i/close]]))
|
||||
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]]))))
|
||||
|
||||
(mf/defc colorpalette
|
||||
[{:keys [left-sidebar?]}]
|
||||
(let [colls (mf/deref collections-iref)]
|
||||
#_(mf/use-effect #(st/emit! (udc/fetch-collections)))
|
||||
(let [team-id (-> project-ref mf/deref :team-id)
|
||||
libraries (-> libraries-ref mf/deref vals flatten)]
|
||||
(mf/use-effect #(st/emit! (dlib/retrieve-libraries :palettes)))
|
||||
(mf/use-effect #(st/emit! (dlib/retrieve-libraries :palettes team-id)))
|
||||
[:& palette {:left-sidebar? left-sidebar?
|
||||
:colls (vals colls)}]))
|
||||
:libraries libraries}]))
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[uxbox.main.data.library :as dlib]))
|
||||
[uxbox.main.data.library :as dlib]
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
||||
|
||||
(def project-ref
|
||||
(-> (l/key :workspace-project)
|
||||
|
@ -34,29 +35,34 @@
|
|||
(-> (comp (l/key :library) (l/key section))
|
||||
(l/derive st/state)))
|
||||
|
||||
(defn selected-items-ref [library-id]
|
||||
(-> (comp (l/key :library) (l/key :selected-items) (l/key library-id))
|
||||
(defn selected-items-ref [section library-id]
|
||||
(-> (comp (l/key :library-items) (l/key section) (l/key library-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc icons-tab [{:keys [libraries]}]
|
||||
|
||||
(when (and libraries (-> libraries count (> 0)))
|
||||
(let [state (mf/use-state {:selected-library (-> libraries first :id)})]
|
||||
(mf/use-effect (mf/deps libraries)
|
||||
#(when (not (some (fn [it] (= (:selected-library @state) (-> it :id))) libraries))
|
||||
(swap! state assoc :selected-library (-> libraries first :id))))
|
||||
(mf/use-effect (mf/deps (:selected-library @state))
|
||||
#(st/emit! (dlib/retrieve-library-data :icons (:selected-library @state))))
|
||||
|
||||
[:div.library-tab.icons-tab
|
||||
[:select.input-select.library-tab-libraries
|
||||
{:on-change #(swap! state assoc :selected-library (-> % dom/get-target dom/get-value))}
|
||||
{:on-change #(swap! state assoc :selected-library (-> % dom/get-target dom/get-value uuid))}
|
||||
(for [library libraries]
|
||||
[:option.library-tab-libraries-item
|
||||
{:key (:id library)
|
||||
:value (:id library)}
|
||||
(:name library)])]
|
||||
[:div.library-tab-content
|
||||
(let [items (mf/deref (selected-items-ref (:selected-library @state)))]
|
||||
(let [items (mf/deref (selected-items-ref :icons (:selected-library @state)))]
|
||||
(for [item items]
|
||||
[:div.library-tab-element
|
||||
{:key (:id item)}
|
||||
{:key (:id item)
|
||||
:on-click #(st/emit! (dw/select-for-drawing :icon item))}
|
||||
[:svg {:view-box (->> item :metadata :view-box (str/join " "))
|
||||
:width (-> item :metadata :width)
|
||||
:height (-> item :metadat :height)
|
||||
|
@ -78,19 +84,30 @@
|
|||
:value (:id library)}
|
||||
(:name library)])]
|
||||
[:div.library-tab-content
|
||||
(let [items (mf/deref (selected-items-ref (:selected-library @state)))]
|
||||
(let [items (mf/deref (selected-items-ref :images (:selected-library @state)))]
|
||||
(for [item items]
|
||||
[:div.library-tab-element
|
||||
{:key (:id item)}
|
||||
{:key (:id item)
|
||||
:on-click #(st/emit! (dw/select-for-drawing :image item))}
|
||||
[:img {:src (:thumb-uri item)}]
|
||||
[:span.library-tab-element-name (:name item)]]))]])))
|
||||
|
||||
(mf/defc libraries-toolbox
|
||||
[{:keys [key]}]
|
||||
(let [team-id (-> project-ref mf/deref :team-id)
|
||||
locale (i18n/use-locale)]
|
||||
(let [state (mf/use-state {:menu-open false
|
||||
:selected :all})
|
||||
team-id (-> project-ref mf/deref :team-id)
|
||||
locale (i18n/use-locale)
|
||||
key-to-str {:all "All libraries"
|
||||
:own "My libraries"
|
||||
:store "Store libraries"}
|
||||
select-option (fn [option] (swap! state assoc :selected option))
|
||||
|
||||
filter-libraries (fn [libraries] (case (:selected @state)
|
||||
:all (-> libraries vals flatten)
|
||||
:own (libraries team-id)
|
||||
:store (libraries uuid/zero)))]
|
||||
(mf/use-effect
|
||||
(mf/deps key)
|
||||
#(do
|
||||
(st/emit! (dlib/retrieve-libraries :icons))
|
||||
(st/emit! (dlib/retrieve-libraries :images))))
|
||||
|
@ -104,17 +121,27 @@
|
|||
[:div.libraries-window-bar
|
||||
[:div.libraries-window-bar-title "Libraries"]
|
||||
[:div.libraries-window-bar-options
|
||||
"All libraries"
|
||||
[:button {:type "button"}
|
||||
i/arrow-slide]]]
|
||||
{:on-click #(swap! state assoc :menu-open true)}
|
||||
(key-to-str (:selected @state))
|
||||
[:button
|
||||
{
|
||||
:type "button"}
|
||||
i/arrow-slide
|
||||
[:& context-menu {:selectable true
|
||||
:show (:menu-open @state)
|
||||
:selected (key-to-str (:selected @state))
|
||||
:on-close #(swap! state assoc :menu-open false)
|
||||
:options (mapv (fn [[key val]] [val #(select-option key)]) key-to-str)}]]
|
||||
|
||||
]]
|
||||
[:div.tool-window-content
|
||||
[:& tab-container {}
|
||||
[:& tab-element
|
||||
{:id :icons :title "Icons"}
|
||||
[:& icons-tab {:libraries (-> (libraries-ref :icons) mf/deref vals flatten) }]]
|
||||
[:& icons-tab {:libraries (-> (libraries-ref :icons) mf/deref filter-libraries) }]]
|
||||
|
||||
[:& tab-element
|
||||
{:id :images :title "Images"}
|
||||
[:& images-tab {:libraries (-> (libraries-ref :images) mf/deref vals flatten)}]]]]]))
|
||||
[:& images-tab {:libraries (-> (libraries-ref :images) mf/deref filter-libraries)}]]]]]))
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue