Merge pull request #5906 from penpot/niwinz-libraries-fix

🐛 Fix incorrect libraries filtering on workspace
This commit is contained in:
Alejandro 2025-02-20 07:40:24 +01:00 committed by GitHub
commit befa5f4c7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 113 additions and 84 deletions

View file

@ -168,11 +168,13 @@
(assoc file :data (d/removem (comp t/pointer? val) data)))))))))) (assoc file :data (d/removem (comp t/pointer? val) data))))))))))
(defn- libraries-fetched (defn- libraries-fetched
[libraries] [file-id libraries]
(ptk/reify ::libraries-fetched (ptk/reify ::libraries-fetched
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [libraries (d/index-by :id libraries)] (let [libraries (->> libraries
(map (fn [l] (assoc l :library-of file-id)))
(d/index-by :id))]
(update state :files merge libraries))) (update state :files merge libraries)))
ptk/WatchEvent ptk/WatchEvent
@ -208,7 +210,7 @@
(rx/map #(assoc % :synced-at synced-at))))) (rx/map #(assoc % :synced-at synced-at)))))
(rx/merge-map resolve-file) (rx/merge-map resolve-file)
(rx/reduce conj []) (rx/reduce conj [])
(rx/map libraries-fetched)) (rx/map (partial libraries-fetched file-id)))
(->> (rx/from libraries) (->> (rx/from libraries)
(rx/map :id) (rx/map :id)
(rx/mapcat (fn [file-id] (rx/mapcat (fn [file-id]

View file

@ -1201,7 +1201,7 @@
(vals (get state :files))) (vals (get state :files)))
do-more-info do-more-info
#(modal/show! :libraries-dialog {:starting-tab "updates"}) #(modal/show! :libraries-dialog {:starting-tab "updates" :file-id file-id})
do-update do-update
#(do (apply st/emit! (map (fn [library] #(do (apply st/emit! (map (fn [library]
@ -1388,7 +1388,10 @@
(let [libraries (:workspace-shared-files state) (let [libraries (:workspace-shared-files state)
library (d/seek #(= (:id %) library-id) libraries)] library (d/seek #(= (:id %) library-id) libraries)]
(if library (if library
(update state :files assoc library-id (dissoc library :library-summary)) (update state :files assoc library-id
(-> library
(dissoc :library-summary)
(assoc :library-of file-id)))
state))) state)))
ptk/WatchEvent ptk/WatchEvent
@ -1401,6 +1404,8 @@
(->> (rp/cmd! :get-file {:id library-id :features features}) (->> (rp/cmd! :get-file {:id library-id :features features})
(rx/merge-map fpmap/resolve-file) (rx/merge-map fpmap/resolve-file)
;; FIXME: this should call the libraries-fetched event instead of ad-hoc assoc event ;; FIXME: this should call the libraries-fetched event instead of ad-hoc assoc event
(rx/map (fn [file]
(assoc file :library-of file-id)))
(rx/map (fn [file] (rx/map (fn [file]
(fn [state] (fn [state]
(assoc-in state [:files library-id] file))))) (assoc-in state [:files library-id] file)))))

View file

@ -83,10 +83,32 @@
files (without the content, only summary)" files (without the content, only summary)"
(l/derived :shared-files st/state)) (l/derived :shared-files st/state))
(defn select-libraries
[files file-id]
(persistent!
(reduce-kv (fn [result id file]
(if (or (= id file-id)
(= (:library-of file) file-id))
(assoc! result id file)
result))
(transient {})
files)))
;; NOTE: for performance reasons, prefer derefing refs/files and then
;; use with-memo mechanism with `select-libraries` this will avoid
;; executing the select-libraries reduce-kv on each state change and
;; only execute it when files are changed. This ref exists for
;; backward compatibility with the code, but it is considered
;; DEPRECATED and all new code should not use it and old code should
;; be gradually migrated to more efficient approach
(def libraries (def libraries
"A derived state that contanins the currently loaded shared libraries "A derived state that contanins the currently loaded shared
with all its content; including the current file" libraries with all its content; including the current file"
(l/derived :files st/state)) (l/derived (fn [state]
(let [files (get state :files)
file-id (get state :current-file-id)]
(select-libraries files file-id)))
st/state))
(defn extract-selected-files (defn extract-selected-files
[files selected] [files selected]

View file

@ -56,10 +56,12 @@
(make-typographies-library-ref (:typography-ref-file style))) (make-typographies-library-ref (:typography-ref-file style)))
typography-library (mf/deref typography-library-ref) typography-library (mf/deref typography-library-ref)
;; FIXME: too many duplicate operations
file-typographies-viewer (mf/deref file-typographies-ref) file-typographies-viewer (mf/deref file-typographies-ref)
file-typographies-workspace (mf/deref refs/workspace-file-typography) file-typographies-workspace (mf/deref refs/workspace-file-typography)
file-library-workspace (get (mf/deref refs/libraries) (:typography-ref-file style)) file-library-workspace (get (mf/deref refs/files) (:typography-ref-file style))
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)]) typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
color-format (mf/use-state :hex) color-format (mf/use-state :hex)

