diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index c36174739..b4d526141 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -1088,3 +1088,21 @@ new-shapes (into new-shapes (:shapes parent))] (assoc parent :shapes (into [] (reverse new-shapes))))) + +(defn shapes-by-row + [parent index] + (->> (:layout-grid-cells parent) + (filter (fn [[_ {:keys [row row-span]}]] + (and (>= (inc index) row) + (< (inc index) (+ row row-span))))) + (map second) + (mapcat :shapes))) + +(defn shapes-by-column + [parent index] + (->> (:layout-grid-cells parent) + (filter (fn [[_ {:keys [column column-span]}]] + (and (>= (inc index) column) + (< (inc index) (+ column column-span))))) + (map second) + (mapcat :shapes))) diff --git a/frontend/resources/styles/main/partials/sidebar-layers.scss b/frontend/resources/styles/main/partials/sidebar-layers.scss index 1ac8f0fb1..461ddaea8 100644 --- a/frontend/resources/styles/main/partials/sidebar-layers.scss +++ b/frontend/resources/styles/main/partials/sidebar-layers.scss @@ -71,7 +71,8 @@ } } - &:hover { + &:hover, + &.hover { background-color: $color-primary; svg { diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 1451f5937..7a6006585 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -432,12 +432,22 @@ (ptk/reify ::hover-layout-track ptk/UpdateEvent (update [_ state] - (cond-> state - hover? - (update-in [:workspace-grid-edition (first ids) :hover-track] (fnil conj #{}) [type index]) + (let [objects (wsh/lookup-page-objects state) + shape (get objects (first ids)) + highlighted (when hover? + (->> (if (= type :row) + (ctl/shapes-by-row shape index) + (ctl/shapes-by-column shape index)) + (set)))] + (cond-> state + hover? + (update-in [:workspace-grid-edition (first ids) :hover-track] (fnil conj #{}) [type index]) - (not hover?) - (update-in [:workspace-grid-edition (first ids) :hover-track] (fnil disj #{}) [type index]))))) + (not hover?) + (update-in [:workspace-grid-edition (first ids) :hover-track] (fnil disj #{}) [type index]) + + :always + (assoc-in [:workspace-local :highlighted] highlighted)))))) (defn change-layout-track [ids type index props] diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 2cefb77a8..867a225c0 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -126,6 +126,9 @@ [id] (l/derived #(contains? % id) selected-shapes)) +(def highlighted-shapes + (l/derived :highlighted workspace-local)) + (def export-in-progress? (l/derived :export-in-progress? export)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs index 964de3776..61bb1dbc3 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layer_item.cljs @@ -32,7 +32,7 @@ (mf/defc layer-item {::mf/wrap-props false} - [{:keys [index item selected objects sortable? filtered? depth parent-size component-child?]}] + [{:keys [index item selected objects sortable? filtered? depth parent-size component-child? highlighted]}] (let [id (:id item) name (:name item) blocked? (:blocked item) @@ -50,6 +50,7 @@ expanded? (mf/deref expanded-iref) selected? (contains? selected id) + highlighted? (contains? highlighted id) container? (or (cph/frame-shape? item) (cph/group-shape? item)) absolute? (ctl/layout-absolute? item) @@ -341,6 +342,7 @@ [:div.element-list-body {:class (stl/css-case* :selected selected? + :hover highlighted? :icon-layer (= (:type item) :icon)) :on-click select-shape :on-pointer-enter on-pointer-enter @@ -395,6 +397,7 @@ [:& layer-item {:item item :selected selected + :highlighted highlighted :index index :objects objects :key (dm/str id) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 430dad276..fee063fab 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -43,6 +43,8 @@ [{:keys [objects filtered? parent-size] :as props}] (let [selected (mf/deref refs/selected-shapes) selected (hooks/use-equal-memo selected) + highlighted (mf/deref refs/highlighted-shapes) + highlighted (hooks/use-equal-memo highlighted) root (get objects uuid/zero) new-css-system (mf/use-ctx ctx/new-css-system)] [:ul @@ -54,6 +56,7 @@ [:& frame-wrapper {:item obj :selected selected + :highlighted highlighted :index index :objects objects :key id @@ -64,6 +67,7 @@ [:& layer-item {:item obj :selected selected + :highlighted highlighted :index index :objects objects :key id 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 48c06ce1b..fdb6d6274 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 @@ -1542,7 +1542,7 @@ [:div.layout-row [:div.jusfiy-content-grid.row-title "Content"] - [:div.btn-wrapper.align-grid + [:div.btn-wrapper.align-grid-content [:& justify-grid-row {:is-col? true :justify-items grid-justify-content-column :set-justify set-content-grid}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs index 333782b2c..d630eea1d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs @@ -27,7 +27,8 @@ ;; --- Page Item -(mf/defc page-item [{:keys [page index deletable? selected? editing?] :as props}] +(mf/defc page-item + [{:keys [page index deletable? selected? editing? hovering?] :as props}] (let [input-ref (mf/use-ref) id (:id page) new-css-system (mf/use-ctx ctx/new-css-system) @@ -135,6 +136,7 @@ (css :selected) selected?) (dom/classnames :element-list-body true + :hover hovering? :selected selected?)) :data-test (dm/str "page-" id) :tab-index "0" diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss index e2595c96f..8ba8c7d6d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss @@ -176,7 +176,8 @@ } } } - &:hover { + &:hover, + &.hover { .element-list-body { color: var(--layer-row-foreground-color-hover); background-color: var(--layer-row-background-color-hover); 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 6c4aef79a..6a1326c18 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 @@ -25,6 +25,7 @@ [app.main.ui.css-cursors :as cur] [app.main.ui.formats :as fmt] [app.main.ui.hooks :as hooks] + [app.main.ui.icons :as i] [app.main.ui.workspace.viewport.viewport-ref :as uwvv] [app.util.dom :as dom] [app.util.keyboard :as kbd] @@ -443,10 +444,10 @@ start-p (cond-> start-p (and (= type :column) (= index 0)) - (gpt/subtract (hv width)) + (gpt/subtract (hv (/ width 2))) (and (= type :row) (= index 0)) - (gpt/subtract (vv height)) + (gpt/subtract (vv (/ height 2))) (and (= type :column) (not= index 0) (not last?)) (-> (gpt/subtract (hv (/ layout-gap-col 2))) @@ -605,6 +606,24 @@ (when esc? (dom/blur! (dom/get-target event)))))) + handle-pointer-enter + (mf/use-callback + (mf/deps (:id shape) type index) + (fn [] + (st/emit! (dwsl/hover-layout-track [(:id shape)] type index true)))) + + handle-pointer-leave + (mf/use-callback + (mf/deps (:id shape) type index) + (fn [] + (st/emit! (dwsl/hover-layout-track [(:id shape)] type index false)))) + + handle-remove-track + (mf/use-callback + (mf/deps (:id shape) type index) + (fn [] + (st/emit! (dwsl/remove-layout-track [(:id shape)] type index)))) + track-list-prop (if (= type :column) :column-tracks :row-tracks) [text-x text-y text-width text-height] (if (= type :column) @@ -619,7 +638,9 @@ (dom/set-value! (mf/ref-val track-input-ref) (format-size track-data)))) [:g.track - [:g {:transform (if (= type :column) + [:g {:on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :transform (if (= type :column) (dm/str (gmt/transform-in text-p (:transform shape))) (dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))} @@ -629,17 +650,22 @@ :width (- text-width (/ 10 zoom)) :height (- text-height (/ 5 zoom)) :rx (/ 3 zoom) - :fill "#DB00FF" + :fill "var(--color-distance)" :opacity 0.2}]) [:foreignObject {:x text-x :y text-y :width text-width :height text-height} - [:input - {:ref track-input-ref - :class (css :grid-editor-label) - :type "text" - :default-value (format-size track-data) - :data-default-value (format-size track-data) - :on-key-down handle-keydown-track-input - :on-blur handle-blur-track-input}]]] + [:div {:class (css :grid-editor-wrapper)} + [:input + {:ref track-input-ref + :style {} + :class (css :grid-editor-label) + :type "text" + :default-value (format-size track-data) + :data-default-value (format-size track-data) + :on-key-down handle-keydown-track-input + :on-blur handle-blur-track-input}] + (when hovering? + [:button {:class (css :grid-editor-button) + :on-click handle-remove-track} i/trash])]]] [:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))} [:& track-marker @@ -755,6 +781,15 @@ [:g.grid-editor {:pointer-events (when view-only "none") :on-pointer-down handle-pointer-down} + [:g.cells + (for [cell (ctl/get-cells shape {:sort? true})] + [:& grid-cell {:key (dm/str "cell-" (:id cell)) + :shape base-shape + :layout-data layout-data + :cell cell + :zoom zoom + :hover? (contains? hover-cells (:id cell)) + :selected? (= selected-cells (:id cell))}])] (when-not view-only [:* [:& grid-editor-frame {:zoom zoom @@ -846,14 +881,4 @@ :type :row :track-before (last row-tracks) :snap-pixel? snap-pixel? - :zoom zoom}]]))]) - - [:g.cells - (for [cell (ctl/get-cells shape {:sort? true})] - [:& grid-cell {:key (dm/str "cell-" (:id cell)) - :shape base-shape - :layout-data layout-data - :cell cell - :zoom zoom - :hover? (contains? hover-cells (:id cell)) - :selected? (= selected-cells (:id cell))}])]])) + :zoom zoom}]]))])])) diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss index 97269139b..a8043abb3 100644 --- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss +++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.scss @@ -11,19 +11,27 @@ } } -.grid-editor-label { - position: absolute; - background: none; +.grid-editor-wrapper { width: 100%; - height: 100%; - text-align: center; - font-family: worksans; + height: 80%; + display: flex; + justify-content: center; + align-items: center; +} + +.grid-editor-label { + background: none; + border-bottom: calc(1px / var(--zoom)) solid transparent; + border: 0; color: var(--color-distance); + font-family: worksans; + font-size: calc(12px / var(--zoom)); font-weight: 600; margin: 0; + max-width: calc(80px / var(--zoom)); padding: 0; - border: 0; - font-size: calc(12px / var(--zoom)); + padding: 4px; + text-align: center; &:focus { outline: none; @@ -31,6 +39,24 @@ } } +.grid-editor-button { + background: none; + border: none; + cursor: pointer; + margin: 0; + padding: 0; + position: absolute; + right: calc(10px / var(--zoom)); + width: calc(20px / var(--zoom)); + height: calc(20px / var(--zoom)); + + svg { + width: calc(16px / var(--zoom)); + height: auto; + fill: var(--color-distance); + } +} + .grid-frame { fill: #f6f6f6; stroke: var(--color-distance);