diff --git a/frontend/deps.edn b/frontend/deps.edn index 394c49bf34..8febd1edd0 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -20,8 +20,8 @@ :git/url "https://github.com/funcool/beicon.git"} funcool/rumext - {:git/tag "v2.14" - :git/sha "0016623" + {:git/tag "v2.15" + :git/sha "28783a7" :git/url "https://github.com/funcool/rumext.git"} instaparse/instaparse {:mvn/version "1.5.0"} diff --git a/frontend/src/app/main.cljs b/frontend/src/app/main.cljs index d266422f6b..0a584446b9 100644 --- a/frontend/src/app/main.cljs +++ b/frontend/src/app/main.cljs @@ -23,7 +23,6 @@ [app.main.ui.confirm] [app.main.ui.css-cursors :as cur] [app.main.ui.delete-shared] - [app.main.ui.modal :refer [modal]] [app.main.ui.routes :as rt] [app.main.worker :as worker] [app.plugins :as plugins] @@ -52,14 +51,9 @@ (let [el (dom/get-element "app")] (mf/create-root el))) -(defonce modal-root - (let [el (dom/get-element "modal")] - (mf/create-root el))) - (defn init-ui [] - (mf/render! app-root (mf/element ui/app)) - (mf/render! modal-root (mf/element modal))) + (mf/render! app-root (mf/element ui/app))) (defn- initialize-profile "Event used mainly on application bootstrap; it fetches the profile @@ -132,9 +126,7 @@ ;; The hard flag will force to unmount the whole UI and will redraw every component (when hard? (mf/unmount! app-root) - (mf/unmount! modal-root) - (set! app-root (mf/create-root (dom/get-element "app"))) - (set! modal-root (mf/create-root (dom/get-element "modal")))) + (set! app-root (mf/create-root (dom/get-element "app")))) (st/emit! (ev/initialize)) (init-ui))) diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs index cad843859a..f5f495ac2e 100644 --- a/frontend/src/app/main/ui/dashboard.cljs +++ b/frontend/src/app/main/ui/dashboard.cljs @@ -29,6 +29,7 @@ [app.main.ui.dashboard.team :refer [team-settings-page* team-members-page* team-invitations-page* webhooks-page*]] [app.main.ui.dashboard.templates :refer [templates-section*]] [app.main.ui.hooks :as hooks] + [app.main.ui.modal :refer [modal-container*]] [app.main.ui.workspace.plugins] [app.plugins.register :as preg] [app.util.dom :as dom] @@ -240,6 +241,7 @@ (use-plugin-register plugin-url team-id (:id default-project)) [:& (mf/provider ctx/current-project-id) {:value project-id} + [:> modal-container*] ;; NOTE: dashboard events and other related functions assumes ;; that the team is a implicit context variable that is ;; available using react context or accessing diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs index 4cae675931..3aa83a9ac6 100644 --- a/frontend/src/app/main/ui/modal.cljs +++ b/frontend/src/app/main/ui/modal.cljs @@ -7,7 +7,8 @@ (ns app.main.ui.modal (:require-macros [app.main.style :as stl]) (:require - [app.main.data.modal :as dm] + [app.common.data.macros :as dm] + [app.main.data.modal :as modal] [app.main.store :as st] [app.util.dom :as dom] [app.util.keyboard :as k] @@ -20,13 +21,13 @@ [event allow-click-outside] (when (and (k/esc? event) (not allow-click-outside)) (dom/stop-propagation event) - (st/emit! (dm/hide)))) + (st/emit! (modal/hide)))) (defn- on-pop-state [event] (dom/prevent-default event) (dom/stop-propagation event) - (st/emit! (dm/hide)) + (st/emit! (modal/hide)) (.forward js/history)) (defn- on-click-outside @@ -41,15 +42,14 @@ (= (.-button event) 0)) (dom/stop-propagation event) (dom/prevent-default event) - (st/emit! (dm/hide))))) + (st/emit! (modal/hide))))) -(mf/defc modal-wrapper - {::mf/wrap-props false +(mf/defc modal-wrapper* + {::mf/props :obj ::mf/wrap [mf/memo]} - [props] - (let [data (unchecked-get props "data") - wrapper-ref (mf/use-ref nil) - components (mf/deref dm/components) + [{:keys [data]}] + (let [wrapper-ref (mf/use-ref nil) + components (mf/deref modal/components) allow-click-outside (:allow-click-outside data) @@ -61,31 +61,29 @@ (fn [event] (on-esc-clicked event allow-click-outside))] - (mf/use-layout-effect - (mf/deps allow-click-outside) - (fn [] - (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) - (events/listen js/document EventType.KEYDOWN handle-keydown) + (mf/with-effect [allow-click-outside] + (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) + (events/listen js/document EventType.KEYDOWN handle-keydown) - ;; Changing to js/document breaks the color picker - (events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside) + ;; Changing to js/document breaks the color picker + (events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside) - (events/listen js/document EventType.CONTEXTMENU handle-click-outside)]] - #(doseq [key keys] - (events/unlistenByKey key))))) + (events/listen js/document EventType.CONTEXTMENU handle-click-outside)]] + (fn [] + (run! events/unlistenByKey keys)))) (when-let [component (get components (:type data))] [:div {:ref wrapper-ref :class (stl/css :modal-wrapper)} (mf/element component (:props data))]))) -(def modal-ref - (l/derived ::dm/modal st/state)) +(def ^:private ref:modal + (l/derived ::modal/modal st/state)) -(mf/defc modal - {::mf/wrap-props false} +(mf/defc modal-container* + {::mf/props :obj} [] - (let [modal (mf/deref modal-ref)] - (when modal - [:& modal-wrapper {:data modal - :key (:id modal)}]))) + (when-let [modal (mf/deref ref:modal)] + (mf/portal + (mf/html [:> modal-wrapper* {:data modal :key (dm/str (:id modal))}]) + (.-body js/document)))) diff --git a/frontend/src/app/main/ui/settings.cljs b/frontend/src/app/main/ui/settings.cljs index 30f7d15ef8..d5192320d8 100644 --- a/frontend/src/app/main/ui/settings.cljs +++ b/frontend/src/app/main/ui/settings.cljs @@ -12,6 +12,7 @@ [app.main.router :as rt] [app.main.store :as st] [app.main.ui.hooks :as hooks] + [app.main.ui.modal :refer [modal-container*]] [app.main.ui.settings.access-tokens :refer [access-tokens-page]] [app.main.ui.settings.change-email] [app.main.ui.settings.delete-account] @@ -41,25 +42,29 @@ (when (nil? profile) (st/emit! (rt/nav :auth-login)))) - [:section {:class (stl/css :dashboard-layout-refactor :dashboard)} - [:& sidebar {:profile profile - :section section}] + [:* + [:> modal-container*] + [:section {:class (stl/css :dashboard-layout-refactor :dashboard)} - [:div {:class (stl/css :dashboard-content)} - [:& header] - [:section {:class (stl/css :dashboard-container)} - (case section - :settings-profile - [:& profile-page] - :settings-feedback - [:& feedback-page] + [:& sidebar {:profile profile + :section section}] - :settings-password - [:& password-page] + [:div {:class (stl/css :dashboard-content)} + [:& header] + [:section {:class (stl/css :dashboard-container)} + (case section + :settings-profile + [:& profile-page] - :settings-options - [:& options-page] + :settings-feedback + [:& feedback-page] - :settings-access-tokens - [:& access-tokens-page])]]])) + :settings-password + [:& password-page] + + :settings-options + [:& options-page] + + :settings-access-tokens + [:& access-tokens-page])]]]])) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 1578a49112..6e2562b774 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -25,6 +25,7 @@ [app.main.ui.ds.product.loader :refer [loader*]] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] + [app.main.ui.modal :refer [modal-container*]] [app.main.ui.viewer.comments :refer [comments-layer comments-sidebar*]] [app.main.ui.viewer.header :as header] [app.main.ui.viewer.inspect :as inspect] @@ -633,7 +634,9 @@ (if-let [data (mf/deref refs/viewer-data)] (let [props (obj/merge props #js {:data data :key (dm/str file-id)})] - [:> viewer-content* props]) + [:* + [:> modal-container*] + [:> viewer-content* props]]) [:> loader* {:title (tr "labels.loading") :overlay true}])) diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 244b1bb0b3..67a831f309 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -19,6 +19,7 @@ [app.main.ui.ds.product.loader :refer [loader*]] [app.main.ui.hooks :as hooks] [app.main.ui.hooks.resize :refer [use-resize-observer]] + [app.main.ui.modal :refer [modal-container*]] [app.main.ui.workspace.colorpicker] [app.main.ui.workspace.context-menu :refer [context-menu]] [app.main.ui.workspace.coordinates :as coordinates] @@ -211,6 +212,7 @@ [:& (mf/provider ctx/components-v2) {:value components-v2?} [:& (mf/provider ctx/design-tokens) {:value design-tokens?} [:& (mf/provider ctx/workspace-read-only?) {:value read-only?} + [:> modal-container*] [:section {:class (stl/css :workspace) :style {:background-color background-color :touch-action "none"}}