enhance(ui): WIP playground for x popup

pull/10933/head^2
charlie 2024-02-08 10:04:11 +08:00
parent b6a0ecd462
commit 6eb46ba77a
1 changed files with 77 additions and 30 deletions

View File

@ -1,51 +1,98 @@
(ns logseq.shui.demo2
(:require [rum.core :as rum]
[logseq.shui.ui :as ui]
[frontend.rum :refer [use-atom]]
[medley.core :as medley]
[logseq.shui.util :refer [use-atom]]
[frontend.components.icon :refer [emojis-cp emojis]]))
(defonce *x-popup-state
(atom {:open? false :content nil :position [0 0]}))
;; {:id "" :open? false :content nil :position [0 0] :root-props nil :content-props nil}
(defonce ^:private *popups (atom []))
(defonce ^:private *id (atom 0))
(defonce ^:private gen-id #(reset! *id (inc @*id)))
(defn get-popup
[id]
(when id
(some->> (medley/indexed @*popups)
(filter #(= id (:id (second %)))) (first))))
(defn upsert-popup!
[config]
(when-let [_id (:id config)]
(swap! *popups conj config)))
(defn update-popup!
[id ks val]
(when-let [[index config] (get-popup id)]
(let [ks (if (coll? ks) ks [ks])
config (if (nil? val)
(medley/dissoc-in config ks)
(assoc-in config ks val))]
(swap! *popups assoc index config))))
(defn detach-popup!
[id]
(when-let [[index] (get-popup id)]
(swap! *popups #(->> % (medley/remove-nth index) (vec)))))
(defn show-x-popup!
[^js event content & {:keys [as-menu? root-props content-props]}]
[^js event content & {:keys [id as-menu? root-props content-props]}]
(let [x (.-clientX event)
y (.-clientY event)]
(reset! *x-popup-state
{:open? true :content content :position [x y]
(upsert-popup!
{:id (or id (gen-id)) :open? true :content content :position [x y]
:as-menu? as-menu? :root-props root-props :content-props content-props})))
(defn hide-x-popup!
[]
(when (true? (:open? @*x-popup-state))
(swap! *x-popup-state assoc :open? false)
(js/setTimeout
#(reset! *x-popup-state
{:open? false :content nil :position [0 0] :as-menu? false}) 128)))
[id]
(update-popup! id :open? false))
(rum/defc x-popup []
(let [[{:keys [open? content position as-menu? root-props content-props]} _] (use-atom *x-popup-state)]
(when-let [[x y] position]
(let [popup-root (if as-menu? ui/dropdown-menu ui/popover)
popup-trigger (if as-menu? ui/dropdown-menu-trigger ui/popover-trigger)
popup-content (if as-menu? ui/dropdown-menu-content ui/popover-content)]
(popup-root
(merge root-props {:open open?})
(popup-trigger
{:as-child true}
(ui/button {:class "w-1 h-1 overflow-hidden fixed p-0 opacity-0"
:style {:top y :left x}} ""))
(popup-content
(merge {:onEscapeKeyDown #(hide-x-popup!)
:onPointerDownOutside #(hide-x-popup!)} content-props)
(if (fn? content) (content) content))))
)))
(defn hide-x-popup-all!
[]
(doseq [{:keys [id]} @*popups]
(hide-x-popup! id)))
(rum/defc x-popup [{:keys [id open? content position as-menu? root-props content-props] :as _props}]
(rum/use-effect!
(fn []
(when (false? open?)
(js/setTimeout #(detach-popup! id) 128)))
[open?])
(when-let [[x y] position]
(let [popup-root (if as-menu? ui/dropdown-menu ui/popover)
popup-trigger (if as-menu? ui/dropdown-menu-trigger ui/popover-trigger)
popup-content (if as-menu? ui/dropdown-menu-content ui/popover-content)]
(popup-root
(merge root-props {:open open?})
(popup-trigger
{:as-child true}
(ui/button {:class "w-1 h-1 overflow-hidden fixed p-0 opacity-0"
:style {:top y :left x}} ""))
(popup-content
(merge {:onEscapeKeyDown #(hide-x-popup! id)
:onPointerDownOutside #(hide-x-popup! id)} content-props)
(if (fn? content) (content {:id id}) content))))))
(rum/defc install-popups
< rum/static
[]
(let [[popups _set-popups!] (use-atom *popups)]
[:<>
(for [config popups
:when (and (map? config) (:id config))]
(x-popup config))]))
(rum/defc page []
[:div.sm:p-10
[:h1.text-3xl.font-bold.border-b.pb-4 "UI X Popup"]
(rum/portal (x-popup) js/document.body)
(rum/portal
(install-popups)
js/document.body)
(let [[emoji set-emoji!] (rum/use-state nil)
emoji-picker (fn [_nested?]
@ -58,7 +105,7 @@
{:on-chosen
(fn [_ t]
(set-emoji! t)
(hide-x-popup!))})]
(hide-x-popup-all!))})]
{:content-props {:class "w-72 p-0"}
:as-menu? true})}
(if emoji [:strong.px-1.text-6xl [:em-emoji emoji]] "emoji :O")] "."])]
@ -81,7 +128,7 @@
(ui/dropdown-menu-item
{:on-select (fn []
(ui/toast! it)
(hide-x-popup!))}
(hide-x-popup-all!))}
[:strong it]))))
{:as-menu? true
:content-props {:class "w-48"}})