Bladeren bron

enhance(ux): use arrows for properties navigation (#11535)

enhance: properties support arrow navigation
Tienson Qin 1 jaar geleden
bovenliggende
commit
1c71b10247

+ 18 - 14
src/main/frontend/components/block.cljs

@@ -2532,7 +2532,7 @@
         attrs (cond->
         attrs (cond->
                {:blockid       (str uuid)
                {:blockid       (str uuid)
                 :class (util/classnames [{:jtrigger (:property-block? config)
                 :class (util/classnames [{:jtrigger (:property-block? config)
-                                          :!cursor-pointer (:page-title? config)}])
+                                          :!cursor-pointer (or (:property? config) (:page-title? config))}])
                 :containerid (:container-id config)
                 :containerid (:container-id config)
                 :data-type (name block-type)
                 :data-type (name block-type)
                 :style {:width "100%"
                 :style {:width "100%"
@@ -2736,14 +2736,14 @@
                                     (editor-handler/edit-block! block :max))}
                                     (editor-handler/edit-block! block :max))}
                 svg/edit])])])
                 svg/edit])])])
 
 
-       (when-not (or (:table? config) (:page-title? config))
+       (when-not (or (:table? config) (:property? config) (:page-title? config))
          (block-refs-count block refs-count *hide-block-refs?))
          (block-refs-count block refs-count *hide-block-refs?))
 
 
-       (when-not (or (:block-ref? config) (:table? config))
+       (when-not (or (:block-ref? config) (:table? config) (:property? config))
          (when (and db-based? (seq (:block/tags block)))
          (when (and db-based? (seq (:block/tags block)))
            (tags-cp (assoc config :block/uuid (:block/uuid block)) block)))]
            (tags-cp (assoc config :block/uuid (:block/uuid block)) block)))]
 
 
-      (when (and (not (:table? config))
+      (when (and (not (or (:table? config) (:property? config)))
                  (not hide-block-refs?)
                  (not hide-block-refs?)
                  (> refs-count 0)
                  (> refs-count 0)
                  (not (:page-title? config)))
                  (not (:page-title? config)))
@@ -3097,6 +3097,7 @@
         editing? (or (state/sub-editing? [container-id (:block/uuid block)])
         editing? (or (state/sub-editing? [container-id (:block/uuid block)])
                      (state/sub-editing? [:unknown-container (:block/uuid block)]))
                      (state/sub-editing? [:unknown-container (:block/uuid block)]))
         table? (:table? config*)
         table? (:table? config*)
+        property? (:property? config*)
         custom-query? (boolean (:custom-query? config*))
         custom-query? (boolean (:custom-query? config*))
         ref-or-custom-query? (or ref? custom-query?)
         ref-or-custom-query? (or ref? custom-query?)
         *navigating-block (get container-state ::navigating-block)
         *navigating-block (get container-state ::navigating-block)
@@ -3131,9 +3132,12 @@
         db-based? (config/db-based-graph? repo)]
         db-based? (config/db-based-graph? repo)]
     [:div.ls-block
     [:div.ls-block
      (cond->
      (cond->
-      {:id (str "ls-block-" uuid)
+      {:id (str "ls-block-"
+                ;; container-id "-"
+                uuid)
        :blockid (str uuid)
        :blockid (str uuid)
        :containerid container-id
        :containerid container-id
+       :data-is-property (ldb/property? block)
        :ref #(when (nil? @*ref) (reset! *ref %))
        :ref #(when (nil? @*ref) (reset! *ref %))
        :data-collapsed (and collapsed? has-child?)
        :data-collapsed (and collapsed? has-child?)
        :class (str "id" uuid " "
        :class (str "id" uuid " "
@@ -3162,13 +3166,13 @@
        custom-query?
        custom-query?
        (assoc :data-query true))
        (assoc :data-query true))
 
 
-     (when (and ref? breadcrumb-show? (not table?))
+     (when (and ref? breadcrumb-show? (not (or table? property?)))
        (breadcrumb config repo uuid {:show-page? false
        (breadcrumb config repo uuid {:show-page? false
                                      :indent? true
                                      :indent? true
                                      :navigating-block *navigating-block}))
                                      :navigating-block *navigating-block}))
 
 
      ;; only render this for the first block in each container
      ;; only render this for the first block in each container
-     (when (and top? (not table?))
+     (when (and top? (not (or table? property?)))
        (dnd-separator-wrapper block children block-id slide? true false))
        (dnd-separator-wrapper block children block-id slide? true false))
 
 
      (when-not (:hide-title? config)
      (when-not (:hide-title? config)
@@ -3188,7 +3192,7 @@
          :on-mouse-leave (fn [e]
          :on-mouse-leave (fn [e]
                            (block-mouse-leave e *control-show? block-id doc-mode?))}
                            (block-mouse-leave e *control-show? block-id doc-mode?))}
 
 
-        (when (and (not slide?) (not in-whiteboard?))
+        (when (and (not slide?) (not in-whiteboard?) (not property?))
           (let [edit? (or editing?
           (let [edit? (or editing?
                           (= uuid (:block/uuid (state/get-edit-block))))]
                           (= uuid (:block/uuid (state/get-edit-block))))]
             (block-control (assoc config :hide-bullet? (:page-title? config))
             (block-control (assoc config :hide-bullet? (:page-title? config))
@@ -3199,7 +3203,7 @@
                             :*control-show? *control-show?
                             :*control-show? *control-show?
                             :edit? edit?})))
                             :edit? edit?})))
 
 
-        (when (and @*show-left-menu? (not in-whiteboard?) (not table?))
+        (when (and @*show-left-menu? (not in-whiteboard?) (not (or table? property?)))
           (block-left-menu config block))
           (block-left-menu config block))
 
 
         [:div.flex.flex-col.w-full
         [:div.flex.flex-col.w-full
@@ -3246,22 +3250,22 @@
                                          :edit? editing?
                                          :edit? editing?
                                          :hide-block-refs-count? hide-block-refs-count?}))])]
                                          :hide-block-refs-count? hide-block-refs-count?}))])]
 
 
