Quellcode durchsuchen

enhance(ui): support multi select within the popup

charlie vor 1 Jahr
Ursprung
Commit
0b43253bbe

+ 17 - 10
deps/shui/src/logseq/shui/popup/core.cljs

@@ -60,7 +60,7 @@
     (swap! *popups #(->> % (medley/remove-nth index) (vec)))))
 
 (defn show!
-  [^js event content & {:keys [id as-menu? align root-props content-props] :as opts}]
+  [^js event content & {:keys [id as-menu? as-content? align root-props content-props] :as opts}]
   (let [position (cond
                    (vector? event) event
 
@@ -81,9 +81,10 @@
                    :else [0 0])]
     (upsert-popup!
       (merge opts
-        {:id       (or id (gen-id))
-         :open?    true :content content :position position
+        {:id (or id (gen-id))
+         :open? true :content content :position position
          :as-menu? as-menu?
+         :as-content? as-content?
          :root-props root-props
          :content-props (cond-> content-props
                           (not (nil? align))
@@ -100,7 +101,8 @@
     (hide! id)))
 
 (rum/defc x-popup
-  [{:keys [id open? content position as-menu? auto-side? root-props content-props] :as _props}]
+  [{:keys [id open? content position as-menu? as-content? auto-side? root-props content-props]
+    :as _props}]
   (rum/use-effect!
     (fn []
       (when (false? open?)
@@ -129,12 +131,17 @@
                                          (> height 0))
                                      height 1)
                            :width 1
-                           :top    y
-                           :left   x}} ""))
-        (popup-content
-          (merge {:onEscapeKeyDown      #(hide! id)
-                  :onPointerDownOutside #(hide! id)} content-props)
-          (if (fn? content) (content {:id id}) content))))))
+                           :top y
+                           :left x}} ""))
+        (let [content-props (merge {:onEscapeKeyDown #(hide! id)
+                                    :onPointerDownOutside #(hide! id)} content-props)
+              content (if (fn? content)
+                        (content (cond-> {:id id}
+                                   as-content?
+                                   (assoc :content-props content-props))) content)]
+          (if as-content?
+            content
+            (popup-content content-props content)))))))
 
 (rum/defc install-popups
   < rum/static

+ 1 - 1
deps/shui/src/logseq/shui/select/multi.cljs

@@ -52,7 +52,7 @@
                  (string/lower-case)
                  (string/includes? q)) items))))
 
-(rum/defc x-select
+(rum/defc x-select-content
   [items selected-items & {:keys [on-chosen item-render value-render
                                   head-render foot-render open? close!
                                   search-enabled? search-key on-search-key-change

+ 4 - 1
deps/shui/src/logseq/shui/ui.cljs

@@ -3,6 +3,7 @@
             [logseq.shui.icon.v2 :as icon-v2]
             [logseq.shui.toaster.core :as toaster-core]
             [logseq.shui.select.core :as select-core]
+            [logseq.shui.select.multi :as select-multi]
             [logseq.shui.dialog.core :as dialog-core]
             [logseq.shui.popup.core :as popup-core]
             [logseq.shui.form.core :as form-core]))
@@ -111,4 +112,6 @@
 (def dialog-close-all! dialog-core/close-all!)
 (def popup-show! popup-core/show!)
 (def popup-hide! popup-core/hide!)
-(def popup-hide-all! popup-core/hide-all!)
+(def popup-hide-all! popup-core/hide-all!)
+
+(def multi-select-content select-multi/x-select-content)

+ 7 - 5
src/main/frontend/components/property.css

@@ -19,10 +19,6 @@
     max-height: var(--radix-dropdown-menu-content-available-height);
 }
 
-/* .property-value-content:hover { */
-/*     background: var(--ls-secondary-background-color); */
-/* } */
-
 .ls-block .ls-properties-area, .property-block-container {
     border-left: 1px solid;
     border-left-color: or(--lx-gray-04-alpha, --ls-guideline-color, #ddd) !important;
@@ -36,7 +32,9 @@
     margin-left: 0;
 }
 
-.ls-block .property-pair, .property-block .property-value, .property-template .property-pair {
+.ls-block .property-pair,
+.property-block .property-value,
+.property-template .property-pair {
     padding-left: 22px;
 }
 
@@ -107,6 +105,10 @@
     .property-key a:hover {
         color: var(--ls-link-text-hover-color);
     }
+
+    .multi-values {
+        @apply cursor-pointer active:opacity-80;
+    }
 }
 
 .block-main-container .ls-properties-area {

+ 58 - 38
src/main/frontend/components/property/value.cljs

@@ -193,7 +193,11 @@
     (select/select (assoc opts
                           :selected-choices selected-choices
                           :items items'
-                          k f'))))
+                          k f'))
+    ;(shui/multi-select-content
+    ;  (map #(let [{:keys [value label]} %]
+    ;          {:id value :value label}) items') nil opts)
+    ))
 
 (defn select-page
   [property
@@ -393,7 +397,7 @@
                (reset! *values result))
              (assoc state ::values *values)))}
   [state block property
-   {:keys [multiple-choices? dropdown?] :as opts}
+   {:keys [multiple-choices? dropdown? content-props] :as select-opts}
    {:keys [*show-new-property-config?]}]
   (let [values (rum/react (::values state))]
     (when-not (= :loading values)
@@ -428,7 +432,7 @@
             on-chosen (fn [chosen]
                         (p/do!
                          (add-property-f (if (map? chosen) (:value chosen) chosen))
-                         (when-let [f (:on-chosen opts)] (f))))
+                         (when-let [f (:on-chosen select-opts)] (f))))
             selected-choices' (get-in block [:block/properties (:block/uuid property)])
             selected-choices (if (coll? selected-choices') selected-choices' [selected-choices'])]
         (select-aux block property
@@ -440,10 +444,11 @@
                       :show-new-when-not-exact-match? (not (or closed-values? (= :date type)))
                       :input-default-placeholder "Select"
                       :extract-chosen-fn :value
+                      :content-props content-props
                       :input-opts (fn [_]
                                     {:on-blur (fn []
                                                 (exit-edit-property)
-                                                (when-let [f (:on-chosen opts)] (f)))
+                                                (when-let [f (:on-chosen select-opts)] (f)))
                                      :on-click (fn []
                                                  (when *show-new-property-config?
                                                    (reset! *show-new-property-config? false)))
@@ -453,7 +458,7 @@
                                          "Escape"
                                          (do
                                            (exit-edit-property)
-                                           (when-let [f (:on-chosen opts)] (f)))
+                                           (when-let [f (:on-chosen select-opts)] (f)))
                                          nil))})}
                       closed-values?
                       (assoc :extract-fn :label)
@@ -564,20 +569,21 @@
 (rum/defc select-item
   [property type value {:keys [page-cp inline-text _icon?] :as opts}]
   (let [closed-values? (seq (get-in property [:block/schema :values]))]
-    (cond
-      (contains? #{:page :date} type)
-      (when-let [page (db/entity [:block/uuid value])]
-        (page-cp {:disable-preview? true
-                  :hide-close-button? true} page))
+    [:div.select-item
+     (cond
+       (contains? #{:page :date} type)
+       (when-let [page (db/entity [:block/uuid value])]
+         (page-cp {:disable-preview? true
+                   :hide-close-button? true} page))
 
-      closed-values?
-      (closed-value-item value opts)
+       closed-values?
+       (closed-value-item value opts)
 
-      (= type :number)
-      [:span.number (str value)]
+       (= type :number)
+       [:span.number (str value)]
 
-      :else
-      (inline-text {} :markdown (macro-util/expand-value-if-macro (str value) (state/get-macros))))))
+       :else
+       (inline-text {} :markdown (macro-util/expand-value-if-macro (str value) (state/get-macros))))]))
 
 (rum/defc single-value-select
   [block property value value-f select-opts {:keys [editing?] :as opts}]
@@ -711,12 +717,13 @@
 
                   (inline-text {} :markdown (macro-util/expand-value-if-macro (str value) (state/get-macros)))))]))]))))
 
