Browse Source

enhance: select auto-complete support dropdown

Tienson Qin 2 years ago
parent
commit
c5c253b510

+ 3 - 0
src/main/frontend/components/property.cljs

@@ -154,6 +154,7 @@
         pages (->> (model/get-all-page-original-names repo)
                    (map (fn [p] {:value p})))]
     (select/select {:items pages
+                    :dropdown? true
                     :on-chosen (fn [chosen]
                                  (let [page (:value chosen)
                                        id (:block/uuid (db/entity [:block/name (util/page-name-sanity-lc page)]))]
@@ -180,6 +181,7 @@
                    (map (fn [b]
                           (assoc b :value (:block/content b)))))]
     (select/select {:items blocks
+                    :dropdown? true
                     :on-chosen (fn [chosen]
                                  (let [id (:block/uuid chosen)]
                                    (add-property! block (:block/original-name property) id true)))
@@ -220,6 +222,7 @@
                    (distinct))
         add-property-f #(add-property! block (:block/original-name property) % true)]
     (select/select {:items items
+                    :dropdown? true
                     :on-chosen (fn [chosen] (add-property-f (:value chosen)))
                     :input-opts (fn [not-matched?]
                                   {:on-key-down (fn [e]

+ 15 - 2
src/main/frontend/components/property.css

@@ -31,6 +31,14 @@
     .cp__select-main {
         width: fit-content;
         margin: 0;
+
+        .ui__dropdown-trigger {
+            position: absolute;
+
+            .dropdown-wrapper {
+                left: 0;
+            }
+        }
     }
 
     .cp__select .input-wrap {
@@ -38,12 +46,17 @@
         min-width: 14em;
     }
 
-    .cp__select .input-wrap input {
+    .cp__select .input-wrap input.cp__select-input {
         border: none;
     }
 
+    .cp__select .input-wrap input.cp__select-input:focus {
+        outline: none;
+        box-shadow: none;
+    }
+
     .cp__select-input {
-        padding: 0.5em 1em;
+        padding: 0.25em;
     }
 
     .ls-block, .editor-wrapper {

+ 43 - 33
src/main/frontend/components/select.cljs

@@ -47,7 +47,8 @@
                  prompt-key input-default-placeholder close-modal?
                  extract-fn host-opts on-input input-opts
                  item-cp transform-fn tap-*input-val
-                 multiple-choices? on-apply _selected-choices]
+                 multiple-choices? on-apply _selected-choices
+                 dropdown?]
           :or {limit 100
                prompt-key :select/default-prompt
                empty-placeholder (fn [_t] [:div])
@@ -58,43 +59,52 @@
         search-result (cond-> (search/fuzzy-search items @input :limit limit :extract-fn extract-fn)
                         (fn? transform-fn)
                         (transform-fn @input))
-        input-opts' (if (fn? input-opts) (input-opts (empty? search-result)) input-opts)]
+        input-opts' (if (fn? input-opts) (input-opts (empty? search-result)) input-opts)
+        input-container [:div.input-wrap
+                         [:input.cp__select-input.w-full
+                          (merge {:type        "text"
+                                  :placeholder (or input-default-placeholder (t prompt-key))
+                                  :auto-focus  true
+                                  :value       @input
+                                  :on-change   (fn [e]
+                                                 (let [v (util/evalue e)]
+                                                   (reset! input v)
+                                                   (and (fn? on-input) (on-input v))))}
+                                 input-opts')]]
+        results-container [:div
+                           [:div.item-results-wrap
+                            (ui/auto-complete
+                             search-result
+                             {:item-render       (or item-cp (fn [result chosen?]
+                                                               (render-item result chosen? multiple-choices? *selected-choices)))
+                              :class             "cp__select-results"
+                              :on-chosen         (fn [x]
+                                                   (reset! input "")
+                                                   (if multiple-choices?
+                                                     (if (@*selected-choices x)
+                                                       (swap! *selected-choices disj x)
+                                                       (swap! *selected-choices conj x))
+                                                     (do
+                                                       (when close-modal? (state/close-modal!))
+                                                       (when on-chosen
+                                                         (on-chosen (if multiple-choices? @*selected-choices x))))))
+                              :empty-placeholder (empty-placeholder t)})]
+
+                           (when multiple-choices?
+                             [:div.p-4 (ui/button "Apply updates" :on-click on-apply)])]]
     (when (fn? tap-*input-val)
       (tap-*input-val input))
     [:div.cp__select
      (merge {:class "cp__select-main"} host-opts)
-     [:div.input-wrap
-      [:input.cp__select-input.w-full
-       (merge {:type        "text"
-               :placeholder (or input-default-placeholder (t prompt-key))
-               :auto-focus  true
-               :value       @input
-               :on-change   (fn [e]
-                              (let [v (util/evalue e)]
-                                (reset! input v)
-                                (and (fn? on-input) (on-input v))))}
-              input-opts')]]
-
-     [:div.item-results-wrap
-      (ui/auto-complete
-       search-result
-       {:item-render       (or item-cp (fn [result chosen?]
-                                         (render-item result chosen? multiple-choices? *selected-choices)))
-        :class             "cp__select-results"
-        :on-chosen         (fn [x]
-                             (reset! input "")
-                             (if multiple-choices?
-                               (if (@*selected-choices x)
-                                 (swap! *selected-choices disj x)
-                                 (swap! *selected-choices conj x))
-                               (do
-                                 (when close-modal? (state/close-modal!))
-                                 (when on-chosen
-                                   (on-chosen (if multiple-choices? @*selected-choices x))))))
-        :empty-placeholder (empty-placeholder t)})]
 
-     (when multiple-choices?
-       [:div.p-4 (ui/button "Apply updates" :on-click on-apply)])]))
+     (if dropdown?
+       (ui/dropdown
+        (fn [] input-container)
+        (fn [] results-container)
+        :initial-open? true)
+       [:<>
+        input-container
+        results-container])]))
 
 (defn select-config
   "Config that supports multiple types (uses) of this component. To add a new

+ 9 - 1
src/main/frontend/ui.cljs

@@ -142,8 +142,16 @@
 
 ;; public exports
 (rum/defcs dropdown < (mixins/modal :open?)
+  {:init (fn [state]
+           (let [opts (->> (drop 2 (:rum/args state))
+                           (partition 2)
+                           (map vec)
+                           (into {}))]
+             (when (:initial-open? opts)
+               (reset! (:open? state) true)))
+           state)}
   [state content-fn modal-content-fn
-   & [{:keys [modal-class z-index trigger-class]
+   & [{:keys [modal-class z-index trigger-class initial-open?]
        :or   {z-index 999}}]]
   (let [{:keys [open?]} state
         modal-content (modal-content-fn state)