Reorder grid tracks

This commit is contained in:
alonso.torres 2023-09-11 09:51:39 +02:00
parent de4ef1b19d
commit 495ba6e4a4
7 changed files with 220 additions and 41 deletions

View file

@ -695,6 +695,25 @@
(update :layout-grid-cells update-cells) (update :layout-grid-cells update-cells)
(assign-cells)))) (assign-cells))))
(defn- reorder-grid-track
[prop parent from-index to-index]
(-> parent
(update prop
(fn [tracks]
(let [tr (nth tracks from-index)]
(-> tracks
(assoc from-index nil)
(d/insert-at-index (inc to-index) [tr])
(d/vec-without-nils)))))))
(defn reorder-grid-column
[parent from-index to-index]
(reorder-grid-track :layout-grid-columns parent from-index to-index))
(defn reorder-grid-row
[parent from-index to-index]
(reorder-grid-track :layout-grid-rows parent from-index to-index))
(defn get-cells (defn get-cells
([parent] ([parent]
(get-cells parent nil)) (get-cells parent nil))

View file

@ -1880,6 +1880,16 @@
} }
} }
} }
&.single-button {
display: flex;
justify-content: end;
height: 1.5rem;
.btn-wrapper {
width: initial;
}
}
} }
.no-wrap { .no-wrap {
display: flex; display: flex;
@ -2262,6 +2272,13 @@
grid-template-columns: 35px 1fr 1fr auto; grid-template-columns: 35px 1fr 1fr auto;
background-color: $color-gray-60; background-color: $color-gray-60;
padding: 3px; padding: 3px;
border-radius: 3px;
border: 1px solid transparent;
&:hover {
border: 1px solid $color-primary;
}
&:not(:first-child) { &:not(:first-child) {
margin-top: 3px; margin-top: 3px;
} }

View file

@ -38,6 +38,13 @@
(update [_ state] (update [_ state]
(update-in state [:workspace-grid-edition grid-id] dissoc :selected)))) (update-in state [:workspace-grid-edition grid-id] dissoc :selected))))
(defn clear-selection
[grid-id]
(ptk/reify ::clear-selection
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-grid-edition grid-id] dissoc :selected))))
(defn stop-grid-layout-editing (defn stop-grid-layout-editing
[grid-id] [grid-id]
(ptk/reify ::stop-grid-layout-editing (ptk/reify ::stop-grid-layout-editing

View file

@ -407,6 +407,38 @@
(ptk/data-event :layout/update ids) (ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id)))))) (dwu/commit-undo-transaction undo-id))))))
(defn reorder-layout-track
[ids type from-index to-index]
(assert (#{:row :column} type))
(ptk/reify ::reorder-layout-track
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dwc/update-shapes
ids
(fn [shape]
(case type
:row (ctl/reorder-grid-row shape from-index to-index)
:column (ctl/reorder-grid-column shape from-index to-index))))
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id))))))
(defn hover-layout-track
[ids type index hover?]
(assert (#{:row :column} type))
(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])
(not hover?)
(update-in [:workspace-grid-edition (first ids) :hover-track] (fnil disj #{}) [type index])))))
(defn change-layout-track (defn change-layout-track
[ids type index props] [ids type index props]
(assert (#{:row :column} type)) (assert (#{:row :column} type))

View file

@ -8,6 +8,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shape-layout :as dwsl]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
@ -99,7 +100,13 @@
(let [props (cond-> {:mode mode} (let [props (cond-> {:mode mode}
(not= mode :area) (not= mode :area)
(assoc :area-name nil))] (assoc :area-name nil))]
(st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) props)))))] (st/emit! (dwsl/update-grid-cell (:id shape) (:id cell) props)))))
toggle-edit-mode
(mf/use-fn
(mf/deps (:id shape))
(fn []
(st/emit! (dwge/remove-selection (:id shape)))))]
[:div.element-set [:div.element-set
[:div.element-set-title [:div.element-set-title
@ -191,4 +198,14 @@
[:div.btn-wrapper [:div.btn-wrapper
[:& set-self-alignment {:is-col? true [:& set-self-alignment {:is-col? true
:alignment justify-self :alignment justify-self
:set-alignment set-justify-self}]]]]])) :set-alignment set-justify-self}]]]
[:div.layout-row.single-button
[:div.btn-wrapper
[:div.edit-mode
[:button.tooltip.tooltip-bottom-left
{:alt "Grid edit mode"
:on-click toggle-edit-mode
:style {:padding 0}}
"Edit grid"
i/grid-layout-mode]]]]]]))