View file

@ -26,16 +26,11 @@
"Retrieve all libraries, including the local file, on workspace or viewer" "Retrieve all libraries, including the local file, on workspace or viewer"
[from] [from]
(if (= from :workspace) (if (= from :workspace)
(let [workspace-data (deref refs/workspace-data) (deref refs/libraries)
{:keys [id] :as local} workspace-data (let [viewer-data (deref refs/viewer-data)
libraries (deref refs/libraries)] local (get-in viewer-data [:file :data])
(-> libraries id (get local :id)
(assoc id {:id id libraries (:libraries viewer-data)]
:data local})))
(let [viewer-data (deref refs/viewer-data)
local (get-in viewer-data [:file :data])
id (get local :id)
libraries (:libraries viewer-data)]
(-> libraries (-> libraries
(assoc id {:id id (assoc id {:id id
:data local}))))) :data local})))))

View file

@ -166,9 +166,9 @@
(defn- make-library-colors-ref (defn- make-library-colors-ref
[file-id] [file-id]
(l/derived (fn [libraries] (l/derived (fn [files]
(dm/get-in libraries [file-id :data :colors])) (dm/get-in files [file-id :data :colors]))
refs/libraries)) refs/files))
(mf/defc file-color-palette* (mf/defc file-color-palette*
{::mf/private true} {::mf/private true}

View file

@ -48,7 +48,7 @@
{:value "file" :label (tr "workspace.libraries.colors.file-library")}]) {:value "file" :label (tr "workspace.libraries.colors.file-library")}])
options options
(mf/with-memo [library-options file-id] (mf/with-memo [library-options libraries file-id]
(into library-options (into library-options
(comp (comp
(map val) (map val)

View file

@ -248,10 +248,12 @@
(mf/use-fn (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
#(st/emit! (dwl/set-file-shared file-id false) #(st/emit! (dwl/set-file-shared file-id false)
(modal/show :libraries-dialog {}))) (modal/show :libraries-dialog {:file-id file-id})))
on-delete-cancel on-delete-cancel
(mf/use-fn #(st/emit! (modal/show :libraries-dialog {}))) (mf/use-fn
(mf/deps file-id)
#(st/emit! (modal/show :libraries-dialog {:file-id file-id})))
publish publish
(mf/use-fn (mf/use-fn
@ -259,7 +261,7 @@
(fn [event] (fn [event]
(let [input-node (dom/get-target event) (let [input-node (dom/get-target event)
publish-library #(st/emit! (dwl/set-file-shared file-id true)) publish-library #(st/emit! (dwl/set-file-shared file-id true))
cancel-publish #(st/emit! (modal/show :libraries-dialog {}))] cancel-publish #(st/emit! (modal/show :libraries-dialog {:file-id file-id}))]
(if empty-library? (if empty-library?
(st/emit! (modal/show (st/emit! (modal/show
{:type :confirm {:type :confirm
@ -563,17 +565,15 @@
(mf/defc libraries-dialog (mf/defc libraries-dialog
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :libraries-dialog} ::mf/register-as :libraries-dialog}
[{:keys [starting-tab] :as props :or {starting-tab :libraries}}] [{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}]
(let [;; NOTE: we don't want to react on file changes, we just want (let [files (mf/deref refs/files)
;; a snapshot of file on the momento of open the dialog file (get files file-id)
file (deref refs/file) team-id (:team-id file)
shared? (:is-shared file)
file-id (:id file)
team-id (:team-id file)
shared? (:is-shared file)
linked-libraries linked-libraries
(mf/deref refs/files) (mf/with-memo [files file-id]
(refs/select-libraries files file-id))
linked-libraries linked-libraries
(mf/with-memo [linked-libraries file-id] (mf/with-memo [linked-libraries file-id]

View file

@ -56,6 +56,7 @@
[{:keys [layout file page-id] :as props}] [{:keys [layout file page-id] :as props}]
(let [options-mode (mf/deref refs/options-mode-global) (let [options-mode (mf/deref refs/options-mode-global)
project (mf/deref refs/project) project (mf/deref refs/project)
file-id (get file :id)
design-tokens? (features/use-feature "design-tokens/v1") design-tokens? (features/use-feature "design-tokens/v1")
mode-inspect? (= options-mode :inspect) mode-inspect? (= options-mode :inspect)
@ -116,7 +117,7 @@
assets-tab assets-tab
(mf/html [:& assets-toolbox {:size (- size 58) :file-id file}]) (mf/html [:& assets-toolbox {:size (- size 58) :file-id file-id}])
tokens-tab tokens-tab
(when design-tokens? (when design-tokens?

View file

@ -33,10 +33,10 @@
::mf/private true} ::mf/private true}
[{:keys [filters]}] [{:keys [filters]}]
(let [file-id (mf/use-ctx ctx/current-file-id) (let [file-id (mf/use-ctx ctx/current-file-id)
files (mf/deref refs/files)
libraries (mf/deref refs/libraries) libraries (mf/with-memo [files file-id]
libraries (mf/with-memo [libraries file-id] (->> (refs/select-libraries files file-id)
(->> (vals libraries) (vals)
(remove :is-indirect) (remove :is-indirect)
(remove #(= file-id (:id %))) (remove #(= file-id (:id %)))
(map (fn [file] (map (fn [file]
@ -129,8 +129,9 @@
show-libraries-dialog show-libraries-dialog
(mf/use-fn (mf/use-fn
(mf/deps file-id)
(fn [] (fn []
(modal/show! :libraries-dialog {}) (modal/show! :libraries-dialog {:file-id file-id})
(modal/allow-click-outside!))) (modal/allow-click-outside!)))
on-open-menu on-open-menu

View file

@ -321,7 +321,7 @@
current-file-id (mf/use-ctx ctx/current-file-id) current-file-id (mf/use-ctx ctx/current-file-id)
current-page-id (mf/use-ctx ctx/current-page-id) current-page-id (mf/use-ctx ctx/current-page-id)
libraries (deref refs/libraries) libraries (deref refs/files)
current-file (get libraries current-file-id) current-file (get libraries current-file-id)
objects (-> (dsh/get-page (:data current-file) current-page-id) objects (-> (dsh/get-page (:data current-file) current-page-id)

View file

@ -44,7 +44,7 @@
(defn- get-component-root-and-container (defn- get-component-root-and-container
[file-id component] [file-id component]
(let [data (dm/get-in @refs/libraries [file-id :data]) (let [data (dm/get-in @refs/files [file-id :data])
root-shape (ctf/get-component-root data component) root-shape (ctf/get-component-root data component)
container (ctf/get-component-page data component)] container (ctf/get-component-page data component)]
[root-shape container])) [root-shape container]))
@ -453,7 +453,7 @@
(fn [component event] (fn [component event]
(let [file-data (let [file-data
(dm/get-in @refs/libraries [file-id :data]) (dm/get-in @refs/files [file-id :data])
shape-main shape-main
(ctf/get-component-root file-data component)] (ctf/get-component-root file-data component)]

View file

@ -44,7 +44,7 @@
(mf/defc shape-options* (mf/defc shape-options*
{::mf/wrap [#(mf/throttle % 60)]} {::mf/wrap [#(mf/throttle % 60)]}
[{:keys [shape shapes-with-children page-id file-id shared-libs] :as props}] [{:keys [shape shapes-with-children page-id file-id libraries] :as props}]
(let [shape-type (dm/get-prop shape :type) (let [shape-type (dm/get-prop shape :type)
shape-id (dm/get-prop shape :id) shape-id (dm/get-prop shape :id)
@ -56,8 +56,8 @@
[:* [:*
(case shape-type (case shape-type
:frame [:> frame/options* props] :frame [:> frame/options* props]
:group [:& group/options {:shape shape :shape-with-children shapes-with-children :file-id file-id :shared-libs shared-libs}] :group [:& group/options {:shape shape :shape-with-children shapes-with-children :file-id file-id :libraries libraries}]
:text [:& text/options {:shape shape :file-id file-id :shared-libs shared-libs}] :text [:& text/options {:shape shape :file-id file-id :libraries libraries}]
:rect [:& rect/options {:shape shape}] :rect [:& rect/options {:shape shape}]
:circle [:& circle/options {:shape shape}] :circle [:& circle/options {:shape shape}]
:path [:& path/options {:shape shape}] :path [:& path/options {:shape shape}]
@ -83,7 +83,7 @@
[{:keys [selected objects page-id file-id selected-shapes shapes-with-children]}] [{:keys [selected objects page-id file-id selected-shapes shapes-with-children]}]
(let [sp-panel (mf/deref refs/specialized-panel) (let [sp-panel (mf/deref refs/specialized-panel)
drawing (mf/deref refs/workspace-drawing) drawing (mf/deref refs/workspace-drawing)
shared-libs (mf/deref refs/libraries) libraries (mf/deref refs/libraries)
edition (mf/deref refs/selected-edition) edition (mf/deref refs/selected-edition)
edit-grid? (ctl/grid-layout? objects edition) edit-grid? (ctl/grid-layout? objects edition)
grid-edition (mf/deref refs/workspace-grid-edition) grid-edition (mf/deref refs/workspace-grid-edition)
@ -113,7 +113,7 @@
{:shape (:object drawing) {:shape (:object drawing)
:page-id page-id :page-id page-id
:file-id file-id :file-id file-id
:shared-libs shared-libs}] :libraries libraries}]
(= 0 (count selected)) (= 0 (count selected))
[:> page/options*] [:> page/options*]
@ -123,7 +123,7 @@
{:shape (first selected-shapes) {:shape (first selected-shapes)
:page-id page-id :page-id page-id
:file-id file-id :file-id file-id
:shared-libs shared-libs :libraries libraries
:shapes-with-children shapes-with-children}] :shapes-with-children shapes-with-children}]
:else :else
@ -132,7 +132,7 @@
:shapes selected-shapes :shapes selected-shapes
:page-id page-id :page-id page-id
:file-id file-id :file-id file-id
:shared-libs shared-libs}])])) :libraries libraries}])]))
(mf/defc options-content* (mf/defc options-content*
{::mf/memo true {::mf/memo true

View file

@ -19,8 +19,8 @@
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn- prepare-colors (defn- prepare-colors
[shapes file-id shared-libs] [shapes file-id libraries]
(let [data (into [] (remove nil? (ctc/extract-all-colors shapes file-id shared-libs))) (let [data (into [] (remove nil? (ctc/extract-all-colors shapes file-id libraries)))
groups (d/group-by :attrs #(dissoc % :attrs) data) groups (d/group-by :attrs #(dissoc % :attrs) data)
all-colors (distinct (mapv :attrs data)) all-colors (distinct (mapv :attrs data))

View file

@ -295,7 +295,8 @@
(let [single? (= 1 (count shapes)) (let [single? (= 1 (count shapes))
shape (first shapes) shape (first shapes)
current-file-id (mf/use-ctx ctx/current-file-id) current-file-id (mf/use-ctx ctx/current-file-id)
libraries (mf/deref refs/files)
libraries (mf/deref refs/libraries)
objects (mf/deref refs/workspace-page-objects) objects (mf/deref refs/workspace-page-objects)
^boolean ^boolean
@ -513,7 +514,7 @@
[{:keys [shapes swap-opened?]}] [{:keys [shapes swap-opened?]}]
(let [current-file-id (mf/use-ctx ctx/current-file-id) (let [current-file-id (mf/use-ctx ctx/current-file-id)
libraries (deref refs/libraries) libraries (deref refs/files)
current-file (get libraries current-file-id) current-file (get libraries current-file-id)
state* (mf/use-state state* (mf/use-state

View file

@ -184,7 +184,7 @@
(let [file-id (mf/use-ctx ctx/current-file-id) (let [file-id (mf/use-ctx ctx/current-file-id)
typographies (mf/deref refs/workspace-file-typography) typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/libraries) libraries (mf/deref refs/files)
label (case type label (case type
:multiple (tr "workspace.options.text-options.title-selection") :multiple (tr "workspace.options.text-options.title-selection")
:group (tr "workspace.options.text-options.title-group") :group (tr "workspace.options.text-options.title-group")
@ -224,21 +224,19 @@
(emit-update! ids attrs))) (emit-update! ids attrs)))
typography typography
(mf/use-memo (mf/with-memo [values file-id libraries]
(mf/deps values file-id shared-libs) (cond
(fn [] (and typography-id
(cond (not= typography-id :multiple)
(and typography-id (not= typography-file-id file-id))
(not= typography-id :multiple) (-> libraries
(not= typography-file-id file-id)) (get-in [typography-file-id :data :typographies typography-id])
(-> shared-libs (assoc :file-id typography-file-id))
(get-in [typography-file-id :data :typographies typography-id])
(assoc :file-id typography-file-id))
(and typography-id (and typography-id
(not= typography-id :multiple) (not= typography-id :multiple)
(= typography-file-id file-id)) (= typography-file-id file-id))
(get typographies typography-id)))) (get typographies typography-id)))
on-convert-to-typography on-convert-to-typography
(fn [_] (fn [_]

View file

@ -48,13 +48,13 @@
[{:keys [index color disable-gradient disable-opacity disable-image disable-picker hidden [{:keys [index color disable-gradient disable-opacity disable-image disable-picker hidden
on-change on-reorder on-detach on-open on-close on-remove on-change on-reorder on-detach on-open on-close on-remove
disable-drag on-focus on-blur select-only select-on-focus]}] disable-drag on-focus on-blur select-only select-on-focus]}]
(let [shared-libs (mf/deref refs/libraries) (let [libraries (mf/deref refs/files)
hover-detach (mf/use-state false) hover-detach (mf/use-state false)
on-change (h/use-ref-callback on-change) on-change (h/use-ref-callback on-change)
file-id (or (:ref-file color) (:file-id color)) file-id (or (:ref-file color) (:file-id color))
color-id (or (:ref-id color) (:id color)) color-id (or (:ref-id color) (:id color))
src-colors (dm/get-in shared-libs [file-id :data :colors]) src-colors (dm/get-in libraries [file-id :data :colors])
color-name (dm/get-in src-colors [color-id :name]) color-name (dm/get-in src-colors [color-id :name])
multiple-colors? (uc/multiple? color) multiple-colors? (uc/multiple? color)

View file

@ -34,7 +34,7 @@
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
shape-with-children (unchecked-get props "shape-with-children") shape-with-children (unchecked-get props "shape-with-children")
shared-libs (unchecked-get props "shared-libs") libraries (unchecked-get props "libraries")
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v)))) objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
file-id (unchecked-get props "file-id") file-id (unchecked-get props "file-id")
layout-container-values (select-keys shape layout-container-flex-attrs) layout-container-values (select-keys shape layout-container-flex-attrs)
@ -106,7 +106,7 @@
{:type type {:type type
:shapes (vals objects) :shapes (vals objects)
:file-id file-id :file-id file-id
:libraries shared-libs}] :libraries libraries}]
(when-not (empty? shadow-ids) (when-not (empty? shadow-ids)
[:> shadow-menu* {:ids ids :values (get shape :shadow) :type type}]) [:> shadow-menu* {:ids ids :values (get shape :shadow) :type type}])

View file

@ -29,7 +29,7 @@
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc options (mf/defc options
[{:keys [shape file-id] :as props}] [{:keys [shape file-id libraries] :as props}]
(let [ids [(:id shape)] (let [ids [(:id shape)]
type (:type shape) type (:type shape)
@ -53,8 +53,6 @@
(mf/deref refs/workspace-v2-editor-state) (mf/deref refs/workspace-v2-editor-state)
(mf/deref refs/workspace-editor-state)) (mf/deref refs/workspace-editor-state))
shared-libs (mf/deref refs/libraries)
editor-state (when (not (features/active-feature? @st/state "text-editor/v2")) editor-state (when (not (features/active-feature? @st/state "text-editor/v2"))
(get state-map (:id shape))) (get state-map (:id shape)))
@ -150,7 +148,7 @@
{:type type {:type type
:shapes [shape] :shapes [shape]
:file-id file-id :file-id file-id
:libraries shared-libs}]) :libraries libraries}])
[:> shadow-menu* {:ids ids :values (get shape :shadow)}] [:> shadow-menu* {:ids ids :values (get shape :shadow)}]

View file

@ -68,7 +68,7 @@
(str (:font-size typography) "px | " (:name variant-data))]])])) (str (:font-size typography) "px | " (:name variant-data))]])]))
(mf/defc palette (mf/defc palette
[{:keys [selected selected-ids current-file-id file-typographies shared-libs size width]}] [{:keys [selected selected-ids current-file-id file-typographies libraries size width]}]
(let [file-id (let [file-id
(case selected (case selected
:recent nil :recent nil
@ -79,7 +79,7 @@
(case selected (case selected
:recent [] :recent []
:file (sort-by #(str/lower (:name %)) (vals file-typographies)) :file (sort-by #(str/lower (:name %)) (vals file-typographies))
(sort-by #(str/lower (:name %)) (vals (get-in shared-libs [selected :data :typographies])))) (sort-by #(str/lower (:name %)) (vals (get-in libraries [selected :data :typographies]))))
state (mf/use-state {:offset 0}) state (mf/use-state {:offset 0})
offset-step 144 offset-step 144
buttons-size (cond buttons-size (cond
@ -182,13 +182,17 @@
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [size width selected] :as props}] [{:keys [size width selected] :as props}]
(let [selected-ids (mf/deref refs/selected-shapes) (let [selected-ids (mf/deref refs/selected-shapes)
;; FIXME: we have duplicate operations, if we already have the
;; libraries, so we already have file-typographies so we don't
;; need two separate lens/refs for that
file-typographies (mf/deref refs/workspace-file-typography) file-typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/libraries) libraries (mf/deref refs/files)
current-file-id (mf/use-ctx ctx/current-file-id)] current-file-id (mf/use-ctx ctx/current-file-id)]
[:& palette {:current-file-id current-file-id [:& palette {:current-file-id current-file-id
:selected-ids selected-ids :selected-ids selected-ids
:file-typographies file-typographies :file-typographies file-typographies
:shared-libs shared-libs :libraries libraries
:width width :width width
:selected selected :selected selected
:size size}])) :size size}]))

View file

@ -17,11 +17,11 @@
(mf/defc text-palette-ctx-menu (mf/defc text-palette-ctx-menu
[{:keys [show-menu? close-menu on-select-palette selected]}] [{:keys [show-menu? close-menu on-select-palette selected]}]
(let [typographies (mf/deref refs/workspace-file-typography) (let [typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/libraries)] libraries (mf/deref refs/libraries)]
[:& dropdown {:show show-menu? [:& dropdown {:show show-menu?
:on-close close-menu} :on-close close-menu}
[:ul {:class (stl/css :text-context-menu)} [:ul {:class (stl/css :text-context-menu)}
(for [[idx cur-library] (map-indexed vector (vals shared-libs))] (for [[idx cur-library] (map-indexed vector (vals libraries))]
(let [typographies (-> cur-library (get-in [:data :typographies]) vals)] (let [typographies (-> cur-library (get-in [:data :typographies]) vals)]
[:li [:li
{:class (stl/css-case :palette-library true {:class (stl/css-case :palette-library true