mirror of
https://github.com/penpot/penpot.git
synced 2025-02-24 15:56:11 -05:00
✨ Multispan cells auto sizing
This commit is contained in:
parent
0eff2e8887
commit
cdebf245e3
6 changed files with 316 additions and 76 deletions
|
@ -51,6 +51,7 @@
|
|||
|
||||
(ns app.common.geom.shapes.grid-layout.layout-data
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
@ -134,6 +135,137 @@
|
|||
(= :auto type)
|
||||
(assoc :size (min (+ size add-size) max-size)))))))
|
||||
|
||||
(defn size-to-allocate
|
||||
[type parent [child-bounds _] cell]
|
||||
(let [[row-gap column-gap] (ctl/gaps parent)
|
||||
[sfn gap prop-span]
|
||||
(if (= type :column)
|
||||
[gpo/width-points column-gap :column-span ]
|
||||
[gpo/height-points row-gap :row-span ])
|
||||
span (get cell prop-span)]
|
||||
(- (sfn child-bounds) (* gap (dec span)))))
|
||||
|
||||
(defn allocate-size
|
||||
[allocations indexed-tracks to-allocate]
|
||||
(if (empty? indexed-tracks)
|
||||
allocations
|
||||
(let [[idx track] (first indexed-tracks)
|
||||
old-allocated (get allocations idx 0.01)
|
||||
auto-track? (= :auto (:type track))
|
||||
|
||||
allocated (if auto-track?
|
||||
(max old-allocated
|
||||
(/ to-allocate (count indexed-tracks))
|
||||
(:size track))
|
||||
(:size track))]
|
||||
(recur (cond-> allocations auto-track?
|
||||
(assoc idx allocated))
|
||||
(rest indexed-tracks) (- to-allocate allocated)))))
|
||||
|
||||
(defn allocate-flex
|
||||
[allocations indexed-tracks to-allocate fr-value]
|
||||
(if (empty? indexed-tracks)
|
||||
allocations
|
||||
(let [[idx track] (first indexed-tracks)
|
||||
old-allocated (get allocations idx 0.01)
|
||||
|
||||
auto-track? (= :auto (:type track))
|
||||
flex-track? (= :flex (:type track))
|
||||
|
||||
fr (if flex-track? (:value track) 0)
|
||||
|
||||
target-allocation (* fr-value fr)
|
||||
|
||||
allocated (if (or auto-track? flex-track?)
|
||||
(max target-allocation
|
||||
old-allocated
|
||||
(:size track))
|
||||
(:size track))]
|
||||
(recur (cond-> allocations (or flex-track? auto-track?)
|
||||
(assoc idx allocated))
|
||||
(rest indexed-tracks)
|
||||
(- to-allocate allocated)
|
||||
fr-value))))
|
||||
|
||||
(defn set-auto-multi-span
|
||||
[parent track-list children-map shape-cells type]
|
||||
|
||||
(let [[prop prop-span]
|
||||
(if (= type :column)
|
||||
[:column :column-span]
|
||||
[:row :row-span])
|
||||
|
||||
;; First calculate allocation without applying so we can modify them on the following tracks
|
||||
allocate-auto-tracks
|
||||
(->> shape-cells
|
||||
(vals)
|
||||
(filter #(> (get % prop-span) 1))
|
||||
(sort-by prop-span -)
|
||||
(reduce
|
||||
(fn [alloc cell]
|
||||
(let [shape-id (first (:shapes cell))
|
||||
from-idx (dec (get cell prop))
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
indexed-tracks (subvec (d/enumerate track-list) from-idx to-idx)
|
||||
has-flex? (->> indexed-tracks (d/seek #(= :flex (:type (second %)))) some?)
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell)]
|
||||
(cond-> alloc
|
||||
;; skip cells with flex tracks
|
||||
(and (not has-flex?) (some? to-allocate))
|
||||
(allocate-size indexed-tracks to-allocate))))
|
||||
{}))
|
||||
|
||||
;; Apply the allocations to the tracks
|
||||
track-list
|
||||
(into []
|
||||
(map-indexed #(update %2 :size max (get allocate-auto-tracks %1)))
|
||||
track-list)]
|
||||
track-list))
|
||||
|
||||
(defn set-flex-multi-span
|
||||
[parent track-list children-map shape-cells type]
|
||||
|
||||
(let [[prop prop-span]
|
||||
(if (= type :column)
|
||||
[:column :column-span]
|
||||
[:row :row-span])
|
||||
|
||||
;; First calculate allocation without applying so we can modify them on the following tracks
|
||||
allocate-fr-tracks
|
||||
(->> shape-cells
|
||||
(vals)
|
||||
(filter #(> (get % prop-span) 1))
|
||||
(sort-by prop-span -)
|
||||
(reduce
|
||||
(fn [alloc cell]
|
||||
(let [shape-id (first (:shapes cell))
|
||||
from-idx (dec (get cell prop))
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
indexed-tracks (subvec (d/enumerate track-list) from-idx to-idx)
|
||||
has-flex? (->> indexed-tracks (d/seek #(= :auto (:type (second %)))) some?)
|
||||
total-frs (->> indexed-tracks (reduce (fn [tot [_ {:keys [type value]}]]
|
||||
(cond-> tot
|
||||
(= type :flex)
|
||||
(+ value)))
|
||||
0))
|
||||
|
||||
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell)
|
||||
fr-value (when (some? to-allocate) (/ to-allocate total-frs))]
|
||||
(cond-> alloc
|
||||
;; skip cells with no flex tracks
|
||||
(and has-flex? (some? to-allocate))
|
||||
(allocate-flex indexed-tracks to-allocate fr-value))))
|
||||
{}))
|
||||
|
||||
;; Apply the allocations to the tracks
|
||||
track-list
|
||||
(into []
|
||||
(map-indexed #(update %2 :size max (get allocate-fr-tracks %1)))
|
||||
track-list)]
|
||||
track-list))
|
||||
|
||||
|
||||
(defn calc-layout-data
|
||||
[parent children transformed-parent-bounds]
|
||||
|
||||
|
@ -155,6 +287,10 @@
|
|||
(->> (:shapes cell) (map #(vector % cell)))))
|
||||
(:layout-grid-cells parent))
|
||||
|
||||
children-map
|
||||
(into {}
|
||||
(map #(vector (:id (second %)) %))
|
||||
children)
|
||||
|
||||
;; Initialize tracks
|
||||
column-tracks
|
||||
|
@ -171,8 +307,8 @@
|
|||
|
||||
|
||||
;; Adjust multi-spaned cells with no flex columns
|
||||
;; TODO
|
||||
|
||||
column-tracks (set-auto-multi-span parent column-tracks children-map shape-cells :column)
|
||||
row-tracks (set-auto-multi-span parent row-tracks children-map shape-cells :row)
|
||||
|
||||
;; Calculate the `fr` unit and adjust the size
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
|
@ -184,6 +320,12 @@
|
|||
column-frs (tracks-total-frs column-tracks)
|
||||
row-frs (tracks-total-frs row-tracks)
|
||||
|
||||
;; Assign minimum size to the multi-span flex tracks. We do this after calculating
|
||||
;; the fr size because will affect only the minimum. The maximum will be set by the
|
||||
;; fracion
|
||||
column-tracks (set-flex-multi-span parent column-tracks children-map shape-cells :column)
|
||||
row-tracks (set-flex-multi-span parent row-tracks children-map shape-cells :row)
|
||||
|
||||
;; Once auto sizes have been calculated we get calculate the `fr` unit with the remainining size and adjust the size
|
||||
free-column-space (- bound-width (+ column-total-size column-total-gap))
|
||||
free-row-space (- bound-height (+ row-total-size row-total-gap))
|
||||
|
@ -235,8 +377,7 @@
|
|||
[(conj tracks (assoc track :start-p start-p))
|
||||
(gpt/add start-p (vv (+ size row-gap)))])
|
||||
[[] start-p])
|
||||
(first))
|
||||
]
|
||||
(first))]
|
||||
|
||||
{:origin start-p
|
||||
:layout-bounds layout-bounds
|
||||
|
@ -270,4 +411,3 @@
|
|||
(gpt/to-vec origin row-start-p)))]
|
||||
|
||||
(assoc grid-cell :start-p start-p)))))
|
||||
|
||||
|
|
|
@ -55,11 +55,13 @@
|
|||
|
||||
(defn width-points
|
||||
[[p0 p1 _ _]]
|
||||
(max 0.01 (gpt/length (gpt/to-vec p0 p1))))
|
||||
(when (and (some? p0) (some? p1))
|
||||
(max 0.01 (gpt/length (gpt/to-vec p0 p1)))))
|
||||
|
||||
(defn height-points
|
||||
[[p0 _ _ p3]]
|
||||
(max 0.01 (gpt/length (gpt/to-vec p0 p3))))
|
||||
(when (and (some? p0) (some? p3))
|
||||
(max 0.01 (gpt/length (gpt/to-vec p0 p3)))))
|
||||
|
||||
(defn pad-points
|
||||
[[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left]
|
||||
|
|
|
@ -262,7 +262,7 @@
|
|||
(hooks/setup-shortcuts node-editing? drawing-path? text-editing?)
|
||||
(hooks/setup-active-frames base-objects hover-ids selected active-frames zoom transform vbox)
|
||||
|
||||
[:div.viewport
|
||||
[:div.viewport {:style #js {"--zoom" zoom}}
|
||||
[:div.viewport-overlays
|
||||
;; The behaviour inside a foreign object is a bit different that in plain HTML so we wrap
|
||||
;; inside a foreign object "dummy" so this awkward behaviour is take into account
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.viewport.grid-layout-editor
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
|
@ -20,6 +21,8 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.object :as obj]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -41,36 +44,38 @@
|
|||
value (unchecked-get props "value")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
marker-width (/ 24 zoom)
|
||||
marker-h1 (/ 22 zoom)
|
||||
marker-h2 (/ 8 zoom)
|
||||
|
||||
marker-half-width (/ marker-width 2)
|
||||
marker-half-height (/ (+ marker-h1 marker-h2) 2)
|
||||
|
||||
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)))])
|
||||
(gpt/point marker-half-width marker-half-height))]
|
||||
[#(gpt/add % (gpt/point marker-width 0))
|
||||
#(gpt/add % (gpt/point 0 marker-h1))
|
||||
#(gpt/add % (gpt/point (- marker-half-width) marker-h2))
|
||||
#(gpt/subtract % (gpt/point marker-half-width marker-h2))])
|
||||
|
||||
text-x (:x center)
|
||||
text-y (:y center)]
|
||||
|
||||
[:g.grid-track-marker
|
||||
[:polygon {:points (->> marker-points
|
||||
[:g {:class (css :grid-track-marker)}
|
||||
[:polygon {:class (css :marker-shape)
|
||||
:points (->> marker-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))
|
||||
|
||||
:style {:fill "var(--color-distance)"
|
||||
:fill-opacity 0.3}}]
|
||||
[:text {:x text-x
|
||||
(str/join " "))}]
|
||||
[:text {:class (css :marker-text)
|
||||
:x text-x
|
||||
:y text-y
|
||||
:width (/ 26.26 zoom)
|
||||
:height (/ 32 zoom)
|
||||
:font-size (/ 16 zoom)
|
||||
:font-family "worksans"
|
||||
:font-weight 600
|
||||
:text-anchor "middle"
|
||||
:dominant-baseline "middle"
|
||||
:style {:fill "var(--color-distance)"}}
|
||||
:dominant-baseline "middle"}
|
||||
(dm/str value)]]))
|
||||
|
||||
(mf/defc grid-editor-frame
|
||||
|
@ -95,11 +100,11 @@
|
|||
#(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)}}]))
|
||||
[:polygon
|
||||
{:class (css :grid-frame)
|
||||
:points (->> frame-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))}]))
|
||||
|
||||
(mf/defc plus-btn
|
||||
{::mf/wrap-props false}
|
||||
|
@ -127,22 +132,21 @@
|
|||
(mf/deps on-click)
|
||||
#(when on-click (on-click)))]
|
||||
|
||||
[:g.plus-button {:cursor "pointer"
|
||||
:on-click handle-click}
|
||||
[:rect {:x rect-x
|
||||
[:g {:class (css :grid-plus-button)
|
||||
:on-click handle-click}
|
||||
|
||||
[:rect {:class (css :grid-plus-shape)
|
||||
: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)}}]
|
||||
:height (/ 40 zoom)}]
|
||||
|
||||
[:use {:x icon-x
|
||||
[:use {:class (css :grid-plus-icon)
|
||||
:x icon-x
|
||||
:y icon-y
|
||||
:width (/ 16 zoom)
|
||||
:height (/ 16 zoom)
|
||||
:href (dm/str "#icon-plus")
|
||||
:fill "white"}]]))
|
||||
:href (dm/str "#icon-plus")}]]))
|
||||
|
||||
(defn use-drag
|
||||
[{:keys [on-drag-start on-drag-end on-drag-delta on-drag-position]}]
|
||||
|
@ -259,7 +263,6 @@
|
|||
:height height
|
||||
:width width
|
||||
:style {:fill "transparent" :stroke-width 0 :cursor cursor}
|
||||
|
||||
:on-pointer-down handle-pointer-down
|
||||
:on-lost-pointer-capture handle-lost-pointer-capture
|
||||
:on-pointer-move handle-pointer-move}]))
|
||||
|
@ -301,21 +304,17 @@
|
|||
|
||||
[:g.cell-editor
|
||||
[:rect
|
||||
{:x (:x start-p)
|
||||
{:class (dom/classnames (css :grid-cell-outline) true
|
||||
(css :hover) hover?
|
||||
(css :selected) selected?)
|
||||
:x (:x start-p)
|
||||
:y (:y start-p)
|
||||
:width cell-width
|
||||
:height cell-height
|
||||
|
||||
:on-pointer-enter #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) true))
|
||||
:on-pointer-leave #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) false))
|
||||
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) (:id cell)))
|
||||
|
||||
: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)}}]
|
||||
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) (:id cell)))}]
|
||||
|
||||
(when selected?
|
||||
(let [handlers
|
||||
|
@ -451,7 +450,44 @@
|
|||
(mf/use-callback
|
||||
(mf/deps (:id shape))
|
||||
(fn []
|
||||
(st/emit! (st/emit! (dwsl/add-layout-track [(:id shape)] :row ctl/default-track-value)))))]
|
||||
(st/emit! (st/emit! (dwsl/add-layout-track [(:id shape)] :row ctl/default-track-value)))))
|
||||
|
||||
handle-blur-track-input
|
||||
(mf/use-callback
|
||||
(mf/deps (:id shape))
|
||||
(fn [track-type index event]
|
||||
(let [target (-> event dom/get-target)
|
||||
value (-> target dom/get-input-value str/upper)
|
||||
value-int (d/parse-integer value)
|
||||
|
||||
[type value]
|
||||
(cond
|
||||
(str/ends-with? value "%")
|
||||
[:percent value-int]
|
||||
|
||||
(str/ends-with? value "FR")
|
||||
[:flex value-int]
|
||||
|
||||
(some? value-int)
|
||||
[:fixed value-int]
|
||||
|
||||
(or (= value "AUTO") (= "" value))
|
||||
[:auto nil])]
|
||||
(if (some? type)
|
||||
(do (obj/set! target "value" (format-size {:type type :value value}))
|
||||
(dom/set-attribute! target "data-default-value" (format-size {:type type :value value}))
|
||||
(st/emit! (dwsl/change-layout-track [(:id shape)] track-type index {:type type :value value})))
|
||||
(obj/set! target "value" (dom/get-attribute target "data-default-value"))))))
|
||||
|
||||
handle-keydown-track-input
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)]
|
||||
(when enter?
|
||||
(dom/blur! (dom/get-target event)))
|
||||
(when esc?
|
||||
(dom/blur! (dom/get-target event))))))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
|
@ -482,23 +518,19 @@
|
|||
(gpt/subtract (hv (/ layout-gap-col 2)))))
|
||||
|
||||
text-p (-> start-p
|
||||
(gpt/subtract (vv (/ 20 zoom)))
|
||||
(gpt/add (hv (/ (:size column-data) 2))))]
|
||||
(gpt/subtract (vv (/ 36 zoom))))]
|
||||
[:* {:key (dm/str "column-" idx)}
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc idx))
|
||||
:zoom zoom}]
|
||||
|
||||
[:text {:x (:x text-p)
|
||||
:y (:y text-p)
|
||||
:font-size (/ 14 zoom)
|
||||
:font-weight 600
|
||||
:font-family "worksans"
|
||||
:dominant-baseline "central"
|
||||
:text-anchor "middle"
|
||||
:style {:fill "var(--color-distance)"}}
|
||||
(format-size column-data)]
|
||||
|
||||
[:foreignObject {:x (:x text-p) :y (:y text-p) :width (max 0 (- (:size column-data) 4)) :height (/ 32 zoom)}
|
||||
[:input
|
||||
{:class (css :grid-editor-label)
|
||||
:type "text"
|
||||
:default-value (format-size column-data)
|
||||
:data-default-value (format-size column-data)
|
||||
:on-key-down handle-keydown-track-input
|
||||
:on-blur #(handle-blur-track-input :column idx %)}]]
|
||||
(when (not= idx 0)
|
||||
[:& resize-handler {:shape shape
|
||||
:layout-data layout-data
|
||||
|
@ -514,24 +546,25 @@
|
|||
(gpt/subtract (vv (/ layout-gap-row 2)))))
|
||||
|
||||
text-p (-> start-p
|
||||
(gpt/subtract (hv (/ 20 zoom)))
|
||||
(gpt/add (vv (/ (:size row-data) 2))))]
|
||||
(gpt/subtract (hv (/ (:size row-data) 2)))
|
||||
(gpt/subtract (hv (/ 16 zoom)))
|
||||
(gpt/add (vv (/ (:size row-data) 2)))
|
||||
(gpt/subtract (vv (/ 18 zoom))))]
|
||||
[:* {:key (dm/str "row-" idx)}
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc idx))
|
||||
:zoom zoom}]]
|
||||
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x text-p) (:y text-p))}
|
||||
[:text {:x (:x text-p)
|
||||
:y (:y text-p)
|
||||
:font-size (/ 14 zoom)
|
||||
:font-weight 600
|
||||
:font-family "worksans"
|
||||
:dominant-baseline "central"
|
||||
:text-anchor "middle"
|
||||
:style {:fill "var(--color-distance)"}}
|
||||
(format-size row-data)]]
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (+ (:x text-p) (/ (:size row-data) 2)) (+ (:y text-p) (/ 36 zoom 2)))}
|
||||
[:foreignObject {:x (:x text-p) :y (:y text-p) :width (:size row-data) :height (/ 36 zoom)}
|
||||
[:input
|
||||
{:class (css :grid-editor-label)
|
||||
:type "text"
|
||||
:default-value (format-size row-data)
|
||||
:data-default-value (format-size row-data)
|
||||
:on-key-down handle-keydown-track-input
|
||||
:on-blur #(handle-blur-track-input :row idx %)}]]]
|
||||
|
||||
(when (not= idx 0)
|
||||
[:& resize-handler {:shape shape
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"grid-track-marker":"viewport_grid_layout_editor_grid-track-marker_HABEp","marker-shape":"viewport_grid_layout_editor_marker-shape_FZTUQ","marker-text":"viewport_grid_layout_editor_marker-text_5xM8J","grid-editor-label":"viewport_grid_layout_editor_grid-editor-label_2NbYe","grid-frame":"viewport_grid_layout_editor_grid-frame_CzMnU","grid-plus-button":"viewport_grid_layout_editor_grid-plus-button_brOge","grid-plus-shape":"viewport_grid_layout_editor_grid-plus-shape_jtOU9","grid-plus-icon":"viewport_grid_layout_editor_grid-plus-icon_Zolso","grid-cell-outline":"viewport_grid_layout_editor_grid-cell-outline_1-cRq","hover":"viewport_grid_layout_editor_hover_Rn-tv","selected":"viewport_grid_layout_editor_selected_nhyhL"}
|
|
@ -0,0 +1,64 @@
|
|||
.grid-track-marker {
|
||||
.marker-shape {
|
||||
fill: var(--color-distance);
|
||||
fill-opacity: 0.3;
|
||||
}
|
||||
.marker-text {
|
||||
fill: var(--color-distance);
|
||||
font-size: calc(12px / var(--zoom));
|
||||
font-family: worksans;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-editor-label {
|
||||
background: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
font-family: worksans;
|
||||
color: var(--color-distance);
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: calc(12px / var(--zoom));
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-bottom: calc(1px / var(--zoom)) solid var(--color-distance);
|
||||
}
|
||||
}
|
||||
|
||||
.grid-frame {
|
||||
fill: transparent;
|
||||
stroke: var(--color-distance);
|
||||
stroke-width: calc(1 / var(--zoom));
|
||||
}
|
||||
|
||||
.grid-plus-button {
|
||||
cursor: pointer;
|
||||
|
||||
.grid-plus-shape {
|
||||
fill: var(--color-distance);
|
||||
stroke: var(--color-distance);
|
||||
stroke-width: calc(1 / var(--zoom));
|
||||
}
|
||||
|
||||
.grid-plus-icon {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-cell-outline {
|
||||
fill: transparent;
|
||||
stroke: var(--color-distance);
|
||||
stroke-linecap: round;
|
||||
stroke-width: calc(2 / var(--zoom));
|
||||
stroke-dasharray: 0 calc(8 / var(--zoom));
|
||||
|
||||
&.hover,
|
||||
&.selected {
|
||||
stroke-dasharray: initial;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue