0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-21 06:02:32 -05:00

New UI for grid layout

This commit is contained in:
alonso.torres 2023-11-10 16:05:47 +01:00
parent 02612ab4ca
commit 7ad747b9d0
24 changed files with 1321 additions and 504 deletions

View file

@ -882,3 +882,15 @@
([pred coll]
(transduce (take-until pred) conj [] coll)))
(defn safe-subvec
"Wrapper around subvec so it doesn't throw an exception but returns nil instead"
([v start]
(when (and (some? v)
(> start 0) (< start (count v)))
(subvec v start)))
([v start end]
(let [size (count v)]
(when (and (some? v)
(>= start 0) (< start size)
(>= end 0) (<= start end) (<= end size))
(subvec v start end)))))

View file

@ -495,6 +495,12 @@
(pos->Point (if (mth/almost-zero? x) 0.001 x)
(if (mth/almost-zero? y) 0.001 y))))
(defn resize
"Creates a new vector with the same direction but different length"
[vector new-length]
(let [old-length (length vector)]
(scale vector (/ new-length old-length))))
;; FIXME: perfromance
(defn abs
[point]
@ -522,3 +528,4 @@
:class Point
:wfn #(into {} %)
:rfn map->Point})

View file

@ -25,32 +25,32 @@
(let [hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
span-column-tracks (subvec column-tracks (dec column) (+ (dec column) column-span))
span-row-tracks (subvec row-tracks (dec row) (+ (dec row) row-span))
span-column-tracks (d/safe-subvec column-tracks (dec column) (+ (dec column) column-span))
span-row-tracks (d/safe-subvec row-tracks (dec row) (+ (dec row) row-span))]
p1
(gpt/add
origin
(gpt/add
(gpt/to-vec origin (dm/get-in span-column-tracks [0 :start-p]))
(gpt/to-vec origin (dm/get-in span-row-tracks [0 :start-p]))))
(when (and span-column-tracks span-row-tracks)
(let [p1
(gpt/add
origin
(gpt/add
(gpt/to-vec origin (dm/get-in span-column-tracks [0 :start-p]))
(gpt/to-vec origin (dm/get-in span-row-tracks [0 :start-p]))))
p2
(as-> p1 $
(reduce (fn [p track] (gpt/add p (hv (:size track)))) $ span-column-tracks)
(gpt/add $ (hv (* column-gap (dec (count span-column-tracks))))))
p2
(as-> p1 $
(reduce (fn [p track] (gpt/add p (hv (:size track)))) $ span-column-tracks)
(gpt/add $ (hv (* column-gap (dec (count span-column-tracks))))))
p3
(as-> p2 $
(reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks)
(gpt/add $ (vv (* row-gap (dec (count span-row-tracks))))))
p3
(as-> p2 $
(reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks)
(gpt/add $ (vv (* row-gap (dec (count span-row-tracks))))))
p4
(as-> p1 $
(reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks)
(gpt/add $ (vv (* row-gap (dec (count span-row-tracks))))))]
[p1 p2 p3 p4]))
p4
(as-> p1 $
(reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks)
(gpt/add $ (vv (* row-gap (dec (count span-row-tracks))))))]
[p1 p2 p3 p4]))))
(defn calc-fill-width-data
"Calculates the size and modifiers for the width of an auto-fill child"

View file

@ -28,6 +28,8 @@ paths.resources = "./resources/";
paths.output = "./resources/public/";
paths.dist = "./target/dist/";
const touchSourceOnStyleChange = true;
/***********************************************
* Marked Extensions
***********************************************/
@ -282,12 +284,15 @@ gulp.task("dev:dirs", async function(next) {
});
gulp.task("watch:main", function() {
gulp.watch("src/**/**.scss", gulp.series("scss"))
.on("change", function(path) {
const watchTask = gulp.watch("src/**/**.scss", gulp.series("scss"));
if (touchSourceOnStyleChange) {
watchTask.on("change", function(path) {
// Replace ".scss" for ".cljs" to refresh the file
gulp.src(path.replace(".scss", ".cljs"))
.pipe(touch());
gulp.src(path.replace(".scss", ".cljs")).pipe(touch());
});
}
gulp.watch(paths.resources + "styles/**/**.scss", gulp.series("scss"));
gulp.watch(paths.resources + "images/**/*", gulp.series("copy:assets:images"));

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M15.333 1.333v13.334M.667 1.333v13.334m1.833-9.5v-1c0-.817.683-1.5 1.5-1.5h8c.817 0 1.5.683 1.5 1.5v1c0 .827-.672 1.5-1.5 1.5H4c-.828 0-1.5-.673-1.5-1.5zM4 13.333h8c.817 0 1.5-.683 1.5-1.5v-1c0-.827-.672-1.5-1.5-1.5H4c-.828 0-1.5.673-1.5 1.5v1c0 .817.683 1.5 1.5 1.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 399 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M1.333.667h13.334M1.333 15.333h13.334m-9.5-1.833h-1c-.817 0-1.5-.683-1.5-1.5V4c0-.817.683-1.5 1.5-1.5h1c.827 0 1.5.672 1.5 1.5v8c0 .828-.673 1.5-1.5 1.5zm8.166-1.5V4c0-.817-.683-1.5-1.5-1.5h-1c-.827 0-1.5.672-1.5 1.5v8c0 .828.673 1.5 1.5 1.5h1c.817 0 1.5-.683 1.5-1.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -316,6 +316,10 @@
color: var(--input-foreground-color-active);
background-color: var(--input-background-color-active);
}
&[disabled] {
opacity: 0.5;
pointer-events: none;
}
}
.input-icon {

View file

@ -16,7 +16,9 @@
--green: #91fadb;
--green-30: rgba(145, 250, 219, 0.3);
--lilac: #bb97d8;
--pink: #ff6fe0;
--strong-green: #00d1b8;
// NOTIFICATION
--dark-ok-color: var(--strong-green);
--dark-warning-color: #ff9b49;

View file

@ -250,4 +250,13 @@
--comment-bullet-foreground-color-resolved: var(--color-foreground-secondary);
--comment-bullet-border-color-resolved: var(--color-background-quaternary);
--comment-modal-background-color: var(--color-background-primary);
// GRID LAYOUT
--grid-editor-marker-color: var(--color-foreground-tertiary);
--grid-editor-marker-text: var(--color-foreground-tertiary);
--grid-editor-area-background: var(--color-foreground-tertiary);
--grid-editor-area-text: var(--color-foreground-tertiary);
--grid-editor-line-color: var(--color-foreground-tertiary);
--grid-editor-plus-btn-foreground: var(--white);
--grid-editor-plus-btn-background: var(--color-foreground-tertiary);
}

View file

@ -74,6 +74,7 @@ $s-380: calc(var(--s-4) * 95);
$s-400: calc(var(--s-4) * 100);
$s-480: calc(var(--s-4) * 120);
$s-500: calc(var(--s-4) * 125);
$s-512: calc(var(--s-4) * 128);
$s-520: calc(var(--s-4) * 130);
$s-664: calc(var(--s-4) * 166);
$s-712: calc(var(--s-4) * 178);

View file

@ -13,6 +13,7 @@
--color-background-disabled: var(--off-white);
--color-foreground-primary: var(--white);
--color-foreground-secondary: var(--off-white);
--color-foreground-tertiary: var(--pink);
--color-foreground-disabled: var(--dark-gray-4);
--color-accent-primary: var(--green);
--color-accent-primary-muted: var(--green-30);

View file

@ -13,6 +13,7 @@
--color-background-disabled: var(--light-gray-4);
--color-foreground-primary: var(--black);
--color-foreground-secondary: var(--off-black);
--color-foreground-tertiary: var(--pink);
--color-foreground-disabled: var(--light-gray-1);
--color-accent-primary: var(--purple);
--color-accent-primary-muted: var(--purple-30);

View file

@ -7,6 +7,8 @@
(ns app.main.data.workspace.edition
(:require
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
@ -31,11 +33,16 @@
state)))
ptk/WatchEvent
(watch [_ _ stream]
(->> stream
(rx/filter interrupt?)
(rx/take 1)
(rx/map (constantly clear-edition-mode))))))
(watch [_ state stream]
(let [objects (wsh/lookup-page-objects state)]
(rx/concat
(if (ctl/grid-layout? objects id)
(rx/of (dwc/hide-toolbar))
(rx/empty))
(->> stream
(rx/filter interrupt?)
(rx/take 1)
(rx/map (constantly clear-edition-mode))))))))
;; If these event change modules review /src/app/main/data/workspace/path/undo.cljs
(def clear-edition-mode

View file

@ -9,6 +9,7 @@
(:require-macros [app.main.ui.icons :refer [icon-xref]])
(:require
[app.common.data :as d]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@ -275,11 +276,13 @@
(def align-content-column-evenly-refactor (icon-xref :align-content-column-evenly-refactor))
(def align-content-column-start-refactor (icon-xref :align-content-column-start-refactor))
(def align-content-column-end-refactor (icon-xref :align-content-column-end-refactor))
(def align-content-column-stretch-refactor (icon-xref :align-content-column-stretch-refactor))
(def align-content-row-end-refactor (icon-xref :align-content-row-end-refactor))
(def align-content-row-around-refactor (icon-xref :align-content-row-around-refactor))
(def align-content-row-between-refactor (icon-xref :align-content-row-between-refactor))
(def align-content-row-evenly-refactor (icon-xref :align-content-row-evenly-refactor))
(def align-content-row-start-refactor (icon-xref :align-content-row-start-refactor))
(def align-content-row-stretch-refactor (icon-xref :align-content-row-stretch-refactor))
(def align-horizontal-center-refactor (icon-xref :align-horizontal-center-refactor))
(def align-vertical-center-refactor (icon-xref :align-vertical-center-refactor))
(def align-items-row-center-refactor (icon-xref :align-items-row-center-refactor))
@ -474,12 +477,29 @@
(mf/defc debug-icons-preview
{::mf/wrap-props false}
[]
[:section.debug-icons-preview
(for [[key val] (sort-by first (ns-publics 'app.main.ui.icons))]
(when (not= key 'debug-icons-preview)
[:div.icon-item {:key key}
(deref val)
[:span (pr-str key)]]))])
[:*
[:section.debug-icons-preview
[:h2 "Classic"]
[:*
(for [[key val] (->> (ns-publics 'app.main.ui.icons)
(sort-by first)
(remove (fn [[key _]]
(str/ends-with? (str key) "-refactor"))))]
(when (not= key 'debug-icons-preview)
[:div.icon-item {:key key}
(deref val)
[:span (pr-str key)]]))]]
[:section.debug-icons-preview
[:h2 "Refactor"]
[:*
(for [[key val] (->> (ns-publics 'app.main.ui.icons)
(sort-by first)
(filter (fn [[key _]] (str/ends-with? (str key) "-refactor"))))]
(when (not= key 'debug-icons-preview)
[:div.icon-item {:key key}
(deref val)
[:span (pr-str key)]]))]]])
(defn key->icon
[icon-key]

View file

@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.grid-cell
(:require-macros [app.main.style :as stl])
(:require
[app.common.attrs :as attrs]
[app.common.data :as d]
@ -15,10 +16,14 @@
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.menus.layout-container :as lyc]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
(def cell-props [:id
@ -33,25 +38,58 @@
(mf/defc set-self-alignment
[{:keys [is-col? alignment set-alignment] :as props}]
(let [dir-v [:auto :start :center :end :stretch #_:baseline]
alignment (or alignment :auto)]
[:div.align-self-style
(for [align dir-v]
[:button.align-self.tooltip.tooltip-bottom
{:class (dom/classnames :active (= alignment align)
:tooltip-bottom-left (not= align :start)
:tooltip-bottom (= align :start))
:alt (dm/str "Align self " (d/name align)) ;; TODO fix this tooltip
:on-click #(set-alignment align)
:key (str "align-self" align)}
(lyc/get-layout-flex-icon :align-self align is-col?)])]))
(let [new-css-system (mf/use-ctx ctx/new-css-system)
dir-v [:auto :start :center :end :stretch #_:baseline]
alignment (or alignment :auto)
type (if is-col? "col" "row")]
(if new-css-system
[:div {:class (stl/css :self-align-menu)}
[:& radio-buttons {:selected (d/name alignment)
:on-change #(set-alignment (keyword %))
:name (dm/str "flex-align-items-" type)}
[:& radio-button {:value "start"
:icon (if is-col? i/align-self-row-left-refactor i/align-self-column-top-refactor)
:title "Align self start"
:id (dm/str "align-self-start-" type)}]
[:& radio-button {:value "center"
:icon (if is-col? i/align-self-row-center-refactor i/align-self-column-center-refactor)
:title "Align self center"
:id (dm/str "align-self-center-" type)}]
[:& radio-button {:value "end"
:icon (if is-col? i/align-self-row-right-refactor i/align-self-column-bottom-refactor)
:title "Align self end"
:id (dm/str "align-self-end-" type)}]
[:& radio-button {:value "stretch"
:icon (if is-col? i/align-self-row-strech i/align-self-column-strech)
:title "Align self stretch"
:id (dm/str "align-self-stretch-" type)}]]]
[:div.align-self-style
(for [align dir-v]
[:button.align-self.tooltip.tooltip-bottom
{:class (dom/classnames :active (= alignment align)
:tooltip-bottom-left (not= align :start)
:tooltip-bottom (= align :start))
:alt (dm/str "Align self " (d/name align)) ;; TODO fix this tooltip
:on-click #(set-alignment align)
:key (str "align-self" align)}
(lyc/get-layout-flex-icon :align-self align is-col?)])])))
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [shape cell cells] :as props}]
(let [cells (hooks/use-equal-memo cells)
(let [new-css-system (mf/use-ctx ctx/new-css-system)
state* (mf/use-state {:open true})
open? (:open @state*)
cells (hooks/use-equal-memo cells)
cell (or cell (attrs/get-attrs-multi cells cell-props))
multiple? (= :multiple (:id cell))
@ -126,7 +164,8 @@
(mf/use-callback
(mf/deps (:id shape) cell-ids)
(fn [mode]
(st/emit! (dwsl/change-cells-mode (:id shape) cell-ids mode))))
(let [mode (-> mode keyword)]
(st/emit! (dwsl/change-cells-mode (:id shape) cell-ids mode)))))
toggle-edit-mode
(mf/use-fn
@ -135,106 +174,207 @@
(st/emit! (dw/start-edition-mode (:id shape))
(dwge/clear-selection (:id shape)))))]
[:div.element-set
[:div.element-set-title
[:span "Grid Cell"]]
[:div.element-set-content.layout-grid-item-menu
[:div.layout-row
[:div.row-title.sizing "Position"]
[:div.position-wrapper
[:button.position-btn
{:on-click #(set-cell-mode :auto)
:class (dom/classnames :active (= :auto cell-mode))} "Auto"]
(when-not multiple?
(if new-css-system
[:div {:class (stl/css :grid-cell-menu)}
[:div {:class (stl/css :grid-cell-menu-title)}
[:& title-bar {:collapsable? true
:collapsed? (not open?)
:on-collapsed #(swap! state* update :open not)
:title "Grid cell"}]]
(when open?
[:div {:class (stl/css :grid-cell-menu-container)}
[:div {:class (stl/css :cell-mode :row)}
[:& radio-buttons {:selected (d/name cell-mode)
:on-change set-cell-mode
:name "cell-mode"
:wide true}
[:& radio-button {:value "auto" :id :auto}]
[:& radio-button {:value "manual" :id :manual}]
[:& radio-button {:value "area" :id :area}]]]
(when (= :area cell-mode)
[:div {:class (stl/css :row)}
[:input
{:class (stl/css :area-input)
:key (dm/str "name-" (:id cell))
:id "grid-area-name"
:type "text"
:aria-label "grid-area-name"
:placeholder "Area name"
:default-value area-name
:auto-complete "off"
:on-change on-area-name-change}]])
(when (and (not multiple?) (= :auto cell-mode))
[:div {:class (stl/css :row)}
[:div {:class (stl/css :grid-coord-group)}
[:span {:class (stl/css :icon)} i/layout-rows]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :column)
:value column}]]]
[:div {:class (stl/css :grid-coord-group)}
[:span {:class (stl/css :icon)} i/layout-columns]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :row)
:value row}]]]])
(when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
[:div {:class (stl/css :row)}
[:div {:class (stl/css :grid-coord-group)}
[:span {:class (stl/css :icon)} i/layout-rows]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :column)
:value column}]]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :column)
:value column-end}]]]
[:div {:class (stl/css :grid-coord-group)}
[:span {:class (stl/css :icon)} i/layout-columns]
[:div {:class (stl/css :coord-input :double)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :row)
:value row}]]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :row)
:value row-end}]]]])
[:div {:class (stl/css :row)}
[:& set-self-alignment {:is-col? false
:alignment align-self
:set-alignment set-alignment}]
[:& set-self-alignment {:is-col? true
:alignment justify-self
:set-alignment set-justify-self}]]
[:div {:class (stl/css :row)}
[:button
{:class (stl/css :edit-grid-btn)
:alt (tr "workspace.layout_grid.editor.options.edit-grid")
:on-click toggle-edit-mode}
(tr "workspace.layout_grid.editor.options.edit-grid")]]])]
[:div.element-set
[:div.element-set-title
[:span "Grid Cell"]]
[:div.element-set-content.layout-grid-item-menu
[:div.layout-row
[:div.row-title.sizing "Position"]
[:div.position-wrapper
[:button.position-btn
{:on-click #(set-cell-mode :manual)
:class (dom/classnames :active (= :manual cell-mode))} "Manual"])
[:button.position-btn
{:on-click #(set-cell-mode :area)
:disabled (not valid-area-cells?)
:class (dom/classnames :active (= :area cell-mode))} "Area"]]]
{:on-click #(set-cell-mode :auto)
:class (dom/classnames :active (= :auto cell-mode))} "Auto"]
(when-not multiple?
[:button.position-btn
{:on-click #(set-cell-mode :manual)
:class (dom/classnames :active (= :manual cell-mode))} "Manual"])
[:button.position-btn
{:on-click #(set-cell-mode :area)
:disabled (not valid-area-cells?)
:class (dom/classnames :active (= :area cell-mode))} "Area"]]]
[:div.manage-grid-columns
(when (and (not multiple?) (= :auto cell-mode))
[:div.grid-auto
[:div.grid-columns-auto
[:span.icon i/layout-rows]
[:div.manage-grid-columns
(when (and (not multiple?) (= :auto cell-mode))
[:div.grid-auto
[:div.grid-columns-auto
[:span.icon i/layout-rows]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :column)
:value column}]]]
[:div.grid-rows-auto
[:span.icon i/layout-columns]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :row)
:value row}]]]])
(when (= :area cell-mode)
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :column)
:value column}]]]
[:div.grid-rows-auto
[:span.icon i/layout-columns]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :row)
:value row}]]]])
[:input.input-text
{:key (dm/str "name-" (:id cell))
:id "grid-area-name"
:type "text"
:aria-label "grid-area-name"
:placeholder "--"
:default-value area-name
:auto-complete "off"
:on-change on-area-name-change}]])
(when (= :area cell-mode)
[:div.input-wrapper
[:input.input-text
{:key (dm/str "name-" (:id cell))
:id "grid-area-name"
:type "text"
:aria-label "grid-area-name"
:placeholder "--"
:default-value area-name
:auto-complete "off"
:on-change on-area-name-change}]])
(when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
[:div.grid-manual
[:div.grid-columns-auto
[:span.icon i/layout-rows]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :column)
:value column}]
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :column)
:value column-end}]]]
[:div.grid-rows-auto
[:span.icon i/layout-columns]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :row)
:value row}]
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :row)
:value row-end}]]]])]
(when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
[:div.grid-manual
[:div.grid-columns-auto
[:span.icon i/layout-rows]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :column)
:value column}]
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :column)
:value column-end}]]]
[:div.grid-rows-auto
[:span.icon i/layout-columns]
[:div.input-wrapper
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :row)
:value row}]
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :row)
:value row-end}]]]])]
[:div.layout-row
[:div.row-title "Align"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? false
:alignment align-self
:set-alignment set-alignment}]]]
[:div.layout-row
[:div.row-title "Justify"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? true
:alignment justify-self
:set-alignment set-justify-self}]]]
[:div.layout-row
[:div.row-title "Align"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? false
:alignment align-self
:set-alignment set-alignment}]]]
[:div.layout-row
[:div.row-title "Justify"]
[:div.btn-wrapper
[:& set-self-alignment {:is-col? true
:alignment justify-self
:set-alignment set-justify-self}]]]
[:div.layout-row.single-button
[:div.btn-wrapper
[:div.edit-mode
[:button.tooltip.tooltip-bottom-left
{:alt "Grid edit mode"
:on-click toggle-edit-mode
:style {:padding 0}}
"Edit grid"
i/grid-layout-mode]]]]]]))
[:div.layout-row.single-button
[:div.btn-wrapper
[:div.edit-mode
[:button.tooltip.tooltip-bottom-left
{:alt "Grid edit mode"
:on-click toggle-edit-mode
:style {:padding 0}}
"Edit grid"
i/grid-layout-mode]]]]]])))

View file

@ -0,0 +1,59 @@
// 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
@import "refactor/common-refactor.scss";
.grid-cell-menu {
.grid-cell-menu-container {
@include flexColumn;
margin-top: $s-8;
gap: $s-16;
}
.grid-cell-menu-title {
font-size: $fs-11;
}
.row {
@include flexRow;
}
.cell-mode :global(label) {
padding: 0 $s-12;
}
.edit-grid-btn {
@extend .button-secondary;
@include tabTitleTipography;
width: 100%;
padding: $s-8;
}
.area-input {
@extend .input-element;
width: 100%;
padding: $s-8;
}
}
.grid-coord-group {
@include flexRow;
border-radius: $br-8;
padding-left: $s-4;
background-color: var(--input-background-color);
.icon svg {
@extend .button-icon;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
}
.coord-input {
@extend .input-element;
border-radius: 0 $br-8 $br-8 0;
border-left: 1px solid var(--panel-background-color);
}
}

View file

@ -24,6 +24,7 @@
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@ -231,6 +232,43 @@
:stretch i/align-self-column-strech
:baseline i/align-self-column-baseline))))
(defn get-layout-grid-icon-refactor
[type val is-col?]
(case type
:align-items
(if is-col?
(case val
:auto i/remove-refactor
:start i/align-self-row-left-refactor
:end i/align-self-row-right-refactor
:center i/align-self-row-center-refactor
:stretch i/align-self-row-strech
:baseline i/align-self-row-baseline)
(case val
:auto i/remove-refactor
:start i/align-self-column-top-refactor
:end i/align-self-column-bottom-refactor
:center i/align-self-column-center-refactor
:stretch i/align-self-column-strech
:baseline i/align-self-column-baseline))
:justify-items
(if (not is-col?)
(case val
:start i/align-content-column-start-refactor
:center i/align-content-column-center-refactor
:end i/align-content-column-end-refactor
:space-around i/align-content-column-around-refactor
:space-between i/align-content-column-between-refactor
:stretch i/align-content-column-stretch-refactor)
(case val
:start i/align-content-row-start-refactor
:center i/align-content-row-center-refactor
:end i/align-content-row-end-refactor
:space-around i/align-content-row-around-refactor
:space-between i/align-content-row-between-refactor
:stretch i/align-content-row-stretch-refactor))))
(mf/defc direction-row-flex
[{:keys [saved-dir on-change] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
@ -310,7 +348,7 @@
:id "align-items-end"}]]
[:div.align-items-style
[:button.align-start.tooltip.tooltip-bottom
[:button.align-start.tooltip.tooltip-bottom
{:class (dom/classnames :active (= align-items :start))
:alt "Align items start"
:data-value :start
@ -687,8 +725,7 @@
[:div {:class (stl/css-case :row-gap true
:disabled (and (= :nowrap wrap-type) (not is-col?)))
:title "Row gap"}
[:span {:class (stl/css :icon)}
i/gap-vertical-refactor]
[:span {:class (stl/css :icon)} i/gap-vertical-refactor]
[:> numeric-input* {:className (stl/css :numeric-input true)
:no-validate true
:placeholder "--"
@ -704,6 +741,7 @@
:min 0
:value (:row-gap gap-value)
:disabled (and (= :nowrap wrap-type) (not is-col?))}]]
[:div {:class (stl/css-case :column-gap true
:disabled (and (= :nowrap wrap-type) is-col?))
:title "Column gap"}
@ -792,11 +830,11 @@
:space-evenly i/grid-justify-content-row-between))))
(mf/defc direction-row-grid
[{:keys [saved-dir on-change-refactor on-click] :as props}]
[{:keys [saved-dir on-change on-click] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:& radio-buttons {:selected (d/name saved-dir)
:on-change on-change-refactor
:on-change on-change
:name "grid-direction"}
[:& radio-button {:value "row"
:id "grid-direction-row"
@ -832,13 +870,18 @@
(st/emit! (udw/start-edition-mode id))
(st/emit! :interrupt))))]
(if new-css-system
[:div "new-edit-mode"]
[:button
{:class (stl/css :edit-mode-btn)
:alt "Grid edit mode"
:on-click toggle-edit-mode}
(tr "workspace.layout_grid.editor.options.edit-grid")]
[:button.tooltip.tooltip-bottom-left
{:class (dom/classnames :active active?)
:alt "Grid edit mode"
:on-click #(toggle-edit-mode)
:on-click toggle-edit-mode
:style {:padding 0}}
"Edit grid"
(tr "workspace.layout_grid.editor.options.edit-grid")
i/grid-layout-mode])))
(mf/defc align-grid-row
@ -847,20 +890,20 @@
type (if is-col? :column :row)]
(if new-css-system
[:& radio-buttons {:selected (d/name align-items)
:on-change set-align
:name "flex-align-items"}
:on-change #(set-align % type)
:name (dm/str "flex-align-items-" (d/name type))}
[:& radio-button {:value "start"
:icon (get-layout-flex-icon-refactor :align-items :start is-col?)
:icon (get-layout-grid-icon-refactor :align-items :start is-col?)
:title "Align items start"
:id "align-items-start"}]
:id (dm/str "align-items-start-" (d/name type))}]
[:& radio-button {:value "center"
:icon (get-layout-flex-icon-refactor :align-items :center is-col?)
:icon (get-layout-grid-icon-refactor :align-items :center is-col?)
:title "Align items center"
:id "align-items-center"}]
:id (dm/str "align-items-center-" (d/name type))}]
[:& radio-button {:value "end"
:icon (get-layout-flex-icon-refactor :align-items :end is-col?)
:icon (get-layout-grid-icon-refactor :align-items :end is-col?)
:title "Align items end"
:id "align-items-end"}]]
:id (dm/str "align-items-end-" (d/name type))}]]
[:div.align-items-style
(for [align [:start :center :end]]
[:button.align-start.tooltip
@ -876,19 +919,31 @@
(mf/defc justify-grid-row
[{:keys [is-col? justify-items set-justify] :as props}]
(let [type (if is-col? :column :row)]
[:div.justify-content-style
(for [align [:start :center :end :space-around :space-between :stretch]]
[:button.align-start.tooltip
{:class (dom/classnames :active (= justify-items align)
:tooltip-bottom-left (not= align :start)
:tooltip-bottom (= align :start))
:alt (if is-col?
(dm/str "align-content: " (d/name align))
(dm/str "justify-content: " (d/name align)))
:on-click #(set-justify align type)
:key (dm/str "justify-content" (d/name align))}
(get-layout-grid-icon :justify-items align is-col?)])]))
(let [new-css-system (mf/use-ctx ctx/new-css-system)
type (if is-col? :column :row)]
(if new-css-system
[:& radio-buttons {:selected (d/name justify-items)
:on-change #(set-justify % type)
:name (dm/str "grid-justify-items-" (d/name type))}
(for [justify [:start :center :end :space-around :space-between :stretch]]
[:& radio-button {:value (d/name justify)
:icon (get-layout-grid-icon-refactor :justify-items justify is-col?)
:title (dm/str "Justify items " (d/name justify))
:id (dm/str "justify-items-" (d/name justify) "-" (d/name type))}])]
[:div.justify-content-style
(for [align [:start :center :end :space-around :space-between :stretch]]
[:button.align-start.tooltip
{:class (dom/classnames :active (= justify-items align)
:tooltip-bottom-left (not= align :start)
:tooltip-bottom (= align :start))
:alt (if is-col?
(dm/str "align-content: " (d/name align))
(dm/str "justify-content: " (d/name align)))
:on-click #(set-justify align type)
:key (dm/str "justify-content" (d/name align))}
(get-layout-grid-icon :justify-items align is-col?)])])))
(defn manage-values [{:keys [value type]}]
(case type
@ -900,7 +955,9 @@
(mf/defc grid-track-info
[{:keys [is-col? type index column set-column-value set-column-type remove-element reorder-track hover-track]}]
(let [drop-track
(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]
@ -926,74 +983,139 @@
:index index
:column column}
:draggable? true)]
[:div.column-info
{:ref dref
:class (dom/classnames
:dnd-over-top (or (= (:over dprops) :top)
(= (:over dprops) :center))
:dnd-over-bot (= (:over dprops) :bot))
:on-pointer-enter pointer-enter
:on-pointer-leave pointer-leave}
[:div.direction-grid-icon
(if is-col?
i/layout-rows
i/layout-columns)]
[:div.grid-column-value
[:> numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:disabled (= :auto (:type column))}]]
[:div.grid-column-unit
[:& select
{:class "grid-column-unit-selector"
:default-value (:type column)
:options [{:value :flex :label "FR"}
{:value :auto :label "AUTO"}
{:value :fixed :label "PX"}
{:value :percent :label "%"}]
:on-change #(set-column-type type index %)}]]
[:button.remove-grid-column
{:on-click #(remove-element type index)}
i/minus]]))
(if new-css-system
[:div {:class
(stl/css-case :track-info true
:dnd-over-top (or (= (:over dprops) :top)
(= (:over dprops) :center))
:dnd-over-bot (= (:over dprops) :bot))
:ref dref
:on-pointer-enter pointer-enter
:on-pointer-leave pointer-leave}
[:div {:class (stl/css :track-info-container)}
[:div {:class (stl/css :track-info-dir-icon)}
(if is-col? i/flex-vertical-refactor i/flex-horizontal-refactor)]
[:div {:class (stl/css :track-info-value)}
[:> numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:disabled (= :auto (:type column))}]]
[:div {:class (stl/css :track-info-unit)}
[:& select
{:class (stl/css :track-info-unit-selector)
:default-value (:type column)
:options [{:value :flex :label "FR"}
{:value :auto :label "AUTO"}
{:value :fixed :label "PX"}
{:value :percent :label "%"}]
:on-change #(set-column-type type index %)}]]]
[:button
{:class (stl/css :remove-track-btn)
:on-click #(remove-element type index)}
i/remove-refactor]]
[:div.column-info
{:ref dref
:class (dom/classnames
:dnd-over-top (or (= (:over dprops) :top)
(= (:over dprops) :center))
:dnd-over-bot (= (:over dprops) :bot))
:on-pointer-enter pointer-enter
:on-pointer-leave pointer-leave}
[:div.direction-grid-icon
(if is-col?
i/layout-rows
i/layout-columns)]
[:div.grid-column-value
[:> numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:disabled (= :auto (:type column))}]]
[:div.grid-column-unit
[:& select
{:class "grid-column-unit-selector"
:default-value (:type column)
:options [{:value :flex :label "FR"}
{:value :auto :label "AUTO"}
{:value :fixed :label "PX"}
{:value :percent :label "%"}]
:on-change #(set-column-type type index %)}]]
[:button.remove-grid-column
{:on-click #(remove-element type index)}
i/minus]])))
(mf/defc grid-columns-row
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type remove-element reorder-track hover-track] :as props}]
(let [column-num (count column-values)
(let [new-css-system (mf/use-ctx ctx/new-css-system)
column-num (count column-values)
direction (if (> column-num 1)
(if is-col? "Columns " "Rows ")
(if is-col? "Column " "Row "))
column-vals (str/join ", " (map manage-values column-values))
generated-name (dm/str direction (if (= column-num 0) " - empty" (dm/str column-num " (" column-vals ")")))
type (if is-col? :column :row)]
track-name (dm/str direction (if (= column-num 0) " - empty" column-num))
track-detail (str/join ", " (map manage-values column-values))
generated-name (dm/str direction (if (= column-num 0) " - empty" (dm/str column-num " (" track-detail ")")))
[:div.grid-columns
[:div.grid-columns-header
[:button.expand-icon
{:on-click toggle} i/actions]
type (if is-col? :column :row)
[:div.columns-info {:title generated-name
:on-click toggle} generated-name]
[:button.add-column {:on-click #(do
(when-not expanded? (toggle))
(add-new-element type ctl/default-track-value))} i/plus]]
add-track
#(do
(when-not expanded? (toggle))
(add-new-element type ctl/default-track-value))]
(when expanded?
[:& h/sortable-container {}
[:div.columns-info-wrapper
(for [[index column] (d/enumerate column-values)]
[:& grid-track-info {:key (dm/str index "-" (name type) "-" column)
:type type
:is-col? is-col?
:index index
:column column
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}])]])]))
(if new-css-system
[:div {:class (stl/css :grid-tracks)}
[:div {:class (stl/css :grid-track-header)}
[:button {:class (stl/css :expand-icon) :on-click toggle} i/menu-refactor]
[:div {:class (stl/css :track-title) :on-click toggle}
[:div {:class (stl/css :track-name) :title track-name} track-name]
[:div {:class (stl/css :track-detail) :title track-detail} track-detail]]
[:button {:class (stl/css :add-column) :on-click add-track} i/add-refactor]]
(when expanded?
[:& h/sortable-container {}
[:div {:class (stl/css :grid-tracks-info-container)}
(for [[index column] (d/enumerate column-values)]
[:& grid-track-info {:key (dm/str index "-" (name type))
:type type
:is-col? is-col?
:index index
:column column
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}])]])]
[:div.grid-columns
[:div.grid-columns-header
[:button.expand-icon {:on-click toggle} i/actions]
[:div.columns-info {:title generated-name :on-click toggle} generated-name]
[:button.add-column {:on-click add-track} i/plus]]
(when expanded?
[:& h/sortable-container {}
[:div.columns-info-wrapper
(for [[index column] (d/enumerate column-values)]
[:& grid-track-info {:key (dm/str index "-" (name type))
:type type
:is-col? is-col?
:index index
:column column
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}])]])])))
;; LAYOUT COMPONENT
@ -1169,16 +1291,16 @@
(mf/use-fn
(mf/deps ids)
(fn [type prop val]
(let [val (mth/finite val 0)]
(cond
(and (= type :simple) (= prop :p1))
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}}))
(let [val (mth/finite val 0)]
(cond
(and (= type :simple) (= prop :p1))
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}}))
(and (= type :simple) (= prop :p2))
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
(and (= type :simple) (= prop :p2))
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
:else
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))))
:else
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))))
;; Grid-direction
@ -1188,9 +1310,9 @@
(mf/use-fn
(mf/deps [layout-type ids new-css-system])
(fn [dir]
(let [dir (if new-css-system (keyword dir) dir)]
(let [dir (cond-> dir new-css-system keyword)]
(if (= :flex layout-type)
(st/emit! (dwsl/update-layout ids {:layout-flex-dir dir}))
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))
(st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))))
;; Align grid
@ -1198,10 +1320,13 @@
align-items-column (:layout-justify-items values)
set-align-grid
(fn [value type]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))
(mf/use-fn
(mf/deps ids new-css-system)
(fn [value type]
(let [value (cond-> value new-css-system keyword)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))))
;; Justify grid
grid-justify-content-row (:layout-justify-content values)
@ -1211,11 +1336,12 @@
set-justify-grid
(mf/use-fn
(mf/deps ids)
(mf/deps ids new-css-system)
(fn [value type]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value})))))]
(let [value (cond-> value new-css-system keyword)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))]
(if new-css-system
[:div {:class (stl/css :element-set)}
@ -1265,7 +1391,7 @@
[:div {:class (stl/css :second-row)}
[:& justify-content-row {:is-col? is-col?
:justify-content justify-content
:on-change set-justify-content-refactor}]]
:on-change set-justify-content-refactor}]]
(when (= :wrap wrap-type)
[:div {:class (stl/css :third-row)}
[:& align-content-row {:is-col? is-col?
@ -1281,37 +1407,33 @@
[:& padding-section {:values values
:on-change-style change-padding-type
:on-change on-padding-change}]]]
:grid ;; TODO Finish this with new UI
:grid
[:div {:class (stl/css :grid-layout-menu)}
[:div {:class (stl/css :first-row)}
[:div (stl/css :direction-edit)
[:div {:class (stl/css :direction)}
[:& direction-row-grid {:set-direction set-direction
:on-click saved-dir}]
(when (= 1 (count ids))
[:div {:class (stl/css :edit)}
[:& grid-edit-mode {:id (first ids)}]])]]
[:div {:class (stl/css :row :first-row)}
[:div {:class (stl/css :direction-edit)}
[:div {:class (stl/css :direction)}
[:& direction-row-grid {:saved-dir saved-grid-dir
:on-change set-direction}]]]
[:div.layout-row
[:div.align-items-grid.row-title "Items"]
[:div.btn-wrapper.align-grid-items
[:& align-grid-row {:is-col? false
:align-items align-items-row
:set-align set-align-grid}]
[:& align-grid-row {:is-col? false
:align-items align-items-row
:set-align set-align-grid}]
[:& align-grid-row {:is-col? true
:align-items align-items-column
:set-align set-align-grid}]]]
[:& align-grid-row {:is-col? true
:align-items align-items-column
:set-align set-align-grid}]]
[:div.layout-row
[:div.jusfiy-content-grid.row-title "Content"]
[:div.btn-wrapper.align-grid-content
[:& justify-grid-row {:is-col? true
:justify-items grid-justify-content-column
:set-justify set-justify-grid}]
[:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-row
:set-justify set-justify-grid}]]]]]
[:div {:class (stl/css :row :grid-layout-align)}
[:& justify-grid-row {:is-col? true
:justify-items grid-justify-content-column
:set-justify set-justify-grid}]
[:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-row
:set-justify set-justify-grid}]]
(when (= 1 (count ids))
[:& grid-edit-mode {:id (first ids)}])]
nil)))]
[:div.element-set
@ -1427,13 +1549,15 @@
:justify-items grid-justify-content-row
:set-justify set-justify-grid}]]]]
;; Default if not grid or flex
;; Default if not grid or flex
nil)))])))
(mf/defc grid-layout-edition
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
[{:keys [ids values] :as props}]
(let [;; Gap
(let [new-css-system (mf/use-ctx ctx/new-css-system)
;; Gap
gap-selected? (mf/use-state :none)
saved-grid-dir (:layout-grid-dir values)
@ -1468,23 +1592,28 @@
align-items-row (:layout-align-items values)
align-items-column (:layout-justify-items values)
set-items-grid
(fn [value type]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))
set-align-grid
(mf/use-fn
(mf/deps ids new-css-system)
(fn [value type]
(let [value (cond-> value new-css-system keyword)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-items value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-items value}))))))
;; Justify grid
grid-justify-content-row (:layout-align-content values)
grid-justify-content-column (:layout-justify-content values)
grid-justify-content-row (:layout-justify-content values)
grid-justify-content-column (:layout-align-content values)
set-content-grid
set-justify-grid
(mf/use-fn
(mf/deps ids)
(mf/deps ids new-css-system)
(fn [value type]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value})))))
(let [value (cond-> value new-css-system keyword)]
(if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-justify-content value}))
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
;;Grid columns
column-grid-values (:layout-grid-columns values)
@ -1543,72 +1672,133 @@
(st/emit! (dwsl/change-layout-track ids type index {:value value
:type track-type})))))]
[:div.element-set
[:div.element-set-title
[:span "Grid Layout"]]
(if new-css-system
[:div {:class (stl/css :grid-layout-menu)}
[:div {:class (stl/css :row)}
[:div {:class (stl/css :grid-layout-menu-title)} "GRID LAYOUT"]
[:button {:class (stl/css :exit-btn)
:on-click #(st/emit! udw/clear-edition-mode)}
(tr "workspace.layout_grid.editor.options.exit")]]
[:div.element-set-content.layout-menu
[:div.layout-row
[:div.direction-wrap.row-title "Direction"]
[:div.btn-wrapper
[:div.direction
(for [dir [:row :column]]
[:& direction-btn {:key (d/name dir)
:dir dir
:saved-dir saved-grid-dir
:on-click set-direction
:icon? true}])]
[:div {:class (stl/css :row :first-row)}
[:div {:class (stl/css :direction-edit)}
[:div {:class (stl/css :direction)}
[:& direction-row-grid {:saved-dir saved-grid-dir
:on-change set-direction}]]]
(when (= 1 (count ids))
[:div.edit-mode
[:& grid-edit-mode {:id (first ids)}]])]]
[:div.layout-row
[:div.align-items-grid.row-title "Items"]
[:div.btn-wrapper.align-grid
[:& align-grid-row {:is-col? false
:align-items align-items-row
:set-align set-items-grid}]
:set-align set-align-grid}]
[:& align-grid-row {:is-col? true
:align-items align-items-column
:set-align set-items-grid}]]]
:set-align set-align-grid}]]
[:div.layout-row
[:div.jusfiy-content-grid.row-title "Content"]
[:div.btn-wrapper.align-grid-content
[:div {:class (stl/css :row :grid-layout-align)}
[:& justify-grid-row {:is-col? true
:justify-items grid-justify-content-row
:set-justify set-content-grid}]
[:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-column
:set-justify set-content-grid}]]]
[:& grid-columns-row {:is-col? true
:expanded? @grid-columns-open?
:toggle toggle-columns-info
:column-values column-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
:set-justify set-justify-grid}]
[:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-row
:set-justify set-justify-grid}]]
[:div {:class (stl/css :row :grid-tracks-row)}
[:& grid-columns-row {:is-col? true
:expanded? @grid-columns-open?
:toggle toggle-columns-info
:column-values column-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& grid-columns-row {:is-col? false
:expanded? @grid-rows-open?
:toggle toggle-rows-info
:column-values rows-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& grid-columns-row {:is-col? false
:expanded? @grid-rows-open?
:toggle toggle-rows-info
:column-values rows-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]]
[:div {:class (stl/css :row)}
[:& gap-section {:gap-selected? gap-selected?
:on-change set-gap
:gap-value (:layout-gap values)}]]
[:& gap-section {:gap-selected? gap-selected?
:on-change set-gap
:gap-value (:layout-gap values)}]
[:div {:class (stl/css :row :padding-section)}
[:& padding-section {:values values
:on-change-style change-padding-type
:on-change on-padding-change}]]]
[:& padding-section {:values values
:on-change-style change-padding-type
:on-change on-padding-change}]]]))
[:div.element-set
[:div.element-set-title
[:span "Grid Layout"]]
[:div.element-set-content.layout-menu
[:div.layout-row
[:div.direction-wrap.row-title "Direction"]
[:div.btn-wrapper
[:div.direction
(for [dir [:row :column]]
[:& direction-btn {:key (d/name dir)
:dir dir
:saved-dir saved-grid-dir
:on-click set-direction
:icon? true}])]
(when (= 1 (count ids))
[:div.edit-mode
[:& grid-edit-mode {:id (first ids)}]])]]
[:div.layout-row
[:div.align-items-grid.row-title "Items"]
[:div.btn-wrapper.align-grid
[:& align-grid-row {:is-col? false
:align-items align-items-row
:set-align set-align-grid}]
[:& align-grid-row {:is-col? true
:align-items align-items-column
:set-align set-align-grid}]]]
[:div.layout-row
[:div.jusfiy-content-grid.row-title "Content"]
[:div.btn-wrapper.align-grid-content
[:& justify-grid-row {:is-col? true
:justify-items grid-justify-content-row
:set-justify set-justify-grid}]
[:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-column
:set-justify set-justify-grid}]]]
[:& grid-columns-row {:is-col? true
:expanded? @grid-columns-open?
:toggle toggle-columns-info
:column-values column-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& grid-columns-row {:is-col? false
:expanded? @grid-rows-open?
:toggle toggle-rows-info
:column-values rows-grid-values
:add-new-element add-new-element
:set-column-value set-column-value
:set-column-type set-column-type
:remove-element remove-element
:reorder-track reorder-track
:hover-track hover-track}]
[:& gap-section {:gap-selected? gap-selected?
:on-change set-gap
:gap-value (:layout-gap values)}]
[:& padding-section {:values values
:on-change-style change-padding-type
:on-change on-padding-change}]]])))

