diff --git a/resources/public/images/svg/picker.svg b/resources/public/images/svg/picker.svg
new file mode 100644
index 0000000000..a8289a958b
--- /dev/null
+++ b/resources/public/images/svg/picker.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/styles/dependencies/helpers.scss b/resources/styles/dependencies/helpers.scss
index 5f050a678a..26a81fc4fe 100644
--- a/resources/styles/dependencies/helpers.scss
+++ b/resources/styles/dependencies/helpers.scss
@@ -29,7 +29,7 @@ $br-big: 8px;
.row-flex {
align-items: center;
display: flex;
- margin-bottom: $x-small;
+ margin-bottom: $small;
&.column {
flex-direction: column;
diff --git a/resources/styles/partials/colorpicker.scss b/resources/styles/partials/colorpicker.scss
index 5d6be9d3eb..b81d861161 100644
--- a/resources/styles/partials/colorpicker.scss
+++ b/resources/styles/partials/colorpicker.scss
@@ -7,94 +7,191 @@
.color-picker {
display: flex;
+ flex-direction: column;
- /* Common stuff */
- .picker-wrapper,
- .slide-wrapper {
- position: relative;
+ .picker-area {
+ display: flex;
+
+ /* Common stuff */
+ .picker-wrapper,
+ .slide-wrapper {
+ position: relative;
+ }
+ .picker-indicator,
+ .slide-indicator {
+ position: absolute;
+ left: 0;
+ top: 0;
+ pointer-events: none;
+ }
+ .picker,
+ .slide {
+ cursor: crosshair;
+ }
}
- .picker-indicator,
- .slide-indicator {
- position: absolute;
- left: 0;
- top: 0;
- pointer-events: none;
- }
- .picker,
- .slide {
- cursor: crosshair;
- }
-}
-/* Default skin */
-
-.color-picker-default {
- padding: 4px;
- border-radius: 2px;
-
- .picker {
+ .inputs-area {
+ display: flex;
+ justify-content: space-around;
width: 200px;
- height: 200px;
+
+ .row-flex{
+ margin: 0;
+ }
+
+ > input {
+ width: 50%;
+ }
+
+ .input-text {
+ color: $intense-ui-text;
+ font-size: $fs13;
+ margin: 5px;
+ padding: 5px;
+ width: 100%;
+ }
+
}
- .slide {
- width: 20px;
- height: 200px;
+ span {
+ color: $medium-ui-text;
+ font-size: $fs12;
}
- .slide-wrapper {
- margin-left: 4px;
+
+
+ /* Default skin */
+
+ &.theme-default {
+ padding: 4px;
+ border-radius: 2px;
+ width: 230px;
+
+ .picker {
+ width: 200px;
+ height: 200px;
+ }
+
+ .slide {
+ width: 20px;
+ height: 200px;
+ }
+ .slide-wrapper {
+ margin-left: 4px;
+ }
+ .picker-indicator {
+ width: 5px;
+ height: 5px;
+ border: 2px solid darkblue;
+ border-radius: 4px;
+ opacity: .5;
+ background-color: white;
+ }
+ .slide-indicator {
+ width: 28px;
+ height: 10px;
+ left: -4px;
+ opacity: .6;
+ border: 4px solid lightblue;
+ border-radius: 4px;
+ background-color: white;
+ }
+
+ .inputs-area {
+ width: 230px;
+ }
+
}
- .picker-indicator {
- width: 5px;
- height: 5px;
- border: 2px solid darkblue;
- border-radius: 4px;
- opacity: .5;
- background-color: white;
+
+ /* Small skin */
+
+ &.theme-small {
+ border-radius: 2px;
+
+ .picker {
+ width: 170px;
+ height: 170px;
+ }
+
+ .slide {
+ width: 20px;
+ height: 170px;
+ }
+ .slide-wrapper {
+ margin-left: 4px;
+ }
+ .picker-indicator {
+ width: 5px;
+ height: 5px;
+ border: 2px solid darkblue;
+ border-radius: 4px;
+ opacity: .5;
+ background-color: white;
+ }
+ .slide-indicator {
+ width: 28px;
+ height: 10px;
+ left: -4px;
+ opacity: .6;
+ border: 4px solid lightblue;
+ border-radius: 4px;
+ background-color: white;
+ }
+
}
- .slide-indicator {
- width: 28px;
- height: 10px;
- left: -4px;
- opacity: .6;
- border: 4px solid lightblue;
- border-radius: 4px;
- background-color: white;
+
+}
+
+/* NEW COLOR PICKER */
+/* color th */
+.color-data {
+ align-items: center;
+ display: flex;
+ position: relative;
+
+ .color-info {
+ border: 1px solid $soft-ui-border;
+ border-radius: $br-small;
+ margin: 3px 0 0 $x-small;
+ padding: 0 $x-small;
+ }
+
+ .type {
+ color: $soft-ui-text;
+ margin-right: $x-small;
+ }
+
+ .number {
+ color: $intense-ui-text;
}
}
-/* Small skin */
+.colorpicker-tooltip {
+ background: $color-white;
+ border-radius: $br-small;
+ display: flex;
+ flex-direction: column;
+ left: 1400px;
+ top: 100px;
+ padding: $small;
+ position: absolute;
+ z-index: 11;
+ width: auto;
-.color-picker-small {
- border-radius: 2px;
-
- .picker {
- width: 170px;
- height: 170px;
+ span {
+ color: $medium-ui-text;
+ font-size: $fs12;
}
- .slide {
- width: 20px;
- height: 170px;
- }
- .slide-wrapper {
- margin-left: 4px;
- }
- .picker-indicator {
- width: 5px;
- height: 5px;
- border: 2px solid darkblue;
- border-radius: 4px;
- opacity: .5;
- background-color: white;
- }
- .slide-indicator {
- width: 28px;
- height: 10px;
- left: -4px;
- opacity: .6;
- border: 4px solid lightblue;
- border-radius: 4px;
- background-color: white;
+ .inputs-area {
+
+ .input-text {
+ color: $intense-ui-text;
+ font-size: $fs13;
+ margin: 5px;
+ padding: 5px;
+ width: 100%;
+ }
+
}
+
}
diff --git a/resources/styles/partials/lightbox.scss b/resources/styles/partials/lightbox.scss
index b602ab2b08..0eb2364c47 100644
--- a/resources/styles/partials/lightbox.scss
+++ b/resources/styles/partials/lightbox.scss
@@ -17,6 +17,10 @@
width: 100%;
z-index: 1000;
+ &.transparent {
+ background-color: rgba(0,0,0,0);
+ }
+
.lightbox-body {
align-items: center;
background-color: $color-white;
diff --git a/resources/styles/partials/sidebar-element-options.scss b/resources/styles/partials/sidebar-element-options.scss
index 9528c8d03d..cf09de28f1 100644
--- a/resources/styles/partials/sidebar-element-options.scss
+++ b/resources/styles/partials/sidebar-element-options.scss
@@ -150,14 +150,14 @@
&.palette-th {
align-items: center;
- border: 2px solid $medium-ui-icons;
+ border: 1px solid $medium-ui-icons;
display: flex;
justify-content: center;
svg {
fill: $medium-ui-icons;
- height: 18px;
- width: 18px;
+ height: 16px;
+ width: 16px;
}
&:hover {
diff --git a/src/uxbox/ui/auth.cljs b/src/uxbox/ui/auth.cljs
index c3643551da..cad763888b 100644
--- a/src/uxbox/ui/auth.cljs
+++ b/src/uxbox/ui/auth.cljs
@@ -1,3 +1,9 @@
+;; 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) 2016 Andrey Antukh
+
(ns uxbox.ui.auth
(:require [sablono.core :as html :refer-macros [html]]
[lentes.core :as l]
diff --git a/src/uxbox/ui/colorpicker.cljs b/src/uxbox/ui/colorpicker.cljs
index b0fc66260c..b8486238c1 100644
--- a/src/uxbox/ui/colorpicker.cljs
+++ b/src/uxbox/ui/colorpicker.cljs
@@ -10,9 +10,11 @@
[lentes.core :as l]
[goog.events :as events]
[uxbox.schema :as sc]
- [uxbox.util.color :as color]
+ [uxbox.ui.mixins :as mx]
[uxbox.util.math :as mth]
- [uxbox.ui.mixins :as mx])
+ [uxbox.util.data :as data]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.color :as color])
(:import goog.events.EventType))
;; --- Picker Box
@@ -115,6 +117,10 @@
[own & {:keys [value on-change theme]
:or {value "#d4edfb" theme :default}}]
(let [local (:rum/local own)
+ value-rgb (color/hex->rgb value)
+ classes (case theme
+ :default "theme-default"
+ :small "theme-small")
dimensions (case theme
:default default-dimensions
:small small-dimensions
@@ -128,47 +134,88 @@
(/ (:pi-width dimensions) 2))
sit (- (/ (* (- h 15) (:s-height dimensions)) 360)
- (/ (:si-height dimensions) 2))
+ (/ (:si-height dimensions) 2))]
+ (letfn [(on-mouse-down [event]
+ (swap! local assoc :mousedown true))
+ (on-mouse-up [event]
+ (swap! local assoc :mousedown false))
+ (on-mouse-move-slide [event]
+ (when (:mousedown @local)
+ (on-slide-click local dimensions event)))
+ (on-mouse-move-picker [event]
+ (when (:mousedown @local)
+ (on-picker-click local dimensions on-change color event)))
+ (on-hex-changed [event]
+ (let [value (-> (dom/get-target event)
+ (dom/get-value))]
+ (when (color/hex? value)
+ (on-change value))))
+ (on-rgb-change [rgb id event]
+ (let [value (-> (dom/get-target event)
+ (dom/get-value)
+ (data/parse-int 0))
+ rgb (assoc rgb id value)
+ hex (color/rgb->hex rgb)]
+ (when (color/hex? hex)
+ (on-change hex))))]
+ (html
+ [:div.color-picker {:class classes}
+ [:div.picker-area
+ #_[:div.tester {:style {:width "100px" :height "100px"
+ :border "1px solid black"
+ :position "fixed" :top "50px" :left "50px"
+ :backgroundColor (color/hsv->hex color)}}]
+ [:div.picker-wrapper
+ [:div.picker
+ {:ref "picker"
+ :on-click (partial on-picker-click local dimensions on-change color)
+ :on-mouse-down on-mouse-down
+ :on-mouse-up on-mouse-up
+ :on-mouse-move on-mouse-move-picker
+ :style {:backgroundColor bg}}
+ (picker-box)]
+ [:div.picker-indicator
+ {:ref "picker-indicator"
+ :style {:top (str pil "px")
+ :left (str pit "px")
+ :pointerEvents "none"}}]]
+ [:div.slide-wrapper
+ [:div.slide
+ {:ref "slide"
+ :on-mouse-down on-mouse-down
+ :on-mouse-up on-mouse-up
+ :on-mouse-move on-mouse-move-slide
+ :on-click (partial on-slide-click local dimensions)}
+ (slider-box)]
+ [:div.slide-indicator
+ {:ref "slide-indicator"
+ :style {:top (str sit "px")
+ :pointerEvents "none"}}]]]
+
+ [:div.inputs-area
+ [:input.input-text
+ {:placeholder "#"
+ :type "text"
+ :value value
+ :on-change on-hex-changed}]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "R"
+ :on-change (partial on-rgb-change value-rgb 0)
+ :value (nth value-rgb 0)
+ :type "number"}]
+ [:input.input-text
+ {:placeholder "G"
+ :on-change (partial on-rgb-change value-rgb 1)
+ :value (nth value-rgb 1)
+ :type "number"}]
+ [:input.input-text
+ {:placeholder "B"
+ :on-change (partial on-rgb-change value-rgb 2)
+ :value (nth value-rgb 2)
+ :type "number"}]]]]))))
- on-mouse-down #(swap! local assoc :mousedown true)
- on-mouse-up #(swap! local assoc :mousedown false)
- on-mouse-move-slide #(when (:mousedown @local)
- (on-slide-click local dimensions %))
- on-mouse-move-picker #(when (:mousedown @local)
- (on-picker-click local dimensions on-change color %))]
- (html
- [:div.color-picker
- #_[:div.tester {:style {:width "100px" :height "100px"
- :border "1px solid black"
- :position "fixed" :top "50px" :left "50px"
- :backgroundColor (color/hsv->hex color)}}]
- [:div.picker-wrapper
- [:div.picker
- {:ref "picker"
- :on-click (partial on-picker-click local dimensions on-change color)
- :on-mouse-down on-mouse-down
- :on-mouse-up on-mouse-up
- :on-mouse-move on-mouse-move-picker
- :style {:backgroundColor bg}}
- (picker-box)]
- [:div.picker-indicator
- {:ref "picker-indicator"
- :style {:top (str pil "px")
- :left (str pit "px")
- :pointerEvents "none"}}]]
- [:div.slide-wrapper
- [:div.slide
- {:ref "slide"
- :on-mouse-down on-mouse-down
- :on-mouse-up on-mouse-up
- :on-mouse-move on-mouse-move-slide
- :on-click (partial on-slide-click local dimensions)}
- (slider-box)]
- [:div.slide-indicator
- {:ref "slide-indicator"
- :style {:top (str sit "px")
- :pointerEvents "none"}}]]])))
(def ^:static colorpicker
(mx/component
diff --git a/src/uxbox/ui/dashboard/colors.cljs b/src/uxbox/ui/dashboard/colors.cljs
index 5e6294e70d..31fd7d07a9 100644
--- a/src/uxbox/ui/dashboard/colors.cljs
+++ b/src/uxbox/ui/dashboard/colors.cljs
@@ -265,14 +265,7 @@
[:div.lightbox-body
[:h3 "New color"]
[:form
- [:div.row-flex
- [:input#color-hex.input-text
- {:placeholder "#"
- :class (form/error-class local :hex)
- :on-change on-change
- :value (or (:hex @local) color "")
- :type "text"}]]
- [:div.row-flex.center.color-picker-default
+ [:div.row-flex.center
(colorpicker
:value (or (:hex @local) color "#00ccff")
:on-change #(swap! local assoc :hex %))]
diff --git a/src/uxbox/ui/icons.cljs b/src/uxbox/ui/icons.cljs
index 12426d1769..7058ecfa03 100644
--- a/src/uxbox/ui/icons.cljs
+++ b/src/uxbox/ui/icons.cljs
@@ -680,3 +680,14 @@
{:style {:stroke nil}
:d
"M34 6h-24c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h28c2.21 0 4-1.79 4-4v-24l-8-8zm-10 32c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm6-20h-20v-8h20v8z"}]]))
+
+(def picker
+ (html
+ [:svg
+ {:viewBox "0 0 500.00001 500.00001"
+ :height "500"
+ :width "500"}
+ [:g
+ [:path
+ {:d
+ "M11.402 498.536c-4.64-1.613-8.317-5.335-9.896-10.02-.732-2.168-.824-7.17-.824-44.7 0-45.853-.04-45.148 2.807-49.542.653-1.01 53.238-53.866 116.855-117.46 63.617-63.59 115.667-115.852 115.667-116.134 0-.282-11.486-11.997-25.524-26.033-14.038-14.036-25.524-25.75-25.524-26.034 0-.283 14.816-15.328 32.924-33.434l32.924-32.922 29.607 29.59 29.607 29.592 44.286-44.17c32.81-32.726 45.278-44.843 48.115-46.76 7.434-5.025 16.28-8.752 24.758-10.432 5.316-1.053 18.308-.91 23.737.26 25.043 5.4 44.058 24.808 49.064 50.08.927 4.68.927 17.78 0 22.46-1.68 8.48-5.407 17.326-10.432 24.76-1.917 2.836-14.034 15.303-46.76 48.114l-44.17 44.286 29.59 29.608 29.592 29.608-32.92 32.923c-18.107 18.108-33.152 32.924-33.435 32.924-.283 0-11.998-11.485-26.034-25.523s-25.75-25.524-26.033-25.524c-.282 0-52.543 52.05-116.135 115.667-63.593 63.617-116.45 116.202-117.46 116.856-4.4 2.85-3.662 2.81-49.686 2.783-37.102-.023-42.692-.126-44.702-.824zM199.638 353.77C262.6 290.81 314.115 239.07 314.115 238.79c0-.67-52.165-52.838-52.834-52.838-.282 0-52.026 51.515-114.986 114.477L31.82 414.904v26.057c0 19.588.153 26.21.614 26.67.46.462 7.084.614 26.67.614H85.16L199.64 353.77z"}]]]))
diff --git a/src/uxbox/ui/lightbox.cljs b/src/uxbox/ui/lightbox.cljs
index 66f28ce806..186f0b7cd1 100644
--- a/src/uxbox/ui/lightbox.cljs
+++ b/src/uxbox/ui/lightbox.cljs
@@ -6,6 +6,8 @@
[uxbox.data.lightbox :as udl]
[uxbox.ui.mixins :as mx]
[uxbox.ui.keyboard :as k]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (classnames)]
[goog.events :as events])
(:import goog.events.EventType))
@@ -21,9 +23,17 @@
(defmethod render-lightbox :default [_] nil)
(defn- on-esc-clicked
- [e]
- (when (k/esc? e)
- (udl/close!)))
+ [event]
+ (when (k/esc? event)
+ (udl/close!)
+ (dom/stop-propagation event)))
+
+(defn- on-out-clicked
+ [own event]
+ (let [parent (mx/get-ref-dom own "parent")
+ current (dom/get-target event)]
+ (when (dom/equals? parent current)
+ (udl/close!))))
(defn- lightbox-will-mount
[own]
@@ -43,10 +53,15 @@
(defn- lightbox-render
[own]
- (let [data (rum/react lightbox-l)]
+ (let [data (rum/react lightbox-l)
+ classes (classnames
+ :hide (nil? data)
+ :transparent (:transparent? data))]
(html
[:div.lightbox
- {:class (when (nil? data) "hide")}
+ {:class classes
+ :ref "parent"
+ :on-click (partial on-out-clicked own)}
(render-lightbox data)])))
(def lightbox
diff --git a/src/uxbox/ui/users.cljs b/src/uxbox/ui/users.cljs
index e89f0d10c8..982becec75 100644
--- a/src/uxbox/ui/users.cljs
+++ b/src/uxbox/ui/users.cljs
@@ -1,3 +1,9 @@
+;; 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) 2016 Andrey Antukh
+
(ns uxbox.ui.users
(:require [sablono.core :as html :refer-macros [html]]
[lentes.core :as l]
diff --git a/src/uxbox/ui/workspace/colorpicker.cljs b/src/uxbox/ui/workspace/colorpicker.cljs
new file mode 100644
index 0000000000..5afdfbd3e6
--- /dev/null
+++ b/src/uxbox/ui/workspace/colorpicker.cljs
@@ -0,0 +1,68 @@
+;; 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) 2016 Andrey Antukh
+;; Copyright (c) 2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.colorpicker
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.workspace.base :as wb]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.lightbox :as lbx]
+ [uxbox.ui.colorpicker :as cp]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.ui.workspace.base :as wb]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- focus-shape
+ [id]
+ (as-> (l/in [:shapes-by-id id]) $
+ (l/focus-atom $ st/state)))
+
+(defn- colorpicker-render
+ [own {:keys [x y shape attr] :as opts}]
+ (let [shape (rum/react (focus-shape shape))
+ left (- x 260)
+ top (- y 50)]
+ (letfn [(change-color [color]
+ (let [attrs {:color color}]
+ (rs/emit!
+ (case attr
+ :stroke (uds/update-stroke-attrs (:id shape) attrs)
+ :fill (uds/update-fill-attrs (:id shape) attrs)))))
+ (on-change-color [event]
+ (let [color (dom/event->value event)]
+ (change-color color)))]
+ (html
+ [:div.colorpicker-tooltip
+ {:style {:left (str left "px")
+ :top (str top "px")}}
+
+ (cp/colorpicker
+ :theme :small
+ :value (:stroke shape "#000000")
+ :on-change change-color)
+
+ (recent-colors shape change-color)]))))
+
+(def colorpicker
+ (mx/component
+ {:render colorpicker-render
+ :name "colorpicker"
+ :mixins [rum/reactive mx/static]}))
+
+(defmethod lbx/render-lightbox :workspace/colorpicker
+ [params]
+ (colorpicker params))
diff --git a/src/uxbox/ui/workspace/header.cljs b/src/uxbox/ui/workspace/header.cljs
index 1dad5d9961..4f33031291 100644
--- a/src/uxbox/ui/workspace/header.cljs
+++ b/src/uxbox/ui/workspace/header.cljs
@@ -94,6 +94,11 @@
:class (when (contains? flags :drawtools) "selected")
:on-click (partial toggle :drawtools)}
i/shapes]
+ [:li.tooltip.tooltip-bottom
+ {:alt "Color Palette (---)"
+ :class (when (contains? flags :colorpalette) "selected")
+ :on-click (partial toggle :colorpalette)}
+ i/palette]
[:li.tooltip.tooltip-bottom
{:alt "Icons (Ctrl + Shift + I)"
:class (when (contains? flags :icons) "selected")
diff --git a/src/uxbox/ui/workspace/recent_colors.cljs b/src/uxbox/ui/workspace/recent_colors.cljs
index 0fb4dac7ed..d14de70f81 100644
--- a/src/uxbox/ui/workspace/recent_colors.cljs
+++ b/src/uxbox/ui/workspace/recent_colors.cljs
@@ -18,12 +18,7 @@
[uxbox.util.dom :as dom]
[uxbox.ui.workspace.base :as wb]))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Helpers
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(def ^:private ^:static toggle-colorpalette
- #(rs/emit! (dw/toggle-flag :colorpalette)))
+;; --- Helpers
(defn- count-color
[state shape prop]
@@ -41,9 +36,7 @@
(sort-by second (into [] $))
(take 5 (map first $))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Component
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; --- Component
(defn- recent-colors-render
[own {:keys [page id] :as shape} callback]
@@ -56,16 +49,14 @@
[:span (tr "ds.recent-colors")]
[:div.row-flex
(for [color colors]
- [:span.color-th {:style {:background color}
+ [:span.color-th {:style {:background-color color}
:key color
:on-click (partial callback color)}])
(for [i (range (- 5 (count colors)))]
[:span.color-th {:key (str "empty" i)}])
+ [:span.color-th.palette-th i/picker]]])))
- [:span.color-th.palette-th {:on-click toggle-colorpalette}
- i/palette]]])))
-
-(def ^:static recent-colors
+(def recent-colors
(mx/component
{:render recent-colors-render
:name "recent-colors"
diff --git a/src/uxbox/ui/workspace/settings.cljs b/src/uxbox/ui/workspace/settings.cljs
index 1f9947425b..7e91becc93 100644
--- a/src/uxbox/ui/workspace/settings.cljs
+++ b/src/uxbox/ui/workspace/settings.cljs
@@ -80,10 +80,9 @@
:min 1
:max 100}]]
[:span.lightbox-label "Grid color"]
- [:div.color-picker-default
- (uucp/colorpicker
- :value (:grid/color form)
- :on-change on-color-change)]
+ (uucp/colorpicker
+ :value (:grid/color form)
+ :on-change on-color-change)
[:span.lightbox-label "Grid magnet option"]
[:div.input-checkbox.check-primary
[:input
diff --git a/src/uxbox/ui/workspace/sidebar/options.cljs b/src/uxbox/ui/workspace/sidebar/options.cljs
index c884864689..26744e19cf 100644
--- a/src/uxbox/ui/workspace/sidebar/options.cljs
+++ b/src/uxbox/ui/workspace/sidebar/options.cljs
@@ -19,19 +19,22 @@
[uxbox.ui.workspace.base :as wb]
[uxbox.ui.icons :as i]
[uxbox.ui.mixins :as mx]
- [uxbox.ui.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
[uxbox.ui.workspace.recent-colors :refer (recent-colors)]
- [uxbox.ui.workspace.base :as wb]
+ [uxbox.ui.workspace.sidebar.options.icon-measures :as options-iconm]
+ [uxbox.ui.workspace.sidebar.options.circle-measures :as options-circlem]
+ [uxbox.ui.workspace.sidebar.options.rect-measures :as options-rectm]
+ [uxbox.ui.workspace.sidebar.options.line-measures :as options-linem]
+ [uxbox.ui.workspace.sidebar.options.fill :as options-fill]
+ [uxbox.ui.workspace.sidebar.options.text :as options-text]
+ [uxbox.ui.workspace.sidebar.options.stroke :as options-stroke]
[uxbox.util.geom :as geom]
- [uxbox.util.lens :as ul]
[uxbox.util.dom :as dom]
[uxbox.util.data :refer (parse-int parse-float read-string)]))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Constants
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; --- Constants
-(def ^:const ^:private +menus-map+
+(def ^:private +menus-map+
{:icon [:menu/icon-measures :menu/fill :menu/stroke]
:rect [:menu/rect-measures :menu/fill :menu/stroke]
:line [:menu/line-measures :menu/stroke]
@@ -39,590 +42,42 @@
:text [:menu/fill :menu/text]
:group []})
-(def ^:const ^:private +menus-by-id+
- {:menu/icon-measures
+(def ^:private +menus+
+ [{:name "Size, position & rotation"
+ :id :menu/icon-measures
+ :icon i/infocard
+ :comp options-iconm/icon-measures-menu}
{:name "Size, position & rotation"
- :icon i/infocard}
-
- :menu/rect-measures
+ :id :menu/rect-measures
+ :icon i/infocard
+ :comp options-rectm/rect-measures-menu}
{:name "Size, position & rotation"
- :icon i/infocard}
-
- :menu/line-measures
+ :id :menu/line-measures
+ :icon i/infocard
+ :comp options-linem/line-measures-menu}
{:name "Size, position & rotation"
- :icon i/infocard}
-
- :menu/circle-measures
- {:name "Size, position & rotation"
- :icon i/infocard}
-
- :menu/fill
+ :id :menu/circle-measures
+ :icon i/infocard
+ :comp options-circlem/circle-measures-menu}
{:name "Fill"
- :icon i/fill}
-
- :menu/stroke
+ :id :menu/fill
+ :icon i/fill
+ :comp options-fill/fill-menu}
{:name "Stroke"
- :icon i/stroke}
-
- :menu/text
+ :id :menu/stroke
+ :icon i/stroke
+ :comp options-stroke/stroke-menu}
{:name "Text"
- :icon i/text}})
+ :id :menu/text
+ :icon i/text
+ :comp options-text/text-menu}])
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Implementation
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(def ^:private +menus-by-id+
+ (into {} (map #(vector (:id %) %)) +menus+))
-(defmulti -render-menu
- (fn [menu own shape] (:id menu)))
+;; --- Options
-(defmethod -render-menu :menu/stroke
- [menu own shape]
- (letfn [(change-stroke [value]
- (let [sid (:id shape)]
- (rs/emit! (uds/update-stroke-attrs sid value))))
- (on-width-change [event]
- (let [value (dom/event->value event)
- value (parse-float value 1)]
- (change-stroke {:width value})))
- (on-opacity-change [event]
- (let [value (dom/event->value event)
- value (parse-float value 1)
- value (/ value 10000)]
- (change-stroke {:opacity value})))
- (on-color-change [event]
- (let [value (dom/event->value event)]
- (change-stroke {:color value})))
- (on-stroke-style-change [event]
- (let [value (dom/event->value event)
- value (read-string value)]
- (change-stroke {:type value})))]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- [:span "Style"]
- [:div.row-flex
- [:select#style.input-select {:placeholder "Style"
- :value (:stroke-type shape)
- :on-change on-stroke-style-change}
- [:option {:value ":none"} "None"]
- [:option {:value ":solid"} "Solid"]
- [:option {:value ":dotted"} "Dotted"]
- [:option {:value ":dashed"} "Dashed"]
- [:option {:value ":mixed"} "Mixed"]]
- [:input.input-text
- {:placeholder "Width"
- :type "number"
- :min "0"
- :value (:stroke-width shape "1")
- :on-change on-width-change}]]
-
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Color"]
- [:div.color-picker-small
- (colorpicker
- :theme :small
- :value (:stroke shape "#000000")
- :on-change #(change-stroke {:color %}))]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder "#"
- :type "text"
- :value (:stroke shape "")
- :on-change on-color-change}]]
-
- (recent-colors shape #(change-stroke {:color %}))
-
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Opacity"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min "0"
- :max "10000"
- :value (* 10000 (:stroke-opacity shape 1))
- :step "1"
- :on-change on-opacity-change}]]]])))
-
-(defmethod -render-menu :menu/fill
- [menu own shape]
- (letfn [(change-fill [value]
- (let [sid (:id shape)]
- (rs/emit! (uds/update-fill-attrs sid value))))
- (on-color-change [event]
- (let [value (dom/event->value event)]
- (change-fill {:color value})))
- (on-opacity-change [event]
- (let [value (dom/event->value event)
- value (parse-float value 1)
- value (/ value 10000)]
- (change-fill {:opacity value})))
- (on-color-picker-event [color]
- (change-fill {:color color}))]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Color"]
-
- [:div.color-picker-small
- (colorpicker
- :theme :small
- :value (:fill shape "#000000")
- :on-change #(on-color-picker-event %))]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder "#"
- :type "text"
- :value (:fill shape "")
- :on-change on-color-change}]]
-
- (recent-colors shape #(change-fill {:color %}))
-
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Opacity"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min "0"
- :max "10000"
- :value (* 10000 (:fill-opacity shape 1))
- :step "1"
- :on-change on-opacity-change}]]]])))
-
-(defmethod -render-menu :menu/rect-measures
- [menu own shape local]
- (letfn [(on-size-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-size sid props))))
- (on-rotation-change [event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)]
- (rs/emit! (uds/update-rotation sid value))))
- (on-pos-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value nil)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-position sid props))))
- (on-border-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value nil)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-radius-attrs sid props))))]
- (let [size (geom/size shape)]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Size"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "Width"
- :type "number"
- :min "0"
- :value (:width size)
- :on-change (partial on-size-change :width)}]
- [:div.lock-size i/lock]
- [:input.input-text
- {:placeholder "Height"
- :type "number"
- :min "0"
- :value (:height size)
- :on-change (partial on-size-change :height)}]]
-
- [:span "Position"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "x"
- :type "number"
- :value (:x1 shape "")
- :on-change (partial on-pos-change :x)}]
- [:input.input-text
- {:placeholder "y"
- :type "number"
- :value (:y1 shape "")
- :on-change (partial on-pos-change :y)}]]
-
- [:span "Border radius"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "rx"
- :type "number"
- :value (:rx shape "")
- :on-change (partial on-border-change :rx)}]
- [:div.lock-size i/lock]
- [:input.input-text
- {:placeholder "ry"
- :type "number"
- :value (:ry shape "")
- :on-change (partial on-border-change :ry)}]]
-
- [:span "Rotation"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min 0
- :max 360
- :value (:rotation shape 0)
- :on-change on-rotation-change}]]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder ""
- :type "number"
- :min 0
- :max 360
- :value (:rotation shape "0")
- :on-change on-rotation-change
- }]
- [:input.input-text
- {:style {:visibility "hidden"}}]
- ]]]
- ))))
-
-
-(defmethod -render-menu :menu/icon-measures
- [menu own shape]
- (letfn [(on-size-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-size sid props))))
- (on-rotation-change [event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)]
- (rs/emit! (uds/update-rotation sid value))))
- (on-pos-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value nil)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-position sid props))))]
- (let [size (geom/size shape)]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Size"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "Width"
- :type "number"
- :min "0"
- :value (:width size)
- :on-change (partial on-size-change :width)}]
- [:div.lock-size i/lock]
- [:input.input-text
- {:placeholder "Height"
- :type "number"
- :min "0"
- :value (:height size)
- :on-change (partial on-size-change :height)}]]
-
- [:span "Position"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "x"
- :type "number"
- :value (:x1 shape "")
- :on-change (partial on-pos-change :x)}]
- [:input.input-text
- {:placeholder "y"
- :type "number"
- :value (:y1 shape "")
- :on-change (partial on-pos-change :y)}]]
-
- [:span "Rotation"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min 0
- :max 360
- :value (:rotation shape 0)
- :on-change on-rotation-change}]]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder ""
- :type "number"
- :min 0
- :max 360
- :value (:rotation shape "0")
- :on-change on-rotation-change
- }]
- [:input.input-text
- {:style {:visibility "hidden"}}]
- ]]]
- ))))
-
-(defmethod -render-menu :menu/circle-measures
- [menu own shape]
- (letfn [(on-size-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-radius-attrs sid props))))
- (on-rotation-change [event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)]
- (rs/emit! (uds/update-rotation sid value))))
- (on-pos-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value nil)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-position sid props))))]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- ;; SLIDEBAR FOR ROTATION AND OPACITY
- [:span "Size"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "Width"
- :type "number"
- :min "0"
- :value (:rx shape)
- :on-change (partial on-size-change :rx)}]
- [:div.lock-size i/lock]
- [:input.input-text
- {:placeholder "Height"
- :type "number"
- :min "0"
- :value (:ry shape)
- :on-change (partial on-size-change :ry)}]]
-
- [:span "Position"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "cx"
- :type "number"
- :value (:cx shape "")
- :on-change (partial on-pos-change :x)}]
- [:input.input-text
- {:placeholder "cy"
- :type "number"
- :value (:cy shape "")
- :on-change (partial on-pos-change :y)}]]
-
- [:span "Rotation"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min 0
- :max 360
- :value (:rotation shape 0)
- :on-change on-rotation-change}]]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder ""
- :type "number"
- :min 0
- :max 360
- :value (:rotation shape "0")
- :on-change on-rotation-change
- }]
- [:input.input-text
- {:style {:visibility "hidden"}}]
- ]]]
- )))
-
-(defmethod -render-menu :menu/line-measures
- [menu own shape]
- (letfn [(on-rotation-change [event]
- (let [value (dom/event->value event)
- value (parse-int value 0)
- sid (:id shape)]
- (rs/emit! (uds/update-rotation sid value))))
- (on-pos-change [attr event]
- (let [value (dom/event->value event)
- value (parse-int value nil)
- sid (:id shape)
- props {attr value}]
- (rs/emit! (uds/update-line-attrs sid props))))]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
- [:span "Position"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "x1"
- :type "number"
- :value (:x1 shape "")
- :on-change (partial on-pos-change :x1)}]
- [:input.input-text
- {:placeholder "y1"
- :type "number"
- :value (:y1 shape "")
- :on-change (partial on-pos-change :y1)}]]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder "x2"
- :type "number"
- :value (:x2 shape "")
- :on-change (partial on-pos-change :x2)}]
- [:input.input-text
- {:placeholder "y2"
- :type "number"
- :value (:y2 shape "")
- :on-change (partial on-pos-change :y2)}]]
-
- [:span "Rotation"]
- [:div.row-flex
- [:input.slidebar
- {:type "range"
- :min 0
- :max 360
- :value (:rotation shape 0)
- :on-change on-rotation-change}]]
-
- [:div.row-flex
- [:input.input-text
- {:placeholder ""
- :type "number"
- :min 0
- :max 360
- :value (:rotation shape "0")
- :on-change on-rotation-change
- }]
- [:input.input-text
- {:style {:visibility "hidden"}}]
- ]]]
- )))
-
-(defmethod -render-menu :menu/text
- [menu own {:keys [font] :as shape}]
- (letfn [(on-font-family-change [event]
- (let [value (dom/event->value event)
- sid (:id shape)
- params {:family (read-string value)
- :weight "normal"
- :style "normal"}]
- (rs/emit! (uds/update-font-attrs sid params))))
- (on-font-size-change [event]
- (let [value (dom/event->value event)
- params {:size (parse-int value)}
- sid (:id shape)]
- (rs/emit! (uds/update-font-attrs sid params))))
- (on-font-letter-spacing-change [event]
- (let [value (dom/event->value event)
- params {:letter-spacing (parse-float value)}
- sid (:id shape)]
- (rs/emit! (uds/update-font-attrs sid params))))
- (on-font-line-height-change [event]
- (let [value (dom/event->value event)
- params {:line-height (parse-float value)}
- sid (:id shape)]
- (rs/emit! (uds/update-font-attrs sid params))))
- (on-font-align-change [event value]
- (let [params {:align value}
- sid (:id shape)]
- (rs/emit! (uds/update-font-attrs sid params))))
-
- (on-font-style-change [event]
- (let [value (dom/event->value event)
- [weight style] (read-string value)
- sid (:id shape)
- params {:style style
- :weight weight}]
- (rs/emit! (uds/update-font-attrs sid params))))]
- (let [{:keys [family style weight size align line-height letter-spacing]
- :or {family "sourcesanspro"
- align "left"
- style "normal"
- weight "normal"
- letter-spacing 1
- line-height 1.4
- size 16}} font
- styles (:styles (first (filter #(= (:id %) family) library/+fonts+)))]
- (html
- [:div.element-set {:key (str (:id menu))}
- [:div.element-set-title (:name menu)]
- [:div.element-set-content
-
- [:span "Font family"]
- [:div.row-flex
- [:select.input-select {:value (pr-str family)
- :on-change on-font-family-change}
- (for [font library/+fonts+]
- [:option {:value (pr-str (:id font))
- :key (:id font)} (:name font)])]]
-
- [:span "Size and Weight"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "Font Size"
- :type "number"
- :min "0"
- :max "200"
- :value size
- :on-change on-font-size-change}]
- [:select.input-select {:value (pr-str [weight style])
- :on-change on-font-style-change}
- (for [style styles
- :let [data (mapv #(get style %) [:weight :style])]]
- [:option {:value (pr-str data)
- :key (:name style)} (:name style)])]]
-
- [:span "Line height and Letter spacing"]
- [:div.row-flex
- [:input.input-text
- {:placeholder "Line height"
- :type "number"
- :step "0.1"
- :min "0"
- :max "200"
- :value line-height
- :on-change on-font-line-height-change}]
- [:input.input-text
- {:placeholder "Letter spacing"
- :type "number"
- :step "0.1"
- :min "0"
- :max "200"
- :value letter-spacing
- :on-change on-font-letter-spacing-change}]]
-
-
- [:span "Text align"]
- [:div.row-flex.align-icons
- [:span {:class (when (= align "left") "current")
- :on-click #(on-font-align-change % "left")}
- i/align-left]
- [:span {:class (when (= align "right") "current")
- :on-click #(on-font-align-change % "right")}
- i/align-right]
- [:span {:class (when (= align "center") "current")
- :on-click #(on-font-align-change % "center")}
- i/align-center]
- [:span {:class (when (= align "justify") "current")
- :on-click #(on-font-align-change % "justify")}
- i/align-justify]]]]))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Components
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn options-menus-render
+(defn- options-render
[own shape]
(let [local (:rum/local own)
menus (get +menus-map+ (:type shape))
@@ -632,20 +87,18 @@
[:ul.element-icons
(for [menu-id (get +menus-map+ (:type shape))
:let [menu (get +menus-by-id+ menu-id)
- menu (assoc menu :id menu-id)
selected? (= active-menu menu-id)]]
[:li#e-info {:on-click #(swap! local assoc :menu menu-id)
:key (str "menu-" (:id menu))
:class (when selected? "selected")}
(:icon menu)])]
(when-let [menu (get +menus-by-id+ active-menu)]
- (let [menu (assoc menu :id active-menu)]
- (-render-menu menu own shape local)))])))
+ ((:comp menu) menu shape))])))
-(def ^:static ^:private options-menus
+(def ^:private options
(mx/component
- {:render options-menus-render
- :name "options-menus"
+ {:render options-render
+ :name "options"
:mixins [mx/static (mx/local)]}))
(def ^:const selected-shape-l
@@ -653,7 +106,7 @@
(let [selected (get-in state [:workspace :selected])]
(when (= 1 (count selected))
(get-in state [:shapes-by-id (first selected)]))))]
- (as-> (ul/getter getter) $
+ (as-> (l/getter getter) $
(l/focus-atom $ st/state))))
(defn options-toolbox-render
@@ -669,7 +122,7 @@
[:div.tool-window-content
[:div.element-options
(if shape
- (options-menus shape))]]])))
+ (options shape))]]])))
(def ^:static options-toolbox
(mx/component
diff --git a/src/uxbox/ui/workspace/sidebar/options/circle_measures.cljs b/src/uxbox/ui/workspace/sidebar/options/circle_measures.cljs
new file mode 100644
index 0000000000..1901bb651c
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/circle_measures.cljs
@@ -0,0 +1,107 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.circle-measures
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- circle-measures-menu-render
+ [own menu shape]
+ (letfn [(on-size-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-radius-attrs sid props))))
+ (on-rotation-change [event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)]
+ (rs/emit! (uds/update-rotation sid value))))
+ (on-pos-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value nil)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-position sid props))))]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+ ;; SLIDEBAR FOR ROTATION AND OPACITY
+ [:span "Size"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "Width"
+ :type "number"
+ :min "0"
+ :value (:rx shape)
+ :on-change (partial on-size-change :rx)}]
+ [:div.lock-size i/lock]
+ [:input.input-text
+ {:placeholder "Height"
+ :type "number"
+ :min "0"
+ :value (:ry shape)
+ :on-change (partial on-size-change :ry)}]]
+
+ [:span "Position"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "cx"
+ :type "number"
+ :value (:cx shape "")
+ :on-change (partial on-pos-change :x)}]
+ [:input.input-text
+ {:placeholder "cy"
+ :type "number"
+ :value (:cy shape "")
+ :on-change (partial on-pos-change :y)}]]
+
+ [:span "Rotation"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min 0
+ :max 360
+ :value (:rotation shape 0)
+ :on-change on-rotation-change}]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder ""
+ :type "number"
+ :min 0
+ :max 360
+ :value (:rotation shape "0")
+ :on-change on-rotation-change
+ }]
+ [:input.input-text
+ {:style {:visibility "hidden"}}]
+ ]]]
+ )))
+
+(def circle-measures-menu
+ (mx/component
+ {:render circle-measures-menu-render
+ :name "circle-measures-menu"
+ :mixins [mx/static]}))
diff --git a/src/uxbox/ui/workspace/sidebar/options/fill.cljs b/src/uxbox/ui/workspace/sidebar/options/fill.cljs
new file mode 100644
index 0000000000..9dcfa67010
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/fill.cljs
@@ -0,0 +1,83 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.fill
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.shapes :as uds]
+ [uxbox.data.lightbox :as udl]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn fill-menu-render
+ [own menu shape]
+ (letfn [(change-fill [value]
+ (let [sid (:id shape)]
+ (rs/emit! (uds/update-fill-attrs sid value))))
+ (on-color-change [event]
+ (let [value (dom/event->value event)]
+ (change-fill {:color value})))
+ (on-opacity-change [event]
+ (let [value (dom/event->value event)
+ value (parse-float value 1)
+ value (/ value 10000)]
+ (change-fill {:opacity value})))
+ (on-color-picker-event [color]
+ (change-fill {:color color}))
+ (show-color-picker [event]
+ (let [x (.-clientX event)
+ y (.-clientY event)
+ opts {:x x :y y
+ :shape (:id shape)
+ :attr :fill
+ :transparent? true}]
+ (udl/open! :workspace/colorpicker opts)))]
+
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+
+ [:span "Color"]
+ [:div.row-flex.color-data
+ [:span.color-th
+ {:style {:background-color (:fill shape)}
+ :on-click show-color-picker}]
+ [:div.color-info
+ [:span (:fill shape)]]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "#"
+ :type "text"
+ :value (:fill shape "")
+ :on-change on-color-change}]]
+
+ ;; SLIDEBAR FOR ROTATION AND OPACITY
+ [:span "Opacity"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min "0"
+ :max "10000"
+ :value (* 10000 (:fill-opacity shape 1))
+ :step "1"
+ :on-change on-opacity-change}]]]])))
+
+(def fill-menu
+ (mx/component
+ {:render fill-menu-render
+ :name "fill-menu"
+ :mixins [mx/static]}))
diff --git a/src/uxbox/ui/workspace/sidebar/options/icon_measures.cljs b/src/uxbox/ui/workspace/sidebar/options/icon_measures.cljs
new file mode 100644
index 0000000000..d9ce24eeb2
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/icon_measures.cljs
@@ -0,0 +1,107 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.icon-measures
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- icon-measures-menu-render
+ [own menu shape]
+ (letfn [(on-size-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-size sid props))))
+ (on-rotation-change [event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)]
+ (rs/emit! (uds/update-rotation sid value))))
+ (on-pos-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value nil)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-position sid props))))]
+ (let [size (geom/size shape)]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+ ;; SLIDEBAR FOR ROTATION AND OPACITY
+ [:span "Size"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "Width"
+ :type "number"
+ :min "0"
+ :value (:width size)
+ :on-change (partial on-size-change :width)}]
+ [:div.lock-size i/lock]
+ [:input.input-text
+ {:placeholder "Height"
+ :type "number"
+ :min "0"
+ :value (:height size)
+ :on-change (partial on-size-change :height)}]]
+
+ [:span "Position"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "x"
+ :type "number"
+ :value (:x1 shape "")
+ :on-change (partial on-pos-change :x)}]
+ [:input.input-text
+ {:placeholder "y"
+ :type "number"
+ :value (:y1 shape "")
+ :on-change (partial on-pos-change :y)}]]
+
+ [:span "Rotation"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min 0
+ :max 360
+ :value (:rotation shape 0)
+ :on-change on-rotation-change}]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder ""
+ :type "number"
+ :min 0
+ :max 360
+ :value (:rotation shape "0")
+ :on-change on-rotation-change
+ }]
+ [:input.input-text
+ {:style {:visibility "hidden"}}]
+ ]]]))))
+
+(def icon-measures-menu
+ (mx/component
+ {:render icon-measures-menu-render
+ :name "icon-measures-menu"
+ :mixins [mx/static]}))
diff --git a/src/uxbox/ui/workspace/sidebar/options/line_measures.cljs b/src/uxbox/ui/workspace/sidebar/options/line_measures.cljs
new file mode 100644
index 0000000000..fce0e075c9
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/line_measures.cljs
@@ -0,0 +1,96 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.line-measures
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- line-measures-menu-render
+ [own menu shape]
+ (letfn [(on-rotation-change [event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)]
+ (rs/emit! (uds/update-rotation sid value))))
+ (on-pos-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value nil)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-line-attrs sid props))))]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+ [:span "Position"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "x1"
+ :type "number"
+ :value (:x1 shape "")
+ :on-change (partial on-pos-change :x1)}]
+ [:input.input-text
+ {:placeholder "y1"
+ :type "number"
+ :value (:y1 shape "")
+ :on-change (partial on-pos-change :y1)}]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "x2"
+ :type "number"
+ :value (:x2 shape "")
+ :on-change (partial on-pos-change :x2)}]
+ [:input.input-text
+ {:placeholder "y2"
+ :type "number"
+ :value (:y2 shape "")
+ :on-change (partial on-pos-change :y2)}]]
+
+ [:span "Rotation"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min 0
+ :max 360
+ :value (:rotation shape 0)
+ :on-change on-rotation-change}]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder ""
+ :type "number"
+ :min 0
+ :max 360
+ :value (:rotation shape "0")
+ :on-change on-rotation-change
+ }]
+ [:input.input-text
+ {:style {:visibility "hidden"}}]
+ ]]]
+ )))
+
+(def line-measures-menu
+ (mx/component
+ {:render line-measures-menu-render
+ :name "line-measures-menu"
+ :mixins [mx/static]}))
diff --git a/src/uxbox/ui/workspace/sidebar/options/rect_measures.cljs b/src/uxbox/ui/workspace/sidebar/options/rect_measures.cljs
new file mode 100644
index 0000000000..963bf2aac8
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/rect_measures.cljs
@@ -0,0 +1,128 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.rect-measures
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn rect-measures-menu-render
+ [own menu shape]
+ (letfn [(on-size-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-size sid props))))
+ (on-rotation-change [event]
+ (let [value (dom/event->value event)
+ value (parse-int value 0)
+ sid (:id shape)]
+ (rs/emit! (uds/update-rotation sid value))))
+ (on-pos-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value nil)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-position sid props))))
+ (on-border-change [attr event]
+ (let [value (dom/event->value event)
+ value (parse-int value nil)
+ sid (:id shape)
+ props {attr value}]
+ (rs/emit! (uds/update-radius-attrs sid props))))]
+ (let [size (geom/size shape)]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+ ;; SLIDEBAR FOR ROTATION AND OPACITY
+ [:span "Size"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "Width"
+ :type "number"
+ :min "0"
+ :value (:width size)
+ :on-change (partial on-size-change :width)}]
+ [:div.lock-size i/lock]
+ [:input.input-text
+ {:placeholder "Height"
+ :type "number"
+ :min "0"
+ :value (:height size)
+ :on-change (partial on-size-change :height)}]]
+
+ [:span "Position"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "x"
+ :type "number"
+ :value (:x1 shape "")
+ :on-change (partial on-pos-change :x)}]
+ [:input.input-text
+ {:placeholder "y"
+ :type "number"
+ :value (:y1 shape "")
+ :on-change (partial on-pos-change :y)}]]
+
+ [:span "Border radius"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "rx"
+ :type "number"
+ :value (:rx shape "")
+ :on-change (partial on-border-change :rx)}]
+ [:div.lock-size i/lock]
+ [:input.input-text
+ {:placeholder "ry"
+ :type "number"
+ :value (:ry shape "")
+ :on-change (partial on-border-change :ry)}]]
+
+ [:span "Rotation"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min 0
+ :max 360
+ :value (:rotation shape 0)
+ :on-change on-rotation-change}]]
+
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder ""
+ :type "number"
+ :min 0
+ :max 360
+ :value (:rotation shape "0")
+ :on-change on-rotation-change
+ }]
+ [:input.input-text
+ {:style {:visibility "hidden"}}]
+ ]]]))))
+
+(def rect-measures-menu
+ (mx/component
+ {:render rect-measures-menu-render
+ :name "rect-measures"
+ :mixins [mx/static]}))
+
diff --git a/src/uxbox/ui/workspace/sidebar/options/stroke.cljs b/src/uxbox/ui/workspace/sidebar/options/stroke.cljs
new file mode 100644
index 0000000000..a7fc4a36ca
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/stroke.cljs
@@ -0,0 +1,97 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.stroke
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.shapes :as uds]
+ [uxbox.data.lightbox :as udl]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- stroke-menu-render
+ [own menu shape]
+ (letfn [(change-stroke [value]
+ (let [sid (:id shape)]
+ (rs/emit! (uds/update-stroke-attrs sid value))))
+ (on-width-change [event]
+ (let [value (dom/event->value event)
+ value (parse-float value 1)]
+ (change-stroke {:width value})))
+ (on-opacity-change [event]
+ (let [value (dom/event->value event)
+ value (parse-float value 1)
+ value (/ value 10000)]
+ (change-stroke {:opacity value})))
+ (on-color-change [event]
+ (let [value (dom/event->value event)]
+ (change-stroke {:color value})))
+ (on-stroke-style-change [event]
+ (let [value (dom/event->value event)
+ value (read-string value)]
+ (change-stroke {:type value})))
+ (show-color-picker [event]
+ (let [x (.-clientX event)
+ y (.-clientY event)
+ opts {:x x :y y
+ :shape (:id shape)
+ :attr :stroke
+ :transparent? true}]
+ (udl/open! :workspace/colorpicker opts)))]
+ (let [local (:rum/local own)]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+ [:span "Style"]
+ [:div.row-flex
+ [:select#style.input-select {:placeholder "Style"
+ :value (:stroke-type shape)
+ :on-change on-stroke-style-change}
+ [:option {:value ":none"} "None"]
+ [:option {:value ":solid"} "Solid"]
+ [:option {:value ":dotted"} "Dotted"]
+ [:option {:value ":dashed"} "Dashed"]
+ [:option {:value ":mixed"} "Mixed"]]
+ [:input.input-text
+ {:placeholder "Width"
+ :type "number"
+ :min "0"
+ :value (:stroke-width shape "1")
+ :on-change on-width-change}]]
+
+ [:span "Color"]
+ [:div.row-flex.color-data
+ [:span.color-th
+ {:style {:background-color (:stroke shape)}
+ :on-click show-color-picker}]
+ [:div.color-info
+ [:span (:stroke shape)]]]
+
+ [:span "Opacity"]
+ [:div.row-flex
+ [:input.slidebar
+ {:type "range"
+ :min "0"
+ :max "10000"
+ :value (* 10000 (:stroke-opacity shape 1))
+ :step "1"
+ :on-change on-opacity-change}]]]]))))
+
+(def stroke-menu
+ (mx/component
+ {:render stroke-menu-render
+ :name "stroke-menu"
+ :mixed [mx/static]}))
diff --git a/src/uxbox/ui/workspace/sidebar/options/text.cljs b/src/uxbox/ui/workspace/sidebar/options/text.cljs
new file mode 100644
index 0000000000..9a330c7442
--- /dev/null
+++ b/src/uxbox/ui/workspace/sidebar/options/text.cljs
@@ -0,0 +1,142 @@
+;; 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) 2015-2016 Andrey Antukh
+;; Copyright (c) 2015-2016 Juan de la Cruz
+
+(ns uxbox.ui.workspace.sidebar.options.text
+ (:require [sablono.core :as html :refer-macros [html]]
+ [rum.core :as rum]
+ [lentes.core :as l]
+ [uxbox.locales :refer (tr)]
+ [uxbox.router :as r]
+ [uxbox.rstore :as rs]
+ [uxbox.state :as st]
+ [uxbox.library :as library]
+ [uxbox.data.workspace :as udw]
+ [uxbox.data.shapes :as uds]
+ [uxbox.ui.workspace.base :as wb]
+ [uxbox.ui.icons :as i]
+ [uxbox.ui.mixins :as mx]
+ [uxbox.ui.workspace.colorpicker :refer (colorpicker)]
+ [uxbox.ui.workspace.recent-colors :refer (recent-colors)]
+ [uxbox.ui.workspace.base :as wb]
+ [uxbox.util.geom :as geom]
+ [uxbox.util.dom :as dom]
+ [uxbox.util.data :refer (parse-int parse-float read-string)]))
+
+(defn- text-menu-render
+ [own menu {:keys [font] :as shape}]
+ (letfn [(on-font-family-change [event]
+ (let [value (dom/event->value event)
+ sid (:id shape)
+ params {:family (read-string value)
+ :weight "normal"
+ :style "normal"}]
+ (rs/emit! (uds/update-font-attrs sid params))))
+ (on-font-size-change [event]
+ (let [value (dom/event->value event)
+ params {:size (parse-int value)}
+ sid (:id shape)]
+ (rs/emit! (uds/update-font-attrs sid params))))
+ (on-font-letter-spacing-change [event]
+ (let [value (dom/event->value event)
+ params {:letter-spacing (parse-float value)}
+ sid (:id shape)]
+ (rs/emit! (uds/update-font-attrs sid params))))
+ (on-font-line-height-change [event]
+ (let [value (dom/event->value event)
+ params {:line-height (parse-float value)}
+ sid (:id shape)]
+ (rs/emit! (uds/update-font-attrs sid params))))
+ (on-font-align-change [event value]
+ (let [params {:align value}
+ sid (:id shape)]
+ (rs/emit! (uds/update-font-attrs sid params))))
+
+ (on-font-style-change [event]
+ (let [value (dom/event->value event)
+ [weight style] (read-string value)
+ sid (:id shape)
+ params {:style style
+ :weight weight}]
+ (rs/emit! (uds/update-font-attrs sid params))))]
+ (let [{:keys [family style weight size align line-height letter-spacing]
+ :or {family "sourcesanspro"
+ align "left"
+ style "normal"
+ weight "normal"
+ letter-spacing 1
+ line-height 1.4
+ size 16}} font
+ styles (:styles (first (filter #(= (:id %) family) library/+fonts+)))]
+ (html
+ [:div.element-set {:key (str (:id menu))}
+ [:div.element-set-title (:name menu)]
+ [:div.element-set-content
+
+ [:span "Font family"]
+ [:div.row-flex
+ [:select.input-select {:value (pr-str family)
+ :on-change on-font-family-change}
+ (for [font library/+fonts+]
+ [:option {:value (pr-str (:id font))
+ :key (:id font)} (:name font)])]]
+
+ [:span "Size and Weight"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "Font Size"
+ :type "number"
+ :min "0"
+ :max "200"
+ :value size
+ :on-change on-font-size-change}]
+ [:select.input-select {:value (pr-str [weight style])
+ :on-change on-font-style-change}
+ (for [style styles
+ :let [data (mapv #(get style %) [:weight :style])]]
+ [:option {:value (pr-str data)
+ :key (:name style)} (:name style)])]]
+
+ [:span "Line height and Letter spacing"]
+ [:div.row-flex
+ [:input.input-text
+ {:placeholder "Line height"
+ :type "number"
+ :step "0.1"
+ :min "0"
+ :max "200"
+ :value line-height
+ :on-change on-font-line-height-change}]
+ [:input.input-text
+ {:placeholder "Letter spacing"
+ :type "number"
+ :step "0.1"
+ :min "0"
+ :max "200"
+ :value letter-spacing
+ :on-change on-font-letter-spacing-change}]]
+
+
+ [:span "Text align"]
+ [:div.row-flex.align-icons
+ [:span {:class (when (= align "left") "current")
+ :on-click #(on-font-align-change % "left")}
+ i/align-left]
+ [:span {:class (when (= align "right") "current")
+ :on-click #(on-font-align-change % "right")}
+ i/align-right]
+ [:span {:class (when (= align "center") "current")
+ :on-click #(on-font-align-change % "center")}
+ i/align-center]
+ [:span {:class (when (= align "justify") "current")
+ :on-click #(on-font-align-change % "justify")}
+ i/align-justify]]]]))))
+
+(def text-menu
+ (mx/component
+ {:render text-menu-render
+ :name "text-menu"
+ :mixins [mx/static]}))
diff --git a/src/uxbox/util/color.cljs b/src/uxbox/util/color.cljs
index f228fd5bb4..2805ebc8e9 100644
--- a/src/uxbox/util/color.cljs
+++ b/src/uxbox/util/color.cljs
@@ -47,3 +47,6 @@
(-> (hex->rgb data)
(conj opacity)))
+(defn hex?
+ [v]
+ (not (nil? (re-find #"^#[0-9A-Fa-f]{6}$" v))))
diff --git a/src/uxbox/util/dom.cljs b/src/uxbox/util/dom.cljs
index 572058ddd1..a6de948247 100644
--- a/src/uxbox/util/dom.cljs
+++ b/src/uxbox/util/dom.cljs
@@ -55,3 +55,7 @@
or checkbox is checked or not."
[node]
(.-checked node))
+
+(defn ^boolean equals?
+ [node-a node-b]
+ (.isEqualNode node-a node-b))