-         (when (and db-based? (not collapsed?) (not table?))
+         (when (and db-based? (not collapsed?) (not (or table? property?)))
            (block-positioned-properties config block :block-below))]
            (block-positioned-properties config block :block-below))]
 
 
-        (when (and @*show-right-menu? (not in-whiteboard?) (not table?))
+        (when (and @*show-right-menu? (not in-whiteboard?) (not (or table? property?)))
           (block-right-menu config block editing?))])
           (block-right-menu config block editing?))])
 
 
-     (when (and db-based? (not collapsed?) (not table?))
+     (when (and db-based? (not collapsed?) (not (or table? property?)))
        [:div (when-not (:page-title? config) {:style {:padding-left 45}})
        [:div (when-not (:page-title? config) {:style {:padding-left 45}})
         (db-properties-cp config block {:in-block-container? true})])
         (db-properties-cp config block {:in-block-container? true})])
 
 
-     (when-not (or (:hide-children? config) in-whiteboard? table?)
+     (when-not (or (:hide-children? config) in-whiteboard? (or table? property?))
        (let [config' (-> (update config :level inc)
        (let [config' (-> (update config :level inc)
                          (dissoc :original-block :data))]
                          (dissoc :original-block :data))]
          (block-children config' block children collapsed?)))
          (block-children config' block children collapsed?)))
 
 
-     (when-not (or in-whiteboard? table?) (dnd-separator-wrapper block children block-id slide? false false))]))
+     (when-not (or in-whiteboard? table? property?) (dnd-separator-wrapper block children block-id slide? false false))]))
 
 
 (defn- block-changed?
 (defn- block-changed?
   [old-block new-block]
   [old-block new-block]

+ 32 - 26
src/main/frontend/components/property.cljs

@@ -228,14 +228,38 @@
             (p/do!
             (p/do!
              (reset! *show-new-property-config? false))))))))
              (reset! *show-new-property-config? false))))))))
 
 
