mirror of
https://github.com/penpot/penpot.git
synced 2025-03-24 13:41:39 -05:00
Merge remote-tracking branch 'origin/feature-grid' into develop
This commit is contained in:
commit
2a9b99e086
41 changed files with 846 additions and 749 deletions
|
@ -82,7 +82,6 @@
|
|||
children
|
||||
(->> children
|
||||
(keep (d/getf objects))
|
||||
(remove :hidden)
|
||||
(remove gco/invalid-geometry?)
|
||||
(map (partial apply-modifiers bounds)))
|
||||
|
||||
|
@ -169,13 +168,13 @@
|
|||
children-modifiers
|
||||
(if (or flex-layout? grid-layout?)
|
||||
(->> (:shapes parent)
|
||||
(filter #(ctl/layout-absolute? objects %)))
|
||||
(filter #(ctl/position-absolute? objects %)))
|
||||
(:shapes parent))
|
||||
|
||||
children-layout
|
||||
(when (or flex-layout? grid-layout?)
|
||||
(->> (:shapes parent)
|
||||
(remove #(ctl/layout-absolute? objects %))))]
|
||||
(remove #(ctl/position-absolute? objects %))))]
|
||||
|
||||
(cond-> modif-tree
|
||||
(and has-modifiers? parent? (not root?))
|
||||
|
@ -222,7 +221,7 @@
|
|||
(ctm/resize (gpt/point 1 scale-height) origin (:transform parent) (:transform-inverse parent)))))
|
||||
|
||||
children (->> (cfh/get-immediate-children objects parent-id)
|
||||
(remove :hidden)
|
||||
(remove ctl/position-absolute?)
|
||||
(remove gco/invalid-geometry?))
|
||||
|
||||
content-bounds
|
||||
|
|
|
@ -299,7 +299,7 @@
|
|||
ignore-constraints
|
||||
:scale
|
||||
|
||||
(and (ctl/any-layout? parent) (not (ctl/layout-absolute? child)))
|
||||
(and (ctl/any-layout? parent) (not (ctl/position-absolute? child)))
|
||||
:left
|
||||
|
||||
:else
|
||||
|
@ -310,7 +310,7 @@
|
|||
ignore-constraints
|
||||
:scale
|
||||
|
||||
(and (ctl/any-layout? parent) (not (ctl/layout-absolute? child)))
|
||||
(and (ctl/any-layout? parent) (not (ctl/position-absolute? child)))
|
||||
:top
|
||||
|
||||
:else
|
||||
|
@ -335,13 +335,14 @@
|
|||
child-bounds (gtr/transform-bounds child-bounds modifiers)
|
||||
parent-bounds transformed-parent-bounds))
|
||||
|
||||
transformed-child-bounds (if reset-modifiers?
|
||||
child-bounds
|
||||
(gtr/transform-bounds child-bounds modifiers))]
|
||||
transformed-child-bounds
|
||||
(if reset-modifiers?
|
||||
child-bounds
|
||||
(gtr/transform-bounds child-bounds modifiers))]
|
||||
|
||||
;; If the parent is a layout we don't need to calculate its constraints. Finish
|
||||
;; after normalize the children (to keep proper proportions)
|
||||
(if (ctl/any-layout? parent)
|
||||
(if (and (ctl/any-layout? parent) (not (ctl/position-absolute? child)))
|
||||
modifiers
|
||||
(let [child-points-before (gpo/parent-coords-bounds child-bounds parent-bounds)
|
||||
child-points-after (gpo/parent-coords-bounds transformed-child-bounds transformed-parent-bounds)
|
||||
|
|
|
@ -421,8 +421,12 @@
|
|||
reverse? (ctl/reverse? shape)
|
||||
children (cond->> children (not reverse?) reverse)
|
||||
|
||||
ignore-child?
|
||||
(fn [[_ child]]
|
||||
(ctl/position-absolute? child))
|
||||
|
||||
;; Don't take into account absolute children
|
||||
children (->> children (remove (comp ctl/layout-absolute? second)))
|
||||
children (->> children (remove ignore-child?))
|
||||
|
||||
;; Creates the layout lines information
|
||||
layout-lines
|
||||
|
|
|
@ -424,7 +424,7 @@
|
|||
|
||||
children
|
||||
(->> children
|
||||
(remove #(ctl/layout-absolute? (second %))))
|
||||
(remove #(ctl/position-absolute? (second %))))
|
||||
|
||||
children-map
|
||||
(into {}
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
position-delta (child-position-delta parent child child-bounds child-width child-height layout-data cell-data)]
|
||||
|
||||
(cond-> (ctm/empty)
|
||||
(not (ctl/layout-absolute? child))
|
||||
(not (ctl/position-absolute? child))
|
||||
(-> (ctm/add-modifiers fill-modifiers)
|
||||
(ctm/move position-delta)))))
|
||||
|
||||
|
|
|
@ -491,12 +491,19 @@
|
|||
(defn align-self-stretch? [{:keys [layout-item-align-self]}]
|
||||
(= :stretch layout-item-align-self))
|
||||
|
||||
(defn layout-absolute?
|
||||
(defn item-absolute?
|
||||
([objects id]
|
||||
(layout-absolute? (get objects id)))
|
||||
(item-absolute? (get objects id)))
|
||||
([shape]
|
||||
(true? (:layout-item-absolute shape))))
|
||||
|
||||
(defn position-absolute?
|
||||
([objects id]
|
||||
(position-absolute? (get objects id)))
|
||||
([shape]
|
||||
(or (item-absolute? shape)
|
||||
(:hidden shape))))
|
||||
|
||||
(defn layout-z-index
|
||||
([objects id]
|
||||
(layout-z-index (get objects id)))
|
||||
|
@ -509,11 +516,11 @@
|
|||
(auto-width? objects frame-id)
|
||||
(or (and (col? objects frame-id)
|
||||
(->> children-ids
|
||||
(remove (partial layout-absolute? objects))
|
||||
(remove (partial position-absolute? objects))
|
||||
(every? (partial fill-width? objects))))
|
||||
(and (row? objects frame-id)
|
||||
(->> children-ids
|
||||
(remove (partial layout-absolute? objects))
|
||||
(remove (partial position-absolute? objects))
|
||||
(some (partial fill-width? objects)))))))
|
||||
|
||||
(defn change-v-sizing?
|
||||
|
@ -705,8 +712,9 @@
|
|||
(update :layout-grid-cells update-cells)
|
||||
(assign-cells))))
|
||||
|
||||
(defn- reorder-grid-track
|
||||
[prop parent from-index to-index]
|
||||
(defn- reorder-grid-tracks
|
||||
"Swap the positions of the tracks info"
|
||||
[parent prop from-index to-index]
|
||||
(-> parent
|
||||
(update
|
||||
prop
|
||||
|
@ -720,13 +728,70 @@
|
|||
(d/insert-at-index (inc to-index) [[nil tr]])
|
||||
(d/vec-without-nils))))))))
|
||||
|
||||
(defn- swap-track-content
|
||||
"Swap the shapes contained in the given tracks moves as necessary the others."
|
||||
[parent prop from-track to-track]
|
||||
(let [remap-tracks
|
||||
(cond
|
||||
(> from-track to-track)
|
||||
(into {from-track to-track}
|
||||
(map #(vector % (inc %)))
|
||||
(range to-track from-track))
|
||||
(< from-track to-track)
|
||||
(into {from-track to-track}
|
||||
(map #(vector % (dec %)))
|
||||
(range (inc from-track) (inc to-track))))]
|
||||
(-> parent
|
||||
(update
|
||||
:layout-grid-cells
|
||||
update-vals
|
||||
(fn [cell] (update cell prop #(get remap-tracks % %)))))))
|
||||
|
||||
(declare resize-cell-area)
|
||||
(declare cells-by-column)
|
||||
(declare cells-by-row)
|
||||
|
||||
(defn- reorder-grid-track
|
||||
[parent from-index to-index move-content? cells-by tracks-props prop prop-span]
|
||||
(let [from-track (inc from-index)
|
||||
to-track (if (< to-index from-index)
|
||||
(+ to-index 2)
|
||||
(inc to-index))
|
||||
move-content?
|
||||
(and move-content? (not= from-track to-track))
|
||||
|
||||
parent
|
||||
(if move-content?
|
||||
(->> (concat (cells-by parent (dec from-track))
|
||||
(cells-by parent (dec to-track)))
|
||||
(reduce (fn [parent cell]
|
||||
(cond-> parent
|
||||
(and (> (get cell prop-span) 1)
|
||||
(or (> to-track from-track) (not (= to-track (get cell prop))))
|
||||
(or (< to-track from-track) (not (= to-track (+ (get cell prop) (dec (get cell prop-span)))))))
|
||||
(resize-cell-area
|
||||
(:row cell)
|
||||
(:column cell)
|
||||
(:row cell)
|
||||
(:column cell)
|
||||
(if (= prop :row) 1 (:row-span cell))
|
||||
(if (= prop :column) 1 (:column-span cell)))))
|
||||
parent))
|
||||
parent)
|
||||
|
||||
parent
|
||||
(reorder-grid-tracks parent tracks-props from-index to-index)]
|
||||
(cond-> parent
|
||||
move-content?
|
||||
(swap-track-content prop from-track to-track))))
|
||||
|
||||
(defn reorder-grid-column
|
||||
[parent from-index to-index]
|
||||
(reorder-grid-track :layout-grid-columns parent from-index to-index))
|
||||
[parent from-index to-index move-content?]
|
||||
(reorder-grid-track parent from-index to-index move-content? cells-by-column :layout-grid-columns :column :column-span))
|
||||
|
||||
(defn reorder-grid-row
|
||||
[parent from-index to-index]
|
||||
(reorder-grid-track :layout-grid-rows parent from-index to-index))
|
||||
[parent from-index to-index move-content?]
|
||||
(reorder-grid-track parent from-index to-index move-content? cells-by-row :layout-grid-rows :row :row-span))
|
||||
|
||||
(defn cells-seq
|
||||
[{:keys [layout-grid-cells layout-grid-dir]} & {:keys [sort?] :or {sort? false}}]
|
||||
|
@ -992,9 +1057,8 @@
|
|||
(defn resize-cell-area
|
||||
"Increases/decreases the cell size"
|
||||
[parent row column new-row new-column new-row-span new-column-span]
|
||||
|
||||
(if (and (>= new-row 0)
|
||||
(>= new-column 0)
|
||||
(if (and (>= new-row 1)
|
||||
(>= new-column 1)
|
||||
(>= new-row-span 1)
|
||||
(>= new-column-span 1))
|
||||
(let [prev-cell (cell-by-row-column parent row column)
|
||||
|
@ -1112,7 +1176,7 @@
|
|||
(update :shapes #(d/removev children %))
|
||||
(assign-cells))
|
||||
|
||||
children (->> children (remove #(layout-absolute? objects %)))]
|
||||
children (->> children (remove #(position-absolute? objects %)))]
|
||||
|
||||
(-> frame
|
||||
(update :shapes d/concat-vec children)
|
||||
|
@ -1146,22 +1210,30 @@
|
|||
|
||||
(assoc parent :shapes (into [] (reverse new-shapes)))))
|
||||
|
||||
(defn shapes-by-row
|
||||
(defn cells-by-row
|
||||
[parent index]
|
||||
(->> (:layout-grid-cells parent)
|
||||
(filter (fn [[_ {:keys [row row-span]}]]
|
||||
(and (>= (inc index) row)
|
||||
(< (inc index) (+ row row-span)))))
|
||||
(map second)
|
||||
(mapcat :shapes)))
|
||||
(map second)))
|
||||
|
||||
(defn shapes-by-column
|
||||
(defn cells-by-column
|
||||
[parent index]
|
||||
(->> (:layout-grid-cells parent)
|
||||
(filter (fn [[_ {:keys [column column-span]}]]
|
||||
(and (>= (inc index) column)
|
||||
(< (inc index) (+ column column-span)))))
|
||||
(map second)
|
||||
(map second)))
|
||||
|
||||
(defn shapes-by-row
|
||||
[parent index]
|
||||
(->> (cells-by-row parent index)
|
||||
(mapcat :shapes)))
|
||||
|
||||
(defn shapes-by-column
|
||||
[parent index]
|
||||
(->> (cells-by-column parent index)
|
||||
(mapcat :shapes)))
|
||||
|
||||
(defn cells-coordinates
|
||||
|
|
|
@ -1039,9 +1039,7 @@
|
|||
(rx/of (dwe/start-edition-mode id))
|
||||
|
||||
(:group :bool :frame)
|
||||
(let [shapes-ids (into (d/ordered-set)
|
||||
(remove #(dm/get-in objects [% :hidden]))
|
||||
shapes)]
|
||||
(let [shapes-ids (into (d/ordered-set) shapes)]
|
||||
(rx/of (dws/select-shapes shapes-ids)))
|
||||
|
||||
:svg-raw
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.workspace.grid-layout.editor
|
||||
(:require
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
|
@ -84,3 +85,18 @@
|
|||
(-> local
|
||||
(update :vbox merge (select-keys srect [:x :y :x1 :x2 :y1 :y2])))))))))))
|
||||
|
||||
(defn select-track-cells
|
||||
[grid-id type index]
|
||||
(ptk/reify ::select-track-cells
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
parent (get objects grid-id)
|
||||
|
||||
cells
|
||||
(if (= type :column)
|
||||
(ctl/cells-by-column parent index)
|
||||
(ctl/cells-by-row parent index))
|
||||
|
||||
selected (into #{} (map :id) cells)]
|
||||
(assoc-in state [:workspace-grid-edition grid-id :selected] selected)))))
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
(update :shapes #(d/removev ids %))
|
||||
(ctl/assign-cells))
|
||||
|
||||
ids (->> ids (remove #(ctl/layout-absolute? objects %)))
|
||||
ids (->> ids (remove #(ctl/position-absolute? objects %)))
|
||||
frame (-> frame
|
||||
(update :shapes d/concat-vec ids)
|
||||
(cond-> (some? cell)
|
||||
|
|
|
@ -285,7 +285,7 @@
|
|||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn reorder-layout-track
|
||||
[ids type from-index to-index]
|
||||
[ids type from-index to-index move-content?]
|
||||
(assert (#{:row :column} type))
|
||||
|
||||
(ptk/reify ::reorder-layout-track
|
||||
|
@ -297,8 +297,8 @@
|
|||
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))))
|
||||
:row (ctl/reorder-grid-row shape from-index to-index move-content?)
|
||||
:column (ctl/reorder-grid-column shape from-index to-index move-content?))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
|
@ -311,11 +311,13 @@
|
|||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
shape (get objects (first ids))
|
||||
highlighted (when hover?
|
||||
(->> (if (= type :row)
|
||||
(ctl/shapes-by-row shape index)
|
||||
(ctl/shapes-by-column shape index))
|
||||
(set)))]
|
||||
|
||||
highlighted
|
||||
(when hover?
|
||||
(->> (if (= type :row)
|
||||
(ctl/shapes-by-row shape index)
|
||||
(ctl/shapes-by-column shape index))
|
||||
(set)))]
|
||||
(cond-> state
|
||||
hover?
|
||||
(update-in [:workspace-grid-edition (first ids) :hover-track] (fnil conj #{}) [type index])
|
||||
|
@ -359,7 +361,7 @@
|
|||
all-children (->> parent
|
||||
:shapes
|
||||
(map (d/getf objects))
|
||||
(remove ctl/layout-absolute?))]
|
||||
(remove ctl/position-absolute?))]
|
||||
|
||||
(cond-> shape
|
||||
;; If the parent is hug width and the direction column
|
||||
|
|
|
@ -721,7 +721,7 @@
|
|||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
selected-shapes (->> selected (map (d/getf objects)))]
|
||||
(if (every? #(and (ctl/any-layout-immediate-child? objects %)
|
||||
(not (ctl/layout-absolute? %)))
|
||||
(not (ctl/position-absolute? %)))
|
||||
selected-shapes)
|
||||
(rx/of (reorder-selected-layout-child direction))
|
||||
(rx/of (nudge-selected-shapes direction shift?)))))))
|
||||
|
@ -829,7 +829,7 @@
|
|||
moving-shapes
|
||||
(->> moving-shapes
|
||||
(remove (fn [shape]
|
||||
(and (ctl/layout-absolute? shape)
|
||||
(and (ctl/position-absolute? shape)
|
||||
(= frame-id (:parent-id shape))))))
|
||||
|
||||
frame-component
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
[app.common.types.file :as ctf]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.config :as cfg]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.ui.context :as muc]
|
||||
|
@ -34,6 +35,7 @@
|
|||
[app.main.ui.shapes.embed :as embed]
|
||||
[app.main.ui.shapes.export :as export]
|
||||
[app.main.ui.shapes.frame :as frame]
|
||||
[app.main.ui.shapes.grid-layout-viewer :refer [grid-layout-viewer]]
|
||||
[app.main.ui.shapes.group :as group]
|
||||
[app.main.ui.shapes.image :as image]
|
||||
[app.main.ui.shapes.path :as path]
|
||||
|
@ -306,11 +308,22 @@
|
|||
:fill "none"}
|
||||
[:& shape-wrapper {:shape frame}]]]))
|
||||
|
||||
(mf/defc empty-grids
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [root-shape-id objects]}]
|
||||
(let [empty-grids
|
||||
(->> (cons root-shape-id (cfh/get-children-ids objects root-shape-id))
|
||||
(filter #(ctl/grid-layout? objects %))
|
||||
(map #(get objects %))
|
||||
(filter #(empty? (:shapes %))))]
|
||||
(for [grid empty-grids]
|
||||
[:& grid-layout-viewer {:shape grid :objects objects}])))
|
||||
|
||||
;; Component for rendering a thumbnail of a single componenent. Mainly
|
||||
;; used to render thumbnails on assets panel.
|
||||
(mf/defc component-svg
|
||||
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
||||
[{:keys [objects root-shape zoom] :or {zoom 1} :as props}]
|
||||
[{:keys [objects root-shape show-grids? zoom] :or {zoom 1} :as props}]
|
||||
(when root-shape
|
||||
(let [root-shape-id (:id root-shape)
|
||||
include-metadata (mf/use-ctx export/include-metadata-ctx)
|
||||
|
@ -352,9 +365,59 @@
|
|||
:xmlns:penpot (when include-metadata "https://penpot.app/xmlns")
|
||||
:fill "none"}
|
||||
|
||||
[:> shape-container {:shape root-shape'}
|
||||
[:& (mf/provider muc/is-component?) {:value true}
|
||||
[:& root-shape-wrapper {:shape root-shape' :view-box vbox}]]]])))
|
||||
[:*
|
||||
[:> shape-container {:shape root-shape'}
|
||||
[:& (mf/provider muc/is-component?) {:value true}
|
||||
[:& root-shape-wrapper {:shape root-shape' :view-box vbox}]]]
|
||||
|
||||
(when show-grids?
|
||||
[:& empty-grids {:root-shape-id root-shape-id :objects objects}])]])))
|
||||
|
||||
(mf/defc component-svg-thumbnail
|
||||
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
||||
[{:keys [thumbnail-uri on-error show-grids?
|
||||
objects root-shape zoom] :or {zoom 1} :as props}]
|
||||
|
||||
(when root-shape
|
||||
(let [root-shape-id (:id root-shape)
|
||||
|
||||
vector
|
||||
(mf/use-memo
|
||||
(mf/deps (:x root-shape) (:y root-shape))
|
||||
(fn []
|
||||
(-> (gpt/point (:x root-shape) (:y root-shape))
|
||||
(gpt/negate))))
|
||||
|
||||
objects
|
||||
(mf/use-memo
|
||||
(mf/deps vector objects root-shape-id)
|
||||
(fn []
|
||||
(let [children-ids (cons root-shape-id (cfh/get-children-ids objects root-shape-id))
|
||||
update-fn #(update %1 %2 gsh/transform-shape (ctm/move-modifiers vector))]
|
||||
(reduce update-fn objects children-ids))))
|
||||
|
||||
root-shape' (get objects root-shape-id)
|
||||
|
||||
width (:width root-shape' 0)
|
||||
height (:height root-shape' 0)
|
||||
width-zoom (* (:width root-shape') zoom)
|
||||
height-zoom (* (:height root-shape') zoom)
|
||||
vbox (format-viewbox {:width width :height height})]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width (ust/format-precision width-zoom viewbox-decimal-precision)
|
||||
:height (ust/format-precision height-zoom viewbox-decimal-precision)
|
||||
:version "1.1"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:fill "none"}
|
||||
[:foreignObject {:x 0 :y 0 :width width :height height }
|
||||
[:img {:src thumbnail-uri
|
||||
:on-error on-error
|
||||
:loading "lazy"
|
||||
:decoding "async"}]]
|
||||
(when show-grids?
|
||||
[:& empty-grids {:root-shape-id root-shape-id :objects objects}])])))
|
||||
|
||||
(mf/defc object-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
["highlight.js" :as hljs]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.util.dom :as dom]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -19,8 +20,10 @@
|
|||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
block-ref (mf/use-ref)
|
||||
code (str/trim code)]
|
||||
(mf/with-effect [code type]
|
||||
(mf/with-effect
|
||||
[code type]
|
||||
(when-let [node (mf/ref-val block-ref)]
|
||||
(dom/set-data! node "highlighted" nil)
|
||||
(hljs/highlightElement node)))
|
||||
|
||||
(if new-css-system
|
||||
|
|
|
@ -21,6 +21,15 @@
|
|||
(let [percent-val (mth/precision (* value 100) precision)]
|
||||
(dm/str percent-val "%"))))))
|
||||
|
||||
(defn format-frs
|
||||
([value]
|
||||
(format-frs value nil))
|
||||
([value {:keys [precision] :or {precision 2}}]
|
||||
(let [value (if (string? value) (d/parse-double value) value)]
|
||||
(when (d/num? value)
|
||||
(let [value (mth/precision value precision)]
|
||||
(dm/str value "fr"))))))
|
||||
|
||||
(defn format-number
|
||||
([value]
|
||||
(format-number value nil))
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
(cleanup)
|
||||
(rx/push! global-drag-end nil)
|
||||
(when (fn? on-drop)
|
||||
(on-drop side drop-data))))
|
||||
(on-drop side drop-data event))))
|
||||
|
||||
on-drag-end
|
||||
(fn [event]
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
|
@ -693,8 +694,7 @@
|
|||
|
||||
objects (wsh/lookup-page-objects @st/state)
|
||||
children (->> (cfh/get-immediate-children objects frame-id)
|
||||
(remove :layout-item-absolute)
|
||||
(remove :hidden))
|
||||
(remove ctl/position-absolute?))
|
||||
|
||||
children-to-display (if (or (= :row-reverse saved-dir)
|
||||
(= :column-reverse saved-dir))
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[app.main.ui.context :as muc]
|
||||
[app.main.ui.shapes.attrs :as attrs]
|
||||
[app.main.ui.shapes.custom-stroke :refer [shape-fills shape-strokes]]
|
||||
[app.main.ui.shapes.grid-layout-viewer :refer [grid-layout-viewer]]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.object :as obj]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -165,7 +164,6 @@
|
|||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
childs (unchecked-get props "childs")
|
||||
is-component? (mf/use-ctx muc/is-component?)
|
||||
childs (cond-> childs
|
||||
(ctl/any-layout? shape)
|
||||
(cfh/sort-layout-children-z-index))]
|
||||
|
@ -175,9 +173,5 @@
|
|||
(for [item childs]
|
||||
(let [id (dm/get-prop item :id)]
|
||||
(when (some? id)
|
||||
[:& shape-wrapper {:key (dm/str id) :shape item}])))]
|
||||
|
||||
(when (and ^boolean is-component?
|
||||
^boolean (empty? childs))
|
||||
[:& grid-layout-viewer {:shape shape :childs childs}])])))
|
||||
[:& shape-wrapper {:key (dm/str id) :shape item}])))]])))
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[app.common.geom.shapes.grid-layout :as gsg]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc grid-cell-area-label
|
||||
|
@ -85,9 +84,8 @@
|
|||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
objects (unchecked-get props "objects")
|
||||
bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
|
||||
|
||||
children
|
||||
(->> (cfh/get-immediate-children objects (:id shape))
|
||||
(remove :hidden)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.viewer.inspect.left-sidebar
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
|
@ -15,7 +16,9 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.shape-icon :as si]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.layer-item :refer [layer-item-inner]]
|
||||
[app.main.ui.workspace.sidebar.layer-name :refer [layer-name]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
|
@ -28,43 +31,55 @@
|
|||
(l/derived st/state)))
|
||||
|
||||
(mf/defc layer-item
|
||||
[{:keys [item selected objects disable-collapse?] :as props}]
|
||||
(let [id (:id item)
|
||||
name (:name item)
|
||||
hidden? (:hidden item)
|
||||
touched? (-> item :touched seq boolean)
|
||||
[{:keys [item selected objects disable-collapse? depth component-child? hide-toggle?] :as props}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
id (:id item)
|
||||
name (:name item)
|
||||
hidden? (:hidden item)
|
||||
touched? (-> item :touched seq boolean)
|
||||
selected? (contains? selected id)
|
||||
item-ref (mf/use-ref nil)
|
||||
depth (+ depth 1)
|
||||
|
||||
file (mf/deref refs/viewer-file)
|
||||
components-v2 (dm/get-in file [:data :options :components-v2])
|
||||
main-instance? (if components-v2
|
||||
(ctk/main-instance? item)
|
||||
true)
|
||||
collapsed-iref (mf/use-memo
|
||||
(mf/deps id)
|
||||
(make-collapsed-iref id))
|
||||
file (mf/deref refs/viewer-file)
|
||||
components-v2 (dm/get-in file [:data :options :components-v2])
|
||||
|
||||
main-instance?
|
||||
(if components-v2
|
||||
(ctk/main-instance? item)
|
||||
true)
|
||||
|
||||
component-tree? (or component-child? (:component-root item))
|
||||
|
||||
collapsed-iref
|
||||
(mf/use-memo
|
||||
(mf/deps id)
|
||||
(make-collapsed-iref id))
|
||||
|
||||
expanded? (not (mf/deref collapsed-iref))
|
||||
absolute? (ctl/layout-absolute? item)
|
||||
absolute? (ctl/item-absolute? item)
|
||||
|
||||
toggle-collapse
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dv/toggle-collapse id)))
|
||||
(mf/use-callback
|
||||
(mf/deps id)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dv/toggle-collapse id))))
|
||||
|
||||
select-shape
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [id (:id item)]
|
||||
(cond
|
||||
(kbd/mod? event)
|
||||
(st/emit! (dv/toggle-selection id))
|
||||
(mf/use-callback
|
||||
(mf/deps id)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(cond
|
||||
(kbd/mod? event)
|
||||
(st/emit! (dv/toggle-selection id))
|
||||
|
||||
(kbd/shift? event)
|
||||
(st/emit! (dv/shift-select-to id))
|
||||
(kbd/shift? event)
|
||||
(st/emit! (dv/shift-select-to id))
|
||||
|
||||
:else
|
||||
(st/emit! (dv/select-shape id)))))]
|
||||
:else
|
||||
(st/emit! (dv/select-shape id)))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps selected)
|
||||
|
@ -72,55 +87,102 @@
|
|||
(when (and (= (count selected) 1) selected?)
|
||||
(dom/scroll-into-view-if-needed! (mf/ref-val item-ref) true))))
|
||||
|
||||
[:li {:ref item-ref
|
||||
:class (dom/classnames
|
||||
:component (not (nil? (:component-id item)))
|
||||
:masked (:masked-group item)
|
||||
:selected selected?)}
|
||||
(if new-css-system
|
||||
[:& layer-item-inner
|
||||
{:ref item-ref
|
||||
:item item
|
||||
:depth depth
|
||||
:read-only? true
|
||||
:highlighted? false
|
||||
:selected? selected?
|
||||
:component-tree? component-tree?
|
||||
:hidden? hidden?
|
||||
:filtered? false
|
||||
:expanded? expanded?
|
||||
:hide-toggle? hide-toggle?
|
||||
:on-select-shape select-shape
|
||||
:on-toggle-collapse toggle-collapse}
|
||||
|
||||
[:div.element-list-body {:class (dom/classnames :selected selected?
|
||||
:icon-layer (= (:type item) :icon))
|
||||
:on-click select-shape}
|
||||
[:div.icon
|
||||
(when absolute?
|
||||
[:div.absolute i/position-absolute])
|
||||
[:& si/element-icon {:shape item :main-instance? main-instance?}]]
|
||||
[:& layer-name {:shape-id id
|
||||
:shape-name name
|
||||
:shape-touched? touched?
|
||||
:hidden? hidden?
|
||||
:selected? selected?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:disabled-double-click true}]
|
||||
(when (and (:shapes item) expanded?)
|
||||
[:div {:class (stl/css-case
|
||||
:element-children true
|
||||
:parent-selected selected?)}
|
||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key (dm/str id)
|
||||
:depth depth
|
||||
:component-child? component-tree?}]))])]
|
||||
|
||||
(when (and (not disable-collapse?) (:shapes item))
|
||||
[:span.toggle-content
|
||||
{:on-click toggle-collapse
|
||||
:class (when expanded? "inverse")}
|
||||
i/arrow-slide])]
|
||||
;; OLD
|
||||
[:li {:ref item-ref
|
||||
:class (dom/classnames
|
||||
:component (not (nil? (:component-id item)))
|
||||
:masked (:masked-group item)
|
||||
:selected selected?)}
|
||||
|
||||
(when (and (:shapes item) expanded?)
|
||||
[:ul.element-children
|
||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key (:id item)}]))])]))
|
||||
[:div.element-list-body {:class (dom/classnames :selected selected?
|
||||
:icon-layer (= (:type item) :icon))
|
||||
:on-click select-shape}
|
||||
[:div.icon
|
||||
(when absolute?
|
||||
[:div.absolute i/position-absolute])
|
||||
[:& si/element-icon {:shape item :main-instance? main-instance?}]]
|
||||
[:& layer-name {:shape-id id
|
||||
:shape-name name
|
||||
:shape-touched? touched?
|
||||
:hidden? hidden?
|
||||
:selected? selected?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:disabled-double-click true}]
|
||||
|
||||
(when (and (not disable-collapse?) (:shapes item))
|
||||
[:span.toggle-content
|
||||
{:on-click toggle-collapse
|
||||
:class (when expanded? "inverse")}
|
||||
i/arrow-slide])]
|
||||
|
||||
(when (and (:shapes item) expanded?)
|
||||
[:ul.element-children
|
||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key (:id item)}]))])])))
|
||||
|
||||
(mf/defc left-sidebar
|
||||
[{:keys [frame page local]}]
|
||||
(let [selected (:selected local)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
selected (:selected local)
|
||||
objects (:objects page)]
|
||||
|
||||
[:aside.settings-bar.settings-bar-left
|
||||
[:div.settings-bar-inside
|
||||
[:ul.element-list
|
||||
[:& layer-item
|
||||
{:item frame
|
||||
:selected selected
|
||||
:index 0
|
||||
:objects objects
|
||||
:disable-collapse? true}]]]]))
|
||||
(if new-css-system
|
||||
[:aside {:class (stl/css :settings-bar-left)}
|
||||
[:div {:class (stl/css :settings-bar-inside)}
|
||||
[:div {:class (stl/css :element-list)}
|
||||
[:& layer-item
|
||||
{:item frame
|
||||
:selected selected
|
||||
:index 0
|
||||
:objects objects
|
||||
:sortable? false
|
||||
:filtered? false
|
||||
:depth -2
|
||||
:hide-toggle? true}]]]]
|
||||
|
||||
[:aside.settings-bar.settings-bar-left
|
||||
[:div.settings-bar-inside
|
||||
[:ul.element-list
|
||||
[:& layer-item
|
||||
{:item frame
|
||||
:selected selected
|
||||
:index 0
|
||||
:objects objects
|
||||
:disable-collapse? true}]]]])))
|
||||
|
|
22
frontend/src/app/main/ui/viewer/inspect/left_sidebar.scss
Normal file
22
frontend/src/app/main/ui/viewer/inspect/left_sidebar.scss
Normal file
|
@ -0,0 +1,22 @@
|
|||
// 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
|
||||
|
||||
@use "common/refactor/common-refactor.scss" as *;
|
||||
|
||||
.settings-bar-left {
|
||||
background-color: $db-primary;
|
||||
height: 100%;
|
||||
width: $s-256;
|
||||
}
|
||||
|
||||
.settings-bar-inside {
|
||||
display: grid;
|
||||
grid-template-columns: 100%;
|
||||
grid-template-rows: 100%;
|
||||
height: calc(100% - $s-2);
|
||||
overflow-y: auto;
|
||||
padding-top: $s-8;
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.render :refer [component-svg]]
|
||||
[app.main.render :refer [component-svg component-svg-thumbnail]]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
|
||||
|
@ -283,18 +283,26 @@
|
|||
{::mf/wrap-props false}
|
||||
[{:keys [file-id root-shape component container]}]
|
||||
(let [retry (mf/use-state 0)
|
||||
thumbnail-uri (get-component-thumbnail-uri file-id component)]
|
||||
(if (some? thumbnail-uri)
|
||||
[:img {:src thumbnail-uri
|
||||
:on-error (fn []
|
||||
(when (@retry < 3)
|
||||
(inc retry)))
|
||||
:loading "lazy"
|
||||
:decoding "async"
|
||||
:class (dom/classnames (css :thumbnail) true)}]
|
||||
[:& component-svg {:root-shape root-shape
|
||||
:objects (:objects container)}])))
|
||||
thumbnail-uri (get-component-thumbnail-uri file-id component)
|
||||
handle-error
|
||||
(mf/use-fn
|
||||
(mf/deps @retry)
|
||||
(fn []
|
||||
(when (@retry < 3)
|
||||
(inc retry))))]
|
||||
|
||||
(if (some? thumbnail-uri)
|
||||
[:& component-svg-thumbnail
|
||||
{:thumbnail-uri thumbnail-uri
|
||||
:on-error handle-error
|
||||
:root-shape root-shape
|
||||
:objects (:objects container)
|
||||
:show-grids? true}]
|
||||
|
||||
[:& component-svg
|
||||
{:root-shape root-shape
|
||||
:objects (:objects container)
|
||||
:show-grids? true}])))
|
||||
|
||||
(defn generate-components-menu-entries
|
||||
[shapes components-v2]
|
||||
|
|
|
@ -32,6 +32,129 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc layer-item-inner
|
||||
{::mf/wrap-props false
|
||||
::mf/forward-ref true}
|
||||
[{:keys [item depth parent-size name-ref children
|
||||
;; Flags
|
||||
read-only? highlighted? selected? component-tree?
|
||||
filtered? expanded? dnd-over? dnd-over-top? dnd-over-bot? hide-toggle?
|
||||
;; Callbacks
|
||||
on-select-shape on-context-menu on-pointer-enter on-pointer-leave on-zoom-to-selected
|
||||
on-toggle-collapse on-enable-drag on-disable-drag on-toggle-visibility on-toggle-blocking]}
|
||||
dref]
|
||||
|
||||
(let [id (:id item)
|
||||
name (:name item)
|
||||
blocked? (:blocked item)
|
||||
hidden? (:hidden item)
|
||||
has-shapes? (-> item :shapes seq boolean)
|
||||
touched? (-> item :touched seq boolean)
|
||||
parent-board? (and (cfh/frame-shape? item)
|
||||
(= uuid/zero (:parent-id item)))
|
||||
absolute? (ctl/item-absolute? item)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
main-instance? (or (not components-v2) (:main-instance item))]
|
||||
[:*
|
||||
[:div {:id id
|
||||
:ref dref
|
||||
:on-click on-select-shape
|
||||
:on-context-menu on-context-menu
|
||||
:class (stl/css-case
|
||||
:layer-row true
|
||||
:highlight highlighted?
|
||||
:component (some? (:component-id item))
|
||||
:masked (:masked-group item)
|
||||
:selected selected?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:type-bool (cfh/bool-shape? item)
|
||||
:type-comp component-tree?
|
||||
:hidden hidden?
|
||||
:dnd-over dnd-over?
|
||||
:dnd-over-top dnd-over-top?
|
||||
:dnd-over-bot dnd-over-bot?
|
||||
:root-board parent-board?)}
|
||||
[:span {:class (stl/css-case
|
||||
:tab-indentation true
|
||||
:filtered filtered?)
|
||||
:style {"--depth" depth}}]
|
||||
[:div {:class (stl/css-case
|
||||
:element-list-body true
|
||||
:filtered filtered?
|
||||
:selected selected?
|
||||
:icon-layer (= (:type item) :icon))
|
||||
:style {"--depth" depth}
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-double-click dom/stop-propagation}
|
||||
|
||||
(if (< 0 (count (:shapes item)))
|
||||
[:div {:class (stl/css :button-content)}
|
||||
(when (and (not hide-toggle?) (not filtered?))
|
||||
[:button {:class (stl/css-case
|
||||
:toggle-content true
|
||||
:inverse expanded?)
|
||||
:on-click on-toggle-collapse}
|
||||
i/arrow-refactor])
|
||||
|
||||
[:div {:class (stl/css :icon-shape)
|
||||
:on-double-click on-zoom-to-selected}
|
||||
(when absolute?
|
||||
[:div {:class (stl/css :absolute)}])
|
||||
|
||||
[:& sic/element-icon-refactor
|
||||
{:shape item
|
||||
:main-instance? main-instance?}]]]
|
||||
|
||||
[:div {:class (stl/css :button-content)}
|
||||
(when (not ^boolean filtered?)
|
||||
[:span {:class (stl/css :toggle-content)}])
|
||||
[:div {:class (stl/css :icon-shape)
|
||||
:on-double-click on-zoom-to-selected}
|
||||
(when ^boolean absolute?
|
||||
[:div {:class (stl/css :absolute)}])
|
||||
[:& sic/element-icon-refactor
|
||||
{:shape item
|
||||
:main-instance? main-instance?}]]])
|
||||
|
||||
[:& layer-name {:ref name-ref
|
||||
:shape-id id
|
||||
:shape-name name
|
||||
:shape-touched? touched?
|
||||
:disabled-double-click read-only?
|
||||
:on-start-edit on-disable-drag
|
||||
:on-stop-edit on-enable-drag
|
||||
:depth depth
|
||||
:parent-size parent-size
|
||||
:selected? selected?
|
||||
:type-comp component-tree?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:hidden? hidden?}]
|
||||
(when (not read-only?)
|
||||
[:div {:class (stl/css-case
|
||||
:element-actions true
|
||||
:is-parent has-shapes?
|
||||
:selected hidden?
|
||||
:selected blocked?)}
|
||||
[:button {:class (stl/css-case
|
||||
:toggle-element true
|
||||
:selected hidden?)
|
||||
:title (if hidden?
|
||||
(tr "workspace.shape.menu.show")
|
||||
(tr "workspace.shape.menu.hide"))
|
||||
:on-click on-toggle-visibility}
|
||||
(if ^boolean hidden? i/hide-refactor i/shown-refactor)]
|
||||
[:button {:class (stl/css-case
|
||||
:block-element true
|
||||
:selected blocked?)
|
||||
:title (if (:blocked item)
|
||||
(tr "workspace.shape.menu.unlock")
|
||||
(tr "workspace.shape.menu.lock"))
|
||||
:on-click on-toggle-blocking}
|
||||
(if ^boolean blocked? i/lock-refactor i/unlock-refactor)]])]]
|
||||
|
||||
children]))
|
||||
|
||||
(mf/defc layer-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [index item selected objects sortable? filtered? depth parent-size component-child? highlighted]}]
|
||||
|
@ -53,9 +176,10 @@
|
|||
|
||||
selected? (contains? selected id)
|
||||
highlighted? (contains? highlighted id)
|
||||
|
||||
container? (or (cfh/frame-shape? item)
|
||||
(cfh/group-shape? item))
|
||||
absolute? (ctl/layout-absolute? item)
|
||||
absolute? (ctl/item-absolute? item)
|
||||
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
@ -210,113 +334,44 @@
|
|||
(let [scroll-to @scroll-to-middle?]
|
||||
(ts/schedule
|
||||
100
|
||||
#(let [scroll-distance-ratio (dom/get-scroll-distance-ratio node scroll-node)
|
||||
scroll-behavior (if (> scroll-distance-ratio 1) "instant" "smooth")]
|
||||
(if scroll-to
|
||||
(dom/scroll-into-view! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
|
||||
(do
|
||||
(dom/scroll-into-view-if-needed! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
|
||||
(reset! scroll-to-middle? true)))))))]
|
||||
#(when (and node scroll-node)
|
||||
(let [scroll-distance-ratio (dom/get-scroll-distance-ratio node scroll-node)
|
||||
scroll-behavior (if (> scroll-distance-ratio 1) "instant" "smooth")]
|
||||
(if scroll-to
|
||||
(dom/scroll-into-view! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
|
||||
(do
|
||||
(dom/scroll-into-view-if-needed! first-child-node #js {:block "center" :behavior scroll-behavior :inline "start"})
|
||||
(reset! scroll-to-middle? true))))))))]
|
||||
|
||||
#(when (some? subid)
|
||||
(rx/dispose! subid))))
|
||||
|
||||
(if new-css-system
|
||||
[:*
|
||||
[:div {:on-context-menu on-context-menu
|
||||
:ref dref
|
||||
:on-click select-shape
|
||||
:id id
|
||||
:class (stl/css-case
|
||||
:layer-row true
|
||||
:component (some? (:component-id item))
|
||||
:masked (:masked-group item)
|
||||
:selected selected?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:type-bool (cfh/bool-shape? item)
|
||||
:type-comp component-tree?
|
||||
:hidden hidden?
|
||||
:dnd-over (= (:over dprops) :center)
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot)
|
||||
:root-board parent-board?)}
|
||||
[:span {:class (stl/css-case
|
||||
:tab-indentation true
|
||||
:filtered filtered?)
|
||||
:style {"--depth" depth}}]
|
||||
[:div {:class (stl/css-case
|
||||
:element-list-body true
|
||||
:filtered filtered?
|
||||
:selected selected?
|
||||
:icon-layer (= (:type item) :icon))
|
||||
:style {"--depth" depth}
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-double-click dom/stop-propagation}
|
||||
|
||||
(if (< 0 (count (:shapes item)))
|
||||
[:div {:class (stl/css :button-content)}
|
||||
(when (not filtered?)
|
||||
[:button {:class (stl/css-case
|
||||
:toggle-content true
|
||||
:inverse expanded?)
|
||||
:on-click toggle-collapse}
|
||||
i/arrow-refactor])
|
||||
|
||||
[:div {:class (stl/css :icon-shape)
|
||||
:on-double-click zoom-to-selected}
|
||||
(when absolute?
|
||||
[:div {:class (stl/css :absolute)}])
|
||||
|
||||
[:& sic/element-icon-refactor
|
||||
{:shape item
|
||||
:main-instance? main-instance?}]]]
|
||||
|
||||
[:div {:class (stl/css :button-content)}
|
||||
(when (not ^boolean filtered?)
|
||||
[:span {:class (stl/css :toggle-content)}])
|
||||
[:div {:class (stl/css :icon-shape)
|
||||
:on-double-click zoom-to-selected}
|
||||
(when ^boolean absolute?
|
||||
[:div {:class (stl/css :absolute)}])
|
||||
[:& sic/element-icon-refactor
|
||||
{:shape item
|
||||
:main-instance? main-instance?}]]])
|
||||
|
||||
[:& layer-name {:ref ref
|
||||
:shape-id id
|
||||
:shape-name name
|
||||
:shape-touched? touched?
|
||||
:disabled-double-click read-only?
|
||||
:on-start-edit disable-drag
|
||||
:on-stop-edit enable-drag
|
||||
:depth depth
|
||||
:parent-size parent-size
|
||||
:selected? selected?
|
||||
:type-comp component-tree?
|
||||
:type-frame (cfh/frame-shape? item)
|
||||
:hidden? hidden?}]
|
||||
[:div {:class (stl/css-case
|
||||
:element-actions true
|
||||
:is-parent has-shapes?
|
||||
:selected hidden?
|
||||
:selected blocked?)}
|
||||
[:button {:class (stl/css-case
|
||||
:toggle-element true
|
||||
:selected hidden?)
|
||||
:title (if hidden?
|
||||
(tr "workspace.shape.menu.show")
|
||||
(tr "workspace.shape.menu.hide"))
|
||||
:on-click toggle-visibility}
|
||||
(if ^boolean hidden? i/hide-refactor i/shown-refactor)]
|
||||
[:button {:class (stl/css-case
|
||||
:block-element true
|
||||
:selected blocked?)
|
||||
:title (if (:blocked item)
|
||||
(tr "workspace.shape.menu.unlock")
|
||||
(tr "workspace.shape.menu.lock"))
|
||||
:on-click toggle-blocking}
|
||||
(if ^boolean blocked? i/lock-refactor i/unlock-refactor)]]]]
|
||||
[:& layer-item-inner
|
||||
{:ref dref
|
||||
:item item
|
||||
:depth depth
|
||||
:parent-size parent-size
|
||||
:name-ref ref
|
||||
:read-only? read-only?
|
||||
:highlighted? highlighted?
|
||||
:selected? selected?
|
||||
:component-tree? component-tree?
|
||||
:filtered? filtered?
|
||||
:expanded? expanded?
|
||||
:dnd-over? (= (:over dprops) :center)
|
||||
:dnd-over-top? (= (:over dprops) :top)
|
||||
:dnd-over-bot? (= (:over dprops) :bot)
|
||||
:on-select-shape select-shape
|
||||
:on-context-menu on-context-menu
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-zoom-to-selected zoom-to-selected
|
||||
:on-toggle-collapse toggle-collapse
|
||||
:on-enable-drag enable-drag
|
||||
:on-disable-drag disable-drag
|
||||
:on-toggle-visibility toggle-visibility
|
||||
:on-toggle-blocking toggle-blocking}
|
||||
|
||||
(when (and (:shapes item) expanded?)
|
||||
[:div {:class (stl/css-case
|
||||
|
@ -324,11 +379,11 @@
|
|||
:parent-selected selected?
|
||||
:sticky-children parent-board?)
|
||||
:data-id (when ^boolean parent-board? id)}
|
||||
|
||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:highlighted highlighted
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
|
|
|
@ -12,478 +12,242 @@
|
|||
align-items: center;
|
||||
width: 100%;
|
||||
background-color: var(--layer-row-background-color);
|
||||
border: 2px solid transparent;
|
||||
|
||||
.element-list-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
width: calc(100% - (var(--depth) * var(--layer-indentation-size)));
|
||||
padding-right: $s-12;
|
||||
cursor: pointer;
|
||||
|
||||
&.filtered {
|
||||
width: calc(100% - $s-12);
|
||||
}
|
||||
.button-content {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
.toggle-content {
|
||||
@include buttonStyle;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0 4px 0 8px;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
&.inverse {
|
||||
svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.icon-shape {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
width: $s-16;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0 $s-8 0 $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute;
|
||||
background-color: var(--layer-row-foreground-color);
|
||||
opacity: $op-4;
|
||||
width: $s-12;
|
||||
height: $s-12;
|
||||
border-radius: $br-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
display: none;
|
||||
height: 100%;
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
margin: 0;
|
||||
display: none;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
display: flex;
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
display: flex;
|
||||
opacity: $op-0;
|
||||
&.selected {
|
||||
opacity: $op-10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-children {
|
||||
width: 100%;
|
||||
ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
&.parent-selected {
|
||||
.layer-row {
|
||||
background-color: var(--layer-child-row-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.hidden {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
svg {
|
||||
opacity: $op-7;
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.absolute {
|
||||
opacity: $op-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
opacity: $op-7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.highlight,
|
||||
&:hover {
|
||||
--context-hover-color: var(--layer-row-foreground-color-hover);
|
||||
--context-hover-opacity: $op-10;
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
color: var(--layer-row-foreground-color-hover);
|
||||
box-shadow: $s-16 0px 0px 0px var(--layer-row-background-color-hover);
|
||||
&.hidden {
|
||||
opacity: $op-10;
|
||||
}
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
svg {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
opacity: $op-10;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
& .absolute {
|
||||
opacity: $op-4;
|
||||
background-color: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
display: flex;
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
display: flex;
|
||||
svg {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
opacity: $op-10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-children {
|
||||
.layer-row {
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color-hover);
|
||||
&:hover {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
box-shadow: $s-16 0px 0px 0px var(--layer-row-background-color-selected);
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
.absolute {
|
||||
background-color: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
display: flex;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
display: flex;
|
||||
opacity: $op-10;
|
||||
&.selected {
|
||||
opacity: $op-10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-children {
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color-selected);
|
||||
&:hover {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
}
|
||||
}
|
||||
&.type-comp {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
.absolute {
|
||||
background-color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-children {
|
||||
color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
&.hidden {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.icon-shape {
|
||||
opacity: $op-7;
|
||||
.absolute {
|
||||
opacity: $op-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
opacity: $op-7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
opacity: $op-10;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
opacity: $op-10;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
& .absolute {
|
||||
opacity: $op-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected.highlight,
|
||||
&.selected:hover {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
}
|
||||
&.type-comp.selected {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
.absolute {
|
||||
background-color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-children {
|
||||
color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
&.hidden {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.icon-shape {
|
||||
opacity: $op-7;
|
||||
.absolute {
|
||||
opacity: $op-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
opacity: $op-7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
opacity: $op-10;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
opacity: $op-10;
|
||||
& .absolute {
|
||||
opacity: $op-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parent-selected & {
|
||||
background-color: var(--layer-child-row-background-color);
|
||||
}
|
||||
&:global(.sticky) {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
z-index: 3;
|
||||
|
||||
.parent-selected &.highlight,
|
||||
.parent-selected &:hover {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
}
|
||||
|
||||
&.dnd-over-bot {
|
||||
border-bottom: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
&.dnd-over-top {
|
||||
border-bottom: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
&.dnd-over {
|
||||
border: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.parent-selected .layer-row {
|
||||
background-color: var(--layer-child-row-background-color);
|
||||
&:hover {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
&.hidden {
|
||||
|
||||
.element-children {
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
}
|
||||
.layer-row.type-comp & {
|
||||
color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
.layer-row.selected & {
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
|
||||
.element-list-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
width: calc(100% - (var(--depth) * var(--layer-indentation-size)));
|
||||
padding-right: $s-12;
|
||||
cursor: pointer;
|
||||
|
||||
&.filtered {
|
||||
width: calc(100% - $s-12);
|
||||
}
|
||||
}
|
||||
|
||||
.element-actions {
|
||||
display: none;
|
||||
height: 100%;
|
||||
&.selected {
|
||||
display: flex;
|
||||
}
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.button-content {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-shape {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
width: $s-16;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0 $s-8 0 $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
|
||||
.layer-row.selected & {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
.layer-row.type-comp & {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
.inverse & {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.layer-row.hidden & {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
opacity: $op-10;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute;
|
||||
background-color: var(--layer-row-foreground-color);
|
||||
opacity: $op-4;
|
||||
width: $s-12;
|
||||
height: $s-12;
|
||||
border-radius: $br-2;
|
||||
|
||||
.layer-row.hidden & {
|
||||
opacity: $op-1;
|
||||
}
|
||||
.layer-row.type-comp & {
|
||||
background-color: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
opacity: $op-4;
|
||||
background-color: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
.layer-row.selected & {
|
||||
background-color: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-content {
|
||||
@include buttonStyle;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0 4px 0 8px;
|
||||
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
|
||||
.layer-row.hidden & {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.layer-row.selected & {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
.layer-row.type-comp & {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.layer-row.selected & {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
}
|
||||
&.inverse svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
margin: 0;
|
||||
display: none;
|
||||
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
|
||||
.layer-row.hidden & {
|
||||
opacity: $op-7;
|
||||
}
|
||||
.type-comp & {
|
||||
stroke: var(--layer-row-component-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
.element-actions.selected & {
|
||||
display: flex;
|
||||
opacity: $op-0;
|
||||
|
||||
&.selected {
|
||||
opacity: $op-10;
|
||||
}
|
||||
.element-list-body {
|
||||
.button-content {
|
||||
.toggle-content {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
.icon-shape {
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
.absolute {
|
||||
background-color: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-actions {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
display: flex;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
.toggle-element,
|
||||
.block-element {
|
||||
opacity: $op-10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layer-row.highlight &,
|
||||
.layer-row:hover & {
|
||||
display: flex;
|
||||
svg {
|
||||
opacity: $op-10;
|
||||
stroke: var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
.element-children :global(.layer-row) {
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color-hover);
|
||||
&:hover {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
}
|
||||
}
|
||||
.layer-row.selected & {
|
||||
display: flex;
|
||||
svg {
|
||||
stroke: var(--layer-row-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global(.sticky) {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.tab-indentation {
|
||||
display: block;
|
||||
height: $s-16;
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
highlighted (hooks/use-equal-memo highlighted)
|
||||
root (get objects uuid/zero)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
[:ul
|
||||
[:div
|
||||
{:class (stl/css new-css-system :element-list)}
|
||||
[:& hooks/sortable-container {}
|
||||
(for [[index id] (reverse (d/enumerate (:shapes root)))]
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -951,20 +953,20 @@
|
|||
(defn manage-values [{:keys [value type]}]
|
||||
(case type
|
||||
:auto "auto"
|
||||
:percent (dm/str value "%")
|
||||
:flex (dm/str value "fr")
|
||||
:fixed (dm/str value "px")
|
||||
:percent (fmt/format-percent value)
|
||||
:flex (fmt/format-frs value)
|
||||
:fixed (fmt/format-pixels 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]}]
|
||||
[{:keys [is-col? type index column set-column-value set-column-type remove-element reorder-track hover-track on-select-track]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
drop-track
|
||||
(mf/use-fn
|
||||
(mf/deps type reorder-track index)
|
||||
(fn [drop-position data]
|
||||
(reorder-track type (:index data) (if (= :top drop-position) (dec index) index))))
|
||||
(fn [drop-position data event]
|
||||
(reorder-track type (:index data) (if (= :top drop-position) (dec index) index) (kbd/mod? event))))
|
||||
|
||||
pointer-enter
|
||||
(mf/use-fn
|
||||
|
@ -978,6 +980,13 @@
|
|||
(fn []
|
||||
(hover-track type index false)))
|
||||
|
||||
handle-select-track
|
||||
(mf/use-fn
|
||||
(mf/deps on-select-track type index)
|
||||
(fn []
|
||||
(when on-select-track
|
||||
(on-select-track type index))))
|
||||
|
||||
[dprops dref]
|
||||
(h/use-sortable
|
||||
:data-type "penpot/grid-track"
|
||||
|
@ -998,7 +1007,8 @@
|
|||
:on-pointer-leave pointer-leave}
|
||||
|
||||
[:div {:class (stl/css :track-info-container)}
|
||||
[:div {:class (stl/css :track-info-dir-icon)}
|
||||
[:div {:class (stl/css :track-info-dir-icon)
|
||||
:on-click handle-select-track}
|
||||
(if is-col? i/flex-vertical-refactor i/flex-horizontal-refactor)]
|
||||
|
||||
[:div {:class (stl/css :track-info-value)}
|
||||
|
@ -1057,7 +1067,8 @@
|
|||
i/minus]])))
|
||||
|
||||
(mf/defc grid-columns-row
|
||||
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type remove-element reorder-track hover-track] :as props}]
|
||||
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type
|
||||
remove-element reorder-track hover-track on-select-track] :as props}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
column-num (count column-values)
|
||||
|
@ -1098,7 +1109,8 @@
|
|||
:set-column-type set-column-type
|
||||
:remove-element remove-element
|
||||
:reorder-track reorder-track
|
||||
:hover-track hover-track}])]])]
|
||||
:hover-track hover-track
|
||||
:on-select-track on-select-track}])]])]
|
||||
|
||||
[:div.grid-columns
|
||||
[:div.grid-columns-header
|
||||
|
@ -1119,7 +1131,8 @@
|
|||
:set-column-type set-column-type
|
||||
:remove-element remove-element
|
||||
:reorder-track reorder-track
|
||||
:hover-track hover-track}])]])])))
|
||||
:hover-track hover-track
|
||||
:on-select-track on-select-track}])]])])))
|
||||
|
||||
;; LAYOUT COMPONENT
|
||||
|
||||
|
@ -1364,12 +1377,7 @@
|
|||
handle-open-grid-help
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dom/open-new-window cf/grid-help-uri))))
|
||||
|
||||
handle-locate-grid
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dwge/locate-board (first ids)))))]
|
||||
(st/emit! (dom/open-new-window cf/grid-help-uri))))]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
|
@ -1383,7 +1391,18 @@
|
|||
[:div {:class (stl/css :title-actions)}
|
||||
[:button {:class (stl/css :remove-layout)
|
||||
:on-click on-remove-layout}
|
||||
i/remove-refactor]]
|
||||
i/remove-refactor]
|
||||
|
||||
(when ^boolean grid-enabled?
|
||||
[:*
|
||||
[:button {:class (stl/css :add-layout)
|
||||
:on-click handle-show-layout-dropdown}
|
||||
i/menu-refactor]
|
||||
|
||||
[:& dropdown {:show show-layout-dropdown? :on-close handle-close-layout-options}
|
||||
[:div {:class (stl/css :layout-options)}
|
||||
[:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
|
||||
[:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]])]
|
||||
|
||||
[:div {:class (stl/css :title-actions)}
|
||||
(if ^boolean grid-enabled?
|
||||
|
@ -1469,11 +1488,7 @@
|
|||
:set-justify set-justify-grid}]
|
||||
[:& justify-grid-row {:is-col? false
|
||||
:justify-items grid-justify-content-row
|
||||
:set-justify set-justify-grid}]
|
||||
|
||||
[:button {:on-click handle-locate-grid
|
||||
:class (stl/css :locate-button)}
|
||||
i/locate-refactor]]]
|
||||
:set-justify set-justify-grid}]]]
|
||||
nil)))]
|
||||
|
||||
[:div.element-set
|
||||
|
@ -1686,8 +1701,8 @@
|
|||
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))))
|
||||
(fn [type from-index to-index move-content?]
|
||||
(st/emit! (dwsl/reorder-layout-track ids type from-index to-index move-content?))))
|
||||
|
||||
hover-track
|
||||
(mf/use-fn
|
||||
|
@ -1695,6 +1710,12 @@
|
|||
(fn [type index hover?]
|
||||
(st/emit! (dwsl/hover-layout-track ids type index hover?))))
|
||||
|
||||
handle-select-track
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [type index]
|
||||
(st/emit! (dwge/select-track-cells (first ids) type index))))
|
||||
|
||||
set-column-value
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
|
@ -1720,7 +1741,7 @@
|
|||
handle-locate-grid
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dwge/locate-board (first ids))))) ]
|
||||
(st/emit! (dwge/locate-board (first ids)))))]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :grid-layout-menu)}
|
||||
|
@ -1767,7 +1788,8 @@
|
|||
:set-column-type set-column-type
|
||||
:remove-element remove-element
|
||||
:reorder-track reorder-track
|
||||
:hover-track hover-track}]
|
||||
:hover-track hover-track
|
||||
:on-select-track handle-select-track}]
|
||||
|
||||
[:& grid-columns-row {:is-col? false
|
||||
:expanded? @grid-rows-open?
|
||||
|
@ -1778,7 +1800,8 @@
|
|||
:set-column-type set-column-type
|
||||
:remove-element remove-element
|
||||
:reorder-track reorder-track
|
||||
:hover-track hover-track}]]
|
||||
:hover-track hover-track
|
||||
:on-select-track handle-select-track}]]
|
||||
[:div {:class (stl/css :row)}
|
||||
[:& gap-section {:gap-selected? gap-selected?
|
||||
:on-change set-gap
|
||||
|
|
|
@ -222,15 +222,18 @@
|
|||
}
|
||||
|
||||
.track-info-dir-icon {
|
||||
cursor: pointer;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
padding-left: $s-12;
|
||||
|
||||
padding: 0 $s-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
height: 100%;
|
||||
}
|
||||
&:hover svg {
|
||||
stroke: var(--icon-foreground-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.track-info-value {
|
||||
|
|
|
@ -378,7 +378,7 @@
|
|||
selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
selection-parents (mf/deref selection-parents-ref)
|
||||
|
||||
is-absolute? (:layout-item-absolute values)
|
||||
is-absolute? (:layout-item-absolute values)
|
||||
|
||||
is-col? (every? ctl/col? selection-parents)
|
||||
|
||||
|
@ -510,7 +510,7 @@
|
|||
(when open?
|
||||
[:div {:class (stl/css :flex-element-menu)}
|
||||
[:div {:class (stl/css :row)}
|
||||
(when is-flex-parent?
|
||||
(when (or is-layout-child? is-absolute?)
|
||||
[:div {:class (stl/css :position-options)}
|
||||
[:& radio-buttons {:selected (if is-absolute? "absolute" "static")
|
||||
:on-change on-change-position
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
selection-parents (mf/deref selection-parents-ref)
|
||||
|
||||
flex-child? (->> selection-parents (some ctl/flex-layout?))
|
||||
absolute? (ctl/layout-absolute? shape)
|
||||
absolute? (ctl/item-absolute? shape)
|
||||
flex-container? (ctl/flex-layout? shape)
|
||||
flex-auto-width? (ctl/auto-width? shape)
|
||||
flex-fill-width? (ctl/fill-width? shape)
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-container? (ctl/any-layout? shape)
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
is-grid-parent* (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent*)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids* (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids*)]
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
is-layout-child-absolute? (ctl/layout-absolute? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
|
|
|
@ -664,6 +664,7 @@
|
|||
(let [target (-> event dom/get-target)
|
||||
value (-> target dom/get-input-value str/upper)
|
||||
value-int (d/parse-integer value)
|
||||
value-int (when value-int (max 0 value-int))
|
||||
|
||||
[track-type value]
|
||||
(cond
|
||||
|
|
|
@ -61,6 +61,6 @@
|
|||
[objects shape]
|
||||
;; Layout children with a transform should be wrapped
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape))
|
||||
(not (ctl/position-absolute? shape))
|
||||
(not (gmt/unit? (:transform shape)))))
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ body {
|
|||
[:height height]]
|
||||
|
||||
(or (not (ctl/any-layout-immediate-child? objects shape))
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(not (ctl/position-absolute? shape)))
|
||||
(conj [:position "relative"])))))
|
||||
|
||||
(defn shape->wrapper-child-css-properties
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
[_ shape objects]
|
||||
(cond
|
||||
(or (and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape))
|
||||
(not (ctl/position-absolute? shape))
|
||||
(or (cfh/group-like-shape? shape)
|
||||
(cfh/frame-shape? shape)
|
||||
(cgc/svg-markup? shape)))
|
||||
|
@ -39,7 +39,7 @@
|
|||
:relative
|
||||
|
||||
(and (ctl/any-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(not (ctl/position-absolute? shape)))
|
||||
nil
|
||||
|
||||
:else
|
||||
|
@ -50,7 +50,7 @@
|
|||
|
||||
(when (and (not (cfh/root-frame? shape))
|
||||
(or (not (ctl/any-layout-immediate-child? objects shape))
|
||||
(ctl/layout-absolute? shape)))
|
||||
(ctl/position-absolute? shape)))
|
||||
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
|
||||
|
@ -291,7 +291,7 @@
|
|||
(defn get-grid-coord
|
||||
[shape objects prop span-prop]
|
||||
(when (and (ctl/grid-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(not (ctl/position-absolute? shape)))
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(when (and
|
||||
|
@ -314,7 +314,7 @@
|
|||
(defmethod get-value :grid-area
|
||||
[_ shape objects]
|
||||
(when (and (ctl/grid-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(not (ctl/position-absolute? shape)))
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(when (and (= (:position cell) :area) (d/not-empty? (:area-name cell)))
|
||||
|
|
Loading…
Add table
Reference in a new issue