mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 23:06:10 +02:00
Merge pull request #2996 from penpot/alotor-grid-layout
Partial merge of the grid layout infrastructure
This commit is contained in:
commit
c8360b1994
59 changed files with 2388 additions and 322 deletions
|
@ -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
|
||||
|
@ -714,7 +714,7 @@
|
|||
;; Fix the sizing when moving a shape
|
||||
(pcb/update-shapes parents
|
||||
(fn [parent]
|
||||
(if (ctl/layout? parent)
|
||||
(if (ctl/flex-layout? parent)
|
||||
(cond-> parent
|
||||
(ctl/change-h-sizing? (:id parent) objects (:shapes parent))
|
||||
(assoc :layout-item-h-sizing :fix)
|
||||
|
|
|
@ -82,8 +82,9 @@
|
|||
focus (:workspace-focus-selected state)
|
||||
|
||||
fid (ctst/top-nested-frame objects initial)
|
||||
layout? (ctl/layout? objects fid)
|
||||
drop-index (when layout? (gsl/get-drop-index fid objects initial))
|
||||
|
||||
flex-layout? (ctl/flex-layout? objects fid)
|
||||
drop-index (when flex-layout? (gsl/get-drop-index fid objects initial))
|
||||
|
||||
shape (get-in state [:workspace-drawing :object])
|
||||
shape (-> shape
|
||||
|
|
|
@ -47,12 +47,12 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (gpt/point (get-in content [0 :params] nil))
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
layout? (ctl/layout? objects frame-id)
|
||||
drop-index (when layout? (gsl/get-drop-index frame-id objects position))]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (gpt/point (get-in content [0 :params] nil))
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
flex-layout? (ctl/flex-layout? objects frame-id)
|
||||
drop-index (when flex-layout? (gsl/get-drop-index frame-id objects position))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id)
|
||||
(cond-> (some? drop-index)
|
||||
|
|
44
frontend/src/app/main/data/workspace/grid_layout/editor.cljs
Normal file
44
frontend/src/app/main/data/workspace/grid_layout/editor.cljs
Normal file
|
@ -0,0 +1,44 @@
|
|||
;; 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.workspace.grid-layout.editor
|
||||
(:require
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(defn hover-grid-cell
|
||||
[grid-id row column add-to-set]
|
||||
(ptk/reify ::hover-grid-cell
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in
|
||||
state
|
||||
[:workspace-grid-edition grid-id :hover]
|
||||
(fn [hover-set]
|
||||
(let [hover-set (or hover-set #{})]
|
||||
(if add-to-set
|
||||
(conj hover-set [row column])
|
||||
(disj hover-set [row column]))))))))
|
||||
|
||||
(defn select-grid-cell
|
||||
[grid-id row column]
|
||||
(ptk/reify ::hover-grid-cell
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-grid-edition grid-id :selected] [row column]))))
|
||||
|
||||
(defn remove-selection
|
||||
[grid-id]
|
||||
(ptk/reify ::hover-grid-cell
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:workspace-grid-edition grid-id] dissoc :selected))))
|
||||
|
||||
(defn stop-grid-layout-editing
|
||||
[grid-id]
|
||||
(ptk/reify ::stop-grid-layout-editing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-grid-edition dissoc grid-id))))
|
|
@ -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)]))))
|
||||
|
|
|
@ -179,8 +179,8 @@
|
|||
(let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
|
||||
child-set (set (get-in objects [target-frame-id :shapes]))
|
||||
|
||||
target-frame (get objects target-frame-id)
|
||||
target-layout? (ctl/layout? target-frame)
|
||||
target-frame (get objects target-frame-id)
|
||||
target-flex-layout? (ctl/flex-layout? target-frame)
|
||||
|
||||
children-ids (concat (:shapes target-frame) selected)
|
||||
|
||||
|
@ -201,7 +201,7 @@
|
|||
(fn [modif-tree [original-frame shapes]]
|
||||
(let [shapes (->> shapes (d/removev #(= target-frame-id %)))
|
||||
shapes (cond->> shapes
|
||||
(and target-layout? (= original-frame target-frame-id))
|
||||
(and target-flex-layout? (= original-frame target-frame-id))
|
||||
;; When movining inside a layout frame remove the shapes that are not immediate children
|
||||
(filterv #(contains? child-set %)))
|
||||
children-ids (->> (dm/get-in objects [original-frame :shapes])
|
||||
|
@ -219,7 +219,7 @@
|
|||
(cond-> v-sizing?
|
||||
(update-in [original-frame :modifiers] ctm/change-property :layout-item-v-sizing :fix)))
|
||||
|
||||
(and target-layout? (= original-frame target-frame-id))
|
||||
(and target-flex-layout? (= original-frame target-frame-id))
|
||||
(update-in [target-frame-id :modifiers] ctm/add-children shapes drop-index))))]
|
||||
|
||||
(as-> modif-tree $
|
||||
|
|
|
@ -240,12 +240,12 @@
|
|||
(ptk/reify ::setup-frame-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (gpt/point (get-in content [0 :params] nil))
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
layout? (ctl/layout? objects frame-id)
|
||||
drop-index (when layout? (gsl/get-drop-index frame-id objects position))]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (gpt/point (get-in content [0 :params] nil))
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
flex-layout? (ctl/flex-layout? objects frame-id)
|
||||
drop-index (when flex-layout? (gsl/get-drop-index frame-id objects position))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id)
|
||||
(cond-> (some? drop-index)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; 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/.
|
||||
;;
|
||||
|
@ -53,14 +53,29 @@
|
|||
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}})
|
||||
|
||||
(def initial-grid-layout ;; TODO
|
||||
{:layout :grid})
|
||||
{:layout :grid
|
||||
:layout-grid-dir :row
|
||||
:layout-gap-type :multiple
|
||||
:layout-gap {:row-gap 0 :column-gap 0}
|
||||
:layout-align-items :start
|
||||
:layout-align-content :stretch
|
||||
:layout-justify-items :start
|
||||
:layout-justify-content :start
|
||||
:layout-padding-type :simple
|
||||
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:layout-grid-rows []
|
||||
:layout-grid-columns []})
|
||||
|
||||
(defn get-layout-initializer
|
||||
[type from-frame?]
|
||||
(let [initial-layout-data (if (= type :flex) initial-flex-layout initial-grid-layout)]
|
||||
(let [initial-layout-data
|
||||
(case type
|
||||
:flex initial-flex-layout
|
||||
:grid initial-grid-layout)]
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(merge initial-layout-data)
|
||||
(cond-> (= type :grid) ctl/assign-cells)
|
||||
;; If the original shape is not a frame we set clip content and show-viewer to false
|
||||
(cond-> (not from-frame?)
|
||||
(assoc :show-content true :hide-in-viewer true))))))
|
||||
|
@ -140,6 +155,13 @@
|
|||
:layout-align-items :center
|
||||
:layout-gap layout-gap)))))
|
||||
|
||||
(defn shapes->grid-params
|
||||
"Given the shapes calculate its flex parameters (horizontal vs vertical, gaps, etc)"
|
||||
([objects shapes]
|
||||
(shapes->flex-params objects shapes nil))
|
||||
([_objects _shapes _parent]
|
||||
{}))
|
||||
|
||||
(defn create-layout-from-id
|
||||
[ids type from-frame?]
|
||||
(ptk/reify ::create-layout-from-id
|
||||
|
@ -149,8 +171,10 @@
|
|||
children-ids (into [] (mapcat #(get-in objects [% :shapes])) ids)
|
||||
children-shapes (map (d/getf objects) children-ids)
|
||||
parent (get objects (first ids))
|
||||
flex-params (when (d/not-empty? children-shapes)
|
||||
(shapes->flex-params objects children-shapes parent))
|
||||
layout-params (when (d/not-empty? children-shapes)
|
||||
(case type
|
||||
:flex (shapes->flex-params objects children-shapes parent)
|
||||
:grid (shapes->grid-params objects children-shapes parent)))
|
||||
undo-id (js/Symbol)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwc/update-shapes ids (get-layout-initializer type from-frame?))
|
||||
|
@ -161,7 +185,7 @@
|
|||
(not from-frame?)
|
||||
(-> (assoc :layout-item-h-sizing :auto
|
||||
:layout-item-v-sizing :auto)
|
||||
(merge flex-params)))))
|
||||
(merge layout-params)))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwc/update-shapes children-ids #(dissoc % :constraints-h :constraints-v))
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
@ -288,7 +312,7 @@
|
|||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn create-layout
|
||||
[]
|
||||
[type]
|
||||
(ptk/reify ::create-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -300,15 +324,12 @@
|
|||
is-frame? (= :frame (:type (first selected-shapes)))
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(if (and single? is-frame?)
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(create-layout-from-id [(first selected)] :flex true)
|
||||
(dwu/commit-undo-transaction undo-id))
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(create-layout-from-selection :flex)
|
||||
(dwu/commit-undo-transaction undo-id)))))))
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(if (and single? is-frame?)
|
||||
(create-layout-from-id [(first selected)] type true)
|
||||
(create-layout-from-selection type))
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn toggle-layout-flex
|
||||
[]
|
||||
|
@ -320,12 +341,12 @@
|
|||
selected (wsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected)
|
||||
single? (= (count selected-shapes) 1)
|
||||
has-flex-layout? (and single? (ctl/layout? objects (:id (first selected-shapes))))]
|
||||
has-flex-layout? (and single? (ctl/flex-layout? objects (:id (first selected-shapes))))]
|
||||
|
||||
(when (not= 0 (count selected))
|
||||
(if has-flex-layout?
|
||||
(rx/of (remove-layout selected))
|
||||
(rx/of (create-layout))))))))
|
||||
(rx/of (create-layout :flex))))))))
|
||||
|
||||
(defn update-layout
|
||||
[ids changes]
|
||||
|
@ -338,6 +359,101 @@
|
|||
(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 (:layout-grid-cells parent)
|
||||
|
||||
allocated-shapes
|
||||
(into #{} (mapcat :shapes) (:layout-grid-cells parent))
|
||||
|
||||
no-cell-shapes
|
||||
(->> children (:shapes parent) (remove allocated-shapes))
|
||||
|
||||
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 (into {} 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-track
|
||||
[ids type value]
|
||||
(assert (#{:row :column} type))
|
||||
(ptk/reify ::add-layout-column
|
||||
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/add-grid-row shape value)
|
||||
:column (ctl/add-grid-column shape value))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn remove-layout-track
|
||||
[ids type index]
|
||||
(assert (#{:row :column} type))
|
||||
|
||||
(ptk/reify ::remove-layout-column
|
||||
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/remove-grid-row shape index)
|
||||
:column (ctl/remove-grid-column shape index))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn change-layout-track
|
||||
[ids type index props]
|
||||
(assert (#{:row :column} type))
|
||||
(ptk/reify ::change-layout-column
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)
|
||||
property (case :row :layout-grid-rows
|
||||
:column :layout-grid-columns)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwc/update-shapes
|
||||
ids
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(update-in [property index] merge props))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn fix-child-sizing
|
||||
[objects parent-changes shape]
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
selected)
|
||||
|
||||
index (:index (meta attrs))
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(cond-> (some? index)
|
||||
|
@ -102,7 +103,10 @@
|
|||
(cond-> (nil? index)
|
||||
(pcb/add-object shape))
|
||||
(cond-> (some? (:parent-id attrs))
|
||||
(pcb/change-parent (:parent-id attrs) [shape])))
|
||||
(pcb/change-parent (:parent-id attrs) [shape]))
|
||||
(cond-> (ctl/grid-layout? objects (:parent-id shape))
|
||||
(pcb/update-shapes [(:parent-id shape)] ctl/assign-cells))
|
||||
)
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(rx/concat
|
||||
|
@ -131,9 +135,11 @@
|
|||
(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)))]
|
||||
(pcb/change-parent frame-id to-move-shapes 0)
|
||||
(cond-> (ctl/grid-layout? objects frame-id)
|
||||
(pcb/update-shapes [frame-id] ctl/assign-cells))))]
|
||||
|
||||
(if (some? changes)
|
||||
(rx/of (dch/commit-changes changes))
|
||||
|
@ -194,10 +200,6 @@
|
|||
[file page objects ids it components-v2]
|
||||
(let [lookup (d/getf objects)
|
||||
|
||||
layout-ids (->> ids
|
||||
(mapcat (partial cph/get-parent-ids objects))
|
||||
(filter (partial ctl/layout? objects)))
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
;; When the shape to delete is the mask of a masked group,
|
||||
|
@ -319,7 +321,6 @@
|
|||
(dc/detach-comment-thread ids)
|
||||
(ptk/data-event :layout/update all-parents)
|
||||
(dch/commit-changes changes)
|
||||
(ptk/data-event :layout/update layout-ids)
|
||||
(dwu/commit-undo-transaction undo-id))))
|
||||
|
||||
(defn create-and-add-shape
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.geom.shapes.flex-layout :as gslf]
|
||||
[app.common.geom.shapes.grid-layout :as gslg]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
|
@ -440,7 +441,7 @@
|
|||
exclude-frames-siblings
|
||||
(into exclude-frames
|
||||
(comp (mapcat (partial cph/get-siblings-ids objects))
|
||||
(filter (partial ctl/layout-immediate-child-id? objects)))
|
||||
(filter (partial ctl/any-layout-immediate-child-id? objects)))
|
||||
selected)
|
||||
|
||||
position (->> ms/mouse-position
|
||||
|
@ -469,11 +470,14 @@
|
|||
|
||||
(rx/map
|
||||
(fn [[move-vector mod?]]
|
||||
(let [position (gpt/add from-position move-vector)
|
||||
(let [position (gpt/add from-position move-vector)
|
||||
exclude-frames (if mod? exclude-frames exclude-frames-siblings)
|
||||
target-frame (ctst/top-nested-frame objects position exclude-frames)
|
||||
layout? (ctl/layout? objects target-frame)
|
||||
drop-index (when layout? (gsl/get-drop-index target-frame objects position))]
|
||||
target-frame (ctst/top-nested-frame objects position exclude-frames)
|
||||
flex-layout? (ctl/flex-layout? objects target-frame)
|
||||
grid-layout? (ctl/grid-layout? objects target-frame)
|
||||
drop-index (cond
|
||||
flex-layout? (gslf/get-drop-index target-frame objects position)
|
||||
grid-layout? (gslg/get-drop-index target-frame objects position))]
|
||||
[move-vector target-frame drop-index])))
|
||||
|
||||
(rx/take-until stopper))]
|
||||
|
@ -529,7 +533,8 @@
|
|||
get-new-position
|
||||
(fn [parent-id position]
|
||||
(let [parent (get objects parent-id)]
|
||||
(when (ctl/layout? parent)
|
||||
(cond
|
||||
(ctl/flex-layout? parent)
|
||||
(if (or
|
||||
(and (ctl/reverse? parent)
|
||||
(or (= direction :left)
|
||||
|
@ -538,7 +543,12 @@
|
|||
(or (= direction :right)
|
||||
(= direction :down))))
|
||||
(dec position)
|
||||
(+ position 2)))))
|
||||
(+ position 2))
|
||||
|
||||
;; TODO: GRID
|
||||
(ctl/grid-layout? parent)
|
||||
nil
|
||||
)))
|
||||
|
||||
add-children-position
|
||||
(fn [[parent-id children]]
|
||||
|
@ -643,7 +653,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
selected-shapes (->> selected (map (d/getf objects)))]
|
||||
(if (every? #(and (ctl/layout-immediate-child? objects %)
|
||||
(if (every? #(and (ctl/any-layout-immediate-child? objects %)
|
||||
(not (ctl/layout-absolute? %)))
|
||||
selected-shapes)
|
||||
(rx/of (reorder-selected-layout-child direction))
|
||||
|
@ -732,7 +742,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))]
|
||||
|
|
|
@ -405,7 +405,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(into []
|
||||
(comp (map (d/getf objects))
|
||||
(filter (partial ctl/layout-immediate-child? objects)))
|
||||
(filter (partial ctl/flex-layout-immediate-child? objects)))
|
||||
ids)))
|
||||
st/state =))
|
||||
|
||||
|
@ -478,22 +478,22 @@
|
|||
(defn workspace-text-modifier-by-id [id]
|
||||
(l/derived #(get % id) workspace-text-modifier =))
|
||||
|
||||
(defn is-layout-child?
|
||||
(defn is-flex-layout-child?
|
||||
[ids]
|
||||
(l/derived
|
||||
(fn [objects]
|
||||
(->> ids
|
||||
(map (d/getf objects))
|
||||
(some (partial ctl/layout-immediate-child? objects))))
|
||||
(some (partial ctl/flex-layout-immediate-child? objects))))
|
||||
workspace-page-objects))
|
||||
|
||||
(defn all-layout-child?
|
||||
(defn all-flex-layout-child?
|
||||
[ids]
|
||||
(l/derived
|
||||
(fn [objects]
|
||||
(->> ids
|
||||
(map (d/getf objects))
|
||||
(every? (partial ctl/layout-immediate-child? objects))))
|
||||
(every? (partial ctl/flex-layout-immediate-child? objects))))
|
||||
workspace-page-objects))
|
||||
|
||||
(defn get-flex-child-viewer
|
||||
|
@ -503,7 +503,7 @@
|
|||
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
||||
(into []
|
||||
(comp (map (d/getf objects))
|
||||
(filter (partial ctl/layout-immediate-child? objects)))
|
||||
(filter (partial ctl/flex-layout-immediate-child? objects)))
|
||||
ids)))
|
||||
st/state =))
|
||||
|
||||
|
@ -522,3 +522,12 @@
|
|||
|
||||
(def colorpicker
|
||||
(l/derived :colorpicker st/state))
|
||||
|
||||
|
||||
(def workspace-grid-edition
|
||||
(l/derived :workspace-grid-edition st/state))
|
||||
|
||||
(defn workspace-grid-edition-id
|
||||
[id]
|
||||
(l/derived #(get % id) workspace-grid-edition))
|
||||
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
i/component-copy)
|
||||
(case (:type shape)
|
||||
:frame (cond
|
||||
(and (ctl/layout? shape) (ctl/col? shape))
|
||||
(and (ctl/flex-layout? shape) (ctl/col? shape))
|
||||
i/layout-columns
|
||||
|
||||
(and (ctl/layout? shape) (ctl/row? shape))
|
||||
(and (ctl/flex-layout? shape) (ctl/row? shape))
|
||||
i/layout-rows
|
||||
|
||||
;; TODO: GRID ICON
|
||||
|
||||
:else
|
||||
i/artboard)
|
||||
:image i/image
|
||||
|
|
|
@ -113,6 +113,17 @@
|
|||
(def full-screen (icon-xref :full-screen))
|
||||
(def full-screen-off (icon-xref :full-screen-off))
|
||||
(def grid (icon-xref :grid))
|
||||
(def grid-justify-content-column-around (icon-xref :grid-justify-content-column-around))
|
||||
(def grid-justify-content-column-between (icon-xref :grid-justify-content-column-between))
|
||||
(def grid-justify-content-column-center (icon-xref :grid-justify-content-column-center))
|
||||
(def grid-justify-content-column-end (icon-xref :grid-justify-content-column-end))
|
||||
(def grid-justify-content-column-start (icon-xref :grid-justify-content-column-start))
|
||||
(def grid-justify-content-row-around (icon-xref :grid-justify-content-row-around))
|
||||
(def grid-justify-content-row-between (icon-xref :grid-justify-content-row-between))
|
||||
(def grid-justify-content-row-center (icon-xref :grid-justify-content-row-center))
|
||||
(def grid-justify-content-row-end (icon-xref :grid-justify-content-row-end))
|
||||
(def grid-justify-content-row-start (icon-xref :grid-justify-content-row-start))
|
||||
(def grid-layout-mode (icon-xref :grid-layout-mode))
|
||||
(def grid-snap (icon-xref :grid-snap))
|
||||
(def go-next (icon-xref :go-next))
|
||||
(def go-prev (icon-xref :go-prev))
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
[app.main.ui.workspace.sidebar.options.shapes.bool :as bool]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.circle :as circle]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.frame :as frame]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.grid-cell :as grid-cell]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.group :as group]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.image :as image]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.multiple :as multiple]
|
||||
|
@ -67,9 +68,16 @@
|
|||
(let [drawing (mf/deref refs/workspace-drawing)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
grid-edition (mf/deref refs/workspace-grid-edition)
|
||||
selected-shapes (into [] (keep (d/getf objects)) selected)
|
||||
first-selected-shape (first selected-shapes)
|
||||
shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape))
|
||||
|
||||
[grid-id {[row-selected col-selected] :selected}]
|
||||
(d/seek (fn [[_ {:keys [selected]}]] (some? selected)) grid-edition)
|
||||
|
||||
grid-cell-selected? (and (some? grid-id) (some? row-selected) (some? col-selected))
|
||||
|
||||
on-change-tab
|
||||
(fn [options-mode]
|
||||
(st/emit! (udw/set-options-mode options-mode)
|
||||
|
@ -87,6 +95,10 @@
|
|||
[:& align-options]
|
||||
[:& bool-options]
|
||||
(cond
|
||||
grid-cell-selected? [:& grid-cell/options {:shape (get objects grid-id)
|
||||
:row row-selected
|
||||
:column col-selected}]
|
||||
|
||||
(d/not-empty? drawing) [:& shape-options {:shape (:object drawing)
|
||||
:page-id page-id
|
||||
:file-id file-id
|
||||
|
@ -138,4 +150,3 @@
|
|||
:file-id file-id
|
||||
:page-id page-id
|
||||
:section section}]))
|
||||
|
||||
|
|
|
@ -5,97 +5,138 @@
|
|||
;; 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.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.refs :as refs]
|
||||
[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))
|
||||
|
||||
: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)
|
||||
: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))
|
||||
|
||||
(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-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-self (if is-col?
|
||||
(case val
|
||||
: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
|
||||
: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-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-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-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] :as props}]
|
||||
[{:keys [dir saved-dir set-direction icon?] :as props}]
|
||||
(let [handle-on-click
|
||||
(mf/use-callback
|
||||
(mf/deps set-direction dir)
|
||||
|
@ -112,7 +153,9 @@
|
|||
:key (dm/str "direction-" dir)
|
||||
:alt (str/replace (str/capital (d/name dir)) "-" " ")
|
||||
:on-click handle-on-click}
|
||||
i/auto-direction]))
|
||||
(if icon?
|
||||
i/auto-direction
|
||||
(str/replace (str/capital (d/name dir)) "-" " "))]))
|
||||
|
||||
(mf/defc wrap-row
|
||||
[{:keys [wrap-type set-wrap] :as props}]
|
||||
|
@ -299,6 +342,111 @@
|
|||
:value (:row-gap gap-value)
|
||||
:disabled (and (= :nowrap wrap-type) (not is-col?))}]]]])
|
||||
|
||||
(mf/defc grid-edit-mode
|
||||
[{:keys [id] :as props}]
|
||||
(let [edition (mf/deref refs/selected-edition)
|
||||
active? (= id edition)
|
||||
|
||||
toggle-edit-mode
|
||||
(mf/use-callback
|
||||
(mf/deps id edition)
|
||||
(fn []
|
||||
(if-not active?
|
||||
(st/emit! (udw/start-edition-mode id))
|
||||
(st/emit! :interrupt))))]
|
||||
|
||||
[:button.tooltip.tooltip-bottom-left
|
||||
{:class (dom/classnames :active active?)
|
||||
:alt "Grid edit mode"
|
||||
:on-click #(toggle-edit-mode)
|
||||
:style {:padding 0}}
|
||||
i/grid-layout-mode]))
|
||||
|
||||
(mf/defc align-grid-row
|
||||
[{:keys [is-col? align-items set-align] :as props}]
|
||||
(let [type (if is-col? :column :row)]
|
||||
[:div.align-items-style
|
||||
(for [align [:start :center :end :stretch :baseline]]
|
||||
[:button.align-start.tooltip
|
||||
{:class (dom/classnames :active (= align-items align)
|
||||
:tooltip-bottom-left (not= align :start)
|
||||
:tooltip-bottom (= align :start))
|
||||
:alt (dm/str "Align items " (d/name align))
|
||||
: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)]
|
||||
[:div.justify-content-style
|
||||
(for [align [:start :center :end :space-around :space-between]]
|
||||
[:button.align-start.tooltip
|
||||
{:class (dom/classnames :active (= justify-items align)
|
||||
:tooltip-bottom-left (not= align :start)
|
||||
:tooltip-bottom (= align :start))
|
||||
:alt (dm/str "Justify content " (d/name align))
|
||||
:on-click #(set-justify align type)
|
||||
:key (dm/str "justify-content" (d/name align))}
|
||||
(get-layout-grid-icon :justify-items align is-col?)])]))
|
||||
|
||||
(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 set-column-type remove-element] :as props}]
|
||||
(let [column-num (count column-values)
|
||||
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 (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]
|
||||
|
||||
[: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]]
|
||||
|
||||
(when expanded?
|
||||
[:div.columns-info-wrapper
|
||||
(for [[index column] (d/enumerate column-values)]
|
||||
[:div.column-info
|
||||
[: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 "--"}]]
|
||||
[: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 layout-container-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "multiple"]))]}
|
||||
[{:keys [ids _type values multiple] :as props}]
|
||||
|
@ -308,8 +456,8 @@
|
|||
layout-type (:layout values)
|
||||
|
||||
on-add-layout
|
||||
(fn [_]
|
||||
(st/emit! (dwsl/create-layout))
|
||||
(fn [type]
|
||||
(st/emit! (dwsl/create-layout type))
|
||||
(reset! open? true))
|
||||
|
||||
|
||||
|
@ -318,22 +466,20 @@
|
|||
(st/emit! (dwsl/remove-layout ids))
|
||||
(reset! open? false))
|
||||
|
||||
;; Uncomment when activating the grid options
|
||||
;; set-flex (fn []
|
||||
;; (st/emit! (dwsl/remove-layout ids))
|
||||
;; (on-add-layout :flex))
|
||||
;;
|
||||
;; set-grid (fn []
|
||||
;; (st/emit! (dwsl/remove-layout ids))
|
||||
;; (on-add-layout :grid))
|
||||
_set-flex
|
||||
(fn []
|
||||
(st/emit! (dwsl/remove-layout ids))
|
||||
(on-add-layout :flex))
|
||||
|
||||
_set-grid
|
||||
(fn []
|
||||
(st/emit! (dwsl/remove-layout ids))
|
||||
(on-add-layout :grid))
|
||||
|
||||
;; Flex-direction
|
||||
|
||||
saved-dir (:layout-flex-dir values)
|
||||
is-col? (or (= :column saved-dir) (= :column-reverse saved-dir))
|
||||
set-direction
|
||||
(fn [dir]
|
||||
(st/emit! (dwsl/update-layout ids {:layout-flex-dir dir})))
|
||||
|
||||
;; Wrap type
|
||||
|
||||
|
@ -386,7 +532,79 @@
|
|||
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
|
||||
|
||||
:else
|
||||
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))]
|
||||
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))
|
||||
|
||||
;; Grid-direction
|
||||
|
||||
saved-grid-dir (:layout-grid-dir values)
|
||||
|
||||
set-direction
|
||||
(fn [dir type]
|
||||
(if (= :flex type)
|
||||
(st/emit! (dwsl/update-layout ids {:layout-flex-dir dir}))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))
|
||||
|
||||
;; Align grid
|
||||
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-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-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-rows values)
|
||||
grid-rows-open? (mf/use-state false)
|
||||
toggle-rows-info
|
||||
(mf/use-callback
|
||||
(fn [_]
|
||||
(swap! grid-rows-open? not)))
|
||||
|
||||
add-new-element
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [type value]
|
||||
(st/emit! (dwsl/add-layout-track ids type value))))
|
||||
|
||||
remove-element
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [type index]
|
||||
(st/emit! (dwsl/remove-layout-track ids type index))))
|
||||
|
||||
set-column-value
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [type index value]
|
||||
(st/emit! (dwsl/change-layout-track ids type index {:value value}))))
|
||||
|
||||
set-column-type
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [type index track-type]
|
||||
(st/emit! (dwsl/change-layout-track ids type index {:type track-type}))))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
|
@ -395,19 +613,21 @@
|
|||
(if (and (not multiple) (:layout values))
|
||||
[:div.title-actions
|
||||
#_[:div.layout-btns
|
||||
[:button {:on-click set-flex
|
||||
:class (dom/classnames
|
||||
:active (= :flex layout-type))} "Flex"]
|
||||
[:button {:on-click set-grid
|
||||
:class (dom/classnames
|
||||
:active (= :grid layout-type))} "Grid"]]
|
||||
[:button {:on-click set-flex
|
||||
:class (dom/classnames
|
||||
:active (= :flex layout-type))} "Flex"]
|
||||
[:button {:on-click set-grid
|
||||
:class (dom/classnames
|
||||
:active (= :grid layout-type))} "Grid"]]
|
||||
[:button.remove-layout {:on-click on-remove-layout} i/minus]]
|
||||
|
||||
[:button.add-page {:on-click on-add-layout} i/close])]]
|
||||
[:button.add-page {:on-click #(on-add-layout :flex)} i/close])]]
|
||||
|
||||
(when (:layout values)
|
||||
(when (not= :multiple layout-type)
|
||||
(if (= :flex layout-type)
|
||||
(case layout-type
|
||||
:flex
|
||||
|
||||
[:div.element-set-content.layout-menu
|
||||
[:div.layout-row
|
||||
[:div.direction-wrap.row-title "Direction"]
|
||||
|
@ -418,7 +638,8 @@
|
|||
[:& direction-btn {:key (d/name dir)
|
||||
:dir dir
|
||||
:saved-dir saved-dir
|
||||
:set-direction set-direction}])]]
|
||||
:set-direction #(set-direction dir :flex)
|
||||
:icon? true}])]]
|
||||
|
||||
[:div.wrap-type
|
||||
[:& wrap-row {:wrap-type wrap-type
|
||||
|
@ -456,4 +677,74 @@
|
|||
:on-change-style change-padding-type
|
||||
:on-change on-padding-change}]]
|
||||
|
||||
[:div "GRID TO COME"])))]))
|
||||
:grid
|
||||
|
||||
[:div.element-set-content.layout-menu
|
||||
[:div.layout-row
|
||||
[:div.direction-wrap.row-title "Direction"]
|
||||
[:div.btn-wrapper
|
||||
[:div.direction
|
||||
[:*
|
||||
(for [dir [:row :column]]
|
||||
[:& direction-btn {:key (d/name dir)
|
||||
:dir dir
|
||||
:saved-dir saved-grid-dir
|
||||
:set-direction #(set-direction dir :grid)
|
||||
:icon? false}])]]
|
||||
|
||||
(when (= 1 (count ids))
|
||||
[:div.edit-mode
|
||||
[:& grid-edit-mode {:id (first ids)}]])]]
|
||||
|
||||
[:div.layout-row
|
||||
[:div.align-items-grid.row-title "Align"]
|
||||
[:div.btn-wrapper.align-grid
|
||||
[:& align-grid-row {:is-col? false
|
||||
:align-items align-items-row
|
||||
:set-align set-align-grid}]
|
||||
|
||||
[:& align-grid-row {:is-col? true
|
||||
:align-items align-items-column
|
||||
:set-align set-align-grid}]]]
|
||||
|
||||
[:div.layout-row
|
||||
[:div.jusfiy-content-grid.row-title "Justify"]
|
||||
[:div.btn-wrapper.align-grid
|
||||
[:& justify-grid-row {:is-col? true
|
||||
:justify-items grid-justify-content-column
|
||||
:set-justify set-justify-grid}]
|
||||
[:& justify-grid-row {:is-col? false
|
||||
: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 column-grid-values
|
||||
:add-new-element add-new-element
|
||||
:set-column-value set-column-value
|
||||
: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 rows-grid-values
|
||||
:add-new-element add-new-element
|
||||
:set-column-value set-column-value
|
||||
:set-column-type set-column-type
|
||||
:remove-element remove-element}]
|
||||
|
||||
[:& gap-section {:is-col? is-col?
|
||||
:wrap-type wrap-type
|
||||
:gap-selected? gap-selected?
|
||||
:set-gap set-gap
|
||||
:gap-value (:layout-gap values)}]
|
||||
|
||||
[:& padding-section {:values values
|
||||
:on-change-style change-padding-type
|
||||
:on-change on-padding-change}]]
|
||||
|
||||
|
||||
;; Default if not grid or flex
|
||||
nil)))]))
|
||||
|
|
|
@ -83,9 +83,9 @@
|
|||
selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
selection-parents (mf/deref selection-parents-ref)
|
||||
|
||||
flex-child? (->> selection-parents (some ctl/layout?))
|
||||
flex-child? (->> selection-parents (some ctl/flex-layout?))
|
||||
absolute? (ctl/layout-absolute? shape)
|
||||
flex-container? (ctl/layout? shape)
|
||||
flex-container? (ctl/flex-layout? shape)
|
||||
flex-auto-width? (ctl/auto-width? shape)
|
||||
flex-fill-width? (ctl/fill-width? shape)
|
||||
flex-auto-height? (ctl/auto-height? shape)
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
|
@ -41,7 +41,7 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
@ -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}])
|
||||
[:& layer-menu {:ids ids
|
||||
|
|
|
@ -32,9 +32,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
|
@ -43,14 +42,14 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:is-layout-container? false
|
||||
: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}])
|
||||
[:& layer-menu {:ids ids
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
[comp-ids comp-values] [[(:id shape)] (select-keys shape component-attrs)]
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
is-layout-container? (ctl/layout? shape)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids [(:id shape)]
|
||||
|
@ -48,18 +48,18 @@
|
|||
[:& component-menu {:ids comp-ids
|
||||
:values comp-values
|
||||
:shape-name (:name 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}])
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when (or is-layout-child? is-layout-container?)
|
||||
(when (or is-flex-layout-child? is-flex-layout-container?)
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? is-layout-child?
|
||||
:is-layout-container? is-layout-container?
|
||||
:is-layout-child? is-flex-layout-child?
|
||||
:is-layout-container? is-flex-layout-container?
|
||||
:shape shape}])
|
||||
|
||||
[:& layer-menu {:ids ids
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
;; 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.workspace.sidebar.options.shapes.grid-cell
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :as lyc]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc set-self-alignment
|
||||
[{:keys [is-col? alignment set-alignment] :as props}]
|
||||
(let [dir-v [:auto :start :center :end :stretch #_:baseline]]
|
||||
[:div.align-self-style
|
||||
(for [align dir-v]
|
||||
[:button.align-self.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :active (= alignment align)
|
||||
:tooltip-bottom-left (not= align :start)
|
||||
:tooltip-bottom (= align :start))
|
||||
:alt (dm/str "Align self " (d/name align)) ;; TODO fix this tooltip
|
||||
:on-click #(set-alignment align)
|
||||
:key (str "align-self" align)}
|
||||
(lyc/get-layout-flex-icon :align-self align is-col?)])]))
|
||||
|
||||
|
||||
(mf/defc options
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [_shape row column] :as props}]
|
||||
|
||||
(let [position-mode (mf/use-state :auto) ;; TODO this should come from shape
|
||||
|
||||
set-position-mode (fn [mode]
|
||||
(reset! position-mode mode))
|
||||
|
||||
|
||||
align-self (mf/use-state :auto) ;; TODO this should come from shape
|
||||
justify-alignment (mf/use-state :auto) ;; TODO this should come from shape
|
||||
set-alignment (fn [value]
|
||||
(reset! align-self value)
|
||||
#_(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}))))
|
||||
set-justify-self (fn [value]
|
||||
(reset! justify-alignment value)
|
||||
#_(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 column
|
||||
column-end (inc column)
|
||||
row-start row
|
||||
row-end (inc row)
|
||||
|
||||
on-change
|
||||
(fn [_side _orientation _value]
|
||||
;; TODO
|
||||
#_(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"]]
|
||||
|
||||
[:div.element-set-content.layout-grid-item-menu
|
||||
[:div.layout-row
|
||||
[:div.row-title.sizing "Position"]
|
||||
[:div.position-wrapper
|
||||
[:button.position-btn
|
||||
{:on-click #(set-position-mode :auto)
|
||||
:class (dom/classnames :active (= :auto @position-mode))} "Auto"]
|
||||
[:button.position-btn
|
||||
{:on-click #(set-position-mode :manual)
|
||||
:class (dom/classnames :active (= :manual @position-mode))} "Manual"]
|
||||
[:button.position-btn
|
||||
{:on-click #(set-position-mode :area)
|
||||
:class (dom/classnames :active (= :area @position-mode))} "Area"]]]
|
||||
[:div.manage-grid-columns
|
||||
(when (= :auto @position-mode)
|
||||
[:div.grid-auto
|
||||
[:div.grid-columns-auto
|
||||
[:spam.icon i/layout-rows]
|
||||
[:div.input-wrapper
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-change :all :column) ;; TODO cambiar este on-change y el value
|
||||
:value column-start}]]]
|
||||
[: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 :all :row) ;; TODO cambiar este on-change y el value
|
||||
:value row-start}]]]])
|
||||
(when (= :area @position-mode)
|
||||
[:div.input-wrapper
|
||||
[:input.input-text
|
||||
{:key "grid-area-name"
|
||||
:id "grid-area-name"
|
||||
:type "text"
|
||||
:aria-label "grid-area-name"
|
||||
:placeholder "--"
|
||||
:default-value @area-name
|
||||
:auto-complete "off"
|
||||
:on-change on-area-name-change
|
||||
:on-key-press on-key-press}]])
|
||||
|
||||
(when (or (= :manual @position-mode) (= :area @position-mode))
|
||||
[:div.grid-manual
|
||||
[:div.grid-columns-auto
|
||||
[:spam.icon i/layout-rows]
|
||||
[:div.input-wrapper
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click #(dom/select-target %)
|
||||
: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)
|
||||
: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)
|
||||
:value row-start}]
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-change :end :row)
|
||||
:value row-end}]]]])]
|
||||
|
||||
[:div.layout-row
|
||||
[:div.row-title "Align"]
|
||||
[:div.btn-wrapper
|
||||
[:& set-self-alignment {:is-col? false
|
||||
:alignment @align-self
|
||||
:set-alignment set-alignment}]]]
|
||||
|
||||
|
||||
[:div.layout-row
|
||||
[:div.row-title "Justify"]
|
||||
[:div.btn-wrapper
|
||||
[:& set-self-alignment {:is-col? true
|
||||
:alignment @justify-alignment
|
||||
:set-alignment set-justify-self}]]]]]))
|
|
@ -29,15 +29,15 @@
|
|||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
shape-with-children (unchecked-get props "shape-with-children")
|
||||
shared-libs (unchecked-get props "shared-libs")
|
||||
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
|
||||
file-id (unchecked-get props "file-id")
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
ids [(:id shape)]
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
(let [shape (unchecked-get props "shape")
|
||||
shape-with-children (unchecked-get props "shape-with-children")
|
||||
shared-libs (unchecked-get props "shared-libs")
|
||||
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
|
||||
file-id (unchecked-get props "file-id")
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
ids [(:id shape)]
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
|
||||
type :group
|
||||
|
@ -58,7 +58,7 @@
|
|||
[:& component-menu {:ids comp-ids :values comp-values :shape-name (:name shape)}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:type type
|
||||
:ids layout-item-ids
|
||||
|
@ -66,7 +66,7 @@
|
|||
:is-layout-container? false
|
||||
:values layout-item-values}])
|
||||
|
||||
(when (or (not is-layout-child?) is-layout-child-absolute?)
|
||||
(when (or (not is-flex-layout-child?) is-layout-child-absolute?)
|
||||
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
|
||||
|
||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
|
@ -42,7 +42,7 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
@ -50,7 +50,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}])
|
||||
|
||||
|
|
|
@ -294,17 +294,17 @@
|
|||
all-types (into #{} (map :type shapes))
|
||||
|
||||
ids (->> shapes (map :id))
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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)
|
||||
|
||||
has-text? (contains? all-types :text)
|
||||
|
||||
has-layout-container? (->> shapes (some ctl/layout?))
|
||||
has-flex-layout-container? (->> shapes (some ctl/flex-layout?))
|
||||
|
||||
all-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/all-layout-child? ids))
|
||||
all-layout-child? (mf/deref all-layout-child-ref)
|
||||
all-flex-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/all-flex-layout-child? ids))
|
||||
all-flex-layout-child? (mf/deref all-flex-layout-child-ref)
|
||||
|
||||
all-layout-container? (->> shapes (every? ctl/layout?))
|
||||
all-flex-layout-container? (->> shapes (every? ctl/flex-layout?))
|
||||
|
||||
[measure-ids measure-values] (get-attrs shapes objects :measure)
|
||||
|
||||
|
@ -342,15 +342,15 @@
|
|||
|
||||
[:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}]
|
||||
|
||||
(when (or is-layout-child? has-layout-container?)
|
||||
(when (or is-flex-layout-child? has-flex-layout-container?)
|
||||
[:& layout-item-menu
|
||||
{:type type
|
||||
:ids layout-item-ids
|
||||
:is-layout-child? all-layout-child?
|
||||
:is-layout-container? all-layout-container?
|
||||
:is-layout-child? all-flex-layout-child?
|
||||
:is-layout-container? all-flex-layout-container?
|
||||
:values layout-item-values}])
|
||||
|
||||
(when-not (or (empty? constraint-ids) is-layout-child?)
|
||||
(when-not (or (empty? constraint-ids) is-flex-layout-child?)
|
||||
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
|
||||
|
||||
(when-not (empty? layer-ids)
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
|
@ -42,14 +42,14 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:is-layout-container? false
|
||||
: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}])
|
||||
[:& layer-menu {:ids ids
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
stroke-values (select-keys shape stroke-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
|
@ -41,7 +41,7 @@
|
|||
:values measure-values
|
||||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
@ -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}])
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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-layout-child-absolute? (ctl/layout-absolute? shape)]
|
||||
|
||||
(when (contains? svg-elements tag)
|
||||
|
@ -118,7 +118,7 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
@ -126,7 +126,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}])
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
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)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
state-map (mf/deref refs/workspace-editor-state)
|
||||
|
@ -76,7 +76,7 @@
|
|||
:shape shape}]
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when is-layout-child?
|
||||
(when is-flex-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
@ -84,7 +84,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 (select-keys shape constraint-attrs)}])
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
[app.main.ui.workspace.viewport.drawarea :as drawarea]
|
||||
[app.main.ui.workspace.viewport.frame-grid :as frame-grid]
|
||||
[app.main.ui.workspace.viewport.gradients :as gradients]
|
||||
[app.main.ui.workspace.viewport.grid-layout-editor :as grid-layout]
|
||||
[app.main.ui.workspace.viewport.guides :as guides]
|
||||
[app.main.ui.workspace.viewport.hooks :as hooks]
|
||||
[app.main.ui.workspace.viewport.interactions :as interactions]
|
||||
|
@ -51,17 +52,20 @@
|
|||
|
||||
(defn apply-modifiers-to-selected
|
||||
[selected objects text-modifiers modifiers]
|
||||
(into []
|
||||
(comp
|
||||
(keep (d/getf objects))
|
||||
(map (fn [{:keys [id] :as shape}]
|
||||
(cond-> shape
|
||||
(and (cph/text-shape? shape) (contains? text-modifiers id))
|
||||
(dwm/apply-text-modifier (get text-modifiers id))
|
||||
(reduce
|
||||
(fn [objects id]
|
||||
(update
|
||||
objects id
|
||||
(fn [shape]
|
||||
(cond-> shape
|
||||
(and (cph/text-shape? shape) (contains? text-modifiers id))
|
||||
(dwm/apply-text-modifier (get text-modifiers id))
|
||||
|
||||
(contains? modifiers id)
|
||||
(gsh/transform-shape (dm/get-in modifiers [id :modifiers]))))))
|
||||
selected))
|
||||
(contains? modifiers id)
|
||||
(gsh/transform-shape (dm/get-in modifiers [id :modifiers]))))))
|
||||
|
||||
objects
|
||||
selected))
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [wlocal wglobal selected layout file] :as props}]
|
||||
|
@ -97,8 +101,11 @@
|
|||
modifiers (mf/deref refs/workspace-modifiers)
|
||||
text-modifiers (mf/deref refs/workspace-text-modifier)
|
||||
|
||||
objects-modified (mf/with-memo [base-objects modifiers]
|
||||
(gsh/apply-objects-modifiers base-objects modifiers selected))
|
||||
objects-modified (mf/with-memo
|
||||
[base-objects text-modifiers modifiers]
|
||||
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
||||
|
||||
selected-shapes (->> selected (keep (d/getf objects-modified)))
|
||||
|
||||
background (get options :background clr/canvas)
|
||||
|
||||
|
@ -138,7 +145,6 @@
|
|||
drawing-tool (:tool drawing)
|
||||
drawing-obj (:object drawing)
|
||||
|
||||
selected-shapes (apply-modifiers-to-selected selected base-objects text-modifiers modifiers)
|
||||
|
||||
selected-frames (into #{} (map :frame-id) selected-shapes)
|
||||
|
||||
|
@ -152,6 +158,7 @@
|
|||
(and (some? drawing-obj) (= :path (:type drawing-obj))))
|
||||
node-editing? (and edition (not= :text (get-in base-objects [edition :type])))
|
||||
text-editing? (and edition (= :text (get-in base-objects [edition :type])))
|
||||
grid-editing? (and edition (ctl/grid-layout? base-objects edition))
|
||||
|
||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
mode-inspect? (= options-mode :inspect)
|
||||
|
@ -162,7 +169,7 @@
|
|||
on-drag-enter (actions/on-drag-enter)
|
||||
on-drag-over (actions/on-drag-over)
|
||||
on-drop (actions/on-drop file)
|
||||
on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing?
|
||||
on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? grid-editing?
|
||||
drawing-path? create-comment? space? panning z? workspace-read-only?)
|
||||
on-mouse-up (actions/on-mouse-up disable-paste)
|
||||
on-pointer-down (actions/on-pointer-down)
|
||||
|
@ -193,6 +200,7 @@
|
|||
show-pixel-grid? (and (contains? layout :show-pixel-grid)
|
||||
(>= zoom 8))
|
||||
show-text-editor? (and editing-shape (= :text (:type editing-shape)))
|
||||
show-grid-editor? (and editing-shape (ctl/grid-layout? editing-shape))
|
||||
show-presence? page-id
|
||||
show-prototypes? (= options-mode :prototype)
|
||||
show-selection-handlers? (and (seq selected) (not show-text-editor?))
|
||||
|
@ -333,7 +341,7 @@
|
|||
:zoom zoom
|
||||
:modifiers modifiers}]
|
||||
|
||||
(when (ctl/layout? outlined-frame)
|
||||
(when (ctl/any-layout? outlined-frame)
|
||||
[:g.ghost-outline
|
||||
[:& outline/shape-outlines
|
||||
{:objects base-objects
|
||||
|
@ -496,6 +504,12 @@
|
|||
:hover-top-frame-id @hover-top-frame-id
|
||||
:zoom zoom}])
|
||||
|
||||
(when (debug? :grid-layout)
|
||||
[:& wvd/debug-grid-layout {:selected-shapes selected-shapes
|
||||
:objects base-objects
|
||||
:hover-top-frame-id @hover-top-frame-id
|
||||
:zoom zoom}])
|
||||
|
||||
(when show-selection-handlers?
|
||||
[:g.selection-handlers {:clipPath "url(#clip-handlers)"}
|
||||
[:defs
|
||||
|
@ -526,4 +540,11 @@
|
|||
(when show-gradient-handlers?
|
||||
[:& gradients/gradient-handlers
|
||||
{:id (first selected)
|
||||
:zoom zoom}])]]]))
|
||||
:zoom zoom}])
|
||||
|
||||
(when show-grid-editor?
|
||||
[:& grid-layout/editor
|
||||
{:zoom zoom
|
||||
:objects base-objects
|
||||
:shape (get base-objects edition)}])
|
||||
]]]))
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
|
||||
(defn on-mouse-down
|
||||
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? space? panning z? workspace-read-only?]
|
||||
node-editing? grid-editing? drawing-path? create-comment? space? panning z? workspace-read-only?]
|
||||
(mf/use-callback
|
||||
(mf/deps id blocked hidden type selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? @z? @space?
|
||||
node-editing? grid-editing? drawing-path? create-comment? @z? @space?
|
||||
panning workspace-read-only?)
|
||||
(fn [bevent]
|
||||
(when (or (dom/class? (dom/get-target bevent) "viewport-controls")
|
||||
|
@ -70,7 +70,7 @@
|
|||
(do
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?))
|
||||
|
||||
(when (and (not= edition id) text-editing?)
|
||||
(when (and (not= edition id) (or text-editing? grid-editing?))
|
||||
(st/emit! dw/clear-edition-mode))
|
||||
|
||||
(when (and (not text-editing?)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.geom.shapes.grid-layout :as gsg]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
|
@ -68,7 +69,7 @@
|
|||
|
||||
shape (or selected-frame (get objects hover-top-frame-id))]
|
||||
|
||||
(when (and shape (ctl/layout? shape))
|
||||
(when (and shape (ctl/flex-layout? shape))
|
||||
(let [row? (ctl/row? shape)
|
||||
col? (ctl/col? shape)
|
||||
|
||||
|
@ -195,3 +196,55 @@
|
|||
:cy (:y point)
|
||||
:r (/ 2 zoom)
|
||||
:style {:fill "red"}}]))])]))))
|
||||
|
||||
(mf/defc debug-grid-layout
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [objects (unchecked-get props "objects")
|
||||
zoom (unchecked-get props "zoom")
|
||||
selected-shapes (unchecked-get props "selected-shapes")
|
||||
hover-top-frame-id (unchecked-get props "hover-top-frame-id")
|
||||
|
||||
selected-frame
|
||||
(when (and (= (count selected-shapes) 1) (= :frame (-> selected-shapes first :type)))
|
||||
(first selected-shapes))
|
||||
|
||||
parent (or selected-frame (get objects hover-top-frame-id))
|
||||
parent-bounds (:points parent)]
|
||||
|
||||
(when (and (some? parent) (not= uuid/zero (:id parent)))
|
||||
(let [children (->> (cph/get-immediate-children objects (:id parent))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points parent)) %)))
|
||||
|
||||
hv #(gpo/start-hv parent-bounds %)
|
||||
vv #(gpo/start-vv parent-bounds %)
|
||||
|
||||
width (gpo/width-points parent-bounds)
|
||||
height (gpo/height-points parent-bounds)
|
||||
origin (gpo/origin parent-bounds)
|
||||
|
||||
{:keys [row-tracks column-tracks]}
|
||||
(gsg/calc-layout-data parent children parent-bounds)]
|
||||
|
||||
[:*
|
||||
(for [row-data row-tracks]
|
||||
(let [start-p (gpt/add origin (vv (:distance row-data)))
|
||||
end-p (gpt/add start-p (hv width))]
|
||||
[:line {:x1 (:x start-p)
|
||||
:y1 (:y start-p)
|
||||
:x2 (:x end-p)
|
||||
:y2 (:y end-p)
|
||||
:style {:stroke "red"
|
||||
:stroke-width (/ 1 zoom)}}]))
|
||||
|
||||
(for [column-data column-tracks]
|
||||
(let [start-p (gpt/add origin (hv (:distance column-data)))
|
||||
end-p (gpt/add start-p (vv height))]
|
||||
[:line {:x1 (:x start-p)
|
||||
:y1 (:y start-p)
|
||||
:x2 (:x end-p)
|
||||
:y2 (:y end-p)
|
||||
:style {:stroke "red"
|
||||
:stroke-width (/ 1 zoom)}}]))]))))
|
||||
|
|
|
@ -0,0 +1,324 @@
|
|||
;; 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.workspace.viewport.grid-layout-editor
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.grid-layout :as gsg]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[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.util.dom :as dom]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn apply-to-point [result next-fn]
|
||||
(conj result (next-fn (last result))))
|
||||
|
||||
(mf/defc track-marker
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [center (unchecked-get props "center")
|
||||
value (unchecked-get props "value")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
marker-points
|
||||
(reduce
|
||||
apply-to-point
|
||||
[(gpt/subtract center
|
||||
(gpt/point (/ 13 zoom) (/ 16 zoom)))]
|
||||
[#(gpt/add % (gpt/point (/ 26 zoom) 0))
|
||||
#(gpt/add % (gpt/point 0 (/ 24 zoom)))
|
||||
#(gpt/add % (gpt/point (- (/ 13 zoom)) (/ 8 zoom)))
|
||||
#(gpt/subtract % (gpt/point (/ 13 zoom) (/ 8 zoom)))])
|
||||
|
||||
text-x (:x center)
|
||||
text-y (:y center)]
|
||||
|
||||
[:g.grid-track-marker
|
||||
[:polygon {:points (->> marker-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))
|
||||
|
||||
:style {:fill "var(--color-distance)"
|
||||
:fill-opacity 0.3}}]
|
||||
[:text {:x text-x
|
||||
:y text-y
|
||||
:width (/ 26.26 zoom)
|
||||
:height (/ 32 zoom)
|
||||
:font-size (/ 16 zoom)
|
||||
:text-anchor "middle"
|
||||
:dominant-baseline "middle"
|
||||
:style {:fill "var(--color-distance)"}}
|
||||
(dm/str value)]]))
|
||||
|
||||
(mf/defc grid-editor-frame
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [bounds (unchecked-get props "bounds")
|
||||
zoom (unchecked-get props "zoom")
|
||||
hv #(gpo/start-hv bounds %)
|
||||
vv #(gpo/start-vv bounds %)
|
||||
width (gpo/width-points bounds)
|
||||
height (gpo/height-points bounds)
|
||||
origin (gpo/origin bounds)
|
||||
|
||||
frame-points
|
||||
(reduce
|
||||
apply-to-point
|
||||
[origin]
|
||||
[#(gpt/add % (hv width))
|
||||
#(gpt/subtract % (vv (/ 40 zoom)))
|
||||
#(gpt/subtract % (hv (+ width (/ 40 zoom))))
|
||||
#(gpt/add % (vv (+ height (/ 40 zoom))))
|
||||
#(gpt/add % (hv (/ 40 zoom)))])]
|
||||
|
||||
[:polygon {:points (->> frame-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))
|
||||
:style {:stroke "var(--color-distance)"
|
||||
:stroke-width (/ 1 zoom)}}]))
|
||||
|
||||
(mf/defc plus-btn
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [start-p (unchecked-get props "start-p")
|
||||
zoom (unchecked-get props "zoom")
|
||||
type (unchecked-get props "type")
|
||||
|
||||
[rect-x rect-y icon-x icon-y]
|
||||
(if (= type :column)
|
||||
[(:x start-p)
|
||||
(- (:y start-p) (/ 40 zoom))
|
||||
(+ (:x start-p) (/ 12 zoom))
|
||||
(- (:y start-p) (/ 28 zoom))]
|
||||
|
||||
[(- (:x start-p) (/ 40 zoom))
|
||||
(:y start-p)
|
||||
(- (:x start-p) (/ 28 zoom))
|
||||
(+ (:y start-p) (/ 12 zoom))])]
|
||||
|
||||
[:g.plus-button
|
||||
[:rect {:x rect-x
|
||||
:y rect-y
|
||||
:width (/ 40 zoom)
|
||||
:height (/ 40 zoom)
|
||||
:style {:fill "var(--color-distance)"
|
||||
:stroke "var(--color-distance)"
|
||||
:stroke-width (/ 1 zoom)}}]
|
||||
|
||||
[:use {:x icon-x
|
||||
:y icon-y
|
||||
:width (/ 16 zoom)
|
||||
:height (/ 16 zoom)
|
||||
:href (dm/str "#icon-plus")
|
||||
:fill "white"}]]))
|
||||
|
||||
(mf/defc grid-cell
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [row-tracks column-tracks]} (unchecked-get props "layout-data")
|
||||
bounds (unchecked-get props "bounds")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
hover? (unchecked-get props "hover?")
|
||||
selected? (unchecked-get props "selected?")
|
||||
|
||||
row (unchecked-get props "row")
|
||||
column (unchecked-get props "column")
|
||||
|
||||
column-track (nth column-tracks (dec column) nil)
|
||||
row-track (nth row-tracks (dec row) nil)
|
||||
|
||||
|
||||
origin (gpo/origin bounds)
|
||||
hv #(gpo/start-hv bounds %)
|
||||
vv #(gpo/start-vv bounds %)
|
||||
|
||||
start-p (-> origin
|
||||
(gpt/add (hv (:distance column-track)))
|
||||
(gpt/add (vv (:distance row-track))))
|
||||
|
||||
end-p (-> start-p
|
||||
(gpt/add (hv (:value column-track)))
|
||||
(gpt/add (vv (:value row-track))))]
|
||||
|
||||
[:rect.cell-editor
|
||||
{:x (:x start-p)
|
||||
:y (:y start-p)
|
||||
:width (- (:x end-p) (:x start-p))
|
||||
:height (- (:y end-p) (:y start-p))
|
||||
|
||||
:on-pointer-enter #(st/emit! (dwge/hover-grid-cell (:id shape) row column true))
|
||||
:on-pointer-leave #(st/emit! (dwge/hover-grid-cell (:id shape) row column false))
|
||||
|
||||
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) row column))
|
||||
|
||||
:style {:fill "transparent"
|
||||
:stroke "var(--color-distance)"
|
||||
:stroke-dasharray (when-not (or hover? selected?)
|
||||
(str/join " " (map #(/ % zoom) [0 8]) ))
|
||||
:stroke-linecap "round"
|
||||
: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}
|
||||
[props]
|
||||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (unchecked-get props "objects")
|
||||
zoom (unchecked-get props "zoom")
|
||||
bounds (:points shape)
|
||||
|
||||
grid-edition-id-ref (mf/use-memo #(refs/workspace-grid-edition-id (:id shape)))
|
||||
grid-edition (mf/deref grid-edition-id-ref)
|
||||
|
||||
hover-cells (:hover grid-edition)
|
||||
selected-cells (:selected grid-edition)
|
||||
|
||||
children (->> (cph/get-immediate-children objects (:id shape))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
|
||||
|
||||
hv #(gpo/start-hv bounds %)
|
||||
vv #(gpo/start-vv bounds %)
|
||||
width (gpo/width-points bounds)
|
||||
height (gpo/height-points bounds)
|
||||
origin (gpo/origin bounds)
|
||||
|
||||
{:keys [row-tracks column-tracks] :as layout-data}
|
||||
(gsg/calc-layout-data shape children bounds)]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
|
||||
|
||||
[:g.grid-editor
|
||||
[:& grid-editor-frame {:zoom zoom
|
||||
:bounds bounds}]
|
||||
(let [start-p (-> origin (gpt/add (hv width)))]
|
||||
[:& plus-btn {:start-p start-p
|
||||
:zoom zoom
|
||||
:type :column}])
|
||||
|
||||
(let [start-p (-> origin (gpt/add (vv height)))]
|
||||
[:& plus-btn {:start-p start-p
|
||||
:zoom zoom
|
||||
:type :row}])
|
||||
|
||||
(for [[_ {:keys [column row]}] (:layout-grid-cells shape)]
|
||||
[:& grid-cell {:shape shape
|
||||
:layout-data layout-data
|
||||
:row row
|
||||
:column column
|
||||
:bounds bounds
|
||||
:zoom zoom
|
||||
:hover? (contains? hover-cells [row column])
|
||||
:selected? (= selected-cells [row column])
|
||||
}])
|
||||
|
||||
(for [[idx column-data] (d/enumerate column-tracks)]
|
||||
(let [start-p (-> origin (gpt/add (hv (:distance column-data))))
|
||||
marker-p (-> start-p (gpt/subtract (vv (/ 20 zoom))))]
|
||||
[:*
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc idx))
|
||||
:zoom zoom}]
|
||||
|
||||
[:& 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))))
|
||||
marker-p (-> start-p (gpt/subtract (hv (/ 20 zoom))))]
|
||||
[:*
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc idx))
|
||||
:zoom zoom}]]
|
||||
|
||||
[:& resize-handler {:type :row
|
||||
:start-p start-p
|
||||
:zoom zoom
|
||||
:bounds bounds}]]))]))
|
|
@ -268,7 +268,7 @@
|
|||
frame (mf/deref (refs/object-by-id frame-id))
|
||||
selrect (gsh/selection-rect selected-shapes)]
|
||||
|
||||
(when-not (ctl/layout? frame)
|
||||
(when-not (ctl/any-layout? frame)
|
||||
[:g.distance
|
||||
[:& shape-distance
|
||||
{:selrect selrect
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
|
||||
shapes (if drawing [drawing] shapes)
|
||||
frame-id (snap/snap-frame-id shapes)]
|
||||
(when-not (ctl/layout? objects frame-id)
|
||||
(when-not (ctl/any-layout? objects frame-id)
|
||||
[:& snap-feedback {:shapes shapes
|
||||
:page-id page-id
|
||||
:remove-snap? remove-snap?
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
|
@ -55,8 +56,11 @@
|
|||
drawing (mf/deref refs/workspace-drawing)
|
||||
drawing-obj (:object drawing)
|
||||
shape (or drawing-obj (-> selected first))]
|
||||
(when (or (and (= (count selected) 1) (= (:id shape) edition) (not= :text (:type shape)))
|
||||
(and (some? drawing-obj) (= :path (:type drawing-obj))
|
||||
(when (or (and (= (count selected) 1)
|
||||
(= (:id shape) edition)
|
||||
(cph/path-shape? shape))
|
||||
(and (some? drawing-obj)
|
||||
(cph/path-shape? drawing-obj)
|
||||
(not= :curve (:tool drawing))))
|
||||
[:div.viewport-actions
|
||||
[:& path-actions {:shape shape}]])))
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
grid-y-data (get-grids-snap-points frame :y)]
|
||||
|
||||
(cond-> page-data
|
||||
(not (ctl/layout-descent? objects frame))
|
||||
(not (ctl/any-layout-descent? objects frame))
|
||||
|
||||
(-> ;; Update root frame information
|
||||
(assoc-in [uuid/zero :objects-data frame-id] frame-data)
|
||||
|
@ -106,7 +106,7 @@
|
|||
:id (:id shape)
|
||||
:pt %)))]
|
||||
(cond-> page-data
|
||||
(not (ctl/layout-descent? objects shape))
|
||||
(not (ctl/any-layout-descent? objects shape))
|
||||
(-> (assoc-in [frame-id :objects-data (:id shape)] shape-data)
|
||||
(update-in [frame-id :x] (make-insert-tree-data shape-data :x))
|
||||
(update-in [frame-id :y] (make-insert-tree-data shape-data :y))))))
|
||||
|
|
|
@ -95,6 +95,9 @@
|
|||
|
||||
;; Show shape name and id
|
||||
:shape-titles
|
||||
|
||||
;;
|
||||
:grid-layout
|
||||
})
|
||||
|
||||
;; These events are excluded when we activate the :events flag
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue