mirror of https://github.com/penpot/penpot.git
Merge pull request #6992 from penpot/niwinz-artboard-defaults
✨ Add defaults for artboard drawing
This commit is contained in:
commit
e43b6fb0b7
|
|
@ -9,6 +9,7 @@
|
|||
### :heart: Community contributions (Thank you!)
|
||||
|
||||
### :sparkles: New features & Enhancements
|
||||
- Add defaults for artboard drawing [Taiga #494](https://tree.taiga.io/project/penpot/us/494?milestone=465047)
|
||||
|
||||
- Continuous display of distances between elements when moving a layer with the keyboard [Taiga #1780](https://tree.taiga.io/project/penpot/issue/1780)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"Drawing interactions."
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.drawing.box :as box]
|
||||
|
|
@ -100,5 +101,37 @@
|
|||
:curve (curve/handle-drawing)
|
||||
(box/handle-drawing type))))))
|
||||
|
||||
(defn change-orientation
|
||||
[orientation]
|
||||
|
||||
(assert
|
||||
(contains? #{:horizontal :vertical} orientation)
|
||||
"expected valid orientation")
|
||||
|
||||
(ptk/reify ::change-orientation
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [width height]}
|
||||
(get state :workspace-drawing)
|
||||
|
||||
width'
|
||||
(if (= orientation :vertical)
|
||||
(mth/min width height)
|
||||
(mth/max width height))
|
||||
|
||||
height'
|
||||
(if (= orientation :vertical)
|
||||
(mth/max width height)
|
||||
(mth/min width height))]
|
||||
|
||||
(update state :workspace-drawing assoc :width width' :height height')))))
|
||||
|
||||
(defn set-default-size
|
||||
[width height]
|
||||
(ptk/reify ::change-preset
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing assoc :width width :height height))))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@
|
|||
|
||||
(ns app.main.data.workspace.drawing.common
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.shape :as cts]
|
||||
|
|
@ -25,27 +23,35 @@
|
|||
(ptk/reify ::clear-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing dissoc :tool :object))))
|
||||
(dissoc state :workspace-drawing))))
|
||||
|
||||
(defn handle-finish-drawing
|
||||
[]
|
||||
(ptk/reify ::handle-finish-drawing
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [tool (dm/get-in state [:workspace-drawing :tool])
|
||||
shape (dm/get-in state [:workspace-drawing :object])
|
||||
objects (dsh/lookup-page-objects state)
|
||||
page-id (:current-page-id state)]
|
||||
(let [drawing-state
|
||||
(get state :workspace-drawing)
|
||||
|
||||
shape
|
||||
(get drawing-state :object)
|
||||
|
||||
tool
|
||||
(get drawing-state :tool)
|
||||
|
||||
objects
|
||||
(dsh/lookup-page-objects state)
|
||||
|
||||
page-id
|
||||
(:current-page-id state)]
|
||||
|
||||
(rx/concat
|
||||
(when (:initialized? shape)
|
||||
(let [click-draw? (:click-draw? shape)
|
||||
text? (cfh/text-shape? shape)
|
||||
vbox (dm/get-in state [:workspace-local :vbox])
|
||||
|
||||
min-side (mth/min 100
|
||||
(mth/floor (dm/get-prop vbox :width))
|
||||
(mth/floor (dm/get-prop vbox :height)))
|
||||
width (get drawing-state :width 100)
|
||||
height (get drawing-state :height 100)
|
||||
|
||||
shape
|
||||
(cond-> shape
|
||||
|
|
@ -53,14 +59,14 @@
|
|||
(assoc :grow-type :fixed)
|
||||
|
||||
(and ^boolean click-draw? (not ^boolean text?))
|
||||
(-> (assoc :width min-side)
|
||||
(assoc :height min-side)
|
||||
(-> (assoc :width width)
|
||||
(assoc :height height)
|
||||
;; NOTE: we need to recalculate the selrect and
|
||||
;; points, so we assign `nil` to it
|
||||
(assoc :selrect nil)
|
||||
(assoc :points nil)
|
||||
(cts/setup-shape)
|
||||
(gsh/transform-shape (ctm/move-modifiers (- (/ min-side 2)) (- (/ min-side 2)))))
|
||||
(gsh/transform-shape (ctm/move-modifiers (- (/ width 2)) (- (/ height 2)))))
|
||||
|
||||
(and click-draw? text?)
|
||||
(-> (assoc :height 17 :width 4 :grow-type :auto-width)
|
||||
|
|
|
|||
|
|
@ -551,9 +551,7 @@
|
|||
|
||||
(defn start-move-selected
|
||||
"Enter mouse move mode, until mouse button is released."
|
||||
([]
|
||||
(start-move-selected nil false))
|
||||
|
||||
([] (start-move-selected nil false))
|
||||
([id shift?]
|
||||
(ptk/reify ::start-move-selected
|
||||
ptk/WatchEvent
|
||||
|
|
@ -972,8 +970,9 @@
|
|||
(defn move-selected
|
||||
"Move shapes a fixed increment in one direction, from a keyboard action."
|
||||
[direction shift?]
|
||||
(dm/assert! (contains? valid-directions direction))
|
||||
(dm/assert! (boolean? shift?))
|
||||
|
||||
(assert (contains? valid-directions direction))
|
||||
(assert (boolean? shift?))
|
||||
|
||||
(ptk/reify ::move-selected
|
||||
ptk/WatchEvent
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.inspect.right-sidebar :as hrs]
|
||||
[app.main.ui.workspace.sidebar.options.drawing :as drawing]
|
||||
[app.main.ui.workspace.sidebar.options.menus.align :refer [align-options]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.bool :refer [bool-options]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
|
||||
|
|
@ -109,11 +110,8 @@
|
|||
[:& specialized-panel {:panel sp-panel}]
|
||||
|
||||
(d/not-empty? drawing)
|
||||
[:> shape-options*
|
||||
{:shape (:object drawing)
|
||||
:page-id page-id
|
||||
:file-id file-id
|
||||
:libraries libraries}]
|
||||
[:> drawing/drawing-options*
|
||||
{:drawing-state drawing}]
|
||||
|
||||
(= 0 (count selected))
|
||||
[:> page/options*]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.drawing
|
||||
(:require
|
||||
[app.main.ui.workspace.sidebar.options.drawing.frame :as frame]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc drawing-options*
|
||||
{::mf/wrap [#(mf/throttle % 60)]
|
||||
::mf/private true}
|
||||
[{:keys [drawing-state] :as props}]
|
||||
(case (:tool drawing-state)
|
||||
:frame
|
||||
[:> frame/options* {:drawing-state drawing-state}]
|
||||
|
||||
nil))
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.drawing.frame
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.constants :refer [size-presets]]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options*
|
||||
[{:keys [drawing-state]}]
|
||||
|
||||
(let [show* (mf/use-state false)
|
||||
show? (deref show*)
|
||||
|
||||
selected-preset-name*
|
||||
(mf/use-state nil)
|
||||
|
||||
selected-preset-name
|
||||
(deref selected-preset-name*)
|
||||
|
||||
on-open
|
||||
(mf/use-fn (fn [] (reset! show* true)))
|
||||
|
||||
on-close
|
||||
(mf/use-fn (fn [] (reset! show* false)))
|
||||
|
||||
on-preset-selected
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [target (dom/get-current-target event)
|
||||
name (dom/get-data target "name")
|
||||
width (-> (dom/get-data target "width")
|
||||
(d/read-string))
|
||||
height (-> (dom/get-data target "height")
|
||||
(d/read-string))]
|
||||
|
||||
(reset! selected-preset-name* name)
|
||||
(st/emit! (dwd/set-default-size width height)))))
|
||||
|
||||
orientation
|
||||
(when (:width drawing-state)
|
||||
(if (> (:width drawing-state) (:height drawing-state))
|
||||
:horizontal
|
||||
:vertical))
|
||||
|
||||
on-orientation-change
|
||||
(mf/use-fn
|
||||
(fn [orientation]
|
||||
(let [orientation (keyword orientation)]
|
||||
(st/emit! (dwd/change-orientation orientation)))))]
|
||||
|
||||
[:div {:class (stl/css :presets)}
|
||||
[:div {:class (stl/css-case :presets-wrapper true
|
||||
:opened show?)
|
||||
:on-click on-open}
|
||||
[:span {:class (stl/css :select-name)}
|
||||
(or selected-preset-name
|
||||
(tr "workspace.options.size-presets"))]
|
||||
[:span {:class (stl/css :collapsed-icon)} i/arrow]
|
||||
[:& dropdown {:show show?
|
||||
:on-close on-close}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)}
|
||||
(for [preset size-presets]
|
||||
(if-not (:width preset)
|
||||
[:li {:key (:name preset)
|
||||
:class (stl/css-case :dropdown-element true
|
||||
:disabled true)}
|
||||
[:span {:class (stl/css :preset-name)} (:name preset)]]
|
||||
|
||||
(let [preset-match (and (= (:width preset) (:width drawing-state))
|
||||
(= (:height preset) (:height drawing-state)))]
|
||||
[:li {:key (:name preset)
|
||||
:class (stl/css-case :dropdown-element true
|
||||
:match preset-match)
|
||||
:data-width (str (:width preset))
|
||||
:data-height (str (:height preset))
|
||||
:data-name (:name preset)
|
||||
:on-click on-preset-selected}
|
||||
[:div {:class (stl/css :name-wrapper)}
|
||||
[:span {:class (stl/css :preset-name)} (:name preset)]
|
||||
[:span {:class (stl/css :preset-size)} (:width preset) " x " (:height preset)]]
|
||||
(when preset-match
|
||||
[:span {:class (stl/css :check-icon)} i/tick])])))]]]
|
||||
|
||||
[:& radio-buttons {:selected (or (d/name orientation) "")
|
||||
:on-change on-orientation-change
|
||||
:name "frame-orientation"
|
||||
:wide true
|
||||
:class (stl/css :radio-buttons)}
|
||||
[:& radio-button {:icon i/size-vertical
|
||||
:value "vertical"
|
||||
:id "size-vertical"}]
|
||||
[:& radio-button {:icon i/size-horizontal
|
||||
:value "horizontal"
|
||||
:id "size-horizontal"}]]]))
|
||||
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// 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 "../../../../ds/_sizes.scss";
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.presets {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, var(--sp-xxxl));
|
||||
gap: var(--sp-xs);
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.presets-wrapper {
|
||||
@extend .asset-element;
|
||||
position: relative;
|
||||
grid-column: span 6;
|
||||
display: flex;
|
||||
height: $s-32;
|
||||
padding: $s-8;
|
||||
border-radius: $br-8;
|
||||
|
||||
.collapsed-icon {
|
||||
@include flexCenter;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.collapsed-icon svg {
|
||||
stroke: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radio-buttons {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.select-name {
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-select-dropdown {
|
||||
@extend .dropdown-wrapper;
|
||||
margin-top: $s-2;
|
||||
max-height: 70vh;
|
||||
width: $s-252;
|
||||
.dropdown-element {
|
||||
@extend .dropdown-element-base;
|
||||
.name-wrapper {
|
||||
display: flex;
|
||||
gap: $s-8;
|
||||
flex-grow: 1;
|
||||
.preset-name {
|
||||
color: var(--menu-foreground-color-rest);
|
||||
}
|
||||
.preset-size {
|
||||
color: var(--menu-foreground-color-rest);
|
||||
}
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
.preset-name {
|
||||
color: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.match {
|
||||
.name-wrapper .preset-name {
|
||||
color: var(--menu-foreground-color-hover);
|
||||
}
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
.name-wrapper .preset-name {
|
||||
color: var(--menu-foreground-color-hover);
|
||||
}
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -338,6 +338,7 @@
|
|||
:aria-label (tr "workspace.options.fit-content")
|
||||
:on-pointer-down handle-fit-content
|
||||
:icon "fit-content"}]])
|
||||
|
||||
(when (options :size)
|
||||
[:div {:class (stl/css :size)}
|
||||
[:div {:class (stl/css-case :width true
|
||||
|
|
|
|||
Loading…
Reference in New Issue