-(rum/defcs property-key-cp <
-  (rum/local false ::hover?)
-  [state block property {:keys [other-position? class-schema?]}]
-  (let [*hover? (::hover? state)
-        icon (:logseq.property/icon property)]
+(rum/defc property-key-title
+  [block property class-schema?]
+  (let [block-container (state/get-component :block/container)]
+    (shui/trigger-as
+     :a
+     {:tabIndex 0
+      :title (:block/title property)
+      :class "property-k flex select-none jtrigger w-full"
+      :on-pointer-down (fn [^js e]
+                         (when (util/meta-key? e)
+                           (route-handler/redirect-to-page! (:block/uuid property))
+                           (.preventDefault e)))
+      :on-click (fn [^js/MouseEvent e]
+                  (shui/popup-show! (.-target e)
+                                    (fn []
+                                      (property-config/dropdown-editor property block {:debug? (.-altKey e)
+                                                                                       :class-schema? class-schema?}))
+                                    {:content-props
+                                     {:class "ls-property-dropdown-editor as-root"
+                                      :onEscapeKeyDown (fn [e]
+                                                         (util/stop e)
+                                                         (shui/popup-hide!)
+                                                         (when-let [input (state/get-input)]
+                                                           (.focus input)))}
+                                     :align "start"
+                                     :as-dropdown? true}))}
+     (block-container {:property? true} property))))
+
+(rum/defc property-key-cp < rum/static
+  [block property {:keys [other-position? class-schema?]}]
+  (let [icon (:logseq.property/icon property)]
     [:div.property-key-inner.jtrigger-view
     [:div.property-key-inner.jtrigger-view
-     {:on-mouse-over   #(reset! *hover? true)
-      :on-mouse-leave  #(reset! *hover? false)}
      ;; icon picker
      ;; icon picker
      (when-not other-position?
      (when-not other-position?
        (let [content-fn (fn [{:keys [id]}]
        (let [content-fn (fn [{:keys [id]}]
@@ -268,25 +292,7 @@
        [:a.property-k.flex.select-none.jtrigger
        [:a.property-k.flex.select-none.jtrigger
         {:on-click #(route-handler/redirect-to-page! (:block/uuid property))}
         {:on-click #(route-handler/redirect-to-page! (:block/uuid property))}
         (:block/title property)]
         (:block/title property)]
-
-       (shui/trigger-as :a
-         {:tabIndex 0
-          :title (:block/title property)
-          :class "property-k flex select-none jtrigger w-full"
-          :on-pointer-down (fn [^js e]
-                             (when (util/meta-key? e)
-                               (route-handler/redirect-to-page! (:block/uuid property))
-                               (.preventDefault e)))
-          :on-click (fn [^js/MouseEvent e]
-                      (shui/popup-show! (.-target e)
-                        (fn []
-                          (property-config/dropdown-editor property block {:debug? (.-altKey e)
-                                                                           :class-schema? class-schema?}))
-                        {:content-props
-                         {:class "ls-property-dropdown-editor as-root"}
-                         :align "start"
-                         :as-dropdown? true}))}
-         (:block/title property)))]))
+       (property-key-title block property class-schema?))]))
 
 
 (rum/defcs property-input < rum/reactive
 (rum/defcs property-input < rum/reactive
   (rum/local nil ::ref)
   (rum/local nil ::ref)

+ 25 - 8
src/main/frontend/handler/editor.cljs

@@ -1280,7 +1280,7 @@
     (and (state/selection?) (= direction (state/get-selection-direction)))
     (and (state/selection?) (= direction (state/get-selection-direction)))
     (let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed-skip)
     (let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed-skip)
           first-last (if (= :up direction) first last)
           first-last (if (= :up direction) first last)
-          element (f (first-last (state/get-selection-blocks)))]
+          element (f (first-last (state/get-selection-blocks)) {:up-down? true})]
       (when element
       (when element
         (util/scroll-to-block element)
         (util/scroll-to-block element)
         (state/conj-selection-block! element direction)))
         (state/conj-selection-block! element direction)))
@@ -1289,7 +1289,7 @@
     (state/selection?)
     (state/selection?)
     (let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed)
     (let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed)
           last-first (if (= :up direction) last first)
           last-first (if (= :up direction) last first)
-          element (f (last-first (state/get-selection-blocks)))]
+          element (f (last-first (state/get-selection-blocks)) {:up-down? true})]
       (when element
       (when element
         (util/scroll-to-block element)
         (util/scroll-to-block element)
         (state/drop-last-selection-block!))))
         (state/drop-last-selection-block!))))
@@ -2550,7 +2550,7 @@
         f (case direction
         f (case direction
             :up util/get-prev-block-non-collapsed
             :up util/get-prev-block-non-collapsed
             :down util/get-next-block-non-collapsed)
             :down util/get-next-block-non-collapsed)
-        sibling-block (f selected)]
+        sibling-block (f selected {:up-down? true})]
     (when (and sibling-block (dom/attr sibling-block "blockid"))
     (when (and sibling-block (dom/attr sibling-block "blockid"))
       (util/scroll-to-block sibling-block)
       (util/scroll-to-block sibling-block)
       (state/exit-editing-and-set-selected-blocks! [sibling-block]))))
       (state/exit-editing-and-set-selected-blocks! [sibling-block]))))