View file

@ -63,65 +63,242 @@
}
.forth-row {
@include flexColumn;
.gap-group {
display: flex;
gap: $s-4;
.column-gap {
@extend .input-element;
width: $s-108;
&.disabled {
@extend .disabled-input;
}
}
.row-gap {
@extend .input-element;
width: $s-108;
&.disabled {
@extend .disabled-input;
}
}
}
.padding-group {
display: flex;
gap: $s-4;
.padding-inputs {
display: flex;
gap: $s-4;
.paddings-simple {
display: flex;
gap: $s-4;
.padding-simple {
@extend .input-element;
width: $s-108;
}
}
.paddings-multiple {
display: grid;
grid-template-columns: 1fr 1fr;
gap: $s-4;
.padding-multiple {
@extend .input-element;
width: $s-108;
}
}
}
.padding-toggle {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
border-radius: $br-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
&.selected {
background-color: var(--button-tertiary-background-color-hover);
svg {
stroke: var(--button-tertiary-foreground-color-active);
}
}
}
}
}
}
.gap-group {
display: flex;
gap: $s-4;
.column-gap {
@extend .input-element;
width: $s-108;
&.disabled {
@extend .disabled-input;
}
}
.row-gap {
@extend .input-element;
width: $s-108;
&.disabled {
@extend .disabled-input;
}
}
}
.padding-group {
display: flex;
gap: $s-4;
.padding-inputs {
display: flex;
gap: $s-4;
}
.paddings-simple {
display: flex;
gap: $s-4;
.padding-simple {
@extend .input-element;
width: $s-108;
}
}
.paddings-multiple {
display: grid;
grid-template-columns: 1fr 1fr;
gap: $s-4;
.padding-multiple {
@extend .input-element;
width: $s-108;
}
}
.padding-toggle {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
border-radius: $br-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
&.selected {
background-color: var(--button-tertiary-background-color-hover);
svg {
stroke: var(--button-tertiary-foreground-color-active);
}
}
}
}
.grid-layout-menu {
@include flexColumn;
gap: $s-8;
.row {
@include flexRow;
}
.first-row {
margin-bottom: $s-8;
}
.grid-layout-align {
@include flexColumn;
gap: $s-4;
align-items: flex-start;
}
.grid-layout-menu-title {
flex: 1;
font-size: $fs-11;
}
.edit-mode-btn {
@extend .button-secondary;
@include tabTitleTipography;
margin-top: $s-8;
width: 100%;
padding: $s-8;
}
.exit-btn {
@extend .button-secondary;
@include tabTitleTipography;
padding: $s-8 $s-20;
}
.grid-tracks-info-container {
@include flexColumn;
margin-top: $s-4;
}
.padding-section {
margin-top: $s-8;
}
.grid-tracks-row {
@include flexColumn;
margin: $s-8 0;
gap: $s-12;
}
}
.track-info {
display: flex;
&.dnd-over-top {
border-top: $s-2 solid var(--button-foreground-hover);
}
&.dnd-over-bot {
border-bottom: $s-2 solid var(--button-foreground-hover);
}
.track-info-container {
display: flex;
}
.track-info-dir-icon {
border-radius: $br-8 0 0 $br-8;
background-color: var(--input-background-color);
padding-left: $s-12;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
height: 100%;
}
}
.track-info-value {
@extend .input-element;
border-radius: 0;
border-right: $s-1 solid var(--panel-background-color);
}
.track-info-unit {
}
.track-info-unit-selector {
border-radius: 0 $br-8 $br-8 0;
width: $s-96;
}
.remove-track-btn {
@extend .button-tertiary;
padding: $s-8;
svg {
@extend .button-icon;
width: $s-12;
height: $s-12;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
}
}
}
.grid-tracks {
width: 100%;
margin-top: $s-8;
.grid-track-header {
@include flexRow;
font-size: $fs-12;
border-radius: $br-8;
overflow: hidden;
background: var(--button-secondary-background-color-rest);
height: $s-52;
}
.track-title {
@include flexColumn;
flex-grow: 1;
padding: $s-8;
gap: 0;
}
.track-name {
color: var(--color-foreground-secondary);
}
.expand-icon {
@extend .button-secondary;
height: $s-52;
border-radius: $s-8 0 0 $s-8;
border-right: $s-1 solid var(--panel-background-color);
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
}
&:hover,
&:active {
svg {
stroke: var(--button-foreground-hover);
fill: var(--button-foreground-hover);
}
}
}
.columns-info {
}
.add-column {
@extend .button-tertiary;
height: $s-52;
svg {
@extend .button-icon;
height: $s-12;
width: $s-12;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
}
}
}

