diff --git a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc index aba5d9f87f..08caa33eb7 100644 --- a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc +++ b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc @@ -21,7 +21,7 @@ {:type :percent :value 25} {:type :fixed :value 100} ;;{:type :auto} - ;;{:type :fr :value 1} + ;;{:type :flex :value 1} ] :layout-grid-rows @@ -29,7 +29,7 @@ {:type :percent :value 50} ;;{:type :fixed :value 100} ;;{:type :auto} - ;;{:type :fr :value 1} + ;;{:type :flex :value 1} ]) num-rows (count (:layout-grid-rows parent)) @@ -71,12 +71,7 @@ (defn calc-layout-data [parent children transformed-parent-bounds] - (let [ - - ;; TODO: Delete when there is UI - [parent children] (set-sample-data parent children) - - height (gpo/height-points transformed-parent-bounds) + (let [height (gpo/height-points transformed-parent-bounds) width (gpo/width-points transformed-parent-bounds) ;; Initialize tracks diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index 29fe313edb..62a7e784db 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -303,7 +303,7 @@ (:shapes parent)) children-layout - (when layout? + (when flex-layout? (->> (:shapes parent) (remove #(ctl/layout-absolute? objects %))))] @@ -312,7 +312,7 @@ (set-children-modifiers children-modifiers objects bounds parent transformed-parent-bounds ignore-constraints) flex-layout? - (set-flex-layout-modifiers children-layout objects bounds parent transformed-parent-bounds)) + (set-flex-layout-modifiers children-layout objects bounds parent transformed-parent-bounds) grid-layout? (set-grid-layout-modifiers objects bounds parent transformed-parent-bounds)) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 776271f6ae..17639f9a18 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -51,8 +51,8 @@ (s/def ::layout-wrap-type #{:wrap :nowrap :no-wrap}) ;;TODO remove no-wrap after script (s/def ::layout-padding-type #{:simple :multiple}) -(s/def :grid/type #{:fr :auto :fixed}) -(s/def :grid/value (s/nilable ::us/string)) +(s/def :grid/type #{:percent :flex :auto :fixed}) +(s/def :grid/value (s/nilable ::us/safe-number)) (s/def ::grid-definition (s/keys :opt-un [:grid/type :grid/value])) (s/def ::layout-grid-rows (s/coll-of ::grid-definition :kind vector?)) diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index 356b99f5d6..3997cd3b30 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -164,7 +164,7 @@ :else ;; If the base is a layout we should check if the z-index property is set (let [[z-index-a z-index-b] - (if (ctl/layout? objects base) + (if (ctl/any-layout? objects base) [(ctl/layout-z-index objects (dm/get-in objects [base :shapes index-a])) (ctl/layout-z-index objects (dm/get-in objects [base :shapes index-b]))] [0 0])] diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index 2f7991f9be..41b636aa8b 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -1705,7 +1705,9 @@ color: $color-gray-20; &.active, &:hover { - color: $color-primary; + &.dir { + color: $color-primary; + } svg { fill: $color-primary; } @@ -2160,6 +2162,9 @@ .columns-info { flex-grow: 1; font-size: 12px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .expand-icon, .add-column { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 04dcb5a965..2278c0c9d8 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -660,7 +660,7 @@ (pcb/with-objects objects) ;; Remove layout-item properties when moving a shape outside a layout - (cond-> (not (ctl/layout? objects parent-id)) + (cond-> (not (ctl/any-layout? objects parent-id)) (pcb/update-shapes ordered-indexes ctl/remove-layout-item-data)) ;; Move the shapes diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index bbdaf10451..de927b33f2 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -144,7 +144,7 @@ (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) - (cond-> (ctl/layout? frame) + (cond-> (ctl/any-layout? frame) (pcb/update-shapes (:shapes frame) ctl/remove-layout-item-data)) (pcb/change-parent parent-id children idx-in-parent) (pcb/remove-objects [(:id frame)])))) diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index f3317e214e..612cd16464 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -183,6 +183,7 @@ ;; Never call this directly but through the data-event `:layout/update` ;; Otherwise a lot of cycle dependencies could be generated +(declare check-grid-cells-update) (defn- update-layout-positions [ids] (ptk/reify ::update-layout-positions @@ -190,10 +191,16 @@ (watch [_ state _] (let [objects (wsh/lookup-page-objects state) ids (->> ids (filter #(contains? objects %)))] - (if (d/not-empty? ids) - (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] - (rx/of (dwm/apply-modifiers {:modifiers modif-tree}))) - (rx/empty)))))) + + (rx/concat + ;; Update grids if necesary + (rx/of (check-grid-cells-update + (->> (concat ids (map #(cph/get-parent-id objects %) ids)) + (filter #(ctl/grid-layout? objects %))))) + (if (d/not-empty? ids) + (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] + (rx/of (dwm/apply-modifiers {:modifiers modif-tree}))) + (rx/empty))))))) (defn initialize [] @@ -352,6 +359,93 @@ (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) +(defn update-grid-cells + [parent objects] + + (let [children (cph/get-immediate-children objects (:id parent)) + layout-grid-rows (:layout-grid-rows parent) + layout-grid-columns (:layout-grid-columns parent) + num-rows (count layout-grid-columns) + num-columns (count layout-grid-columns) + + layout-grid-cells + (for [[row-idx row] (d/enumerate layout-grid-rows) + [col-idx col] (d/enumerate layout-grid-columns)] + + (let [shape (nth children (+ (* row-idx num-columns) col-idx) nil) + cell-data {:id (uuid/next) + :row (inc row-idx) + :column (inc col-idx) + :row-span 1 + :col-span 1 + :shapes (when shape [(:id shape)])}] + [(:id cell-data) cell-data]))] + (assoc parent :layout-grid-cells layout-grid-cells))) + +(defn check-grid-cells-update + [ids] + (ptk/reify ::check-grid-cells-update + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + undo-id (js/Symbol)] + (rx/of (dwc/update-shapes + ids + (fn [shape] + (-> shape + (update-grid-cells objects))))))))) + +(defn add-layout-column + [ids property value] + (ptk/reify ::add-layout-column + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + undo-id (js/Symbol)] + (rx/of (dwu/start-undo-transaction undo-id) + (dwc/update-shapes + ids + (fn [shape] + (-> shape + (update property (fnil conj []) value) + (update-grid-cells objects)))) + (ptk/data-event :layout/update ids) + (dwu/commit-undo-transaction undo-id)))))) + +(defn remove-layout-column + [ids property index] + (ptk/reify ::remove-layout-column + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + undo-id (js/Symbol)] + (rx/of (dwu/start-undo-transaction undo-id) + (dwc/update-shapes + ids + (fn [shape] + (-> shape + (update property d/remove-at-index index) + (update-grid-cells objects)))) + (ptk/data-event :layout/update ids) + (dwu/commit-undo-transaction undo-id)))))) + +(defn change-layout-column + [ids property index props] + (ptk/reify ::change-layout-column + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + undo-id (js/Symbol)] + (rx/of (dwu/start-undo-transaction undo-id) + (dwc/update-shapes + ids + (fn [shape] + (-> shape + (update-in [property index] merge props) + (update-grid-cells objects)))) + (ptk/data-event :layout/update ids) + (dwu/commit-undo-transaction undo-id)))))) + (defn fix-child-sizing [objects parent-changes shape] diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index 353ee2f6bd..f123efb69f 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -18,6 +18,7 @@ [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctst] [app.common.types.shape.interactions :as ctsi] + [app.common.types.shape.layout :as ctl] [app.common.uuid :as uuid] [app.main.data.comments :as dc] [app.main.data.workspace.changes :as dch] @@ -130,7 +131,7 @@ (when (d/not-empty? to-move-shapes) (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) - (cond-> (not (ctl/layout? objects frame-id)) + (cond-> (not (ctl/any-layout? objects frame-id)) (pcb/update-shapes ordered-indexes ctl/remove-layout-item-data)) (pcb/change-parent frame-id to-move-shapes 0)))] diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 77357fe7b8..656d2e9fbe 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -739,7 +739,7 @@ (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) ;; Remove layout-item properties when moving a shape outside a layout - (cond-> (not (ctl/layout? objects frame-id)) + (cond-> (not (ctl/any-layout? objects frame-id)) (pcb/update-shapes (map :id moving-shapes) ctl/remove-layout-item-data)) (pcb/change-parent frame-id moving-shapes drop-index) (pcb/remove-objects empty-parents))] diff --git a/frontend/src/app/main/ui/shapes/frame.cljs b/frontend/src/app/main/ui/shapes/frame.cljs index f667cd2f4b..11be6ba001 100644 --- a/frontend/src/app/main/ui/shapes/frame.cljs +++ b/frontend/src/app/main/ui/shapes/frame.cljs @@ -129,7 +129,7 @@ (let [shape (unchecked-get props "shape") childs (unchecked-get props "childs") childs (cond-> childs - (ctl/layout? shape) + (ctl/any-layout? shape) (cph/sort-layout-children-z-index))] [:> frame-container props [:g.frame-children {:opacity (:opacity shape)} diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index 1643228d99..a25b8e75c6 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -5,114 +5,135 @@ ;; Copyright (c) KALEIDOS INC (ns app.main.ui.workspace.sidebar.options.menus.layout-container - (:require [app.common.data :as d] - [app.common.data.macros :as dm] - [app.main.data.workspace :as udw] - [app.main.data.workspace.shape-layout :as dwsl] - [app.main.store :as st] - [app.main.ui.components.numeric-input :refer [numeric-input]] - [app.main.ui.components.select :refer [select]] - [app.main.ui.icons :as i] - [app.util.dom :as dom] - [cuerdas.core :as str] - [rumext.v2 :as mf])) + (:require + [app.common.data :as d] + [app.common.data.macros :as dm] + [app.main.data.workspace :as udw] + [app.main.data.workspace.shape-layout :as dwsl] + [app.main.store :as st] + [app.main.ui.components.numeric-input :refer [numeric-input]] + [app.main.ui.components.select :refer [select]] + [app.main.ui.icons :as i] + [app.util.dom :as dom] + [cuerdas.core :as str] + [rumext.v2 :as mf])) (def layout-container-flex-attrs [:layout ;; :flex, :grid in the future :layout-flex-dir ;; :row, :row-reverse, :column, :column-reverse :layout-gap-type ;; :simple, :multiple :layout-gap ;; {:row-gap number , :column-gap number} + :layout-align-items ;; :start :end :center :stretch :layout-justify-content ;; :start :center :end :space-between :space-around :space-evenly :layout-align-content ;; :start :center :end :space-between :space-around :space-evenly :stretch (by default) :layout-wrap-type ;; :wrap, :nowrap :layout-padding-type ;; :simple, :multiple :layout-padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative + + :layout-grid-dir ;; :row :column + :layout-justify-items + :layout-grid-columns + :layout-grid-rows ]) (defn get-layout-flex-icon [type val is-col?] (case type - :align-items (if is-col? - (case val - :start i/align-items-column-start - :end i/align-items-column-end - :center i/align-items-column-center - :stretch i/align-items-column-strech - :baseline i/align-items-column-baseline) - (case val - :start i/align-items-row-start - :end i/align-items-row-end - :center i/align-items-row-center - :stretch i/align-items-row-strech - :baseline i/align-items-row-baseline)) - :justify-content (if is-col? - (case val - :start i/justify-content-column-start - :end i/justify-content-column-end - :center i/justify-content-column-center - :space-around i/justify-content-column-around - :space-evenly i/justify-content-column-evenly - :space-between i/justify-content-column-between) - (case val - :start i/justify-content-row-start - :end i/justify-content-row-end - :center i/justify-content-row-center - :space-around i/justify-content-row-around - :space-evenly i/justify-content-row-evenly - :space-between i/justify-content-row-between)) + :align-items + (if is-col? + (case val + :start i/align-items-column-start + :end i/align-items-column-end + :center i/align-items-column-center + :stretch i/align-items-column-strech + :baseline i/align-items-column-baseline) + (case val + :start i/align-items-row-start + :end i/align-items-row-end + :center i/align-items-row-center + :stretch i/align-items-row-strech + :baseline i/align-items-row-baseline)) + + :justify-content + (if is-col? + (case val + :start i/justify-content-column-start + :end i/justify-content-column-end + :center i/justify-content-column-center + :space-around i/justify-content-column-around + :space-evenly i/justify-content-column-evenly + :space-between i/justify-content-column-between) + (case val + :start i/justify-content-row-start + :end i/justify-content-row-end + :center i/justify-content-row-center + :space-around i/justify-content-row-around + :space-evenly i/justify-content-row-evenly + :space-between i/justify-content-row-between)) - :align-content (if is-col? - (case val - :start i/align-content-column-start - :end i/align-content-column-end - :center i/align-content-column-center - :space-around i/align-content-column-around - :space-evenly i/align-content-column-evenly - :space-between i/align-content-column-between - :stretch nil) + :align-content + (if is-col? + (case val + :start i/align-content-column-start + :end i/align-content-column-end + :center i/align-content-column-center + :space-around i/align-content-column-around + :space-evenly i/align-content-column-evenly + :space-between i/align-content-column-between + :stretch nil) - (case val - :start i/align-content-row-start - :end i/align-content-row-end - :center i/align-content-row-center - :space-around i/align-content-row-around - :space-evenly i/align-content-row-evenly - :space-between i/align-content-row-between - :stretch nil)) + (case val + :start i/align-content-row-start + :end i/align-content-row-end + :center i/align-content-row-center + :space-around i/align-content-row-around + :space-evenly i/align-content-row-evenly + :space-between i/align-content-row-between + :stretch nil)) - :align-self (if is-col? - (case val - :auto i/minus - :start i/align-self-row-left - :end i/align-self-row-right - :center i/align-self-row-center - :stretch i/align-self-row-strech - :baseline i/align-self-row-baseline) - (case val - :auto i/minus - :start i/align-self-column-top - :end i/align-self-column-bottom - :center i/align-self-column-center - :stretch i/align-self-column-strech - :baseline i/align-self-column-baseline)))) + (case val + :start i/align-content-row-start + :end i/align-content-row-end + :center i/align-content-row-center + :space-around i/align-content-row-around + :space-between i/align-content-row-between + :stretch nil) + + :align-self + (if is-col? + (case val + :auto i/minus + :start i/align-self-row-left + :end i/align-self-row-right + :center i/align-self-row-center + :stretch i/align-self-row-strech + :baseline i/align-self-row-baseline) + (case val + :auto i/minus + :start i/align-self-column-top + :end i/align-self-column-bottom + :center i/align-self-column-center + :stretch i/align-self-column-strech + :baseline i/align-self-column-baseline)))) (defn get-layout-grid-icon [type val is-col?] (case type - :justify-content (if is-col? - (case val - :start i/grid-justify-content-column-start - :end i/grid-justify-content-column-end - :center i/grid-justify-content-column-center - :space-around i/grid-justify-content-column-around - :space-between i/grid-justify-content-column-between) - (case val - :start i/grid-justify-content-row-start - :end i/grid-justify-content-row-end - :center i/grid-justify-content-row-center - :space-around i/grid-justify-content-row-around - :space-between i/grid-justify-content-row-between)))) + :justify-items + (if is-col? + (case val + :start i/grid-justify-content-column-start + :end i/grid-justify-content-column-end + :center i/grid-justify-content-column-center + :space-around i/grid-justify-content-column-around + :space-between i/grid-justify-content-column-between) + (case val + :start i/grid-justify-content-row-start + :end i/grid-justify-content-row-end + :center i/grid-justify-content-row-center + :space-around i/grid-justify-content-row-around + :space-between i/grid-justify-content-row-between)))) (mf/defc direction-btn [{:keys [dir saved-dir set-direction icon?] :as props}] @@ -333,9 +354,7 @@ (mf/defc align-grid-row [{:keys [is-col? align-items set-align] :as props}] - (let [type (if is-col? - :column - :row)] + (let [type (if is-col? :column :row)] [:div.align-items-style (for [align [:start :center :end :stretch :baseline]] [:button.align-start.tooltip @@ -343,15 +362,13 @@ :tooltip-bottom-left (not= align :start) :tooltip-bottom (= align :start)) :alt (dm/str "Align items " (d/name align)) - :on-click #(set-align align % type) + :on-click #(set-align align type) :key (dm/str "align-items" (d/name align))} (get-layout-flex-icon :align-items align is-col?)])])) (mf/defc justify-grid-row [{:keys [is-col? justify-items set-justify] :as props}] - (let [type (if is-col? - :column - :row)] + (let [type (if is-col? :column :row)] [:div.justify-content-style (for [align [:start :center :end :space-around :space-between]] [:button.align-start.tooltip @@ -359,44 +376,43 @@ :tooltip-bottom-left (not= align :start) :tooltip-bottom (= align :start)) :alt (dm/str "Justify content " (d/name align)) - :on-click #(set-justify align % type) + :on-click #(set-justify align type) :key (dm/str "justify-content" (d/name align))} - (get-layout-grid-icon :justify-content align is-col?)])])) + (get-layout-grid-icon :justify-items align is-col?)])])) -(defn manage-values [value] - (let [quantity (:value value) - unit (:unit value)] - (case unit - :auto (d/name unit) - :perc (str/join [quantity "%"]) - (str/join [quantity (d/name unit)])))) +(defn manage-values [{:keys [value type]}] + (case type + :auto "auto" + :percent (dm/str value "%") + :flex (dm/str value "fr") + :fixed (dm/str value "px") + value)) (mf/defc grid-columns-row - [{:keys [is-col? expanded? column-values toggle add-new-element set-column-value handle-focus handle-blur on-unit-change remove-column] :as props}] + [{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type remove-element] :as props}] (let [column-num (count column-values) - direction (if (< 1 column-num) - (if is-col? - "Columns " - "Rows ") - (if is-col? - "Column " - "Row ")) + direction (if (> column-num 1) + (if is-col? "Columns " "Rows ") + (if is-col? "Column " "Row ")) + column-vals (str/join ", " (map manage-values column-values)) - generated-name (str direction column-num " (" column-vals ")")] + generated-name (dm/str direction (if (= column-num 0) " - empty" (dm/str column-num " (" column-vals ")"))) + type (if is-col? :column :row)] + [:div.grid-columns [:div.grid-columns-header [:button.expand-icon - {:on-click toggle} - i/actions] + {:on-click toggle} i/actions] + + [:div.columns-info {:title generated-name + :on-click toggle} generated-name] + [:button.add-column {:on-click #(do + (when-not expanded? (toggle)) + (add-new-element type {:type :fixed :value 100}))} i/plus]] - [:div.columns-info - generated-name] - [:button.add-column - {:on-click add-new-element} - i/plus]] (when expanded? [:div.columns-info-wrapper - (for [column column-values] + (for [[index column] (d/enumerate column-values)] [:div.column-info [:div.direction-grid-icon (if is-col? @@ -406,21 +422,19 @@ [:div.grid-column-value [:> numeric-input {:no-validate true :value (:value column) - :on-change set-column-value - :on-focus handle-focus - :on-blur handle-blur + :on-change #(set-column-value type index %) :placeholder "--"}]] [:div.grid-column-unit [:& select {:class "grid-column-unit-selector" - :default-value (:unit column) - :options [{:value :fr :label "fr"} + :default-value (:type column) + :options [{:value :flex :label "fr"} {:value :auto :label "auto"} - {:value :px :label "px"} - {:value :perc :label "%"}] - :on-change on-unit-change}]] + {:value :fixed :label "px"} + {:value :percent :label "%"}] + :on-change #(set-column-type type index %)}]] [:button.remove-grid-column - {:on-change remove-column} + {:on-click #(remove-element type index)} i/minus]])])])) (mf/defc layout-container-menu @@ -520,50 +534,74 @@ (st/emit! (dwsl/update-layout ids {:layout-grid-dir dir})))) ;; Align grid - align-items-row (:layout-grid-align-row values) - align-items-column (:layout-grid-align-column values) - set-align-grid (fn [value type] - (if (= type :row) - (st/emit! (dwsl/update-layout ids {:layout-grid-align-row value})) - (st/emit! (dwsl/update-layout ids {:layout-grid-align-column value})))) + align-items-row (:layout-align-items values) + align-items-column (:layout-justify-items values) + + set-align-grid + (fn [value type] + (if (= type :row) + (st/emit! (dwsl/update-layout ids {:layout-align-items value})) + (st/emit! (dwsl/update-layout ids {:layout-justify-items value})))) ;; Justify grid - grid-justify-content-row (:layout-grid-justify-row values) - grid-justify-content-column (:layout-grid-justify-column values) - set-justify-grid (fn [value type] - (if (= type :row) - (st/emit! (dwsl/update-layout ids {:layout-grid-justify-row value})) - (st/emit! (dwsl/update-layout ids {:layout-grid-justify-column value})))) + grid-justify-content-row (:layout-align-content values) + grid-justify-content-column (:layout-justify-content values) + + set-justify-grid + (mf/use-callback + (mf/deps ids) + (fn [value type] + (if (= type :row) + (st/emit! (dwsl/update-layout ids {:layout-align-content value})) + (st/emit! (dwsl/update-layout ids {:layout-justify-content value}))))) ;;Grid columns - - column-grid-values (:layout-grid-column-values values) + column-grid-values (:layout-grid-columns values) grid-columns-open? (mf/use-state false) toggle-columns-info (mf/use-callback (fn [_] (swap! grid-columns-open? not))) - - ; Grid rows / columns - rows-grid-values (:layout-grid-row-values values) + rows-grid-values (:layout-grid-rows values) grid-rows-open? (mf/use-state false) - toggle-rows-info (mf/use-callback - (fn [_] - (swap! grid-rows-open? not))) + toggle-rows-info + (mf/use-callback + (fn [_] + (swap! grid-rows-open? not))) - ;; TODO -> fix this, is doing nothing - add-new-element (fn [value type] - (if (= type :row) - (st/emit! (dwsl/update-layout ids {:layout-grid-row-values value})) - (st/emit! (dwsl/update-layout ids {:layout-grid-column-values value})))) + add-new-element + (mf/use-callback + (mf/deps ids) + (fn [type value] + (if (= type :row) + (st/emit! (dwsl/add-layout-column ids :layout-grid-rows value)) + (st/emit! (dwsl/add-layout-column ids :layout-grid-columns value))))) - set-column-value (fn[] ) - handle-focus (fn []) - handle-blur (fn []) - set-colum-unit (fn []) - remove-column (fn [])] + remove-element + (mf/use-callback + (mf/deps ids) + (fn [type index] + (if (= type :row) + (st/emit! (dwsl/remove-layout-column ids :layout-grid-rows index)) + (st/emit! (dwsl/remove-layout-column ids :layout-grid-columns index))))) + + set-column-value + (mf/use-callback + (mf/deps ids) + (fn [type index value] + (if (= type :row) + (st/emit! (dwsl/change-layout-column ids :layout-grid-rows index {:value value})) + (st/emit! (dwsl/change-layout-column ids :layout-grid-columns index {:value value}))))) + + set-column-type + (mf/use-callback + (mf/deps ids) + (fn [type index col-type] + (if (= type :row) + (st/emit! (dwsl/change-layout-column ids :layout-grid-rows index {:type col-type})) + (st/emit! (dwsl/change-layout-column ids :layout-grid-columns index {:type col-type})))))] [:div.element-set [:div.element-set-title @@ -585,6 +623,7 @@ (when (:layout values) (when (not= :multiple layout-type) (if (= :flex layout-type) + ;; FLEX [:div.element-set-content.layout-menu [:div.layout-row [:div.direction-wrap.row-title "Direction"] @@ -634,6 +673,7 @@ :on-change-style change-padding-type :on-change on-padding-change}]] + ;; GRID [:div.element-set-content.layout-menu [:div.layout-row [:div.direction-wrap.row-title "Direction"] @@ -667,34 +707,30 @@ [:div.jusfiy-content-grid.row-title "Justify"] [:div.btn-wrapper.align-grid [:& justify-grid-row {:is-col? true - :align-items grid-justify-content-column + :justify-items grid-justify-content-column :set-justify set-justify-grid}] [:& justify-grid-row {:is-col? false - :align-items grid-justify-content-row + :justify-items grid-justify-content-row :set-justify set-justify-grid}]]] [:& grid-columns-row {:is-col? true :expanded? @grid-columns-open? :toggle toggle-columns-info - :column-values [{:value 1 :unit :fr} {:value 1 :unit :fr}];; column-grid-values - :add-new-column add-new-element + :column-values column-grid-values + :add-new-element add-new-element :set-column-value set-column-value - :handle-focus handle-focus - :handle-blur handle-blur - :set-colum-unit set-colum-unit - :remove-column remove-column}] + :set-column-type set-column-type + :remove-element remove-element}] [:& grid-columns-row {:is-col? false :expanded? @grid-rows-open? :toggle toggle-rows-info - :column-values [{:value "--" :unit :auto} {:value "--" :unit :auto}] ;; column-grid-values - :add-new-column add-new-element + :column-values rows-grid-values + :add-new-element add-new-element :set-column-value set-column-value - :handle-focus handle-focus - :handle-blur handle-blur - :set-colum-unit set-colum-unit - :remove-column remove-column}] - + :set-column-type set-column-type + :remove-element remove-element}] + [:& gap-section {:is-col? is-col? :wrap-type wrap-type :gap-selected? gap-selected? diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs index 576d21be23..78b938ca72 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs @@ -33,8 +33,7 @@ layout-container-values (select-keys shape layout-container-flex-attrs) is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) - is-layout-child? (mf/deref is-layout-child-ref) - + is-flex-layout-child? (mf/deref is-flex-layout-child-ref) is-layout-child-absolute? (ctl/layout-absolute? shape)] [:* [:& measures-menu {:ids ids diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs index 832e8bb1fd..2f33bd52af 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs @@ -38,7 +38,7 @@ is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) is-flex-layout-child? (mf/deref is-flex-layout-child-ref) - is-flex-layout-container? (ctl/flex-layout? shape)] + is-flex-layout-container? (ctl/flex-layout? shape) is-layout-child-absolute? (ctl/layout-absolute? shape)] [:* [:& measures-menu {:ids [(:id shape)] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs index 838e107943..f7afd62771 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs @@ -51,28 +51,31 @@ #_(if (= align-self value) (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil})) (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value})))) - column-start (mf/use-state 1) - column-end (mf/use-state 1) - row-start (mf/use-state 1) - row-end (mf/use-state 1) - on-change (fn [side orientation value] - (if (= orientation :column) - (case side - :all ((reset! column-start value) - (reset! column-end value)) - :start (reset! column-start value) - :end (reset! column-end value)) - (case side - :all ((reset! row-start value) - (reset! row-end value)) - :start (reset! row-start value) - :end (reset! row-end value)))) + column-start column + column-end (inc column) + row-start row + row-end (inc row) + + on-change + (fn [side orientation value] + (if (= orientation :column) + (case side + :all ((reset! column-start value) + (reset! column-end value)) + :start (reset! column-start value) + :end (reset! column-end value)) + (case side + :all ((reset! row-start value) + (reset! row-end value)) + :start (reset! row-start value) + :end (reset! row-end value)))) area-name (mf/use-state "header") ;; TODO this should come from shape on-area-name-change (fn [value] (reset! area-name value)) on-key-press (fn [event])] + [:div.element-set [:div.element-set-title [:span "Grid Cell"]] @@ -100,7 +103,7 @@ {:placeholder "--" :on-click #(dom/select-target %) :on-change (partial on-change :all :column) ;; TODO cambiar este on-change y el value - :value @column-start}]]] + :value column-start}]]] [:div.grid-rows-auto [:spam.icon i/layout-columns] [:div.input-wrapper @@ -108,7 +111,7 @@ {:placeholder "--" :on-click #(dom/select-target %) :on-change (partial on-change :all :row) ;; TODO cambiar este on-change y el value - :value @row-start}]]]]) + :value row-start}]]]]) (when (= :area @position-mode) [:div.input-wrapper [:input.input-text @@ -130,26 +133,26 @@ [:> numeric-input {:placeholder "--" :on-click #(dom/select-target %) - :on-change (partial on-change :start :column) ;; TODO cambiar este on-change y el value - :value @column-start}] + :on-change (partial on-change :start :column) + :value column-start}] [:> numeric-input {:placeholder "--" :on-click #(dom/select-target %) - :on-change (partial on-change :end :column) ;; TODO cambiar este on-change y el value - :value @column-end}]]] + :on-change (partial on-change :end :column) + :value column-end}]]] [:div.grid-rows-auto [:spam.icon i/layout-columns] [:div.input-wrapper [:> numeric-input {:placeholder "--" :on-click #(dom/select-target %) - :on-change (partial on-change :start :row) ;; TODO cambiar este on-change y el value - :value @row-start}] + :on-change (partial on-change :start :row) + :value row-start}] [:> numeric-input {:placeholder "--" :on-click #(dom/select-target %) - :on-change (partial on-change :end :row) ;; TODO cambiar este on-change y el value - :value @row-end}]]]])] + :on-change (partial on-change :end :row) + :value row-end}]]]])] [:div.layout-row [:div.row-title "Align"] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/image.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/image.cljs index d911e489e9..7d93273044 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/image.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/image.cljs @@ -33,7 +33,7 @@ layout-container-values (select-keys shape layout-container-flex-attrs) is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) - is-flex-layout-child? (mf/deref is-flex-layout-child-ref)] + is-flex-layout-child? (mf/deref is-flex-layout-child-ref) is-layout-child-absolute? (ctl/layout-absolute? shape)] [:* [:& measures-menu {:ids ids diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs index b60ce48724..5a7b1bd953 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs @@ -33,7 +33,7 @@ layout-container-values (select-keys shape layout-container-flex-attrs) is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) - is-flex-layout-child? (mf/deref is-flex-layout-child-ref)] + is-flex-layout-child? (mf/deref is-flex-layout-child-ref) is-layout-child-absolute? (ctl/layout-absolute? shape)] [:* [:& measures-menu {:ids ids diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs index 6eb3fcd67e..401ef70ef4 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs @@ -33,7 +33,7 @@ layout-item-values (select-keys shape layout-item-attrs) layout-container-values (select-keys shape layout-container-flex-attrs) is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) - is-flex-layout-child? (mf/deref is-flex-layout-child-ref)] + is-flex-layout-child? (mf/deref is-flex-layout-child-ref) is-layout-child-absolute? (ctl/layout-absolute? shape)] [:* [:& measures-menu {:ids ids @@ -49,7 +49,7 @@ :is-layout-child? true :shape shape}]) - (when (or (not is-layout-child?) is-layout-child-absolute?) + (when (or (not is-flex-layout-child?) is-layout-child-absolute?) [:& constraints-menu {:ids ids :values constraint-values}]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs index 570e13e249..0560de5494 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs @@ -107,7 +107,7 @@ layout-container-values (select-keys shape layout-container-flex-attrs) is-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-flex-layout-child? ids)) - is-flex-layout-child? (mf/deref is-flex-layout-child-ref)] + is-flex-layout-child? (mf/deref is-flex-layout-child-ref) is-layout-child-absolute? (ctl/layout-absolute? shape)] (when (contains? svg-elements tag) diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs index 48ba043431..9910f63002 100644 --- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.viewport.grid-layout-editor (:require - [app.main.data.workspace.grid-layout.editor :as dwge] [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.point :as gpt] @@ -15,9 +14,12 @@ [app.common.geom.shapes.points :as gpo] [app.common.pages.helpers :as cph] [app.common.types.shape.layout :as ctl] + [app.main.data.workspace.grid-layout.editor :as dwge] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.cursors :as cur] [app.main.ui.icons :as i] + [app.util.dom :as dom] [cuerdas.core :as str] [rumext.v2 :as mf])) @@ -172,8 +174,74 @@ :stroke-dasharray (when-not (or hover? selected?) (str/join " " (map #(/ % zoom) [0 8]) )) :stroke-linecap "round" - :stroke-width (/ 2 zoom)}}]) - ) + :stroke-width (/ 2 zoom)}}])) + +(mf/defc resize-handler + {::mf/wrap-props false} + [props] + + (let [start-p (unchecked-get props "start-p") + type (unchecked-get props "type") + bounds (unchecked-get props "bounds") + zoom (unchecked-get props "zoom") + + width (gpo/width-points bounds) + height (gpo/height-points bounds) + + dragging-ref (mf/use-ref false) + start-ref (mf/use-ref nil) + + on-pointer-down + (mf/use-callback + (fn [event] + (dom/capture-pointer event) + (mf/set-ref-val! dragging-ref true) + (mf/set-ref-val! start-ref (dom/get-client-position event)))) + + on-lost-pointer-capture + (mf/use-callback + (fn [event] + (dom/release-pointer event) + (mf/set-ref-val! dragging-ref false) + (mf/set-ref-val! start-ref nil))) + + on-mouse-move + (mf/use-callback + (fn [event] + (when (mf/ref-val dragging-ref) + (let [start (mf/ref-val start-ref) + pos (dom/get-client-position event) + delta (-> (gpt/to-vec start pos) + (get (if (= type :column) :x :y)))] + + ;; TODO Implement resize + #_(prn ">Delta" delta))))) + + + [x y width height] + (if (= type :column) + [(- (:x start-p) (/ 8 zoom)) + (- (:y start-p) (/ 40 zoom)) + (/ 16 zoom) + (+ height (/ 40 zoom))] + + [(- (:x start-p) (/ 40 zoom)) + (- (:y start-p) (/ 8 zoom)) + (+ width (/ 40 zoom)) + (/ 16 zoom)])] + + [:rect.resize-handler + {:x x + :y y + :height height + :width width + :on-pointer-down on-pointer-down + :on-lost-pointer-capture on-lost-pointer-capture + :on-mouse-move on-mouse-move + :style {:fill "transparent" + :cursor (if (= type :column) + (cur/resize-ew 0) + (cur/resize-ns 0))}}])) (mf/defc editor {::mf/wrap-props false} @@ -201,9 +269,7 @@ origin (gpo/origin bounds) {:keys [row-tracks column-tracks shape-cells] :as layout-data} - (gsg/calc-layout-data shape children bounds) - - [shape children] (set-sample-data shape children)] + (gsg/calc-layout-data shape children bounds)] (mf/use-effect (fn [] @@ -241,12 +307,11 @@ [:& track-marker {:center marker-p :value (dm/str (inc idx)) :zoom zoom}] - [:rect.resize-handler - {:x (- (:x start-p) (/ 8 zoom)) - :y (:y start-p) - :height height - :width (/ 16 zoom) - :style {:fill "transparent"}}]])) + + [:& resize-handler {:type :column + :start-p start-p + :zoom zoom + :bounds bounds}]])) (for [[idx row-data] (d/enumerate row-tracks)] (let [start-p (-> origin (gpt/add (vv (:distance row-data)))) @@ -257,9 +322,7 @@ :value (dm/str (inc idx)) :zoom zoom}]] - [:rect.resize-handler - {:x (:x start-p) - :y (- (:y start-p) (/ 8 zoom)) - :height (/ 16 zoom) - :width width - :style {:fill "transparent"}}]]))])) + [:& resize-handler {:type :row + :start-p start-p + :zoom zoom + :bounds bounds}]]))]))