Browse Source

Take out condition and animate editor modals

ranfdev 4 years ago
parent
commit
3cbd304a22
1 changed files with 160 additions and 162 deletions
  1. 160 162
      src/main/frontend/components/editor.cljs

+ 160 - 162
src/main/frontend/components/editor.cljs

@@ -25,57 +25,46 @@
 
 (rum/defc commands < rum/reactive
   [id format]
-  (let [show-commands? (util/react *show-commands)]
-    (when (and show-commands?
-               @*slash-caret-pos
-               (not (state/sub :editor/show-page-search?))
-               (not (state/sub :editor/show-block-search?))
-               (not (state/sub :editor/show-template-search?))
-               (not (state/sub :editor/show-input))
-               (not (state/sub :editor/show-zotero))
-               (not (state/sub :editor/show-date-picker?)))
-      (let [matched (util/react *matched-commands)]
-        (ui/auto-complete
-         matched
-         {:get-group-name
-          (fn [item]
-            (get *first-command-group (first item)))
-
-          :item-render
-          (fn [item]
-            (let [command-name (first item)
-                  command-doc (get item 2)]
-              [:div {:title (when (state/show-command-doc?) command-doc)} command-name]))
-
-          :on-chosen
-          (fn [chosen-item]
-            (let [command (first chosen-item)]
-              (reset! commands/*current-command command)
-              (let [command-steps (get (into {} matched) command)
-                    restore-slash? (or
-                                    (contains? #{"Today" "Yesterday" "Tomorrow"} command)
-                                    (and
-                                     (not (fn? command-steps))
-                                     (not (contains? (set (map first command-steps)) :editor/input))
-                                     (not (contains? #{"Date Picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
-                (editor-handler/insert-command! id command-steps
-                                                format
-                                                {:restore? restore-slash?}))))
-          :class
-          "black"})))))
+  (let [matched (util/react *matched-commands)]
+    (ui/auto-complete
+     matched
+     {:get-group-name
+      (fn [item]
+        (get *first-command-group (first item)))
+
+      :item-render
+      (fn [item]
+        (let [command-name (first item)
+              command-doc (get item 2)]
+          [:div {:title (when (state/show-command-doc?) command-doc)} command-name]))
+
+      :on-chosen
+      (fn [chosen-item]
+        (let [command (first chosen-item)]
+          (reset! commands/*current-command command)
+          (let [command-steps (get (into {} matched) command)
+                restore-slash? (or
+                                (contains? #{"Today" "Yesterday" "Tomorrow"} command)
+                                (and
+                                 (not (fn? command-steps))
+                                 (not (contains? (set (map first command-steps)) :editor/input))
+                                 (not (contains? #{"Date Picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
+            (editor-handler/insert-command! id command-steps
+                                            format
+                                            {:restore? restore-slash?}))))
+      :class
+      "black"})))
 
 (rum/defc block-commands < rum/reactive
   [id format]
-  (when (and (util/react *show-block-commands)
-             @*angle-bracket-caret-pos)
-    (let [matched (util/react *matched-block-commands)]
-      (ui/auto-complete
-       (map first matched)
-       {:on-chosen (fn [chosen]
-                     (editor-handler/insert-command! id (get (into {} matched) chosen)
-                                                     format
-                                                     {:last-pattern commands/angle-bracket}))
-        :class     "black"}))))
+  (let [matched (util/react *matched-block-commands)]
+    (ui/auto-complete
+     (map first matched)
+     {:on-chosen (fn [chosen]
+                   (editor-handler/insert-command! id (get (into {} matched) chosen)
+                                                   format
+                                                   {:last-pattern commands/angle-bracket}))
+      :class     "black"})))
 
 (defn- in-sidebar? [el]
   (not (.contains (.getElementById js/document "left-container") el)))
@@ -83,38 +72,37 @@
 (rum/defc page-search < rum/reactive
   {:will-unmount (fn [state] (reset! editor-handler/*selected-text nil) state)}
   [id format]
-  (when (state/sub :editor/show-page-search?)
-    (let [pos (:editor/last-saved-cursor @state/state)
-          input (gdom/getElement id)]
-      (when input
-        (let [current-pos (cursor/pos input)
-              edit-content (or (state/sub [:editor/content id]) "")
-              edit-block (state/sub :editor/block)
-              sidebar? (in-sidebar? input)
-              q (or
-                 @editor-handler/*selected-text
-                 (when (state/sub :editor/show-page-search-hashtag?)
-                   (util/safe-subs edit-content pos current-pos))
-                 (when (> (count edit-content) current-pos)
-                   (util/safe-subs edit-content pos current-pos)))
-              matched-pages (when-not (string/blank? q)
-                              (editor-handler/get-matched-pages q))]
-          (ui/auto-complete
-           matched-pages
-           {:on-chosen   (page-handler/on-chosen-handler input id q pos format)
-            :on-enter    #(page-handler/page-not-exists-handler input id q current-pos)
-            :item-render (fn [page-name chosen?]
-                           [:div.py-2.preview-trigger-wrapper
-                            (block/page-preview-trigger
-                             {:children        [:div (search/highlight-exact-query page-name q)]
-                              :open?           chosen?
-                              :manual?         true
-                              :fixed-position? true
-                              :tippy-distance  24
-                              :tippy-position  (if sidebar? "left" "right")}
-                             page-name)])
-            :empty-div   [:div.text-gray-500.pl-4.pr-4 "Search for a page"]
-            :class       "black"}))))))
+  (let [pos (:editor/last-saved-cursor @state/state)
+        input (gdom/getElement id)]
+    (when input
+      (let [current-pos (cursor/pos input)
+            edit-content (or (state/sub [:editor/content id]) "")
+            edit-block (state/sub :editor/block)
+            sidebar? (in-sidebar? input)
+            q (or
+               @editor-handler/*selected-text
+               (when (state/sub :editor/show-page-search-hashtag?)
+                 (util/safe-subs edit-content pos current-pos))
+               (when (> (count edit-content) current-pos)
+                 (util/safe-subs edit-content pos current-pos)))
+            matched-pages (when-not (string/blank? q)
+                            (editor-handler/get-matched-pages q))]
+        (ui/auto-complete
+         matched-pages
+         {:on-chosen   (page-handler/on-chosen-handler input id q pos format)
+          :on-enter    #(page-handler/page-not-exists-handler input id q current-pos)
+          :item-render (fn [page-name chosen?]
+                         [:div.py-2.preview-trigger-wrapper
+                          (block/page-preview-trigger
+                           {:children        [:div (search/highlight-exact-query page-name q)]
+                            :open?           chosen?
+                            :manual?         true
+                            :fixed-position? true
+                            :tippy-distance  24
+                            :tippy-position  (if sidebar? "left" "right")}
+                           page-name)])
+          :empty-div   [:div.text-gray-500.pl-4.pr-4 "Search for a page"]
+          :class       "black"})))))
 
 (rum/defcs block-search-auto-complete < rum/reactive
   {:init (fn [state]
@@ -151,44 +139,42 @@
                    (state/clear-search-result!)
                    state)}
   [state id format]
-  (when (state/sub :editor/show-block-search?)
-    (let [pos (:editor/last-saved-cursor @state/state)
-          input (gdom/getElement id)
-          [id format] (:rum/args state)
-          current-pos (cursor/pos input)
-          edit-content (state/sub [:editor/content id])
-          edit-block (state/get-edit-block)
-          q (or
-             @editor-handler/*selected-text
-             (when (> (count edit-content) current-pos)
-               (subs edit-content pos current-pos)))]
-      (when input
-        (block-search-auto-complete edit-block input id q format)))))
+  (let [pos (:editor/last-saved-cursor @state/state)
+        input (gdom/getElement id)
+        [id format] (:rum/args state)
+        current-pos (cursor/pos input)
+        edit-content (state/sub [:editor/content id])
+        edit-block (state/get-edit-block)
+        q (or
+           @editor-handler/*selected-text
+           (when (> (count edit-content) current-pos)
+             (subs edit-content pos current-pos)))]
+    (when input
+      (block-search-auto-complete edit-block input id q format))))
 
 (rum/defc template-search < rum/reactive
   {:will-unmount (fn [state] (reset! editor-handler/*selected-text nil) state)}
   [id format]
-  (when (state/sub :editor/show-template-search?)
-    (let [pos (:editor/last-saved-cursor @state/state)
-          input (gdom/getElement id)]
-      (when input
-        (let [current-pos (cursor/pos input)
-              edit-content (state/sub [:editor/content id])
-              q (or
-                 (when (>= (count edit-content) current-pos)
-                   (subs edit-content pos current-pos))
-                 "")
-              matched-templates (editor-handler/get-matched-templates q)
-              non-exist-handler (fn [_state]
-                                  (state/set-editor-show-template-search! false))]
-          (ui/auto-complete
-           matched-templates
-           {:on-chosen   (editor-handler/template-on-chosen-handler id)
-            :on-enter    non-exist-handler
-            :empty-div   [:div.text-gray-500.pl-4.pr-4 "Search for a template"]
-            :item-render (fn [[template _block-db-id]]
-                           template)
-            :class       "black"}))))))
+  (let [pos (:editor/last-saved-cursor @state/state)
+        input (gdom/getElement id)]
+    (when input
+      (let [current-pos (cursor/pos input)
+            edit-content (state/sub [:editor/content id])
+            q (or
+               (when (>= (count edit-content) current-pos)
+                 (subs edit-content pos current-pos))
+               "")
+            matched-templates (editor-handler/get-matched-templates q)
+            non-exist-handler (fn [_state]
+                                (state/set-editor-show-template-search! false))]
+        (ui/auto-complete
+         matched-templates
+         {:on-chosen   (editor-handler/template-on-chosen-handler id)
+          :on-enter    non-exist-handler
+          :empty-div   [:div.text-gray-500.pl-4.pr-4 "Search for a template"]
+          :item-render (fn [[template _block-db-id]]
+                         template)
+          :class       "black"})))))
 
 (rum/defc mobile-bar < rum/reactive
   [parent-state parent-id]
@@ -242,7 +228,7 @@
             (let [input-value (get state ::input-value)
                   input-option (get @state/state :editor/show-input)]
               (when (seq @input-value)
-                ;; no new line input
+                  ;; no new line input
                 (util/stop e)
                 (let [[_id on-submit] (:rum/args state)
                       {:keys [pos]} @*slash-caret-pos
@@ -317,7 +303,7 @@
               {:top        (+ top offset-top)
                :max-height to-max-height
                :max-width 700
-               ;; TODO: auto responsive fixed size
+                ;; TODO: auto responsive fixed size
                :width "fit-content"
                :z-index    11}
               (when set-default-width?
@@ -423,6 +409,63 @@
        [:span {:id (str "mock-text_" idx)
                :key idx} c]))])
 
+(defn animated-modal
+  [key component set-default-width? *pos]
+  (when *pos
+    (ui/css-transition
+     {:key key
+      :class-names {:enter "origin-top-left opacity-0 transform scale-95"
+                    :enter-done "origin-top-left transition opacity-100"
+                    :enter-active "origin-top-left transition"
+                    :exit "origin-top-left transition opacity-0 transform scale-95"
+                    :exit-active "origin-top-left transition"
+                    :exit-done "origin-top-left transition opacity-0 transform scale-95"}
+      :timeout 100}
+     (fn [_]
+       (absolute-modal
+        component
+        set-default-width?
+        *pos)))))
+
+
+(rum/defc modals < rum/reactive
+  "React to atom changes, find and render the correct modal"
+  [id format]
+  (ui/transition-group
+   (cond
+     (and (util/react *show-commands)
+          (not (state/sub :editor/show-page-search?))
+          (not (state/sub :editor/show-block-search?))
+          (not (state/sub :editor/show-template-search?))
+          (not (state/sub :editor/show-input))
+          (not (state/sub :editor/show-zotero))
+          (not (state/sub :editor/show-date-picker?)))
+     (animated-modal "commands" (commands id format) true (util/react *slash-caret-pos))
+
+     (and (util/react *show-block-commands) @*angle-bracket-caret-pos)
+     (animated-modal "block-commands" (block-commands id format) true (util/react *angle-bracket-caret-pos))
+
+     (state/sub :editor/show-page-search?)
+     (animated-modal "page-search" (page-search id format) true (util/react *slash-caret-pos))
+
+     (state/sub :editor/show-block-search?)
+     (animated-modal "block-search" (block-search id format) false (util/react *slash-caret-pos))
+
+     (state/sub :editor/show-template-search?)
+     (animated-modal "template-search" (template-search id format) true (util/react *slash-caret-pos))
+
+     (state/sub :editor/show-date-picker?)
+     (animated-modal "date-picker" (datetime-comp/date-picker id format nil) false (util/react *slash-caret-pos))
+
+     (state/sub :editor/show-input)
+     (animated-modal "input" (input id
+                                    (fn [command m pos]
+                                      (editor-handler/handle-command-input command id format m pos)))
+                     true (util/react *slash-caret-pos))
+
+     (state/sub :editor/show-zotero)
+     (animated-modal "zotero-search" (zotero/zotero-search id) false (util/react *slash-caret-pos)))))
+
 (rum/defcs box < rum/reactive
   {:init (fn [state]
            (assoc state ::heading-level (:heading-level (first (:rum/args state)))))
@@ -458,52 +501,7 @@
        :class             (get-editor-heading-class content)})
 
      (mock-textarea)
-
-     ;; TODO: how to render the transitions asynchronously?
-     (transition-cp
-      (commands id format)
-      true
-      *slash-caret-pos)
-
-     (transition-cp
-      (block-commands id format)
-      true
-      *angle-bracket-caret-pos)
-
-     (transition-cp
-      (page-search id format)
-      true
-      *slash-caret-pos)
-
-     (transition-cp
-      (block-search id format)
-      false
-      *slash-caret-pos)
-
-     (transition-cp
-      (template-search id format)
-      true
-      *slash-caret-pos)
-
-     (when (state/sub :editor/show-date-picker?)
-       (transition-cp
-        (datetime-comp/date-picker id format nil)
-        false
-        *slash-caret-pos))
-
-     (when (state/sub :editor/show-input)
-       (transition-cp
-         (input id
-                (fn [command m pos]
-                  (editor-handler/handle-command-input command id format m pos)))
-         true
-         *slash-caret-pos))
-
-     (when (state/sub :editor/show-zotero)
-       (transition-cp
-        (zotero/zotero-search id)
-        false
-        *slash-caret-pos))
+     (modals id format)
 
      (when format
        (image-uploader id format))]))