View file

@ -21,6 +21,7 @@
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -871,8 +872,68 @@
:fixed (dm/str value "px") :fixed (dm/str value "px")
value)) value))
(mf/defc grid-track-info
[{:keys [is-col? type index column set-column-value set-column-type remove-element reorder-track hover-track]}]
(let [drop-track
(mf/use-callback
(mf/deps type reorder-track index)
(fn [drop-position data]
(reorder-track type (:index data) (if (= :top drop-position) (dec index) index))))
pointer-enter
(mf/use-callback
(mf/deps type hover-track index)
(fn []
(hover-track type index true)))
pointer-leave
(mf/use-callback
(mf/deps type hover-track index)
(fn []
(hover-track type index false)))
[dprops dref]
(h/use-sortable
:data-type "penpot/layer"
:on-drop drop-track
:data {:is-col? is-col?
:index index
:column column}
:draggable? true)]
[:div.column-info
{:ref dref
:class (dom/classnames
:dnd-over-top (or (= (:over dprops) :top)
(= (:over dprops) :center))
:dnd-over-bot (= (:over dprops) :bot))
:on-pointer-enter pointer-enter
:on-pointer-leave pointer-leave}
[:div.direction-grid-icon
(if is-col?
i/layout-rows
i/layout-columns)]
[:div.grid-column-value
[:> numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:disabled (= :auto (:type column))}]]
[:div.grid-column-unit
[:& select
{:class "grid-column-unit-selector"
:default-value (:type column)
:options [{:value :flex :label "FR"}
{:value :auto :label "AUTO"}
{:value :fixed :label "PX"}
{:value :percent :label "%"}]
:on-change #(set-column-type type index %)}]]
[:button.remove-grid-column
{:on-click #(remove-element type index)}
i/minus]]))
(mf/defc grid-columns-row (mf/defc grid-columns-row
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type remove-element] :as props}] [{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type remove-element reorder-track hover-track] :as props}]
(let [column-num (count column-values) (let [column-num (count column-values)
direction (if (> column-num 1) direction (if (> column-num 1)
(if is-col? "Columns " "Rows ") (if is-col? "Columns " "Rows ")
@ -894,32 +955,19 @@
(add-new-element type ctl/default-track-value))} i/plus]] (add-new-element type ctl/default-track-value))} i/plus]]
(when expanded? (when expanded?
[:div.columns-info-wrapper [:& h/sortable-container {}
(for [[index column] (d/enumerate column-values)] [:div.columns-info-wrapper
[:div.column-info {:key (dm/str index "-" (name type) "-" column)} (for [[index column] (d/enumerate column-values)]
[:div.direction-grid-icon [:& grid-track-info {:key (dm/str index "-" (name type) "-" column)
(if is-col? :type type
i/layout-rows :is-col? is-col?
i/layout-columns)] :index index
:column column
[:div.grid-column-value :set-column-value set-column-value
[:> numeric-input* {:no-validate true :set-column-type set-column-type
:value (:value column) :remove-element remove-element
:on-change #(set-column-value type index %) :reorder-track reorder-track
:placeholder "--" :hover-track hover-track}])]])]))
:disabled (= :auto (:type column))}]]
[:div.grid-column-unit
[:& select
{:class "grid-column-unit-selector"
:default-value (:type column)
:options [{:value :flex :label "FR"}
{:value :auto :label "AUTO"}
{:value :fixed :label "PX"}
{:value :percent :label "%"}]
:on-change #(set-column-type type index %)}]]
[:button.remove-grid-column
{:on-click #(remove-element type index)}
i/minus]])])]))
;; LAYOUT COMPONENT ;; LAYOUT COMPONENT
@ -1352,7 +1400,7 @@
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]} {::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
[{:keys [ids values] :as props}] [{:keys [ids values] :as props}]
(let [;; Gap (let [;; Gap
gap-selected? (mf/use-state :none) gap-selected? (mf/use-state :none)
saved-grid-dir (:layout-grid-dir values) saved-grid-dir (:layout-grid-dir values)
set-direction set-direction
@ -1431,6 +1479,18 @@
(fn [type index] (fn [type index]
(st/emit! (dwsl/remove-layout-track ids type index)))) (st/emit! (dwsl/remove-layout-track ids type index))))
reorder-track
(mf/use-fn
(mf/deps ids)
(fn [type from-index to-index]
(st/emit! (dwsl/reorder-layout-track ids type from-index to-index))))
hover-track
(mf/use-fn
(mf/deps ids)
(fn [type index hover?]
(st/emit! (dwsl/hover-layout-track ids type index hover?))))
set-column-value set-column-value
(mf/use-fn (mf/use-fn
(mf/deps ids) (mf/deps ids)
@ -1496,7 +1556,9 @@
:add-new-element add-new-element :add-new-element add-new-element
:set-column-value set-column-value :set-column-value set-column-value
:set-column-type set-column-type :set-column-type set-column-type
:remove-element remove-element}] :remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& grid-columns-row {:is-col? false [:& grid-columns-row {:is-col? false
:expanded? @grid-rows-open? :expanded? @grid-rows-open?
@ -1505,7 +1567,9 @@
:add-new-element add-new-element :add-new-element add-new-element
:set-column-value set-column-value :set-column-value set-column-value
:set-column-type set-column-type :set-column-type set-column-type
:remove-element remove-element}] :remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& gap-section {:gap-selected? gap-selected? [:& gap-section {:gap-selected? gap-selected?
:on-change set-gap :on-change set-gap

View file

@ -531,16 +531,17 @@
(dm/str value)]])) (dm/str value)]]))
(mf/defc track (mf/defc track
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "zoom" "index" "type" "track-data" "layout-data"]))] {::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "zoom" "index" "type" "track-data" "layout-data" "hovering?"]))]
::mf/wrap-props false} ::mf/wrap-props false}
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
zoom (unchecked-get props "zoom") zoom (unchecked-get props "zoom")
type (unchecked-get props "type") type (unchecked-get props "type")
index (unchecked-get props "index") index (unchecked-get props "index")
snap-pixel? (unchecked-get props "snap-pixel?") snap-pixel? (unchecked-get props "snap-pixel?")
track-data (unchecked-get props "track-data") track-data (unchecked-get props "track-data")
layout-data (unchecked-get props "layout-data") layout-data (unchecked-get props "layout-data")
hovering? (unchecked-get props "hovering?")
track-input-ref (mf/use-ref) track-input-ref (mf/use-ref)
[layout-gap-row layout-gap-col] (ctl/gaps shape) [layout-gap-row layout-gap-col] (ctl/gaps shape)
@ -621,6 +622,15 @@
[:g {:transform (if (= type :column) [:g {:transform (if (= type :column)
(dm/str (gmt/transform-in text-p (:transform shape))) (dm/str (gmt/transform-in text-p (:transform shape)))
(dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))} (dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))}
(when hovering?
[:rect {:x (+ text-x (/ 5 zoom))
:y text-y
:width (- text-width (/ 10 zoom))
:height (- text-height (/ 5 zoom))
:rx (/ 3 zoom)
:fill "#DB00FF"
:opacity 0.2}])
[:foreignObject {:x text-x :y text-y :width text-width :height text-height} [:foreignObject {:x text-x :y text-y :width text-width :height text-height}
[:input [:input
{:ref track-input-ref {:ref track-input-ref
@ -684,6 +694,18 @@
hover-cells (:hover grid-edition) hover-cells (:hover grid-edition)
selected-cells (:selected grid-edition) selected-cells (:selected grid-edition)
hover-columns
(->> (:hover-track grid-edition)
(filter (fn [[t _]] (= t :column)))
(map (fn [[_ idx]] idx))
(into #{}))
hover-rows
(->> (:hover-track grid-edition)
(filter (fn [[t _]] (= t :row)))
(map (fn [[_ idx]] idx))
(into #{}))
children children
(mf/use-memo (mf/use-memo
(mf/deps shape modifiers) (mf/deps shape modifiers)
@ -759,7 +781,8 @@
:index idx :index idx
:layout-data layout-data :layout-data layout-data
:snap-pixel? snap-pixel? :snap-pixel? snap-pixel?
:track-data column-data}]) :track-data column-data
:hovering? (contains? hover-columns idx)}])
;; Last track resize handler ;; Last track resize handler
(when-not (empty? column-tracks) (when-not (empty? column-tracks)
@ -796,8 +819,8 @@
:snap-pixel? snap-pixel? :snap-pixel? snap-pixel?
:track-data row-data :track-data row-data
:type :row :type :row
:zoom zoom}]) :zoom zoom
:hovering? (contains? hover-rows idx)}])
(when-not (empty? row-tracks) (when-not (empty? row-tracks)
(let [last-track (last row-tracks) (let [last-track (last row-tracks)
start-p (:start-p last-track) start-p (:start-p last-track)