| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- (ns frontend.components.icon
- (:require ["@emoji-mart/data" :as emoji-data]
- ["emoji-mart" :refer [SearchIndex]]
- [promesa.core :as p]
- [cljs-bean.core :as bean]
- [camel-snake-kebab.core :as csk]
- [clojure.string :as string]
- [frontend.search :as search]
- [rum.core :as rum]
- [frontend.ui :as ui]
- [frontend.util :as util]
- [goog.object :as gobj]
- [goog.functions :refer [debounce]]))
- (defn icon
- [icon]
- (cond
- (and (= :emoji (:type icon)) (:id icon))
- [:em-emoji {:id (:id icon)}]
- (and (= :tabler-icon (:type icon)) (:id icon))
- (ui/icon (:id icon))))
- (defn- search-emojis
- [q]
- (p/let [result (.search SearchIndex q)]
- (bean/->clj result)))
- (defonce *tabler-icons (atom nil))
- (defn- get-tabler-icons
- []
- (if @*tabler-icons
- @*tabler-icons
- (let [result (->> (keys (bean/->clj js/tablerIcons))
- (map (fn [k]
- (-> (string/replace (csk/->Camel_Snake_Case (name k)) "_" " ")
- (string/replace-first "Icon " ""))))
- ;; FIXME: somehow those icons don't work
- (remove #{"Ab" "Ab 2" "Ab Off"}))]
- (reset! *tabler-icons result)
- result)))
- (def emojis
- (vals (bean/->clj (gobj/get emoji-data "emojis"))))
- (defn- search-tabler-icons
- [q]
- (search/fuzzy-search (get-tabler-icons) q :limit 100))
- (defn- search
- [q]
- (p/let [icons (search-tabler-icons q)
- emojis (search-emojis q)]
- {:icons icons
- :emojis emojis}))
- (rum/defc emoji-cp < rum/static
- [{:keys [id name] :as emoji} {:keys [on-chosen hover]}]
- [:button.text-2xl.w-9.h-9.transition-opacity
- {:tabIndex "0"
- :title name
- :on-click (fn [e]
- (on-chosen e {:type :emoji
- :id id
- :name name}))
- :on-mouse-over #(reset! hover emoji)
- :on-mouse-out #(reset! hover nil)}
- [:em-emoji {:id id}]])
- (rum/defc emojis-cp < rum/static
- [emojis opts]
- [:div.emojis.flex.flex-1.flex-row.gap-1.flex-wrap
- (for [emoji emojis]
- (rum/with-key (emoji-cp emoji opts) (:id emoji)))])
- (rum/defc icon-cp < rum/static
- [icon {:keys [on-chosen hover]}]
- [:button.w-9.h-9.transition-opacity
- {:key icon
- :tabIndex "0"
- :title icon
- :on-click (fn [e]
- (on-chosen e {:type :tabler-icon
- :id icon
- :name icon}))
- :on-mouse-over #(reset! hover {:type :tabler-icon
- :id icon
- :name icon
- :icon icon})
- :on-mouse-out #(reset! hover nil)}
- (ui/icon icon {:size 24})])
- (rum/defc icons-cp < rum/static
- [icons opts]
- [:div.icons.flex.flex-1.flex-row.gap-1.flex-wrap
- (for [icon icons]
- (icon-cp icon opts))])
- (rum/defcs icon-search <
- (rum/local "" ::q)
- (rum/local nil ::result)
- (rum/local :emoji ::tab)
- (rum/local nil ::hover)
- [state opts]
- (let [*q (::q state)
- *result (::result state)
- *tab (::tab state)
- *hover (::hover state)
- result @*result
- emoji-tab? (= @*tab :emoji)
- opts (assoc opts :hover *hover)]
- [:div.icon-search.flex.flex-1.flex-col.gap-2
- [:input.form-input.block.w-full.sm:text-sm.sm:leading-5
- {:auto-focus true
- :placeholder "Select icon"
- :default-value ""
- :on-change (debounce
- (fn [e]
- (reset! *q (util/evalue e))
- (if (string/blank? @*q)
- (reset! *result {})
- (p/let [result (search @*q)]
- (reset! *result result))))
- 200)}]
- [:div.search-result
- (if (seq result)
- [:div.flex.flex-1.flex-col.gap-1
- (when (seq (:emojis result))
- (emojis-cp (:emojis result) opts))
- (when (seq (:icons result))
- (icons-cp (:icons result) opts))]
- [:div.flex.flex-1.flex-col.gap-1
- [:div.flex.flex-1.flex-row.items-center.gap-2
- (ui/button
- "Emojis"
- {:intent "logseq"
- :small? true
- :on-click #(reset! *tab :emoji)})
- (ui/button
- "Icons"
- {:intent "logseq"
- :small? true
- :on-click #(reset! *tab :icon)})]
- (if emoji-tab?
- (emojis-cp emojis opts)
- (icons-cp (get-tabler-icons) opts))])]
- (if @*hover
- [:div.flex.flex-1.flex-row.items-center.gap-2
- [:button.transition-opacity
- {:style {:font-size 32}
- :key (:id @*hover)
- :title (:name @*hover)}
- (if (= :tabler-icon (:type @*hover))
- (ui/icon (:icon @*hover) {:size 32})
- (:native (first (:skins @*hover))))]
- (:name @*hover)]
- [:div {:style {:padding-bottom 32}}])]))
|