-(rum/defc multiple-values < rum/reactive
+(rum/defc multiple-values
   [block property v {:keys [on-chosen dropdown? editing?]
                      :or {dropdown? true}
                      :as opts} schema]
   (let [type (get schema :type :default)
         date? (= type :date)
+        *el (rum/use-ref nil)
         items (if (coll? v) v (when v [v]))
         values-cp (fn [toggle-fn]
                     (if (seq items)
@@ -726,11 +733,12 @@
                        (when date?
                          [(property-value-date-picker block property nil {:toggle-fn toggle-fn})]))
                       (when-not editing? [:div.opacity-50.pointer.text-sm "Empty"])))
-        select-cp (fn []
-                    (let [select-opts {:multiple-choices? true
-                                       :dropdown? editing?
-                                       :on-chosen (fn []
-                                                    (when on-chosen (on-chosen)))}]
+        select-cp (fn [select-opts]
+                    (let [select-opts (merge {:multiple-choices? true
+                                              :dropdown? editing?
+                                              :on-chosen (fn []
+                                                           (when on-chosen (on-chosen)))}
+                                        select-opts)]
                       [:div.property-select (cond-> {} editing? (assoc :class "h-6"))
                        (if (= :page type)
                          (property-value-select-page block property
@@ -738,23 +746,35 @@
                                                             :classes (:classes schema))
                                                      opts)
                          (select block property select-opts opts))]))]
+
+    (rum/use-effect!
+      (fn []
+        (when editing?
+          (prn "TODO: editing multiple select immediately show...")))
+      [editing?])
+
     (if (and dropdown? (not editing?))
-      (ui/dropdown
-       (fn [{:keys [toggle-fn]}]
-         [:a.control-link.jtrigger
-          {:on-click (fn [_e]
-                       (if config/publishing?
-                         nil
-                         (toggle-fn)))
-           :class "flex flex-1 flex-row items-center flex-wrap gap-x-2 gap-y-2 pr-4"}
-          (values-cp toggle-fn)])
-       (fn [{:keys [_toggle-fn]}]
-         (select-cp))
-       {:modal-class (util/hiccup->class
-                      "origin-top-right.absolute.left-0.rounded-md.shadow-lg.mt-2")
-        :trigger-class "w-full"
-        :initial-open? editing?})
-      (select-cp))))
+      (let [toggle-fn #(shui/popup-hide!)
+            content-fn (fn [{:keys [_id content-props]}]
+                         (select-cp {:content-props content-props}))]
+        ;;
+        [:div.multi-values.jtrigger
+         {:tab-index "0"
+          :ref *el
+          :on-click (fn [^js e]
+                      (when-not (.closest (.-target e) ".select-item")
+                        (if config/publishing?
+                          nil
+                          (shui/popup-show! (rum/deref *el) content-fn
+                            {:as-menu? true :as-content? false}))))
+          :on-key-up (fn [^js e]
+                       (case (.-key e)
+                         (" " "Enter")
+                         (some-> (rum/deref *el) (.click))
+                         :dune))
+          :class "flex flex-1 flex-row items-center flex-wrap gap-x-2 gap-y-2 pr-4"}
+         (values-cp toggle-fn)])
+      (select-cp {:content-props nil}))))
 
 (rum/defc property-value < rum/reactive
   [block property v opts]