From 6eb46ba77ad12e7c541b119668337f689880d073 Mon Sep 17 00:00:00 2001 From: charlie Date: Thu, 8 Feb 2024 10:04:11 +0800 Subject: [PATCH] enhance(ui): WIP playground for x popup --- deps/shui/src/logseq/shui/demo2.cljs | 107 +++++++++++++++++++-------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/deps/shui/src/logseq/shui/demo2.cljs b/deps/shui/src/logseq/shui/demo2.cljs index 65d490fea..565fd1587 100644 --- a/deps/shui/src/logseq/shui/demo2.cljs +++ b/deps/shui/src/logseq/shui/demo2.cljs @@ -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"}})