View file

@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.viewport.grid-layout-editor
(:require-macros [app.main.style :refer [css]])
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@ -18,17 +18,20 @@
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace :as dw]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.data.workspace.modifiers :as dwm]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.css-cursors :as cur]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[app.util.object :as obj]
[cuerdas.core :as str]
@ -47,30 +50,56 @@
:flex (dm/str (fmt/format-number value) "FR")
:auto "AUTO"))
(mf/defc grid-edition-actions
{::mf/wrap-props false}
[{:keys [shape]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :grid-actions)}
[:div {:class (stl/css :grid-actions-container)}
[:div {:class (stl/css :grid-actions-title)}
(tr "workspace.layout_grid.editor.title") " " [:span {:stl/css :board-name} (:name shape)]]
[:button {:class (stl/css :locate-btn)
:on-click #(st/emit! (dwge/locate-board (:id shape)))}
(tr "workspace.layout_grid.editor.top-bar.locate")]
[:button {:class (stl/css :done-btn)
:on-click #(st/emit! dw/clear-edition-mode)}
(tr "workspace.layout_grid.editor.top-bar.done")]]]
[:div.viewport-actions
[:div.viewport-actions-container
[:div.viewport-actions-title
(tr "workspace.layout_grid.editor.title") " " [:span.grid-edit-board-name (:name shape)]]
[:button.btn-secondary {:on-click #(st/emit! (dwge/locate-board (:id shape)))}
(tr "workspace.layout_grid.editor.top-bar.locate")]
[:button.btn-primary {:on-click #(st/emit! dw/clear-edition-mode)}
(tr "workspace.layout_grid.editor.top-bar.done")]
[:button.btn-icon-basic {:on-click #(st/emit! dw/clear-edition-mode)} i/close]]])))
(mf/defc grid-editor-frame
{::mf/wrap-props false}
[props]
(let [bounds (unchecked-get props "bounds")
width (unchecked-get props "width")
height (unchecked-get props "height")
zoom (unchecked-get props "zoom")
hv #(gpo/start-hv bounds %)
vv #(gpo/start-vv bounds %)
width (gpo/width-points bounds)
height (gpo/height-points bounds)
origin (gpo/origin bounds)
frame-points
(reduce
apply-to-point
[origin]
[#(gpt/add % (hv width))
[#(gpt/add % (hv (+ width (/ 70 zoom))))
#(gpt/subtract % (vv (/ 40 zoom)))
#(gpt/subtract % (hv (+ width (/ 40 zoom))))
#(gpt/add % (vv (+ height (/ 40 zoom))))
#(gpt/subtract % (hv (+ width (/ 110 zoom))))
#(gpt/add % (vv (+ height (/ 110 zoom))))
#(gpt/add % (hv (/ 40 zoom)))])]
[:polygon
{:class (css :grid-frame)
{:class (stl/css :grid-frame)
:points (->> frame-points
(map #(dm/fmt "%,%" (:x %) (:y %)))
(str/join " "))}]))
@ -78,7 +107,6 @@
(mf/defc plus-btn
{::mf/wrap-props false}
[props]
(let [start-p (unchecked-get props "start-p")
zoom (unchecked-get props "zoom")
type (unchecked-get props "type")
@ -88,34 +116,36 @@
(if (= type :column)
[(:x start-p)
(- (:y start-p) (/ 40 zoom))
(+ (:x start-p) (/ 12 zoom))
(- (:y start-p) (/ 28 zoom))]
(+ (:x start-p) (/ 9 zoom))
(- (:y start-p) (/ 31 zoom))]
[(- (:x start-p) (/ 40 zoom))
(:y start-p)
(- (:x start-p) (/ 28 zoom))
(+ (:y start-p) (/ 12 zoom))])
(- (:x start-p) (/ 31 zoom))
(+ (:y start-p) (/ 9 zoom))])
handle-click
(mf/use-callback
(mf/deps on-click)
#(when on-click (on-click)))]
[:g {:class (css :grid-plus-button)
[:g {:class (stl/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)}]
[:rect {:class (stl/css :grid-plus-shape)
:x (+ rect-x (/ 6 zoom))
:y (+ rect-y (/ 6 zoom))
:width (/ (- 40 12) zoom)
:height (/ (- 40 12) zoom)
:rx (/ 4 zoom)
:ry (/ 4 zoom)}]
[:use {:class (css :grid-plus-icon)
[:use {:class (stl/css :grid-plus-icon)
:x icon-x
:y icon-y
:width (/ 16 zoom)
:height (/ 16 zoom)
:href (dm/str "#icon-plus")}]]))
:width (/ 22 zoom)
:height (/ 22 zoom)
:href "#icon-add-refactor"}]]))
(defn use-drag
[{:keys [on-drag-start on-drag-end on-drag-delta on-drag-position]}]
@ -260,11 +290,11 @@
:y area-y
:width area-width
:height area-height
:style {:fill "var(--color-distance)"
:style {:fill "var(--grid-editor-area-background)"
:fill-opacity 0.3}}]
[:text {:x area-text-x
:y area-text-y
:style {:fill "var(--color-distance)"
:style {:fill "var(--grid-editor-area-text)"
:font-family "worksans"
:font-weight 600
:font-size (/ 14 zoom)
@ -313,9 +343,9 @@
[:g.cell-editor
[:rect
{:transform (dm/str (gmt/transform-in cell-center (:transform shape)))
:class (dom/classnames (css :grid-cell-outline) true
(css :hover) hover?
(css :selected) selected?)
:class (dom/classnames (stl/css :grid-cell-outline) true
(stl/css :hover) hover?
(stl/css :selected) selected?)
:x (:x cell-origin)
:y (:y cell-origin)
:width cell-width
@ -475,6 +505,78 @@
:style {:fill "transparent"
:stroke-width 0}}]))
(def marker-width 24)
(def marker-h1 20)
(def marker-h2 10)
(def marker-bradius 2)
(defn marker-shape-d
[center zoom]
(let [marker-width (/ marker-width zoom)
marker-h1 (/ marker-h1 zoom)
marker-h2 (/ marker-h2 zoom)
marker-bradius (/ marker-bradius zoom)
marker-half-width (/ marker-width 2)
marker-half-height (/ (+ marker-h1 marker-h2) 2)
start-p
(gpt/subtract center (gpt/point marker-half-width marker-half-height))
[a b c d e]
(reduce
apply-to-point
[start-p]
[#(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))])
vea (gpt/to-vec e a)
vab (gpt/to-vec a b)
vbc (gpt/to-vec b c)
vcd (gpt/to-vec c d)
vde (gpt/to-vec d e)
lea (gpt/length vea)
lab (gpt/length vab)
lbc (gpt/length vbc)
lcd (gpt/length vcd)
lde (gpt/length vde)
a1 (gpt/add e (gpt/resize vea (- lea marker-bradius)))
a2 (gpt/add a (gpt/resize vab marker-bradius))
b1 (gpt/add a (gpt/resize vab (- lab marker-bradius)))
b2 (gpt/add b (gpt/resize vbc marker-bradius))
c1 (gpt/add b (gpt/resize vbc (- lbc marker-bradius)))
c2 (gpt/add c (gpt/resize vcd marker-bradius))
d1 (gpt/add c (gpt/resize vcd (- lcd marker-bradius)))
d2 (gpt/add d (gpt/resize vde marker-bradius))
e1 (gpt/add d (gpt/resize vde (- lde marker-bradius)))
e2 (gpt/add e (gpt/resize vea marker-bradius))]
(dm/str
(dm/fmt "M%,%" (:x a1) (:y a1))
(dm/fmt "Q%,%,%,%" (:x a) (:y a) (:x a2) (:y a2))
(dm/fmt "L%,%" (:x b1) (:y b1))
(dm/fmt "Q%,%,%,%" (:x b) (:y b) (:x b2) (:y b2))
(dm/fmt "L%,%" (:x c1) (:y c1))
(dm/fmt "Q%,%,%,%" (:x c) (:y c) (:x c2) (:y c2))
(dm/fmt "L%,%" (:x d1) (:y d1))
(dm/fmt "Q%,%,%,%" (:x d) (:y d) (:x d2) (:y d2))
(dm/fmt "L%,%" (:x e1) (:y e1))
(dm/fmt "Q%,%,%,%" (:x e) (:y e) (:x e2) (:y e2))
(dm/fmt "L%,%" (:x a1) (:y a1))
"Z")))
(mf/defc track-marker
{::mf/wrap-props false}
[props]
@ -489,23 +591,6 @@
track-after (unchecked-get props "track-after")
snap-pixel? (unchecked-get props "snap-pixel?")
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 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)
@ -515,16 +600,14 @@
[:g {:on-pointer-down handle-pointer-down
:on-lost-pointer-capture handle-lost-pointer-capture
:on-pointer-move handle-pointer-move
:class (dom/classnames (css :grid-track-marker) true
:class (dom/classnames (stl/css :grid-track-marker) true
(cur/get-dynamic "resize-ew" (:rotation shape)) (= type :column)
(cur/get-dynamic "resize-ns" (:rotation shape)) (= type :row))
:transform (dm/str (gmt/transform-in center (:transform shape)))}
[:polygon {:class (css :marker-shape)
:points (->> marker-points
(map #(dm/fmt "%,%" (:x %) (:y %)))
(str/join " "))}]
[:text {:class (css :marker-text)
[:path {:class (stl/css :marker-shape)
:d (marker-shape-d center zoom)}]
[:text {:class (stl/css :marker-text)
:x text-x
:y text-y
:width (/ 26.26 zoom)
@ -656,23 +739,23 @@
:width (- text-width (/ 36 zoom))
:height (- text-height (/ 5 zoom))
:rx (/ 3 zoom)
:fill "var(--color-distance)"
:fill "var(--grid-editor-marker-color)"
:opacity 0.2}])
(when (not small?)
[:foreignObject {:x text-x :y text-y :width text-width :height text-height}
[:div {:class (css :grid-editor-wrapper)}
[:div {:class (stl/css :grid-editor-wrapper)}
[:input
{:ref track-input-ref
:style {}
:class (css :grid-editor-label)
:class (stl/css :grid-editor-label)
:type "text"
:default-value (format-size track-data)
:data-default-value (format-size track-data)
:on-key-down handle-keydown-track-input
:on-blur handle-blur-track-input}]
(when (and hovering? (not medium?) (not small?))
[:button {:class (css :grid-editor-button)
:on-click handle-remove-track} i/trash])]])]
[:button {:class (stl/css :grid-editor-button)
:on-click handle-remove-track} i/delete-refactor])]])]
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
[:& track-marker
@ -757,17 +840,20 @@
bounds (:points shape)
hv #(gpo/start-hv bounds %)
vv #(gpo/start-vv bounds %)
width (gpo/width-points bounds)
height (gpo/height-points bounds)
origin (gpo/origin bounds)
all-bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
{:keys [row-tracks column-tracks] :as layout-data}
{:keys [row-tracks column-tracks
column-total-size column-total-gap
row-total-size row-total-gap] :as layout-data}
(mf/use-memo
(mf/deps shape children)
#(gsg/calc-layout-data shape bounds children all-bounds objects))
width (max (gpo/width-points bounds) (+ column-total-size column-total-gap))
height (max (gpo/height-points bounds) (+ row-total-size row-total-gap))
handle-pointer-down
(mf/use-callback
(fn [event]
@ -806,15 +892,17 @@
(when-not view-only
[:*
[:& grid-editor-frame {:zoom zoom
:bounds bounds}]
(let [start-p (-> origin (gpt/add (hv width)))]
:bounds bounds
:width width
:height height}]
(let [start-p (-> origin (gpt/add (hv (+ width (/ 30 zoom)))))]
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
[:& plus-btn {:start-p start-p
:zoom zoom
:type :column
:on-click handle-add-column}]])
(let [start-p (-> origin (gpt/add (vv height)))]
(let [start-p (-> origin (gpt/add (vv (+ height (/ 30 zoom)))))]
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
[:& plus-btn {:start-p start-p
:zoom zoom

View file

@ -1,13 +1,19 @@
// 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
@import "refactor/common-refactor.scss";
.grid-track-marker {
.marker-shape {
fill: var(--color-distance);
fill-opacity: 0.3;
fill: var(--grid-editor-marker-color);
}
.marker-text {
fill: var(--color-distance);
font-size: calc(12px / var(--zoom));
fill: var(--white);
font-size: calc($s-12 / var(--zoom));
font-family: worksans;
font-weight: 600;
}
}
@ -21,21 +27,21 @@
.grid-editor-label {
background: none;
border-bottom: calc(1px / var(--zoom)) solid transparent;
border-bottom: calc($s-1 / var(--zoom)) solid transparent;
border: 0;
color: var(--color-distance);
color: var(--grid-editor-marker-text);
font-family: worksans;
font-size: calc(12px / var(--zoom));
font-weight: 600;
font-size: calc($fs-12 / var(--zoom));
font-weight: 400;
margin: 0;
max-width: calc(80px / var(--zoom));
max-width: calc($s-80 / var(--zoom));
padding: 0;
padding: 4px;
padding: $s-4;
text-align: center;
&:focus {
outline: none;
border-bottom: calc(1px / var(--zoom)) solid var(--color-distance);
border-bottom: calc($s-1 / var(--zoom)) solid var(--grid-editor-marker-text);
}
}
@ -46,40 +52,48 @@
margin: 0;
padding: 0;
position: absolute;
right: calc(20px / var(--zoom));
width: calc(20px / var(--zoom));
height: calc(20px / var(--zoom));
top: calc($s-6 / var(--zoom));
right: calc($s-20 / var(--zoom));
width: calc($s-20 / var(--zoom));
height: calc($s-20 / var(--zoom));
svg {
width: calc(16px / var(--zoom));
position: absolute;
top: 0;
left: 0;
width: calc($s-16 / var(--zoom));
height: auto;
fill: var(--color-distance);
stroke: var(--grid-editor-marker-color);
}
}
.grid-frame {
fill: #f6f6f6;
stroke: var(--color-distance);
stroke-width: calc(1 / var(--zoom));
fill: var(--grid-editor-marker-color);
fill-opacity: 0.1;
}
.grid-plus-button {
cursor: pointer;
opacity: 0.5;
.grid-plus-shape {
fill: var(--color-distance);
stroke: var(--color-distance);
stroke-width: calc(1 / var(--zoom));
fill: var(--grid-editor-plus-btn-background);
stroke: var(--grid-editor-plus-btn-background);
stroke-width: calc($s-1 / var(--zoom));
}
.grid-plus-icon {
fill: white;
stroke: var(--grid-editor-plus-btn-foreground);
}
&:hover {
opacity: 1;
}
}
.grid-cell-outline {
fill: transparent;
stroke: var(--color-distance);
stroke: var(--grid-editor-line-color);
stroke-opacity: 0.5;
stroke-width: calc(1 / var(--zoom));
@ -89,3 +103,52 @@
stroke-width: calc(2 / var(--zoom));
}
}
.grid-actions {
pointer-events: none;
position: absolute;
top: $s-44;
left: 50%;
.grid-actions-container {
@include flexRow;
background: var(--panel-background-color);
border-radius: $br-12;
box-shadow: 0px 0px $s-12 0px var(--menu-shadow-color);
gap: $s-8;
height: $s-48;
margin-left: -50%;
padding: $s-8;
pointer-events: initial;
width: $s-512;
}
.grid-actions-title {
flex: 1;
font-size: $fs-12;
color: var(--color-foreground-secondary);
padding-left: $s-8;
}
.board-name {
}
.locate-btn {
@extend .button-secondary;
text-transform: uppercase;
padding: $s-8 $s-20;
font-size: $fs-11;
}
.done-btn {
@extend .button-primary;
text-transform: uppercase;
padding: $s-8 $s-20;
font-size: $fs-11;
}
.close-btn {
@extend .button-tertiary;
svg {
@extend .button-icon;
}
}
}

View file

@ -157,7 +157,8 @@
step (calculate-step-size zoom)
clip-id (str "clip-rule-" (d/name axis))
new-css-system (mf/use-ctx ctx/new-css-system)
font-color (if new-css-system new-css-font-color font-color)]
font-color (if new-css-system new-css-font-color font-color)
rules-background (if new-css-system new-css-rules-background rules-background)]
[:*
(let [{:keys [x y width height]} (get-background-area vbox zoom-inverse axis)]

View file

@ -9,11 +9,11 @@
[app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace :as dw]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.viewport.grid-layout-editor :refer [grid-edition-actions]]
[app.main.ui.workspace.viewport.path-actions :refer [path-actions]]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@ -56,7 +56,7 @@
[:div.viewport-actions-title
[:& i18n/tr-html {:tag-name "span"
:label "workspace.top-bar.read-only"}]]
[:button.btn-primary {:on-click handle-close-view-mode} "Done"]
[:button.btn-primary {:on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]
[:button.btn-icon-basic {:on-click handle-close-view-mode} i/close]]]
path-edition?
@ -64,10 +64,4 @@
[:& path-actions {:shape shape}]]
grid-edition?
[:div.viewport-actions
[:div.viewport-actions-container
[:div.viewport-actions-title
(tr "workspace.layout_grid.editor.title") " " [:span.grid-edit-board-name (:name shape)]]
[:button.btn-secondary {:on-click #(st/emit! (dwge/locate-board (:id shape)))} "Locate"]
[:button.btn-primary {:on-click #(st/emit! dw/clear-edition-mode)} "Done"]
[:button.btn-icon-basic {:on-click #(st/emit! dw/clear-edition-mode)} i/close]]])))
[:& grid-edition-actions {:shape shape}])))

View file

@ -3462,6 +3462,18 @@ msgstr "Zoom to selected"
msgid "workspace.layout_grid.editor.title"
msgstr "Editing grid"
msgid "workspace.layout_grid.editor.top-bar.locate"
msgstr "Locate"
msgid "workspace.layout_grid.editor.top-bar.done"
msgstr "Done"
msgid "workspace.layout_grid.editor.options.edit-grid"
msgstr "Edit grid"
msgid "workspace.layout_grid.editor.options.exit"
msgstr "Exit"
#: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.add"
msgstr "Add"
@ -4994,6 +5006,9 @@ msgstr "Click to close the path"
msgid "workspace.top-bar.read-only"
msgstr "**Inspect mode** (View Only)"
msgid "workspace.top-bar.read-only.done"
msgstr "Done"
msgid "media.image"
msgstr "Image"

View file

@ -3536,6 +3536,18 @@ msgstr "Zoom a selección"
msgid "workspace.layout_grid.editor.title"
msgstr "Editando rejilla"
msgid "workspace.layout_grid.editor.top-bar.locate"
msgstr "Mostrar"
msgid "workspace.layout_grid.editor.top-bar.done"
msgstr "Hecho"
msgid "workspace.layout_grid.editor.options.edit-grid"
msgstr "Editar rejilla"
msgid "workspace.layout_grid.editor.options.exit"
msgstr "Salir"
#: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.add"
msgstr "Añadir"
@ -5095,6 +5107,9 @@ msgstr "Pulsar para cerrar la ruta"
msgid "workspace.top-bar.read-only"
msgstr "**Modo inspección** (View only)"
msgid "workspace.top-bar.read-only.done"
msgstr "Hecho"
msgid "media.image"
msgstr "Imagen"