@@ -2564,7 +2564,7 @@
               :up util/get-prev-block-non-collapsed
               :up util/get-prev-block-non-collapsed
               :down util/get-next-block-non-collapsed)
               :down util/get-next-block-non-collapsed)
           current-block (util/rec-get-node input "ls-block")
           current-block (util/rec-get-node input "ls-block")
-          sibling-block (f current-block)
+          sibling-block (f current-block {:up-down? true})
           {:block/keys [uuid title format]} (state/get-edit-block)]
           {:block/keys [uuid title format]} (state/get-edit-block)]
       (if sibling-block
       (if sibling-block
         (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
         (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
@@ -2634,12 +2634,26 @@
         selected-start (util/get-selection-start input)
         selected-start (util/get-selection-start input)
         selected-end (util/get-selection-end input)
         selected-end (util/get-selection-end input)
         left? (= direction :left)
         left? (= direction :left)
-        right? (= direction :right)]
-    (when (= input element)
+        right? (= direction :right)
+        block (some-> (state/get-edit-block) :db/id db/entity)
+        property? (ldb/property? block)]
+    (cond
+      (and input (not= input element))
+      (.focus input)
+
+      (= input element)
       (cond
       (cond
+        (and property? right? (cursor/end? input) (not= (get-in block [:block/schema :type]) :default))
+        (let [pair (util/rec-get-node input "property-pair")
+              jtrigger (when pair (dom/sel1 pair ".property-value-container .jtrigger"))]
+          (when jtrigger
+            (.focus jtrigger)))
+
         (not= selected-start selected-end)
         (not= selected-start selected-end)
-        (if left?
+        (cond
+          left?
           (cursor/move-cursor-to input selected-start)
           (cursor/move-cursor-to input selected-start)
+          :else
           (cursor/move-cursor-to input selected-end))
           (cursor/move-cursor-to input selected-end))
 
 
         (or (and left? (cursor/start? input))
         (or (and left? (cursor/start? input))
@@ -2649,7 +2663,10 @@
         :else
         :else
         (if left?
         (if left?
           (cursor/move-cursor-backward input)
           (cursor/move-cursor-backward input)
-          (cursor/move-cursor-forward input))))))
+          (cursor/move-cursor-forward input)))
+
+      :else
+      nil)))
 
 
 (defn- delete-and-update [^js input start end]
 (defn- delete-and-update [^js input start end]
   (util/safe-set-range-text! input "" start end)
   (util/safe-set-range-text! input "" start end)

+ 30 - 18
src/main/frontend/util.cljc

@@ -876,51 +876,63 @@
            (gdom/getElement section "id"))))))
            (gdom/getElement section "id"))))))
 
 
 #?(:cljs
 #?(:cljs
-   (defn get-elem-idx
-     [nodes node]
-     (let [equal? (fn [^js a ^js b]
-                    (or (some-> b (= a))
-                        (and a b (= (.-id a) (.-id b)))))]
-       (first (filter number? (map-indexed (fn [idx b] (when (equal? b node) idx)) nodes))))))
+   (defn- skip-same-top-blocks
+     [blocks block]
+     (let [property? (= (d/attr block "data-is-property") "true")
+           properties-area (rec-get-node block "ls-properties-area")]
+       (remove (fn [b]
+                 (and
+                  (not= b block)
+                  (or (= (when b (.-top (.getBoundingClientRect b)))
+                         (when block (.-top (.getBoundingClientRect block))))
+                      (when property?
+                        (and (not= (d/attr b "data-is-property") "true")
+                             (gdom/contains properties-area b)))))) blocks))))
 
 
 #?(:cljs
 #?(:cljs
    (defn get-prev-block-non-collapsed
    (defn get-prev-block-non-collapsed
      "Gets previous non-collapsed block. If given a container
      "Gets previous non-collapsed block. If given a container
       looks up blocks in that container e.g. for embed"
       looks up blocks in that container e.g. for embed"
      ([block] (get-prev-block-non-collapsed block {}))
      ([block] (get-prev-block-non-collapsed block {}))
-     ([block {:keys [container]}]
+     ([block {:keys [container up-down?]}]
       (when-let [blocks (if container
       (when-let [blocks (if container
                           (get-blocks-noncollapse container)
                           (get-blocks-noncollapse container)
                           (get-blocks-noncollapse))]
                           (get-blocks-noncollapse))]
-        (when-let [index (get-elem-idx blocks block)]
-          (let [idx (dec index)]
-            (when (>= idx 0)
-              (nth-safe blocks idx))))))))
+        (let [blocks (if up-down?
+                       (skip-same-top-blocks blocks block)
+                       blocks)]
+          (when-let [index (.indexOf blocks block)]
+            (let [idx (dec index)]
+              (when (>= idx 0)
+                (nth-safe blocks idx)))))))))
 
 
 #?(:cljs
 #?(:cljs
    (defn get-prev-block-non-collapsed-non-embed
    (defn get-prev-block-non-collapsed-non-embed
      [block]
      [block]
      (when-let [blocks (->> (get-blocks-noncollapse)
      (when-let [blocks (->> (get-blocks-noncollapse)
                             remove-embedded-blocks)]
                             remove-embedded-blocks)]
-       (when-let [index (get-elem-idx blocks block)]
+       (when-let [index (.indexOf blocks block)]
            (let [idx (dec index)]
            (let [idx (dec index)]
              (when (>= idx 0)
              (when (>= idx 0)
                (nth-safe blocks idx)))))))
                (nth-safe blocks idx)))))))
 
 
 #?(:cljs
 #?(:cljs
    (defn get-next-block-non-collapsed
    (defn get-next-block-non-collapsed
-     [block]
+     [block {:keys [up-down?]}]
      (when-let [blocks (and block (get-blocks-noncollapse))]
      (when-let [blocks (and block (get-blocks-noncollapse))]
-       (when-let [index (get-elem-idx blocks block)]
-         (let [idx (inc index)]
-           (when (>= (count blocks) idx)
-             (nth-safe blocks idx)))))))
+       (let [blocks (if up-down?
+                      (skip-same-top-blocks blocks block)
+                      blocks)]
+         (when-let [index (.indexOf blocks block)]
+           (let [idx (inc index)]
+             (when (>= (count blocks) idx)
+               (nth-safe blocks idx))))))))
 
 
 #?(:cljs
 #?(:cljs
    (defn get-next-block-non-collapsed-skip
    (defn get-next-block-non-collapsed-skip
      [block]
      [block]
      (when-let [blocks (get-blocks-noncollapse)]
      (when-let [blocks (get-blocks-noncollapse)]
-       (when-let [index (get-elem-idx blocks block)]
+       (when-let [index (.indexOf blocks block)]
          (loop [idx (inc index)]
          (loop [idx (inc index)]
            (when (>= (count blocks) idx)
            (when (>= (count blocks) idx)
              (let [block (nth-safe blocks idx)
              (let [block (nth-safe blocks idx)

+ 9 - 3
src/main/frontend/util/cursor.cljs

@@ -125,9 +125,15 @@
   [input]
   [input]
   (move-cursor-to input (line-end-pos input)))
   (move-cursor-to input (line-end-pos input)))
 
 
-;; (defn move-cursor-to-line-beginning
-;;   [input]
-;;   (move-cursor-to input (line-beginning-pos input)))
+(comment
+  (defn move-cursor-to-line-beginning
+    [input]
+    (move-cursor-to input (line-beginning-pos input))))
+
+(comment
+  (defn move-cursor-to-start
+    [input]
+    (move-cursor-to input 0)))
 
 
 (defn move-cursor-to-end
 (defn move-cursor-to-end
   [input]
   [input]