diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 1dd97280d..c0885d892 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -635,8 +635,8 @@ (cond (> (ctl/layout-z-index child-a) (ctl/layout-z-index child-b)) 1 (< (ctl/layout-z-index child-a) (ctl/layout-z-index child-b)) -1 - (> idx-a idx-b) 1 - (< idx-a idx-b) -1 + (< idx-a idx-b) 1 + (> idx-a idx-b) -1 :else 0)) (defn sort-layout-children-z-index diff --git a/frontend/src/app/main/data/preview.cljs b/frontend/src/app/main/data/preview.cljs new file mode 100644 index 000000000..d00daefb9 --- /dev/null +++ b/frontend/src/app/main/data/preview.cljs @@ -0,0 +1,110 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.main.data.preview + (:require + ["js-beautify" :as beautify] + [app.common.data :as d] + [app.common.data.macros :as dm] + [app.common.pages.helpers :as cph] + [app.common.types.shape-tree :as ctst] + [app.main.data.workspace.state-helpers :as wsh] + [app.main.fonts :as fonts] + [app.main.refs :as refs] + [app.util.code-gen :as cg] + [app.util.timers :as ts] + [beicon.core :as rx] + [clojure.set :as set] + [cuerdas.core :as str] + [potok.core :as ptk])) + +(def style-type "css") +(def markup-type "html") + + +(def page-template + " + + + + + + %s + +") + +(defn format-code [code type] + (cond-> code + (= type "svg") + (-> (str/replace "" "") + (str/replace "><" ">\n<")) + + (or (= type "svg") (= type "html")) + (beautify/html #js {"indent_size" 2}))) + +(defn update-preview-window + [preview code] + (when preview + (if (aget preview "load") + (.load preview code) + (ts/schedule #(update-preview-window preview code))))) + +(defn shapes->fonts + [shapes] + (->> shapes + (filter cph/text-shape?) + (map (comp fonts/get-content-fonts :content)) + (reduce set/union #{}))) + +(defn update-preview + [preview shape-id] + (ptk/reify ::update-preview + ptk/EffectEvent + (effect [_ state _] + (let [objects (wsh/lookup-page-objects state) + shape (get objects shape-id) + + all-children + (->> (cph/selected-with-children objects [shape-id]) + (ctst/sort-z-index objects) + (keep (d/getf objects))) + + fonts (shapes->fonts all-children)] + + (->> (rx/from fonts) + (rx/merge-map fonts/fetch-font-css) + (rx/reduce conj []) + (rx/map #(str/join "\n" %)) + (rx/subs + (fn [fontfaces-css] + (let [style-code + (dm/str + fontfaces-css "\n" + (-> (cg/generate-style-code objects style-type all-children) + (format-code style-type))) + + markup-code + (-> (cg/generate-markup-code objects markup-type [shape]) + (format-code markup-type))] + + (update-preview-window preview (str/format page-template style-code markup-code)))))))))) + +(defn open-preview-selected + [] + (ptk/reify ::open-preview-selected + ptk/WatchEvent + (watch [_ state _] + (let [shape-id (first (wsh/lookup-selected state)) + closed-preview (rx/subject) + preview (.open js/window "/#/frame-preview") + listener-fn #(rx/push! closed-preview true)] + (.addEventListener preview "beforeunload" listener-fn) + (->> (rx/from-atom (refs/all-children-objects shape-id) {:emit-current-value? true}) + (rx/take-until closed-preview) + (rx/debounce 1000) + (rx/map #(update-preview preview shape-id))))))) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 9dca64ce6..49879769c 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -16,6 +16,7 @@ [app.main.ui.cursors :as c] [app.main.ui.dashboard :refer [dashboard]] [app.main.ui.debug.components-preview :as cm] + [app.main.ui.frame-preview :as frame-preview] [app.main.ui.icons :as i] [app.main.ui.messages :as msgs] [app.main.ui.onboarding] @@ -135,6 +136,9 @@ :page-id page-id :layout-name layout :key file-id}]) + + :frame-preview + [:& frame-preview/frame-preview] nil)]])) (mf/defc app diff --git a/frontend/src/app/main/ui/frame_preview.cljs b/frontend/src/app/main/ui/frame_preview.cljs new file mode 100644 index 000000000..67cd88e67 --- /dev/null +++ b/frontend/src/app/main/ui/frame_preview.cljs @@ -0,0 +1,73 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.main.ui.frame-preview + (:require + [app.common.data :as d] + [rumext.v2 :as mf])) + +(mf/defc frame-preview + {::mf/wrap-props false + ::mf/wrap [mf/memo]} + [] + + (let [iframe-ref (mf/use-ref nil) + last-data* (mf/use-state nil) + + zoom-ref (mf/use-ref nil) + zoom* (mf/use-state 1) + zoom @zoom* + + + handle-load + (mf/use-callback + (fn [data] + (prn "handle-load" data) + (reset! last-data* data) + (let [iframe-dom (mf/ref-val iframe-ref)] + (when iframe-dom + (-> iframe-dom .-contentWindow .-document .open) + (-> iframe-dom .-contentWindow .-document (.write data)) + (-> iframe-dom .-contentWindow .-document .close))))) + + load-ref + (mf/use-callback + (fn [iframe-dom] + (.log js/console "load-ref" iframe-dom) + (mf/set-ref-val! iframe-ref iframe-dom) + (when (and iframe-dom @last-data*) + (-> iframe-dom .-contentWindow .-document .open) + (-> iframe-dom .-contentWindow .-document (.write @last-data*)) + (-> iframe-dom .-contentWindow .-document .close)))) + + change-zoom + (mf/use-callback + (fn [] + (let [zoom-level (d/parse-integer (.-value (mf/ref-val zoom-ref)))] + (reset! zoom* (/ zoom-level 100)))))] + + (mf/use-effect + (fn [] + (aset js/window "load" handle-load) + #(js-delete js/window "load"))) + + [:div {:style {:display "flex" :width "100%" :height "100%" :flex-direction "column" :overflow "auto" :align-items "center"}} + [:input {:id "zoom-input" + :ref zoom-ref + :type "range" :min 1 :max 200 :default-value 100 + :on-change change-zoom + :style {:max-width "500px"}}] + + [:div {:style {:width "100%" :height "100%" :overflow "auto"}} + [:iframe {:ref load-ref + :frameborder "0" + :scrolling "no" + :style {:width (str (* 100 (if (> zoom 1) + (* 1 zoom) + (/ 1 zoom))) "%") + :height "100%" + :transform-origin "left top" + :transform (str "scale(" zoom ")")}}]]])) diff --git a/frontend/src/app/main/ui/routes.cljs b/frontend/src/app/main/ui/routes.cljs index 4944fcc85..20a103ccb 100644 --- a/frontend/src/app/main/ui/routes.cljs +++ b/frontend/src/app/main/ui/routes.cljs @@ -50,6 +50,7 @@ ["/options" :settings-options] ["/access-tokens" :settings-access-tokens]] + ["/frame-preview" :frame-preview] ["/view/:file-id" {:name :viewer :conform diff --git a/frontend/src/app/main/ui/viewer/inspect/code.cljs b/frontend/src/app/main/ui/viewer/inspect/code.cljs index 91fdd23db..c26c698e8 100644 --- a/frontend/src/app/main/ui/viewer/inspect/code.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/code.cljs @@ -14,6 +14,7 @@ [app.common.types.shape-tree :as ctst] [app.config :as cfg] [app.main.data.events :as ev] + ;; [app.main.data.preview :as dp] [app.main.fonts :as fonts] [app.main.refs :as refs] [app.main.store :as st] @@ -95,6 +96,16 @@ (str/replace value old new)) value map)) +(defn gen-all-code + [style-code markup-code images-data] + (let [markup-code (cond-> markup-code + embed-images? (replace-map images-data)) + + style-code (cond-> style-code + remove-localhost? + (str/replace "http://localhost:3449" ""))] + (str/format page-template style-code markup-code))) + (mf/defc code [{:keys [shapes frame on-expand from]}] (let [style-type* (mf/use-state "css") @@ -110,16 +121,8 @@ shapes (->> shapes (map #(gsh/translate-to-frame % frame))) - route (mf/deref refs/route) - page-id (:page-id (:query-params route)) - flex-items (get-flex-elements page-id shapes from) objects (get-objects from) - ;; TODO REMOVE THIS - shapes (->> shapes - (map #(assoc % :parent (get objects (:parent-id %)))) - (map #(assoc % :flex-items flex-items))) - all-children (->> shapes (map :id) (cph/selected-with-children objects) @@ -194,15 +197,13 @@ (mf/use-callback (mf/deps style-code markup-code images-data) (fn [] - (let [markup-code (cond-> markup-code - embed-images? (replace-map images-data)) + (wapi/write-to-clipboard (gen-all-code style-code markup-code images-data)))) - style-code (cond-> style-code - remove-localhost? - (str/replace "http://localhost:3449" "")) - - data (str/format page-template style-code markup-code)] - (wapi/write-to-clipboard data))))] + ;;handle-open-review + ;;(mf/use-callback + ;; (fn [] + ;; (st/emit! (dp/open-preview-selected)))) + ] (mf/use-effect (mf/deps fonts) @@ -231,6 +232,10 @@ [:button.download-button {:on-click handle-copy-all-code} "Copy all code"]] + #_[:div.attributes-block + [:button.download-button {:on-click handle-open-review} + "Preview"]] + [:div.code-block [:div.code-row-lang [:& select {:default-value style-type diff --git a/frontend/src/app/util/code_gen/style_css.cljs b/frontend/src/app/util/code_gen/style_css.cljs index 1a71e0a49..cabbda805 100644 --- a/frontend/src/app/util/code_gen/style_css.cljs +++ b/frontend/src/app/util/code_gen/style_css.cljs @@ -21,7 +21,6 @@ ;; (def prelude " html, body { - background-color: #E8E9EA; margin: 0; min-height: 100%; min-width: 100%; diff --git a/frontend/src/app/util/code_gen/style_css_values.cljs b/frontend/src/app/util/code_gen/style_css_values.cljs index 67c35856f..148adcb50 100644 --- a/frontend/src/app/util/code_gen/style_css_values.cljs +++ b/frontend/src/app/util/code_gen/style_css_values.cljs @@ -72,7 +72,7 @@ (:layout-item-h-sizing shape) (:layout-item-v-sizing shape))] (cond - (or (and (ctl/any-layout? shape) (= sizing :auto)) + (or (and (ctl/any-layout? shape) (= sizing :auto) (not (svg-markup? shape))) (and (ctl/any-layout-immediate-child? objects shape) (= sizing :fill))) sizing diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index aa8015976..ea8e8a7e1 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -18,6 +18,7 @@ [app.common.uuid :as uuid] [app.config :as cf] [app.main.data.dashboard.shortcuts] + [app.main.data.preview :as dp] [app.main.data.viewer.shortcuts] [app.main.data.workspace :as dw] [app.main.data.workspace.changes :as dwc] @@ -212,6 +213,10 @@ [] (dump-selected' @st/state)) +(defn ^:export preview-selected + [] + (st/emit! (dp/open-preview-selected))) + (defn ^:export parent [] (let [state @st/state