diff --git a/frontend/resources/images/icons/size-horiz.svg b/frontend/resources/images/icons/size-horiz.svg
new file mode 100644
index 0000000000..95c19749c9
--- /dev/null
+++ b/frontend/resources/images/icons/size-horiz.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/resources/images/icons/size-vert.svg b/frontend/resources/images/icons/size-vert.svg
new file mode 100644
index 0000000000..7cb95722f3
--- /dev/null
+++ b/frontend/resources/images/icons/size-vert.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json
index 3f9f493395..a894db5ae7 100644
--- a/frontend/resources/locales.json
+++ b/frontend/resources/locales.json
@@ -1,12 +1,12 @@
{
"dashboard.grid.delete" : {
- "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:72", "src/uxbox/main/ui/dashboard/grid.cljs:92" ],
+ "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:63", "src/uxbox/main/ui/dashboard/grid.cljs:92" ],
"translations" : {
"en" : "Delete"
}
},
"dashboard.grid.edit" : {
- "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:71", "src/uxbox/main/ui/dashboard/grid.cljs:91" ],
+ "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:62", "src/uxbox/main/ui/dashboard/grid.cljs:91" ],
"translations" : {
"en" : "Edit"
}
@@ -45,7 +45,7 @@
"unused" : true
},
"dashboard.header.new-file" : {
- "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:77" ],
+ "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:74" ],
"translations" : {
"en" : "+ New file"
}
@@ -78,7 +78,7 @@
}
},
"dashboard.header.project" : {
- "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:73" ],
+ "used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:70" ],
"translations" : {
"en" : "Project %s"
}
@@ -548,7 +548,7 @@
}
},
"header.sitemap" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:154" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:158" ],
"translations" : {
"en" : null,
"fr" : null
@@ -658,7 +658,7 @@
}
},
"profile.recovery.go-to-login" : {
- "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:81", "src/uxbox/main/ui/profile/recovery_request.cljs:65" ],
+ "used-in" : [ "src/uxbox/main/ui/profile/recovery_request.cljs:65", "src/uxbox/main/ui/profile/recovery.cljs:81" ],
"translations" : {
"en" : "Go back!",
"fr" : "Retour!"
@@ -980,61 +980,61 @@
"unused" : true
},
"workspace.header.menu.hide-grid" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:104" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:108" ],
"translations" : {
"en" : "Hide grid"
}
},
"workspace.header.menu.hide-layers" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:111" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:115" ],
"translations" : {
"en" : "Hide layers"
}
},
"workspace.header.menu.hide-libraries" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:125" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:129" ],
"translations" : {
"en" : "Hide libraries"
}
},
"workspace.header.menu.hide-palette" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:118" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:122" ],
"translations" : {
"en" : "Hide color palette"
}
},
"workspace.header.menu.hide-rules" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:97" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:101" ],
"translations" : {
"en" : "Hide rules"
}
},
"workspace.header.menu.show-grid" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:105" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:109" ],
"translations" : {
"en" : "Show grid"
}
},
"workspace.header.menu.show-layers" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:112" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:116" ],
"translations" : {
"en" : "Show layers"
}
},
"workspace.header.menu.show-libraries" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:126" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:130" ],
"translations" : {
"en" : "Show libraries"
}
},
"workspace.header.menu.show-palette" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:119" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:123" ],
"translations" : {
"en" : "Show color palette"
}
},
"workspace.header.menu.show-rules" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:98" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:102" ],
"translations" : {
"en" : "Show rules"
}
@@ -1075,43 +1075,43 @@
"unused" : true
},
"workspace.library.all" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:106" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:119" ],
"translations" : {
"en" : "All libraries"
}
},
"workspace.library.icons" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:156" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:169" ],
"translations" : {
"en" : "Icons"
}
},
"workspace.library.images" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:161" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:174" ],
"translations" : {
"en" : "Images"
}
},
"workspace.library.libraries" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:138" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:151" ],
"translations" : {
"en" : "Libraries"
}
},
"workspace.library.own" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:107" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:120" ],
"translations" : {
"en" : "My libraries"
}
},
"workspace.library.store" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:108" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:121" ],
"translations" : {
"en" : "Store libraries"
}
},
"workspace.options.color" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81" ],
"translations" : {
"en" : "Color",
"fr" : "Couleur"
@@ -1153,7 +1153,7 @@
}
},
"workspace.options.measures" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:55", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:62", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:68" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:62", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:76", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66" ],
"translations" : {
"en" : "Size, position & rotation",
"fr" : "Taille, position et rotation"
@@ -1167,26 +1167,32 @@
}
},
"workspace.options.position" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:92", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:84", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:91", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:97" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:97", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:91", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:92", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:126", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:95" ],
"translations" : {
"en" : "Position",
"fr" : "Position"
}
},
"workspace.options.rotation-radius" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:107", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:114" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:107", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:112" ],
"translations" : {
"en" : "Rotation & Radius",
"fr" : "TODO"
}
},
"workspace.options.size" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:57", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:70" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:70", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:99", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:68" ],
"translations" : {
"en" : "Size",
"fr" : "Taille"
}
},
+ "workspace.options.size-presets" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:82" ],
+ "translations" : {
+ "en" : "Size presets"
+ }
+ },
"workspace.options.stroke" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:58" ],
"translations" : {
@@ -1265,7 +1271,7 @@
}
},
"workspace.viewport.click-to-close-path" : {
- "used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:335" ],
+ "used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:338" ],
"translations" : {
"en" : "Click to close the path"
}
diff --git a/frontend/resources/styles/common/dependencies/helpers.scss b/frontend/resources/styles/common/dependencies/helpers.scss
index 550575db89..01ff7c4f66 100644
--- a/frontend/resources/styles/common/dependencies/helpers.scss
+++ b/frontend/resources/styles/common/dependencies/helpers.scss
@@ -48,6 +48,10 @@ $br-big: 8px;
}
}
+.flex-grow {
+ flex-grow: 1;
+}
+
.column-half {
margin-right: $small;
}
diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss
index 0ba8537bb3..50d98d8583 100644
--- a/frontend/resources/styles/main/partials/sidebar-element-options.scss
+++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss
@@ -254,6 +254,63 @@
width: 100%;
}
+ .custom-select {
+ border: 1px solid $color-gray-40;
+ padding: $x-small $big $x-small $x-small;
+ position: relative;
+
+ .dropdown-button {
+ position: absolute;
+ right: $x-small;
+ top: $small;
+
+ svg {
+ fill: $color-gray-40;
+ height: 10px;
+ width: 10px;
+ }
+ }
+
+ .custom-select-dropdown {
+ position: absolute;
+ left: 0;
+ z-index: 12;
+ width: 200px;
+ max-height: 30rem;
+ min-width: 7rem;
+ overflow-y: auto;
+
+ background-color: $color-white;
+ border-radius: $br-small;
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
+
+ li {
+ color: $color-gray-60;
+ cursor: pointer;
+ font-size: $fs14;
+ display: flex;
+ padding: $small;
+
+ span {
+ color: $color-gray-20;
+ margin-left: auto;
+ }
+
+ &.dropdown-label:not(:first-child) {
+ border-top: 1px solid $color-gray-10;
+ }
+
+ &.dropdown-label span {
+ margin-left: 0;
+ }
+
+ &:hover {
+ background-color: $color-primary-lighter;
+ }
+ }
+ }
+ }
+
.editable-select {
position: relative;
width: 100%;
@@ -374,3 +431,20 @@
}
}
+
+.orientation-icon {
+ margin-left: $small;
+
+ svg {
+ stroke: $color-gray-40;
+ stroke-width: 30px;
+ height: 25px;
+ width: 25px;
+ }
+
+ &:hover {
+ svg {
+ stroke: $color-gray-10;
+ }
+ }
+}
diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss
index 1d453d55a2..ff623ca27d 100644
--- a/frontend/resources/styles/main/partials/workspace.scss
+++ b/frontend/resources/styles/main/partials/workspace.scss
@@ -173,3 +173,13 @@
}
}
+
+.workspace-frame-label {
+ fill: $color-gray-dark;
+ font-size: $fs12;
+}
+
+.selected .workspace-frame-label {
+ fill: $color-primary-dark;
+}
+
diff --git a/frontend/src/uxbox/builtins/icons.cljs b/frontend/src/uxbox/builtins/icons.cljs
index b34e70b709..08fdd76653 100644
--- a/frontend/src/uxbox/builtins/icons.cljs
+++ b/frontend/src/uxbox/builtins/icons.cljs
@@ -64,6 +64,8 @@
(def ruler-tool (icon-xref :ruler-tool))
(def save (icon-xref :save))
(def search (icon-xref :search))
+(def size-horiz (icon-xref :size-horiz))
+(def size-vert (icon-xref :size-vert))
(def stroke (icon-xref :stroke))
(def sublevel (icon-xref :sublevel))
(def text (icon-xref :text))
diff --git a/frontend/src/uxbox/main/ui/shapes/frame.cljs b/frontend/src/uxbox/main/ui/shapes/frame.cljs
index 328fd91948..d645b150aa 100644
--- a/frontend/src/uxbox/main/ui/shapes/frame.cljs
+++ b/frontend/src/uxbox/main/ui/shapes/frame.cljs
@@ -94,9 +94,14 @@
on-mouse-down #(common/on-mouse-down % shape)
on-context-menu #(common/on-context-menu % shape)
shape (merge frame-default-props shape)
+ {:keys [x y width height]} shape
childs (mapv #(get objects %) (:shapes shape))
+ ds-modifier (:displacement-modifier shape)
+ label-pos (cond-> (gpt/point x (- y 10))
+ (gmt/matrix? ds-modifier) (gpt/transform ds-modifier))
+
on-double-click
(fn [event]
(dom/prevent-default event)
@@ -106,6 +111,13 @@
:on-context-menu on-context-menu
:on-double-click on-double-click
:on-mouse-down on-mouse-down}
+ [:text {:x (:x label-pos)
+ :y (:y label-pos)
+ :width width
+ :height 20
+ :class-name "workspace-frame-label"
+ :on-click on-double-click} ; user may also select with single click in the label
+ (:name shape)]
[:& frame-shape {:shape shape :childs childs}]])))
(mf/defc frame-shape
diff --git a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs
index ab08719d34..6bd603bef1 100644
--- a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs
+++ b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs
@@ -53,6 +53,7 @@
:fill-opacity 0
:segments []}
{:type :frame
+ :stroke-style :none
:name "Artboard"}
{:type :curve
:name "Path"
diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs
index 09036b3142..b2a5bed6cf 100644
--- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs
+++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs
@@ -15,15 +15,36 @@
[uxbox.builtins.icons :as i]
[uxbox.main.data.workspace :as udw]
[uxbox.main.store :as st]
+ [uxbox.main.ui.components.dropdown :refer [dropdown]]
[uxbox.main.ui.workspace.sidebar.options.fill :refer [fill-menu]]
+ [uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-menu]]
[uxbox.util.dom :as dom]
[uxbox.util.geom.point :as gpt]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.math :as math]))
+(declare +size-presets+)
+
(mf/defc measures-menu
[{:keys [shape] :as props}]
- (let [on-size-change
+
+ (let [show-presets-dropdown? (mf/use-state false)
+
+ on-preset-selected
+ (fn [width height]
+ (st/emit! (udw/update-rect-dimensions (:id shape) :width width)
+ (udw/update-rect-dimensions (:id shape) :height height)))
+
+ on-orientation-clicked
+ (fn [orientation]
+ (let [width (:width shape)
+ height (:height shape)
+ new-width (if (= orientation :horiz) (max width height) (min width height))
+ new-height (if (= orientation :horiz) (min width height) (max width height))]
+ (st/emit! (udw/update-rect-dimensions (:id shape) :width new-width)
+ (udw/update-rect-dimensions (:id shape) :height new-height))))
+
+ on-size-change
(fn [event attr]
(let [value (-> (dom/get-target event)
(dom/get-value)
@@ -53,7 +74,28 @@
[:div.element-set
[:div.element-set-title (tr "workspace.options.measures")]
+
[:div.element-set-content
+
+ [:div.row-flex
+ [:div.custom-select.flex-grow {:on-click #(reset! show-presets-dropdown? true)}
+ [:span (tr "workspace.options.size-presets")]
+ [:span.dropdown-button i/arrow-down]
+ [:& dropdown {:show @show-presets-dropdown?
+ :on-close #(reset! show-presets-dropdown? false)}
+ [:ul.custom-select-dropdown
+ (for [size-preset +size-presets+]
+ (if-not (:width size-preset)
+ [:li.dropdown-label {:key (:name size-preset)}
+ [:span (:name size-preset)]]
+ [:li {:key (:name size-preset)
+ :on-click #(on-preset-selected (:width size-preset) (:height size-preset))}
+ (:name size-preset)
+ [:span (:width size-preset) " x " (:height size-preset)]]))]]]
+ [:span.orientation-icon {on-click #(on-orientation-clicked :vert)} i/size-vert]
+ [:span.orientation-icon {on-click #(on-orientation-clicked :horiz)} i/size-horiz]
+ ]
+
[:span (tr "workspace.options.size")]
;; WIDTH & HEIGHT
@@ -98,8 +140,67 @@
(math/precision 2)
(d/coalesce-str "0"))}]]]]]))
+(def +size-presets+
+ [{:name "APPLE"}
+ {:name "iPhone X"
+ :width 375
+ :height 812}
+ {:name "iPhone 6/7/8 Plus"
+ :width 414
+ :height 736}
+ {:name "iPhone 6/7/8"
+ :width 375
+ :height 667}
+ {:name "iPhone 5/SE"
+ :width 320
+ :height 568}
+ {:name "iPad"
+ :width 768
+ :height 1024}
+ {:name "iPad Pro 10.5in"
+ :width 834
+ :height 1112}
+ {:name "iPad Pro 12.9in"
+ :width 1024
+ :height 1366}
+ {:name "Watch 42mm"
+ :width 312
+ :height 390}
+ {:name "Watch 38mm"
+ :width 272
+ :height 340}
+
+ {:name "GOOGLE"}
+ {:name "Android mobile"
+ :width 360
+ :height 640}
+ {:name "Android tablet"
+ :width 768
+ :height 1024}
+
+ {:name "MICROSOFT"}
+ {:name "Surface Pro 3"
+ :width 1440
+ :height 960}
+ {:name "Surface Pro 4"
+ :width 1368
+ :height 912}
+
+ {:name "WEB"}
+ {:name "Web 1280"
+ :width 1280
+ :height 800}
+ {:name "Web 1366"
+ :width 1366
+ :height 768}
+ {:name "Web 1920"
+ :width 1920
+ :height 1080}
+ ])
+
(mf/defc options
[{:keys [shape] :as props}]
[:div
[:& measures-menu {:shape shape}]
- [:& fill-menu {:shape shape}]])
+ [:& fill-menu {:shape shape}]
+ [:& stroke-menu {:shape shape}]])